@@ -2,7 +2,7 @@ import { useTranslation } from "@i18n/client";
22import { getDaysPassed } from "@lib/client/clientHelpers" ;
33import { VaultSubmissionOverview } from "@lib/types" ;
44import { ExclamationIcon } from "@serverComponents/icons" ;
5- import React , { useEffect , useState } from "react" ;
5+ import React , { useEffect , useState , useRef , useCallback } from "react" ;
66import { StatusFilter } from "../types" ;
77import Skeleton from "react-loading-skeleton" ;
88import { getSubmissionRemovalDate } from "../actions" ;
@@ -27,31 +27,54 @@ const ExclamationText = ({
2727const RemovalDateLabel = ( { submission } : { submission : VaultSubmissionOverview } ) => {
2828 const { t } = useTranslation ( "form-builder-responses" ) ;
2929 const [ label , setLabel ] = useState < string | null > ( null ) ;
30+ const elementRef = useRef < HTMLParagraphElement > ( null ) ;
31+ const hasLoadedRef = useRef ( false ) ;
3032
31- const getRemovalByMessage = ( removalAt ?: Date | number ) => {
32- const daysLeft = removalAt && getDaysPassed ( removalAt ) ;
33- if ( daysLeft && daysLeft > 0 ) {
34- return t ( "downloadResponsesTable.status.removeWithinXDays" , { daysLeft } ) ;
35- }
36- return "" ;
37- } ;
33+ const getRemovalByMessage = useCallback (
34+ ( removalAt ?: Date | number ) => {
35+ const daysLeft = removalAt && getDaysPassed ( removalAt ) ;
36+ if ( daysLeft && daysLeft > 0 ) {
37+ return t ( "downloadResponsesTable.status.removeWithinXDays" , { daysLeft } ) ;
38+ }
39+ return "" ;
40+ } ,
41+ [ t ]
42+ ) ;
3843
3944 useEffect ( ( ) => {
40- getSubmissionRemovalDate ( submission . formID , submission . name ) . then ( ( value ) => {
41- if ( typeof value === "number" ) {
42- setLabel ( getRemovalByMessage ( value ) ) ;
43- } else {
44- setLabel ( "-" ) ;
45+ const element = elementRef . current ;
46+ const observer = new IntersectionObserver (
47+ ( [ entry ] ) => {
48+ if ( entry . isIntersecting && ! hasLoadedRef . current ) {
49+ hasLoadedRef . current = true ;
50+ getSubmissionRemovalDate ( submission . formID , submission . name ) . then ( ( value ) => {
51+ if ( typeof value === "number" ) {
52+ setLabel ( getRemovalByMessage ( value ) ) ;
53+ } else {
54+ setLabel ( "-" ) ;
55+ }
56+ } ) ;
57+ }
58+ } ,
59+ {
60+ rootMargin : "50px" , // Start loading slightly before the element is visible
4561 }
46- } ) ;
47- // eslint-disable-next-line react-hooks/exhaustive-deps
48- } , [ ] ) ;
62+ ) ;
4963
50- if ( label === null ) {
51- return < Skeleton count = { 1 } className = "my-4 ml-4 w-[300px]" /> ;
52- }
64+ if ( element ) {
65+ observer . observe ( element ) ;
66+ }
5367
54- return < p > { label } </ p > ;
68+ return ( ) => {
69+ if ( element ) {
70+ observer . unobserve ( element ) ;
71+ }
72+ } ;
73+ } , [ submission . formID , submission . name , getRemovalByMessage ] ) ;
74+
75+ return (
76+ < p ref = { elementRef } > { label === null ? < Skeleton count = { 1 } className = "w-[300px]" /> : label } </ p >
77+ ) ;
5578} ;
5679
5780export const NextStep = ( {
0 commit comments