Skip to content

Commit 86ffd64

Browse files
authored
Merge pull request #991 from vinaayakh-aot/feature/mui-pagination-fix
Feature/mui pagination fix
2 parents d8d9af6 + 0b64a38 commit 86ffd64

File tree

1 file changed

+105
-82
lines changed

1 file changed

+105
-82
lines changed

forms-flow-submissions/src/Routes/SubmissionListing.tsx

Lines changed: 105 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import React, { useCallback, useMemo, useEffect, useState } from "react";
1+
import * as React from "react";
2+
import { useCallback, useMemo, useEffect, useState } from "react";
23
import { useDispatch, useSelector, batch } from "react-redux";
3-
import { useQuery } from "@tanstack/react-query";
44
import { useTranslation } from "react-i18next";
55
import { 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

200208
const 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

359362
const 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

Comments
 (0)