Compare commits
21 Commits
nico/8-okt
...
nico/6-nov
| Author | SHA1 | Date | |
|---|---|---|---|
| db8909b9ed | |||
| f66a46f645 | |||
| fb57698dc9 | |||
| d128313e71 | |||
| 7b4bb1e58e | |||
| 0befe6a3f2 | |||
| a6663bbcee | |||
| ed371bd0d9 | |||
| f82c7b86e0 | |||
| b5d6585cd5 | |||
| aa98359ef7 | |||
| 0ff0d5234a | |||
| 827c1c191a | |||
| fb596f9033 | |||
| 9055b40769 | |||
| bbf13c1cf7 | |||
| 75bf0652b1 | |||
| 0b574406e2 | |||
| ccf39bc778 | |||
| 3c21f7742c | |||
| a158241c0b |
14
package.json
14
package.json
@@ -3,7 +3,7 @@
|
||||
"version": "0.1.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "bun --bun next dev --hostname 0.0.0.0",
|
||||
"dev": "bun --bun next dev",
|
||||
"build": "bun --bun next build",
|
||||
"start": "bun --bun next start"
|
||||
},
|
||||
@@ -19,6 +19,7 @@
|
||||
"@elysiajs/static": "^1.3.0",
|
||||
"@elysiajs/stream": "^1.1.0",
|
||||
"@elysiajs/swagger": "^1.2.0",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@mantine/carousel": "^7.16.2",
|
||||
"@mantine/charts": "^7.17.1",
|
||||
"@mantine/core": "^7.17.4",
|
||||
@@ -26,6 +27,7 @@
|
||||
"@mantine/dropzone": "^8.1.1",
|
||||
"@mantine/form": "^8.1.0",
|
||||
"@mantine/hooks": "^7.17.4",
|
||||
"@mantine/modals": "^8.3.6",
|
||||
"@mantine/tiptap": "^7.17.4",
|
||||
"@paljs/types": "^8.1.0",
|
||||
"@prisma/client": "^6.3.1",
|
||||
@@ -43,6 +45,7 @@
|
||||
"@types/bun": "^1.2.2",
|
||||
"@types/leaflet": "^1.9.20",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/nodemailer": "^7.0.2",
|
||||
"add": "^2.0.6",
|
||||
"adm-zip": "^0.5.16",
|
||||
"animate.css": "^4.1.1",
|
||||
@@ -52,9 +55,11 @@
|
||||
"classnames": "^2.5.1",
|
||||
"colors": "^1.4.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dotenv": "^17.2.3",
|
||||
"elysia": "^1.3.5",
|
||||
"embla-carousel-autoplay": "^8.5.2",
|
||||
"embla-carousel-react": "^7.1.0",
|
||||
"embla-carousel": "^8.6.0",
|
||||
"embla-carousel-autoplay": "^8.6.0",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
"extract-zip": "^2.0.1",
|
||||
"form-data": "^4.0.2",
|
||||
"framer-motion": "^12.23.5",
|
||||
@@ -71,17 +76,20 @@
|
||||
"next": "^15.5.2",
|
||||
"next-view-transitions": "^0.3.4",
|
||||
"node-fetch": "^3.3.2",
|
||||
"nodemailer": "^7.0.10",
|
||||
"p-limit": "^6.2.0",
|
||||
"primeicons": "^7.0.0",
|
||||
"primereact": "^10.9.6",
|
||||
"prisma": "^6.3.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-exif-orientation-img": "^0.1.5",
|
||||
"react-international-phone": "^4.6.0",
|
||||
"react-leaflet": "^5.0.0",
|
||||
"react-simple-toasts": "^6.1.0",
|
||||
"react-toastify": "^11.0.5",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"react-zoom-pan-pinch": "^3.7.0",
|
||||
"readdirp": "^4.1.1",
|
||||
"recharts": "^2.15.3",
|
||||
"sharp": "^0.34.3",
|
||||
|
||||
@@ -1,16 +1,4 @@
|
||||
[
|
||||
{
|
||||
"id": "cmds8w2q60002vnbe6i8qhkuo",
|
||||
"name": "Telephone Desa Darmasaba",
|
||||
"iconUrl": "081239580000",
|
||||
"imageId": "cmff3nv180003vn6h5jvedidq"
|
||||
},
|
||||
{
|
||||
"id": "cmds8z7u20005vnbegyyvnbk0",
|
||||
"name": "Email Desa Darmasaba",
|
||||
"iconUrl": "desadarmasaba@badungkab.go.id",
|
||||
"imageId": "cmff3ll130001vn6hkhls3f5y"
|
||||
},
|
||||
{
|
||||
"id": "cmds9023u0008vnbe3oxmhwyf",
|
||||
"name": "Desa Darmasaba",
|
||||
|
||||
@@ -143,7 +143,7 @@ model MediaSosial {
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
//========================================= PROFILE ========================================= //
|
||||
//========================================= DESA ANTI KORUPSI ========================================= //
|
||||
model DesaAntiKorupsi {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
@@ -324,8 +324,8 @@ model PegawaiPPID {
|
||||
model StrukturOrganisasiPPID {
|
||||
id String @id @default(uuid())
|
||||
posisiOrganisasiId String @db.VarChar(50)
|
||||
pegawaiId String
|
||||
hubunganOrganisasiId String
|
||||
pegawaiId String
|
||||
hubunganOrganisasiId String
|
||||
posisiOrganisasi PosisiOrganisasiPPID @relation(fields: [posisiOrganisasiId], references: [id])
|
||||
pegawai PegawaiPPID @relation(fields: [pegawaiId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
@@ -1450,8 +1450,8 @@ model PegawaiBumDes {
|
||||
model StrukturOrganisasiBumDes {
|
||||
id String @id @default(uuid())
|
||||
posisiOrganisasiId String @db.VarChar(50)
|
||||
pegawaiId String
|
||||
hubunganOrganisasiId String
|
||||
pegawaiId String
|
||||
hubunganOrganisasiId String
|
||||
posisiOrganisasi PosisiOrganisasiBumDes @relation(fields: [posisiOrganisasiId], references: [id])
|
||||
pegawai PegawaiBumDes @relation(fields: [pegawaiId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
@@ -1606,7 +1606,7 @@ model Pembiayaan {
|
||||
ApbDesa ApbDesa[] @relation("ApbDesaPembiayaan")
|
||||
}
|
||||
|
||||
// ========================================= INOVASI ========================================= //
|
||||
// ========================================= MENU INOVASI ========================================= //
|
||||
// ========================================= DESA DIGITAL / SMART VILLAGE ========================================= //
|
||||
model DesaDigital {
|
||||
id String @id @default(cuid())
|
||||
@@ -1820,7 +1820,7 @@ model KategoriKegiatan {
|
||||
isActive Boolean @default(true)
|
||||
KegiatanDesa KegiatanDesa[]
|
||||
}
|
||||
|
||||
|
||||
// ========================================= EDUKASI LINGKUNGAN ========================================= //
|
||||
model TujuanEdukasiLingkungan {
|
||||
id String @id @default(cuid())
|
||||
@@ -2087,6 +2087,9 @@ model DataPerpustakaan {
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
|
||||
// relasi baru ke peminjaman
|
||||
peminjamanBuku PeminjamanBuku[]
|
||||
}
|
||||
|
||||
model KategoriBuku {
|
||||
@@ -2099,6 +2102,31 @@ model KategoriBuku {
|
||||
DataPerpustakaan DataPerpustakaan[]
|
||||
}
|
||||
|
||||
model PeminjamanBuku {
|
||||
id String @id @default(cuid())
|
||||
nama String
|
||||
noTelp String
|
||||
alamat String
|
||||
bukuId String
|
||||
tanggalPinjam DateTime @default(now())
|
||||
batasKembali DateTime // tenggat waktu pengembalian
|
||||
tanggalKembali DateTime? // diisi saat dikembalikan
|
||||
status StatusPeminjaman @default(Dipinjam)
|
||||
catatan String? // opsional, misal: kondisi buku
|
||||
buku DataPerpustakaan @relation(fields: [bukuId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
enum StatusPeminjaman {
|
||||
Dipinjam
|
||||
Dikembalikan
|
||||
Terlambat
|
||||
Dibatalkan
|
||||
}
|
||||
|
||||
// ========================================= USER ========================================= //
|
||||
|
||||
model User {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 378 KiB |
@@ -75,17 +75,18 @@ const berita = proxy({
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
||||
berita.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
const startTime = Date.now();
|
||||
berita.findMany.loading = true;
|
||||
berita.findMany.page = page;
|
||||
berita.findMany.search = search;
|
||||
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
if (kategori) query.kategori = kategori;
|
||||
|
||||
|
||||
const res = await ApiFetch.api.desa.berita["find-many"].get({ query });
|
||||
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
berita.findMany.data = res.data.data ?? [];
|
||||
berita.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
@@ -98,9 +99,16 @@ const berita = proxy({
|
||||
berita.findMany.data = [];
|
||||
berita.findMany.totalPages = 1;
|
||||
} finally {
|
||||
berita.findMany.loading = false;
|
||||
// pastikan minimal 300ms sebelum loading = false (biar UX smooth)
|
||||
const elapsed = Date.now() - startTime;
|
||||
const minDelay = 300;
|
||||
const delay = elapsed < minDelay ? minDelay - elapsed : 0;
|
||||
|
||||
setTimeout(() => {
|
||||
berita.findMany.loading = false;
|
||||
}, delay);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
findUnique: {
|
||||
|
||||
@@ -6,9 +6,9 @@ import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
slug: z.string().min(1, "Deskripsi singkat minimal 1 karakter"),
|
||||
name: z.string().min(5, "Nama minimal 5 karakter"),
|
||||
deskripsi: z.string().min(5, "Deskripsi minimal 5 karakter"),
|
||||
slug: z.string().min(5, "Deskripsi singkat minimal 5 karakter"),
|
||||
icon: z.string().min(1, "Icon minimal 1 karakter"),
|
||||
});
|
||||
|
||||
@@ -29,26 +29,33 @@ const programKreatifState = proxy({
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
toast.error(err);
|
||||
return false; // ⬅️ ini penting
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
programKreatifState.create.loading = true;
|
||||
const res = await ApiFetch.api.inovasi.programkreatif["create"].post(
|
||||
programKreatifState.create.form
|
||||
);
|
||||
|
||||
if (res.status === 200) {
|
||||
programKreatifState.findMany.load();
|
||||
return toast.success("success create");
|
||||
toast.success("success create");
|
||||
return true;
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
|
||||
toast.error("failed create");
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat create");
|
||||
return false;
|
||||
} finally {
|
||||
programKreatifState.create.loading = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
findMany: {
|
||||
data: null as any[] | null,
|
||||
|
||||
@@ -55,46 +55,95 @@ const dataPerpustakaan = proxy({
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.DataPerpustakaanGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
kategori: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
||||
dataPerpustakaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
dataPerpustakaan.findMany.page = page;
|
||||
dataPerpustakaan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
if (kategori) query.kategori = kategori;
|
||||
|
||||
const res = await ApiFetch.api.pendidikan.perpustakaandigital.dataperpustakaan["findMany"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
dataPerpustakaan.findMany.data = res.data.data ?? [];
|
||||
dataPerpustakaan.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
dataPerpustakaan.findMany.data = [];
|
||||
dataPerpustakaan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch data perpustakaan paginated:", err);
|
||||
data: null as
|
||||
| Prisma.DataPerpustakaanGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
kategori: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
||||
const startTime = Date.now();
|
||||
dataPerpustakaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
dataPerpustakaan.findMany.page = page;
|
||||
dataPerpustakaan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
if (kategori) query.kategori = kategori;
|
||||
|
||||
const res =
|
||||
await ApiFetch.api.pendidikan.perpustakaandigital.dataperpustakaan[
|
||||
"findMany"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
dataPerpustakaan.findMany.data = res.data.data ?? [];
|
||||
dataPerpustakaan.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
dataPerpustakaan.findMany.data = [];
|
||||
dataPerpustakaan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
dataPerpustakaan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch data perpustakaan paginated:", err);
|
||||
dataPerpustakaan.findMany.data = [];
|
||||
dataPerpustakaan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
// pastikan minimal 300ms sebelum loading = false (biar UX smooth)
|
||||
const elapsed = Date.now() - startTime;
|
||||
const minDelay = 300;
|
||||
const delay = elapsed < minDelay ? minDelay - elapsed : 0;
|
||||
|
||||
setTimeout(() => {
|
||||
dataPerpustakaan.findMany.loading = false;
|
||||
}, delay);
|
||||
}
|
||||
},
|
||||
},
|
||||
findManyAll: {
|
||||
data: null as
|
||||
| Prisma.DataPerpustakaanGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
kategori: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (search = "", kategori = "") => {
|
||||
dataPerpustakaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
dataPerpustakaan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = {};
|
||||
if (search) query.search = search;
|
||||
if (kategori) query.kategori = kategori;
|
||||
|
||||
const res =
|
||||
await ApiFetch.api.pendidikan.perpustakaandigital.dataperpustakaan[
|
||||
"findManyAll"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
dataPerpustakaan.findManyAll.data = res.data.data ?? [];
|
||||
} else {
|
||||
dataPerpustakaan.findManyAll.data = [];
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch data perpustakaan paginated:", err);
|
||||
dataPerpustakaan.findManyAll.data = [];
|
||||
} finally {
|
||||
dataPerpustakaan.findManyAll.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.DataPerpustakaanGetPayload<{
|
||||
include: {
|
||||
@@ -321,17 +370,20 @@ const kategoriBuku = proxy({
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
kategoriBuku.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kategoriBuku.findMany.page = page;
|
||||
kategoriBuku.findMany.search = search;
|
||||
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.pendidikan.perpustakaandigital.kategoribuku["findMany"].get({ query });
|
||||
|
||||
|
||||
const res =
|
||||
await ApiFetch.api.pendidikan.perpustakaandigital.kategoribuku[
|
||||
"findMany"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kategoriBuku.findMany.data = res.data.data ?? [];
|
||||
kategoriBuku.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
@@ -514,9 +566,319 @@ const kategoriBuku = proxy({
|
||||
},
|
||||
});
|
||||
|
||||
const templatePeminjamanBuku = z.object({
|
||||
nama: z.string().min(1, "Nama harus diisi"),
|
||||
noTelp: z.string().min(1, "No Telp harus diisi"),
|
||||
alamat: z.string().min(1, "Alamat harus diisi"),
|
||||
bukuId: z.string().min(1, "Buku ID harus diisi"),
|
||||
tanggalPinjam: z.string().min(1, "Tanggal Pinjam harus diisi"),
|
||||
batasKembali: z.string().min(1, "Batas Kembali harus diisi"),
|
||||
tanggalKembali: z.string().min(1, "Tanggal Kembali harus diisi"),
|
||||
catatan: z.string().min(1, "Catatan harus diisi"),
|
||||
});
|
||||
|
||||
const defaultPeminjamanBuku = {
|
||||
nama: "",
|
||||
noTelp: "",
|
||||
alamat: "",
|
||||
bukuId: "",
|
||||
tanggalPinjam: "",
|
||||
batasKembali: "",
|
||||
tanggalKembali: "",
|
||||
catatan: "",
|
||||
};
|
||||
|
||||
interface FormEditData {
|
||||
nama: string;
|
||||
noTelp: string;
|
||||
alamat: string;
|
||||
bukuId: string;
|
||||
buku?: {
|
||||
id: string;
|
||||
judul: string;
|
||||
};
|
||||
tanggalPinjam: string;
|
||||
batasKembali: string;
|
||||
tanggalKembali: string;
|
||||
catatan: string;
|
||||
status: "Dipinjam" | "Dikembalikan" | "Terlambat" | "Dibatalkan";
|
||||
}
|
||||
|
||||
const editForm: FormEditData = {
|
||||
nama: "",
|
||||
noTelp: "",
|
||||
alamat: "",
|
||||
bukuId: "",
|
||||
tanggalPinjam: "",
|
||||
batasKembali: "",
|
||||
tanggalKembali: "",
|
||||
catatan: "",
|
||||
status: "Dipinjam",
|
||||
};
|
||||
|
||||
const peminjamanBuku = proxy({
|
||||
create: {
|
||||
form: { ...defaultPeminjamanBuku },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templatePeminjamanBuku.safeParse(peminjamanBuku.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
peminjamanBuku.create.loading = true;
|
||||
const res =
|
||||
await ApiFetch.api.pendidikan.perpustakaandigital.peminjamanbuku[
|
||||
"create"
|
||||
].post(peminjamanBuku.create.form);
|
||||
if (res.status === 200) {
|
||||
peminjamanBuku.findMany.load();
|
||||
return toast.success("Data Peminjaman Buku Berhasil Dibuat");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return toast.error("failed create");
|
||||
} finally {
|
||||
peminjamanBuku.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: [] as Prisma.PeminjamanBukuGetPayload<{
|
||||
include: {
|
||||
buku: true;
|
||||
};
|
||||
}>[],
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
peminjamanBuku.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
peminjamanBuku.findMany.page = page;
|
||||
peminjamanBuku.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res =
|
||||
await ApiFetch.api.pendidikan.perpustakaandigital.peminjamanbuku[
|
||||
"findMany"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
peminjamanBuku.findMany.data = res.data.data ?? [];
|
||||
peminjamanBuku.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
peminjamanBuku.findMany.data = [];
|
||||
peminjamanBuku.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch data peminjaman buku paginated:", err);
|
||||
peminjamanBuku.findMany.data = [];
|
||||
peminjamanBuku.findMany.totalPages = 1;
|
||||
} finally {
|
||||
peminjamanBuku.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PeminjamanBukuGetPayload<{
|
||||
include: {
|
||||
buku: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/pendidikan/perpustakaandigital/peminjamanbuku/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
peminjamanBuku.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
peminjamanBuku.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
peminjamanBuku.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async delete(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
peminjamanBuku.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/pendidikan/perpustakaandigital/peminjamanbuku/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Data Peminjaman Buku berhasil dihapus"
|
||||
);
|
||||
await peminjamanBuku.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus Data Peminjaman Buku"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus Data Peminjaman Buku");
|
||||
} finally {
|
||||
peminjamanBuku.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...editForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/pendidikan/perpustakaandigital/peminjamanbuku/${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 = {
|
||||
nama: data.nama,
|
||||
noTelp: data.noTelp,
|
||||
alamat: data.alamat,
|
||||
bukuId: data.bukuId,
|
||||
tanggalPinjam: data.tanggalPinjam,
|
||||
batasKembali: data.batasKembali,
|
||||
tanggalKembali: data.tanggalKembali,
|
||||
catatan: data.catatan,
|
||||
status: data.status,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading peminjaman buku:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templatePeminjamanBuku.safeParse(peminjamanBuku.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
peminjamanBuku.update.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/pendidikan/perpustakaandigital/peminjamanbuku/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
noTelp: this.form.noTelp,
|
||||
alamat: this.form.alamat,
|
||||
bukuId: this.form.bukuId,
|
||||
tanggalPinjam: this.form.tanggalPinjam,
|
||||
batasKembali: this.form.batasKembali,
|
||||
tanggalKembali: this.form.tanggalKembali,
|
||||
catatan: this.form.catatan,
|
||||
status: this.form.status,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
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 data peminjaman buku");
|
||||
await peminjamanBuku.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(
|
||||
result.message || "Gagal update data peminjaman buku"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating data peminjaman buku:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update data peminjaman buku"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
peminjamanBuku.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
peminjamanBuku.update.id = "";
|
||||
peminjamanBuku.update.form = { ...editForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const perpustakaanDigitalState = proxy({
|
||||
dataPerpustakaan,
|
||||
kategoriBuku,
|
||||
peminjamanBuku,
|
||||
});
|
||||
|
||||
export default perpustakaanDigitalState;
|
||||
|
||||
@@ -561,6 +561,45 @@ const pegawai = proxy({
|
||||
}
|
||||
},
|
||||
},
|
||||
findManyAll: {
|
||||
data: null as
|
||||
| Prisma.PegawaiPPIDGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
posisi: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (search = "") => {
|
||||
// Change to arrow function
|
||||
pegawai.findManyAll.loading = true; // Use the full path to access the property
|
||||
pegawai.findManyAll.search = search;
|
||||
try {
|
||||
const query: any = { search };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ppid.strukturppid.pegawai[
|
||||
"find-many-all"
|
||||
].get({
|
||||
query,
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pegawai.findManyAll.data = res.data.data || [];
|
||||
} else {
|
||||
console.error("Failed to load pegawai:", res.data?.message);
|
||||
pegawai.findManyAll.data = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pegawai:", error);
|
||||
pegawai.findManyAll.data = [];
|
||||
} finally {
|
||||
pegawai.findManyAll.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as
|
||||
| (Prisma.PegawaiPPIDGetPayload<{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||
import { IconBuildingStore, IconFileText, IconSparkles, IconUsers, IconUsersPlus } from '@tabler/icons-react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { IconFileText, IconBuildingStore, IconSparkles, IconUsers, IconUsersPlus } from '@tabler/icons-react';
|
||||
|
||||
function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter()
|
||||
@@ -14,36 +14,31 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||
label: "Pelayanan Surat Keterangan",
|
||||
value: "pelayanansuratketerangan",
|
||||
href: "/admin/desa/layanan/pelayanan_surat_keterangan",
|
||||
icon: <IconFileText size={18} stroke={1.8} />,
|
||||
tooltip: "Layanan terkait surat keterangan resmi desa"
|
||||
icon: <IconFileText size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Pelayanan Perizinan Berusaha",
|
||||
value: "pelayananperizinanusaha",
|
||||
href: "/admin/desa/layanan/pelayanan_perizinan_berusaha",
|
||||
icon: <IconBuildingStore size={18} stroke={1.8} />,
|
||||
tooltip: "Layanan untuk izin usaha masyarakat"
|
||||
icon: <IconBuildingStore size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Pelayanan Telunjuk Sakti Desa",
|
||||
value: "pelayanantelunjuksaktidesa",
|
||||
href: "/admin/desa/layanan/pelayanan_telunjuk_sakti_desa",
|
||||
icon: <IconSparkles size={18} stroke={1.8} />,
|
||||
tooltip: "Layanan inovasi khusus desa"
|
||||
icon: <IconSparkles size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Pelayanan Penduduk Non-Permanent",
|
||||
value: "pelayanannonpermanent",
|
||||
href: "/admin/desa/layanan/pelayanan_penduduk_non_permanent",
|
||||
icon: <IconUsers size={18} stroke={1.8} />,
|
||||
tooltip: "Pendataan penduduk non-permanent"
|
||||
icon: <IconUsers size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Ajukan Permohonan",
|
||||
value: "ajukanpermohonan",
|
||||
href: "/admin/desa/layanan/ajukan_permohonan",
|
||||
icon: <IconUsersPlus size={18} stroke={1.8} />,
|
||||
tooltip: "Ajukan permohonan"
|
||||
icon: <IconUsersPlus size={18} stroke={1.8} />
|
||||
}
|
||||
];
|
||||
|
||||
@@ -91,14 +86,8 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
{tabs.map((tab, i) => (
|
||||
<Tooltip
|
||||
key={i}
|
||||
label={tab.tooltip}
|
||||
position="bottom"
|
||||
withArrow
|
||||
transitionProps={{ transition: 'pop', duration: 200 }}
|
||||
>
|
||||
<TabsTab
|
||||
key={i}
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
@@ -109,7 +98,6 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
</Tooltip>
|
||||
))}
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||
import { IconCategory, IconNews } from '@tabler/icons-react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { IconNews, IconCategory } from '@tabler/icons-react';
|
||||
|
||||
function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter();
|
||||
@@ -15,15 +15,13 @@ function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
|
||||
label: "List Berita",
|
||||
value: "list_berita",
|
||||
href: "/admin/desa/berita/list-berita",
|
||||
icon: <IconNews size={18} stroke={1.8} />,
|
||||
tooltip: "Lihat dan kelola semua berita desa"
|
||||
icon: <IconNews size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Kategori Berita",
|
||||
value: "kategori_berita",
|
||||
href: "/admin/desa/berita/kategori-berita",
|
||||
icon: <IconCategory size={18} stroke={1.8} />,
|
||||
tooltip: "Kelola kategori berita desa"
|
||||
icon: <IconCategory size={18} stroke={1.8} />
|
||||
},
|
||||
];
|
||||
|
||||
@@ -71,46 +69,39 @@ function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
{tabs.map((tab, i) => (
|
||||
<Tooltip
|
||||
<TabsTab
|
||||
key={i}
|
||||
label={tab.tooltip}
|
||||
position="bottom"
|
||||
withArrow
|
||||
transitionProps={{ transition: 'pop', duration: 200 }}
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
<TabsTab
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
</Tooltip>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
))}
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
|
||||
{tabs.map((tab, i) => (
|
||||
<TabsPanel
|
||||
key={i}
|
||||
value={tab.value}
|
||||
style={{
|
||||
padding: "1.5rem",
|
||||
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
|
||||
borderRadius: "1rem",
|
||||
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
|
||||
}}
|
||||
>
|
||||
{/* Konten dummy, bisa diganti sesuai routing */}
|
||||
<>{children}</>
|
||||
</TabsPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
</Stack>
|
||||
{tabs.map((tab, i) => (
|
||||
<TabsPanel
|
||||
key={i}
|
||||
value={tab.value}
|
||||
style={{
|
||||
padding: "1.5rem",
|
||||
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
|
||||
borderRadius: "1rem",
|
||||
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
|
||||
}}
|
||||
>
|
||||
{/* Konten dummy, bisa diganti sesuai routing */}
|
||||
<>{children}</>
|
||||
</TabsPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
</Stack >
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -77,7 +76,6 @@ function EditKategoriBerita() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Back Button + Title */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -86,7 +84,6 @@ function EditKategoriBerita() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Kategori Berita
|
||||
</Title>
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -35,7 +34,6 @@ function CreateKategoriBerita() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header dengan back button */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -44,7 +42,6 @@ function CreateKategoriBerita() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Kategori Berita
|
||||
</Title>
|
||||
|
||||
@@ -17,8 +17,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -86,7 +85,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Kategori Berita</Title>
|
||||
<Tooltip label="Tambah Kategori Berita" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -97,7 +95,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
|
||||
<Box style={{ overflowX: 'auto' }}>
|
||||
@@ -123,7 +120,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
||||
</Text>
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
<Tooltip label="Edit Kategori Berita" withArrow>
|
||||
<Button
|
||||
variant="light"
|
||||
color="green"
|
||||
@@ -135,10 +131,8 @@ function ListKategoriBerita({ search }: { search: string }) {
|
||||
>
|
||||
<IconEdit size={18} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
<Tooltip label="Hapus Kategori Berita" withArrow>
|
||||
<Button
|
||||
variant="light"
|
||||
color="red"
|
||||
@@ -150,7 +144,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
||||
>
|
||||
<IconTrash size={18} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
))
|
||||
|
||||
@@ -15,8 +15,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from "@mantine/core";
|
||||
import { Dropzone } from "@mantine/dropzone";
|
||||
import {
|
||||
@@ -116,7 +115,6 @@ function EditBerita() {
|
||||
<Box px={{ base: "sm", md: "lg" }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -125,7 +123,6 @@ function EditBerita() {
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Berita
|
||||
</Title>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
'use client'
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
import colors from '@/con/colors';
|
||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||
import stateDashboardBerita from '@/app/admin/(dashboard)/_state/desa/berita';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
function DetailBerita() {
|
||||
const beritaState = useProxy(stateDashboardBerita);
|
||||
@@ -111,7 +111,6 @@ function DetailBerita() {
|
||||
|
||||
{/* Action Button */}
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Berita" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
@@ -124,9 +123,7 @@ function DetailBerita() {
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label="Edit Berita" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/desa/berita/list-berita/${data.id}/edit`)}
|
||||
@@ -136,7 +133,6 @@ function DetailBerita() {
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
@@ -73,7 +72,6 @@ export default function CreateBerita() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header dengan tombol kembali */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -82,7 +80,6 @@ export default function CreateBerita() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Berita
|
||||
</Title>
|
||||
|
||||
@@ -16,8 +16,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
|
||||
@@ -68,7 +67,6 @@ function ListBerita({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Berita</Title>
|
||||
<Tooltip label="Tambah Berita" withArrow>
|
||||
<Button
|
||||
leftSection={<IconCircleDashedPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -77,7 +75,6 @@ function ListBerita({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
|
||||
<Box style={{ overflowX: 'auto' }}>
|
||||
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { IconSearch, IconTrash, IconX } from "@tabler/icons-react";
|
||||
@@ -103,7 +102,6 @@ export default function ListImage() {
|
||||
</Box>
|
||||
|
||||
<Group justify="space-between" align="center" pt="xs">
|
||||
<Tooltip label="Hapus foto" withArrow>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
color="red"
|
||||
@@ -116,7 +114,6 @@ export default function ListImage() {
|
||||
>
|
||||
<IconTrash size={18} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||
import { IconPhoto, IconVideo } from '@tabler/icons-react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { IconPhoto, IconVideo } from '@tabler/icons-react';
|
||||
|
||||
function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter()
|
||||
@@ -14,15 +14,13 @@ function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
|
||||
label: "Foto",
|
||||
value: "foto",
|
||||
href: "/admin/desa/gallery/foto",
|
||||
icon: <IconPhoto size={18} stroke={1.8} />,
|
||||
tooltip: "Kelola foto-foto galeri desa"
|
||||
icon: <IconPhoto size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Video",
|
||||
value: "video",
|
||||
href: "/admin/desa/gallery/video",
|
||||
icon: <IconVideo size={18} stroke={1.8} />,
|
||||
tooltip: "Kelola video galeri desa"
|
||||
icon: <IconVideo size={18} stroke={1.8} />
|
||||
},
|
||||
];
|
||||
|
||||
@@ -70,25 +68,18 @@ function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
{tabs.map((tab, i) => (
|
||||
<Tooltip
|
||||
<TabsTab
|
||||
key={i}
|
||||
label={tab.tooltip}
|
||||
position="bottom"
|
||||
withArrow
|
||||
transitionProps={{ transition: 'pop', duration: 200 }}
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
<TabsTab
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
</Tooltip>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
))}
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
|
||||
@@ -10,12 +10,11 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { convertYoutubeUrlToEmbed } from '../../../lib/youtube-utils';
|
||||
@@ -89,7 +88,6 @@ function EditVideo() {
|
||||
return (
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -98,7 +96,6 @@ function EditVideo() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Video
|
||||
</Title>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||
import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -111,7 +111,6 @@ function DetailVideo() {
|
||||
|
||||
{/* Tombol Aksi */}
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Video" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
@@ -124,9 +123,7 @@ function DetailVideo() {
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label="Edit Video" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
@@ -138,7 +135,6 @@ function DetailVideo() {
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -51,7 +50,6 @@ function CreateVideo() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header Back Button + Title */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -60,7 +58,6 @@ function CreateVideo() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Video
|
||||
</Title>
|
||||
|
||||
@@ -16,8 +16,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
@@ -74,7 +73,6 @@ function ListVideo({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Video</Title>
|
||||
<Tooltip label="Tambah Video Baru" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -83,7 +81,6 @@ function ListVideo({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
<Box style={{ overflowX: "auto" }}>
|
||||
<Table highlightOnHover>
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Select,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -87,11 +86,9 @@ function EditAjukanPermohonan() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Back Button */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Ajukan Permohonan
|
||||
</Title>
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Tooltip
|
||||
Text
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
@@ -121,7 +120,6 @@ function DetailAjukanPermohonan() {
|
||||
</Box>
|
||||
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Surat" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
@@ -135,9 +133,7 @@ function DetailAjukanPermohonan() {
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label="Edit Surat" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
@@ -151,7 +147,6 @@ function DetailAjukanPermohonan() {
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -83,7 +82,6 @@ function EditPelayananPendudukNonPermanent() {
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -92,7 +90,6 @@ function EditPelayananPendudukNonPermanent() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Pelayanan Penduduk Non Permanent
|
||||
</Title>
|
||||
|
||||
@@ -11,8 +11,7 @@ import {
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconEdit } from '@tabler/icons-react';
|
||||
@@ -27,7 +26,7 @@ function PelayananPendudukNonPermanent() {
|
||||
);
|
||||
|
||||
useShallowEffect(() => {
|
||||
pelayananPendudukNonPermanen.findById.load('1');
|
||||
pelayananPendudukNonPermanen.findById.load('edit');
|
||||
}, []);
|
||||
|
||||
if (!pelayananPendudukNonPermanen.findById.data) {
|
||||
@@ -51,7 +50,6 @@ function PelayananPendudukNonPermanent() {
|
||||
</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Data Pelayanan" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
@@ -65,7 +63,6 @@ function PelayananPendudukNonPermanent() {
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
Skeleton,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -100,7 +99,6 @@ function EditPelayananPerizinanBerusaha() {
|
||||
<Stack gap="xs">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -109,7 +107,6 @@ function EditPelayananPerizinanBerusaha() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Pelayanan Perizinan Berusaha
|
||||
</Title>
|
||||
|
||||
@@ -16,14 +16,13 @@ import {
|
||||
StepperCompleted,
|
||||
StepperStep,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconEdit } from '@tabler/icons-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import stateLayananDesa from '../../../_state/desa/layananDesa';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateLayananDesa from '../../../_state/desa/layananDesa';
|
||||
|
||||
function PerizinanBerusaha() {
|
||||
const router = useRouter();
|
||||
@@ -43,7 +42,7 @@ function PerizinanBerusaha() {
|
||||
try {
|
||||
setLoading(true);
|
||||
// You should get the ID from your router query or params
|
||||
const id = '1'; // Replace with actual ID or get from URL params
|
||||
const id = 'edit'; // Replace with actual ID or get from URL params
|
||||
await pelayananPerizinanBerusaha.findById.load(id);
|
||||
} catch (err) {
|
||||
setError('Gagal memuat data');
|
||||
@@ -85,7 +84,6 @@ function PerizinanBerusaha() {
|
||||
</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Data Perizinan" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
@@ -99,7 +97,6 @@ function PerizinanBerusaha() {
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -12,13 +12,12 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
@@ -112,11 +111,9 @@ function EditSuratKeterangan() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Back Button */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Surat Keterangan
|
||||
</Title>
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Tooltip,
|
||||
Text
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
@@ -142,7 +141,6 @@ function DetailSuratKeterangan() {
|
||||
</Box>
|
||||
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Surat" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
@@ -156,9 +154,7 @@ function DetailSuratKeterangan() {
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label="Edit Surat" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
@@ -172,7 +168,6 @@ function DetailSuratKeterangan() {
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
@@ -85,11 +84,9 @@ function CreateSuratKeterangan() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Surat Keterangan
|
||||
</Title>
|
||||
|
||||
@@ -17,8 +17,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -82,7 +81,6 @@ function ListSuratKeterangan({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>List Surat Keterangan</Title>
|
||||
<Tooltip label="Tambah Surat Keterangan" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -93,7 +91,6 @@ function ListSuratKeterangan({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
<Box style={{ overflowX: "auto" }}>
|
||||
<Table highlightOnHover>
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -81,11 +80,9 @@ function EditPelayananTelunjukSakti() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Back Button + Title */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Pelayanan Telunjuk Sakti Desa
|
||||
</Title>
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Tooltip,
|
||||
Text
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
@@ -130,7 +129,6 @@ function DetailPelayananTelunjukSakti() {
|
||||
</Box>
|
||||
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Layanan" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
@@ -144,9 +142,7 @@ function DetailPelayananTelunjukSakti() {
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label="Edit Layanan" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
@@ -160,7 +156,6 @@ function DetailPelayananTelunjukSakti() {
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -45,11 +44,9 @@ function CreatePelayananTelunjukDesa() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Pelayanan Telunjuk Sakti Desa
|
||||
</Title>
|
||||
|
||||
@@ -1,159 +1,3 @@
|
||||
// /* eslint-disable react-hooks/exhaustive-deps */
|
||||
// 'use client'
|
||||
// import colors from '@/con/colors';
|
||||
// import { Box, Button, Center, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
|
||||
// import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
|
||||
// import { useRouter } from 'next/navigation';
|
||||
// import { useEffect, useMemo, useState } from 'react';
|
||||
// import { useProxy } from 'valtio/utils';
|
||||
// import HeaderSearch from '../../../_com/header';
|
||||
// import JudulList from '../../../_com/judulList';
|
||||
// import stateLayananDesa from '../../../_state/desa/layananDesa';
|
||||
|
||||
// function PelayananTelunjukSakti() {
|
||||
// const [search, setSearch] = useState("");
|
||||
// return (
|
||||
// <Box>
|
||||
// <HeaderSearch
|
||||
// title='Posisi Organisasi'
|
||||
// placeholder='pencarian'
|
||||
// searchIcon={<IconSearch size={20} />}
|
||||
// value={search}
|
||||
// onChange={(e) => setSearch(e.currentTarget.value)}
|
||||
// />
|
||||
// <ListPelayananTelunjukSakti search={search} />
|
||||
// </Box>
|
||||
// );
|
||||
// }
|
||||
|
||||
// function ListPelayananTelunjukSakti({ search }: { search: string }) {
|
||||
// const telunjukSaktiState = useProxy(stateLayananDesa.pelayananTelunjukSaktiDesa)
|
||||
// const router = useRouter()
|
||||
|
||||
// const {
|
||||
// data,
|
||||
// page,
|
||||
// totalPages,
|
||||
// loading,
|
||||
// load,
|
||||
// } = telunjukSaktiState.findMany;
|
||||
|
||||
// useEffect(() => {
|
||||
// load(page, 10)
|
||||
// }, [])
|
||||
|
||||
// const filteredData = useMemo(() => {
|
||||
// if (!data) return [];
|
||||
// return data.filter(item => {
|
||||
// const keyword = search.toLowerCase();
|
||||
// return (
|
||||
// item.name?.toLowerCase().includes(keyword) ||
|
||||
// item.link?.toLowerCase().includes(keyword) ||
|
||||
// item.deskripsi?.toLowerCase().includes(keyword)
|
||||
// );
|
||||
// })
|
||||
// .sort((a, b) => a.posisi?.hierarki - b.posisi?.hierarki);
|
||||
// }, [data, search]);
|
||||
|
||||
// if (loading || !data) {
|
||||
// return (
|
||||
// <Stack py={10}>
|
||||
// <Skeleton height={300} />
|
||||
// </Stack>
|
||||
// );
|
||||
// }
|
||||
|
||||
// if (data.length === 0) {
|
||||
// return (
|
||||
// <Box py={10}>
|
||||
// <Paper bg={colors['white-1']} p={'md'}>
|
||||
// <JudulList
|
||||
// title='List Pelayanan Telunjuk Sakti Desa'
|
||||
// href='/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/create'
|
||||
// />
|
||||
// <Table striped withTableBorder withRowBorders>
|
||||
// <TableThead>
|
||||
// <TableTr>
|
||||
// <TableTh>Nama</TableTh>
|
||||
// <TableTh>Link</TableTh>
|
||||
// <TableTh>Detail</TableTh>
|
||||
// </TableTr>
|
||||
// </TableThead>
|
||||
// <TableTbody>
|
||||
// <TableTr>
|
||||
// <TableTd colSpan={3}>
|
||||
// <Text fz={"sm"} color="gray.5">
|
||||
// Tidak ada data
|
||||
// </Text>
|
||||
// </TableTd>
|
||||
// </TableTr>
|
||||
// </TableTbody>
|
||||
// </Table>
|
||||
// </Paper>
|
||||
// </Box>
|
||||
// );
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <Box py={10}>
|
||||
// <Paper bg={colors['white-1']} p={'md'}>
|
||||
// <JudulList
|
||||
// title='List Pelayanan Telunjuk Sakti Desa'
|
||||
// href='/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/create'
|
||||
// />
|
||||
// <Table striped withTableBorder withRowBorders>
|
||||
// <TableThead>
|
||||
// <TableTr>
|
||||
// <TableTh>Nama</TableTh>
|
||||
// <TableTh>Link</TableTh>
|
||||
// <TableTh>Detail</TableTh>
|
||||
// </TableTr>
|
||||
// </TableThead>
|
||||
// <TableTbody>
|
||||
// {filteredData.map((item) => (
|
||||
// <TableTr key={item.id}>
|
||||
// <TableTd>
|
||||
// <Box w={100}>
|
||||
// <Text truncate="end" lineClamp={1} fz={"sm"} dangerouslySetInnerHTML={{ __html: item.name }} />
|
||||
// </Box>
|
||||
// </TableTd>
|
||||
// <TableTd>
|
||||
// <Box w={100}>
|
||||
// <a href={item.link} target="_blank" rel="noopener noreferrer">
|
||||
// <Text dangerouslySetInnerHTML={{ __html: item.deskripsi }} truncate="end" fz={"sm"} />
|
||||
// </a>
|
||||
// </Box>
|
||||
// </TableTd>
|
||||
// <TableTd>
|
||||
// <Text>
|
||||
// <Button onClick={() => router.push(`/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/${item.id}`)}>
|
||||
// <IconDeviceImac size={20} />
|
||||
// </Button>
|
||||
// </Text>
|
||||
// </TableTd>
|
||||
// </TableTr>
|
||||
// ))}
|
||||
// </TableTbody>
|
||||
// </Table>
|
||||
// </Paper>
|
||||
// <Center>
|
||||
// <Pagination
|
||||
// value={page}
|
||||
// onChange={(newPage) => {
|
||||
// load(newPage, 10);
|
||||
// window.scrollTo(0, 0);
|
||||
// }}
|
||||
// total={totalPages}
|
||||
// mt="md"
|
||||
// mb="md"
|
||||
// />
|
||||
// </Center>
|
||||
// </Box>
|
||||
// );
|
||||
// }
|
||||
|
||||
// export default PelayananTelunjukSakti;
|
||||
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
|
||||
@@ -174,8 +18,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -225,7 +68,6 @@ function ListPelayananTelunjukSakti({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Pelayanan Telunjuk Sakti</Title>
|
||||
<Tooltip label="Tambah Layanan" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -236,7 +78,6 @@ function ListPelayananTelunjukSakti({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
<Box style={{ overflowX: 'auto' }}>
|
||||
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
||||
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
@@ -102,11 +101,9 @@ function EditPenghargaan() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Tombol Back + Title */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Penghargaan
|
||||
</Title>
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
'use client'
|
||||
import React, { useState } from 'react';
|
||||
import penghargaanState from '../../../_state/desa/penghargaan';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import colors from '@/con/colors';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -12,12 +8,15 @@ import {
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Tooltip,
|
||||
Text
|
||||
} from '@mantine/core';
|
||||
import colors from '@/con/colors';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||
import penghargaanState from '../../../_state/desa/penghargaan';
|
||||
|
||||
function DetailPenghargaan() {
|
||||
const statePenghargaan = useProxy(penghargaanState);
|
||||
@@ -127,34 +126,30 @@ function DetailPenghargaan() {
|
||||
</Box>
|
||||
|
||||
<Group gap="sm" mt={10}>
|
||||
<Tooltip label="Hapus Penghargaan" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
|
||||
<Tooltip label="Edit Penghargaan" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
router.push(`/admin/desa/penghargaan/${data.id}/edit`)
|
||||
}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
router.push(`/admin/desa/penghargaan/${data.id}/edit`)
|
||||
}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
@@ -66,11 +65,9 @@ function CreatePenghargaan() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Penghargaan
|
||||
</Title>
|
||||
|
||||
@@ -18,8 +18,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -69,7 +68,6 @@ function ListPenghargaan({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>List Penghargaan</Title>
|
||||
<Tooltip label="Tambah Penghargaan" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -78,7 +76,6 @@ function ListPenghargaan({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
<Box style={{ overflowX: 'auto' }}>
|
||||
<Table highlightOnHover>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||
import { IconCategory, IconListDetails } from '@tabler/icons-react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { IconListDetails, IconCategory } from '@tabler/icons-react';
|
||||
|
||||
function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter()
|
||||
@@ -14,15 +14,13 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||
label: "List Pengumuman",
|
||||
value: "listpengumuman",
|
||||
href: "/admin/desa/pengumuman/list-pengumuman",
|
||||
icon: <IconListDetails size={18} stroke={1.8} />,
|
||||
tooltip: "Lihat semua daftar pengumuman"
|
||||
icon: <IconListDetails size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Kategori Pengumuman",
|
||||
value: "kategoripengumuman",
|
||||
href: "/admin/desa/pengumuman/kategori-pengumuman",
|
||||
icon: <IconCategory size={18} stroke={1.8} />,
|
||||
tooltip: "Kelola kategori pengumuman"
|
||||
icon: <IconCategory size={18} stroke={1.8} />
|
||||
},
|
||||
];
|
||||
|
||||
@@ -70,19 +68,18 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
{tabs.map((tab, i) => (
|
||||
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
|
||||
<TabsTab
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
</Tooltip>
|
||||
<TabsTab
|
||||
key={i}
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
))}
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -74,7 +73,6 @@ function EditKategoriPengumuman() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -83,7 +81,6 @@ function EditKategoriPengumuman() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Kategori Pengumuman
|
||||
</Title>
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -35,7 +34,6 @@ function CreateKategoriPengumuman() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header dengan back button */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -44,7 +42,6 @@ function CreateKategoriPengumuman() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Kategori Pengumuman
|
||||
</Title>
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import {
|
||||
Box, Button, Center, Paper, Skeleton, Stack,
|
||||
Box, Button, Center,
|
||||
Pagination,
|
||||
Paper, Skeleton, Stack,
|
||||
Table, TableTbody, TableTd, TableTh, TableThead, TableTr,
|
||||
Text, Title, Tooltip, Pagination
|
||||
Text, Title
|
||||
} from '@mantine/core';
|
||||
import { IconEdit, IconSearch, IconTrash, IconPlus } from '@tabler/icons-react';
|
||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
@@ -66,16 +68,14 @@ function ListKategoriPengumuman({ search }: { search: string }) {
|
||||
<Stack>
|
||||
<Box style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 15 }}>
|
||||
<Title order={4}>List Kategori Pengumuman</Title>
|
||||
<Tooltip label="Tambah Kategori Pengumuman" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/desa/pengumuman/kategori-pengumuman/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/desa/pengumuman/kategori-pengumuman/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Box style={{ overflowX: 'auto' }}>
|
||||
@@ -99,29 +99,25 @@ function ListKategoriPengumuman({ search }: { search: string }) {
|
||||
<Text truncate lineClamp={1}>{item.name}</Text>
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
<Tooltip label="Edit Kategori Pengumuman" withArrow>
|
||||
<Button
|
||||
variant='light'
|
||||
color='green'
|
||||
onClick={() => router.push(`/admin/desa/pengumuman/kategori-pengumuman/${item.id}`)}
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant='light'
|
||||
color='green'
|
||||
onClick={() => router.push(`/admin/desa/pengumuman/kategori-pengumuman/${item.id}`)}
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
<Tooltip label="Hapus Kategori Pengumuman" withArrow>
|
||||
<Button
|
||||
variant='light'
|
||||
color='red'
|
||||
disabled={listDataState.delete.loading}
|
||||
onClick={() => {
|
||||
setSelectedId(item.id)
|
||||
setModalHapus(true)
|
||||
}}>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant='light'
|
||||
color='red'
|
||||
disabled={listDataState.delete.loading}
|
||||
onClick={() => {
|
||||
setSelectedId(item.id)
|
||||
setModalHapus(true)
|
||||
}}>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
))
|
||||
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from "@mantine/core";
|
||||
import { IconArrowBack } from "@tabler/icons-react";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
@@ -85,16 +84,14 @@ function EditPengumuman() {
|
||||
return (
|
||||
<Box px={{ base: "sm", md: "lg" }} py="md">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Pengumuman
|
||||
</Title>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
|
||||
import colors from '@/con/colors';
|
||||
import {
|
||||
Box,
|
||||
@@ -8,16 +10,13 @@ import {
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Tooltip,
|
||||
Text
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useRouter, useParams } from 'next/navigation';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
|
||||
|
||||
export default function DetailPengumuman() {
|
||||
const pengumumanState = useProxy(stateDesaPengumuman);
|
||||
@@ -117,7 +116,6 @@ export default function DetailPengumuman() {
|
||||
</Box>
|
||||
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Pengumuman" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
@@ -130,9 +128,7 @@ export default function DetailPengumuman() {
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label="Edit Pengumuman" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
@@ -146,7 +142,6 @@ export default function DetailPengumuman() {
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
@@ -47,11 +46,9 @@ function CreatePengumuman() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Pengumuman
|
||||
</Title>
|
||||
|
||||
@@ -17,8 +17,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
|
||||
@@ -69,16 +68,14 @@ function ListPengumuman({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Pengumuman</Title>
|
||||
<Tooltip label="Tambah Pengumuman" withArrow>
|
||||
<Button
|
||||
leftSection={<IconCircleDashedPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/desa/pengumuman/list-pengumuman/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
leftSection={<IconCircleDashedPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/desa/pengumuman/list-pengumuman/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Group>
|
||||
<Box style={{ overflowX: 'auto' }}>
|
||||
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||
import { IconCategory, IconListCheck } from '@tabler/icons-react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@@ -14,15 +14,13 @@ function LayoutTabsPotensi({ children }: { children: React.ReactNode }) {
|
||||
label: "List Potensi",
|
||||
value: "list_potensi",
|
||||
href: "/admin/desa/potensi/list-potensi",
|
||||
icon: <IconListCheck size={18} stroke={1.8} />,
|
||||
tooltip: "Lihat semua potensi desa"
|
||||
icon: <IconListCheck size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Kategori Potensi",
|
||||
value: "kategori_potensi",
|
||||
href: "/admin/desa/potensi/kategori-potensi",
|
||||
icon: <IconCategory size={18} stroke={1.8} />,
|
||||
tooltip: "Kelola kategori potensi"
|
||||
icon: <IconCategory size={18} stroke={1.8} />
|
||||
},
|
||||
];
|
||||
|
||||
@@ -70,19 +68,18 @@ function LayoutTabsPotensi({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
{tabs.map((tab, i) => (
|
||||
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
|
||||
<TabsTab
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
</Tooltip>
|
||||
<TabsTab
|
||||
key={i}
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
))}
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -76,7 +75,6 @@ function EditKategoriPotensi() {
|
||||
return (
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -85,7 +83,6 @@ function EditKategoriPotensi() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Kategori Potensi
|
||||
</Title>
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -35,7 +34,6 @@ function CreateKategoriPotensi() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header dengan back button */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -44,7 +42,6 @@ function CreateKategoriPotensi() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Kategori Potensi
|
||||
</Title>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title, Tooltip, Pagination, Group } from '@mantine/core';
|
||||
import { IconEdit, IconSearch, IconTrash, IconPlus } from '@tabler/icons-react';
|
||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import HeaderSearch from '../../../_com/header';
|
||||
import potensiDesaState from '../../../_state/desa/potensi';
|
||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||
import potensiDesaState from '../../../_state/desa/potensi';
|
||||
|
||||
function KategoriPotensi() {
|
||||
const [search, setSearch] = useState('');
|
||||
@@ -62,7 +62,6 @@ function ListKategoriPotensi({ search }: { search: string }) {
|
||||
<Stack>
|
||||
<Group justify="space-between">
|
||||
<Title order={4}>List Kategori Potensi</Title>
|
||||
<Tooltip label="Tambah Kategori Potensi" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -71,7 +70,6 @@ function ListKategoriPotensi({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
|
||||
<Box style={{ overflowX: 'auto' }}>
|
||||
|
||||
@@ -15,8 +15,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from "@mantine/core";
|
||||
import { Dropzone } from "@mantine/dropzone";
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from "@tabler/icons-react";
|
||||
@@ -122,7 +121,6 @@ function EditPotensi() {
|
||||
return (
|
||||
<Box px={{ base: "sm", md: "lg" }} py="md">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -131,7 +129,6 @@ function EditPotensi() {
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Potensi Desa
|
||||
</Title>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useRouter, useParams } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
export default function DetailPotensi() {
|
||||
const router = useRouter();
|
||||
@@ -108,7 +108,6 @@ export default function DetailPotensi() {
|
||||
</Box>
|
||||
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Potensi" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
@@ -121,9 +120,7 @@ export default function DetailPotensi() {
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label="Edit Potensi" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
@@ -135,7 +132,6 @@ export default function DetailPotensi() {
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -14,8 +14,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
@@ -72,11 +71,9 @@ function CreatePotensi() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Potensi Desa
|
||||
</Title>
|
||||
|
||||
@@ -18,8 +18,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -76,7 +75,6 @@ function ListPotensi({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Potensi Desa</Title>
|
||||
<Tooltip label="Tambah Potensi" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -85,7 +83,6 @@ function ListPotensi({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
<Box style={{ overflowX: "auto" }}>
|
||||
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||
import { IconCalendar, IconUser, IconUsers } from '@tabler/icons-react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { IconUser, IconUsers, IconCalendar } from '@tabler/icons-react';
|
||||
|
||||
function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter()
|
||||
@@ -14,22 +14,19 @@ function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
|
||||
label: "Profile Desa",
|
||||
value: "profiledesa",
|
||||
href: "/admin/desa/profile/profile-desa",
|
||||
icon: <IconUser size={18} stroke={1.8} />,
|
||||
tooltip: "Lihat dan kelola profil desa"
|
||||
icon: <IconUser size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Profile Perbekel",
|
||||
value: "profileperbekel",
|
||||
href: "/admin/desa/profile/profile-perbekel",
|
||||
icon: <IconUsers size={18} stroke={1.8} />,
|
||||
tooltip: "Kelola data Perbekel"
|
||||
icon: <IconUsers size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Profile Perbekel Dari Masa Ke Masa",
|
||||
value: "profile-perbekel-dari-masa-ke-masa",
|
||||
href: "/admin/desa/profile/profile-perbekel-dari-masa-ke-masa",
|
||||
icon: <IconCalendar size={18} stroke={1.8} />,
|
||||
tooltip: "Riwayat Perbekel dari masa ke masa"
|
||||
icon: <IconCalendar size={18} stroke={1.8} />
|
||||
}
|
||||
];
|
||||
|
||||
@@ -76,42 +73,41 @@ function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
|
||||
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
||||
}}
|
||||
>
|
||||
{tabs.map((tab, i) => (
|
||||
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
|
||||
<TabsTab
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
</Tooltip>
|
||||
))}
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
|
||||
{tabs.map((tab, i) => (
|
||||
<TabsPanel
|
||||
<TabsTab
|
||||
key={i}
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
padding: "1.5rem",
|
||||
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
|
||||
borderRadius: "1rem",
|
||||
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{/* Konten dummy, bisa diganti sesuai routing */}
|
||||
<>{children}</>
|
||||
</TabsPanel>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
))}
|
||||
</Tabs>
|
||||
</Stack>
|
||||
);
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
|
||||
{tabs.map((tab, i) => (
|
||||
<TabsPanel
|
||||
key={i}
|
||||
value={tab.value}
|
||||
style={{
|
||||
padding: "1.5rem",
|
||||
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
|
||||
borderRadius: "1rem",
|
||||
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
|
||||
}}
|
||||
>
|
||||
{/* Konten dummy, bisa diganti sesuai routing */}
|
||||
<>{children}</>
|
||||
</TabsPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default LayoutTabsDetail;
|
||||
export default LayoutTabsDetail;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -99,11 +99,9 @@ function Page() {
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">Edit Lambang Desa</Title>
|
||||
</Group>
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import ApiFetch from '@/lib/api-fetch';
|
||||
import { Box, Button, Group, Image, Paper, SimpleGrid, Stack, Text, TextInput, Title, Tooltip, Center, Alert } from '@mantine/core';
|
||||
import { Alert, Box, Button, Center, Group, Image, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX, IconAlertCircle } from '@tabler/icons-react';
|
||||
import { IconAlertCircle, IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -161,11 +161,9 @@ function Page() {
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">Edit Maskot Desa</Title>
|
||||
</Group>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -100,11 +100,9 @@ function Page() {
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">Edit Sejarah Desa</Title>
|
||||
</Group>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, Title } from '@mantine/core';
|
||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -100,11 +100,11 @@ function Page() {
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">Edit Visi Misi Desa</Title>
|
||||
</Group>
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use client'
|
||||
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Card, Center, Divider, Grid, GridCol, Image, Paper, SimpleGrid, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { useSnapshot } from 'valtio';
|
||||
import stateProfileDesa from '../../../_state/desa/profile';
|
||||
import { useEffect } from 'react';
|
||||
import { Box, Button, Card, Center, Divider, Grid, GridCol, Image, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
|
||||
import { IconEdit } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
import { useSnapshot } from 'valtio';
|
||||
import stateProfileDesa from '../../../_state/desa/profile';
|
||||
|
||||
function Page() {
|
||||
const router = useRouter();
|
||||
@@ -37,7 +37,6 @@ function Page() {
|
||||
<Title order={3} c={colors['blue-button']}>Preview Sejarah Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Sejarah Desa" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
@@ -47,7 +46,6 @@ function Page() {
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
@@ -84,7 +82,6 @@ function Page() {
|
||||
<Title order={3} c={colors['blue-button']}>Preview Visi Misi Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Visi Misi Desa" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
@@ -94,7 +91,6 @@ function Page() {
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
@@ -134,7 +130,6 @@ function Page() {
|
||||
<Title order={3} c={colors['blue-button']}>Preview Lambang Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Lambang Desa" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
@@ -144,7 +139,6 @@ function Page() {
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
@@ -181,7 +175,6 @@ function Page() {
|
||||
<Title order={3} c={colors['blue-button']}>Preview Maskot Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Maskot Desa" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
@@ -191,7 +184,6 @@ function Page() {
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
@@ -97,11 +96,9 @@ function EditPerbekelDariMasaKeMasa() {
|
||||
return (
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Perbekel Dari Masa Ke Masa
|
||||
</Title>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -98,7 +98,6 @@ function DetailPerbekelDariMasa() {
|
||||
</Box>
|
||||
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Perbekel" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
@@ -111,9 +110,7 @@ function DetailPerbekelDariMasa() {
|
||||
>
|
||||
<IconX size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label="Edit Perbekel" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/desa/profile/profile-perbekel-dari-masa-ke-masa/${data.id}/edit`)}
|
||||
@@ -123,7 +120,6 @@ function DetailPerbekelDariMasa() {
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import ApiFetch from '@/lib/api-fetch';
|
||||
import { Box, Button, Group, Image, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -50,11 +50,9 @@ function CreatePerbekelDariMasaKeMasa() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Back button + Title */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Create Perbekel Dari Masa Ke Masa
|
||||
</Title>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -49,7 +49,6 @@ function ListPerbekelDariMasaKeMasa({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||
<Group justify='space-between' mb="md">
|
||||
<Title order={4}>List Perbekel Dari Masa Ke Masa</Title>
|
||||
<Tooltip label="Tambah Perbekel Baru" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
@@ -58,7 +57,6 @@ function ListPerbekelDariMasaKeMasa({ search }: { search: string }) {
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
|
||||
<Box style={{ overflowX: "auto" }}>
|
||||
|
||||
@@ -4,9 +4,9 @@ import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import ApiFetch from '@/lib/api-fetch';
|
||||
import { Box, Button, Center, Group, Image, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Center, Group, Image, Paper, Stack, Text, Title } from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX, IconImageInPicture } from '@tabler/icons-react';
|
||||
import { IconArrowBack, IconImageInPicture, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -101,11 +101,9 @@ function ProfilePerbekel() {
|
||||
<Stack gap="xs">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Profil Perbekel
|
||||
</Title>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Divider, Grid, GridCol, Image, Paper, Skeleton, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Center, Divider, Grid, GridCol, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||
import { IconEdit } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
@@ -36,7 +36,6 @@ function Page() {
|
||||
<Title order={3} c={colors['blue-button']}>Preview Profil PPID</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Profil Perbekel" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
@@ -46,7 +45,6 @@ function Page() {
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { BarChart } from '@mantine/charts';
|
||||
@@ -85,7 +86,7 @@ function ListDemografiPekerjaan({ search }: { search: string }) {
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setChartData(
|
||||
data.map((item) => ({
|
||||
data.map((item: any) => ({
|
||||
id: item.id,
|
||||
pekerjaan: item.pekerjaan,
|
||||
lakiLaki: Number(item.lakiLaki),
|
||||
|
||||
@@ -24,8 +24,7 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
|
||||
label: "Produk Pasar Desa",
|
||||
value: "produkpasardesa",
|
||||
href: "/admin/ekonomi/pasar-desa/produk-pasar-desa",
|
||||
icon: <IconShoppingBag size={18} stroke={1.8} />,
|
||||
tooltip: "Kelola data produk yang ada di pasar desa",
|
||||
icon: <IconShoppingBag size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Kategori Produk",
|
||||
|
||||
@@ -55,9 +55,9 @@ function EditProgramKemiskinan() {
|
||||
useEffect(() => {
|
||||
if (!id) return;
|
||||
|
||||
stateProgram.findUnique
|
||||
.load(id)
|
||||
.then(() => {
|
||||
const loadData = async () => {
|
||||
try {
|
||||
await stateProgram.findUnique.load(id);
|
||||
const data = stateProgram.findUnique.data;
|
||||
if (data) {
|
||||
setFormData({
|
||||
@@ -70,12 +70,16 @@ function EditProgramKemiskinan() {
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
} catch (err) {
|
||||
console.error('Error load data:', err);
|
||||
toast.error('Gagal mengambil data program');
|
||||
});
|
||||
}, [id, stateProgram.findUnique]);
|
||||
}
|
||||
};
|
||||
|
||||
loadData();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [id]); // ✅ hanya trigger saat id berubah
|
||||
|
||||
|
||||
// generic handler untuk field top-level
|
||||
const handleChange = useCallback(
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
Box,
|
||||
Button,
|
||||
Group,
|
||||
Image,
|
||||
Paper,
|
||||
Stack,
|
||||
Text,
|
||||
@@ -21,6 +20,7 @@ import { useProxy } from 'valtio/utils';
|
||||
import CreateEditor from '../../../_com/createEditor';
|
||||
import desaDigitalState from '../../../_state/inovasi/desa-digital';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import ExifOrientationImg from 'react-exif-orientation-img';
|
||||
|
||||
export default function CreateDesaDigital() {
|
||||
const stateDesaDigital = useProxy(desaDigitalState);
|
||||
@@ -173,17 +173,16 @@ export default function CreateDesaDigital() {
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src={previewImage}
|
||||
alt="Preview"
|
||||
radius="md"
|
||||
style={{
|
||||
maxHeight: 220,
|
||||
objectFit: 'cover',
|
||||
border: '1px solid #e0e0e0',
|
||||
}}
|
||||
loading="lazy"
|
||||
/>
|
||||
<ExifOrientationImg
|
||||
src={previewImage}
|
||||
alt="Preview"
|
||||
style={{
|
||||
maxHeight: 220,
|
||||
objectFit: 'cover',
|
||||
border: '1px solid #e0e0e0',
|
||||
borderRadius: 12,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -54,8 +54,8 @@ function DetailInfoTeknologiTepatGuna() {
|
||||
{/* Card Utama */}
|
||||
<Paper
|
||||
withBorder
|
||||
w={{ base: "100%", md: "70%", lg: "60%" }}
|
||||
bg="#ECEEF8"
|
||||
w={{ base: "100%", md: "50%" }}
|
||||
bg={colors['white-1']}
|
||||
p="lg"
|
||||
radius="md"
|
||||
shadow="sm"
|
||||
@@ -65,7 +65,7 @@ function DetailInfoTeknologiTepatGuna() {
|
||||
Detail Info Teknologi Tepat Guna
|
||||
</Text>
|
||||
|
||||
<Paper bg={colors['BG-trans']} p="md" radius="md" shadow="xs">
|
||||
<Paper bg="#ECEEF8" p="md" radius="md" shadow="xs">
|
||||
<Stack gap="sm">
|
||||
<Box>
|
||||
<Text fz="lg" fw="bold">Judul</Text>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import { IconKey } from '@/app/admin/(dashboard)/_com/iconMap';
|
||||
import programKreatifState from '@/app/admin/(dashboard)/_state/inovasi/program-kreatif';
|
||||
import colors from '@/con/colors';
|
||||
import {
|
||||
@@ -11,8 +12,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -20,7 +20,6 @@ import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import SelectIconProgramEdit from '../../../../_com/selectIconEdit';
|
||||
import { IconKey } from '@/app/admin/(dashboard)/_com/iconMap';
|
||||
|
||||
interface FormProgramKreatif {
|
||||
name: string;
|
||||
@@ -41,6 +40,15 @@ function EditProgramKreatifDesa() {
|
||||
icon: '',
|
||||
});
|
||||
|
||||
const [originalData, setOriginalData] = useState<FormProgramKreatif>({
|
||||
name: '',
|
||||
deskripsi: '',
|
||||
slug: '',
|
||||
icon: '',
|
||||
});
|
||||
|
||||
const [isDataChanged, setIsDataChanged] = useState(false);
|
||||
|
||||
// Load data hanya sekali berdasarkan params.id
|
||||
useEffect(() => {
|
||||
const loadProgramKreatif = async () => {
|
||||
@@ -51,12 +59,14 @@ function EditProgramKreatifDesa() {
|
||||
const data = await stateProgramKreatif.update.load(id);
|
||||
if (data) {
|
||||
stateProgramKreatif.update.id = id;
|
||||
setFormData({
|
||||
const loadedData = {
|
||||
name: data.name || '',
|
||||
slug: data.slug || '',
|
||||
deskripsi: data.deskripsi || '',
|
||||
icon: data.icon || '',
|
||||
});
|
||||
};
|
||||
setFormData(loadedData);
|
||||
setOriginalData(loadedData);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading program kreatif:', error);
|
||||
@@ -67,12 +77,49 @@ function EditProgramKreatifDesa() {
|
||||
loadProgramKreatif();
|
||||
}, [params?.id]);
|
||||
|
||||
// Deteksi perubahan data
|
||||
useEffect(() => {
|
||||
const hasChanged =
|
||||
formData.name !== originalData.name ||
|
||||
formData.slug !== originalData.slug ||
|
||||
formData.deskripsi !== originalData.deskripsi ||
|
||||
formData.icon !== originalData.icon;
|
||||
|
||||
setIsDataChanged(hasChanged);
|
||||
}, [formData, originalData]);
|
||||
|
||||
// Prevent browser back/refresh jika ada perubahan
|
||||
useEffect(() => {
|
||||
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
||||
if (isDataChanged) {
|
||||
e.preventDefault();
|
||||
e.returnValue = '';
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||
return () => window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||
}, [isDataChanged]);
|
||||
|
||||
const handleChange =
|
||||
(field: keyof FormProgramKreatif) =>
|
||||
(value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
};
|
||||
|
||||
const handleBackClick = () => {
|
||||
if (isDataChanged) {
|
||||
const confirmed = window.confirm(
|
||||
'Anda memiliki perubahan yang belum disimpan. Apakah Anda yakin ingin keluar dari halaman ini? Semua perubahan akan hilang.'
|
||||
);
|
||||
if (confirmed) {
|
||||
router.back();
|
||||
}
|
||||
} else {
|
||||
router.back();
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
stateProgramKreatif.update.form = {
|
||||
@@ -82,6 +129,11 @@ function EditProgramKreatifDesa() {
|
||||
icon: formData.icon.trim(),
|
||||
};
|
||||
await stateProgramKreatif.update.submit();
|
||||
|
||||
// Reset isDataChanged agar tidak muncul konfirmasi setelah save
|
||||
setOriginalData(formData);
|
||||
setIsDataChanged(false);
|
||||
|
||||
router.push('/admin/inovasi/program-kreatif-desa');
|
||||
} catch (error) {
|
||||
console.error('Error updating program kreatif:', error);
|
||||
@@ -92,16 +144,14 @@ function EditProgramKreatifDesa() {
|
||||
return (
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={handleBackClick}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Program Kreatif Desa
|
||||
</Title>
|
||||
@@ -172,4 +222,4 @@ function EditProgramKreatifDesa() {
|
||||
);
|
||||
}
|
||||
|
||||
export default EditProgramKreatifDesa;
|
||||
export default EditProgramKreatifDesa;
|
||||
@@ -32,10 +32,14 @@ function CreateProgramKreatifDesa() {
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
await stateCreate.create.create();
|
||||
resetForm();
|
||||
router.push("/admin/inovasi/program-kreatif-desa");
|
||||
const success = await stateCreate.create.create();
|
||||
|
||||
if (success) {
|
||||
resetForm();
|
||||
router.push("/admin/inovasi/program-kreatif-desa");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
IconArrowBack,
|
||||
@@ -116,16 +115,14 @@ function EditKeamananLingkungan() {
|
||||
<Box px={{ base: "sm", md: "lg" }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Keamanan Lingkungan
|
||||
</Title>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -93,36 +93,32 @@ function DetailKeamananLingkungan() {
|
||||
|
||||
{/* Aksi */}
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Data" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
|
||||
<Tooltip label="Edit Data" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
router.push(
|
||||
`/admin/keamanan/keamanan-lingkungan-pecalang-patwal/${data.id}/edit`
|
||||
)
|
||||
}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
router.push(
|
||||
`/admin/keamanan/keamanan-lingkungan-pecalang-patwal/${data.id}/edit`
|
||||
)
|
||||
}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import {
|
||||
@@ -71,16 +70,14 @@ function CreateKeamananLingkungan() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Data Keamanan Lingkungan
|
||||
</Title>
|
||||
|
||||
@@ -16,8 +16,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
@@ -78,18 +77,16 @@ function ListKeamananLingkungan({ search }: { search: string }) {
|
||||
{/* Judul + Tombol Tambah */}
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Keamanan Lingkungan</Title>
|
||||
<Tooltip label="Tambah Data Keamanan" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() =>
|
||||
router.push('/admin/keamanan/keamanan-lingkungan-pecalang-patwal/create')
|
||||
}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() =>
|
||||
router.push('/admin/keamanan/keamanan-lingkungan-pecalang-patwal/create')
|
||||
}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
{/* Tabel */}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||
import { IconPhone, IconTag } from '@tabler/icons-react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@@ -15,15 +15,13 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
|
||||
label: "Kontak Darurat Keamanan",
|
||||
value: "kontak-darurat-keamanan",
|
||||
href: "/admin/keamanan/kontak-darurat/kontak-darurat-keamanan",
|
||||
icon: <IconPhone size={18} stroke={1.8} />,
|
||||
tooltip: "Lihat dan kelola kontak darurat keamanan",
|
||||
icon: <IconPhone size={18} stroke={1.8} />
|
||||
},
|
||||
{
|
||||
label: "Kontak Darurat Item",
|
||||
value: "kontak-darurat-item",
|
||||
href: "/admin/keamanan/kontak-darurat/kontak-darurat-item",
|
||||
icon: <IconTag size={18} stroke={1.8} />,
|
||||
tooltip: "Kelola data kontak darurat item",
|
||||
icon: <IconTag size={18} stroke={1.8} />
|
||||
}
|
||||
];
|
||||
|
||||
@@ -73,19 +71,18 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
|
||||
}}
|
||||
>
|
||||
{tabs.map((tab, i) => (
|
||||
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
|
||||
<TabsTab
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
</Tooltip>
|
||||
<TabsTab
|
||||
key={i}
|
||||
value={tab.value}
|
||||
leftSection={tab.icon}
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: "0.9rem",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
{tab.label}
|
||||
</TabsTab>
|
||||
))}
|
||||
</TabsList>
|
||||
</ScrollArea>
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -86,11 +85,9 @@ function EditKontakItem() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Kontak Darurat Item
|
||||
</Title>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { IconKey, IconMapper } from '@/app/admin/(dashboard)/_com/iconMap';
|
||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||
import kontakDarurat from '@/app/admin/(dashboard)/_state/keamanan/kontak-darurat-keamanan';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -92,32 +92,28 @@ function DetailKontakDarurat() {
|
||||
|
||||
{/* Aksi */}
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Data" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
|
||||
<Tooltip label="Edit Data" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/keamanan/kontak-darurat/kontak-darurat-item/${data.id}/edit`)}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/keamanan/kontak-darurat/kontak-darurat-item/${data.id}/edit`)}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -38,16 +37,14 @@ function CreateKontakItem() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Kontak Darurat Item
|
||||
</Title>
|
||||
|
||||
@@ -16,8 +16,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
@@ -79,16 +78,14 @@ function ListKontakItem({ search }: { search: string }) {
|
||||
{/* Judul + Tombol Tambah */}
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Kontak Darurat Item</Title>
|
||||
<Tooltip label="Tambah Kontak Item" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/keamanan/kontak-darurat/kontak-darurat-item/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/keamanan/kontak-darurat/kontak-darurat-item/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
{/* Tabel */}
|
||||
|
||||
@@ -14,8 +14,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from "@mantine/core";
|
||||
import { IconArrowBack } from "@tabler/icons-react";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
@@ -42,7 +41,7 @@ function EditKontakDaruratKeamanan() {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
await kontakDarurat.kontakDaruratItem.findMany.load();
|
||||
|
||||
|
||||
const id = params?.id as string;
|
||||
if (id) {
|
||||
const data = await kontakState.update.load(id);
|
||||
@@ -88,16 +87,14 @@ function EditKontakDaruratKeamanan() {
|
||||
<Box px={{ base: "sm", md: "lg" }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Kontak Darurat Keamanan
|
||||
</Title>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { IconKey, IconMapper } from '@/app/admin/(dashboard)/_com/iconMap';
|
||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||
import kontakDarurat from '@/app/admin/(dashboard)/_state/keamanan/kontak-darurat-keamanan';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -108,32 +108,28 @@ function DetailKontakDaruratKeamanan() {
|
||||
|
||||
{/* Aksi */}
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Data" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
|
||||
<Tooltip label="Edit Data" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/keamanan/kontak-darurat/kontak-darurat-keamanan/${data.id}/edit`)}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/keamanan/kontak-darurat/kontak-darurat-keamanan/${data.id}/edit`)}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -11,8 +11,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
@@ -45,16 +44,14 @@ function CreateKontakDaruratKeamanan() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Kontak Darurat Keamanan
|
||||
</Title>
|
||||
|
||||
@@ -16,8 +16,7 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
@@ -79,16 +78,14 @@ function ListKontakDaruratKeamanan({ search }: { search: string }) {
|
||||
{/* Judul + Tombol Tambah */}
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Kontak Darurat Keamanan</Title>
|
||||
<Tooltip label="Tambah Kontak Darurat Keamanan" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/keamanan/kontak-darurat/kontak-darurat-keamanan/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/keamanan/kontak-darurat/kontak-darurat-keamanan/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
{/* Tabel */}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import laporanPublikState from '@/app/admin/(dashboard)/_state/keamanan/laporan-publik';
|
||||
@@ -11,8 +12,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { DateTimePicker } from '@mantine/dates';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
@@ -48,29 +48,29 @@ function EditLaporanPublik() {
|
||||
const loadLaporanPublik = async () => {
|
||||
const id = params?.id as string;
|
||||
if (!id) return;
|
||||
|
||||
|
||||
try {
|
||||
const data = await stateLaporan.edit.load(id);
|
||||
if (data) {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
judul: data.judul ?? prev.judul,
|
||||
lokasi: data.lokasi ?? prev.lokasi,
|
||||
tanggalWaktu: data.tanggalWaktu ?? prev.tanggalWaktu,
|
||||
status: (data.status as Status) ?? prev.status,
|
||||
penanganan: data.penanganan?.[0]?.deskripsi ?? prev.penanganan,
|
||||
kronologi: data.kronologi ?? prev.kronologi,
|
||||
}));
|
||||
setFormData({
|
||||
judul: data.judul ?? '',
|
||||
lokasi: data.lokasi ?? '',
|
||||
tanggalWaktu: data.tanggalWaktu ?? '',
|
||||
status: (data.status as Status) ?? 'Proses',
|
||||
penanganan: data.penanganan?.[0]?.deskripsi ?? '',
|
||||
kronologi: data.kronologi ?? '',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading laporan publik:", error);
|
||||
toast.error("Gagal mengambil data laporan publik");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
loadLaporanPublik();
|
||||
}, [params?.id, stateLaporan.edit]);
|
||||
|
||||
}, [params?.id]);
|
||||
|
||||
|
||||
|
||||
const handleChange = (field: string, value: string | Status) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
@@ -96,11 +96,9 @@ function EditLaporanPublik() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Laporan Publik
|
||||
</Title>
|
||||
|
||||
@@ -7,16 +7,15 @@ import {
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Tooltip,
|
||||
Text
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import laporanPublikState from '../../../_state/keamanan/laporan-publik';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||
import laporanPublikState from '../../../_state/keamanan/laporan-publik';
|
||||
|
||||
function DetailLaporanPublik() {
|
||||
const [modalHapus, setModalHapus] = useState(false);
|
||||
@@ -102,12 +101,12 @@ function DetailLaporanPublik() {
|
||||
padding: '4px 12px',
|
||||
borderRadius: '16px',
|
||||
backgroundColor:
|
||||
data.status === 'Selesai' ? '#94EF95FF' :
|
||||
data.status === 'Proses' ? '#F1D295FF' :
|
||||
data.status === 'Selesai' ? '#94EF95FF' :
|
||||
data.status === 'Proses' ? '#F1D295FF' :
|
||||
'#F38E8EFF',
|
||||
color:
|
||||
data.status === 'Selesai' ? '#01BA01FF' :
|
||||
data.status === 'Proses' ? '#B67A00FF' :
|
||||
data.status === 'Selesai' ? '#01BA01FF' :
|
||||
data.status === 'Proses' ? '#B67A00FF' :
|
||||
'#AE1700FF',
|
||||
fontWeight: 900,
|
||||
fontSize: '0.75rem',
|
||||
@@ -146,35 +145,31 @@ function DetailLaporanPublik() {
|
||||
|
||||
{/* Tombol Aksi */}
|
||||
<Group gap="sm" mt="sm">
|
||||
<Tooltip label="Hapus Laporan Publik" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
disabled={stateLaporan.delete.loading}
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
disabled={stateLaporan.delete.loading}
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
|
||||
<Tooltip label="Edit Laporan Publik" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
router.push(`/admin/keamanan/laporan-publik/${data.id}/edit`)
|
||||
}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() =>
|
||||
router.push(`/admin/keamanan/laporan-publik/${data.id}/edit`)
|
||||
}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { DateTimePicker } from '@mantine/dates';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
@@ -42,11 +41,9 @@ function CreateLaporanPublik() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header with Back Button */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Laporan Publik
|
||||
</Title>
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
Button,
|
||||
Center,
|
||||
Group,
|
||||
Paper,
|
||||
Pagination,
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Table,
|
||||
@@ -16,16 +16,15 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import HeaderSearch from '../../_com/header';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import laporanPublikState from '../../_state/keamanan/laporan-publik';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import HeaderSearch from '../../_com/header';
|
||||
import laporanPublikState from '../../_state/keamanan/laporan-publik';
|
||||
|
||||
function LaporanPublik() {
|
||||
const [search, setSearch] = useState("");
|
||||
@@ -74,16 +73,14 @@ function ListLaporanPublik({ search }: { search: string }) {
|
||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Laporan Publik</Title>
|
||||
<Tooltip label="Tambah Laporan Publik" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/keamanan/laporan-publik/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/keamanan/laporan-publik/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Group>
|
||||
<Box style={{ overflowX: "auto" }}>
|
||||
<Table highlightOnHover>
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
@@ -96,16 +95,14 @@ function EditPencegahanKriminalitas() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Back button + Title */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Pencegahan Kriminalitas
|
||||
</Title>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Flex, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useRouter, useParams } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { Box, Button, Flex, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||
import pencegahanKriminalitasState from '../../../_state/keamanan/pencegahan-kriminalitas';
|
||||
@@ -108,32 +108,28 @@ function DetailPencegahanKriminalitas() {
|
||||
|
||||
{/* Tombol Aksi */}
|
||||
<Flex gap="sm" mt="sm">
|
||||
<Tooltip label="Hapus" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
|
||||
<Tooltip label="Edit" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/keamanan/pencegahan-kriminalitas/${data.id}/edit`)}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/keamanan/pencegahan-kriminalitas/${data.id}/edit`)}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Flex>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -9,17 +9,16 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import CreateEditor from '../../../_com/createEditor';
|
||||
import pencegahanKriminalitasState from '../../../_state/keamanan/pencegahan-kriminalitas';
|
||||
import { useState } from 'react';
|
||||
import { convertYoutubeUrlToEmbed } from '../../../desa/gallery/lib/youtube-utils';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
function CreatePencegahanKriminalitas() {
|
||||
const router = useRouter();
|
||||
@@ -53,7 +52,6 @@ function CreatePencegahanKriminalitas() {
|
||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||
{/* Header Back Button + Title */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
@@ -62,7 +60,6 @@ function CreatePencegahanKriminalitas() {
|
||||
>
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Tambah Pencegahan Kriminalitas
|
||||
</Title>
|
||||
|
||||
@@ -16,16 +16,15 @@ import {
|
||||
TableThead,
|
||||
TableTr,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from '@mantine/core';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import HeaderSearch from '../../_com/header';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import pencegahanKriminalitasState from '../../_state/keamanan/pencegahan-kriminalitas';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import HeaderSearch from '../../_com/header';
|
||||
import pencegahanKriminalitasState from '../../_state/keamanan/pencegahan-kriminalitas';
|
||||
|
||||
function PencegahanKriminalitas() {
|
||||
const [search, setSearch] = useState("");
|
||||
@@ -77,16 +76,14 @@ function ListPencegahanKriminalitas({ search }: { search: string }) {
|
||||
{/* Judul + Tombol Tambah */}
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Daftar Pencegahan Kriminalitas</Title>
|
||||
<Tooltip label="Tambah Program Pencegahan" withArrow>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/keamanan/pencegahan-kriminalitas/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color="blue"
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/keamanan/pencegahan-kriminalitas/create')}
|
||||
>
|
||||
Tambah Baru
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
{/* Tabel */}
|
||||
@@ -106,9 +103,9 @@ function ListPencegahanKriminalitas({ search }: { search: string }) {
|
||||
<TableTr key={item.id}>
|
||||
<TableTd>
|
||||
<Box w={200}>
|
||||
<Text fw={500} truncate="end" lineClamp={1}>
|
||||
{item.judul}
|
||||
</Text>
|
||||
<Text fw={500} truncate="end" lineClamp={1}>
|
||||
{item.judul}
|
||||
</Text>
|
||||
</Box>
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
"use client";
|
||||
|
||||
import polsekTerdekat from "@/app/admin/(dashboard)/_state/keamanan/polsek-terdekat";
|
||||
import colors from "@/con/colors";
|
||||
import {
|
||||
Box,
|
||||
@@ -14,15 +15,13 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
Tooltip,
|
||||
Title
|
||||
} from "@mantine/core";
|
||||
import { IconArrowBack } from "@tabler/icons-react";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { useProxy } from "valtio/utils";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
import polsekTerdekat from "@/app/admin/(dashboard)/_state/keamanan/polsek-terdekat";
|
||||
import { useProxy } from "valtio/utils";
|
||||
|
||||
function EditPolsekTerdekat() {
|
||||
const polsekState = useProxy(polsekTerdekat);
|
||||
@@ -52,36 +51,36 @@ function EditPolsekTerdekat() {
|
||||
layananPolsekId: "",
|
||||
});
|
||||
|
||||
// load data untuk form edit
|
||||
useEffect(() => {
|
||||
const loadPolsekTerdekat = async () => {
|
||||
const id = params?.id as string;
|
||||
if (!id) return;
|
||||
|
||||
try {
|
||||
const data = await polsekState.edit.load(id);
|
||||
if (data) {
|
||||
setFormData({
|
||||
nama: data.nama || "",
|
||||
jarakKeDesa: data.jarakKeDesa || "",
|
||||
alamat: data.alamat || "",
|
||||
nomorTelepon: data.nomorTelepon || "",
|
||||
jamOperasional: data.jamOperasional || "",
|
||||
embedMapUrl: data.embedMapUrl || "",
|
||||
namaTempatMaps: data.namaTempatMaps || "",
|
||||
alamatMaps: data.alamatMaps || "",
|
||||
linkPetunjukArah: data.linkPetunjukArah || "",
|
||||
layananPolsekId: data.layananPolsekId || "",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading polsek terdekat:", error);
|
||||
toast.error("Gagal memuat data polsek terdekat");
|
||||
// load data untuk form edit
|
||||
useEffect(() => {
|
||||
const loadPolsekTerdekat = async () => {
|
||||
const id = params?.id as string;
|
||||
if (!id) return;
|
||||
|
||||
try {
|
||||
const data = await polsekState.edit.load(id);
|
||||
if (data) {
|
||||
setFormData({
|
||||
nama: data.nama || "",
|
||||
jarakKeDesa: data.jarakKeDesa || "",
|
||||
alamat: data.alamat || "",
|
||||
nomorTelepon: data.nomorTelepon || "",
|
||||
jamOperasional: data.jamOperasional || "",
|
||||
embedMapUrl: data.embedMapUrl || "",
|
||||
namaTempatMaps: data.namaTempatMaps || "",
|
||||
alamatMaps: data.alamatMaps || "",
|
||||
linkPetunjukArah: data.linkPetunjukArah || "",
|
||||
layananPolsekId: data.layananPolsekId || "",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
loadPolsekTerdekat();
|
||||
}, [params?.id]);
|
||||
} catch (error) {
|
||||
console.error("Error loading polsek terdekat:", error);
|
||||
toast.error("Gagal memuat data polsek terdekat");
|
||||
}
|
||||
};
|
||||
|
||||
loadPolsekTerdekat();
|
||||
}, [params?.id]);
|
||||
|
||||
const fetchLayanan = async () => {
|
||||
try {
|
||||
@@ -248,16 +247,14 @@ function EditPolsekTerdekat() {
|
||||
|
||||
{/* Header */}
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="subtle"
|
||||
onClick={() => router.back()}
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||
</Button>
|
||||
<Title order={4} ml="sm" c="dark">
|
||||
Edit Polsek Terdekat
|
||||
</Title>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import polsekTerdekat from '../../../_state/keamanan/polsek-terdekat';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||
import polsekTerdekat from '../../../_state/keamanan/polsek-terdekat';
|
||||
|
||||
function DetailPolsekTerdekat() {
|
||||
const router = useRouter();
|
||||
@@ -157,32 +157,28 @@ function DetailPolsekTerdekat() {
|
||||
|
||||
{/* Aksi */}
|
||||
<Group gap="sm">
|
||||
<Tooltip label="Hapus Data" withArrow position="top">
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => {
|
||||
setSelectedId(data.id);
|
||||
setModalHapus(true);
|
||||
}}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
|
||||
<Tooltip label="Edit Data" withArrow position="top">
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/keamanan/polsek-terdekat/${data.id}/edit`)}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
color="green"
|
||||
onClick={() => router.push(`/admin/keamanan/polsek-terdekat/${data.id}/edit`)}
|
||||
variant="light"
|
||||
radius="md"
|
||||
size="md"
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user