useAllSettings.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { useCallback, useEffect, useMemo, useState } from 'react';
  2. import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
  3. import { HttpUtil, Msg } from '@/utils';
  4. import { parseMsg } from '@/utils/zodValidate';
  5. import { AllSetting } from '@/models/setting';
  6. import { AllSettingSchema, type AllSettingInput } from '@/schemas/setting';
  7. import { keys } from '@/api/queryKeys';
  8. async function fetchAllSetting(): Promise<AllSettingInput | null> {
  9. const msg = await HttpUtil.post('/panel/setting/all', undefined, { silent: true });
  10. if (!msg?.success) throw new Error(msg?.msg || 'Failed to fetch settings');
  11. const validated = parseMsg(msg, AllSettingSchema, 'setting/all');
  12. return validated.obj;
  13. }
  14. export function useAllSettings() {
  15. const queryClient = useQueryClient();
  16. const [draft, setDraft] = useState<AllSetting>(() => new AllSetting());
  17. const [extraSpinning, setExtraSpinning] = useState(false);
  18. const query = useQuery({
  19. queryKey: keys.settings.all(),
  20. queryFn: fetchAllSetting,
  21. staleTime: Infinity,
  22. });
  23. const server = useMemo(() => new AllSetting(query.data), [query.data]);
  24. useEffect(() => {
  25. if (query.data !== undefined) {
  26. setDraft(new AllSetting(query.data));
  27. }
  28. }, [query.data]);
  29. const updateSetting = useCallback((patch: Partial<AllSetting>) => {
  30. setDraft((prev) => {
  31. const next = new AllSetting(prev);
  32. Object.assign(next, patch);
  33. return next;
  34. });
  35. }, []);
  36. const saveMut = useMutation({
  37. mutationFn: async (next: AllSetting): Promise<Msg<unknown>> => {
  38. const body = AllSettingSchema.partial().safeParse(next);
  39. if (!body.success) {
  40. console.warn('[zod] setting/update body failed validation', body.error.issues);
  41. }
  42. return HttpUtil.post('/panel/setting/update', body.success ? body.data : next);
  43. },
  44. onSuccess: (msg) => {
  45. if (msg?.success) queryClient.invalidateQueries({ queryKey: keys.settings.all() });
  46. },
  47. });
  48. const saveAll = useCallback(() => saveMut.mutateAsync(draft), [saveMut, draft]);
  49. const saveDisabled = useMemo(() => server.equals(draft), [server, draft]);
  50. return {
  51. allSetting: draft,
  52. updateSetting,
  53. fetched: query.data !== undefined,
  54. spinning: extraSpinning || saveMut.isPending,
  55. setSpinning: setExtraSpinning,
  56. saveDisabled,
  57. saveAll,
  58. };
  59. }