fix inputan edit menu: desa, ekonomi, inovasi, keamanan, kesehatan, landing-page, & lingkungan

This commit is contained in:
2025-09-30 21:41:26 +08:00
parent c2f1ab8179
commit 63054cedf0
67 changed files with 3056 additions and 2989 deletions

View File

@@ -1,19 +1,17 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
'use client';
import { useProxy } from 'valtio/utils';
import { Box, Button, Group, Image, Paper, Select, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { useParams, useRouter } from 'next/navigation';
import { Box, Button, Group, Image, Paper, Select, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
import { toast } from 'react-toastify';
import colors from '@/con/colors';
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import prestasiState from '@/app/admin/(dashboard)/_state/landing-page/prestasi-desa';
import ApiFetch from '@/lib/api-fetch';
import { Dropzone } from '@mantine/dropzone';
import { toast } from 'react-toastify';
interface FormPrestasiDesa {
name: string;
@@ -22,31 +20,31 @@ interface FormPrestasiDesa {
imageId: string;
}
function EditPrestasiDesa() {
const editState = useProxy(prestasiState.prestasiDesa)
const [previewFile, setPreviewFile] = useState<string | null>(null);
const [file, setFile] = useState<File | null>(null);
const params = useParams()
const router = useRouter()
export default function EditPrestasiDesa() {
const editState = useProxy(prestasiState.prestasiDesa);
const [formData, setFormData] = useState<FormPrestasiDesa>({
name: '',
deskripsi: '',
kategoriId: '',
imageId: '',
})
});
const [previewFile, setPreviewFile] = useState<string | null>(null);
const [file, setFile] = useState<File | null>(null);
const params = useParams();
const router = useRouter();
// Load kategori & prestasi desa
useEffect(() => {
prestasiState.kategoriPrestasi.findMany.load()
const loadDesaAntiKorupsi = async () => {
prestasiState.kategoriPrestasi.findMany.load();
const loadPrestasi = async () => {
const id = params?.id as string;
if (!id) return;
try {
const data = await editState.edit.load(id);
if (data) {
// ⬇️ FIX PENTING: tambahkan ini
editState.edit.id = id;
editState.edit.form = {
name: data.name,
deskripsi: data.deskripsi,
@@ -61,51 +59,37 @@ function EditPrestasiDesa() {
imageId: data.imageId,
});
if (data?.image?.link) {
setPreviewFile(data.image.link)
}
if (data.image?.link) setPreviewFile(data.image.link);
}
} catch (error) {
console.error("Error loading prestasi desa:", error);
toast.error("Gagal memuat data prestasi desa");
console.error('Error loading prestasi desa:', error);
toast.error('Gagal memuat data prestasi desa');
}
}
};
loadDesaAntiKorupsi();
loadPrestasi();
}, [params?.id]);
const handleSubmit = async () => {
try {
// Update global state with form data
editState.edit.form = {
...editState.edit.form,
name: formData.name,
deskripsi: formData.deskripsi,
kategoriId: formData.kategoriId || '',
imageId: formData.imageId // Keep existing imageId if not changed
};
// Jika ada file baru, upload
// Jika ada file baru, upload dulu
let imageId = formData.imageId;
if (file) {
const res = await ApiFetch.api.fileStorage.create.post({ file, name: file.name });
const uploaded = res.data?.data;
if (!uploaded?.id) {
return toast.error("Gagal upload gambar");
}
// Update imageId in global state
editState.edit.form.imageId = uploaded.id;
if (!uploaded?.id) return toast.error('Gagal upload gambar');
imageId = uploaded.id;
}
// Update global state sekaligus
editState.edit.form = { ...formData, imageId };
await editState.edit.update();
toast.success("prestasi desa berhasil diperbarui!");
router.push("/admin/landing-page/prestasi-desa/list-prestasi-desa");
toast.success('Prestasi desa berhasil diperbarui!');
router.push('/admin/landing-page/prestasi-desa/list-prestasi-desa');
} catch (error) {
console.error("Error updating prestasi desa:", error);
toast.error("Terjadi kesalahan saat memperbarui prestasi desa");
console.error('Error updating prestasi desa:', error);
toast.error('Terjadi kesalahan saat memperbarui prestasi desa');
}
};
@@ -117,71 +101,35 @@ function EditPrestasiDesa() {
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Prestasi Desa
</Title>
<Title order={4} ml="sm" c="dark">Edit Prestasi Desa</Title>
</Group>
<Paper
w={{ base: '100%', md: '50%' }}
bg={colors['white-1']}
p="lg"
radius="md"
shadow="sm"
style={{ border: '1px solid #e0e0e0' }}
>
<Paper w={{ base: '100%', md: '50%' }} bg={colors['white-1']} p="lg" radius="md" shadow="sm" style={{ border: '1px solid #e0e0e0' }}>
<Stack gap="md">
<TextInput
label="Judul Prestasi"
placeholder="Masukkan judul prestasi"
defaultValue={formData.name}
onChange={(val) => {
setFormData({
...formData,
name: val.target.value
});
}}
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
required
/>
<Box>
<Text fw="bold" fz="sm" mb={6}>
Deskripsi
</Text>
<EditEditor
value={formData.deskripsi}
onChange={(val) => {
setFormData({
...formData,
deskripsi: val
});
}}
/>
<Text fw="bold" fz="sm" mb={6}>Deskripsi</Text>
<EditEditor value={formData.deskripsi} onChange={(val) => setFormData({ ...formData, deskripsi: val })} />
</Box>
<Select
label="Kategori"
placeholder="Pilih kategori"
value={formData.kategoriId}
onChange={(val) => {
setFormData({
...formData,
kategoriId: val ?? ""
});
}}
data={
prestasiState.kategoriPrestasi.findMany.data?.map((v) => ({
value: v.id,
label: v.name,
})) || []
}
onChange={(val) => setFormData({ ...formData, kategoriId: val ?? '' })}
data={prestasiState.kategoriPrestasi.findMany.data?.map((v) => ({ value: v.id, label: v.name })) || []}
required
/>
<Box>
<Text fw="bold" fz="sm" mb={6}>
Gambar Prestasi
</Text>
<Text fw="bold" fz="sm" mb={6}>Gambar Prestasi</Text>
<Dropzone
onDrop={(files) => {
const selectedFile = files[0];
@@ -197,22 +145,12 @@ function EditPrestasiDesa() {
p="xl"
>
<Group justify="center" gap="xl" mih={180}>
<Dropzone.Accept>
<IconUpload size={48} color={colors['blue-button']} stroke={1.5} />
</Dropzone.Accept>
<Dropzone.Reject>
<IconX size={48} color="red" stroke={1.5} />
</Dropzone.Reject>
<Dropzone.Idle>
<IconPhoto size={48} color="#868e96" stroke={1.5} />
</Dropzone.Idle>
<Dropzone.Accept><IconUpload size={48} color={colors['blue-button']} stroke={1.5} /></Dropzone.Accept>
<Dropzone.Reject><IconX size={48} color="red" stroke={1.5} /></Dropzone.Reject>
<Dropzone.Idle><IconPhoto size={48} color="#868e96" stroke={1.5} /></Dropzone.Idle>
<Stack gap="xs" align="center">
<Text size="md" fw={500}>
Seret gambar atau klik untuk memilih file
</Text>
<Text size="sm" c="dimmed">
Maksimal 5MB, format gambar wajib
</Text>
<Text size="md" fw={500}>Seret gambar atau klik untuk memilih file</Text>
<Text size="sm" c="dimmed">Maksimal 5MB, format gambar wajib</Text>
</Stack>
</Group>
</Dropzone>
@@ -224,7 +162,7 @@ function EditPrestasiDesa() {
alt="Preview Gambar"
radius="md"
style={{ maxHeight: 220, objectFit: 'contain', border: `1px solid ${colors['blue-button']}` }}
loading='lazy'
loading="lazy"
/>
</Box>
)}
@@ -249,6 +187,3 @@ function EditPrestasiDesa() {
</Box>
);
}
export default EditPrestasiDesa;