diff --git a/src/app/admin/(dashboard)/landing-page/profile/pejabat-desa/[id]/page.tsx b/src/app/admin/(dashboard)/landing-page/profile/pejabat-desa/[id]/page.tsx new file mode 100644 index 00000000..f2ddf10b --- /dev/null +++ b/src/app/admin/(dashboard)/landing-page/profile/pejabat-desa/[id]/page.tsx @@ -0,0 +1,270 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +'use client' +import colors from '@/con/colors'; +import { Alert, Box, Button, Center, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +import profileLandingPageState from '@/app/admin/(dashboard)/_state/landing-page/profile'; +import ApiFetch from '@/lib/api-fetch'; +import { Dropzone } from '@mantine/dropzone'; +import { IconAlertCircle, IconArrowBack, IconImageInPicture, IconPhoto, IconUpload, IconX } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { toast } from 'react-toastify'; + +function EditPejabatDesa() { + const allState = useProxy(profileLandingPageState.pejabatDesa); + const params = useParams(); + const router = useRouter(); + + // UI States + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + const [isSubmitting, setIsSubmitting] = useState(false); + + // Load data on mount + useEffect(() => { + const loadData = async () => { + const id = params?.id as string; + if (!id) { + toast.error("ID tidak valid"); + router.push("/admin/landing-page/profile/pejabat-desa"); + return; + } + + try { + const profileData = await profileLandingPageState.pejabatDesa.findUnique.load(id); + profileLandingPageState.pejabatDesa.edit.initialize(profileData); + + + if (profileData && profileData.image?.link) { + setPreviewImage(profileData.image.link); + } + } catch (error) { + console.error("Error loading profile:", error); + toast.error("Gagal memuat data profile"); + } + }; + + loadData(); + + return () => { + profileLandingPageState.pejabatDesa.edit.reset(); // cleanup form + }; + }, [params?.id, router]); + + const handleFieldChange = (field: string, value: string) => { + profileLandingPageState.pejabatDesa.edit.updateField(field as any, value); + }; + + const handleFileChange = (newFile: File | null) => { + if (!newFile) { + setFile(null); + return; + } + + setFile(newFile); + + const reader = new FileReader(); + reader.onload = (event) => { + setPreviewImage(event.target?.result as string); + }; + reader.readAsDataURL(newFile); + }; + + const handleSubmit = async () => { + if (isSubmitting || !profileLandingPageState.pejabatDesa.edit.form.name.trim()) { + toast.error("Nama wajib diisi"); + return; + } + + setIsSubmitting(true); + + try { + // Upload file jika ada + if (file) { + const uploadResponse = await ApiFetch.api.fileStorage.create.post({ file, name: file.name }); + const uploaded = uploadResponse.data?.data; + + if (!uploaded?.id) { + toast.error("Gagal upload gambar"); + return; + } + + profileLandingPageState.pejabatDesa.edit.form.imageId = uploaded.id; + } + + // Submit form + const success = await profileLandingPageState.pejabatDesa.edit.submit(); + + if (success) { + toast.success("Berhasil menyimpan perubahan"); + router.push("/admin/landing-page/profile/pejabat-desa"); + } + } catch (error) { + console.error("Error submitting form:", error); + toast.error("Gagal menyimpan profile"); + } finally { + setIsSubmitting(false); + } + }; + + const handleBack = () => { + router.back(); + }; + + // Loading state + if (allState.edit.loading) { + return ( + +
+ Memuat data profile... +
+
+ ); + } + + // Error state + if (allState.edit.error) { + return ( + + + + } color="red"> + Error + {allState.edit.error} + + + + ); + } + + return ( + + + + + + + + + + Edit Profile Pejabat Desa + + {/* Nama Field */} + Nama Perbekel} + placeholder="Masukkan nama perbekel" + value={allState.edit.form.name} + onChange={(e) => handleFieldChange('name', e.currentTarget.value)} + error={!allState.edit.form.name && "Nama wajib diisi"} + /> + + {/* Posisi Field */} + Posisi} + placeholder="Masukkan posisi" + value={allState.edit.form.position} + onChange={(e) => handleFieldChange('position', e.currentTarget.value)} + error={!allState.edit.form.position && "Posisi wajib diisi"} + /> + + {/* File Upload */} + + Gambar + + handleFileChange(files[0])} + onReject={() => toast.error('File tidak valid.')} + maxSize={5 * 1024 ** 2} // Maks 5MB + accept={{ 'image/*': [] }} + > + + + + + + + + + + + +
+ + Drag gambar ke sini atau klik untuk pilih file + + + Maksimal 5MB dan harus format gambar + +
+
+
+ + {/* Tampilkan preview kalau ada */} + {previewImage && ( + + Preview + + )} + +
+
+ + {/* Preview Gambar */} + + Preview Gambar + {previewImage ? ( + Profile preview + ) : ( +
+ + + Tidak ada gambar + +
+ )} +
+ + {/* Submit Button */} + + + + + +
+
+
+
+
+ ); +} + +export default EditPejabatDesa; \ No newline at end of file diff --git a/src/app/admin/(dashboard)/landing-page/profile/pejabat-desa/page.tsx b/src/app/admin/(dashboard)/landing-page/profile/pejabat-desa/page.tsx index 69da2f21..38618fa7 100644 --- a/src/app/admin/(dashboard)/landing-page/profile/pejabat-desa/page.tsx +++ b/src/app/admin/(dashboard)/landing-page/profile/pejabat-desa/page.tsx @@ -1,11 +1,104 @@ -import React from 'react'; +'use client' +import colors from '@/con/colors'; +import { Box, Button, Center, Divider, Grid, GridCol, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconEdit } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import profileLandingPageState from '@/app/admin/(dashboard)/_state/landing-page/profile'; + function Page() { + const router = useRouter() + const allList = useProxy(profileLandingPageState.pejabatDesa) + useShallowEffect(() => { + allList.findUnique.load("edit") // Assuming "1" is your default ID, adjust as needed + }, []) + + if (!allList.findUnique.data) { + return + + + } + + const dataArray = Array.isArray(allList.findUnique.data) + ? allList.findUnique.data + : [allList.findUnique.data]; + return ( -
- Page -
- ); + + + + + Preview Pejabat Desa + + + + + + {dataArray.map((item) => ( + + + + + +
+ +
+
+ + PROFIL PIMPINAN BADAN PUBLIK DESA DARMASABA + +
+
+ + {/* biodata perbekel */} + + + + +
+ Foto Profil PPID { + e.currentTarget.src = "/perbekel.png"; + }} + /> +
+ + + {item.name} + + +
+
+
+ + + Position + {item.position} + + +
+
+
+ ))} +
+
+ ) } -export default Page; + + +export default Page; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/landing_page/profile/pejabat-desa/findUnique.ts b/src/app/api/[[...slugs]]/_lib/landing_page/profile/pejabat-desa/findUnique.ts index c2854a6a..65f69950 100644 --- a/src/app/api/[[...slugs]]/_lib/landing_page/profile/pejabat-desa/findUnique.ts +++ b/src/app/api/[[...slugs]]/_lib/landing_page/profile/pejabat-desa/findUnique.ts @@ -1,23 +1,9 @@ import prisma from "@/lib/prisma"; -import { Prisma } from "@prisma/client"; import { Context } from "elysia"; -import fs from "fs/promises"; -import path from "path"; -type FormUpdate = Prisma.PejabatDesaGetPayload<{ - select: { - id: true; - name: true; - position: true; - imageId: true; - }; -}>; export default async function pejabatDesaFindUnique(context: Context) { try { const id = context.params?.id as string; - const body = (await context.body) as Omit; - - const { name, position, imageId } = body; if (!id) { return new Response( @@ -35,12 +21,8 @@ export default async function pejabatDesaFindUnique(context: Context) { } const existing = await prisma.pejabatDesa.findUnique({ - where: { - id, - }, - include: { - image: true, - }, + where: { id }, + include: { image: true }, }); if (!existing) { @@ -58,37 +40,11 @@ export default async function pejabatDesaFindUnique(context: Context) { ); } - if (existing.imageId !== imageId) { - const oldImage = existing.image; - if (oldImage) { - try { - const filePath = path.join(oldImage.path, oldImage.name); - await fs.unlink(filePath); - await prisma.fileStorage.delete({ - where: { id: oldImage.id }, - }); - } catch (error) { - console.error("Gagal hapus gambar lama:", error); - } - } - } - - const updated = await prisma.pejabatDesa.update({ - where: { - id, - }, - data: { - name, - position, - imageId, - }, - }); - return new Response( JSON.stringify({ success: true, message: "Data pejabat desa berhasil ditemukan", - data: updated, + data: existing, }), { status: 200, @@ -98,11 +54,11 @@ export default async function pejabatDesaFindUnique(context: Context) { } ); } catch (error) { - console.error("Error updating pejabat desa:", error); + console.error("Error fetching pejabat desa:", error); return new Response( JSON.stringify({ success: false, - message: "Terjadi kesalahan saat mengupdate pejabat desa", + message: "Terjadi kesalahan saat mengambil data pejabat desa", }), { status: 500,