Compare commits

...

1 Commits

Author SHA1 Message Date
ee9368e911 UI Admin Keamanan 2025-05-23 11:33:59 +08:00
57 changed files with 978 additions and 430 deletions

View File

@@ -6,6 +6,6 @@
"riwayat": "<ul> <li>2021 - 2027: Perbekel Desa Darmasaba</li> <li>2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates</li> <li>2020 - Sekarang: Founder Ugawa Record Music Studio</li> <li>2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar</li> </ul>", "riwayat": "<ul> <li>2021 - 2027: Perbekel Desa Darmasaba</li> <li>2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates</li> <li>2020 - Sekarang: Founder Ugawa Record Music Studio</li> <li>2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar</li> </ul>",
"pengalaman": "<ul> <li>1996 1997: Ketua OSIS SMP Negeri 1 Abiansemal</li><li>1999 2000: Ketua OSIS SMA Negeri 1 Mengwi</li> <li>2008 2009: Ketua BEM Universitas Mahasaraswati Denpasar</li> <li>2008 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba</li> <li>2020 Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar</li> <li>2021 Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung</li> <li>2023 2028: Komite Tetap Advokasi Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung</li> </ul>", "pengalaman": "<ul> <li>1996 1997: Ketua OSIS SMP Negeri 1 Abiansemal</li><li>1999 2000: Ketua OSIS SMA Negeri 1 Mengwi</li> <li>2008 2009: Ketua BEM Universitas Mahasaraswati Denpasar</li> <li>2008 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba</li> <li>2020 Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar</li> <li>2021 Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung</li> <li>2023 2028: Komite Tetap Advokasi Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung</li> </ul>",
"unggulan": "<h3>Pemberdayaan Ekonomi dan UMKM</h3> <ul> <li>Pelatihan dan pendampingan UMKM lokal</li> <li>Program bantuan modal usaha bagi pelaku usaha kecil</li><li>Digitalisasi UMKM untuk meningkatkan pemasaran produk lokal</li></ul>", "unggulan": "<h3>Pemberdayaan Ekonomi dan UMKM</h3> <ul> <li>Pelatihan dan pendampingan UMKM lokal</li> <li>Program bantuan modal usaha bagi pelaku usaha kecil</li><li>Digitalisasi UMKM untuk meningkatkan pemasaran produk lokal</li></ul>",
"imageUrl": "/assets/images/ppid/profile-ppid/perbekel.png" "imageUrl": "/uploads/seeded-images/profile-ppid/perbekel.png"
} }
] ]

View File

@@ -593,7 +593,7 @@ model FileStorage {
mimeType String mimeType String
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
deletedAt DateTime? // nullable agar bisa menandakan belum dihapus deletedAt DateTime?
isActive Boolean @default(true) isActive Boolean @default(true)
link String link String
} }

View File

@@ -1,277 +1,277 @@
import prisma from '@/lib/prisma' import prisma from "@/lib/prisma";
import categoryPengumuman from './data/category-pengumuman.json' import categoryPengumuman from "./data/category-pengumuman.json";
import katagoryBerita from './data/katagory-berita.json' import katagoryBerita from "./data/katagory-berita.json";
import caraMemperolehInformasi from './data/list-caraMemperolehInformasi.json' import caraMemperolehInformasi from "./data/list-caraMemperolehInformasi.json";
import caraMemperolehSalinanInformasi from './data/list-caraMemperolehSalinanInformasi.json' import caraMemperolehSalinanInformasi from "./data/list-caraMemperolehSalinanInformasi.json";
import jenisInformasiDiminta from './data/list-jenisInfromasi.json' import jenisInformasiDiminta from "./data/list-jenisInfromasi.json";
import layanan from './data/list-layanan.json' import layanan from "./data/list-layanan.json";
import potensi from './data/list-potensi.json' import potensi from "./data/list-potensi.json";
import visiMisiPPID from './data/ppid/visi-misi-ppid/visimisiPPID.json' import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
import dasarHukumPPID from './data/ppid/dasar-hukum-ppid/dasarhukumPPID.json' import dasarHukumPPID from "./data/ppid/dasar-hukum-ppid/dasarhukumPPID.json";
import profileDesa from './data/desa/profile/profile_desa.json' import profileDesa from "./data/desa/profile/profile_desa.json";
import profilePerbekel from './data/desa/profile/profil_perbekel.json' import profilePerbekel from "./data/desa/profile/profil_perbekel.json";
import profilePPID from './data/ppid/profile-ppid/profilePPid.json' import profilePPID from "./data/ppid/profile-ppid/profilePPid.json";
import path from 'path' import path from "path";
import fs from 'fs' import fs from "fs";
import { mkdir, writeFile } from 'fs/promises' import { mkdir, writeFile } from "fs/promises";
import { v4 as uuid } from 'uuid' import { v4 as uuid } from "uuid";
(async () => { (async () => {
for (const l of layanan) { for (const l of layanan) {
await prisma.layanan.upsert({ await prisma.layanan.upsert({
where: { where: {
name: l.name name: l.name,
}, },
update: { update: {
name: l.name name: l.name,
}, },
create: { create: {
name: l.name name: l.name,
} },
}) });
}
console.log("layanan success ...");
for (const p of potensi) {
await prisma.potensi.upsert({
where: {
name: p.name,
},
update: {
name: p.name,
},
create: {
name: p.name,
},
});
}
console.log("potensi success ...");
for (const k of katagoryBerita) {
await prisma.katagoryBerita.upsert({
where: {
name: k.name,
},
update: {
name: k.name,
},
create: {
name: k.name,
},
});
}
console.log("katagory berita success ...");
for (const c of categoryPengumuman) {
await prisma.categoryPengumuman.upsert({
where: {
name: c.name,
},
update: {
name: c.name,
},
create: {
name: c.name,
},
});
}
console.log("category pengumuman success ...");
for (const j of jenisInformasiDiminta) {
await prisma.jenisInformasiDiminta.upsert({
where: {
name: j.name,
},
update: {
name: j.name,
},
create: {
name: j.name,
},
});
}
console.log("jenis informasi diminta success ...");
for (const c of caraMemperolehInformasi) {
await prisma.caraMemperolehInformasi.upsert({
where: {
name: c.name,
},
update: {
name: c.name,
},
create: {
name: c.name,
},
});
}
console.log("cara memperoleh informasi success ...");
for (const c of caraMemperolehSalinanInformasi) {
await prisma.caraMemperolehSalinanInformasi.upsert({
where: {
name: c.name,
},
update: {
name: c.name,
},
create: {
name: c.name,
},
});
}
console.log("cara memperoleh salinan informasi success ...");
const seedProfilePPID = async () => {
const targetDir = path.resolve("public", "uploads", "seeded-images", "profile-ppid")
// Buat folder hanya jika belum ada
if (!fs.existsSync(targetDir)) {
await mkdir(targetDir, { recursive: true })
} }
console.log("layanan success ...") for (const c of profilePPID) {
let finalImageUrl = c.imageUrl
for (const p of potensi) {
await prisma.potensi.upsert({ if (c.imageUrl.startsWith("/uploads/seeded-images/")) {
where: { const filename = path.basename(c.imageUrl)
name: p.name const seedImagePath = path.resolve("prisma", "seed-images", filename)
},
update: { const targetFilename = `${uuid()}_${filename}`
name: p.name const targetPath = path.join(targetDir, targetFilename)
},
create: { const buffer = fs.readFileSync(seedImagePath)
name: p.name await writeFile(targetPath, buffer)
}
}) finalImageUrl = `/uploads/seeded-images/profile-ppid/${targetFilename}`
}
console.log("potensi success ...")
for (const k of katagoryBerita) {
await prisma.katagoryBerita.upsert({
where: {
name: k.name
},
update: {
name: k.name
},
create: {
name: k.name
}
})
}
console.log("katagory berita success ...")
for (const c of categoryPengumuman) {
await prisma.categoryPengumuman.upsert({
where: {
name: c.name
},
update: {
name: c.name
},
create: {
name: c.name
}
})
}
console.log("category pengumuman success ...")
for (const j of jenisInformasiDiminta) {
await prisma.jenisInformasiDiminta.upsert({
where: {
name: j.name
},
update: {
name: j.name
},
create: {
name: j.name
}
})
}
console.log("jenis informasi diminta success ...")
for (const c of caraMemperolehInformasi) {
await prisma.caraMemperolehInformasi.upsert({
where: {
name: c.name
},
update: {
name: c.name
},
create: {
name: c.name
}
})
}
console.log("cara memperoleh informasi success ...")
for (const c of caraMemperolehSalinanInformasi) {
await prisma.caraMemperolehSalinanInformasi.upsert({
where: {
name: c.name
},
update: {
name: c.name
},
create: {
name: c.name
}
})
}
console.log("cara memperoleh salinan informasi success ...")
const seedProfilePPID = async () => {
const targetDir = path.resolve("public", "assets", "images", "ppid", "profile-ppid")
await mkdir(targetDir, { recursive: true })
for (const c of profilePPID) {
let finalImageUrl = c.imageUrl
// kalau imageUrl diawali dengan "/assets/images", artinya kita harus copy file dari seed-images
if (c.imageUrl.startsWith("/assets/images/")) {
const filename = path.basename(c.imageUrl) // misal "perbekel.png"
const seedImagePath = path.resolve("prisma", "seed-images", filename)
// Buat nama baru yang unik agar tidak bentrok
const targetFilename = `${uuid()}_${filename}`
const targetPath = path.join(targetDir, targetFilename)
// Salin file dari prisma/seed-images ke public/
const buffer = fs.readFileSync(seedImagePath)
await writeFile(targetPath, buffer)
finalImageUrl = `/assets/images/ppid/profile-ppid/${targetFilename}`
}
// Upsert ke database
await prisma.profilePPID.upsert({
where: { id: c.id },
update: {
name: c.name,
biodata: c.biodata,
riwayat: c.riwayat,
pengalaman: c.pengalaman,
unggulan: c.unggulan,
imageUrl: finalImageUrl,
},
create: {
id: c.id,
name: c.name,
biodata: c.biodata,
riwayat: c.riwayat,
pengalaman: c.pengalaman,
unggulan: c.unggulan,
imageUrl: finalImageUrl,
},
})
}
console.log("✅ profilePPID seeded from JSON with image copying")
} }
await seedProfilePPID() await prisma.profilePPID.upsert({
where: { id: c.id },
update: {
for (const v of visiMisiPPID) { name: c.name,
await prisma.visiMisiPPID.upsert({ biodata: c.biodata,
where: { riwayat: c.riwayat,
id: v.id, pengalaman: c.pengalaman,
}, unggulan: c.unggulan,
update: { imageUrl: finalImageUrl,
misi: v.misi, },
visi: v.visi create: {
}, id: c.id,
create: { name: c.name,
id: v.id, biodata: c.biodata,
misi: v.misi, riwayat: c.riwayat,
visi: v.visi pengalaman: c.pengalaman,
} unggulan: c.unggulan,
}) imageUrl: finalImageUrl,
},
})
} }
console.log("visi misi PPID success ...")
console.log("✅ profilePPID seeded from JSON with image copying")
}
await seedProfilePPID()
for (const v of dasarHukumPPID) { for (const v of visiMisiPPID) {
await prisma.dasarHukumPPID.upsert({ await prisma.visiMisiPPID.upsert({
where: { where: {
id: v.id, id: v.id,
}, },
update: { update: {
judul: v.judul, misi: v.misi,
content: v.content visi: v.visi,
}, },
create: { create: {
id: v.id, id: v.id,
judul: v.judul, misi: v.misi,
content: v.content visi: v.visi,
} },
}) });
} }
console.log("dasar hukum PPID success ...") console.log("visi misi PPID success ...");
for (const v of profileDesa) { for (const v of dasarHukumPPID) {
await prisma.profileDesa.upsert({ await prisma.dasarHukumPPID.upsert({
where: { where: {
id: v.id, id: v.id,
}, },
update: { update: {
sejarah: v.sejarah, judul: v.judul,
visi: v.visi, content: v.content,
misi: v.misi, },
lambang: v.lambang, create: {
maskot: v.maskot, id: v.id,
profilPerbekelId: v.profilPerbekelId judul: v.judul,
}, content: v.content,
create: { },
id: v.id, });
sejarah: v.sejarah, }
visi: v.visi, console.log("dasar hukum PPID success ...");
misi: v.misi,
lambang: v.lambang,
maskot: v.maskot,
profilPerbekelId: v.profilPerbekelId
}
})
}
console.log("profile desa success ...")
for (const v of profilePerbekel) { for (const v of profileDesa) {
await prisma.profilPerbekel.upsert({ await prisma.profileDesa.upsert({
where: { where: {
id: v.id, id: v.id,
}, },
update: { update: {
biodata: v.biodata, sejarah: v.sejarah,
pengalaman: v.pengalaman, visi: v.visi,
pengalamanOrganisasi: v.pengalamanOrganisasi, misi: v.misi,
programUnggulan: v.programUnggulan lambang: v.lambang,
}, maskot: v.maskot,
create: { profilPerbekelId: v.profilPerbekelId,
id: v.id, },
biodata: v.biodata, create: {
pengalaman: v.pengalaman, id: v.id,
pengalamanOrganisasi: v.pengalamanOrganisasi, sejarah: v.sejarah,
programUnggulan: v.programUnggulan visi: v.visi,
} misi: v.misi,
}) lambang: v.lambang,
} maskot: v.maskot,
console.log("profile perbekel success ...") profilPerbekelId: v.profilPerbekelId,
},
});
}
console.log("profile desa success ...");
})().then(() => prisma.$disconnect()).catch((e) => { for (const v of profilePerbekel) {
console.error(e) await prisma.profilPerbekel.upsert({
prisma.$disconnect() where: {
id: v.id,
},
update: {
biodata: v.biodata,
pengalaman: v.pengalaman,
pengalamanOrganisasi: v.pengalamanOrganisasi,
programUnggulan: v.programUnggulan,
},
create: {
id: v.id,
biodata: v.biodata,
pengalaman: v.pengalaman,
pengalamanOrganisasi: v.pengalamanOrganisasi,
programUnggulan: v.programUnggulan,
},
});
}
console.log("profile perbekel success ...");
})()
.then(() => prisma.$disconnect())
.catch((e) => {
console.error(e);
prisma.$disconnect();
});
process.on("exit", () => {
prisma.$disconnect();
}); });
process.on('exit', () => { process.on("SIGINT", () => {
prisma.$disconnect() prisma.$disconnect();
}) process.exit(0);
});
process.on('SIGINT', () => {
prisma.$disconnect()
process.exit(0)
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

View File

@@ -1,11 +1,31 @@
import React from 'react'; import colors from "@/con/colors";
import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from "@mantine/core";
import PengangguranBerdasarkanUsia from "./ui/pengangguranBerdasarkanUsia/page";
import PengangguranBerdasarkanPendidikan from "./ui/pengangguranBerdasarkanPendidikan/page";
function Page() { export default function Page() {
return ( return (
<div> <Box>
jumlah-penduduk-usia-kerja-yang-menganggur <Stack gap={"xs"}>
</div> <Title order={3}>Jumlah Penduduk Usia Kerja yang Menganggur</Title>
); <Tabs color={colors['blue-button']} variant='pills' defaultValue={"Pengangguran Bredasarkan Usia"}>
} <TabsList p={"xs"} bg={"#BBC8E7FF"}>
<TabsTab value={"Pengangguran Bredasarkan Usia"}>
Pengangguran Bredasarkan Usia
</TabsTab>
<TabsTab value={"Pengangguran Bredasarkan Pendidikan"}>
Pengangguran Bredasarkan Pendidikan
</TabsTab>
</TabsList>
export default Page; <TabsPanel value={"Pengangguran Bredasarkan Usia"}>
<PengangguranBerdasarkanUsia />
</TabsPanel>
<TabsPanel value={"Pengangguran Bredasarkan Pendidikan"}>
<PengangguranBerdasarkanPendidikan/>
</TabsPanel>
</Tabs>
</Stack>
</Box>
);
}

View File

@@ -0,0 +1,47 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
import React from 'react';
function PengangguranBerdasarkanPendidikan() {
return (
<Box>
<Box py={15}>
<Paper w={{ base: '100%', md: '50%' }} bg={colors['white-1']} p={'md'} radius={10}>
<Stack gap={"xs"}>
<Title order={3}>Pengangguran Berdasarkan Pendidikan</Title>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Pendidikan SD</Text>}
placeholder="masukkan jumlah penduduk Pendidikan SD yang menganggur"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Pendidikan SMP</Text>}
placeholder="masukkan jumlah penduduk Pendidikan SMP yang menganggur"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Pendidikan SMA / SMK</Text>}
placeholder="masukkan jumlah penduduk Pendidikan SMA / SMK yang menganggur"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Pendidikan D1-D3 / S1</Text>}
placeholder="masukkan jumlah penduduk Pendidikan D1-D3 yang menganggur"
/>
<Group>
<Button mt={10} bg={colors['blue-button']}>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
<Stack>
<Title pb={10} order={3}>Grafik Pengangguran Berdasarkan Pendidikan</Title>
</Stack>
</Paper>
</Box>
</Box>
);
}
export default PengangguranBerdasarkanPendidikan;

View File

@@ -0,0 +1,47 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
import React from 'react';
function PengangguranBerdasarkanUsia() {
return (
<Box>
<Box py={15}>
<Paper w={{ base: '100%', md: '50%' }} bg={colors['white-1']} p={'md'} radius={10}>
<Stack gap={"xs"}>
<Title order={3}>Pengangguran Berdasarkan Usia</Title>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Usia 18 - 25 tahun</Text>}
placeholder="masukkan jumlah penduduk usia 18 - 25 tahun yang menganggur"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Usia 26 - 35 tahun</Text>}
placeholder="masukkan jumlah penduduk usia 26 - 35 tahun yang menganggur"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Usia 36 - 45 tahun</Text>}
placeholder="masukkan jumlah penduduk usia 36 - 45 tahun yang menganggur"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Usia 46+</Text>}
placeholder="masukkan jumlah penduduk usia 46+ yang menganggur"
/>
<Group>
<Button mt={10} bg={colors['blue-button']}>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
<Stack>
<Title pb={10} order={3}>Grafik Pengangguran Berdasarkan Usia</Title>
</Stack>
</Paper>
</Box>
</Box>
);
}
export default PengangguranBerdasarkanUsia;

View File

@@ -0,0 +1,29 @@
import { Box, Stack, Text, TextInput, Title } from '@mantine/core';
function CreateLowongan() {
return (
<Box>
<Stack gap={"xs"}>
<Title order={4}>Lowongan Kerja Lokal</Title>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Bekerja Sebagai</Text>}
placeholder="masukkan bekerja sebagai"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Alamat Usaha</Text>}
placeholder="masukkan alamat usaha"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Waktu Kerja</Text>}
placeholder="masukkan waktu kerja"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Gaji selama 1 bulan</Text>}
placeholder="masukkan gaji selama 1 bulan"
/>
</Stack>
</Box>
);
}
export default CreateLowongan;

View File

@@ -0,0 +1,25 @@
import colors from '@/con/colors';
import { Box, Paper, Stack, Title, Text } from '@mantine/core';
import React from 'react';
function ListDataLowongan() {
return (
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Stack gap={"xs"}>
<Title order={3}>List Data Lowongan Kerja Lokal</Title>
<Box>
<Text fw={"bold"}>Bekerja Sebagai</Text>
<Text> </Text>
<Text fw={"bold"}>Alamat Usaha</Text>
<Text> </Text>
<Text fw={"bold"}>Waktu Kerja</Text>
<Text> </Text>
<Text fw={"bold"}>Gaji selama 1 bulan</Text>
<Text> </Text>
</Box>
</Stack>
</Paper>
);
}
export default ListDataLowongan;

View File

@@ -1,10 +1,31 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
import React from 'react'; import React from 'react';
import CreateLowongan from './create/createLowongan';
import ListDataLowongan from './listData/page';
function Page() { function Page() {
return ( return (
<div> <Stack gap={"xs"}>
lowongan-kerja-lokal <SimpleGrid cols={{ base: 1, md: 2 }}>
</div> <Box>
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Title order={3}>Lowongan Kerja Lokal</Title>
<CreateLowongan/>
<Group>
<Button mt={10} bg={colors['blue-button']}>
Submit
</Button>
</Group>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<ListDataLowongan/>
</Paper>
</Box>
</SimpleGrid>
</Stack>
); );
} }

View File

@@ -0,0 +1,36 @@
import colors from '@/con/colors';
import { Box, Stack, Text, TextInput, Title } from '@mantine/core';
import { IconImageInPicture } from '@tabler/icons-react';
import React from 'react';
function CreatePasarDesa() {
return (
<Box>
<Stack gap={"xs"}>
<Title order={4}>Produk Pasar Desa</Title>
<Box>
<Text fz={"sm"} fw={"bold"}>Masukkan Foto Produk</Text>
<IconImageInPicture size={24} color={colors['blue-button']} />
</Box>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Nama Produk</Text>}
placeholder="masukkan nama produk"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Harga Produk</Text>}
placeholder="masukkan harga produk"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Rating Produk</Text>}
placeholder="masukkan rating produk"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Alamat Usaha</Text>}
placeholder="masukkan alamat usaha"
/>
</Stack>
</Box>
);
}
export default CreatePasarDesa;

View File

@@ -0,0 +1,32 @@
import colors from '@/con/colors';
import { Box, Paper, Stack, Text, Title } from '@mantine/core';
import { IconImageInPicture } from '@tabler/icons-react';
import React from 'react';
function ListDataUsaha() {
return (
<Box>
<Stack gap={"xs"}>
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Box>
<Title mb={10} order={4}>List Produk Pasar Desa</Title>
<Box>
<Text fz={"sm"} fw={"bold"}>Foto Produk</Text>
<IconImageInPicture size={24} color={colors['blue-button']} />
</Box>
<Text fz={"sm"} fw={"bold"}>Nama Produk</Text>
<Text></Text>
<Text fz={"sm"} fw={"bold"}>Harga Produk</Text>
<Text></Text>
<Text fz={"sm"} fw={"bold"}>Rating Produk</Text>
<Text></Text>
<Text fz={"sm"} fw={"bold"}>Alamat Usaha</Text>
<Text></Text>
</Box>
</Paper>
</Stack>
</Box>
);
}
export default ListDataUsaha;

View File

@@ -1,10 +1,30 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Stack, Title } from '@mantine/core';
import React from 'react'; import React from 'react';
import CreatePasarDesa from './create/createPasarDesa';
import ListDataUsaha from './listData/page';
function Page() { function Page() {
return ( return (
<div> <Stack gap={'xs'}>
pasar-desa <Box>
</div> <Paper w={{ base: '100%', md: '50%' }} bg={colors['white-1']} p={'md'} radius={10}>
<Stack gap={'xs'}>
<Title order={3}>Pasar Desa</Title>
<CreatePasarDesa />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<ListDataUsaha />
</Stack>
); );
} }

View File

@@ -0,0 +1,28 @@
import colors from '@/con/colors';
import { Box, Stack, Text, TextInput } from '@mantine/core';
import { IconImageInPicture } from '@tabler/icons-react';
function CreateKontakDarurat() {
return (
<Box>
<Stack gap={"xs"}>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Judul Kontak Darurat</Text>}
placeholder="masukkan judul kontak darurat"
/>
<IconImageInPicture size={24} color={colors['blue-button']} />
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Nama Kontak Darurat</Text>}
placeholder="masukkan nama kontak darurat"
/>
<IconImageInPicture size={24} color={colors['blue-button']} />
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Nomor Kontak Darurat</Text>}
placeholder="masukkan nomor kontak darurat"
/>
</Stack>
</Box>
);
}
export default CreateKontakDarurat;

View File

@@ -0,0 +1,23 @@
import colors from '@/con/colors';
import { Box, Paper, Stack, Text, Title } from '@mantine/core';
import React from 'react';
function ListDataKontakDarurat() {
return (
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Stack gap={"xs"}>
<Title order={3}>List Data Kontak Darurat</Title>
<Box>
<Text fw={"bold"}>Judul Kontak Darurat</Text>
<Text> </Text>
<Text fw={"bold"}>Nama Kontak Darurat</Text>
<Text> </Text>
<Text fw={"bold"}>Nomor Kontak Darurat</Text>
<Text> </Text>
</Box>
</Stack>
</Paper>
);
}
export default ListDataKontakDarurat;

View File

@@ -1,10 +1,30 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
import React from 'react'; import React from 'react';
import CreateKontakDarurat from './create/createKontak';
import ListDataKontakDarurat from './listData/page';
function Page() { function Page() {
return ( return (
<div> <Stack gap={"xs"}>
kontak-darurat <SimpleGrid cols={{ base: 1, md: 2 }}>
</div> <Box>
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Title order={3}>Kontak Darurat</Title>
<CreateKontakDarurat/>
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Paper>
</Box>
<ListDataKontakDarurat/>
</SimpleGrid>
</Stack>
); );
} }

View File

@@ -0,0 +1,27 @@
import { Box, Stack, Text, TextInput } from '@mantine/core';
import React from 'react';
import { KeamananEditor } from '../../_com/keamananEditor';
function CreateLaporanPublik() {
return (
<Box>
<Stack gap={"xs"}>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Judul Laporan Publik</Text>}
placeholder="masukkan judul laporan publik"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Tanggal Laporan Publik</Text>}
placeholder="masukkan tanggal laporan publik"
/>
<Box>
<Text fz={"sm"} fw={"bold"}>Deskripsi Laporan Publik</Text>
<KeamananEditor showSubmit={false} />
</Box>
</Stack>
</Box>
);
}
export default CreateLaporanPublik;

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { Box, Paper, Stack, Text, Title } from '@mantine/core';
import colors from '@/con/colors';
function ListDataLaporanPublik() {
return (
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Stack gap={"xs"}>
<Title order={3}>List Data Laporan Publik</Title>
<Box>
<Text fw={"bold"}>Judul Laporan Publik</Text>
<Text></Text>
<Text fw={"bold"}>Tanggal Laporan Publik</Text>
<Text></Text>
<Text fw={"bold"}>Deskripsi Laporan Publik</Text>
<Text></Text>
</Box>
</Stack>
</Paper>
);
}
export default ListDataLaporanPublik;

View File

@@ -1,11 +1,28 @@
import React from 'react'; import colors from "@/con/colors";
import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from "@mantine/core";
import CreateLaporanPublik from "./create/createLaporan";
import ListDataLaporanPublik from "./listData/page";
function Page() { export default function Page() {
return ( return (
<div> <Stack gap={"xs"}>
laporan-publik <SimpleGrid cols={{ base: 1, md: 2 }}>
</div> <Box>
); <Paper bg={colors['white-1']} p={'md'} radius={10}>
} <Title order={3}>Laporan Publik</Title>
<CreateLaporanPublik/>
export default Page; <Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Paper>
</Box>
<ListDataLaporanPublik/>
</SimpleGrid>
</Stack>
)
}

View File

@@ -0,0 +1,25 @@
import colors from '@/con/colors';
import { Box, Stack, Text, TextInput } from '@mantine/core';
import { IconImageInPicture } from '@tabler/icons-react';
import React from 'react';
function CreatePencegahan() {
return (
<Box>
<Stack gap={"xs"}>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Judul Pencegahan Kriminalitas</Text>}
placeholder="masukkan judul pencegahan kriminalitas"
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Deskripsi Pencegahan Kriminalitas</Text>}
placeholder="masukkan deskripsi pencegahan kriminalitas"
/>
<Text fw={"bold"} fz={"sm"} >Gambar Pencegahan Kriminalitas</Text>
<IconImageInPicture size={24} color={colors['blue-button']} />
</Stack>
</Box>
);
}
export default CreatePencegahan;

View File

@@ -0,0 +1,23 @@
import colors from '@/con/colors';
import { Box, Paper, Stack, Text, Title } from '@mantine/core';
import React from 'react';
function ListDataPencegahan() {
return (
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Stack gap={"xs"}>
<Title order={3}>List Data Pencegahan Kriminalitas</Title>
<Box>
<Text fw={"bold"}>Judul Pencegahan Kriminalitas</Text>
<Text> </Text>
<Text fw={"bold"}>Deskripsi Pencegahan Kriminalitas</Text>
<Text> </Text>
<Text fw={"bold"}>Gambar Pencegahan Kriminalitas</Text>
<Text> </Text>
</Box>
</Stack>
</Paper>
);
}
export default ListDataPencegahan;

View File

@@ -1,10 +1,31 @@
import colors from '@/con/colors';
import { Stack, SimpleGrid, Box, Paper, Title, Group, Button } from '@mantine/core';
import React from 'react'; import React from 'react';
import CreatePencegahan from './create/createPencegahan';
import ListDataPencegahan from './listData/page';
function Page() { function Page() {
return ( return (
<div> <Stack gap={"xs"}>
pencegahan-kriminalitas <SimpleGrid cols={{ base: 1, md: 2 }}>
</div> <Box>
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Title order={3}>Kontak Darurat</Title>
<CreatePencegahan/>
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Paper>
</Box>
<ListDataPencegahan/>
</SimpleGrid>
</Stack>
); );
} }

View File

@@ -0,0 +1,27 @@
import colors from '@/con/colors';
import { Box, Stack, Text, TextInput } from '@mantine/core';
import { IconImageInPicture } from '@tabler/icons-react';
import React from 'react';
import { KeamananEditor } from '../../_com/keamananEditor';
function CreateTipsKeamanan() {
return (
<Box>
<Stack gap={"xs"}>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Judul Tips Keamanan</Text>}
placeholder="masukkan judul tips keamanan"
/>
<Box>
<Text fz={"sm"} fw={"bold"}>Upload Gambar</Text>
<IconImageInPicture size={24} color={colors['blue-button']} />
</Box>
<KeamananEditor
showSubmit={false}
/>
</Stack>
</Box>
);
}
export default CreateTipsKeamanan;

View File

@@ -0,0 +1,24 @@
import colors from '@/con/colors';
import { Box, Paper, Stack, Text, Title } from '@mantine/core';
import { IconImageInPicture } from '@tabler/icons-react';
import React from 'react';
function ListDataTipsKeamanan() {
return (
<Paper bg={colors['white-1']} p={'md'} radius={10}>
<Stack gap={"xs"}>
<Title order={3}>List Data Tips Keamanan</Title>
<Box>
<Text fw={"bold"}>Judul Tips Keamanan</Text>
<Text></Text>
<Text fw={"bold"}>Gambar Tips Keamanan</Text>
<IconImageInPicture size={24} color={colors['blue-button']} />
<Text fw={"bold"}>Deskripsi Tips Keamanan</Text>
<Text></Text>
</Box>
</Stack>
</Paper>
);
}
export default ListDataTipsKeamanan;

View File

@@ -1,11 +1,31 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
import React from 'react'; import React from 'react';
import CreateTipsKeamanan from './create/createTips';
import ListDataTipsKeamanan from './listData/page';
function Page() { function Page() {
return ( return (
<div> <Stack gap={"xs"}>
tips-keamanan <SimpleGrid cols={{ base: 1, md: 2 }}>
</div> <Box>
); <Paper bg={colors['white-1']} p={'md'} radius={10}>
<Title order={3}>Tips Keamanan</Title>
<CreateTipsKeamanan/>
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Paper>
</Box>
<ListDataTipsKeamanan/>
</SimpleGrid>
</Stack>
)
} }
export default Page; export default Page;

View File

@@ -2,6 +2,7 @@ import Elysia from "elysia";
import Berita from "./berita"; import Berita from "./berita";
import Pengumuman from "./pengumuman"; import Pengumuman from "./pengumuman";
import ProfileDesa from "./profile/profile_desa"; import ProfileDesa from "./profile/profile_desa";
const Desa = new Elysia({ prefix: "/api/desa", tags: ["Desa"] }) const Desa = new Elysia({ prefix: "/api/desa", tags: ["Desa"] })
.use(Berita) .use(Berita)

View File

@@ -44,6 +44,7 @@ const fileStorageCreate = async (context: Context) => {
const data = await prisma.fileStorage.create({ const data = await prisma.fileStorage.create({
data: { data: {
name: newName, name: newName,
realName: file.name, // Add the original file name as realName
path: rootPath, path: rootPath,
mimeType: file.type, mimeType: file.type,
link: `/api/fileStorage/findUnique/${newName}`, link: `/api/fileStorage/findUnique/${newName}`,
@@ -60,4 +61,4 @@ const fileStorageCreate = async (context: Context) => {
}; };
}; };
export default fileStorageCreate; export default fileStorageCreate;

View File

@@ -18,20 +18,14 @@ import uplImg from "./_lib/upl-img";
import { uplImgSingle } from "./_lib/upl-img-single"; import { uplImgSingle } from "./_lib/upl-img-single";
import FileStorage from "./_lib/fileStorage"; import FileStorage from "./_lib/fileStorage";
const ROOT = process.cwd(); const ROOT = process.cwd();
if (!process.env.WIBU_UPLOAD_DIR) if (!process.env.WIBU_UPLOAD_DIR)
throw new Error("WIBU_UPLOAD_DIR is not defined"); throw new Error("WIBU_UPLOAD_DIR is not defined");
const UPLOAD_DIR = path.join(ROOT, process.env.WIBU_UPLOAD_DIR); const UPLOAD_DIR = path.join(ROOT, process.env.WIBU_UPLOAD_DIR);
const UPLOAD_DIR_IMAGE = path.join( const UPLOAD_DIR_IMAGE = path.join(UPLOAD_DIR, "image");
UPLOAD_DIR,
"public",
"assets",
"images",
"ppid",
"profile-ppid"
);
// create uploads dir // create uploads dir
fs.mkdir(UPLOAD_DIR, { fs.mkdir(UPLOAD_DIR, {
@@ -73,8 +67,8 @@ const ApiServer = new Elysia()
.use(swagger({ path: "/api/docs" })) .use(swagger({ path: "/api/docs" }))
.use( .use(
staticPlugin({ staticPlugin({
prefix: "/", // biar bisa akses dari root URL assets: process.env.WIBU_UPLOAD_DIR || "./uploads",
assets: "./public", prefix: "/uploads",
}) })
) )
.use(cors(corsConfig)) .use(cors(corsConfig))
@@ -93,116 +87,116 @@ const ApiServer = new Elysia()
}) })
.group("/api", (app) => .group("/api", (app) =>
app app
.get("/layanan", layanan) .get("/layanan", layanan)
.get("/potensi", getPotensi) .get("/potensi", getPotensi)
.get( .get(
"/img/:name", "/img/:name",
({ params, query }) => { ({ params, query }) => {
return img({ return img({
name: params.name, name: params.name,
UPLOAD_DIR_IMAGE, UPLOAD_DIR_IMAGE,
ROOT, ROOT,
size: query.size, size: query.size,
}); });
}, },
{ {
params: t.Object({ params: t.Object({
name: t.String(), name: t.String(),
}), }),
query: t.Optional( query: t.Optional(
t.Object({ t.Object({
size: t.Optional(t.Number()), size: t.Optional(t.Number()),
}) })
), ),
} }
) )
.delete( .delete(
"/img/:name", "/img/:name",
({ params }) => { ({ params }) => {
return imgDel({ return imgDel({
name: params.name, name: params.name,
UPLOAD_DIR_IMAGE, UPLOAD_DIR_IMAGE,
}); });
}, },
{ {
params: t.Object({ params: t.Object({
name: t.String(), name: t.String(),
}), }),
} }
) )
.get( .get(
"/imgs", "/imgs",
({ query }) => { ({ query }) => {
return imgs({ return imgs({
search: query.search, search: query.search,
page: query.page, page: query.page,
count: query.count, count: query.count,
UPLOAD_DIR_IMAGE, UPLOAD_DIR_IMAGE,
}); });
}, },
{ {
query: t.Optional( query: t.Optional(
t.Object({ t.Object({
page: t.Number({ default: 1 }), page: t.Number({ default: 1 }),
count: t.Number({ default: 10 }), count: t.Number({ default: 10 }),
search: t.String({ default: "" }), search: t.String({ default: "" }),
}) })
), ),
} }
) )
.post( .post(
"/upl-img", "/upl-img",
({ body }) => { ({ body }) => {
console.log(body.title); console.log(body.title);
return uplImg({ files: body.files, UPLOAD_DIR_IMAGE }); return uplImg({ files: body.files, UPLOAD_DIR_IMAGE });
}, },
{ {
body: t.Object({ body: t.Object({
title: t.String(), title: t.String(),
files: t.Files({ multiple: true }), files: t.Files({ multiple: true }),
}), }),
} }
) )
.post( .post(
"/upl-img-single", "/upl-img-single",
({ body }) => { ({ body }) => {
return uplImgSingle({ return uplImgSingle({
fileName: body.name, fileName: body.name,
file: body.file, file: body.file,
UPLOAD_DIR_IMAGE, UPLOAD_DIR_IMAGE,
}); });
}, },
{ {
body: t.Object({ body: t.Object({
name: t.String(), name: t.String(),
file: t.File(), file: t.File(),
}), }),
} }
) )
.post( .post(
"/upl-csv-single", "/upl-csv-single",
({ body }) => { ({ body }) => {
return uplCsvSingle({ fileName: body.name, file: body.file }); return uplCsvSingle({ fileName: body.name, file: body.file });
}, },
{ {
body: t.Object({ body: t.Object({
name: t.String(), name: t.String(),
file: t.File(), file: t.File(),
}), }),
} }
) )
.post( .post(
"/upl-csv", "/upl-csv",
({ body }) => { ({ body }) => {
return uplCsv({ files: body.files }); return uplCsv({ files: body.files });
}, },
{ {
body: t.Object({ body: t.Object({
files: t.Files(), files: t.Files(),
}), }),
} }
) )
); );
export const GET = ApiServer.handle; export const GET = ApiServer.handle;
export const POST = ApiServer.handle; export const POST = ApiServer.handle;

View File

@@ -1,11 +1,11 @@
'use client' 'use client'
import colors from '@/con/colors'; import colors from '@/con/colors';
import { Box, Button, Combobox, Flex, Group, Image, InputBase, InputPlaceholder, Paper, SimpleGrid, Stack, Text, TextInput, useCombobox } from '@mantine/core'; import { Box, Combobox, Flex, Image, InputBase, InputPlaceholder, Paper, SimpleGrid, Stack, Text, TextInput, useCombobox } from '@mantine/core';
import { IconArrowDown, IconMapPinFilled, IconSearch, IconShoppingCartFilled, IconStarFilled } from '@tabler/icons-react'; import { IconMapPinFilled, IconSearch, IconShoppingCartFilled, IconStarFilled } from '@tabler/icons-react';
import { motion } from 'motion/react';
import { useRouter } from 'next/navigation';
import { useState } from 'react'; import { useState } from 'react';
import BackButton from '../../desa/layanan/_com/BackButto'; import BackButton from '../../desa/layanan/_com/BackButto';
import { useRouter } from 'next/navigation';
import { motion } from 'motion/react';
const groceries = [ const groceries = [
'Makanan', 'Makanan',
@@ -170,9 +170,6 @@ function Page() {
) )
})} })}
</SimpleGrid> </SimpleGrid>
<Group justify='center'>
<Button bg={colors['blue-button']} rightSection={<IconArrowDown size={20} color={colors['white-1']} />} fz={'md'}>Lihat Produk Lainnya</Button>
</Group>
</Stack> </Stack>
</Box> </Box>
</Stack> </Stack>

View File

@@ -64,4 +64,4 @@ function Page() {
); );
} }
export default Page; export default Page;

0
test.txt Normal file
View File