2026-01-07 08:06:07 +00:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import { useState } from "react";
|
|
|
|
|
import { Upload, Plus, Settings } from "lucide-react";
|
|
|
|
|
import Image from "next/image";
|
|
|
|
|
import { Input } from "@/components/ui/input";
|
|
|
|
|
import { Label } from "@/components/ui/label";
|
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
|
import { Card, CardHeader, CardContent, CardTitle } from "@/components/ui/card";
|
|
|
|
|
import {
|
|
|
|
|
Dialog,
|
|
|
|
|
DialogContent,
|
|
|
|
|
DialogFooter,
|
|
|
|
|
DialogHeader,
|
|
|
|
|
DialogTitle,
|
|
|
|
|
} from "@/components/ui/dialog";
|
|
|
|
|
|
|
|
|
|
export default function UpdateProductForm() {
|
|
|
|
|
const [specs, setSpecs] = useState([
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
title: "Jaecoo 7 SHS Teknologi dan Exterior",
|
|
|
|
|
images: ["/spec1.jpg", "/spec2.jpg", "/spec3.jpg", "/spec4.jpg"],
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
type ColorType = {
|
|
|
|
|
id: number;
|
|
|
|
|
name: string;
|
|
|
|
|
preview: string;
|
|
|
|
|
colorSelected: string | null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const [colors, setColors] = useState<ColorType[]>([
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
name: "",
|
|
|
|
|
preview: "/car-1.png",
|
|
|
|
|
colorSelected: null,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 2,
|
|
|
|
|
name: "",
|
|
|
|
|
preview: "/car-2.png",
|
|
|
|
|
colorSelected: null,
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const palette = [
|
|
|
|
|
"#1E4E52",
|
|
|
|
|
"#597E8D",
|
|
|
|
|
"#6B6B6B",
|
|
|
|
|
"#BEBEBE",
|
|
|
|
|
"#E2E2E2",
|
|
|
|
|
"#F4F4F4",
|
|
|
|
|
"#FFFFFF",
|
|
|
|
|
"#F9360A",
|
|
|
|
|
"#9A2A00",
|
|
|
|
|
"#7A1400",
|
|
|
|
|
"#4B0200",
|
|
|
|
|
"#B48B84",
|
|
|
|
|
"#FFA598",
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const handleAddSpec = () => {
|
|
|
|
|
setSpecs((prev) => [
|
|
|
|
|
...prev,
|
|
|
|
|
{
|
|
|
|
|
id: prev.length + 1,
|
|
|
|
|
title: "",
|
|
|
|
|
images: [],
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleAddColor = () => {
|
|
|
|
|
setColors((p) => [
|
|
|
|
|
...p,
|
|
|
|
|
{
|
|
|
|
|
id: p.length + 1,
|
|
|
|
|
name: "",
|
|
|
|
|
preview: "/car-default.png",
|
|
|
|
|
colorSelected: null,
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const [isUploadDialogOpen, setIsUploadDialogOpen] = useState(false);
|
|
|
|
|
const [uploadTarget, setUploadTarget] = useState<{
|
|
|
|
|
type: "spec" | "color";
|
|
|
|
|
index: number;
|
|
|
|
|
} | null>(null);
|
|
|
|
|
|
|
|
|
|
const fileInputId = "file-upload-input";
|
|
|
|
|
|
|
|
|
|
const handleFileSelected = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
|
|
const file = event.target.files?.[0];
|
|
|
|
|
if (!file || !uploadTarget) return;
|
|
|
|
|
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
reader.onload = () => {
|
|
|
|
|
const fileUrl = reader.result as string;
|
|
|
|
|
|
|
|
|
|
if (uploadTarget.type === "spec") {
|
|
|
|
|
setSpecs((prev) => {
|
|
|
|
|
const updated = [...prev];
|
|
|
|
|
updated[uploadTarget.index].images.push(fileUrl);
|
|
|
|
|
return updated;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (uploadTarget.type === "color") {
|
|
|
|
|
setColors((prev) => {
|
|
|
|
|
const updated = [...prev];
|
|
|
|
|
updated[uploadTarget.index].preview = fileUrl;
|
|
|
|
|
return updated;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
reader.readAsDataURL(file);
|
|
|
|
|
setIsUploadDialogOpen(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Card className="w-full border-none shadow-md">
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<CardTitle className="text-xl font-bold text-teal-900">
|
|
|
|
|
Edit Produk
|
|
|
|
|
</CardTitle>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
|
|
|
|
|
<CardContent className="space-y-8">
|
|
|
|
|
<div className="grid md:grid-cols-3 gap-4">
|
|
|
|
|
<div>
|
|
|
|
|
<Label>Nama Produk *</Label>
|
|
|
|
|
<Input defaultValue="JAECOO J7" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<Label>Tipe Varian *</Label>
|
|
|
|
|
<Input defaultValue="SHS" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<Label>Harga Produk *</Label>
|
|
|
|
|
<Input defaultValue="RP 599.000.000" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<Label className="font-semibold">Warna Produk *</Label>
|
|
|
|
|
|
|
|
|
|
{colors.map((item, index) => (
|
2026-01-26 03:04:14 +00:00
|
|
|
<div
|
|
|
|
|
key={item.id}
|
|
|
|
|
className="mt-6 pb-6 border-2 rounded-lg border-black p-3"
|
|
|
|
|
>
|
2026-01-07 08:06:07 +00:00
|
|
|
<Label>Pilih Warna {index + 1}</Label>
|
|
|
|
|
<Input
|
|
|
|
|
placeholder="Contoh: Silver / #E2E2E2"
|
|
|
|
|
className="mt-1"
|
|
|
|
|
defaultValue={item.name}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div className="flex items-center gap-2 mt-3">
|
|
|
|
|
<div className="w-10 h-10 rounded-full flex items-center justify-center bg-teal-900">
|
|
|
|
|
<Settings className="w-5 h-5 text-white" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{palette.map((colorCode) => (
|
|
|
|
|
<button
|
|
|
|
|
key={colorCode}
|
|
|
|
|
type="button"
|
|
|
|
|
style={{ backgroundColor: colorCode }}
|
|
|
|
|
className={`w-10 h-10 rounded-full border-2 transition ${
|
|
|
|
|
item.colorSelected === colorCode
|
|
|
|
|
? "border-teal-700 scale-110"
|
|
|
|
|
: "border-gray-300"
|
|
|
|
|
}`}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setColors((prev) => {
|
|
|
|
|
const updated = [...prev];
|
|
|
|
|
updated[index].colorSelected = colorCode;
|
|
|
|
|
return updated;
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mt-4">
|
|
|
|
|
<Label className="font-semibold">
|
|
|
|
|
Foto Produk Warna {index + 1}
|
|
|
|
|
</Label>
|
|
|
|
|
|
|
|
|
|
<div className="flex items-center gap-4 mt-2">
|
|
|
|
|
<Image
|
|
|
|
|
src={item.preview}
|
|
|
|
|
alt="car color"
|
|
|
|
|
width={120}
|
|
|
|
|
height={80}
|
|
|
|
|
className="object-cover rounded-md border"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
className="bg-teal-800 hover:bg-teal-900 text-white"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setUploadTarget({ type: "color", index });
|
|
|
|
|
setIsUploadDialogOpen(true);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
Upload File Baru
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={handleAddColor}
|
|
|
|
|
className="w-full bg-teal-800 hover:bg-teal-900 text-white mt-4"
|
|
|
|
|
>
|
|
|
|
|
<Plus className="w-4 h-4 mr-2" /> Tambah Warna Baru
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mt-10">
|
|
|
|
|
<Label className="text-lg font-semibold text-teal-900">
|
|
|
|
|
Spesifikasi Produk <span className="text-red-500">*</span>
|
|
|
|
|
</Label>
|
|
|
|
|
|
|
|
|
|
{specs.map((spec, index) => (
|
|
|
|
|
<div key={spec.id} className="mt-6">
|
|
|
|
|
<Label className="font-semibold text-sm">
|
|
|
|
|
Judul Spesifikasi {index + 1}
|
|
|
|
|
</Label>
|
|
|
|
|
<Input
|
|
|
|
|
defaultValue={spec.title}
|
|
|
|
|
placeholder="Masukkan Judul Spesifikasi"
|
|
|
|
|
className="mt-1"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Label className="font-semibold text-sm mt-4 block">
|
|
|
|
|
Foto Spesifikasi {index + 1}
|
|
|
|
|
</Label>
|
|
|
|
|
|
|
|
|
|
<div className="flex flex-wrap gap-4 mt-2">
|
|
|
|
|
{spec.images.map((img, i) => (
|
|
|
|
|
<Image
|
|
|
|
|
key={i}
|
|
|
|
|
src={img}
|
|
|
|
|
width={120}
|
|
|
|
|
height={120}
|
|
|
|
|
alt="spec"
|
|
|
|
|
className="rounded-lg border object-cover"
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
className="bg-teal-800 hover:bg-teal-900 text-white"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setUploadTarget({ type: "spec", index });
|
|
|
|
|
setIsUploadDialogOpen(true);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
Upload File Baru
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="my-6 border-b"></div>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
onClick={handleAddSpec}
|
|
|
|
|
className="w-full bg-teal-800 hover:bg-teal-900 text-white flex items-center justify-center gap-2 py-4 rounded-xl"
|
|
|
|
|
>
|
|
|
|
|
<Plus className="w-4 h-4" />
|
|
|
|
|
Tambahkan Spesifikasi Baru
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Button className=" bg-teal-800 hover:bg-teal-900 text-white py-3">
|
|
|
|
|
Submit
|
|
|
|
|
</Button>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
<Dialog open={isUploadDialogOpen} onOpenChange={setIsUploadDialogOpen}>
|
|
|
|
|
<DialogContent className="max-w-md">
|
|
|
|
|
<DialogHeader>
|
|
|
|
|
<DialogTitle className="text-teal-900 font-semibold">
|
|
|
|
|
Upload File
|
|
|
|
|
</DialogTitle>
|
|
|
|
|
</DialogHeader>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
className="border-2 border-dashed rounded-xl p-8 text-center cursor-pointer"
|
|
|
|
|
onClick={() => document.getElementById(fileInputId)?.click()}
|
|
|
|
|
>
|
|
|
|
|
<Upload className="w-10 h-10 text-gray-400 mx-auto mb-3" />
|
|
|
|
|
<p className="text-sm text-gray-500">
|
|
|
|
|
Klik untuk upload atau drag & drop
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-xs text-gray-400">PNG, JPG (max 2 MB)</p>
|
|
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
id={fileInputId}
|
|
|
|
|
type="file"
|
|
|
|
|
accept="image/*"
|
|
|
|
|
className="hidden"
|
|
|
|
|
onChange={handleFileSelected}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<DialogFooter className="flex gap-3 pt-4">
|
|
|
|
|
<Button
|
|
|
|
|
variant="secondary"
|
|
|
|
|
className="bg-slate-200"
|
|
|
|
|
onClick={() => setIsUploadDialogOpen(false)}
|
|
|
|
|
>
|
|
|
|
|
Batal
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
onClick={() => document.getElementById(fileInputId)?.click()}
|
|
|
|
|
className="bg-teal-800 hover:bg-teal-900 text-white"
|
|
|
|
|
>
|
|
|
|
|
Pilih File
|
|
|
|
|
</Button>
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
</DialogContent>
|
|
|
|
|
</Dialog>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|