{"path":"src/components/admin/ProductForm.tsx","size":7235,"locked":false,"binary":false,"truncated":false,"content":"\"use client\";\n\nimport { useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport { createClient } from \"@/lib/supabase/client\";\nimport { Plus, Trash2 } from \"lucide-react\";\n\ninterface ProductFormProps {\n  initialData?: any;\n  isEditing?: boolean;\n}\n\nexport function ProductForm({ initialData, isEditing }: ProductFormProps) {\n  const router = useRouter();\n  const supabase = createClient();\n  const [loading, setLoading] = useState(false);\n\n  // Convert images array (if exists) to an array of strings, default to one empty string\n  const existingImages: string[] = Array.isArray(initialData?.images)\n    ? initialData.images\n    : initialData?.image\n    ? [initialData.image]\n    : [\"\"];\n\n  const [imageList, setImageList] = useState<string[]>(existingImages);\n\n  const [form, setForm] = useState({\n    name: initialData?.name || \"\",\n    description: initialData?.description || \"\",\n    price: initialData?.price?.toString() || \"\",\n    badge: initialData?.badge || \"\",\n    icon: initialData?.icon || \"sparkles\",\n    is_active: initialData?.is_active ?? true,\n  });\n\n  const handleChange = (\n    e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>\n  ) => {\n    const { name, value, type } = e.target;\n    setForm((prev) => ({\n      ...prev,\n      [name]: type === \"checkbox\" ? (e.target as HTMLInputElement).checked : value,\n    }));\n  };\n\n  const handleImageChange = (index: number, value: string) => {\n    const updated = [...imageList];\n    updated[index] = value;\n    setImageList(updated);\n  };\n\n  const addImageField = () => setImageList([...imageList, \"\"]);\n\n  const removeImageField = (index: number) => {\n    if (imageList.length <= 1) return;\n    const updated = imageList.filter((_, i) => i !== index);\n    setImageList(updated);\n  };\n\n  const handleSubmit = async (e: React.FormEvent) => {\n    e.preventDefault();\n    if (!supabase) {\n      alert(\"Database not connected. Please run the Setup Wizard first.\");\n      return;\n    }\n    setLoading(true);\n\n    // Filter out empty URLs\n    const cleanedImages = imageList.map((url) => url.trim()).filter((url) => url.length > 0);\n    const primaryImage = cleanedImages.length > 0 ? cleanedImages[0] : \"\";\n\n    const payload = {\n      name: form.name,\n      description: form.description,\n      price: parseFloat(form.price) || 0,\n      image: primaryImage,\n      images: cleanedImages,\n      badge: form.badge,\n      icon: form.icon,\n      is_active: form.is_active,\n    };\n\n    if (isEditing && initialData) {\n      await supabase.from(\"products\").update(payload).eq(\"id\", initialData.id);\n    } else {\n      await supabase.from(\"products\").insert([payload]);\n    }\n\n    setLoading(false);\n    router.push(\"/admin/products\");\n    router.refresh();\n  };\n\n  return (\n    <form onSubmit={handleSubmit} className=\"max-w-2xl bg-white border border-neutral-200 rounded-sm p-6 space-y-6\">\n      <h2 className=\"text-xl font-serif font-semibold\">\n        {isEditing ? \"Edit Product\" : \"New Product\"}\n      </h2>\n\n      <div className=\"grid grid-cols-1 gap-4\">\n        <div>\n          <label className=\"block text-sm font-medium text-neutral-700 mb-1\">Name</label>\n          <input type=\"text\" name=\"name\" value={form.name} onChange={handleChange} required className=\"w-full border border-neutral-300 rounded-sm px-3 py-2 text-sm\" />\n        </div>\n        <div>\n          <label className=\"block text-sm font-medium text-neutral-700 mb-1\">Description</label>\n          <textarea name=\"description\" value={form.description} onChange={handleChange} rows={3} className=\"w-full border border-neutral-300 rounded-sm px-3 py-2 text-sm\" />\n        </div>\n        <div className=\"grid grid-cols-2 gap-4\">\n          <div>\n            <label className=\"block text-sm font-medium text-neutral-700 mb-1\">Price</label>\n            <input type=\"number\" name=\"price\" value={form.price} onChange={handleChange} step=\"0.01\" required className=\"w-full border border-neutral-300 rounded-sm px-3 py-2 text-sm\" />\n          </div>\n          <div>\n            <label className=\"block text-sm font-medium text-neutral-700 mb-1\">Badge (optional)</label>\n            <input type=\"text\" name=\"badge\" value={form.badge} onChange={handleChange} className=\"w-full border border-neutral-300 rounded-sm px-3 py-2 text-sm\" />\n          </div>\n        </div>\n\n        {/* Multi‑image section */}\n        <div>\n          <label className=\"block text-sm font-medium text-neutral-700 mb-2\">\n            Product Images (first is primary)\n          </label>\n          <div className=\"space-y-2\">\n            {imageList.map((url, idx) => (\n              <div key={idx} className=\"flex gap-2 items-center\">\n                <input\n                  type=\"text\"\n                  value={url}\n                  onChange={(e) => handleImageChange(idx, e.target.value)}\n                  placeholder=\"https://...\"\n                  className=\"flex-1 border border-neutral-300 rounded-sm px-3 py-2 text-sm\"\n                />\n                {imageList.length > 1 && (\n                  <button\n                    type=\"button\"\n                    onClick={() => removeImageField(idx)}\n                    className=\"text-neutral-400 hover:text-red-500 transition p-1\"\n                  >\n                    <Trash2 className=\"w-4 h-4\" />\n                  </button>\n                )}\n              </div>\n            ))}\n          </div>\n          <button\n            type=\"button\"\n            onClick={addImageField}\n            className=\"mt-2 inline-flex items-center gap-1 text-xs uppercase tracking-wider text-neutral-500 hover:text-black transition font-medium\"\n          >\n            <Plus className=\"w-3.5 h-3.5\" /> Add Image URL\n          </button>\n          <p className=\"text-xs text-neutral-400 mt-1\">Leave empty if no images are needed.</p>\n        </div>\n\n        <div className=\"grid grid-cols-2 gap-4\">\n          <div>\n            <label className=\"block text-sm font-medium text-neutral-700 mb-1\">Icon</label>\n            <select name=\"icon\" value={form.icon} onChange={handleChange} className=\"w-full border border-neutral-300 rounded-sm px-3 py-2 text-sm\">\n              <option value=\"sparkles\">Sparkles</option>\n              <option value=\"wallet\">Wallet</option>\n              <option value=\"glasses\">Glasses</option>\n              <option value=\"watch\">Watch</option>\n            </select>\n          </div>\n          <div className=\"flex items-end pb-1\">\n            <label className=\"flex items-center gap-2 text-sm\">\n              <input type=\"checkbox\" name=\"is_active\" checked={form.is_active} onChange={handleChange} className=\"rounded\" />\n              Active (visible on site)\n            </label>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"flex justify-end gap-3\">\n        <button type=\"button\" onClick={() => router.back()} className=\"px-4 py-2 text-sm border border-neutral-300 rounded-sm hover:bg-neutral-50\">Cancel</button>\n        <button type=\"submit\" disabled={loading} className=\"px-4 py-2 text-sm bg-black text-white rounded-sm hover:bg-neutral-800 disabled:opacity-50\">\n          {loading ? \"Saving...\" : isEditing ? \"Update Product\" : \"Create Product\"}\n        </button>\n      </div>\n    </form>\n  );\n    }\n"}