Files
desa-darmasaba/src/app/darmasaba/(pages)/inovasi/layanan-online-desa/administrasi-online/page.tsx
nico 8132609ccb feat: add form validation for inovasi, lingkungan, and pendidikan modules
- Added isFormValid() and isHtmlEmpty() helper functions for form validation
- Disabled submit buttons when required fields are empty across multiple admin and public pages
- Applied consistent validation pattern for creating and editing records
- Commented out WhatsApp OTP sending in login route for debugging/testing
- Fixed path in NavbarMainMenu tooltip action
2026-02-20 15:08:41 +08:00

132 lines
3.9 KiB
TypeScript

/* 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);
// Check if form is valid
const isFormValid = () => {
return (
state.administrasiOnline.create.form.name?.trim() !== '' &&
state.administrasiOnline.create.form.alamat?.trim() !== '' &&
state.administrasiOnline.create.form.nomorTelepon?.trim() !== '' &&
state.administrasiOnline.create.form.jenisLayananId?.trim() !== ''
);
};
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 jenis layanan"
data={
state.jenisLayanan.findMany.data?.map((v) => ({
value: v.id,
label: v.nama,
})) || []
}
/>
<Button
bg={colors['blue-button']}
onClick={handleSubmit}
disabled={!isFormValid()}
>
Simpan
</Button>
</Stack>
</Paper>
</Modal>
</Box>
);
}
export default AdministrasiOnline;