import { useCallback, useEffect, useMemo, useState } from "react"; import { parseForm } from "@/shared/forms/validation"; import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js"; import { useToast } from "@/shared/ui/ToastProvider.jsx"; import { listResourceGroups } from "@/features/resources/api"; import { getSevenDayCheckInConfig, listSevenDayCheckInClaims, updateSevenDayCheckInConfig, } from "@/features/seven-day-checkin/api"; import { useSevenDayCheckInAbilities } from "@/features/seven-day-checkin/permissions.js"; import { sevenDayCheckInConfigFormSchema } from "@/features/seven-day-checkin/schema"; const pageSize = 50; const emptyClaims = { items: [], page: 1, pageSize, total: 0 }; const emptyForm = { enabled: false, rewards: Array.from({ length: 7 }, (_, index) => ({ dayIndex: index + 1, resourceGroupId: "", })), }; export function useSevenDayCheckInPage() { const abilities = useSevenDayCheckInAbilities(); const { showToast } = useToast(); const [config, setConfig] = useState(null); const [configDrawerOpen, setConfigDrawerOpen] = useState(false); const [form, setForm] = useState(emptyForm); const [configLoading, setConfigLoading] = useState(false); const [configSaving, setConfigSaving] = useState(false); const [resourceGroups, setResourceGroups] = useState([]); const [query, setQuery] = useState(""); const [status, setStatus] = useState(""); const [checkinDay, setCheckinDay] = useState(""); const [dayIndex, setDayIndex] = useState(""); const [page, setPage] = useState(1); const filters = useMemo( () => ({ checkin_day: checkinDay, day_index: dayIndex, keyword: query, status }), [checkinDay, dayIndex, query, status], ); const { data: claims = emptyClaims, error: claimsError, loading: claimsLoading, reload: reloadClaims, } = usePaginatedQuery({ errorMessage: "加载签到记录失败", fetcher: listSevenDayCheckInClaims, filters, page, pageSize, queryKey: ["seven-day-checkin-claims", filters, page], }); const reloadConfig = useCallback(async () => { setConfigLoading(true); try { const [config, groups] = await Promise.all([ getSevenDayCheckInConfig(), listResourceGroups({ page: 1, page_size: 100, status: "active" }), ]); setConfig(config); setForm(formFromConfig(config)); setResourceGroups(groups.items || []); } catch (err) { showToast(err.message || "加载七日签到配置失败", "error"); } finally { setConfigLoading(false); } }, [showToast]); useEffect(() => { void reloadConfig(); }, [reloadConfig]); const openConfigDrawer = useCallback(() => { setForm(config ? formFromConfig(config) : emptyForm); setConfigDrawerOpen(true); }, [config]); const closeConfigDrawer = useCallback(() => { setConfigDrawerOpen(false); setForm(config ? formFromConfig(config) : emptyForm); }, [config]); const changeQuery = (value) => { setQuery(value); setPage(1); }; const changeStatus = (value) => { setStatus(value); setPage(1); }; const changeCheckinDay = (value) => { setCheckinDay(value); setPage(1); }; const changeDayIndex = (value) => { setDayIndex(value); setPage(1); }; const submitConfig = async (event) => { event.preventDefault(); if (!abilities.canUpdate) { return; } setConfigSaving(true); try { const parsed = parseForm(sevenDayCheckInConfigFormSchema, form); const saved = await updateSevenDayCheckInConfig(payloadFromForm(parsed)); setConfig(saved); setForm(formFromConfig(saved)); setConfigDrawerOpen(false); showToast("七日签到配置已保存", "success"); await reloadClaims(); } catch (err) { showToast(err.message || "保存七日签到配置失败", "error"); } finally { setConfigSaving(false); } }; return { abilities, changeCheckinDay, changeDayIndex, changeQuery, changeStatus, checkinDay, claims, claimsError, claimsLoading, closeConfigDrawer, config, configDrawerOpen, configLoading, configSaving, dayIndex, form, openConfigDrawer, page, query, reloadClaims, reloadConfig, resourceGroups, setForm, setPage, status, submitConfig, }; } function formFromConfig(config) { return { enabled: Boolean(config?.enabled), rewards: Array.from({ length: 7 }, (_, index) => { const dayIndex = index + 1; const reward = config?.rewards?.find((item) => Number(item.dayIndex) === dayIndex); return { dayIndex, resourceGroupId: reward?.resourceGroupId ? String(reward.resourceGroupId) : "", }; }), }; } function payloadFromForm(form) { return { enabled: Boolean(form.enabled), rewards: form.rewards .map((reward) => ({ day_index: Number(reward.dayIndex), resource_group_id: Number(reward.resourceGroupId || 0), })) .sort((left, right) => left.day_index - right.day_index), }; }