API & UI Menu Inovasi & Submenu Layan Online Desa 2 tabs

This commit is contained in:
2025-07-16 00:20:55 +08:00
parent e8ad74d118
commit 55433128a9
45 changed files with 2566 additions and 399 deletions

View File

@@ -1,10 +1,40 @@
'use client'
import ajukanIdeInovatifState from '@/app/admin/(dashboard)/_state/inovasi/ajukan-ide-inovatif';
import colors from '@/con/colors';
import { Stack, Box, Text, SimpleGrid, Paper, List, ListItem, Flex, ActionIcon } from '@mantine/core';
import React from 'react';
import BackButton from '../../desa/layanan/_com/BackButto';
import { ActionIcon, Box, Button, Flex, List, ListItem, Modal, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { IconArrowRight, IconBulbFilled } from '@tabler/icons-react';
import { useProxy } from 'valtio/utils';
import BackButton from '../../desa/layanan/_com/BackButto';
import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor';
function Page() {
const [opened, { open, close }] = useDisclosure(false);
const ideInovatif = useProxy(ajukanIdeInovatifState)
const resetForm = () => {
// Reset state di valtio
ideInovatif.create.form = {
name: "",
deskripsi: "",
alamat: "",
namaIde: "",
masalah: "",
benefit: "",
};
// Reset state lokal
};
const handleSubmit = async () => {
// Submit data berita
await ideInovatif.create.create();
// Reset form setelah submit
resetForm();
close();
};
return (
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
<Box px={{ base: 'md', md: 100 }}>
@@ -40,7 +70,7 @@ function Page() {
<IconArrowRight size={30} color={colors['blue-button']} />
</Box>
<Box px={{ base: 5, md: 10 }} py={5}>
<ActionIcon variant="transparent" size={150}>
<ActionIcon variant="transparent" size={150} onClick={open}>
<IconBulbFilled size={150} color={colors['blue-button']} />
</ActionIcon>
</Box>
@@ -49,6 +79,65 @@ function Page() {
</SimpleGrid>
</Stack>
</Box>
<Modal
opened={opened}
onClose={close}
radius={0}
transitionProps={{ transition: 'fade', duration: 200 }}
>
<Paper p={"md"} withBorder>
<Stack gap={"xs"}>
<Title order={3}>Ajukan Ide Inovatif</Title>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Nama</Text>}
placeholder="masukkan nama"
onChange={(val) => {
ideInovatif.create.form.name = val.target.value
}}
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Alamat</Text>}
placeholder="masukkan alamat"
onChange={(val) => {
ideInovatif.create.form.alamat = val.target.value
}}
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Nama Ide</Text>}
placeholder="masukkan nama ide"
onChange={(val) => {
ideInovatif.create.form.namaIde = val.target.value
}}
/>
<Box>
<Text fz={"sm"} fw={"bold"}>Deskripsi</Text>
<CreateEditor
value={ideInovatif.create.form.deskripsi}
onChange={(htmlContent) => {
ideInovatif.create.form.deskripsi = htmlContent;
}}
/>
</Box>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Masalah</Text>}
placeholder="masukkan masalah"
onChange={(val) => {
ideInovatif.create.form.masalah = val.target.value
}}
/>
<TextInput
label={<Text fz={"sm"} fw={"bold"}>Benefit</Text>}
placeholder="masukkan benefit"
onChange={(val) => {
ideInovatif.create.form.benefit = val.target.value
}}
/>
<Button bg={colors['blue-button']} onClick={handleSubmit}>Simpan</Button>
</Stack>
</Paper>
</Modal>
</Stack>
);
}

View File

@@ -0,0 +1,117 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import layananonlineDesa from '@/app/admin/(dashboard)/_state/inovasi/layanan-online-desa';
import colors from '@/con/colors';
import {
Box,
Button,
Modal,
Paper,
Select,
Stack,
Text,
TextInput,
Title,
} from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { IconFileCheckFilled } from '@tabler/icons-react';
import { motion } from 'framer-motion';
import { useEffect } from 'react';
import { useProxy } from 'valtio/utils';
function AdministrasiOnline() {
const [opened, { open, close }] = useDisclosure(false);
const state = useProxy(layananonlineDesa);
useEffect(() => {
// ✅ Panggil load data jenis layanan dari backend
if (!state.jenisLayanan.findMany.data) {
state.jenisLayanan.findMany.load();
}
}, []);
const resetForm = () => {
state.administrasiOnline.create.form = {
name: '',
alamat: '',
nomorTelepon: '',
jenisLayananId: '',
};
};
const handleSubmit = async () => {
await state.administrasiOnline.create.create();
resetForm();
close(); // Tutup modal setelah submit
};
return (
<Box>
<Stack>
<motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.8 }} onClick={open}>
<Paper p="xl" withBorder>
<Box>
<IconFileCheckFilled size={50} color={colors['blue-button']} />
</Box>
<Text fz="h3" fw="bold" c={colors['blue-button']}>
Administrasi Online
</Text>
<Text fz="lg" c="black">
Pengurusan surat dan dokumen secara digital tanpa perlu datang ke kantor desa
</Text>
</Paper>
</motion.div>
</Stack>
<Modal
opened={opened}
onClose={close}
radius={0}
transitionProps={{ transition: 'fade', duration: 200 }}
>
<Paper p="md" withBorder>
<Stack gap="xs">
<Title order={3}>Ajukan Administrasi Online</Title>
<TextInput
label={<Text fz="sm" fw="bold">Nama</Text>}
placeholder="masukkan nama"
onChange={(val) => (state.administrasiOnline.create.form.name = val.target.value)}
/>
<TextInput
label={<Text fz="sm" fw="bold">Alamat</Text>}
placeholder="masukkan alamat"
onChange={(val) => (state.administrasiOnline.create.form.alamat = val.target.value)}
/>
<TextInput
type="number"
label={<Text fz="sm" fw="bold">Nomor Telepon</Text>}
placeholder="masukkan nomor telepon"
onChange={(val) => (state.administrasiOnline.create.form.nomorTelepon = val.target.value)}
/>
<Select
value={state.administrasiOnline.create.form.jenisLayananId}
onChange={(val) => {
state.administrasiOnline.create.form.jenisLayananId = val ?? "";
}}
label={<Text fw={"bold"} fz={"sm"}>Jenis Layanan</Text>}
placeholder="Pilih kategori produk"
data={
state.jenisLayanan.findMany.data?.map((v) => ({
value: v.id,
label: v.nama,
})) || []
}
/>
<Button bg={colors['blue-button']} onClick={handleSubmit}>
Simpan
</Button>
</Stack>
</Paper>
</Modal>
</Box>
);
}
export default AdministrasiOnline;

View File

@@ -0,0 +1,28 @@
'use client'
import colors from '@/con/colors';
import { Box, Paper, Stack, Text } from '@mantine/core';
import { IconBell } from '@tabler/icons-react';
import { motion } from 'framer-motion';
function InformasiDesa() {
return (
<Box>
<Stack >
<motion.div
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.8 }}
>
<Paper p={'xl'} >
<Box>
<IconBell size={50} color={colors['blue-button']} />,
</Box>
<Text fz={'h3'} fw={'bold'} c={colors['blue-button']}>Informasi Desa</Text>
<Text fz={'lg'} c={'black'}>Akses berita dan pengumuman terbaru seputar kegiatan desa</Text>
</Paper>
</motion.div>
</Stack>
</Box>
);
}
export default InformasiDesa;

View File

@@ -1,28 +1,11 @@
'use client'
import colors from '@/con/colors';
import { Box, Paper, SimpleGrid, Stack, Text } from '@mantine/core';
import { IconBell, IconFileCheckFilled, IconMessageCircleQuestion } from '@tabler/icons-react';
import { Box, SimpleGrid, Stack, Text } from '@mantine/core';
import BackButton from '../../desa/layanan/_com/BackButto';
import AdministrasiOnline from './administrasi-online/page';
import InformasiDesa from './informasi-desa/page';
import PengaduanMasyarakat from './pengaduan-masyarakat/page';
const data = [
{
id: 1,
icon: <IconFileCheckFilled size={50} color={colors['blue-button']} />,
judul: 'Administrasi Online',
deskripsi: 'Pengurusan surat dan dokumen secara digital tanpa perlu datang ke kantor desa'
},
{
id: 2,
icon: <IconMessageCircleQuestion size={50} color={colors['blue-button']} />,
judul: 'Pengaduan Masyarakat',
deskripsi: 'Sampaikan keluhan dan aspirasi Anda melalui platform digital kami'
},
{
id: 3,
icon: <IconBell size={50} color={colors['blue-button']} />,
judul: 'Informasi Desa',
deskripsi: 'Akses berita dan pengumuman terbaru seputar kegiatan desa'
},
]
function Page() {
return (
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
@@ -37,30 +20,20 @@ function Page() {
<Box px={{ base: "md", md: 100 }}>
<Stack gap={'lg'} justify='center'>
<SimpleGrid
pb={10}
cols={{
base: 1,
md: 1
}}
>
{data.map((v, k) => {
return (
<Stack key={k} >
<Paper p={'xl'} >
<Box>
{v.icon}
</Box>
<Text fz={'h3'} fw={'bold'} c={colors['blue-button']}>{v.judul}</Text>
<Text fz={'lg'} c={'black'}>{v.deskripsi}</Text>
</Paper>
</Stack>
)
})}
<Stack gap={'lg'}>
<AdministrasiOnline />
<PengaduanMasyarakat />
<InformasiDesa />
</Stack>
</SimpleGrid>
</Stack>
</Box>
</Stack>
</Box >
</Stack >
);
}

View File

@@ -0,0 +1,28 @@
'use client'
import colors from '@/con/colors';
import { Box, Paper, Stack, Text } from '@mantine/core';
import { IconMessageCircleQuestion } from '@tabler/icons-react';
import { motion } from 'framer-motion';
function PengaduanMasyarakat() {
return (
<Box>
<Stack >
<motion.div
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.8 }}
>
<Paper p={'xl'} >
<Box>
<IconMessageCircleQuestion size={50} color={colors['blue-button']} />,
</Box>
<Text fz={'h3'} fw={'bold'} c={colors['blue-button']}>Pengaduan Masyarakat</Text>
<Text fz={'lg'} c={'black'}>Sampaikan keluhan dan aspirasi Anda melalui platform digital kami</Text>
</Paper>
</motion.div>
</Stack>
</Box>
);
}
export default PengaduanMasyarakat;