/* eslint-disable @typescript-eslint/no-explicit-any */ import ApiFetch from "@/lib/api-fetch"; import type { Prisma } from "@prisma/client"; import { toast } from "react-toastify"; import { proxy } from "valtio"; import { z } from "zod"; const templateProgramInovasi = z.object({ name: z.string().min(1, "Nama minimal 1 karakter"), description: z.string().min(1, "Deskripsi minimal 1 karakter"), imageId: z.string().min(1, "Gambar wajib dipilih"), link: z.string().min(1, "Link minimal 1 karakter"), }); type ProgramInovasiForm = Prisma.ProgramInovasiGetPayload<{ select: { name: true; description: true; imageId: true; link: true; }; }>; const programInovasi = proxy({ create: { form: { name: "", description: "", imageId: "", link: "", } as ProgramInovasiForm, loading: false, async create() { // Ensure all required fields are non-null const formData = { name: programInovasi.create.form.name || "", description: programInovasi.create.form.description || "", imageId: programInovasi.create.form.imageId || "", link: programInovasi.create.form.link || "", }; const cek = templateProgramInovasi.safeParse(formData); if (!cek.success) { const err = `[${cek.error.issues .map((v) => `${v.path.join(".")}`) .join("\n")}] required`; return toast.error(err); } try { programInovasi.create.loading = true; const res = await ApiFetch.api.landingpage.programinovasi[ "create" ].post(formData); if (res.status === 200) { programInovasi.findMany.load(); return toast.success("Sukses menambahkan"); } if (process.env.NODE_ENV === 'development') { console.log(res); } return toast.error("failed create"); } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Create error:", error); } toast.error("Gagal menambahkan data"); } finally { programInovasi.create.loading = false; } }, }, findMany: { data: null as any[] | null, page: 1, totalPages: 1, total: 0, loading: false, search: "", load: async (page = 1, limit = 10, search = "") => { // Change to arrow function programInovasi.findMany.loading = true; // Use the full path to access the property programInovasi.findMany.page = page; programInovasi.findMany.search = search; try { const query: any = { page, limit }; if (search) query.search = search; const res = await ApiFetch.api.landingpage.programinovasi[ "findMany" ].get({ query, }); if (res.status === 200 && res.data?.success) { programInovasi.findMany.data = res.data.data || []; programInovasi.findMany.total = res.data.total || 0; programInovasi.findMany.totalPages = res.data.totalPages || 1; } else { if (process.env.NODE_ENV === 'development') { console.error("Failed to load pegawai:", res.data?.message); } programInovasi.findMany.data = []; programInovasi.findMany.total = 0; programInovasi.findMany.totalPages = 1; } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Error loading pegawai:", error); } programInovasi.findMany.data = []; programInovasi.findMany.total = 0; programInovasi.findMany.totalPages = 1; } finally { programInovasi.findMany.loading = false; } }, }, findUnique: { data: null as Prisma.ProgramInovasiGetPayload<{ include: { image: true; }; }> | null, loading: false, async load(id: string) { try { programInovasi.findUnique.loading = true; const res = await (ApiFetch.api.landingpage.programinovasi as any)[id].get(); if (res.data?.success) { programInovasi.findUnique.data = res.data.data ?? null; return res.data.data; } else { toast.error(res.data?.message || "Gagal memuat data program inovasi"); programInovasi.findUnique.data = null; return null; } } catch (error) { console.error("Error fetching program inovasi:", error); programInovasi.findUnique.data = null; return null; } finally { programInovasi.findUnique.loading = false; } }, }, delete: { loading: false, async byId(id: string) { if (!id) return toast.warn("ID tidak valid"); try { programInovasi.delete.loading = true; const res = await (ApiFetch.api.landingpage.programinovasi as any)["del"][id].delete(); if (res.data?.success) { toast.success(res.data.message || "Program inovasi berhasil dihapus"); await programInovasi.findMany.load(); } else { toast.error(res.data?.message || "Gagal menghapus program inovasi"); } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Gagal delete:", error); } toast.error("Terjadi kesalahan saat menghapus program inovasi"); } finally { programInovasi.delete.loading = false; } }, }, update: { id: "", form: {} as ProgramInovasiForm, loading: false, async load(id: string) { if (!id) { toast.warn("ID tidak valid"); return null; } try { programInovasi.update.loading = true; const res = await (ApiFetch.api.landingpage.programinovasi as any)[id].get(); if (res.data?.success) { const data = res.data.data; this.id = data.id; this.form = { name: data.name, description: data.description, imageId: data.imageId, link: data.link, }; return data; } else { toast.error(res.data?.message || "Gagal mengambil data program inovasi"); return null; } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Error loading program inovasi:", error); } toast.error("Terjadi kesalahan saat mengambil data program inovasi"); return null; } finally { programInovasi.update.loading = false; } }, async update() { const cek = templateProgramInovasi.safeParse(programInovasi.update.form); if (!cek.success) { const err = `[${cek.error.issues .map((v) => `${v.path.join(".")}`) .join("\n")}] required`; toast.error(err); return false; } try { programInovasi.update.loading = true; const res = await (ApiFetch.api.landingpage.programinovasi as any)[this.id].put({ name: this.form.name, description: this.form.description, imageId: this.form.imageId, link: this.form.link, }); if (res.data?.success) { toast.success("Berhasil update program inovasi"); await programInovasi.findMany.load(); return true; } else { toast.error(res.data?.message || "Gagal update program inovasi"); return false; } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Error updating program inovasi:", error); } toast.error( error instanceof Error ? error.message : "Terjadi kesalahan saat update program inovasi" ); return false; } finally { programInovasi.update.loading = false; } }, }, }); const templatePejabatDesa = z.object({ name: z.string().min(3, "Nama minimal 3 karakter"), position: z.string().min(3, "Posisi minimal 3 karakter"), imageId: z.string().min(1, "Gambar wajib dipilih"), }); const defaultFormPejabatDesa = { name: "", position: "", imageId: "", }; type PejabatDesaForm = { id: string; name: string; position: string; imageId: string | null; image?: { id: string; name: string; link: string; path: string; mimeType: string; realName: string; isActive: boolean; createdAt: Date; updatedAt: Date; deletedAt: Date | null; } | null; createdAt: Date; updatedAt: Date; deletedAt: Date | null; isActive: boolean; }; const pejabatDesa = proxy({ findUnique: { data: null as PejabatDesaForm | null, loading: false, error: null as string | null, async load(id: string) { if (!id) { toast.warn("ID tidak valid"); return null; } this.loading = true; this.error = null; try { const response = await fetch(`/api/landingpage/pejabatdesa/${id}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); if (result.success) { this.data = result.data; return result.data; } else { throw new Error( result.message || "Gagal mengambil data pejabat desa" ); } } catch (error) { const errorMessage = (error as Error).message; this.error = errorMessage; console.error("Load pejabat desa error:", errorMessage); toast.error("Terjadi kesalahan saat mengambil data pejabat desa"); return null; } finally { this.loading = false; } }, reset() { this.data = null; this.error = null; this.loading = false; }, }, edit: { id: "", form: { ...defaultFormPejabatDesa }, loading: false, error: null as string | null, isReadOnly: false, initialize(profileData: PejabatDesaForm) { this.id = profileData.id; this.isReadOnly = false; // Semua data bisa diedit this.form = { name: profileData.name || "", position: profileData.position || "", imageId: profileData.imageId || "", }; }, // Update form field updateField(field: keyof typeof defaultFormPejabatDesa, value: string) { this.form[field] = value; }, // Submit form async submit() { // Validate form const validation = templatePejabatDesa.safeParse(this.form); if (!validation.success) { const errors = validation.error.issues .map((issue) => `${issue.path.join(".")}: ${issue.message}`) .join(", "); toast.error(`Form tidak valid: ${errors}`); return false; } this.loading = true; this.error = null; try { // Ensure ID is properly encoded in the URL const url = new URL( `/api/landingpage/pejabatdesa/${encodeURIComponent(this.id)}`, window.location.origin ); const response = await fetch(url.toString(), { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify(this.form), }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error( errorData.message || `HTTP error! status: ${response.status}` ); } const result = await response.json(); if (result.success) { toast.success("Berhasil update profile"); // Refresh profile data await pejabatDesa.findUnique.load(this.id); return true; } else { throw new Error(result.message || "Gagal update profile"); } } catch (error) { const errorMessage = (error as Error).message; this.error = errorMessage; console.error("Update profile error:", errorMessage); toast.error("Terjadi kesalahan saat update profile"); return false; } finally { this.loading = false; } }, reset() { this.id = ""; this.form = { ...defaultFormPejabatDesa }; this.error = null; this.loading = false; this.isReadOnly = false; }, }, }); const templateMediaSosial = z.object({ name: z.string().min(3, "Nama minimal 3 karakter"), imageId: z.string().nullable().optional(), iconUrl: z.string().optional(), // ✅ Optional - tidak selalu required icon: z.string().nullable().optional(), }); type MediaSosialForm = { name: string; imageId: string | null; // boleh null iconUrl: string; icon: string | null; // boleh null }; const mediaSosial = proxy({ create: { form: {} as MediaSosialForm, loading: false, async create() { // Ensure all required fields are non-null const formData = { name: mediaSosial.create.form.name ?? "", imageId: mediaSosial.create.form.imageId ?? null, // FIXED iconUrl: mediaSosial.create.form.iconUrl ?? "", icon: mediaSosial.create.form.icon ?? null, // FIXED }; const cek = templateMediaSosial.safeParse(formData); if (!cek.success) { const err = `[${cek.error.issues .map((v) => `${v.path.join(".")}`) .join("\n")}] required`; return toast.error(err); } try { mediaSosial.create.loading = true; const res = await ApiFetch.api.landingpage.mediasosial["create"].post( formData ); if (res.status === 200) { mediaSosial.findMany.load(); return toast.success("Sukses menambahkan"); } if (process.env.NODE_ENV === 'development') { console.log(res); } return toast.error("failed create"); } catch (error) { if (process.env.NODE_ENV === 'development') { console.log((error as Error).message); } toast.error("Gagal menambahkan data"); } finally { mediaSosial.create.loading = false; } }, }, findMany: { data: null as any[] | null, page: 1, totalPages: 1, total: 0, loading: false, search: "", load: async (page = 1, limit = 10, search = "") => { // Change to arrow function mediaSosial.findMany.loading = true; // Use the full path to access the property mediaSosial.findMany.page = page; mediaSosial.findMany.search = search; try { const query: any = { page, limit }; if (search) query.search = search; const res = await ApiFetch.api.landingpage.mediasosial["findMany"].get({ query, }); if (res.status === 200 && res.data?.success) { mediaSosial.findMany.data = res.data.data || []; mediaSosial.findMany.total = res.data.total || 0; mediaSosial.findMany.totalPages = res.data.totalPages || 1; } else { if (process.env.NODE_ENV === 'development') { console.error("Failed to load media sosial:", res.data?.message); } mediaSosial.findMany.data = []; mediaSosial.findMany.total = 0; mediaSosial.findMany.totalPages = 1; } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Error loading media sosial:", error); } mediaSosial.findMany.data = []; mediaSosial.findMany.total = 0; mediaSosial.findMany.totalPages = 1; } finally { mediaSosial.findMany.loading = false; } }, }, findUnique: { data: null as Prisma.MediaSosialGetPayload<{ include: { image: true; }; }> | null, loading: false, async load(id: string) { if (!id) { toast.warn("ID tidak valid"); return null; } mediaSosial.findUnique.loading = true; try { const res = await (ApiFetch.api.landingpage.mediasosial as any)[id].get(); if (res.data?.success) { mediaSosial.findUnique.data = res.data.data ?? null; return res.data.data; } else { toast.error(res.data?.message || "Gagal memuat data media sosial"); mediaSosial.findUnique.data = null; return null; } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Error fetching media sosial:", error); } mediaSosial.findUnique.data = null; return null; } finally { mediaSosial.findUnique.loading = false; } }, }, delete: { loading: false, async byId(id: string) { if (!id) return toast.warn("ID tidak valid"); try { mediaSosial.delete.loading = true; const res = await (ApiFetch.api.landingpage.mediasosial as any)["del"][id].delete(); if (res.data?.success) { toast.success(res.data.message || "Media Sosial berhasil dihapus"); await mediaSosial.findMany.load(); } else { toast.error(res.data?.message || "Gagal menghapus media sosial"); } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Gagal delete:", error); } toast.error("Terjadi kesalahan saat menghapus media sosial"); } finally { mediaSosial.delete.loading = false; } }, }, update: { id: "", form: {} as MediaSosialForm, loading: false, async load(id: string) { if (!id) { toast.warn("ID tidak valid"); return null; } mediaSosial.update.loading = true; try { const res = await (ApiFetch.api.landingpage.mediasosial as any)[id].get(); if (res.data?.success) { const data = res.data.data; this.id = data.id; this.form = { name: data.name || "", imageId: data.imageId || null, iconUrl: data.iconUrl || "", icon: data.icon || null, }; return data; } else { toast.error(res.data?.message || "Gagal mengambil data media sosial"); return null; } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Error loading media sosial:", error); } toast.error("Terjadi kesalahan saat mengambil data media sosial"); return null; } finally { mediaSosial.update.loading = false; } }, async update() { const cek = templateMediaSosial.safeParse(mediaSosial.update.form); if (!cek.success) { const err = `[${cek.error.issues .map((v) => `${v.path.join(".")}`) .join("\n")}] required`; toast.error(err); return false; } try { mediaSosial.update.loading = true; const res = await (ApiFetch.api.landingpage.mediasosial as any)[this.id].put({ name: this.form.name, imageId: this.form.imageId, iconUrl: this.form.iconUrl, icon: this.form.icon, }); if (res.data?.success) { toast.success("Berhasil update media sosial"); await mediaSosial.findMany.load(); return true; } else { toast.error(res.data?.message || "Gagal update media sosial"); return false; } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error("Error updating media sosial:", error); } toast.error( error instanceof Error ? error.message : "Terjadi kesalahan saat update media sosial" ); return false; } finally { mediaSosial.update.loading = false; } }, }, }); const profileLandingPageState = proxy({ programInovasi, pejabatDesa, mediaSosial, }); export default profileLandingPageState;