refactor(catalog): separate Studio data hooks and presentation
CI / check (push) Successful in 1m40s
CI / deploy (push) Successful in 1m26s
CI / e2e (push) Successful in 24s

This commit is contained in:
Simo committed 2026-09-05 18:15:29 +02:00
1 parent 570f3dde44
commit 3ae4f21217
9 files changed
+348 -263

No files matched your search

+1 -89
View File
@@ -1,94 +1,6 @@
"use client";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { adminFetch } from "@/lib/admin-fetch";
import type { ImportJob, ImportJobItem } from "@/lib/furni/import-job";
export function useFurnitureJobs(onComplete: () => void) {
const [jobs, setJobs] = useState<ImportJob[]>([]),
[busy, setBusy] = useState(false),
[error, setError] = useState("");
const completed = useRef(new Set<string>()),
callback = useRef(onComplete);
callback.current = onComplete;
const request = useRef<{ payload: string; id: string } | null>(null);
const submitting = useRef(false);
const refresh = useCallback(async () => {
try {
const response = await adminFetch("/api/admin/studio/import-jobs");
const data = await response.json();
if (!response.ok)
throw Error(
data.error || `Import history unavailable (${response.status})`,
);
setJobs(data.jobs);
setError("");
let changed = false;
for (const job of data.jobs as ImportJob[])
if (
(job.state === "completed" || job.state === "interrupted") &&
!completed.current.has(job.id)
) {
completed.current.add(job.id);
changed = true;
}
if (changed) callback.current();
} catch (error) {
setError(
error instanceof Error ? error.message : "Cannot load import history",
);
}
}, []);
useEffect(() => {
void refresh();
const timer = setInterval(() => void refresh(), 5000);
return () => clearInterval(timer);
}, [refresh]);
const submit = async (
items: ImportJobItem[],
options: {
sourceId?: string;
translate: boolean;
langs?: string[];
mode?: "repair";
},
) => {
if (submitting.current) return false;
submitting.current = true;
setBusy(true);
const body = { items, ...options },
payload = JSON.stringify(body);
if (request.current?.payload !== payload)
request.current = { payload, id: crypto.randomUUID() };
try {
const response = await adminFetch("/api/admin/studio/import-jobs", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ...body, id: request.current.id }),
});
const data = await response.json();
if (!response.ok)
throw Error(
data.error || `Could not queue import (${response.status})`,
);
request.current = null;
await refresh();
toast.success(
"Import queued. You can leave this page and return to its history.",
);
return true;
} catch (error) {
toast.error(
error instanceof Error ? error.message : "Could not queue import",
);
return false;
} finally {
submitting.current = false;
setBusy(false);
}
};
return { jobs, busy, error, submit, refresh };
}
import type { useFurnitureJobs } from "./use-furniture-jobs";
export function FurnitureJobHistory({
state,
}: {