63 lines
1.8 KiB
TypeScript
63 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
import { generateGalleryVariantsMissing } from "@/actions/artworks/generateGalleryVariant";
|
|
import { getGalleryVariantStats } from "@/actions/artworks/getGalleryVariantStats";
|
|
import { Button } from "@/components/ui/button";
|
|
import * as React from "react";
|
|
|
|
export function ArtworkGalleryVariantProcessor() {
|
|
const [stats, setStats] = React.useState<Awaited<
|
|
ReturnType<typeof getGalleryVariantStats>
|
|
> | null>(null);
|
|
const [loading, setLoading] = React.useState(false);
|
|
const [msg, setMsg] = React.useState<string | null>(null);
|
|
|
|
const refreshStats = React.useCallback(async () => {
|
|
const s = await getGalleryVariantStats();
|
|
setStats(s);
|
|
}, []);
|
|
|
|
React.useEffect(() => {
|
|
void refreshStats();
|
|
}, [refreshStats]);
|
|
|
|
const run = async () => {
|
|
setLoading(true);
|
|
setMsg(null);
|
|
try {
|
|
const res = await generateGalleryVariantsMissing({ limit: 50 });
|
|
setMsg(`Processed ${res.processed}: ${res.ok} ok, ${res.failed} failed`);
|
|
await refreshStats();
|
|
} catch (e) {
|
|
setMsg(e instanceof Error ? e.message : "Failed");
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const done = !!stats && stats.missing === 0;
|
|
|
|
return (
|
|
<div className="flex flex-col gap-2">
|
|
<div className="flex items-center gap-4">
|
|
<Button onClick={run} disabled={loading || done}>
|
|
{done
|
|
? "All gallery variants present"
|
|
: loading
|
|
? "Generating…"
|
|
: "Generate missing gallery variants"}
|
|
</Button>
|
|
|
|
{stats && (
|
|
<span className="text-sm text-muted-foreground">
|
|
Ready {stats.withGallery}/{stats.total}
|
|
{stats.missing > 0 && ` · Missing ${stats.missing}`}
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
{msg && <p className="text-sm text-muted-foreground">{msg}</p>}
|
|
</div>
|
|
);
|
|
}
|