UI Admin Menu Desa Sub Menu Profile

This commit is contained in:
2025-05-15 17:47:43 +08:00
parent 2844132ea0
commit f5d68d4982
51 changed files with 1603 additions and 865 deletions

View File

@@ -56,6 +56,7 @@ const caraMemperolehSalinanInformasi = proxy({
}
}
})
console.log(caraMemperolehSalinanInformasi)
type PermohonanInformasiPublikForm = Prisma.PermohonanInformasiPublikGetPayload<{
select: {
@@ -70,12 +71,12 @@ type PermohonanInformasiPublikForm = Prisma.PermohonanInformasiPublikGetPayload<
};
}>;
const permohonanInformasiPublikForm = proxy({
const statepermohonanInformasiPublik = proxy({
create: {
form: {} as PermohonanInformasiPublikForm,
loading: false,
async create(){
const cek = templateForm.safeParse(permohonanInformasiPublikForm.create.form);
const cek = templateForm.safeParse(statepermohonanInformasiPublik.create.form);
if(!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
@@ -83,38 +84,42 @@ const permohonanInformasiPublikForm = proxy({
return toast.error(err);
}
try {
permohonanInformasiPublikForm.create.loading = true;
const res = await ApiFetch.api.ppid.permohonaninformasipublik["create"].post(permohonanInformasiPublikForm.create.form);
statepermohonanInformasiPublik.create.loading = true;
const res = await ApiFetch.api.ppid.permohonaninformasipublik["create"].post(statepermohonanInformasiPublik.create.form);
if (res.status === 200) {
permohonanInformasiPublikForm.findMany.load();
statepermohonanInformasiPublik.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
permohonanInformasiPublikForm.create.loading = false;
statepermohonanInformasiPublik.create.loading = false;
}
}
},
findMany: {
data: null as
| Prisma.PermohonanInformasiPublikGetPayload<{ omit: { isActive: true } }>[]
| Prisma.PermohonanInformasiPublikGetPayload<{ include: {
caraMemperolehSalinanInformasi: true,
jenisInformasiDiminta: true,
caraMemperolehInformasi: true,
} }>[]
| null,
async load() {
const res = await ApiFetch.api.ppid.permohonaninformasipublik["find-many"].get();
if (res.status === 200) {
permohonanInformasiPublikForm.findMany.data = res.data?.data ?? [];
statepermohonanInformasiPublik.findMany.data = res.data?.data ?? [];
}
}
}
})
const statePermohonanInformasi = proxy({
permohonanInformasiPublikForm,
const statepermohonanInformasiPublikForm = proxy({
statepermohonanInformasiPublik,
jenisInformasiDiminta,
caraMemperolehInformasi,
caraMemperolehSalinanInformasi
caraMemperolehSalinanInformasi,
})
export default statePermohonanInformasi;
export default statepermohonanInformasiPublikForm;

View File

@@ -20,12 +20,12 @@ type PermohonanKeberatanInformasiForm = Prisma.FormulirPermohonanKeberatanGetPay
};
}>;
const permohonanKeberatanInformasiForm = proxy({
const permohonanKeberatanInformasi = proxy({
create: {
form: {} as PermohonanKeberatanInformasiForm,
loading: false,
async create(){
const cek = templateForm.safeParse(permohonanKeberatanInformasiForm.create.form);
const cek = templateForm.safeParse(permohonanKeberatanInformasi.create.form);
if(!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
@@ -33,17 +33,17 @@ const permohonanKeberatanInformasiForm = proxy({
return toast.error(err);
}
try {
permohonanKeberatanInformasiForm.create.loading = true;
const res = await ApiFetch.api.ppid.permohonankeberataninformasipublik["create"].post(permohonanKeberatanInformasiForm.create.form);
permohonanKeberatanInformasi.create.loading = true;
const res = await ApiFetch.api.ppid.permohonankeberataninformasipublik["create"].post(permohonanKeberatanInformasi.create.form);
if (res.status === 200) {
permohonanKeberatanInformasiForm.findMany.load();
permohonanKeberatanInformasi.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
permohonanKeberatanInformasiForm.create.loading = false;
permohonanKeberatanInformasi.create.loading = false;
}
},
},
@@ -54,15 +54,11 @@ const permohonanKeberatanInformasiForm = proxy({
async load() {
const res = await ApiFetch.api.ppid.permohonankeberataninformasipublik["find-many"].get();
if (res.status === 200) {
permohonanKeberatanInformasiForm.findMany.data = res.data?.data ?? [];
permohonanKeberatanInformasi.findMany.data = res.data?.data ?? [];
}
}
}
});
const statePermohonanKeberatan = proxy({
permohonanKeberatanInformasiForm,
})
export default statePermohonanKeberatan;
export default permohonanKeberatanInformasi;

View File

@@ -0,0 +1,93 @@
'use client'
import colors from '@/con/colors';
import { Button, Stack } from '@mantine/core';
import { Link, RichTextEditor } from '@mantine/tiptap';
import Highlight from '@tiptap/extension-highlight';
import SubScript from '@tiptap/extension-subscript';
import Superscript from '@tiptap/extension-superscript';
import TextAlign from '@tiptap/extension-text-align';
import Underline from '@tiptap/extension-underline';
import { useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
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 DesaEditor({showSubmit = true} : {
showSubmit: boolean
}) {
const editor = useEditor({
extensions: [
StarterKit,
Underline,
Link,
Superscript,
SubScript,
Highlight,
TextAlign.configure({ types: ['heading', 'paragraph'] }),
],
immediatelyRender: false,
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>
{showSubmit && (
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
)}
</Stack>
);
}

View File

@@ -0,0 +1,95 @@
'use client'
import { Button, Stack } from '@mantine/core';
import { Link, RichTextEditor } from '@mantine/tiptap';
import Highlight from '@tiptap/extension-highlight';
import SubScript from '@tiptap/extension-subscript';
import Superscript from '@tiptap/extension-superscript';
import TextAlign from '@tiptap/extension-text-align';
import Underline from '@tiptap/extension-underline';
import { useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
function DesaEditorText({ onSubmit, onChange, showSubmit = true, initialContent = '', }: {
onSubmit?: (val: string) => void,
onChange: (val: string) => void,
showSubmit?: boolean,
initialContent?: string }) {
const editor = useEditor({
extensions: [
StarterKit,
Underline,
Link,
Superscript,
SubScript,
Highlight,
TextAlign.configure({ types: ['heading', 'paragraph'] }),
],
immediatelyRender: false,
content: initialContent,
onUpdate : ({editor}) => {
onChange(editor.getHTML())
}
});
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>
{showSubmit && (
<Button onClick={() => {
if (!editor) return
onSubmit?.(editor?.getHTML())
}}>Submit</Button>
)}
</Stack>
);
}
export default DesaEditorText;

View File

@@ -1,10 +1,52 @@
import colors from '@/con/colors';
import { Stack, Title, Tabs, TabsList, TabsTab, TabsPanel } from '@mantine/core';
import React from 'react';
import SejarahDesa from './ui/sejarah_desa/page';
import VisiMisiDesa from './ui/visi_misi_desa/page';
import LambangDesa from './ui/lambang_desa/page';
import MaskotDesa from './ui/maskot_desa/page';
import ProfilePerbekel from './ui/profile_perbekel/page';
function Page() {
return (
<div>
Profile
</div>
<Stack >
<Title order={3}>Profile Desa</Title>
<Tabs color={colors['blue-button']} variant='pills' defaultValue={"Sejarah Desa"}>
<TabsList p={"xs"} bg={"#BBC8E7FF"}>
<TabsTab value="Sejarah Desa">
Sejarah Desa
</TabsTab>
<TabsTab value="Visi Misi Desa">
Visi Misi Desa
</TabsTab>
<TabsTab value="Lambang Desa">
Lambang Desa
</TabsTab>
<TabsTab value="Maskot Desa">
Maskot Desa
</TabsTab>
<TabsTab value="Profile Perbekel">
Profile Perbekel
</TabsTab>
</TabsList>
<TabsPanel value="Sejarah Desa">
<SejarahDesa/>
</TabsPanel>
<TabsPanel value="Visi Misi Desa">
<VisiMisiDesa/>
</TabsPanel>
<TabsPanel value="Lambang Desa">
<LambangDesa/>
</TabsPanel>
<TabsPanel value="Maskot Desa">
<MaskotDesa/>
</TabsPanel>
<TabsPanel value="Profile Perbekel">
<ProfilePerbekel/>
</TabsPanel>
</Tabs>
</Stack>
);
}

View File

@@ -0,0 +1,39 @@
import colors from '@/con/colors';
import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, Text } from '@mantine/core';
import React from 'react';
import { DesaEditor } from '../../../_com/desaEditor';
function LambangDesa() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Lambang Desa</Title>
<Text fw={"bold"}>Deskripsi Lambang Desa</Text>
<DesaEditor showSubmit={false} />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Lambang Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default LambangDesa;

View File

@@ -0,0 +1,39 @@
import colors from '@/con/colors';
import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, Text } from '@mantine/core';
import React from 'react';
import { DesaEditor } from '../../../_com/desaEditor';
function MaskotDesa() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Maskot Desa</Title>
<Text fw={"bold"}>Deskripsi Maskot Desa</Text>
<DesaEditor showSubmit={false} />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Maskot Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default MaskotDesa;

View File

@@ -0,0 +1,49 @@
import colors from '@/con/colors';
import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, TextInput, Text } from '@mantine/core';
import React from 'react';
import { DesaEditor } from '../../../_com/desaEditor';
function ProfilePerbekel() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Profil Perbekel</Title>
<TextInput
label="Nama Perbekel"
placeholder="masukkan nama perbekel"
/>
<Text fz={"sm"} fw={"bold"}>Biodata</Text>
<DesaEditor showSubmit={false} />
<Text fz={"sm"} fw={"bold"}>Pengalaman</Text>
<DesaEditor showSubmit={false} />
<Text fz={"sm"} fw={"bold"}>Pengalaman Organisasi</Text>
<DesaEditor showSubmit={false} />
<Text fz={"sm"} fw={"bold"}>Program Unggulan</Text>
<DesaEditor showSubmit={false} />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Profil Perbekel</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default ProfilePerbekel;

View File

@@ -0,0 +1,38 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
import { DesaEditor } from '../../../_com/desaEditor';
function SejarahDesa() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Sejarah Desa</Title>
<Text fw={"bold"}>Deskripsi Sejarah Desa</Text>
<DesaEditor showSubmit={false}/>
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Sejarah Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default SejarahDesa;

View File

@@ -0,0 +1,64 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
import { DesaEditor } from '../../../_com/desaEditor';
function VisiMisiDesa() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Visi Desa</Title>
<Text fw={"bold"}>Deskripsi Visi Desa</Text>
<DesaEditor showSubmit={false} />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Visi Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
<SimpleGrid py={30} cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Misi Desa</Title>
<Text fw={"bold"}>Deskripsi Misi Desa</Text>
<DesaEditor showSubmit={false}/>
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Misi Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default VisiMisiDesa;

View File

@@ -10,7 +10,7 @@ import { useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
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>';
'<p>Dokumen yang berisi kebijakan dan regulasi desa</p>';
export function PPIDEditor({ onSubmit, onChange, showSubmit = true }: {
onSubmit?: (val: string) => void,

View File

@@ -1,11 +1,10 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, TextInput, Title } from '@mantine/core';
import React from 'react';
import { useShallowEffect } from '@mantine/hooks';
import { useProxy } from 'valtio/utils';
import stateDaftarInformasiPublik from '../../_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
import { PPIDEditor } from '../_com/ppid_Editor';
import colors from '@/con/colors';
import { useShallowEffect } from '@mantine/hooks';
import { PPIDTextEditor } from '../_com/PPIDTextEditor';
function Page() {
const daftarInformasi = useProxy(stateDaftarInformasiPublik.daftarInformasi)
@@ -30,7 +29,7 @@ function Page() {
daftarInformasi.create.form.jenisInformasi = val.target.value
}}
/>
<PPIDEditor
<PPIDTextEditor
showSubmit={false}
onChange={(val) => {
daftarInformasi.create.form.deskripsi = val
@@ -68,46 +67,50 @@ function ListDaftarInformasi() {
if (!listData.findMany.data) return <Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return <Paper bg={colors['white-1']} p={'md'}>
<Stack gap={"xs"}>
<Title fw={"bold"} order={3}>List Daftar Informasi Publik Desa Darmasaba</Title>
<Table
suppressHydrationWarning
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead>
<TableTr>
<TableTh>
No
</TableTh>
<TableTh>
Jenis Informasi
</TableTh>
<TableTh>
Deskripsi
</TableTh>
<TableTh>
Tanggal Publikasi
</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{listData.findMany.data?.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.nomor}</TableTd>
<TableTd>{item.jenisInformasi}</TableTd>
<TableTd dangerouslySetInnerHTML={{ __html: item.deskripsi }}></TableTd>
<TableTd>{item.tanggal}</TableTd>
</TableTr>
))}
</TableTbody>
</Table>
</Stack>
</Paper>
return (
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack gap={"xs"}>
<Title fw={"bold"} order={3}>List Daftar Informasi Publik Desa Darmasaba</Title>
<Table
suppressHydrationWarning
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead>
<TableTr>
<TableTh>
No
</TableTh>
<TableTh>
Jenis Informasi
</TableTh>
<TableTh>
Deskripsi
</TableTh>
<TableTh>
Tanggal Publikasi
</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{listData.findMany.data?.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.nomor}</TableTd>
<TableTd>{item.jenisInformasi}</TableTd>
<TableTd dangerouslySetInnerHTML={{ __html: item.deskripsi }}></TableTd>
<TableTd>{item.tanggal}</TableTd>
</TableTr>
))}
</TableTbody>
</Table>
</Stack>
</Paper>
</Box>
)
}
export default Page;

View File

@@ -1,4 +1,4 @@
import { Stack, Tabs, TabsList, TabsPanel, TabsTab } from '@mantine/core';
import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import React from 'react';
import colors from '@/con/colors';
import GrafikHasilKepuasan from './_ui/grafik_hasil_kepuasan_masyarakat/page';
@@ -8,9 +8,10 @@ import GrafikBerdasarakanUmur from './_ui/grafik_berdasarkan_umur/page';
function Page() {
return (
<Stack>
<Tabs color={colors['blue-button']} variant='pills' defaultValue={"Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik"}>
<TabsList>
<Stack >
<Title order={3}>Indeks Kepuasan Masyarakat (IKM) Desa Darmasaba</Title>
<Tabs color={colors['blue-button']} variant='pills' defaultValue={"Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik"}>
<TabsList p={"xs"} bg={"#BBC8E7FF"}>
<TabsTab value="Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik">
Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
</TabsTab>

View File

@@ -1,41 +0,0 @@
import { Prisma } from '@prisma/client';
import React from 'react';
import { useProxy } from 'valtio/utils';
import statePermohonanInformasi from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
import { useShallowEffect } from '@mantine/hooks';
import { Group, Select, Skeleton } from '@mantine/core';
function JenisInformasi({ onChange }: {
onChange: (value: Prisma.JenisInformasiDimintaGetPayload<{
select: {
id: true,
name: true
}
}>) => void
}) {
const jenisInformasiState = useProxy(statePermohonanInformasi.jenisInformasiDiminta)
useShallowEffect(() => {
jenisInformasiState.findMany.load()
}, [])
if (!jenisInformasiState.findMany.data) return <Skeleton h={40} />
return (
<Group>
<Select
placeholder='pilih jenis informasi'
label={'select jenis informasi'}
data={jenisInformasiState.findMany.data.map((item) => ({
value: item.id,
label: item.name
}))}
onChange={(v) => {
const data = jenisInformasiState.findMany.data?.find((item) => item.id === v)
if (!data) return
onChange(data)
}}
/>
</Group>
);
}
export default JenisInformasi;

View File

@@ -1,38 +0,0 @@
import { Group, Select } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { Prisma } from '@prisma/client';
import React from 'react';
import { useProxy } from 'valtio/utils';
import statePermohonanInformasi from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
function MemperolehInformasi({ onChange }: {
onChange: (value: Prisma.CaraMemperolehInformasiGetPayload<{
select: {
id: true,
name: true
}
}>) => void
}) {
const memperolehInformasiState = useProxy(statePermohonanInformasi.caraMemperolehInformasi)
useShallowEffect(() => {
memperolehInformasiState.findMany.load()
}, [])
return (
<Group>
<Select
placeholder='pilih katagori'
label={"select katagori"}
data={memperolehInformasiState.findMany.data?.map((item) => ({
value: item.id,
label: item.name
}))} onChange={(v) => {
const data = memperolehInformasiState.findMany.data?.find((item) => item.id === v)
if (!data) return
onChange(data)
}} />
</Group>
);
}
export default MemperolehInformasi;

View File

@@ -1,45 +0,0 @@
import { Group, Select, Skeleton } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { Prisma } from '@prisma/client';
import React from 'react';
import { useProxy } from 'valtio/utils';
import statePermohonanInformasi from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
function MemperolehSalinan({ onChange }: {
onChange: (value: Prisma.CaraMemperolehSalinanInformasiGetPayload<{
select: {
id: true,
name: true
}
}>) => void
}) {
const memperolehSalinanInformasiState = useProxy(statePermohonanInformasi.caraMemperolehSalinanInformasi)
useShallowEffect(() => {
memperolehSalinanInformasiState.findMany.load()
}, [])
if (!memperolehSalinanInformasiState.findMany.data) return <Skeleton h={40} />
return (
<Group>
<Select
placeholder='pilih salinan informasi'
label={'select salinan informasi'}
data={memperolehSalinanInformasiState.findMany.data.map((item) => ({
value: item.id,
label: item.name
}))}
onChange={(v) => {
if (!v) return
const selectedItem = memperolehSalinanInformasiState.findMany.data?.find(item => item.id === v)
if (selectedItem) {
onChange({
id: selectedItem.id,
name: selectedItem.name
})
}
}}
/>
</Group>
);
}
export default MemperolehSalinan;

View File

@@ -1,115 +1,57 @@
'use client'
import { Box, Button, Group, Paper, SimpleGrid, Stack, TextInput, Title } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import statePermohonanInformasi from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
import JenisInformasi from './jenisInformasi';
import MemperolehInformasi from './memperolehInformasi';
import MemperolehSalinan from './memperolehSalinan';
import colors from '@/con/colors';
import { Box, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Title } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { useShallowEffect } from '@mantine/hooks';
import statepermohonanInformasiPublikForm from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
function Page() {
const permohonanInformasiPublikState = useProxy(statepermohonanInformasiPublikForm)
useShallowEffect(() => {
permohonanInformasiPublikState.statepermohonanInformasiPublik.findMany.load()
}, [])
if (!permohonanInformasiPublikState.statepermohonanInformasiPublik.findMany.data) return <Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return (
<Box>
<Stack>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<PermohonanInformasiPublikCreate />
</SimpleGrid>
</Stack>
<Box py={5}>
<Paper bg={colors['white-1']} p={'md'}>
<Stack gap={"xs"}>
<Title order={3}>Permohonan Informasi Publik</Title>
<Box p={"xl"}>
<Table striped withRowBorders withColumnBorders withTableBorder>
<TableThead>
<TableTr>
<TableTh>No</TableTh>
<TableTh>Nama</TableTh>
<TableTh>NIK</TableTh>
<TableTh>Telepon</TableTh>
<TableTh>Email</TableTh>
<TableTh>Jenis Informasi</TableTh>
<TableTh>Cara Memperoleh Informasi</TableTh>
<TableTh>Cara Memperoleh Salinan Informasi</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{permohonanInformasiPublikState.statepermohonanInformasiPublik.findMany.data?.map((item, index) => (
<TableTr key={item.id}>
<TableTd>{index + 1}</TableTd>
<TableTd>{item.name}</TableTd>
<TableTd>{item.nik}</TableTd>
<TableTd>{item.notelp}</TableTd>
<TableTd>{item.email}</TableTd>
<TableTd>{item.jenisInformasiDiminta?.name}</TableTd>
<TableTd>{item.caraMemperolehInformasi?.name}</TableTd>
<TableTd>{item.caraMemperolehSalinanInformasi?.name}</TableTd>
</TableTr>
))}
</TableTbody>
</Table> </Box>
</Stack>
</Paper>
</Box>
);
}
function PermohonanInformasiPublikCreate() {
const permohonanInformasiPublikState = useProxy(statePermohonanInformasi)
const submitForms = () => {
// Tambahkan log untuk debugging
console.log("Form data sebelum submit:", {
name: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.name,
nik: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.nik,
notelp: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.notelp,
alamat: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.alamat,
email: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.email,
jenisInformasiDimintaId: permohonanInformasiPublikState.jenisInformasiDiminta,
caraMemperolehInformasiId: permohonanInformasiPublikState.caraMemperolehInformasi,
caraMemperolehSalinanInformasiId: permohonanInformasiPublikState.caraMemperolehSalinanInformasi
});
if (permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.name &&
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.nik &&
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.notelp &&
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.alamat &&
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.email &&
permohonanInformasiPublikState.jenisInformasiDiminta &&
permohonanInformasiPublikState.caraMemperolehInformasi &&
permohonanInformasiPublikState.caraMemperolehSalinanInformasi) {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.create()
} else {
console.log("Validasi gagal, form tidak lengkap");
// Tampilkan pesan error ke pengguna di sini
}
}
return (
<Box py={5}>
<Paper bg={colors['white-1']} p={'md'}>
<Stack gap={"10"}>
<Title order={3}>Permohonan Informasi Publik</Title>
<TextInput
label="Nama Lengkap"
placeholder="masukkan nama lengkap"
onChange={(val) => {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.name = val.target.value
}}
/>
<TextInput
label="NIK"
placeholder="masukkan NIK"
onChange={(val) => {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.nik = val.target.value
}}
/>
<TextInput
label="No.Telp"
placeholder="masukkan no telp"
onChange={(val) => {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.notelp = val.target.value
}}
/>
<TextInput
label="Alamat"
placeholder="masukkan alamat"
onChange={(val) => {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.alamat = val.target.value
}}
/>
<TextInput
label="Email"
placeholder="masukkan email"
onChange={(val) => {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.email = val.target.value
}}
/>
<JenisInformasi
onChange={(val) => {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.jenisInformasiDimintaId = val.id
}}
/>
<MemperolehInformasi
onChange={(val) => {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.caraMemperolehInformasiId = val.id
}}
/>
<MemperolehSalinan
onChange={(val) => {
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.caraMemperolehSalinanInformasiId = val.id
}}
/>
<Group>
<Button onClick={submitForms}>Submit</Button>
</Group>
</Stack>
</Paper>
</Box >
)
}
export default Page;

View File

@@ -1,73 +1,12 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core';
import React from 'react';
import { Box, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { useProxy } from 'valtio/utils';
import statePermohonanKeberatan from '../../_state/ppid/permohonan_keberatan_informasi_publik/permohonanKeberatanInformasi';
import { useShallowEffect } from '@mantine/hooks';
function Page() {
return (
<Box>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<PermohonanKeberatanInformasiCreate />
<PermohonanKeberatanInformasiList />
</SimpleGrid>
</Box>
);
}
function PermohonanKeberatanInformasiCreate() {
const state = useProxy(statePermohonanKeberatan.permohonanKeberatanInformasiForm)
const submit = () => {
if (state.create.form.name && state.create.form.email && state.create.form.notelp && state.create.form.alasan) {
state.create.create()
}
}
return (
<Box py={10}>
<Paper bg={colors['white-1']} p={'md'}>
<Stack gap={"xs"}>
<Title order={3}>Permohonan Keberatan Informasi Publik</Title>
<TextInput
label="Nama"
placeholder="masukkan nama lengkap"
onChange={(val) => {
state.create.form.name = val.target.value
}}
/>
<TextInput
label="Email"
placeholder="masukkan email"
onChange={(val) => {
state.create.form.email = val.target.value
}}
/>
<TextInput
label="Nomor Telepon"
placeholder="masukkan nomor telepon"
onChange={(val) => {
state.create.form.notelp = val.target.value
}}
/>
<TextInput
label="Alasan Keberatan"
placeholder="masukkan alasan keberatan"
onChange={(val) => {
state.create.form.alasan = val.target.value
}}
/>
<Group>
<Button onClick={submit} bg={colors['blue-button']}>Kirim Permohonan</Button>
</Group>
</Stack>
</Paper>
</Box>
)
}
function PermohonanKeberatanInformasiList() {
const listState = useProxy(statePermohonanKeberatan.permohonanKeberatanInformasiForm)
const listState = useProxy(statePermohonanKeberatan)
useShallowEffect(() => {
listState.findMany.load()
}, [])
@@ -75,24 +14,36 @@ function PermohonanKeberatanInformasiList() {
if (!listState.findMany.data) return <Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return (
<Box py={10}>
<Paper bg={colors['white-1']} p={'md'}>
<Stack gap={"xs"}>
<Title order={3}>Permohonan Keberatan Informasi Publik</Title>
{listState.findMany.data?.map((item) => (
<Box key={item.id}>
<Text>Nama: {item.name}</Text>
<Text>Email: {item.email}</Text>
<Text>Telepon: {item.notelp}</Text>
<Text>Alasan: {item.alasan}</Text>
</Box>
))}
<Table striped withRowBorders withColumnBorders withTableBorder>
<TableThead>
<TableTr>
<TableTh>No</TableTh>
<TableTh>Nama</TableTh>
<TableTh>Email</TableTh>
<TableTh>Telepon</TableTh>
<TableTh>Alasan</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{listState.findMany.data?.map((item, index) => (
<TableTr key={item.id}>
<TableTd>{index + 1}</TableTd>
<TableTd>{item.name}</TableTd>
<TableTd>{item.email}</TableTd>
<TableTd>{item.notelp}</TableTd>
<TableTd dangerouslySetInnerHTML={{ __html: item.alasan }} />
</TableTr>
))}
</TableTbody>
</Table>
</Stack>
</Paper>
</Box>
)
);
}
export default Page;

View File

@@ -1,18 +1,18 @@
'use client'
import { Box, Group, Text } from '@mantine/core';
import React, { useState } from 'react';
import { useState } from 'react';
import ApiFetch from '@/lib/api-fetch';
import { Dropzone, MIME_TYPES } from '@mantine/dropzone';
import { IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
import { useProxy } from 'valtio/utils';
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
import { Dropzone, MIME_TYPES } from '@mantine/dropzone';
import { IconUpload, IconX, IconPhoto } from '@tabler/icons-react';
import ApiFetch from '@/lib/api-fetch';
function Biodata() {
const biodataState = useProxy(stateProfilePPID)
const [loading, setLoading] = useState(false);
return (<Box>
<Text fw={"bold"}>Biodata</Text>
<Dropzone
@@ -55,6 +55,9 @@ function Biodata() {
</div>
</Group>
</Dropzone>
<PPIDTextEditor
key={biodataState.findById.data?.id ?? 'new'}
showSubmit={false}
@@ -67,8 +70,7 @@ function Biodata() {
/>
</Box>
);
}
export default Biodata;
export default Biodata;

View File

@@ -25,19 +25,16 @@ function ProfileList() {
<Title order={3}>List Profile PPID</Title>
{dataArray.map((item) => (
<Box key={item.id}>
<Box>
<Text fw={"bold"}>Gambar</Text>
{item.imageUrl ? (
{item.imageUrl && (
<Box mb={20}>
<Text fw={"bold"} mb={5}>Preview Gambar:</Text>
<Image
src={item.imageUrl}
alt="Foto Profil"
alt="Profile"
w={200}
radius="md"
/>
) : (
<Text c="dimmed">Belum ada foto</Text>
)}
</Box>
</Box>
)}
<Box>
<Text fw={"bold"}>Nama</Text>
<Text dangerouslySetInnerHTML={{ __html: item.name }}></Text>