import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { cursorPage, PolicyPreviewSummary, PolicyRevision, type PolicyRevisionCreate, type PolicyRevisionUpdate, type PolicyStatus, } from "@umt/contracts"; import { api } from "~/lib/api.ts"; import { getParsed, parseOrThrow } from "./library.ts"; import { fetchAllCursorPages } from "./parse.ts"; // 策略版本:草案 → 预览 → 授权发布 → 版本化 / 回滚(REQ §6.4) export const policyKeys = { all: ["policies"] as const, list: (f: PolicyFilters) => ["policies", "list", f] as const, }; export type PolicyFilters = { policyKey?: string; status?: PolicyStatus }; const Page = cursorPage(PolicyRevision); export function usePolicyRevisions(filters: PolicyFilters = {}) { return useQuery({ queryKey: policyKeys.list(filters), queryFn: ({ signal }) => fetchAllCursorPages((cursor) => getParsed(Page, "/policy-revisions", { ...filters, limit: 200, cursor }, signal)), }); } /** 预览结果(合同 PolicyPreviewSummary;存在 policy_revision.preview) */ export const PolicyPreview = PolicyPreviewSummary; export type PolicyPreview = PolicyPreviewSummary; const parse = (d: unknown) => parseOrThrow(PolicyRevision, d, "/policy-revisions"); function useAction(fn: (v: V) => Promise) { const qc = useQueryClient(); return useMutation({ mutationFn: (v: V) => fn(v).then(parse), onSuccess: () => { void qc.invalidateQueries({ queryKey: policyKeys.all }); void qc.invalidateQueries({ queryKey: ["subscriptions"] }); }, }); } export const useCreatePolicy = () => useAction((body: PolicyRevisionCreate) => api.post("/policy-revisions", body)); export const useUpdatePolicy = () => useAction(({ id, ...body }: PolicyRevisionUpdate & { id: string }) => api.patch(`/policy-revisions/${id}`, body)); export const usePreviewPolicy = () => useAction((id: string) => api.post(`/policy-revisions/${id}/preview`)); export const usePublishPolicy = () => useAction((v: { id: string; expectedRevision: number }) => api.post(`/policy-revisions/${v.id}/publish`, { expectedRevision: v.expectedRevision }), ); export const useRollbackPolicy = () => useAction((id: string) => api.post(`/policy-revisions/${id}/rollback`));