/** @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 = { isLoading: boolean; error: RestErrorResponse | undefined; data: TYPE[]; get: (value: MODEL, key?: string) => TYPE | undefined; gets: (value: MODEL[] | undefined, key?: string) => TYPE[]; update: (request: Promise, key?: string) => void; remove: (id: number | string, request: Promise, key?: string) => void; }; export const useDataStore = ( { primaryKey = 'id', restApiName, available = true, getsCall, }: { restApiName?: string; primaryKey?: string; available?: boolean; getsCall: () => Promise; }, deps: DependencyList = [] ): DataStoreType => { const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(undefined); const [data, setData] = useState([]); 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( (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( (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, 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, 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 }; };