Compare commits

...

2 Commits

Author SHA1 Message Date
9a6f8dc7f6 Membuat database menu desa: Berita & Pengummuman 2025-04-22 21:48:01 +08:00
7b0fb9332e Dashboard Admin 2025-04-21 17:49:13 +08:00
94 changed files with 2514 additions and 43 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -20,15 +20,25 @@
"@elysiajs/swagger": "^1.2.0",
"@mantine/carousel": "^7.16.2",
"@mantine/charts": "^7.17.1",
"@mantine/core": "^7.16.2",
"@mantine/core": "^7.17.4",
"@mantine/dates": "^7.17.4",
"@mantine/dropzone": "^7.17.0",
"@mantine/hooks": "^7.16.2",
"@mantine/hooks": "^7.17.4",
"@mantine/tiptap": "^7.17.4",
"@paljs/types": "^8.1.0",
"@prisma/client": "^6.3.1",
"@tabler/icons-react": "^3.30.0",
"@tiptap/extension-highlight": "^2.11.7",
"@tiptap/extension-link": "^2.11.7",
"@tiptap/extension-subscript": "^2.11.7",
"@tiptap/extension-superscript": "^2.11.7",
"@tiptap/extension-text-align": "^2.11.7",
"@tiptap/extension-underline": "^2.11.7",
"@tiptap/pm": "^2.11.7",
"@tiptap/react": "^2.11.7",
"@tiptap/starter-kit": "^2.11.7",
"@types/bun": "^1.2.2",
"@types/lodash": "^4.17.15",
"@types/lodash": "^4.17.16",
"add": "^2.0.6",
"animate.css": "^4.1.1",
"bun": "^1.2.2",
@@ -39,6 +49,7 @@
"embla-carousel-react": "^7.1.0",
"framer-motion": "^12.4.1",
"get-port": "^7.1.0",
"jotai": "^2.12.3",
"lodash": "^4.17.21",
"motion": "^12.4.1",
"nanoid": "^5.1.0",
@@ -49,10 +60,12 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-simple-toasts": "^6.1.0",
"react-toastify": "^11.0.5",
"readdirp": "^4.1.1",
"recharts": "2",
"swr": "^2.3.2",
"valtio": "^2.1.3"
"valtio": "^2.1.3",
"zod": "^3.24.3"
},
"devDependencies": {
"@eslint/eslintrc": "^3",

View File

@@ -0,0 +1,8 @@
[
{ "name": "Sosial & Kesehatan" },
{ "name": "Ekonomi & UMKM" },
{ "name": "Pendidikan & Kepemudaan" },
{ "name": "Lingkungan & Bencana" },
{ "name": "Adat & Budaya" },
{ "name": "Digitalisasi Desa" }
]

View File

@@ -0,0 +1,9 @@
[
{ "name": "Semua" },
{ "name": "Pemerintahan" },
{ "name": "Pembangunan" },
{ "name": "Ekonomi" },
{ "name": "Sosial" },
{ "name": "Budaya" },
{ "name": "Teknologi" }
]

View File

@@ -17,3 +17,81 @@ model Potensi {
name String @unique
}
model LandingPage_Layanan {
id String @id @default(cuid())
deksripsi String
}
// ========================================= APPMENU ========================================= //
model AppMenu {
id String @id @default(cuid())
name String @unique
link String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
AppMenuChild AppMenuChild[]
}
// ========================================= APPMENUCHILD ========================================= //
model AppMenuChild {
id String @id @default(cuid())
name String @unique
link String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
AppMenu AppMenu? @relation(fields: [appMenuId], references: [id])
appMenuId String?
}
// ========================================= BERITA ========================================= //
model Berita {
id String @id @default(cuid())
judul String
deskripsi String
image String
content String @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
KatagoryBerita KatagoryBerita? @relation(fields: [katagoryBeritaId], references: [id])
katagoryBeritaId String?
}
model KatagoryBerita {
id String @id @default(cuid())
name String @unique
beritas Berita[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
// ========================================= PENGUMUMAN ========================================= //
model Pengumuman {
id String @id @default(cuid())
judul String
deskripsi String
content String @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
CategoryPengumuman CategoryPengumuman? @relation(fields: [categoryPengumumanId], references: [id])
categoryPengumumanId String?
}
model CategoryPengumuman {
id String @id @default(cuid())
name String @unique
pengumumans Pengumuman[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}

View File

@@ -1,7 +1,9 @@
import layanan from './data/list-layanan.json'
import potensi from './data/list-potensi.json'
import katagoryBerita from './data/katagory-berita.json'
import categoryPengumuman from './data/category-pengumuman.json'
import prisma from '@/lib/prisma';
; (async () => {
(async () => {
for (const l of layanan) {
await prisma.layanan.upsert({
where: {
@@ -33,6 +35,38 @@ import prisma from '@/lib/prisma';
}
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 ...")
})().then(() => prisma.$disconnect()).catch((e) => {
console.error(e)
prisma.$disconnect()

View File

@@ -0,0 +1,91 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import ApiFetch from "@/lib/api-fetch";
import { Prisma } from "@prisma/client";
import { toast } from "react-toastify";
import { proxy } from "valtio";
import { z } from "zod";
const templateForm = z.object({
judul: z.string().min(3, "Judul minimal 3 karakter"),
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
image: z.string().url().min(3, "Image minimal 3 karakter"),
content: z.string().min(3, "Content minimal 3 karakter"),
katagoryBeritaId: z.string().nonempty(),
});
const category = proxy({
findMany: {
data: null as
| null
| Prisma.KatagoryBeritaGetPayload<{ omit: { isActive: true } }>[],
async load() {
const res = await ApiFetch.api.desa.berita.category["find-many"].get();
if (res.status === 200) {
category.findMany.data = res.data?.data ?? [];
}
},
},
});
type BeritaForm = Prisma.BeritaGetPayload<{
select: {
judul: true;
deskripsi: true;
image: true;
content: true;
katagoryBeritaId: true;
};
}>;
const berita = proxy({
create: {
form: {} as BeritaForm,
loading: false,
async create() {
berita.create.form.image =
"https://www.shutterstock.com/image-vector/lower-news-live-streaming-breaking-600nw-2535984111.jpg";
const cek = templateForm.safeParse(berita.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
berita.create.loading = true;
const res = await ApiFetch.api.desa.berita["create"].post(
berita.create.form
);
if (res.status === 200) {
berita.findMany.load();
return toast.success("succes create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
berita.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.BeritaGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.desa.berita["find-many"].get();
console.log(res)
if (res.status === 200) {
berita.findMany.data = (res.data?.data as any) ?? [];
}
},
},
});
const stateDashboardBerita = proxy({
category,
berita,
});
export default stateDashboardBerita;

View File

@@ -0,0 +1,83 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import ApiFetch from "@/lib/api-fetch"
import { Prisma } from "@prisma/client"
import { toast } from "react-toastify"
import { proxy } from "valtio"
import { z } from "zod"
const templateFormPengumuman = z.object({
judul: z.string().min(3, "Judul minimal 3 karakter"),
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
content: z.string().min(3, "Content minimal 3 karakter"),
categoryPengumumanId: z.string().nonempty(),
})
const category = proxy ({
findMany: {
data: null as
| null
| Prisma.CategoryPengumumanGetPayload<{ omit: { isActive: true } }>[],
async load() {
const res = await ApiFetch.api.desa.pengumuman.category["find-many"].get();
if (res.status === 200) {
category.findMany.data = res.data?.data as any ?? [];
}
}
}
})
type PengumumanForm = Prisma.PengumumanGetPayload<{
select: {
judul: true;
deskripsi: true;
content: true;
categoryPengumumanId: true;
}
}>
const pengumuman = proxy({
create: {
form: {} as PengumumanForm,
loading: false,
async create() {
const cek = templateFormPengumuman.safeParse(pengumuman.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
pengumuman.create.loading = true;
const res = await ApiFetch.api.desa.pengumuman["create"].post(pengumuman.create.form)
if (res.status === 200) {
pengumuman.findMany.load();
return toast.success("success create");
}
console.log(res)
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally{
pengumuman.create.loading = false;
}
}
},
findMany: {
data: null as
| Prisma.PengumumanGetPayload<{omit: {isActive: true}}>[]
| null,
async load () {
const res = await ApiFetch.api.desa.pengumuman["find-many"].get();
console.log(res)
if (res.status === 200) {
pengumuman.findMany.data = res.data?.data ?? [];
}
}
}
})
const stateDesaPengumuman = proxy({
category,
pengumuman
})
export default stateDesaPengumuman

View File

@@ -0,0 +1,85 @@
'use client'
import { RichTextEditor, Link } from '@mantine/tiptap';
import { useEditor } from '@tiptap/react';
import Highlight from '@tiptap/extension-highlight';
import StarterKit from '@tiptap/starter-kit';
import Underline from '@tiptap/extension-underline';
import TextAlign from '@tiptap/extension-text-align';
import Superscript from '@tiptap/extension-superscript';
import SubScript from '@tiptap/extension-subscript';
import { Button, Stack } from '@mantine/core';
const content =
'<h2 style="text-align: center;">Welcome to Mantine rich text editor</h2><p><code>RichTextEditor</code> component focuses on usability and is designed to be as simple as possible to bring a familiar editing experience to regular users. <code>RichTextEditor</code> is based on <a href="https://tiptap.dev/" rel="noopener noreferrer" target="_blank">Tiptap.dev</a> and supports all of its features:</p><ul><li>General text formatting: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike-through</s> </li><li>Headings (h1-h6)</li><li>Sub and super scripts (<sup>&lt;sup /&gt;</sup> and <sub>&lt;sub /&gt;</sub> tags)</li><li>Ordered and bullet lists</li><li>Text align&nbsp;</li><li>And all <a href="https://tiptap.dev/extensions" target="_blank" rel="noopener noreferrer">other extensions</a></li></ul>';
export function BeritaEditor({ onSubmit }: { onSubmit: (val: string) => void }) {
const editor = useEditor({
extensions: [
StarterKit,
Underline,
Link,
Superscript,
SubScript,
Highlight,
TextAlign.configure({ types: ['heading', 'paragraph'] }),
],
content,
});
return (
<Stack>
<RichTextEditor editor={editor}>
<RichTextEditor.Toolbar sticky stickyOffset={60}>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Bold />
<RichTextEditor.Italic />
<RichTextEditor.Underline />
<RichTextEditor.Strikethrough />
<RichTextEditor.ClearFormatting />
<RichTextEditor.Highlight />
<RichTextEditor.Code />
</RichTextEditor.ControlsGroup>
<RichTextEditor.ControlsGroup>
<RichTextEditor.H1 />
<RichTextEditor.H2 />
<RichTextEditor.H3 />
<RichTextEditor.H4 />
</RichTextEditor.ControlsGroup>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Blockquote />
<RichTextEditor.Hr />
<RichTextEditor.BulletList />
<RichTextEditor.OrderedList />
<RichTextEditor.Subscript />
<RichTextEditor.Superscript />
</RichTextEditor.ControlsGroup>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Link />
<RichTextEditor.Unlink />
</RichTextEditor.ControlsGroup>
<RichTextEditor.ControlsGroup>
<RichTextEditor.AlignLeft />
<RichTextEditor.AlignCenter />
<RichTextEditor.AlignJustify />
<RichTextEditor.AlignRight />
</RichTextEditor.ControlsGroup>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Undo />
<RichTextEditor.Redo />
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>
<Button onClick={() => {
if (!editor) return
onSubmit(editor?.getHTML())
}}>Submit</Button>
</Stack>
);
}

View File

@@ -0,0 +1,88 @@
'use client'
import { Center, Group, Select, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { Prisma } from '@prisma/client';
import { IconImageInPicture } from '@tabler/icons-react';
import { useProxy } from 'valtio/utils';
import stateDashboardBerita from '../../_state/berita';
import { BeritaEditor } from './_com/BeritaEditor';
function Page() {
return (
<Stack>
<SimpleGrid cols={2}>
<BeritaList />
<BeritaCreate />
</SimpleGrid>
</Stack>
);
}
function BeritaList() {
const beritaState = useProxy(stateDashboardBerita)
useShallowEffect(() => {
beritaState.berita.findMany.load()
}, [])
if (!beritaState.berita.findMany.data) return <Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return <Stack>
<Text>News List</Text>
{beritaState.berita.findMany.data?.map((item) => (
<Text key={item.id}>{item.judul}</Text>
))}
</Stack>
}
function BeritaCreate() {
const beritaState = useProxy(stateDashboardBerita)
return <Stack gap={"md"}>
<Text>Create Some News</Text>
<SelectCategory onChange={(val) => {
beritaState.berita.create.form.katagoryBeritaId = val.id
}} />
<TextInput onChange={(val) => {
beritaState.berita.create.form.judul = val.target.value
}} label={"Judul"} placeholder='masukkan judul' />
<TextInput onChange={(val) => {
beritaState.berita.create.form.deskripsi = val.target.value
}} label={"Deskripsi"} placeholder='masukkan deskripsi' />
<Center w={200} h={200} bg={"gray"}>
<IconImageInPicture />
</Center>
<BeritaEditor onSubmit={(val) => {
beritaState.berita.create.form.content = val
beritaState.berita.create.create()
}} />
</Stack>
}
function SelectCategory({ onChange }: {
onChange: (value: Prisma.KatagoryBeritaGetPayload<{
select: {
name: true,
id: true
}
}>) => void
}) {
const beritaState = useProxy(stateDashboardBerita)
useShallowEffect(() => {
beritaState.category.findMany.load()
}, [])
if (!beritaState.category.findMany.data) return <Skeleton h={40} />
return <Group>
<Select placeholder='pilih katagori' label={"select katagori"} data={beritaState.category.findMany.data.map((item) => ({
value: item.id,
label: item.name
}))} onChange={(v) => {
const data = beritaState.category.findMany.data?.find((item) => item.id === v)
if (!data) return
onChange(data)
}} />
</Group>
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Gallery
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Layanan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Penghargaan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,89 @@
'use client'
import { Group, Select, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
import React from 'react';
import { useProxy } from 'valtio/utils';
import stateDesaPengumuman from '../../_state/pengumuman';
import { useShallowEffect } from '@mantine/hooks';
import { Prisma } from '@prisma/client';
import { BeritaEditor } from '../berita/_com/BeritaEditor';
function Page() {
return (
<Stack>
<SimpleGrid cols={{
base: 1, md: 2
}}>
<PengumumanList />
<PengumumanCreate />
</SimpleGrid>
</Stack>
);
}
function PengumumanList() {
const pengumumanState = useProxy(stateDesaPengumuman)
useShallowEffect(() => {
pengumumanState.pengumuman.findMany.load()
}, [])
if (!pengumumanState.pengumuman.findMany.data) return <Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return <Stack>
<Text>Announcement List</Text>
{pengumumanState.pengumuman.findMany.data?.map((item) => (
<Text key={item.id}>{item.judul}</Text>
))}
</Stack>;
}
function PengumumanCreate() {
const pengumumanState = useProxy(stateDesaPengumuman)
return <Stack gap={"md"}>
<Text>Create Some Announcement</Text>
<SelectCategory onChange={(val) => {
pengumumanState.pengumuman.create.form.categoryPengumumanId = val.id
}} />
<TextInput onChange={(val) => {
pengumumanState.pengumuman.create.form.judul = val.target.value
}} label={"Judul"} placeholder='masukkan judul' />
<TextInput onChange={(val) => {
pengumumanState.pengumuman.create.form.deskripsi = val.target.value
}} label={"Deskripsi"} placeholder='masukkan deskripsi' />
<BeritaEditor onSubmit={(val) => {
pengumumanState.pengumuman.create.form.content = val
pengumumanState.pengumuman.create.create()
}} />
</Stack>
}
function SelectCategory({ onChange }: {
onChange: (value: Prisma.CategoryPengumumanGetPayload<{
select: {
name: true,
id: true
}
}>) => void
}) {
const pengumumanState = useProxy(stateDesaPengumuman)
useShallowEffect(() => {
pengumumanState.category.findMany.load()
}, [])
if (!pengumumanState.category.findMany.data) return <Skeleton h={40} />
return <Group>
{/* {JSON.stringify(pengumumanState.category.findMany.data)} */}
<Select placeholder='pilih kategori' label={"select katagori"} data={pengumumanState.category.findMany.data.map((item) => ({
value: item.id,
label: item.name
}))} onChange={(v) => {
const data = pengumumanState.category.findMany.data?.find((item) => item.id === v)
if (!data) return
onChange(data)
}}
/>
</Group>
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Potensi
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Profile
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
PADesa-pendapatan-asli-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
demografi-pekerjaan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
jumlah-penduduk-miskin-2024-2025
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
jumlah-penduduk-usia-kerja-yang-menganggur
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
jumlah-pengangguran-2024-2025
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
lowongan-kerja-lokal
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
pasar-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
program-kemiskinan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
sektor-unggulan-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
struktur-organisasi-dan-sk-pengurus-bumdesa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
ajukan-ide-inovatif
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
desa-digital-smart-village
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
info-teknologi-tepat-guna
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
kolaborasi-inovasi
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
layanan-online-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
program-kreatif-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
keamanan-lingkungan-pecalang-patwal
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
kontak-darurat
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
laporan-publik
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
pencegahan-kriminalitas
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
polsek-terdekat
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
tips-keamanan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Data Kesehatan Warga
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Wabah Penyakit
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Kontak Darurat
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Penanganan Darurat
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Posyandu
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Program Kesehatan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Puskesmas
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
APBDes
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Desa Anti Korupsi
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Indeks Kepuasan MAsyarakat
</div>
);
}
export default Page;

View File

@@ -0,0 +1,23 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Group, Stack, Text, Textarea, Title } from '@mantine/core';
function Page() {
return (
<Box>
<Stack gap={"xs"}>
<Title order={2}>Layanan</Title>
<Textarea
label={<Text>Deskripsi</Text>}
placeholder='tambah deskripsi'
/>
<Group>
<Button
bg={colors['blue-button']} fz={'md'}>Submit</Button>
</Group>
</Stack>
</Box>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Penghargaan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Potensi
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Prestasi Desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Profile
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
SDGS Desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
data-lingkungan-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
edukasi-lingkungan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
gotong-royong
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
konservasi-adat-bali
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
pengelolaan-sampah-bank-sampah
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
program-penghijauan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
beasiswa-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
bimbingan-belajar-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
data-pendidikan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
info-sekolah-paud
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
pendidikan-non-formal
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
perpustakaan-digital
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
program-pendidikan-anak
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
daftar-informasi-publik-desa-darmasaba
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
dasar-hukum
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
ikm-desa-darmasaba
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
permohonan-informasi-publik
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
permohonan-keberatan-informasi-publik
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
profile-ppid
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
struktur-ppid
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
visi-misi-ppid
</div>
);
}
export default Page;

View File

@@ -0,0 +1,396 @@
export const navBar = [
{
id: "Landing Page",
name: "Landing Page",
path: "",
children: [
{
id: "Landing_Page_1",
name: "Profile",
path: "/admin/landing-page/profile"
},
{
id: "Landing_Page_2",
name: "Penghargaan",
path: "/admin/landing-page/penghargaan"
},
{
id: "Landing_Page_3",
name: "Layanan",
path: "/admin/landing-page/layanan"
},
{
id: "Landing_Page_4",
name: "Potensi",
path: "/admin/landing-page/potensi"
},
{
id: "Landing_Page_5",
name: "Desa Anti Korupsi",
path: "/admin/landing-page/desa-anti-korupsi"
},
{
id: "Landing_Page_6",
name: "Indeks Kepuasan Masyarakat",
path: "/admin/landing-page/indeks-kepuasan-masyarakat"
},
{
id: "Landing_Page_7",
name: "SDGs Desa",
path: "/admin/landing-page/sdgs-desa"
},
{
id: "Landing_Page_8",
name: "APBDes",
path: "/admin/landing-page/apbdes"
},
{
id: "Landing_Page_9",
name: "Prestasi Desa",
path: "/admin/landing-page/prestasi-desa"
}
]
},
{
id: "PPID",
name: "PPID",
path: "",
children: [
{
id: "PPID_1",
name: "Profile PPID",
path: "/admin/ppid/profile-ppid"
},
{
id: "PPID_2",
name: "Struktur PPID",
path: "/admin/ppid/struktur-ppid"
},
{
id: "PPID_3",
name: "Visi Misi PPID",
path: "/admin/ppid/visi-misi-ppid"
},
{
id: "PPID_4",
name: "Dasar Hukum",
path: "/admin/ppid/dasar-hukum"
},
{
id: "PPID_5",
name: "Permohonan Informasi Publik",
path: "/admin/ppid/permohonan-informasi-publik"
},
{
id: "PPID_6",
name: "Permohonan Keberatan Informasi Publik",
path: "/admin/ppid/permohonan-keberatan-informasi-publik"
},
{
id: "PPID_7",
name: "Daftar Informasi Publik Desa Darmasaba",
path: "/admin/ppid/daftar-informasi-publik-desa-darmasaba"
},
{
id: "PPID_8",
name: "IKM Desa Darmasaba",
path: "/admin/ppid/ikm-desa-darmasaba"
},
]
},
{
id: "Desa",
name: "Desa",
path: "",
children: [
{
id: "Desa_1",
name: "Profile",
path: "/admin/desa/profile"
},
{
id: "Desa_2",
name: "Potensi",
path: "/admin/desa/potensi"
},
{
id: "Desa_3",
name: "Berita",
path: "/admin/desa/berita"
},
{
id: "Desa_4",
name: "Pengumuman",
path: "/admin/desa/pengumuman"
},
{
id: "Desa_5",
name: "Gallery",
path: "/admin/desa/gallery"
},
{
id: "Desa_6",
name: "Layanan",
path: "/admin/desa/layanan"
},
{
id: "Desa_7",
name: "Penghargaan",
path: "/admin/desa/penghargaan"
}
]
},
{
id: "Kesehatan",
name: "Kesehatan",
path: "",
children: [
{
id: "Kesehatan_1",
name: "Posyandu",
path: "/admin/kesehatan/posyandu"
},
{
id: "Kesehatan_2",
name: "Data Kesehatan Warga",
path: "/admin/kesehatan/data-kesehatan-warga"
},
{
id: "Kesehatan_3",
name: "Puskesmas",
path: "/admin/kesehatan/puskesmas"
},
{
id: "Kesehatan_4",
name: "Program Kesehatan",
path: "/admin/kesehatan/program-kesehatan"
},
{
id: "Kesehatan_5",
name: "Penanganan Darurat",
path: "/admin/kesehatan/penanganan-darurat"
},
{
id: "Kesehatan_6",
name: "Kontak Darurat",
path: "/admin/kesehatan/kontak-darurat"
},
{
id: "Kesehatan_7",
name: "Info Wabah/Penyakit",
path: "/admin/kesehatan/info-wabah-penyakit"
}
]
},
{
id: "Keamanan",
name: "Keamanan",
path: "",
children: [
{
id: "Keamanan_1",
name: "Keamanan Lingkungan (Pecalang/Patwal)",
path: "/admin/keamanan/keamanan-lingkungan-pecalang-patwal"
},
{
id: "Keamanan_2",
name: "Polsek Terdekat",
path: "/admin/keamanan/polsek-terdekat"
},
{
id: "Keamanan_3",
name: "Kontak Darurat",
path: "/admin/keamanan/kontak-darurat"
},
{
id: "Keamanan_4",
name: "Pencegahan Kriminalitas",
path: "/admin/keamanan/pencegahan-kriminalitas"
},
{
id: "Keamanan_5",
name: "Laporan Publik",
path: "/admin/keamanan/laporan-publik"
},
{
id: "Keamanan_6",
name: "Tips Keamanan",
path: "/admin/keamanan/tips-keamanan"
}
]
},
{
id: "Ekonomi",
name: "Ekonomi",
path: "",
children: [
{
id: "Ekonomi_1",
name: "Pasar Desa",
path: "/admin/ekonomi/pasar-desa"
},
{
id: "Ekonomi_2",
name: "Lowongan Kerja Lokal",
path: "/admin/ekonomi/lowongan-kerja-lokal"
},
{
id: "Ekonomi_3",
name: "Struktur Organisasi dan SK Pengurus BUMDesa",
path: "/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa"
},
{
id: "Ekonomi_4",
name: "PADesa (Pendapatan Asli Desa)",
path: "/admin/ekonomi/PADesa-pendapatan-asli-desa"
},
{
id: "Ekonomi_5",
name: "Jumlah Pengangguran 2024-2025",
path: "/admin/ekonomi/jumlah-pengangguran-2024-2025"
},
{
id: "Ekonomi_6",
name: "Jumlah penduduk usia kerja yang menganggur",
path: "/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur"
},
{
id: "Ekonomi_7",
name: "Jumlah Penduduk Miskin 2024-2025",
path: "/admin/ekonomi/jumlah-penduduk-miskin-2024-2025"
},
{
id: "Ekonomi_8",
name: "Program Kemiskinan",
path: "/admin/ekonomi/program-kemiskinan"
},
{
id: "Ekonomi_9",
name: "Sektor Unggulan Desa",
path: "/admin/ekonomi/sektor-unggulan-desa"
},
{
id: "Ekonomi_10",
name: "Demografi Pekerjaan",
path: "/admin/ekonomi/demografi-pekerjaan"
}
]
}, {
id: "Inovasi",
name: "Inovasi",
path: "",
children: [
{
id: "Inovasi_1",
name: "Desa Digital/Smart Village",
path: "/admin/inovasi/desa-digital-smart-village"
},
{
id: "Inovasi_2",
name: "Layanan Online Desa",
path: "/admin/inovasi/layanan-online-desa"
},
{
id: "Inovasi_3",
name: "Program Kreatif Desa",
path: "/admin/inovasi/program-kreatif-desa"
},
{
id: "Inovasi_4",
name: "Kolaborasi Inovasi",
path: "/admin/inovasi/kolaborasi-inovasi"
},
{
id: "Inovasi_5",
name: "Info Teknologi Tepat Guna",
path: "/admin/inovasi/info-teknologi-tepat-guna"
},
{
id: "Inovasi_6",
name: "Ajukan Ide Inovatif",
path: "/admin/inovasi/ajukan-ide-inovatif"
}
]
}, {
id: "Lingkungan",
name: "Lingkungan",
path: "",
children: [
{
id: "Lingkungan_1",
name: "Pengelolaan Sampah (Bank Sampah)",
path: "/admin/lingkungan/pengelolaan-sampah-bank-sampah"
},
{
id: "Lingkungan_2",
name: "Program Penghijauan",
path: "/admin/lingkungan/program-penghijauan"
},
{
id: "Lingkungan_3",
name: "Data Lingkungan Desa",
path: "/admin/lingkungan/data-lingkungan-desa"
},
{
id: "Lingkungan_4",
name: "Gotong Royong",
path: "/admin/lingkungan/gotong-royong"
},
{
id: "Lingkungan_5",
name: "Edukasi Lingkungan",
path: "/admin/lingkungan/edukasi-lingkungan"
},
{
id: "Lingkungan_6",
name: "Konservasi Adat Bali",
path: "/admin/lingkungan/konservasi-adat-bali"
}
]
}, {
id: "Pendidikan",
name: "Pendidikan",
path: "",
children: [
{
id: "Pendidikan_1",
name: "Info Sekolah & PAUD",
path: "/admin/pendidikan/info-sekolah-paud"
},
{
id: "Pendidikan_2",
name: "Beasiswa Desa",
path: "/admin/pendidikan/beasiswa-desa"
},
{
id: "Pendidikan_3",
name: "Program Pendidikan Anak",
path: "/admin/pendidikan/program-pendidikan-anak"
},
{
id: "Pendidikan_4",
name: "Bimbingan Belajar Desa",
path: "/admin/pendidikan/bimbingan-belajar-desa"
},
{
id: "Pendidikan_5",
name: "Pendidikan Non Formal",
path: "/admin/pendidikan/pendidikan-non-formal"
},
{
id: "Pendidikan_6",
name: "Perpustakaan Digital",
path: "/admin/pendidikan/perpustakaan-digital"
},
{
id: "Pendidikan_7",
name: "Data Pendidikan",
path: "/admin/pendidikan/data-pendidikan"
}
]
}
]

View File

@@ -0,0 +1,13 @@
import { Stack } from "@mantine/core";
import AdminNav from "../_com/AdminNav";
function Layout({ children }: { children: React.ReactNode }) {
return (
<Stack gap={0}>
<AdminNav />
{children}
</Stack>
);
}
export default Layout;

View File

@@ -1,11 +1,87 @@
import { Stack } from "@mantine/core";
import AdminNav from "./_com/AdminNav";
'use client'
import colors from "@/con/colors";
import { ActionIcon, AppShell, AppShellHeader, AppShellMain, AppShellNavbar, Burger, Group, Image, NavLink, ScrollArea, Text } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { IconChevronLeft, IconChevronRight } from "@tabler/icons-react";
import _ from 'lodash';
import Link from "next/link";
import { useSelectedLayoutSegments } from "next/navigation";
import { navBar } from "./_com/list_PageAdmin";
export default function Layout({ children }: { children: React.ReactNode }) {
const [opened, { toggle }] = useDisclosure();
const [desktopOpened, { toggle: toggleDesktop }] =
useDisclosure(true);
const segments = useSelectedLayoutSegments()
return (
<Stack gap={0}>
<AdminNav />
{children}
</Stack>
<AppShell
suppressHydrationWarning
header={{ height: 60 }}
navbar={{
width: 300, breakpoint: 'sm', collapsed: { mobile: !opened, desktop: !desktopOpened }
}}
padding={'md'}
>
<AppShellHeader bg={colors["white-trans-1"]}>
<Group px={10} align="center">
{!desktopOpened && <ActionIcon variant="light" onClick={toggleDesktop}><IconChevronRight /></ActionIcon>}
<Burger opened={opened} onClick={toggle} hiddenFrom="sm" size={'sm'} />
<ActionIcon w={50} h={50} variant="transparent" component={Link} href="/admin">
<Image py={5} src={'/assets/images/darmasaba-icon.png'} alt="" width={50} height={50} />
</ActionIcon>
<Text fw={'bold'} c={colors["blue-button"]} fz={'lg'}>Dashboard Admin</Text>
</Group>
</AppShellHeader>
<AppShellNavbar
c={colors["blue-button"]}
component={ScrollArea}
>
<AppShell.Section h={100} bg={"gray.1"}>
<Text c={colors["blue-button"]}>Heder Navbar</Text>
</AppShell.Section>
<AppShell.Section >
{navBar.map((v, k) => {
return (
<NavLink
c={_.lowerCase(v.name) == segments[1] ? colors["blue-button"] : "grey"}
key={k}
defaultOpened={_.lowerCase(v.name) == segments[1]}
// onClick={() => setActive(k)}
label={<Text
style={{ fontWeight: _.lowerCase(v.name) == segments[1] ? "bold" : "normal" }}
>{v.name}</Text>}
>
{v.children.map((child, key) => {
return (
<NavLink
c={_.lowerCase(child.name) == _.lowerCase(segments[2]) ? colors["blue-button"] : "grey"}
key={key}
href={child.path}
// active={isClient && Number(child.id) === active}
// onClick={() => setActive(Number(child.id))}
label={<Text
style={{ fontWeight: _.lowerCase(child.name) == _.lowerCase(segments[2]) ? "bold" : "normal" }}
>{child.name}</Text>}
/>
)
})}
</NavLink>
)
})}
</AppShell.Section>
<AppShell.Section>
<Group justify="end">
<ActionIcon variant="light" onClick={toggleDesktop}><IconChevronLeft /></ActionIcon>
</Group>
</AppShell.Section>
</AppShellNavbar>
<AppShellMain bg={colors.Bg}>
{children}
</AppShellMain>
</AppShell>
);
}
}

View File

@@ -1,9 +1,9 @@
import { Container, Stack } from "@mantine/core";
import { Text } from "@mantine/core";
export default function Page() {
return (
<Stack h={"100%"}>
<Container>admin</Container>
</Stack>
);
}
return(
<Text>
Test
</Text>
)
}

View File

@@ -0,0 +1,9 @@
import prisma from "@/lib/prisma";
async function katagoryBeritaFindMany() {
const data = await prisma.katagoryBerita.findMany();
return { data };
}
export default katagoryBeritaFindMany

View File

@@ -0,0 +1,39 @@
import prisma from "@/lib/prisma";
import { Prisma } from "@prisma/client";
import { Context } from "elysia";
type FormCreate = Prisma.BeritaGetPayload<{
select: {
judul: true;
deskripsi: true;
image: true;
content: true;
katagoryBeritaId: true;
};
}>;
async function beritaCreate(context: Context) {
const body = context.body as FormCreate;
// console.log(body)
await prisma.berita.create({
data: {
content: body.content,
deskripsi: body.deskripsi,
image: body.image,
judul: body.judul,
katagoryBeritaId: body.katagoryBeritaId,
},
});
return {
success: true,
message: "Success create berita",
data: {
...body,
},
};
}
export default beritaCreate

View File

@@ -0,0 +1,8 @@
import prisma from "@/lib/prisma";
export default async function beritaFindMany() {
const res = await prisma.berita.findMany();
return {
data: res,
};
}

View File

@@ -0,0 +1,19 @@
import Elysia, { t } from "elysia";
import katagoryBeritaFindMany from "./category";
import beritaFindMany from "./find-many";
import beritaCreate from "./create";
const Berita = new Elysia({ prefix: "/berita", tags: ["Desa/Berita"] })
.get("/category/find-many", katagoryBeritaFindMany)
.get("/find-many", beritaFindMany)
.post("/create", beritaCreate, {
body: t.Object({
judul: t.String(),
deskripsi: t.String(),
image: t.String(),
content: t.String(),
katagoryBeritaId: t.Union([t.String(), t.Null()]),
}),
});
export default Berita;

View File

@@ -0,0 +1,9 @@
import Elysia from "elysia";
import Berita from "./berita";
import Pengumuman from "./pengumuman";
const Desa = new Elysia({ prefix: "/api/desa", tags: ["Desa"] })
.use(Berita)
.use(Pengumuman)
export default Desa;

View File

@@ -0,0 +1,8 @@
import prisma from "@/lib/prisma";
async function pengumumanCategoryFindMany() {
const data = await prisma.categoryPengumuman.findMany();
return { data };
}
export default pengumumanCategoryFindMany

View File

@@ -0,0 +1,43 @@
import prisma from "@/lib/prisma";
import { Prisma } from "@prisma/client";
import { Context } from "elysia";
type FormCreate = Prisma.PengumumanGetPayload<{
select: {
judul: true;
deskripsi: true;
content: true;
categoryPengumumanId: true;
};
}>;
export async function pengumumanCreate(context: Context) {
const body = context.body as FormCreate;
try {
await prisma.pengumuman.create({
data: {
content: body.content,
deskripsi: body.deskripsi,
judul: body.judul,
categoryPengumumanId: body.categoryPengumumanId,
},
});
} catch (error) {
console.error(error);
console.error(body)
return {
success: false,
message: "Failed create pengumuman",
error: error,
};
}
return {
success: true,
message: "Success create pengumuman",
data: {
...body,
},
};
}

View File

@@ -0,0 +1,8 @@
import prisma from "@/lib/prisma";
export default async function pengumumanFindMany() {
const res = await prisma.pengumuman.findMany();
return {
data: res,
};
}

View File

@@ -0,0 +1,19 @@
import Elysia from "elysia";
import { pengumumanCreate } from "./create";
import pengumumanFindMany from "./find-many";
import { t } from "elysia";
import pengumumanCategoryFindMany from "./category";
const Pengumuman = new Elysia({ prefix: "/pengumuman", tags: ["Desa/Pengumuman"] })
.get("/category/find-many", pengumumanCategoryFindMany)
.get("/find-many", pengumumanFindMany)
.post("/create", pengumumanCreate, {
body: t.Object({
judul: t.String(),
deskripsi: t.String(),
content: t.String(),
categoryPengumumanId: t.Union([t.String(), t.Null()]),
}),
});
export default Pengumuman;

View File

@@ -0,0 +1,36 @@
import { MODEL_LANDING_PAGE_LAYANAN } from "@/app/admin/(dashboard)/landing-page/layanan/lib/interface";
import prisma from "@/lib/prisma";
import { NextResponse } from "next/server";
export async function layanan_landingpage({req} : {req: MODEL_LANDING_PAGE_LAYANAN}) {
try {
const data = await prisma.landingPage_Layanan.create({
data: {
id: req.id,
deksripsi: req.deskripsi
},
select: {
id: true,
deksripsi: true
}
})
return NextResponse.json(
{
success: true,
message: "Success get collaboration",
data: data,
},
{ status: 200 }
);
} catch (error) {
console.error("Error create layanan", error);
return NextResponse.json(
{
success: false,
message: "Error create layanan",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}

View File

@@ -2,16 +2,17 @@ import prisma from "@/lib/prisma";
import cors, { HTTPMethod } from "@elysiajs/cors";
import swagger from "@elysiajs/swagger";
import { Elysia, t } from "elysia";
import getPotensi from "./_lib/get-potensi";
import img from "./_lib/img";
import fs from "fs/promises";
import path from "path";
import uplImg from "./_lib/upl-img";
import getPotensi from "./_lib/get-potensi";
import img from "./_lib/img";
import imgDel from "./_lib/img-del";
import imgs from "./_lib/imgs";
import uplCsv from "./_lib/upl-csv";
import imgDel from "./_lib/img-del";
import { uplImgSingle } from "./_lib/upl-img-single";
import { uplCsvSingle } from "./_lib/upl-csv-single";
import uplImg from "./_lib/upl-img";
import { uplImgSingle } from "./_lib/upl-img-single";
import Desa from "./_lib/desa";
const ROOT = process.cwd();
if (!process.env.WIBU_UPLOAD_DIR)
@@ -46,6 +47,7 @@ async function layanan() {
const ApiServer = new Elysia()
.use(swagger({ path: "/api/docs" }))
.use(cors(corsConfig))
.use(Desa)
.onError(({ code }) => {
if (code === "NOT_FOUND") {
return {

View File

@@ -1,11 +1,277 @@
import React from 'react';
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
import colors from '@/con/colors';
import { Box, Button, Center, Divider, Flex, Group, Image, List, ListItem, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
const dataMitos = [
{
id: 1,
mitos: 'Daun pepaya dan daun jambu biji bisa menyembuhkan DBD',
fakta: 'Belum ada bukti ilmiah yang kuat. Namun dapat dikonsumsi sebagai pendamping terapi medis',
},
{
id: 2,
mitos: 'DBD hanya menyerang anak-anak',
fakta: 'DBD dapat menyerang siapa saja terlepas dari usia',
},
{
id: 3,
mitos: 'Nyamuk DBD hanya aktif pada malam hari',
fakta: 'Nyamuk Aedes aegypti aktif pada pagi dan sore hari',
},
{
id: 4,
mitos: 'Sekali terkena DBD, tidak akan terkena lagi',
fakta: 'Seseorang bisa terkena DBD hingga 4 kali karena terdapat 4 serotipe virus dengue',
},
]
function Page() {
const rows = dataMitos.map((element) => (
<TableTr key={element.mitos}>
<TableTd fz={'h4'}>{element.mitos}</TableTd>
<TableTd fz={'h4'}>{element.fakta}</TableTd>
</TableTr>
));
return (
<div>
Page
</div>
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
<Box px={{ base: 'md', md: 100 }}>
<BackButton />
</Box>
<Box px={{ base: "md", md: 100 }}>
<Stack gap={'lg'}>
<Paper radius={10}>
<Box style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10 }} bg={colors['blue-button']}>
<Text p={'md'} fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw={"bold"}>
Detail Lengkap Fasilitas Kesehatan
</Text>
</Box>
<Box p={'md'} >
<Stack gap={'xs'}>
<Center bg={'#DEE3E3FF'}>
<Image
w={'100%'}
src={'/api/img/dbd.png'}
alt='' />
</Center>
<Flex gap={'xs'}>
<Box>
<Text c={'#9A9D9DFF'} fz={{ base: 'h6', md: 'h5' }}>
12 Februari 2025
</Text>
</Box>
<Divider size="1" orientation="vertical" />
<Box>
<Text c={'#9A9D9DFF'} fz={{ base: 'h6', md: 'h5' }}>
Dinas Kesehatan
</Text>
</Box>
<Divider size="1" orientation="vertical" />
<Box>
<Text c={'#9A9D9DFF'} fz={{ base: 'h6', md: 'h5' }}>
Kategori: Kesehatan Masyarakat
</Text>
</Box>
</Flex>
{/* Pendahuluan */}
<Text fz={'h4'} fw={"bold"}>
Pendahuluan
</Text>
<Divider />
<Text pb={10} fz={'h4'} ta={'justify'}>
Demam Berdarah Dengue (DBD) adalah penyakit yang disebabkan oleh virus dengue yang ditularkan melalui gigitan nyamuk Aedes aegypti. Selama musim hujan, risiko penyebaran DBD meningkat karena genangan air menjadi tempat berkembang biaknya nyamuk. Artikel ini akan membahas cara efektif untuk mencegah dan menangani DBD di musim hujan.
</Text>
{/* Kenali Gejala DBD */}
<Text fz={'h4'} fw={"bold"}>
Kenali Gejala DBD
</Text>
<Divider />
<Text fz={'h4'}>
Gejala awal DBD seringkali mirip dengan flu biasa, namun ada beberapa tanda khas yang perlu diwaspadai:
</Text>
<List pb={10}>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Demam tinggi mendadak <Text span fz={'h4'}>(38-40°C) yang berlangsung 2-7 hari</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Nyeri pada sendi, otot, dan tulang <Text span fz={'h4'}>yang sangat mengganggu</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Ruam kemerahan <Text span fz={'h4'}>pada kulit yang muncul 3-4 hari setelah demam</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Nyeri di belakang mata <Text span fz={'h4'}>yang bertambah parah saat menggerakkan mata</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Pendarahan <Text span fz={'h4'}>seperti mimisan, gusi berdarah, atau lebam pada kulit</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Penurunan jumlah trombosit <Text span fz={'h4'}>dalam pemeriksaan darah</Text>
</Text>
</ListItem>
</List>
{/* Cara Mencegah DBD */}
<Text fz={'h4'} fw={"bold"}>
Cara Mencegah DBD
</Text>
<Divider />
<List pb={10} type='ordered'>
<ListItem >
<Text pb={10} fz={'h4'} fw={"bold"}>
3M Plus:
</Text>
<List pb={5}>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Menguras <Text span fz={'h4'}>tempat penampungan air minimal seminggu sekali</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Menutup <Text span fz={'h4'}>rapat tempat penampungan air</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Mengubur <Text span fz={'h4'}>atau mendaur ulang barang bekas yang dapat menampung air</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Plus: <Text span fz={'h4'}>menanam tanaman pengusir nyamuk, memelihara ikan pemakan jentik, dan menggunakan kelambu saat tidur</Text>
</Text>
</ListItem>
</List>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Penggunaan repellent atau lotion anti nyamuk <Text span fz={'h4'}>terutama pada pagi dan sore hari saat nyamuk DBD aktif</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Pemasangan kawat kasa <Text span fz={'h4'}>pada ventilasi rumah</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Fogging atau pengasapan <Text span fz={'h4'}>pada area dengan kasus DBD tinggi (dilakukan oleh petugas kesehatan)</Text>
</Text>
</ListItem>
<ListItem>
<Text pb={10} fz={'h4'} fw={"bold"}>
Bubuk abate <Text span fz={'h4'}>yang ditaburkan pada penampungan air yang sulit dikuras</Text>
</Text>
</ListItem>
</List>
{/* Pertolongan Pertama Pada Penderita DBD */}
<Text fz={'h4'} fw={"bold"}>
Pertolongan Pertama Pada Penderita DBD
</Text>
<Divider />
<List pb={10} type='ordered'>
<ListItem fz={'h4'}>
Berikan banyak cairan untuk mencegah dehidrasi
</ListItem>
<ListItem fz={'h4'}>
Kompres hangat untuk menurunkan demam (hindari kompres dingin)
</ListItem>
<ListItem fz={'h4'}>
Istirahat yang cukup dan pemberian paracetamol untuk meredakan demam (hindari obat aspirin dan ibuprofen)
</ListItem>
<ListItem fz={'h4'}>
Pantau gejala penurunan trombosit seperti bintik merah pada kulit
</ListItem>
<ListItem fz={'h4'}>
Segera bawa ke fasilitas kesehatan jika demam tidak turun setelah 2 hari
</ListItem>
</List>
{/* Mitos dan Fakta tentang DBD */}
<Text fz={'h4'} fw={"bold"}>
Mitos dan Fakta tentang DBD
</Text>
<Divider />
<Table pb={10} highlightOnHover withTableBorder withColumnBorders>
<TableThead>
<TableTr>
<TableTh fz={'h4'}>Mitos</TableTh>
<TableTh fz={'h4'}>Fakta</TableTh>
</TableTr>
</TableThead>
<TableTbody>{rows}</TableTbody>
</Table>
{/* Kapan Harus ke Dokter */}
<Text fz={'h4'} fw={"bold"}>
Kapan Harus ke Dokter?
</Text>
<Divider />
<Text fz={'h4'}>
Segera bawa penderita ke fasilitas kesehatan jika mengalami:
</Text>
<List pb={10}>
<ListItem fz={'h4'}>Demam tinggi yang tidak turun setelah 2 hari</ListItem>
<ListItem fz={'h4'}>Muntah terus-menerus</ListItem>
<ListItem fz={'h4'}>Nyeri perut yang hebat</ListItem>
<ListItem fz={'h4'}>Perdarahan dari hidung atau gusi</ListItem>
<ListItem fz={'h4'}>Bintik merah pada kulit (petekie)</ListItem>
<ListItem fz={'h4'}>Sulit bernapas</ListItem>
<ListItem fz={'h4'}>Gelisah atau letargi</ListItem>
<ListItem fz={'h4'}>Penurunan kesadaran</ListItem>
</List>
{/* Kasus DBD di Wilayah Abiansemal */}
<Text fz={'h4'} fw={"bold"}>
Kasus DBD di Wilayah Abiansemal
</Text>
<Divider />
<Paper p={'lg'} bg={colors['blue-button-trans']}>
<Text fz={'h3'} c={colors['white-1']} fw={'bold'}>Informasi Lebih Lanjut</Text>
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
Hotline DBD : <Text span fz={'h4'}>(0361) 123456</Text>
</Text>
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
WhatsApp Center : <Text span fz={'h4'}>081234567890</Text>
</Text>
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
Email : <Text span fz={'h4'}>
p2p@dinkes.badungkab.go.id</Text>
</Text>
</Paper>
{/* Referensi */}
<Text fz={'h4'} fw={"bold"}>
Referensi
</Text>
<Divider />
<List pb={10} type='ordered'>
<ListItem fz={'h4'}>Kementerian Kesehatan RI. (2024). Pedoman Pencegahan dan Pengendalian DBD.</ListItem>
<ListItem fz={'h4'}>World Health Organization. (2024). Dengue Guidelines for Diagnosis, Treatment, Prevention and Control.</ListItem>
<ListItem fz={'h4'}>Dinas Kesehatan Kabupaten Badung. (2025). Laporan Surveilans DBD Triwulan I 2025.</ListItem>
</List>
<Group>
<Button fz={'lg'} bg={colors['blue-button']}>
Download Infografis Pencegahan DBD (PDF)
</Button>
<Button fz={'lg'} bg={'green'}>
Bagikan Artikel Ini
</Button>
</Group>
</Stack>
</Box>
</Paper>
</Stack>
</Box>
</Stack>
);
}
export default Page;

View File

@@ -1,11 +1,233 @@
import React from 'react';
'use client'
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
import colors from '@/con/colors';
import { ActionIcon, Box, Button, CheckIcon, Combobox, ComboboxChevron, ComboboxOption, ComboboxOptions, ComboboxTarget, Divider, Group, InputBase, InputPlaceholder, List, ListItem, Paper, Stack, Text, Textarea, TextInput, useCombobox } from '@mantine/core';
import { DateInput } from '@mantine/dates';
import { IconCalendar } from '@tabler/icons-react';
import { useState } from 'react';
const layanan = [
'Penimbangan',
'Imunisasi',
'Vitamin A',
'Konsultasi Gizi',
'Pemeriksaan Kesehatan'
];
function Page() {
const combobox = useCombobox({
onDropdownClose: () => combobox.resetSelectedOption(),
onDropdownOpen: (eventSource) => {
if (eventSource === 'keyboard') {
combobox.selectActiveOption();
} else {
combobox.updateSelectedOptionIndex('active');
}
},
});
const [value, setValue] = useState<string | null>('');
const options = layanan.map((item) => (
<ComboboxOption value={item} key={item} active={item === value}>
<Group gap="xs">
{item === value && <CheckIcon size={12} />}
<span>{item}</span>
</Group>
</ComboboxOption>
));
const [dateInputOpened, setDateInputOpened] = useState(false);
const pickerControl = (
<ActionIcon onClick={() => setDateInputOpened(true)} variant="subtle" color="gray">
<IconCalendar size={18} />
</ActionIcon>
);
return (
<div>
Page
</div>
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
<Box px={{ base: 'md', md: 100 }}>
<BackButton />
</Box>
<Box px={{ base: "md", md: 100 }}>
<Stack gap={'lg'}>
<Paper radius={10}>
<Box style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10 }} bg={colors['blue-button']}>
<Text p={'md'} fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw={"bold"}>
Detail & Pendaftaran Kegiatan
</Text>
</Box>
<Box p={'md'} >
<Stack gap={'xs'}>
{/* Informasi Kegiatan */}
<Text fz={'h4'} fw={"bold"}>
Informasi Kegiatan
</Text>
<Divider />
<Text fz={'h4'} fw={"bold"}>
Nama Kegiatan : <Text span fz={'h4'}>Posyandu Balita</Text>
</Text>
<Text fz={'h4'} fw={"bold"}>
Tanggal : <Text span fz={'h4'}>21 Februari 2025</Text>
</Text>
<Text fz={'h4'} fw={"bold"}>
Waktu : <Text span fz={'h4'}>08:00-12:00 WITA</Text>
</Text>
<Text pb={10} fz={'h4'} fw={"bold"}>
Lokasi : <Text span fz={'h4'}>Banjar Gulingan</Text>
</Text>
{/* Deskripsi Kegiatan */}
<Text fz={'h4'} fw={"bold"}>
Deskripsi Kegiatan
</Text>
<Divider />
<Text pb={10} ta={'justify'} fz={'h4'}>
Posyandu balita adalah program kesehatan rutin untuk memantau tumbuh kembang balita. Kegiatan ini meliputi penimbangan berat badan, pengukuran tinggi badan, pemeriksaan kesehatan dasar, imunisasi, dan konsultasi gizi.
</Text>
{/* Layanan Yang Tersedia */}
<Text fz={'h4'} fw={"bold"}>
Layanan Yang Tersedia
</Text>
<Divider />
<List pb={10}>
<ListItem fz={'h4'}>Penimbangan berat badan</ListItem>
<ListItem fz={'h4'}>Pengukuran tinggi badan</ListItem>
<ListItem fz={'h4'}>Imunisasi rutin</ListItem>
<ListItem fz={'h4'}>Pemberian vitamin A</ListItem>
<ListItem fz={'h4'}>Konsultasi pertumbuhan dan gizi</ListItem>
<ListItem fz={'h4'}>Pemeriksaan kesehatan dasar</ListItem>
</List>
{/* Syarat dan Ketentuan */}
<Text fz={'h4'} fw={"bold"}>
Syarat dan Ketentuan
</Text>
<Divider />
<List pb={10}>
<ListItem fz={'h4'}>Balita berusia 0-5 tahun</ListItem>
<ListItem fz={'h4'}>Membawa KMS (Kartu Menuju Sehat)</ListItem>
<ListItem fz={'h4'}>Membawa buku KIA (Kesehatan Ibu dan Anak)</ListItem>
<ListItem fz={'h4'}>Orang tua/wali wajib mendampingi</ListItem>
<ListItem fz={'h4'}>Balita dalam kondisi sehat (tidak demam)</ListItem>
</List>
{/* Dokumen yang Perlu Dibawa */}
<Text fz={'h4'} fw={"bold"}>
Dokumen yang Perlu Dibawa
</Text>
<Divider />
<List pb={10}>
<ListItem fz={'h4'}>KMS (Kartu Menuju Sehat)</ListItem>
<ListItem fz={'h4'}>Buku KIA (Kesehatan Ibu dan Anak)</ListItem>
<ListItem fz={'h4'}>KTP orang tua/wali</ListItem>
<ListItem fz={'h4'}>Kartu Keluarga</ListItem>
<ListItem fz={'h4'}>Kartu BPJS (jika ada)</ListItem>
</List>
{/* Pendaftaran */}
<Text fz={'h4'} fw={"bold"}>
Pendaftaran
</Text>
<Divider />
<Stack gap={'xs'} pb={20}>
<TextInput
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
label="Nama Balita"
placeholder='Masukkan nama balita'
/>
<DateInput
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
placeholder='dd/mm/yyyy'
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
label="Tanggal Lahir"
popoverProps={{ opened: dateInputOpened, onChange: setDateInputOpened }}
rightSection={pickerControl}
/>
<TextInput
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
label="Nama Orang Tua / Wali"
placeholder='Masukkan nama orang tua / wali'
/>
<TextInput
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
label="No. Telepon"
placeholder='Masukkan no. telepon'
/>
<TextInput
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
label="Alamat"
placeholder='Masukkan alamat lengkap'
/>
{/* Layanan */}
<Text fz={'16px'} fw={"bold"}>
Layananan Yang Dibutuhkan
</Text>
<Box
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
>
<Combobox
store={combobox}
resetSelectionOnOptionHover
withinPortal={false}
onOptionSubmit={(val) => {
setValue(val);
combobox.updateSelectedOptionIndex('active');
}}
>
<ComboboxTarget targetType="button">
<InputBase
component="button"
type="button"
pointer
rightSection={<ComboboxChevron />}
rightSectionPointerEvents="none"
onClick={() => combobox.toggleDropdown()}
>
{value || <InputPlaceholder>Layanan</InputPlaceholder>}
</InputBase>
</ComboboxTarget>
<Combobox.Dropdown>
<ComboboxOptions>{options}</ComboboxOptions>
</Combobox.Dropdown>
</Combobox>
</Box>
<Textarea
pb={10}
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }} w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
label="Catatan Khusus (Opsional)"
placeholder='Masukkan catatan jika ada'
/>
<Button
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
fz={'md'} bg={colors['blue-button']}>
Daftar Sekarang
</Button>
</Stack>
<Paper p={'lg'} bg={colors['blue-button-trans']}>
<Text fz={'h3'} c={colors['white-1']} fw={'bold'}>Informasi Kontak</Text>
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
Penanggung Jawab : <Text span fz={'h4'}>Bidan Komang Ayu</Text>
</Text>
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
Telepon : <Text span fz={'h4'}>081234567890</Text>
</Text>
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
Email : <Text span fz={'h4'}>puskesmasabiansemal3@gmail.com</Text>
</Text>
</Paper>
<Group>
<Button fz={'lg'} bg={'green'}>
Download Jadwal Posyandu 2025 (PDF)
</Button>
</Group>
</Stack>
</Box>
</Paper>
</Stack>
</Box>
</Stack>
);
}
export default Page;

View File

@@ -146,7 +146,7 @@ function Page() {
Layanan Unggulan: Poli Umum, Poli Gigi, Imunisasi, Ibu/KB
</Text>
<Anchor component={Link} href={'/darmasaba/kesehatan/data-kesehatan-warga/fasilitas-kesehatan'} c={'black'} variant='transparent'>
<Text c={'black'} fz={'h4'}>
<Text c={colors['blue-button']} fz={'h4'}>
Detail Lengkap {'>>'}
</Text>
</Anchor>
@@ -167,7 +167,7 @@ function Page() {
Layanan Unggulan: Poli Umum, Poli Gigi, Imunisasi, Ibu/KB
</Text>
<Anchor component={Link} href={'/darmasaba/kesehatan/data-kesehatan-warga/fasilitas-kesehatan'} c={'black'} variant='transparent'>
<Text c={'black'} fz={'h4'}>
<Text c={colors['blue-button']} fz={'h4'}>
Detail Lengkap {'>>'}
</Text>
</Anchor>
@@ -188,7 +188,7 @@ function Page() {
Layanan Unggulan: Poli Umum, Poli Gigi, Imunisasi, Ibu/KB
</Text>
<Anchor component={Link} href={'/darmasaba/kesehatan/data-kesehatan-warga/fasilitas-kesehatan'} c={'black'} variant='transparent'>
<Text c={'black'} fz={'h4'}>
<Text c={colors['blue-button']} fz={'h4'}>
Detail Lengkap {'>>'}
</Text>
</Anchor>
@@ -215,7 +215,7 @@ function Page() {
<Text fz={'h4'}>
Banjar Gulingan
</Text>
<Anchor c={colors['blue-button']} variant='transparent'>
<Anchor component={Link} href={'/darmasaba/kesehatan/data-kesehatan-warga/jadwal-kegiatan'} c={colors['blue-button']} variant='transparent'>
<Text c={colors['blue-button']} fz={'h4'} >
Detail & Pendaftaran
</Text>
@@ -235,7 +235,7 @@ function Page() {
<Text fz={'h4'}>
Puskesmas Abiansemal III
</Text>
<Anchor c={colors['blue-button']} variant='transparent'>
<Anchor component={Link} href={'/darmasaba/kesehatan/data-kesehatan-warga/jadwal-kegiatan'} c={colors['blue-button']} variant='transparent'>
<Text c={colors['blue-button']} fz={'h4'} >
Detail & Pendaftaran
</Text>
@@ -260,8 +260,8 @@ function Page() {
<Text fz={'h4'} pb={10}>
Yuk Kenali gelaja dan cara penanganan DBD yang efektif untuk melindungi keluarga anda selama musim hujan.
</Text>
<Anchor c={'black'} variant='transparent'>
<Text c={'black'} fz={'h4'} >
<Anchor c={'black'} component={Link} href={'/darmasaba/kesehatan/data-kesehatan-warga/artikel-kesehatan'} variant='transparent'>
<Text c={colors['blue-button']} fz={'h4'} >
Baca Selengkapnya {'>>'}
</Text>
</Anchor>
@@ -279,8 +279,8 @@ function Page() {
<Text fz={'h4'} pb={10}>
Yuk Kenali gelaja dan cara penanganan DBD yang efektif untuk melindungi keluarga anda selama musim hujan.
</Text>
<Anchor c={'black'} variant='transparent'>
<Text c={'black'} fz={'h4'} >
<Anchor c={'black'} href={'/darmasaba/kesehatan/data-kesehatan-warga/artikel-kesehatan'} variant='transparent'>
<Text c={colors['blue-button']} fz={'h4'} >
Baca Selengkapnya {'>>'}
</Text>
</Anchor>

View File

@@ -9,8 +9,7 @@ import 'react-simple-toasts/dist/theme/dark.css';
import "./globals.css";
import '@mantine/charts/styles.css';
import '@mantine/dates/styles.css';
import '@mantine/tiptap/styles.css';
import LoadDataFirstClient from "@/app/darmasaba/_com/LoadDataFirstClient";
import {
@@ -20,6 +19,7 @@ import {
mantineHtmlProps,
} from "@mantine/core";
import { ViewTransitions } from "next-view-transitions";
import { ToastContainer } from "react-toastify";
export const metadata = {
title: "Desa Darmasaba",
@@ -53,7 +53,11 @@ export default function RootLayout({
<body>
<MantineProvider theme={theme}>
{children}
</MantineProvider>
<ToastContainer position="bottom-center" hideProgressBar style={{
zIndex: 9999
}} />
</body>
<LoadDataFirstClient />
</html>