Files
EMS-ESP32/interface/src/utils/useRest.ts
2026-04-28 17:31:50 +02:00

98 lines
2.4 KiB
TypeScript

import { useCallback, useState } from 'react';
import { useBlocker } from 'react-router';
import { toast } from 'react-toastify';
import type { AlovaGenerics, Method } from 'alova';
import { useRequest } from 'alova/client';
import { useI18nContext } from 'i18n/i18n-react';
export interface RestRequestOptions<D> {
read: () => Method<AlovaGenerics>;
update: (value: D) => Method<AlovaGenerics>;
}
const REBOOT_ERROR_MESSAGE = 'Reboot required';
export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
const { LL } = useI18nContext();
const [errorMessage, setErrorMessage] = useState<string>();
const [restartNeeded, setRestartNeeded] = useState(false);
const [origData, setOrigData] = useState<D>();
const [dirtyFlags, setDirtyFlags] = useState<string[]>([]);
const blocker = useBlocker(dirtyFlags.length !== 0);
const {
data,
send: readData,
update: updateData
} = useRequest(read()).onComplete((event) => {
setOrigData(event.data as D);
});
const { loading: saving, send: writeData } = useRequest(
(newData: D) => update(newData),
{ immediate: false }
).onSuccess(() => {
toast.success(LL.UPDATED_OF(LL.SETTINGS(1)));
setDirtyFlags([]);
});
const updateDataValue = useCallback(
(new_data: D) => updateData({ data: new_data }),
[updateData]
);
const loadData = useCallback(async () => {
setDirtyFlags([]);
setErrorMessage(undefined);
try {
await readData();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
toast.error(message);
setErrorMessage(message);
}
}, [readData]);
const saveData = async () => {
if (!data) return;
setRestartNeeded(false);
setErrorMessage(undefined);
try {
await writeData(data as D);
setOrigData(data as D);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (message === REBOOT_ERROR_MESSAGE) {
setRestartNeeded(true);
return;
}
if (origData) {
updateData({ data: origData });
}
toast.error(message);
setErrorMessage(message);
setDirtyFlags([]);
}
};
return {
loadData,
saveData,
saving: !!saving,
updateDataValue,
data: data as D,
origData: origData as D,
dirtyFlags,
setDirtyFlags,
setOrigData,
blocker,
errorMessage,
restartNeeded
};
};