137 lines
3.9 KiB
TypeScript
137 lines
3.9 KiB
TypeScript
/** @file
|
|
* @author Edouard DUPIN
|
|
* @copyright 2024, Edouard DUPIN, all right reserved
|
|
* @license PROPRIETARY (see license file)
|
|
*/
|
|
import { DependencyList, useCallback, useEffect, useState } from 'react';
|
|
|
|
import { RestErrorResponse } from '@/back-api';
|
|
import { useToastAPIError } from '@/utils/toastHook';
|
|
import { isNullOrUndefined } from '@/utils/validator';
|
|
|
|
export type DataStoreType<TYPE> = {
|
|
isLoading: boolean;
|
|
error: RestErrorResponse | undefined;
|
|
data: TYPE[];
|
|
get: <MODEL>(value: MODEL, key?: string) => TYPE | undefined;
|
|
gets: <MODEL>(value: MODEL[] | undefined, key?: string) => TYPE[];
|
|
update: (request: Promise<TYPE>, key?: string) => void;
|
|
remove: (id: number | string, request: Promise<void>, key?: string) => void;
|
|
};
|
|
|
|
export const useDataStore = <TYPE>(
|
|
{
|
|
primaryKey = 'id',
|
|
restApiName,
|
|
available = true,
|
|
getsCall,
|
|
}: {
|
|
restApiName?: string;
|
|
primaryKey?: string;
|
|
available?: boolean;
|
|
getsCall: () => Promise<TYPE[]>;
|
|
},
|
|
deps: DependencyList = []
|
|
): DataStoreType<TYPE> => {
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [error, setError] = useState<RestErrorResponse | undefined>(undefined);
|
|
const [data, setData] = useState<TYPE[]>([]);
|
|
const toastAPIError = useToastAPIError();
|
|
|
|
// on instantiation ==> call the request of the data...
|
|
useEffect(() => {
|
|
setError(undefined);
|
|
setIsLoading(true);
|
|
if (!available) {
|
|
console.log(`[${restApiName}] NOT call data. service not available`);
|
|
return;
|
|
}
|
|
console.log(`[${restApiName}] call data ...`);
|
|
getsCall()
|
|
.then((response: TYPE[]) => {
|
|
/*console.log(
|
|
`[${restApiName}] getData Response: ${JSON.stringify(response, null, 2)}`
|
|
);*/
|
|
setData(response);
|
|
setError(undefined);
|
|
setIsLoading(false);
|
|
})
|
|
.catch((error: RestErrorResponse) => {
|
|
toastAPIError(error);
|
|
console.log(
|
|
`[${restApiName}] catch error: ${JSON.stringify(error, null, 2)}`
|
|
);
|
|
setError(error);
|
|
setIsLoading(false);
|
|
});
|
|
}, [setIsLoading, setData, ...deps]);
|
|
|
|
const get = useCallback(
|
|
<MODEL>(value: MODEL, key?: string): TYPE | undefined => {
|
|
const keyValue = key ?? primaryKey;
|
|
for (let iii = 0; iii < data.length; iii++) {
|
|
if (data[iii][keyValue] === value) {
|
|
return data[iii];
|
|
}
|
|
}
|
|
return undefined;
|
|
},
|
|
[data]
|
|
);
|
|
const gets = useCallback(
|
|
<MODEL>(value: MODEL[] | undefined, key?: string): TYPE[] => {
|
|
const keyValue = key ?? primaryKey;
|
|
const out: TYPE[] = [];
|
|
if (isNullOrUndefined(value)) {
|
|
return out;
|
|
}
|
|
for (let iii = 0; iii < data.length; iii++) {
|
|
if (value.includes(data[iii][keyValue])) {
|
|
out.push(data[iii]);
|
|
}
|
|
}
|
|
return out;
|
|
},
|
|
[data]
|
|
);
|
|
|
|
const update = useCallback(
|
|
(request: Promise<TYPE>, key?: string) => {
|
|
const keyValue = key ?? primaryKey;
|
|
request
|
|
.then((responseData: TYPE) => {
|
|
const filterData = data.filter(
|
|
(localData: TYPE) => localData[keyValue] !== responseData[keyValue]
|
|
);
|
|
filterData.push(responseData);
|
|
setData(filterData);
|
|
})
|
|
.catch((error: RestErrorResponse) => {
|
|
toastAPIError(error);
|
|
});
|
|
},
|
|
[data, setData]
|
|
);
|
|
const remove = useCallback(
|
|
(id: number | string, request: Promise<void>, key?: string) => {
|
|
const keyValue = key ?? primaryKey;
|
|
request
|
|
.then(() => {
|
|
const filterData = data.filter(
|
|
(localData: TYPE) => localData[keyValue] !== id
|
|
);
|
|
setData(filterData);
|
|
})
|
|
.catch((error) => {
|
|
toastAPIError(error);
|
|
console.log(
|
|
`catch an error on delete: ... ${JSON.stringify(error, null, 2)}`
|
|
);
|
|
});
|
|
},
|
|
[data, setData]
|
|
);
|
|
|
|
return { isLoading, error, data, get, gets, update, remove };
|
|
};
|