"use client"; import { useState, useTransition } from "react"; import { FolderTree, Loader2, CheckCircle2 } from "lucide-react"; import { previewReorganize, reorganizeFiles } from "@/app/actions/maintenance"; type State = | { kind: "idle" } | { kind: "scanning" } | { kind: "preview"; total: number; toMove: number } | { kind: "running" } | { kind: "done"; moved: number; skipped: number; errors: number }; export function ReorganizeButton() { const [state, setState] = useState({ kind: "idle" }); const [pending, start] = useTransition(); const scan = () => { setState({ kind: "scanning" }); start(async () => { const r = await previewReorganize(); setState({ kind: "preview", total: r.total, toMove: r.toMove }); }); }; const run = () => { if (state.kind !== "preview") return; if (!confirm(`Move ${state.toMove} file${state.toMove === 1 ? "" : "s"} into letter buckets on disk? This relocates files; cannot be undone.`)) return; setState({ kind: "running" }); start(async () => { const r = await reorganizeFiles(); setState({ kind: "done", ...r }); }); }; return (
Re-organize Files
Move covers into letter buckets on disk —{" "} A-E / F-J / K-P / Q-U / V-Z at the top level, single-letter folders inside, keyed off each cover's code. Files without a code go to{" "} #/#/. Attached images bucket with their parent.
{state.kind === "preview" && (
{state.toMove} of {state.total} need to move
)} {state.kind === "done" && (
Moved {state.moved} · skipped {state.skipped} {state.errors > 0 && · {state.errors} error{state.errors === 1 ? "" : "s"}}
)}
{state.kind === "idle" && ( )} {(state.kind === "scanning" || state.kind === "running") && ( {state.kind === "scanning" ? "Scanning…" : "Moving…"} )} {state.kind === "preview" && state.toMove > 0 && ( <> )} {state.kind === "preview" && state.toMove === 0 && ( )} {state.kind === "done" && ( )}
); }