"use client"; import { useState, useRef } from "react"; import { Plus, Pencil, Trash2, Upload, X } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Badge } from "@/components/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { useAdmin } from "@/contexts/AdminContext"; import { useLanguage } from "@/contexts/LanguageContext"; import { ApiError } from "@/lib/api"; import { adminUploadProductImage } from "@/lib/api/products"; import { Product } from "@/data/products"; import { toast } from "sonner"; type FormState = { name: string; category: Product["category"]; price: string; original_price: string; stock_quantity: string; description: string; colors: string; lengths: string; isNew: boolean; isBestseller: boolean; }; const emptyForm: FormState = { name: "", category: "clip-in", price: "", original_price: "", stock_quantity: "0", description: "", colors: "", lengths: "", isNew: false, isBestseller: false, }; export default function AdminProducts() { const { products, productsLoading, addProduct, updateProduct, deleteProduct, refreshProducts } = useAdmin(); const { t } = useLanguage(); const [dialogOpen, setDialogOpen] = useState(false); const [editingId, setEditingId] = useState(null); const [form, setForm] = useState(emptyForm); const [deleteId, setDeleteId] = useState(null); const [saving, setSaving] = useState(false); const [imageFile, setImageFile] = useState(null); const [imagePreview, setImagePreview] = useState(null); const fileInputRef = useRef(null); const categoryLabels: Record = { "clip-in": "Clip-In", "tape-in": "Tape-In", "ponytail": "Ponytail", "keratin": t("admin.products.category") === "Kategorie" ? "Keratin" : t("admin.products.category") === "Category" ? "Keratin" : "Kératine", }; const openCreate = () => { setEditingId(null); setForm(emptyForm); setImageFile(null); setImagePreview(null); setDialogOpen(true); }; const openEdit = (p: Product) => { setEditingId(p.id); setForm({ name: p.name, category: p.category, price: String(p.price), original_price: p.originalPrice ? String(p.originalPrice) : "", stock_quantity: String(p.stockQuantity ?? 0), description: p.description, colors: p.colors.join(", "), lengths: p.lengths.join(", "), isNew: !!p.isNew, isBestseller: !!p.isBestseller, }); setImageFile(null); setImagePreview(p.image || null); setDialogOpen(true); }; const handleFileChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; setImageFile(file); setImagePreview(URL.createObjectURL(file)); }; const clearImage = () => { setImageFile(null); setImagePreview(null); if (fileInputRef.current) fileInputRef.current.value = ""; }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const price = parseFloat(form.price); if (!form.name || isNaN(price)) { toast.error(t("admin.products.valid_required")); return; } const payload = { name: form.name, category: form.category, price, original_price: form.original_price ? parseFloat(form.original_price) : undefined, stock_quantity: parseInt(form.stock_quantity) || 0, colors: form.colors.split(",").map((c) => c.trim()).filter(Boolean), lengths: form.lengths.split(",").map((l) => l.trim()).filter(Boolean), description: form.description, features: [], is_new: form.isNew, is_bestseller: form.isBestseller, }; setSaving(true); try { let savedId = editingId; if (editingId) { await updateProduct(editingId, payload); } else { const created = await addProduct(payload); savedId = created.id; } if (imageFile && savedId) { await adminUploadProductImage(savedId, imageFile); await refreshProducts(); } toast.success(editingId ? t("admin.products.saved") : t("admin.products.added")); setDialogOpen(false); } catch (err) { toast.error(err instanceof ApiError ? err.message : t("admin.products.save_error")); } finally { setSaving(false); } }; const handleDelete = async () => { if (!deleteId) return; try { await deleteProduct(deleteId); toast.success(t("admin.products.deleted")); } catch (err) { toast.error(err instanceof ApiError ? err.message : t("admin.products.delete_error")); } finally { setDeleteId(null); } }; return (

{t("admin.products.title")}

{products.length} {t("admin.products.subtitle")}

{productsLoading ? (
{Array.from({ length: 4 }).map((_, i) => (
))}
) : ( {t("admin.products.col_image")} {t("admin.products.col_name")} {t("admin.products.col_category")} {t("admin.products.col_price")} {t("admin.products.col_stock")} {t("admin.products.col_status")} {t("admin.actions")} {products.map((p) => ( {p.image ? ( {p.name} ) : (
)}
{p.name} {categoryLabels[p.category]} {p.price} € {p.stockQuantity ?? 0} {p.isNew && {t("admin.products.badge_new")}} {p.isBestseller && Bestseller}
))}
)} {editingId ? t("admin.products.edit_title") : t("admin.products.create_title")} {t("admin.products.form_desc")}
setForm({ ...form, name: e.target.value })} required />
setForm({ ...form, price: e.target.value })} required />
setForm({ ...form, original_price: e.target.value })} placeholder={t("admin.products.optional")} />
setForm({ ...form, stock_quantity: e.target.value })} />
{imagePreview && (
preview {imageFile && ( )}
)}
{imageFile &&

{imageFile.name}

}