/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable react-hooks/exhaustive-deps */ 'use client'; import colors from '@/con/colors'; import ApiFetch from '@/lib/api-fetch'; import { Box, Button, Group, Image, Paper, Stack, Text, TextInput, Title, Loader, ActionIcon, NumberInput, Select, Table, Badge, } from '@mantine/core'; import { Dropzone } from '@mantine/dropzone'; import { IconArrowBack, IconFile, IconPhoto, IconUpload, IconX, IconPlus, IconTrash } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; import { toast } from 'react-toastify'; import { useProxy } from 'valtio/utils'; import apbdes from '../../../_state/landing-page/apbdes'; // Tipe item untuk form type ItemForm = { kode: string; uraian: string; anggaran: number; level: number; tipe: 'pendapatan' | 'belanja' | 'pembiayaan'; }; function CreateAPBDes() { const router = useRouter(); const stateAPBDes = useProxy(apbdes); const [previewImage, setPreviewImage] = useState(null); const [previewDoc, setPreviewDoc] = useState(null); const [imageFile, setImageFile] = useState(null); const [docFile, setDocFile] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); // Check if form is valid const isFormValid = () => { return ( imageFile !== null && docFile !== null && stateAPBDes.create.form.items.length > 0 ); }; // Form sementara untuk input item baru const [newItem, setNewItem] = useState({ kode: '', uraian: '', anggaran: 0, level: 1, tipe: 'pendapatan', }); useEffect(() => { stateAPBDes.findMany.load(); }, []); const resetForm = () => { stateAPBDes.create.reset(); setImageFile(null); setDocFile(null); setPreviewImage(null); setPreviewDoc(null); setNewItem({ kode: '', uraian: '', anggaran: 0, level: 1, tipe: 'pendapatan', }); }; const handleSubmit = async () => { if (!imageFile || !docFile) { return toast.warn("Pilih gambar dan dokumen terlebih dahulu"); } if (stateAPBDes.create.form.items.length === 0) { return toast.warn("Minimal tambahkan 1 item APBDes"); } try { setIsSubmitting(true); const [uploadImageRes, uploadDocRes] = await Promise.all([ ApiFetch.api.fileStorage.create.post({ file: imageFile, name: imageFile.name }), ApiFetch.api.fileStorage.create.post({ file: docFile, name: docFile.name }), ]); const imageId = uploadImageRes?.data?.data?.id; const fileId = uploadDocRes?.data?.data?.id; if (!imageId || !fileId) { return toast.error("Gagal mengupload file"); } // Update form dengan ID file stateAPBDes.create.form.imageId = imageId; stateAPBDes.create.form.fileId = fileId; await stateAPBDes.create.create(); toast.success("Berhasil menambahkan APBDes"); resetForm(); router.push("/admin/landing-page/apbdes"); } catch (error: any) { console.error("Gagal submit:", error); toast.error(error?.message || "Gagal menyimpan data"); } finally { setIsSubmitting(false); } }; // Tambahkan item ke state const handleAddItem = () => { const { kode, uraian, anggaran, level, tipe } = newItem; if (!kode || !uraian) { return toast.warn("Kode dan uraian wajib diisi"); } const finalTipe = level === 1 ? null : tipe; stateAPBDes.create.addItem({ kode, uraian, anggaran, level, tipe: finalTipe, }); // Reset form input setNewItem({ kode: '', uraian: '', anggaran: 0, level: 1, tipe: 'pendapatan', }); }; // Hapus item const handleRemoveItem = (index: number) => { stateAPBDes.create.removeItem(index); }; return ( Tambah APBDes {/* Gambar & Dokumen (dipendekkan untuk fokus pada items) */} {/* Gambar APBDes */} Gambar APBDes { const selectedFile = files[0]; if (selectedFile) { setImageFile(selectedFile); setPreviewImage(URL.createObjectURL(selectedFile)); } }} onReject={() => toast.error('File tidak valid, gunakan format gambar')} maxSize={5 * 1024 ** 2} accept={{ 'image/*': ['.jpeg', '.jpg', '.png', '.webp'] }} radius="md" p="xl" > Seret gambar atau klik untuk memilih {previewImage && ( Preview Gambar {/* Tombol hapus (pojok kanan atas) */} { setPreviewImage(null); setImageFile(null); }} style={{ boxShadow: '0 2px 6px rgba(0,0,0,0.15)', }} > )} {/* Dokumen APBDes */} Dokumen APBDes { const selectedFile = files[0]; if (selectedFile) { setDocFile(selectedFile); setPreviewDoc(URL.createObjectURL(selectedFile)); } }} onReject={() => toast.error('File tidak valid')} maxSize={5 * 1024 ** 2} accept={{ 'application/pdf': ['.pdf'], 'application/msword': ['.doc'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'], }} radius="md" p="xl" > Seret dokumen atau klik untuk memilih {previewDoc && ( Pratinjau Dokumen