feat: WIP Contnet managemtn

This commit is contained in:
Nathnael
2026-08-08 09:37:28 +00:00
parent ee25de8817
commit 41e8c08ba3
48 changed files with 6601 additions and 657 deletions

View File

@@ -0,0 +1,78 @@
import type { SupportDocPayload, SupportDocSlug } from "@edr/types";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import toast from "react-hot-toast";
import { portalContentService } from "@/services/portal-content.service";
/**
* Every key shares the `portal-content` prefix so one invalidate after a save
* or a restore sweeps the document and its version list together.
*/
const KEYS = {
ROOT: ["portal-content"] as const,
bySlug: (slug: string) => ["portal-content", "detail", slug] as const,
versions: (slug: string) => ["portal-content", "versions", slug] as const,
};
export function usePortalDoc(slug: SupportDocSlug) {
return useQuery({
queryKey: KEYS.bySlug(slug),
queryFn: () => portalContentService.getBySlug(slug),
});
}
/** Version history. Stays idle until the history modal is opened. */
export function usePortalDocVersions(slug: SupportDocSlug, enabled: boolean) {
return useQuery({
queryKey: KEYS.versions(slug),
queryFn: () => portalContentService.listVersions(slug),
enabled,
});
}
/** One historical payload, fetched only when a version is previewed. */
export function usePortalDocVersion(
slug: SupportDocSlug,
version: number | null,
) {
return useQuery({
queryKey: [...KEYS.versions(slug), version],
queryFn: () => portalContentService.getVersion(slug, version as number),
enabled: version !== null,
});
}
function usePortalContentMutation<TVariables>(
mutationFn: (vars: TVariables) => Promise<unknown>,
successMessage: string,
) {
const queryClient = useQueryClient();
return useMutation({
mutationFn,
onSuccess: () => {
toast.success(successMessage);
void queryClient.invalidateQueries({ queryKey: KEYS.ROOT });
},
onError: (error: unknown) => {
const message =
(error as { response?: { data?: { message?: string } } })?.response?.data
?.message ?? "Something went wrong";
toast.error(Array.isArray(message) ? message.join(", ") : message);
},
});
}
export function useUpdatePortalDoc(slug: SupportDocSlug) {
return usePortalContentMutation(
(vars: { payload: SupportDocPayload; note?: string }) =>
portalContentService.update(slug, vars.payload, vars.note),
"Portal content saved",
);
}
export function useRestorePortalVersion(slug: SupportDocSlug) {
return usePortalContentMutation(
(version: number) => portalContentService.restore(slug, version),
"Version restored",
);
}