Skip to content

Commit

Permalink
resolves pagination issue
Browse files Browse the repository at this point in the history
  • Loading branch information
KelvinTegelaar committed Jan 23, 2025
1 parent e6596a7 commit 4176e9e
Showing 1 changed file with 78 additions and 29 deletions.
107 changes: 78 additions & 29 deletions src/components/CippComponents/CippAutocomplete.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ArrowDropDown } from "@mui/icons-material";
import { Autocomplete, CircularProgress, createFilterOptions, TextField } from "@mui/material";
import { ApiGetCall } from "../../api/ApiCall";
import { useEffect, useState } from "react";
import { useSettings } from "../../hooks/use-settings";
import { getCippError } from "../../utils/get-cipp-error";
import { ApiGetCallWithPagination } from "../../api/ApiCall";

export const CippAutoComplete = (props) => {
const {
Expand All @@ -25,15 +25,29 @@ export const CippAutoComplete = (props) => {
sx,
...other
} = props;
const filter = createFilterOptions({ stringify: (option) => JSON.stringify(option) });

const [usedOptions, setUsedOptions] = useState(options);
const [getRequestInfo, setGetRequestInfo] = useState({ url: "", waiting: false, queryKey: "" });
const filter = createFilterOptions({
stringify: (option) => JSON.stringify(option),
});

const actionGetRequest = ApiGetCall({
// This is our paginated call
const actionGetRequest = ApiGetCallWithPagination({
...getRequestInfo,
});

const currentTenant = api?.tenantFilter ? api.tenantFilter : useSettings().currentTenant;
useEffect(() => {
if (actionGetRequest.isSuccess && !actionGetRequest.isFetching) {
const lastPage = actionGetRequest.data?.pages[actionGetRequest.data.pages.length - 1];
const nextLinkExists = lastPage?.Metadata?.nextLink;
if (nextLinkExists) {
actionGetRequest.fetchNextPage();
}
}
}, [actionGetRequest.data?.pages?.length, actionGetRequest.isFetching, api?.queryKey]);

useEffect(() => {
if (api) {
setGetRequestInfo({
Expand All @@ -46,52 +60,87 @@ export const CippAutoComplete = (props) => {
queryKey: api.queryKey,
});
}
}, [api, currentTenant]);

// After the data is fetched, combine and map it
useEffect(() => {
if (actionGetRequest.isSuccess) {
const dataToMap = api.dataKey ? actionGetRequest.data?.[api.dataKey] : actionGetRequest.data;
if (!Array.isArray(dataToMap)) {
// E.g., allPages is an array of pages returned by the pagination
const allPages = actionGetRequest.data?.pages || [];

// Helper to get nested data if you have something like "response.data.items"
const getNestedValue = (obj, path) => {
if (!path) return obj;
const keys = path.split(".");
let result = obj;
for (const key of keys) {
if (result && typeof result === "object" && key in result) {
result = result[key];
} else {
return undefined;
}
}
return result;
};

// Flatten the results from all pages
const combinedResults = allPages.flatMap((page) => {
const nestedData = getNestedValue(page, api?.dataKey);
return nestedData !== undefined ? nestedData : [];
});

if (!Array.isArray(combinedResults)) {
setUsedOptions([
{
label: "Error: The API returned data we cannot map to this field",
value: "Error: The API returned data we cannot map to this field",
value: "Error",
},
]);
return;
} else {
// Convert each item into your { label, value, addedFields } shape
const convertedOptions = combinedResults.map((option) => {
const addedFields = {};
if (api?.addedField) {
Object.keys(api.addedField).forEach((key) => {
addedFields[key] = option[api.addedField[key]];
});
}

return {
label:
typeof api?.labelField === "function"
? api.labelField(option)
: option[api?.labelField],
value:
typeof api?.valueField === "function"
? api.valueField(option)
: option[api?.valueField],
addedFields,
};
});
setUsedOptions(convertedOptions);
}
const convertedOptions = dataToMap.map((option) => {
const addedFields = {};
if (api.addedField) {
Object.keys(api.addedField).forEach((key) => {
addedFields[key] = option[api.addedField[key]];
});
}
return {
label:
typeof api.labelField === "function" ? api.labelField(option) : option[api.labelField],
value:
typeof api.valueField === "function" ? api.valueField(option) : option[api.valueField],
addedFields: addedFields,
};
});
setUsedOptions(convertedOptions);
}

if (actionGetRequest.isError) {
setUsedOptions([{ label: getCippError(actionGetRequest.error), value: "error" }]);
}
}, [api, actionGetRequest.data]);
}, [api, actionGetRequest.data, actionGetRequest.isSuccess, actionGetRequest.isError]);

const rand = Math.random().toString(36).substring(5);

return (
<Autocomplete
key={`${defaultValue}-${rand}`}
disabled={disabled || actionGetRequest.isFetching}
popupIcon={
props.isFetching || actionGetRequest.isFetching ? (
actionGetRequest.isFetching ? (
<CircularProgress color="inherit" size={20} />
) : (
<ArrowDropDown />
)
}
isOptionEqualToValue={(option, value) => option.value === value.value}
isOptionEqualToValue={(option, val) => option.value === val.value}
value={typeof value === "string" ? { label: value, value: value } : value}
filterSelectedOptions
disableClearable={disableClearable}
Expand All @@ -100,12 +149,11 @@ export const CippAutoComplete = (props) => {
filterOptions={(options, params) => {
const filtered = filter(options, params);
const isExisting =
options !== undefined &&
options !== null &&
options?.length > 0 &&
options?.some(
options.some(
(option) => params.inputValue === option.value || params.inputValue === option.label
);

if (params.inputValue !== "" && creatable && !isExisting) {
filtered.push({
label: `Add option: "${params.inputValue}"`,
Expand All @@ -126,6 +174,7 @@ export const CippAutoComplete = (props) => {
onChange={(event, newValue) => {
if (Array.isArray(newValue)) {
newValue = newValue.map((item) => {
// If user typed a new item or missing label
if (item?.manual || !item?.label) {
item = {
label: item?.label ? item.value : item,
Expand Down

0 comments on commit 4176e9e

Please sign in to comment.