diff --git a/src/app/admin/(dashboard)/_state/desa/berita.ts b/src/app/admin/(dashboard)/_state/desa/berita.ts
index 56b4fb01..b314fcd4 100644
--- a/src/app/admin/(dashboard)/_state/desa/berita.ts
+++ b/src/app/admin/(dashboard)/_state/desa/berita.ts
@@ -80,13 +80,33 @@ const berita = proxy({
};
}>[]
| null,
- async load() {
- const res = await ApiFetch.api.desa.berita["find-many"].get();
- if (res.status === 200) {
- berita.findMany.data = (res.data?.data ) ?? [];
+ page: 1,
+ totalPages: 1,
+ loading: false,
+
+ async load(page = 1, limit = 10) {
+ berita.findMany.loading = true;
+ berita.findMany.page = page;
+ try {
+ const res = await ApiFetch.api.desa.berita["find-many"].get({
+ query: {
+ page,
+ limit,
+ },
+ });
+
+ if (res.status === 200 && res.data?.success) {
+ berita.findMany.data = res.data.data ?? [];
+ berita.findMany.totalPages = res.data.totalPages ?? 1;
+ }
+ } catch (err) {
+ console.error("Gagal fetch berita paginated:", err);
+ } finally {
+ berita.findMany.loading = false;
}
},
},
+
findUnique: {
data: null as
| Prisma.BeritaGetPayload<{
diff --git a/src/app/admin/(dashboard)/_state/ekonomi/struktur-organisasi/struktur-organisasi.ts b/src/app/admin/(dashboard)/_state/ekonomi/struktur-organisasi/struktur-organisasi.ts
index cacc801e..7819facb 100644
--- a/src/app/admin/(dashboard)/_state/ekonomi/struktur-organisasi/struktur-organisasi.ts
+++ b/src/app/admin/(dashboard)/_state/ekonomi/struktur-organisasi/struktur-organisasi.ts
@@ -30,9 +30,9 @@ const posisiOrganisasi = proxy({
try {
this.loading = true;
- const res = await ApiFetch.api.ekonomi["struktur-organisasi"]["posisi-organisasi"]["create"].post(
- this.form
- );
+ const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
+ "posisi-organisasi"
+ ]["create"].post(this.form);
if (res.status === 200) {
toast.success("Berhasil menambahkan posisi organisasi");
posisiOrganisasi.findMany.load();
@@ -62,12 +62,15 @@ const posisiOrganisasi = proxy({
return null;
}
try {
- const response = await fetch(`/api/ekonomi/struktur-organisasi/posisi-organisasi/${id}`, {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- },
- });
+ const response = await fetch(
+ `/api/ekonomi/struktur-organisasi/posisi-organisasi/${id}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
@@ -160,7 +163,9 @@ const posisiOrganisasi = proxy({
}>,
async load() {
try {
- const res = await ApiFetch.api.ekonomi["struktur-organisasi"]["posisi-organisasi"]["find-many"].get();
+ const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
+ "posisi-organisasi"
+ ]["find-many"].get();
if (res.status === 200) {
// The API now returns the id field, so we can use it directly
this.data = res.data?.data ?? [];
@@ -209,238 +214,278 @@ const posisiOrganisasi = proxy({
});
const templatePegawai = z.object({
- namaLengkap: z.string().min(1, "Nama wajib diisi"),
- gelarAkademik: z.string().optional(),
- imageId: z.string().nullable().optional(),
- tanggalMasuk: z.string().optional(), // ISO format
- email: z.string().email("Email tidak valid").optional(),
- telepon: z.string().optional(),
- alamat: z.string().optional(),
- posisiId: z.string().min(1, "Posisi wajib diisi"),
- isActive: z.boolean().default(true),
- });
-
- const pegawaiDefaultForm = {
- namaLengkap: "",
- gelarAkademik: "",
- imageId: "",
- tanggalMasuk: "",
- email: "",
- telepon: "",
- alamat: "",
- posisiId: "",
- isActive: true,
- };
-
- const pegawai = proxy({
- create: {
- form: { ...pegawaiDefaultForm },
- loading: false,
- async submit() {
- const cek = templatePegawai.safeParse(pegawai.create.form);
- if (!cek.success) {
- const err = cek.error.issues.map(i => i.message).join("\n");
- toast.error(err);
- return;
- }
-
- try {
- pegawai.create.loading = true;
- const res = await ApiFetch.api.ekonomi["struktur-organisasi"]["pegawai"]["create"].post(
- pegawai.create.form
- );
- if (res.status === 200) {
- toast.success("Pegawai berhasil ditambahkan");
- await pegawai.findMany.load();
- } else {
- toast.error(res.data?.message ?? "Gagal tambah pegawai");
- }
- } catch (error) {
- console.error("Gagal create:", error);
- toast.error("Terjadi kesalahan saat menambahkan pegawai");
- } finally {
- pegawai.create.loading = false;
- }
- },
- },
- findMany: {
- data: null as (Prisma.PegawaiGetPayload<{ include: { posisi: true, image: true } }> & { isActive: boolean })[] | null,
- async load() {
- try {
- const res = await ApiFetch.api.ekonomi["struktur-organisasi"]["pegawai"]["find-many"].get();
- if (res.status === 200) {
- pegawai.findMany.data = (res.data?.data ?? []).map((item: any) => ({
- ...item,
- posisi: item.posisi || { id: '', nama: '' }, // Ensure posisi exists with required fields
- isActive: item.isActive ?? true // Default to true if not provided
- }));
- } else {
- console.error('Failed to load pegawai:', res.data?.message);
- }
- } catch (error) {
- console.error('Error loading pegawai:', error);
- pegawai.findMany.data = [];
- }
- },
- },
- findUnique: {
- data: null as (Prisma.PegawaiGetPayload<{ include: { posisi: true, image: true } }> & { isActive: boolean }) | null,
- async load(id: string) {
- const res = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/${id}`);
- if (res.ok) {
- const json = await res.json();
- pegawai.findUnique.data = json.data ? {
- ...json.data,
- isActive: json.data.isActive ?? json.data.aktif ?? true // Fallback ke aktif:true jika tidak ada data
- } : null;
- } else {
- pegawai.findUnique.data = null;
- }
- },
- },
-
- delete: {
- loading: false,
- async byId(id: string) {
- if (!id) return toast.warn("ID tidak valid");
- try {
- pegawai.delete.loading = true;
- const res = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/del/${id}`, {
- method: "DELETE",
- });
- const json = await res.json();
- if (res.ok) {
- toast.success(json.message ?? "Berhasil hapus pegawai");
- await pegawai.findMany.load();
- } else {
- toast.error(json.message ?? "Gagal hapus pegawai");
- }
- } catch (error) {
- console.error("Gagal delete:", error);
- toast.error("Terjadi kesalahan saat menghapus");
- } finally {
- pegawai.delete.loading = false;
- }
- },
- },
-
- edit: {
- id: "",
- form: { ...pegawaiDefaultForm },
- loading: false,
-
- async load(id: string) {
- if (!id) {
- toast.warn("ID tidak valid");
- return null;
- }
-
- try {
- const response = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/${id}`, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- },
- });
-
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
-
- const result = await response.json();
-
- if (result?.success) {
- const data = result.data;
- this.id = data.id;
- this.form = {
- namaLengkap: data.namaLengkap,
- gelarAkademik: data.gelarAkademik,
- imageId: data.imageId,
- tanggalMasuk: data.tanggalMasuk,
- email: data.email,
- telepon: data.telepon,
- alamat: data.alamat,
- posisiId: data.posisiId,
- isActive: data.isActive,
- };
- return data; // Return the loaded data
- } else {
- throw new Error(result?.message || "Gagal memuat data");
- }
- } catch (error) {
- console.error("Error loading berita:", error);
- toast.error(error instanceof Error ? error.message : "Gagal memuat data");
- return null;
- }
- },
-
- async submit() {
- const cek = templatePegawai.safeParse(pegawai.edit.form);
- if (!cek.success) {
- const err = `[${cek.error.issues
- .map((v) => `${v.path.join(".")}`)
- .join("\n")}] required`;
- toast.error(err);
- return false;
- }
-
- try {
- pegawai.edit.loading = true;
-
- // Format tanggalMasuk to ISO string if it exists
- const formattedTanggalMasuk = this.form.tanggalMasuk
- ? new Date(this.form.tanggalMasuk).toISOString()
- : undefined;
-
- const response = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/${this.id}`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- id: this.id,
- namaLengkap: this.form.namaLengkap,
- gelarAkademik: this.form.gelarAkademik,
- imageId: this.form.imageId || null,
- tanggalMasuk: formattedTanggalMasuk,
- email: this.form.email,
- telepon: this.form.telepon,
- alamat: this.form.alamat,
- posisiId: this.form.posisiId,
- isActive: this.form.isActive,
- }),
- });
-
- 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 pegawai");
- await pegawai.findMany.load(); // refresh list
- return true;
- } else {
- throw new Error(result.message || "Gagal update pegawai");
- }
- } catch (error) {
- console.error("Error updating pegawai:", error);
- toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat update pegawai");
- return false;
- } finally {
- pegawai.edit.loading = false;
- }
- },
-
- reset() {
- pegawai.edit.id = "";
- pegawai.edit.form = { ...pegawaiDefaultForm };
- },
- },
- });
+ namaLengkap: z.string().min(1, "Nama wajib diisi"),
+ gelarAkademik: z.string().optional(),
+ imageId: z.string().nullable().optional(),
+ tanggalMasuk: z.string().optional(), // ISO format
+ email: z.string().email("Email tidak valid").optional(),
+ telepon: z.string().optional(),
+ alamat: z.string().optional(),
+ posisiId: z.string().min(1, "Posisi wajib diisi"),
+ isActive: z.boolean().default(true),
+});
+const pegawaiDefaultForm = {
+ namaLengkap: "",
+ gelarAkademik: "",
+ imageId: "",
+ tanggalMasuk: "",
+ email: "",
+ telepon: "",
+ alamat: "",
+ posisiId: "",
+ isActive: true,
+};
+
+const pegawai = proxy({
+ create: {
+ form: { ...pegawaiDefaultForm },
+ loading: false,
+ async submit() {
+ const cek = templatePegawai.safeParse(pegawai.create.form);
+ if (!cek.success) {
+ const err = cek.error.issues.map((i) => i.message).join("\n");
+ toast.error(err);
+ return;
+ }
+
+ try {
+ pegawai.create.loading = true;
+ const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
+ "pegawai"
+ ]["create"].post(pegawai.create.form);
+ if (res.status === 200) {
+ toast.success("Pegawai berhasil ditambahkan");
+ await pegawai.findMany.load();
+ } else {
+ toast.error(res.data?.message ?? "Gagal tambah pegawai");
+ }
+ } catch (error) {
+ console.error("Gagal create:", error);
+ toast.error("Terjadi kesalahan saat menambahkan pegawai");
+ } finally {
+ pegawai.create.loading = false;
+ }
+ },
+ },
+
+ // In struktur-organisasi.ts
+findMany: {
+ data: null as any[] | null,
+ page: 1,
+ totalPages: 1,
+ total: 0,
+ loading: false,
+ load: async (page = 1, limit = 10) => { // Change to arrow function
+ pegawai.findMany.loading = true; // Use the full path to access the property
+ pegawai.findMany.page = page;
+ try {
+ const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
+ "pegawai"
+ ]["find-many"].get({
+ query: { page, limit },
+ });
+
+ if (res.status === 200 && res.data?.success) {
+ pegawai.findMany.data = res.data.data || [];
+ pegawai.findMany.total = res.data.total || 0;
+ pegawai.findMany.totalPages = res.data.totalPages || 1;
+ } else {
+ console.error("Failed to load pegawai:", res.data?.message);
+ pegawai.findMany.data = [];
+ pegawai.findMany.total = 0;
+ pegawai.findMany.totalPages = 1;
+ }
+ } catch (error) {
+ console.error("Error loading pegawai:", error);
+ pegawai.findMany.data = [];
+ pegawai.findMany.total = 0;
+ pegawai.findMany.totalPages = 1;
+ } finally {
+ pegawai.findMany.loading = false;
+ }
+ },
+},
+ findUnique: {
+ data: null as
+ | (Prisma.PegawaiGetPayload<{
+ include: { posisi: true; image: true };
+ }> & { isActive: boolean })
+ | null,
+ async load(id: string) {
+ const res = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/${id}`);
+ if (res.ok) {
+ const json = await res.json();
+ pegawai.findUnique.data = json.data
+ ? {
+ ...json.data,
+ isActive: json.data.isActive ?? json.data.aktif ?? true, // Fallback ke aktif:true jika tidak ada data
+ }
+ : null;
+ } else {
+ pegawai.findUnique.data = null;
+ }
+ },
+ },
+
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+ try {
+ pegawai.delete.loading = true;
+ const res = await fetch(
+ `/api/ekonomi/struktur-organisasi/pegawai/del/${id}`,
+ {
+ method: "DELETE",
+ }
+ );
+ const json = await res.json();
+ if (res.ok) {
+ toast.success(json.message ?? "Berhasil hapus pegawai");
+ await pegawai.findMany.load();
+ } else {
+ toast.error(json.message ?? "Gagal hapus pegawai");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus");
+ } finally {
+ pegawai.delete.loading = false;
+ }
+ },
+ },
+
+ edit: {
+ id: "",
+ form: { ...pegawaiDefaultForm },
+ loading: false,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ try {
+ const response = await fetch(
+ `/api/ekonomi/struktur-organisasi/pegawai/${id}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ const result = await response.json();
+
+ if (result?.success) {
+ const data = result.data;
+ this.id = data.id;
+ this.form = {
+ namaLengkap: data.namaLengkap,
+ gelarAkademik: data.gelarAkademik,
+ imageId: data.imageId,
+ tanggalMasuk: data.tanggalMasuk,
+ email: data.email,
+ telepon: data.telepon,
+ alamat: data.alamat,
+ posisiId: data.posisiId,
+ isActive: data.isActive,
+ };
+ return data; // Return the loaded data
+ } else {
+ throw new Error(result?.message || "Gagal memuat data");
+ }
+ } catch (error) {
+ console.error("Error loading berita:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+
+ async submit() {
+ const cek = templatePegawai.safeParse(pegawai.edit.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ toast.error(err);
+ return false;
+ }
+
+ try {
+ pegawai.edit.loading = true;
+
+ // Format tanggalMasuk to ISO string if it exists
+ const formattedTanggalMasuk = this.form.tanggalMasuk
+ ? new Date(this.form.tanggalMasuk).toISOString()
+ : undefined;
+
+ const response = await fetch(
+ `/api/ekonomi/struktur-organisasi/pegawai/${this.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ id: this.id,
+ namaLengkap: this.form.namaLengkap,
+ gelarAkademik: this.form.gelarAkademik,
+ imageId: this.form.imageId || null,
+ tanggalMasuk: formattedTanggalMasuk,
+ email: this.form.email,
+ telepon: this.form.telepon,
+ alamat: this.form.alamat,
+ posisiId: this.form.posisiId,
+ isActive: this.form.isActive,
+ }),
+ }
+ );
+
+ 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 pegawai");
+ await pegawai.findMany.load(); // refresh list
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal update pegawai");
+ }
+ } catch (error) {
+ console.error("Error updating pegawai:", error);
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : "Terjadi kesalahan saat update pegawai"
+ );
+ return false;
+ } finally {
+ pegawai.edit.loading = false;
+ }
+ },
+
+ reset() {
+ pegawai.edit.id = "";
+ pegawai.edit.form = { ...pegawaiDefaultForm };
+ },
+ },
+});
// Schema Zod untuk form validasi
const templateHubunganOrganisasiForm = z.object({
@@ -474,7 +519,9 @@ const hubunganOrganisasi = proxy({
try {
hubunganOrganisasi.create.loading = true;
- const res = await ApiFetch.api.ekonomi["struktur-organisasi"]["hubungan-organisasi"]["create"].post(hubunganOrganisasi.create.form);
+ const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
+ "hubungan-organisasi"
+ ]["create"].post(hubunganOrganisasi.create.form);
if (res.status === 200 && res.data?.success) {
hubunganOrganisasi.findMany.load();
@@ -482,7 +529,7 @@ const hubunganOrganisasi = proxy({
} else {
return toast.error(res.data?.message || "Gagal menambahkan data");
}
- } catch (error) {
+ } catch (error) {
console.error("Gagal create:", error);
toast.error("Terjadi kesalahan saat menambahkan");
} finally {
@@ -490,7 +537,7 @@ const hubunganOrganisasi = proxy({
}
},
},
- findMany: {
+ findMany: {
data: null as Array<{
id: string;
atasanId: string;
@@ -528,20 +575,29 @@ const hubunganOrganisasi = proxy({
async load() {
try {
- const res = await ApiFetch.api.ekonomi["struktur-organisasi"]["hubungan-organisasi"]["find-many"].get();
+ const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
+ "hubungan-organisasi"
+ ]["find-many"].get();
if (res.status === 200) {
- hubunganOrganisasi.findMany.data = (res.data?.data ?? []).map((item: any) => ({
- ...item,
- atasan: item.atasan ? {
- ...item.atasan,
- isActive: item.atasan.isActive ?? item.atasan.aktif ?? true
- } : null,
- bawahan: item.bawahan ? {
- ...item.bawahan,
- isActive: item.bawahan.isActive ?? item.bawahan.aktif ?? true
- } : null
- }));
+ hubunganOrganisasi.findMany.data = (res.data?.data ?? []).map(
+ (item: any) => ({
+ ...item,
+ atasan: item.atasan
+ ? {
+ ...item.atasan,
+ isActive: item.atasan.isActive ?? item.atasan.aktif ?? true,
+ }
+ : null,
+ bawahan: item.bawahan
+ ? {
+ ...item.bawahan,
+ isActive:
+ item.bawahan.isActive ?? item.bawahan.aktif ?? true,
+ }
+ : null,
+ })
+ );
} else {
hubunganOrganisasi.findMany.data = [];
}
@@ -591,7 +647,9 @@ const hubunganOrganisasi = proxy({
async load(id: string) {
try {
- const res = await fetch(`/api/ekonomi/struktur-organisasi/hubungan-organisasi/${id}`);
+ const res = await fetch(
+ `/api/ekonomi/struktur-organisasi/hubungan-organisasi/${id}`
+ );
const result = await res.json();
if (res.ok && result?.success) {
@@ -616,7 +674,9 @@ const hubunganOrganisasi = proxy({
if (!id) return toast.warn("ID tidak valid");
try {
- const res = await fetch(`/api/ekonomi/struktur-organisasi/hubungan-organisasi/${id}`);
+ const res = await fetch(
+ `/api/ekonomi/struktur-organisasi/hubungan-organisasi/${id}`
+ );
const result = await res.json();
if (res.ok && result?.success) {
@@ -633,7 +693,9 @@ const hubunganOrganisasi = proxy({
}
} catch (error) {
console.error("Error loading:", error);
- toast.error(error instanceof Error ? error.message : "Gagal memuat data");
+ toast.error(
+ error instanceof Error ? error.message : "Gagal memuat data"
+ );
return null;
}
},
@@ -690,9 +752,12 @@ const hubunganOrganisasi = proxy({
try {
hubunganOrganisasi.delete.loading = true;
- const res = await fetch(`/api/ekonomi/struktur-organisasi/hubungan-organisasi/del/${id}`, {
- method: "DELETE",
- });
+ const res = await fetch(
+ `/api/ekonomi/struktur-organisasi/hubungan-organisasi/del/${id}`,
+ {
+ method: "DELETE",
+ }
+ );
const result = await res.json();
if (res.ok && result?.success) {
diff --git a/src/app/admin/(dashboard)/desa/berita/page.tsx b/src/app/admin/(dashboard)/desa/berita/page.tsx
index e0cff5d4..7ba706f9 100644
--- a/src/app/admin/(dashboard)/desa/berita/page.tsx
+++ b/src/app/admin/(dashboard)/desa/berita/page.tsx
@@ -1,6 +1,6 @@
'use client'
import colors from '@/con/colors';
-import { Box, Button, Grid, GridCol, Image, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
+import { Box, Button, Grid, GridCol, Image, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -29,12 +29,21 @@ function Berita() {
function ListBerita({ search }: { search: string }) {
const beritaState = useProxy(stateDashboardBerita)
const router = useRouter()
+ const {
+ data,
+ page,
+ totalPages,
+ loading,
+ load,
+ } = beritaState.berita.findMany;
+
+ // Fetch pertama kali
useShallowEffect(() => {
- beritaState.berita.findMany.load()
- }, [])
+ load(page); // awal page = 1
+ }, []);
- const filteredData = (beritaState.berita.findMany.data || []).filter(item => {
+ const filteredData = (data || []).filter((item) => {
const keyword = search.toLowerCase();
return (
item.judul.toLowerCase().includes(keyword) ||
@@ -42,67 +51,84 @@ function ListBerita({ search }: { search: string }) {
);
});
-
- if (!beritaState.berita.findMany.data) {
- return (
-
-
-
- )
+ if (loading || !data) {
+ return ;
}
return (
-
+ load(newPage)} // ini penting!
+ total={totalPages}
+ mt="md"
+ mb="md"
+ />
+
+
- List Berita
+
+ List Berita
+
-
-
+
Judul
Kategori
Image
Detail
-
-
+
{filteredData.map((item) => (
-
+
- {item.judul}
+
+ {item.judul}
+
- {item.kategoriBerita?.name}
+ {item.kategoriBerita?.name}
- router.push(`/admin/desa/berita/${item.id}`)}>
+
+ router.push(`/admin/desa/berita/${item.id}`)
+ }
+ >
-
))}
-
+
+
-
- )
+ );
}
-
export default Berita;
diff --git a/src/app/admin/(dashboard)/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/pegawai/page.tsx b/src/app/admin/(dashboard)/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/pegawai/page.tsx
index fe7f3864..f1d69d6e 100644
--- a/src/app/admin/(dashboard)/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/pegawai/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/pegawai/page.tsx
@@ -1,10 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
-import { Badge, Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
-import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+import { Badge, Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, ThemeIcon } from '@mantine/core';
+import { IconCheck, IconDeviceImacCog, IconSearch, IconX } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
-import { useEffect, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../../_com/header';
import JudulList from '../../../_com/judulList';
@@ -30,46 +30,33 @@ function ListPegawai({ search }: { search: string }) {
const stateOrganisasi = useProxy(strukturorganisasiState.pegawai);
const router = useRouter();
+ const {
+ data,
+ page,
+ totalPages,
+ loading,
+ load,
+ } = stateOrganisasi.findMany;
+
useEffect(() => {
- const loadData = async () => {
- try {
- // Clear existing data to ensure we see the loading state
- stateOrganisasi.findMany.data = [];
+ load(page, 10);
+ }, [page]);
- // Load new data
- await stateOrganisasi.findMany.load();
-
- // Type guard to ensure data is an array
- const data = stateOrganisasi.findMany.data || [];
- if (data.length > 0) {
- console.log('4. First record sample:', data[0]);
- }
- } catch (error) {
- console.error('Error loading pegawai data:', error);
- stateOrganisasi.findMany.data = [];
- }
- };
-
- loadData();
-
- // Cleanup function
- return () => {
- console.log('Cleanup: Unmounting component');
- };
- }, []);
-
- const filteredData = (stateOrganisasi.findMany.data || []).filter(item => {
- const keyword = search.toLowerCase();
- return (
- item.namaLengkap?.toLowerCase().includes(keyword) ||
- item.gelarAkademik?.toLowerCase().includes(keyword) ||
- item.telepon?.toLowerCase().includes(keyword) ||
- item.posisi?.nama?.toLowerCase().includes(keyword)
- );
- });
+ const filteredData = useMemo(() => {
+ if (!data) return [];
+ return data.filter(item => {
+ const keyword = search.toLowerCase();
+ return (
+ item.namaLengkap?.toLowerCase().includes(keyword) ||
+ item.gelarAkademik?.toLowerCase().includes(keyword) ||
+ item.telepon?.toLowerCase().includes(keyword) ||
+ item.posisi?.nama?.toLowerCase().includes(keyword)
+ );
+ });
+ }, [data, search]);
// Handle loading state
- if (stateOrganisasi.findMany.data === null) {
+ if (loading || !data) {
return (
@@ -77,8 +64,6 @@ function ListPegawai({ search }: { search: string }) {
);
}
- // Check if data is an empty array
- const data = stateOrganisasi.findMany.data || [];
if (data.length === 0) {
return (
@@ -95,48 +80,79 @@ function ListPegawai({ search }: { search: string }) {
title='List Pegawai'
href='/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/pegawai/create'
/>
-
-
-
- Nama
- Gelar Akademik
- Telepon
- Posisi
- Aktif
- Detail
-
-
-
- {(() => {
- console.log('Rendering table with items:', stateOrganisasi.findMany.data);
- return null;
- })()}
- {([...filteredData]
- .sort((a, b) => {
- if (a.isActive === b.isActive) {
- return a.namaLengkap.localeCompare(b.namaLengkap); // kalau status sama, urut nama
- }
- return Number(b.isActive) - Number(a.isActive); // aktif duluan
- }) // Aktif di atas
- ).map((item) => (
-
- {item.namaLengkap}
- {item.gelarAkademik}
- {item.telepon}
- {item.posisi?.nama}
-
- {item.isActive ? "Aktif" : "Tidak Aktif"}
-
-
- router.push(`/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/pegawai/${item.id}`)}>
-
-
-
+
+
+
+
+ Nama
+ Gelar Akademik
+ Telepon
+ Posisi
+ Aktif
+ Detail
- ))}
-
-
+
+
+ {(() => {
+ console.log('Rendering table with items:', stateOrganisasi.findMany.data);
+ return null;
+ })()}
+ {([...filteredData]
+ .sort((a, b) => {
+ if (a.isActive === b.isActive) {
+ return a.namaLengkap.localeCompare(b.namaLengkap); // kalau status sama, urut nama
+ }
+ return Number(b.isActive) - Number(a.isActive); // aktif duluan
+ }) // Aktif di atas
+ ).map((item) => (
+
+ {item.namaLengkap}
+ {item.gelarAkademik}
+ {item.telepon}
+ {item.posisi?.nama}
+
+
+
+
+ {item.isActive ? "Aktif" : "Tidak Aktif"}
+
+
+
+ {item.isActive ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+
+
+ router.push(`/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/pegawai/${item.id}`)}>
+
+
+
+
+ ))}
+
+
+
+
+ {
+ load(newPage, 10);
+ window.scrollTo(0, 0);
+ }}
+ total={totalPages}
+ mt="md"
+ mb="md"
+ />
+
);
}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/berita/find-many.ts b/src/app/api/[[...slugs]]/_lib/desa/berita/find-many.ts
index 5d8fb601..0d582ab7 100644
--- a/src/app/api/[[...slugs]]/_lib/desa/berita/find-many.ts
+++ b/src/app/api/[[...slugs]]/_lib/desa/berita/find-many.ts
@@ -1,27 +1,44 @@
+// /api/berita/findManyPaginated.ts
import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+async function beritaFindManyPaginated(context: Context) {
+ const page = Number(context.query.page) || 1;
+ const limit = Number(context.query.limit) || 10;
+ const skip = (page - 1) * limit;
-async function beritaFindMany() {
try {
- const data = await prisma.berita.findMany({
- where: { isActive: true },
- include: {
- image: true,
- kategoriBerita: true,
- },
- });
+ const [data, total] = await Promise.all([
+ prisma.berita.findMany({
+ where: { isActive: true },
+ include: {
+ image: true,
+ kategoriBerita: true,
+ },
+ skip,
+ take: limit,
+ orderBy: { createdAt: 'desc' }, // opsional, kalau mau urut berdasarkan waktu
+ }),
+ prisma.berita.count({
+ where: { isActive: true }
+ })
+ ]);
return {
success: true,
- message: "Success fetch berita",
+ message: "Success fetch berita with pagination",
data,
+ page,
+ totalPages: Math.ceil(total / limit),
+ total,
};
} catch (e) {
- console.error("Find many error:", e);
+ console.error("Find many paginated error:", e);
return {
success: false,
- message: "Failed fetch berita",
+ message: "Failed fetch berita with pagination",
};
}
}
-export default beritaFindMany;
+export default beritaFindManyPaginated;
diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/struktur-organisasi/pegawai/findMany.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/struktur-organisasi/pegawai/findMany.ts
index e15dd235..b5bf9570 100644
--- a/src/app/api/[[...slugs]]/_lib/ekonomi/struktur-organisasi/pegawai/findMany.ts
+++ b/src/app/api/[[...slugs]]/_lib/ekonomi/struktur-organisasi/pegawai/findMany.ts
@@ -1,26 +1,48 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+// Di findMany.ts
+export default async function pegawaiFindMany(context: Context) {
+ const page = Number(context.query.page) || 1;
+ const limit = Number(context.query.limit) || 10;
+ const skip = (page - 1) * limit;
-export default async function pegawaiFindMany() {
try {
- const pegawaiList = await prisma.pegawai.findMany({
- orderBy: { createdAt: "desc" },
- include: {
- posisi: true,
- image: true,
- },
- });
+ const [data, total] = await Promise.all([
+ prisma.pegawai.findMany({
+ where: { isActive: true },
+ include: {
+ posisi: true,
+ image: true,
+ },
+ skip,
+ take: limit,
+ orderBy: { createdAt: 'desc' },
+ }),
+ prisma.pegawai.count({
+ where: { isActive: true }
+ })
+ ]);
+
+ const totalPages = Math.ceil(total / limit);
return {
success: true,
- data: pegawaiList,
+ message: "Success fetch pegawai with pagination",
+ data,
+ page,
+ totalPages,
+ total,
};
- } catch (error: any) {
- console.error("Error findMany pegawai:", error);
+ } catch (e) {
+ console.error("Find many paginated error:", e);
return {
success: false,
- message: "Gagal mengambil data pegawai",
- error: error.message,
+ message: "Failed fetch pegawai with pagination",
+ data: [],
+ page: 1,
+ totalPages: 1,
+ total: 0,
};
}
-}
+}
\ No newline at end of file