feat(kesehatan): refactor ringkasan kesehatan to auto-derived stats
- Add IbuHamil and Balita models to schema.prisma - Implement IbuHamil and Balita API modules (CRUD) - Implement /stats endpoint for aggregated health KPIs - Refactor ringkasan-kesehatan admin page to dashboard-style UI - Update sidebar with Ibu Hamil and Balita entries - Fix type errors and icon exports in admin UI - Bump version to 0.1.52
This commit is contained in:
190
src/app/admin/(dashboard)/kesehatan/balita/edit/[id]/page.tsx
Normal file
190
src/app/admin/(dashboard)/kesehatan/balita/edit/[id]/page.tsx
Normal file
@@ -0,0 +1,190 @@
|
||||
'use client';
|
||||
|
||||
import colors from '@/con/colors';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
Group,
|
||||
Loader,
|
||||
NumberInput,
|
||||
Paper,
|
||||
Select,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Textarea,
|
||||
TextInput,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import balitaState from '../../../../_state/kesehatan/balita/balita';
|
||||
|
||||
export default function BalitaEditPage() {
|
||||
const router = useRouter();
|
||||
const params = useParams();
|
||||
const id = params.id as string;
|
||||
const state = useProxy(balitaState);
|
||||
const form = state.edit.form;
|
||||
|
||||
useEffect(() => {
|
||||
if (id) state.edit.load(id);
|
||||
}, [id]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const ok = await state.edit.update();
|
||||
if (ok) router.push('/admin/kesehatan/balita');
|
||||
};
|
||||
|
||||
return (
|
||||
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||
<Group mb="md" gap="sm">
|
||||
<Button variant="subtle" onClick={() => router.back()} radius="md">
|
||||
<IconArrowBack size={20} />
|
||||
</Button>
|
||||
<Title order={3} c="black">Edit Balita</Title>
|
||||
</Group>
|
||||
|
||||
<Paper withBorder w={{ base: '100%', md: '80%' }} p="lg" radius="md" shadow="xl" bg="white">
|
||||
<Stack gap="md">
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }} spacing="md">
|
||||
<TextInput
|
||||
label="Nama Lengkap"
|
||||
required
|
||||
placeholder="Nama balita"
|
||||
value={form.nama}
|
||||
onChange={(e) => { form.nama = e.currentTarget.value; }}
|
||||
radius="md"
|
||||
/>
|
||||
<TextInput
|
||||
label="NIK"
|
||||
placeholder="Nomor Induk Kependudukan"
|
||||
value={form.nik}
|
||||
onChange={(e) => { form.nik = e.currentTarget.value; }}
|
||||
radius="md"
|
||||
/>
|
||||
<TextInput
|
||||
label="Tanggal Lahir"
|
||||
required
|
||||
type="date"
|
||||
value={form.tanggalLahir}
|
||||
onChange={(e) => { form.tanggalLahir = e.currentTarget.value; }}
|
||||
radius="md"
|
||||
/>
|
||||
<Select
|
||||
label="Jenis Kelamin"
|
||||
required
|
||||
data={[
|
||||
{ value: 'L', label: 'Laki-laki' },
|
||||
{ value: 'P', label: 'Perempuan' },
|
||||
]}
|
||||
value={form.jenisKelamin}
|
||||
onChange={(v) => { if (v) form.jenisKelamin = v as typeof form.jenisKelamin; }}
|
||||
radius="md"
|
||||
/>
|
||||
<NumberInput
|
||||
label="Berat Badan (kg)"
|
||||
placeholder="0.0"
|
||||
min={0}
|
||||
decimalScale={1}
|
||||
value={form.beratBadanKg ?? ''}
|
||||
onChange={(v) => { form.beratBadanKg = v === '' ? undefined : Number(v); }}
|
||||
radius="md"
|
||||
/>
|
||||
<NumberInput
|
||||
label="Tinggi Badan (cm)"
|
||||
placeholder="0.0"
|
||||
min={0}
|
||||
decimalScale={1}
|
||||
value={form.tinggiBadanCm ?? ''}
|
||||
onChange={(v) => { form.tinggiBadanCm = v === '' ? undefined : Number(v); }}
|
||||
radius="md"
|
||||
/>
|
||||
<TextInput
|
||||
label="Nama Orang Tua"
|
||||
placeholder="Nama ayah/ibu"
|
||||
value={form.namaOrtu}
|
||||
onChange={(e) => { form.namaOrtu = e.currentTarget.value; }}
|
||||
radius="md"
|
||||
/>
|
||||
<TextInput
|
||||
label="No. HP Orang Tua"
|
||||
placeholder="08xx-xxxx-xxxx"
|
||||
value={form.noHpOrtu}
|
||||
onChange={(e) => { form.noHpOrtu = e.currentTarget.value; }}
|
||||
radius="md"
|
||||
/>
|
||||
<Select
|
||||
label="Status Stunting"
|
||||
required
|
||||
data={[
|
||||
{ value: 'NORMAL', label: 'Normal' },
|
||||
{ value: 'ALERT', label: 'Alert (Berisiko)' },
|
||||
{ value: 'STUNTING', label: 'Stunting' },
|
||||
]}
|
||||
value={form.statusStunting}
|
||||
onChange={(v) => { if (v) form.statusStunting = v as typeof form.statusStunting; }}
|
||||
radius="md"
|
||||
/>
|
||||
</SimpleGrid>
|
||||
|
||||
<TextInput
|
||||
label="Alamat"
|
||||
placeholder="Alamat lengkap"
|
||||
value={form.alamat}
|
||||
onChange={(e) => { form.alamat = e.currentTarget.value; }}
|
||||
radius="md"
|
||||
/>
|
||||
|
||||
<Group gap="xl">
|
||||
<Checkbox
|
||||
label="Imunisasi Lengkap"
|
||||
checked={form.imunisasiLengkap}
|
||||
onChange={(e) => { form.imunisasiLengkap = e.currentTarget.checked; }}
|
||||
/>
|
||||
<Checkbox
|
||||
label="Gizi Baik"
|
||||
checked={form.giziBaik}
|
||||
onChange={(e) => { form.giziBaik = e.currentTarget.checked; }}
|
||||
/>
|
||||
<Checkbox
|
||||
label="Pemeriksaan Rutin"
|
||||
checked={form.pemeriksaanRutin}
|
||||
onChange={(e) => { form.pemeriksaanRutin = e.currentTarget.checked; }}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Textarea
|
||||
label="Catatan"
|
||||
placeholder="Catatan tambahan"
|
||||
value={form.catatan}
|
||||
onChange={(e) => { form.catatan = e.currentTarget.value; }}
|
||||
radius="md"
|
||||
rows={3}
|
||||
/>
|
||||
|
||||
<Group justify="right">
|
||||
<Button variant="outline" color="gray" radius="md" onClick={() => router.back()}>
|
||||
Batal
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
radius="md"
|
||||
disabled={state.edit.loading}
|
||||
style={{
|
||||
background: state.edit.loading
|
||||
? 'linear-gradient(135deg, #ccc, #eee)'
|
||||
: `linear-gradient(135deg, ${colors['blue-button']}, #4facfe)`,
|
||||
color: '#fff',
|
||||
}}
|
||||
>
|
||||
{state.edit.loading ? <Loader size="sm" color="white" /> : 'Simpan'}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user