import { useMemo, useState } from "react"; import { parseForm } from "@/shared/forms/validation"; import { useRegionOptions } from "@/shared/hooks/useRegionOptions.js"; import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js"; import { useConfirm } from "@/shared/ui/ConfirmProvider.jsx"; import { useToast } from "@/shared/ui/ToastProvider.jsx"; import { deleteRoom, listRooms, updateRoom } from "@/features/rooms/api"; import { useRoomAbilities } from "@/features/rooms/permissions.js"; import { roomStatusSchema, roomUpdateSchema } from "@/features/rooms/schema"; const pageSize = 10; const emptyData = { items: [], page: 1, pageSize, total: 0 }; const emptyForm = () => ({ coverUrl: "", description: "", title: "", visibleRegionId: 0, }); const emptyStatusForm = () => ({ status: "active" }); export function useRoomsPage() { const abilities = useRoomAbilities(); const confirm = useConfirm(); const { showToast } = useToast(); const { loadingRegions, regionOptions } = useRegionOptions(); const [query, setQuery] = useState(""); const [status, setStatus] = useState(""); const [regionId, setRegionId] = useState(""); const [page, setPage] = useState(1); const [activeAction, setActiveAction] = useState(""); const [activeRoom, setActiveRoom] = useState(null); const [form, setForm] = useState(emptyForm); const [statusForm, setStatusForm] = useState(emptyStatusForm); const [loadingAction, setLoadingAction] = useState(""); const filters = useMemo( () => ({ keyword: query, region_id: regionId, status, }), [query, regionId, status], ); const { data = emptyData, error, loading, reload, } = usePaginatedQuery({ errorMessage: "加载房间列表失败", fetcher: listRooms, filters, page, pageSize, queryKey: ["rooms", filters, page], }); const changeQuery = (value) => { setQuery(value); setPage(1); }; const changeStatus = (value) => { setStatus(value); setPage(1); }; const changeRegionId = (value) => { setRegionId(value); setPage(1); }; const resetFilters = () => { setQuery(""); setStatus(""); setRegionId(""); setPage(1); }; const openEdit = (room) => { setActiveRoom(room); setForm({ coverUrl: room.coverUrl || "", description: "", title: room.title || "", visibleRegionId: room.visibleRegionId || 0, }); setActiveAction("edit"); }; const openDetail = (room) => { setActiveRoom(room); setActiveAction("detail"); }; const openStatus = (room) => { setActiveRoom(room); setStatusForm({ status: room.status === "closed" ? "closed" : "active" }); setActiveAction("status"); }; const closeAction = () => { setActiveAction(""); setActiveRoom(null); }; const submitEdit = async (event) => { event.preventDefault(); if (!activeRoom) { return; } await runAction("edit", "房间已更新", async () => { const payload = parseForm(roomUpdateSchema, form); if (!String(form.description || "").trim()) { delete payload.description; } await updateRoom(activeRoom.roomId, payload); closeAction(); await reload(); }); }; const submitStatus = async (event) => { event.preventDefault(); if (!activeRoom) { return; } await runAction("status", "房间状态已更新", async () => { const payload = parseForm(roomStatusSchema, statusForm); await updateRoom(activeRoom.roomId, payload); closeAction(); await reload(); }); }; const removeRoom = async (room) => { const ok = await confirm({ confirmText: "删除", message: `${room.title || room.roomId} 会从房间列表和房间状态中删除。`, title: "删除房间", tone: "danger", }); if (!ok) { return; } await runAction(`delete-${room.roomId}`, "房间已删除", async () => { await deleteRoom(room.roomId); await reload(); }); }; const runAction = async (action, successMessage, submitter) => { setLoadingAction(action); try { await submitter(); showToast(successMessage, "success"); } catch (err) { showToast(err.message || "操作失败", "error"); } finally { setLoadingAction(""); } }; return { abilities, activeAction, activeRoom, changeQuery, changeRegionId, changeStatus, closeAction, data, error, form, loading, loadingAction, loadingRegions, openDetail, openEdit, openStatus, page, query, regionId, regionOptions, reload, removeRoom, resetFilters, setForm, setPage, setStatusForm, status, statusForm, submitStatus, submitEdit, }; }