1- import React , { useCallback , useMemo , useEffect , useState } from "react" ;
1+ import * as React from "react" ;
2+ import { useCallback , useMemo , useEffect , useState } from "react" ;
23import { useDispatch , useSelector , batch } from "react-redux" ;
3- import { useQuery } from "@tanstack/react-query" ;
44import { useTranslation } from "react-i18next" ;
55import { push } from "connected-react-router" ;
66
@@ -91,10 +91,10 @@ const AnalyzeSubmissionList: React.FC = () => {
9191 const columnWidths = useSelector ( ( state : any ) => state ?. analyzeSubmission ?. columnWidths ?? { } ) ;
9292 //local state
9393 const [ isManageFieldsModalOpen , setIsManageFieldsModalOpen ] = useState ( false ) ;
94- const handleManageFieldsOpen = ( ) => setIsManageFieldsModalOpen ( true ) ;
95- const handleManageFieldsClose = ( ) => setIsManageFieldsModalOpen ( false ) ;
94+ const handleManageFieldsOpen = useCallback ( ( ) => setIsManageFieldsModalOpen ( true ) , [ ] ) ;
95+ const handleManageFieldsClose = useCallback ( ( ) => setIsManageFieldsModalOpen ( false ) , [ ] ) ;
9696 const [ dropdownSelection , setDropdownSelection ] = useState < string | null > ( null ) ;
97- const [ form , setForm ] = React . useState ( [ ] ) ;
97+ const [ form , setForm ] = useState ( [ ] ) ;
9898 const [ savedFormVariables , setSavedFormVariables ] = useState ( { } ) ;
9999 const [ filtersApplied , setFiltersApplied ] = useState ( false ) ;
100100 const [ lastFetchedFormId , setLastFetchedFormId ] = useState < string | null > ( null ) ;
@@ -104,6 +104,11 @@ const AnalyzeSubmissionList: React.FC = () => {
104104 const [ selectedSearchFieldKey , setSelectedSearchFieldKey ] = useState < string > ( "id" ) ;
105105 const [ searchFieldFilterTerm , setSearchFieldFilterTerm ] = useState < string > ( "" ) ;
106106 const [ searchText , setSearchText ] = useState < string > ( "" ) ;
107+ const [ submissionsData , setSubmissionsData ] = useState < { submissions : Submission [ ] ; totalCount : number } > ( {
108+ submissions : [ ] ,
109+ totalCount : 0 ,
110+ } ) ;
111+ const [ isSubmissionsLoading , setIsSubmissionsLoading ] = useState ( false ) ;
107112
108113 // Default submission fields constant
109114 const DEFAULT_SUBMISSION_FIELDS = [
@@ -134,11 +139,11 @@ const AnalyzeSubmissionList: React.FC = () => {
134139 } , [ dropdownSelection ] ) ;
135140
136141
137- const handleClearSearch = ( ) => {
142+ const handleClearSearch = useCallback ( ( ) => {
138143 setFieldFilters ( { } ) ;
139144 // Clear the search field values globally
140145 dispatch ( clearSearchFieldValues ( ) ) ;
141- } ;
146+ } , [ dispatch ] ) ;
142147
143148
144149
@@ -188,14 +193,17 @@ useEffect (() => {
188193
189194
190195
191- const handleFieldSearch = ( filters : Record < string , string > ) => {
196+ const handleFieldSearch = useCallback ( ( filters : Record < string , string > ) => {
192197 setFieldFilters ( filters ) ;
193198 dispatch ( setAnalyzeSubmissionPage ( 1 ) ) ;
194199 setFiltersApplied ( true ) ;
195200 dispatch ( setSearchFieldValues ( filters ) ) ;
196- } ;
201+ } , [ dispatch ] ) ;
197202// Use the current submissionFields state for calculation
198- const currentFields = selectedSubmissionFilter ?. variables ?? submissionFields ;
203+ const currentFields = useMemo ( ( ) =>
204+ selectedSubmissionFilter ?. variables ?? submissionFields ,
205+ [ selectedSubmissionFilter ?. variables , submissionFields ]
206+ ) ;
199207
200208const initialInputFields = useMemo ( ( ) => {
201209 //these pinned fileds should always come first in sidebar
@@ -274,6 +282,7 @@ useEffect(() => {
274282 . catch ( ( error ) => {
275283 console . error ( "Error fetching submission list:" , error ) ;
276284 } ) ;
285+ // eslint-disable-next-line react-hooks/exhaustive-deps
277286} , [ ] ) ;
278287
279288 // Column width helper function
@@ -341,61 +350,64 @@ const columnVisibilityModel = useMemo(() => {
341350
342351 // Memoize sortModel to prevent unnecessary re-renders and ensure it updates correctly
343352 const sortModel = useMemo ( ( ) => {
344- if ( activeSortKey ) {
345- return [
346- {
347- field : activeSortKey ,
348- sort : activeSortOrder ,
349- } ,
350- ] ;
351- }
352- return [ ] ;
353+ return activeSortKey
354+ ? [ { field : activeSortKey , sort : activeSortOrder } ]
355+ : [ ] ;
353356 } , [ activeSortKey , activeSortOrder ] ) ;
354357
355358 // Fetch Submissions
356- const systemFields = [ "id" , "form_name" , "created_by" , "created" , "application_status" ] ;
359+ const systemFields = useMemo ( ( ) => [ "id" , "form_name" , "created_by" , "created" , "application_status" ] , [ ] ) ;
357360
358361
359362const selectedFormFields = useMemo ( ( ) => {
360363 return ( selectedSubmissionFilter ?. variables ?? [ ] )
361364 . map ( ( v ) => v . key )
362365 . filter ( ( key ) => ! systemFields . includes ( key ) ) ;
363- } , [ selectedSubmissionFilter ] ) ;
364-
365-
366-
367- //data for searching data in filter table
368- const {
369- data,
370- isLoading : isSubmissionsLoading ,
371- isFetching,
372- refetch,
373- } = useQuery ( {
374- queryKey : [
375- "submissions" ,
376- page ,
377- limit ,
378- activeSortKey ,
379- activeSortOrder ,
380- dateRange ,
381- dropdownSelection ,
382- filtersApplied ? fieldFilters : { } ,
383- selectedFormFields
384- ] ,
385- queryFn : ( ) =>
386- getSubmissionList (
366+ } , [ selectedSubmissionFilter , systemFields ] ) ;
367+
368+ const appliedFieldFilters = useMemo (
369+ ( ) => ( filtersApplied ? fieldFilters : { } ) ,
370+ [ filtersApplied , fieldFilters ]
371+ ) ;
372+
373+
374+ const fetchSubmissions = useCallback ( async ( ) => {
375+ setIsSubmissionsLoading ( true ) ;
376+ try {
377+ const response = await getSubmissionList (
387378 limit ,
388379 page ,
389380 activeSortOrder ,
390381 activeSortKey ,
391382 dateRange ,
392383 dropdownSelection ,
393- filtersApplied ? fieldFilters : { } ,
384+ appliedFieldFilters ,
394385 selectedFormFields
395- ) ,
396- staleTime : 0 ,
397- cacheTime :0
398- } ) ;
386+ ) ;
387+ setSubmissionsData ( {
388+ submissions : response ?. submissions ?? [ ] ,
389+ totalCount : response ?. totalCount ?? 0 ,
390+ } ) ;
391+ } catch ( error ) {
392+ console . error ( "Error fetching submissions:" , error ) ;
393+ setSubmissionsData ( {
394+ submissions : [ ] ,
395+ totalCount : 0 ,
396+ } ) ;
397+ } finally {
398+ setIsSubmissionsLoading ( false ) ;
399+ }
400+ } , [
401+ limit ,
402+ page ,
403+ activeSortOrder ,
404+ activeSortKey ,
405+ dateRange ?. startDate ,
406+ dateRange ?. endDate ,
407+ dropdownSelection ,
408+ appliedFieldFilters ,
409+ selectedFormFields ,
410+ ] ) ;
399411
400412
401413 useEffect ( ( ) => {
@@ -431,29 +443,43 @@ const {
431443 setIsFormFetched ( false ) ;
432444 } ) ;
433445 } , [ dropdownSelection , lastFetchedFormId , formData ] ) ;
446+ useEffect ( ( ) => {
447+ fetchSubmissions ( ) ;
448+ } , [ fetchSubmissions ] ) ;
449+
434450 // taking data from submission response for mapping to the table
435- const submissions : Submission [ ] = data ? .submissions ?? [ ] ;
436- const totalCount : number = data ? .totalCount ?? 0 ;
451+ const submissions : Submission [ ] = submissionsData . submissions ;
452+ const totalCount : number = submissionsData . totalCount ;
437453
438454 // Pagination Model for ReusableTable
439- const paginationModel = useMemo (
440- ( ) => ( { page : page - 1 , pageSize : limit } ) ,
441- [ page , limit ]
442- ) ;
455+ const paginationModel = useMemo ( ( ) => {
456+ return { page : page - 1 , pageSize : limit } ;
457+ } , [ page , limit ] ) ;
443458
444- // Handle Pagination Model Change for ReusableTable
445- const handlePaginationModelChange = useCallback ( ( { page, pageSize } : any ) => {
446- batch ( ( ) => {
447- dispatch ( setAnalyzeSubmissionPage ( page + 1 ) ) ;
448- dispatch ( setAnalyzeSubmissionLimit ( pageSize ) ) ;
449- } ) ;
450- } , [ dispatch ] ) ;
459+ // Handle Pagination Model Change for ReusableTable
460+ const handlePaginationModelChange = useCallback ( ( { page : dataGridPage , pageSize } : any ) => {
461+ const requestedPage = ( dataGridPage ?? 0 ) + 1 ;
462+ const expectedDataGridPage = page - 1 ;
451463
452- const handlerefresh = ( ) => {
453- refetch ( ) ;
454- } ;
464+ if ( dataGridPage === expectedDataGridPage && pageSize === limit ) {
465+ return ;
466+ }
455467
456- const handleDateRangeChange = ( newDateRange ) => {
468+ if ( limit !== pageSize ) {
469+ batch ( ( ) => {
470+ dispatch ( setAnalyzeSubmissionLimit ( pageSize ) ) ;
471+ dispatch ( setAnalyzeSubmissionPage ( 1 ) ) ;
472+ } ) ;
473+ } else if ( page !== requestedPage ) {
474+ dispatch ( setAnalyzeSubmissionPage ( requestedPage ) ) ;
475+ }
476+ } , [ dispatch , limit , page ] ) ;
477+
478+ const handlerefresh = useCallback ( ( ) => {
479+ fetchSubmissions ( ) ;
480+ } , [ fetchSubmissions ] ) ;
481+
482+ const handleDateRangeChange = useCallback ( ( newDateRange ) => {
457483 const { startDate, endDate } = newDateRange ;
458484
459485 // Update state if:
@@ -464,9 +490,11 @@ const {
464490
465491 if ( ! ( bothSelected || bothCleared ) ) return ;
466492
467- dispatch ( setAnalyzeSubmissionDateRange ( newDateRange ) ) ;
468- dispatch ( setAnalyzeSubmissionPage ( 1 ) ) ;
469- } ;
493+ batch ( ( ) => {
494+ dispatch ( setAnalyzeSubmissionDateRange ( newDateRange ) ) ;
495+ dispatch ( setAnalyzeSubmissionPage ( 1 ) ) ;
496+ } ) ;
497+ } , [ dispatch ] ) ;
470498
471499 // Reset to default: set form to "All Forms" and clear date range
472500 const handleResetToDefault = useCallback ( ( ) => {
@@ -587,27 +615,24 @@ const {
587615 form_name : { sortOrder : "asc" } ,
588616 activeKey : "form_name" ,
589617 } ;
590- dispatch ( setAnalyzeSubmissionSort ( updatedSort ) ) ;
618+ // Reset page to 1 when sort is reset
619+ batch ( ( ) => {
620+ dispatch ( setAnalyzeSubmissionSort ( updatedSort ) ) ;
621+ dispatch ( setAnalyzeSubmissionPage ( 1 ) ) ;
622+ } ) ;
591623 return ;
592624 }
593625
594626 const field = model [ 0 ] . field ;
595- // Always use DataGrid's sort order directly - DataGrid handles toggling automatically
596- // DataGrid sends "asc" for first click, "desc" for second click on the same column
597627 const dataGridSort = model [ 0 ] ?. sort || "asc" ;
598-
599- // Reset all sort keys to "asc" and set only the active field to DataGrid's sort order
600- // This ensures only one sort is active at a time, and all others are reset to "asc"
601628 const resetSortOrders = HelperServices . getResetSortOrders ( optionSortBy . options ) ;
602629
603630 const updatedSort = {
604- ...resetSortOrders , // All keys reset to {sortOrder: "asc"}
605- [ field ] : { sortOrder : dataGridSort } , // Active field uses DataGrid's sort order
631+ ...resetSortOrders ,
632+ [ field ] : { sortOrder : dataGridSort } ,
606633 activeKey : field ,
607634 } ;
608635
609- // Dispatch the update - this will trigger a re-render and the sortModel will update
610- // Since sortModel is memoized based on activeSortKey and activeSortOrder, it will update immediately
611636 dispatch ( setAnalyzeSubmissionSort ( updatedSort ) ) ;
612637 } , [ dispatch , optionSortBy ] ) ;
613638
@@ -825,7 +850,6 @@ const {
825850 ] ) ;
826851 return (
827852 < >
828- < div className = "analyze-submissions-page" >
829853 < div className = "Toastify" > </ div >
830854 < div className = "toast-section" > { } </ div >
831855 < div className = "header-section-1" >
@@ -932,7 +956,7 @@ const {
932956 columns = { muiColumns }
933957 rows = { memoizedRows }
934958 rowCount = { totalCount }
935- loading = { isSubmissionsLoading || isFetching }
959+ loading = { isSubmissionsLoading }
936960 disableColumnResize = { false }
937961 paginationMode = "server"
938962 sortingMode = "server"
@@ -957,7 +981,6 @@ const {
957981 />
958982 </ div >
959983 </ div >
960- </ div >
961984 { isManageFieldsModalOpen && < ManageFieldsSortModal
962985 show = { isManageFieldsModalOpen }
963986 onClose = { handleManageFieldsClose }
0 commit comments