Files
lotteryAdmin/src/modules/settings/hooks/use-settings-section.ts
kang b15e377187 feat(api, i18n): add agent_node_id to various admin queries and enhance multi-language support
Introduced the agent_node_id field in AdminDrawListQuery, AdminPlayerListQuery, AdminSettlementBatchListQuery, TicketItemsListQuery, and TransferOrderListQuery to improve filtering capabilities. Updated the admin-breadcrumb and admin-sidebar components to include new translations for agent-related terms in English, Nepali, and Chinese, enhancing the overall user experience and multi-language support across the admin interface.
2026-06-02 14:37:08 +08:00

100 lines
2.8 KiB
TypeScript

"use client";
import { useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { updateAdminSettingsBatch, type AdminSettingBatchItem } from "@/api/admin-settings";
import { setCachedApplyRebateToPayoutSetting } from "@/lib/admin-settlement-settings-cache";
import { useAdminSettingsData } from "@/modules/settings/admin-settings-data-context";
import { SETTLEMENT_KEYS } from "@/modules/settings/settings-keys";
import { LotteryApiBizError } from "@/types/api/errors";
export function useSettingsSection<TDraft>(options: {
initialDraft: TDraft;
fromKv: (kv: Record<string, unknown>) => TDraft;
buildDirtyItems: (draft: TDraft, saved: TDraft) => AdminSettingBatchItem[];
saveSuccessKey: string;
saveFailedKey: string;
}) {
const { t } = useTranslation(["config"]);
const tRef = useRef(t);
tRef.current = t;
const { kv, loading, patchKv } = useAdminSettingsData();
const [draft, setDraft] = useState(options.initialDraft);
const [saved, setSaved] = useState(options.initialDraft);
const [saving, setSaving] = useState(false);
const hydratedRef = useRef(false);
const { fromKv, buildDirtyItems, saveSuccessKey, saveFailedKey } = options;
const dirty = useMemo(
() => buildDirtyItems(draft, saved).length > 0,
[draft, saved, buildDirtyItems],
);
useEffect(() => {
if (kv === null) {
return;
}
const next = fromKv(kv);
setDraft(next);
setSaved(next);
hydratedRef.current = true;
}, [kv, fromKv]);
const updateField = <K extends keyof TDraft>(field: K, value: TDraft[K]) => {
setDraft((prev) => ({ ...prev, [field]: value }));
};
const discard = () => {
setDraft(saved);
};
const save = async (): Promise<boolean> => {
const items = buildDirtyItems(draft, saved);
if (items.length === 0) {
return true;
}
setSaving(true);
try {
await updateAdminSettingsBatch(items);
const updates: Record<string, unknown> = {};
for (const item of items) {
updates[item.key] = item.value;
if (item.key === SETTLEMENT_KEYS.APPLY_REBATE_TO_PAYOUT) {
setCachedApplyRebateToPayoutSetting(Boolean(item.value));
}
}
patchKv(updates);
setSaved(draft);
toast.success(tRef.current(saveSuccessKey, { ns: "config" }));
return true;
} catch (error) {
toast.error(
error instanceof LotteryApiBizError
? error.message
: tRef.current(saveFailedKey, { ns: "config" }),
);
return false;
} finally {
setSaving(false);
}
};
const sectionLoading = loading || (kv !== null && !hydratedRef.current);
return {
draft,
saved,
loading: sectionLoading,
saving,
dirty,
updateField,
discard,
save,
};
}