2025-11-18 06:56:39 +00:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
Dialog,
|
|
|
|
|
DialogContent,
|
|
|
|
|
DialogHeader,
|
|
|
|
|
DialogTitle,
|
|
|
|
|
DialogFooter,
|
|
|
|
|
} from "@/components/ui/dialog";
|
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
|
import { Input } from "@/components/ui/input";
|
2025-11-20 06:57:16 +00:00
|
|
|
import { Upload, X } from "lucide-react";
|
|
|
|
|
import { useState, useRef, useEffect } from "react";
|
|
|
|
|
import { createGalery, uploadGaleryFile } from "@/service/galery";
|
2025-11-18 06:56:39 +00:00
|
|
|
|
2026-02-03 11:30:03 +00:00
|
|
|
const CATEGORY_OPTIONS = [
|
|
|
|
|
"Grand Opening",
|
|
|
|
|
"IIMS",
|
|
|
|
|
"GIIAS",
|
|
|
|
|
"GJAW",
|
|
|
|
|
"Exhibitions",
|
|
|
|
|
"Test Drive",
|
|
|
|
|
];
|
|
|
|
|
|
2025-11-18 06:56:39 +00:00
|
|
|
export function GaleriDialog({ open, onClose, onSubmit }: any) {
|
|
|
|
|
const [title, setTitle] = useState("");
|
2025-11-20 06:57:16 +00:00
|
|
|
const [description, setDescription] = useState("");
|
|
|
|
|
const [files, setFiles] = useState<File[]>([]);
|
|
|
|
|
const [previews, setPreviews] = useState<string[]>([]);
|
2025-11-18 06:56:39 +00:00
|
|
|
const fileRef = useRef<HTMLInputElement>(null);
|
2026-02-03 11:30:03 +00:00
|
|
|
const [category, setCategory] = useState("");
|
2025-11-18 06:56:39 +00:00
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (!files || files.length === 0) {
|
|
|
|
|
setPreviews([]);
|
2025-11-18 06:56:39 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
const objectUrls = files.map((file) => URL.createObjectURL(file));
|
|
|
|
|
setPreviews(objectUrls);
|
2025-11-18 06:56:39 +00:00
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
return () => {
|
|
|
|
|
objectUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
|
|
|
};
|
|
|
|
|
}, [files]);
|
2025-11-18 06:56:39 +00:00
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
|
|
const files = e.target.files;
|
|
|
|
|
if (!files) return;
|
|
|
|
|
setFiles((prev: File[]) => [...prev, ...Array.from(files)]);
|
|
|
|
|
};
|
2025-11-18 06:56:39 +00:00
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
const removeFile = (index: number) => {
|
|
|
|
|
setFiles((prev) => prev.filter((_, i) => i !== index));
|
2025-11-18 06:56:39 +00:00
|
|
|
};
|
|
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
const handleSubmit = async () => {
|
|
|
|
|
try {
|
|
|
|
|
if (!title) return alert("Judul wajib diisi!");
|
2026-02-03 11:30:03 +00:00
|
|
|
if (!category) return alert("Category wajib diisi!");
|
2025-11-20 06:57:16 +00:00
|
|
|
const formData = new FormData();
|
|
|
|
|
formData.append("title", title);
|
|
|
|
|
formData.append("description", description);
|
2026-02-03 11:30:03 +00:00
|
|
|
formData.append("category", category);
|
2025-11-20 06:57:16 +00:00
|
|
|
|
|
|
|
|
const res = await createGalery(formData);
|
|
|
|
|
|
|
|
|
|
const galleryId = res?.data?.data?.id;
|
|
|
|
|
if (!galleryId) {
|
|
|
|
|
alert("Galeri gagal dibuat");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log("Galeri Created:", galleryId);
|
|
|
|
|
|
|
|
|
|
for (const file of files) {
|
|
|
|
|
const fileForm = new FormData();
|
|
|
|
|
fileForm.append("gallery_id", galleryId);
|
|
|
|
|
fileForm.append("title", title);
|
|
|
|
|
fileForm.append("file", file);
|
|
|
|
|
|
|
|
|
|
const uploadRes = await uploadGaleryFile(galleryId, fileForm);
|
|
|
|
|
console.log("File Uploaded:", uploadRes?.data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onSubmit();
|
2026-02-03 11:30:03 +00:00
|
|
|
setCategory("");
|
2025-11-20 06:57:16 +00:00
|
|
|
setTitle("");
|
|
|
|
|
setDescription("");
|
|
|
|
|
setFiles([]);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Submit failed:", error);
|
|
|
|
|
alert("Gagal mengupload galeri");
|
|
|
|
|
}
|
2025-11-18 06:56:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Dialog open={open} onOpenChange={onClose}>
|
|
|
|
|
<DialogContent className="max-w-2xl rounded-2xl p-0 overflow-hidden">
|
2025-11-20 06:57:16 +00:00
|
|
|
{/* HEADER */}
|
2025-11-18 06:56:39 +00:00
|
|
|
<div className="bg-[#1F6779] text-white px-6 py-4 flex justify-between items-center">
|
|
|
|
|
<DialogTitle className="text-white">Tambah Galeri</DialogTitle>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
{/* BODY */}
|
2025-11-18 06:56:39 +00:00
|
|
|
<div className="px-6 py-6 space-y-6">
|
|
|
|
|
{/* Judul */}
|
|
|
|
|
<div>
|
|
|
|
|
<label className="font-medium text-sm">
|
|
|
|
|
Judul Galeri <span className="text-red-500">*</span>
|
|
|
|
|
</label>
|
|
|
|
|
<Input
|
|
|
|
|
placeholder="Masukkan judul galeri"
|
|
|
|
|
className="mt-1 h-12"
|
|
|
|
|
value={title}
|
|
|
|
|
onChange={(e) => setTitle(e.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-02-03 11:30:03 +00:00
|
|
|
{/* Category */}
|
|
|
|
|
<div>
|
|
|
|
|
<label className="font-medium text-sm">
|
|
|
|
|
Category <span className="text-red-500">*</span>
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
<select
|
|
|
|
|
value={category}
|
|
|
|
|
onChange={(e) => setCategory(e.target.value)}
|
|
|
|
|
className="mt-1 h-12 w-full rounded-md border border-gray-300 px-3 text-sm focus:outline-none focus:ring-2 focus:ring-[#1F6779]"
|
|
|
|
|
>
|
|
|
|
|
<option value="">Pilih category</option>
|
|
|
|
|
{CATEGORY_OPTIONS.map((cat) => (
|
|
|
|
|
<option key={cat} value={cat}>
|
|
|
|
|
{cat}
|
|
|
|
|
</option>
|
|
|
|
|
))}
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-18 06:56:39 +00:00
|
|
|
{/* Deskripsi */}
|
|
|
|
|
<div>
|
|
|
|
|
<label className="font-medium text-sm">
|
|
|
|
|
Deskripsi Galeri <span className="text-red-500">*</span>
|
|
|
|
|
</label>
|
|
|
|
|
<Input
|
|
|
|
|
placeholder="Masukkan deskripsi galeri"
|
|
|
|
|
className="mt-1 h-12"
|
2025-11-20 06:57:16 +00:00
|
|
|
value={description}
|
|
|
|
|
onChange={(e) => setDescription(e.target.value)}
|
2025-11-18 06:56:39 +00:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
{/* Upload File */}
|
2025-11-18 06:56:39 +00:00
|
|
|
<div>
|
|
|
|
|
<label className="font-medium text-sm">
|
2025-11-20 06:57:16 +00:00
|
|
|
Upload File (opsional)
|
2025-11-18 06:56:39 +00:00
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
className="border-2 border-dashed rounded-xl flex flex-col items-center justify-center py-10 cursor-pointer"
|
|
|
|
|
onClick={() => fileRef.current?.click()}
|
|
|
|
|
>
|
|
|
|
|
<Upload className="w-10 h-10 text-[#1F6779]" />
|
|
|
|
|
|
|
|
|
|
<p className="text-sm text-gray-600 mt-2">
|
|
|
|
|
Klik untuk upload atau drag & drop
|
|
|
|
|
</p>
|
|
|
|
|
<p className="text-xs text-gray-400">PNG, JPG (max 2MB)</p>
|
|
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
ref={fileRef}
|
|
|
|
|
type="file"
|
|
|
|
|
className="hidden"
|
|
|
|
|
onChange={handleFileChange}
|
|
|
|
|
accept="image/*"
|
2025-11-20 06:57:16 +00:00
|
|
|
multiple
|
2025-11-18 06:56:39 +00:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
{/* Preview Gambar */}
|
|
|
|
|
{previews.length > 0 && (
|
|
|
|
|
<div className="mt-4 flex flex-wrap gap-4">
|
|
|
|
|
{previews.map((src, i) => (
|
|
|
|
|
<div
|
|
|
|
|
key={i}
|
|
|
|
|
className="relative w-24 h-24 rounded-lg overflow-hidden border border-gray-300"
|
|
|
|
|
>
|
|
|
|
|
<img
|
|
|
|
|
src={src}
|
|
|
|
|
alt={`preview-${i}`}
|
|
|
|
|
className="object-cover w-full h-full"
|
|
|
|
|
/>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => removeFile(i)}
|
|
|
|
|
className="absolute top-1 right-1 bg-red-600 rounded-full p-1 text-white hover:bg-red-700 transition"
|
|
|
|
|
title="Hapus gambar"
|
|
|
|
|
type="button"
|
|
|
|
|
>
|
|
|
|
|
<X size={16} />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
2025-11-18 06:56:39 +00:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-20 06:57:16 +00:00
|
|
|
{/* FOOTER */}
|
2025-11-18 06:56:39 +00:00
|
|
|
<DialogFooter className="flex justify-between px-6 pb-6 gap-4">
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
onClick={onClose}
|
|
|
|
|
className="bg-slate-200 text-slate-700 w-full h-12"
|
|
|
|
|
>
|
|
|
|
|
Batal
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
onClick={handleSubmit}
|
|
|
|
|
className="bg-[#1F6779] hover:bg-[#165766] text-white w-full h-12"
|
|
|
|
|
>
|
|
|
|
|
Submit
|
|
|
|
|
</Button>
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
</DialogContent>
|
|
|
|
|
</Dialog>
|
|
|
|
|
);
|
|
|
|
|
}
|