"use client"; import { AlertTriangle, CheckCircle2, Loader2, Upload } from "lucide-react"; import { useMemo, useState } from "react"; import { toast } from "sonner"; import { bulkCreateCatalogItems } from "@/actions/catalog-items"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; interface ParsedRow { lineNumber: number; raw: string; ok: boolean; error?: string; baseId?: number; credits?: number; points?: number; pointsType?: number; } interface BulkImportItemsProps { pageId: number; onImported?: () => void; } export function BulkImportItems({ pageId, onImported }: BulkImportItemsProps) { const [open, setOpen] = useState(false); const [input, setInput] = useState(""); const [importing, setImporting] = useState(false); const parsed = useMemo(() => { const lines = input.split("\n"); const out: ParsedRow[] = []; lines.forEach((raw, idx) => { const trimmed = raw.trim(); if (!trimmed || trimmed.startsWith("#")) return; const parts = trimmed.split(/[,\s;]+/).filter(Boolean); const baseId = parseInt(parts[0], 10); if (Number.isNaN(baseId) || baseId <= 0) { out.push({ lineNumber: idx + 1, raw: trimmed, ok: false, error: "Invalid base ID", }); return; } const credits = parts[1] !== undefined ? parseInt(parts[1], 10) : 0; const points = parts[2] !== undefined ? parseInt(parts[2], 10) : 0; const pointsType = parts[3] !== undefined ? parseInt(parts[3], 10) : 0; if ( (parts[1] !== undefined && Number.isNaN(credits)) || (parts[2] !== undefined && Number.isNaN(points)) ) { out.push({ lineNumber: idx + 1, raw: trimmed, ok: false, error: "Invalid number", }); return; } out.push({ lineNumber: idx + 1, raw: trimmed, ok: true, baseId, credits, points, pointsType, }); }); return out; }, [input]); const validCount = parsed.filter((r) => r.ok).length; const invalidCount = parsed.length - validCount; async function handleImport() { const valid = parsed.filter((r) => r.ok); if (valid.length === 0) { toast.error("No valid rows to import"); return; } setImporting(true); try { const res = await bulkCreateCatalogItems({ pageId, rows: valid.map((row) => ({ baseId: row.baseId!, credits: row.credits, points: row.points, pointsType: row.pointsType, })), }); if (!res.ok) { toast.error(res.error || "Bulk import failed."); return; } const { created, failed } = res.data; if (created > 0) { toast.success( `Imported ${created} item(s)${failed > 0 ? `, ${failed} failed` : ""}.`, ); setInput(""); setOpen(false); onImported?.(); } else { toast.error( failed > 0 ? `All ${failed} imports failed (unknown base IDs?).` : "Nothing imported.", ); } } catch { toast.error("Bulk import failed."); } finally { setImporting(false); } } return ( Bulk Import Items