fix(kesehatan): solve valtio mutation error and sync db

- Fix 'Cannot assign to read only property' by mutating original Valtio proxy in create/edit pages for IbuHamil and Balita
- Sync database schema with 'prisma db push' to create IbuHamil and Balita tables
- Verify build success
This commit is contained in:
2026-05-04 17:04:44 +08:00
parent dccba1f82b
commit afe0d9d04b
4 changed files with 54 additions and 54 deletions

View File

@@ -27,9 +27,9 @@ export default function BalitaCreatePage() {
const form = state.create.form; const form = state.create.form;
const handleSubmit = async () => { const handleSubmit = async () => {
const ok = await state.create.submit(); const ok = await balitaState.create.submit();
if (ok) { if (ok) {
state.create.reset(); balitaState.create.reset();
router.push('/admin/kesehatan/balita'); router.push('/admin/kesehatan/balita');
} }
}; };
@@ -51,14 +51,14 @@ export default function BalitaCreatePage() {
required required
placeholder="Nama balita" placeholder="Nama balita"
value={form.nama} value={form.nama}
onChange={(e) => { form.nama = e.currentTarget.value; }} onChange={(e) => { balitaState.create.form.nama = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="NIK" label="NIK"
placeholder="Nomor Induk Kependudukan" placeholder="Nomor Induk Kependudukan"
value={form.nik} value={form.nik}
onChange={(e) => { form.nik = e.currentTarget.value; }} onChange={(e) => { balitaState.create.form.nik = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
@@ -66,7 +66,7 @@ export default function BalitaCreatePage() {
required required
type="date" type="date"
value={form.tanggalLahir} value={form.tanggalLahir}
onChange={(e) => { form.tanggalLahir = e.currentTarget.value; }} onChange={(e) => { balitaState.create.form.tanggalLahir = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<Select <Select
@@ -77,7 +77,7 @@ export default function BalitaCreatePage() {
{ value: 'P', label: 'Perempuan' }, { value: 'P', label: 'Perempuan' },
]} ]}
value={form.jenisKelamin} value={form.jenisKelamin}
onChange={(v) => { if (v) form.jenisKelamin = v as typeof form.jenisKelamin; }} onChange={(v) => { if (v) balitaState.create.form.jenisKelamin = v as typeof form.jenisKelamin; }}
radius="md" radius="md"
/> />
<NumberInput <NumberInput
@@ -86,7 +86,7 @@ export default function BalitaCreatePage() {
min={0} min={0}
decimalScale={1} decimalScale={1}
value={form.beratBadanKg ?? ''} value={form.beratBadanKg ?? ''}
onChange={(v) => { form.beratBadanKg = v === '' ? undefined : Number(v); }} onChange={(v) => { balitaState.create.form.beratBadanKg = v === '' ? undefined : Number(v); }}
radius="md" radius="md"
/> />
<NumberInput <NumberInput
@@ -95,21 +95,21 @@ export default function BalitaCreatePage() {
min={0} min={0}
decimalScale={1} decimalScale={1}
value={form.tinggiBadanCm ?? ''} value={form.tinggiBadanCm ?? ''}
onChange={(v) => { form.tinggiBadanCm = v === '' ? undefined : Number(v); }} onChange={(v) => { balitaState.create.form.tinggiBadanCm = v === '' ? undefined : Number(v); }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="Nama Orang Tua" label="Nama Orang Tua"
placeholder="Nama ayah/ibu" placeholder="Nama ayah/ibu"
value={form.namaOrtu} value={form.namaOrtu}
onChange={(e) => { form.namaOrtu = e.currentTarget.value; }} onChange={(e) => { balitaState.create.form.namaOrtu = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="No. HP Orang Tua" label="No. HP Orang Tua"
placeholder="08xx-xxxx-xxxx" placeholder="08xx-xxxx-xxxx"
value={form.noHpOrtu} value={form.noHpOrtu}
onChange={(e) => { form.noHpOrtu = e.currentTarget.value; }} onChange={(e) => { balitaState.create.form.noHpOrtu = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<Select <Select
@@ -121,7 +121,7 @@ export default function BalitaCreatePage() {
{ value: 'STUNTING', label: 'Stunting' }, { value: 'STUNTING', label: 'Stunting' },
]} ]}
value={form.statusStunting} value={form.statusStunting}
onChange={(v) => { if (v) form.statusStunting = v as typeof form.statusStunting; }} onChange={(v) => { if (v) balitaState.create.form.statusStunting = v as typeof form.statusStunting; }}
radius="md" radius="md"
/> />
</SimpleGrid> </SimpleGrid>
@@ -130,7 +130,7 @@ export default function BalitaCreatePage() {
label="Alamat" label="Alamat"
placeholder="Alamat lengkap" placeholder="Alamat lengkap"
value={form.alamat} value={form.alamat}
onChange={(e) => { form.alamat = e.currentTarget.value; }} onChange={(e) => { balitaState.create.form.alamat = e.currentTarget.value; }}
radius="md" radius="md"
/> />
@@ -138,17 +138,17 @@ export default function BalitaCreatePage() {
<Checkbox <Checkbox
label="Imunisasi Lengkap" label="Imunisasi Lengkap"
checked={form.imunisasiLengkap} checked={form.imunisasiLengkap}
onChange={(e) => { form.imunisasiLengkap = e.currentTarget.checked; }} onChange={(e) => { balitaState.create.form.imunisasiLengkap = e.currentTarget.checked; }}
/> />
<Checkbox <Checkbox
label="Gizi Baik" label="Gizi Baik"
checked={form.giziBaik} checked={form.giziBaik}
onChange={(e) => { form.giziBaik = e.currentTarget.checked; }} onChange={(e) => { balitaState.create.form.giziBaik = e.currentTarget.checked; }}
/> />
<Checkbox <Checkbox
label="Pemeriksaan Rutin" label="Pemeriksaan Rutin"
checked={form.pemeriksaanRutin} checked={form.pemeriksaanRutin}
onChange={(e) => { form.pemeriksaanRutin = e.currentTarget.checked; }} onChange={(e) => { balitaState.create.form.pemeriksaanRutin = e.currentTarget.checked; }}
/> />
</Group> </Group>
@@ -156,7 +156,7 @@ export default function BalitaCreatePage() {
label="Catatan" label="Catatan"
placeholder="Catatan tambahan" placeholder="Catatan tambahan"
value={form.catatan} value={form.catatan}
onChange={(e) => { form.catatan = e.currentTarget.value; }} onChange={(e) => { balitaState.create.form.catatan = e.currentTarget.value; }}
radius="md" radius="md"
rows={3} rows={3}
/> />

View File

@@ -30,11 +30,11 @@ export default function BalitaEditPage() {
const form = state.edit.form; const form = state.edit.form;
useEffect(() => { useEffect(() => {
if (id) state.edit.load(id); if (id) balitaState.edit.load(id);
}, [id]); // eslint-disable-line react-hooks/exhaustive-deps }, [id]); // eslint-disable-line react-hooks/exhaustive-deps
const handleSubmit = async () => { const handleSubmit = async () => {
const ok = await state.edit.update(); const ok = await balitaState.edit.update();
if (ok) router.push('/admin/kesehatan/balita'); if (ok) router.push('/admin/kesehatan/balita');
}; };
@@ -55,14 +55,14 @@ export default function BalitaEditPage() {
required required
placeholder="Nama balita" placeholder="Nama balita"
value={form.nama} value={form.nama}
onChange={(e) => { form.nama = e.currentTarget.value; }} onChange={(e) => { balitaState.edit.form.nama = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="NIK" label="NIK"
placeholder="Nomor Induk Kependudukan" placeholder="Nomor Induk Kependudukan"
value={form.nik} value={form.nik}
onChange={(e) => { form.nik = e.currentTarget.value; }} onChange={(e) => { balitaState.edit.form.nik = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
@@ -70,7 +70,7 @@ export default function BalitaEditPage() {
required required
type="date" type="date"
value={form.tanggalLahir} value={form.tanggalLahir}
onChange={(e) => { form.tanggalLahir = e.currentTarget.value; }} onChange={(e) => { balitaState.edit.form.tanggalLahir = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<Select <Select
@@ -81,7 +81,7 @@ export default function BalitaEditPage() {
{ value: 'P', label: 'Perempuan' }, { value: 'P', label: 'Perempuan' },
]} ]}
value={form.jenisKelamin} value={form.jenisKelamin}
onChange={(v) => { if (v) form.jenisKelamin = v as typeof form.jenisKelamin; }} onChange={(v) => { if (v) balitaState.edit.form.jenisKelamin = v as typeof form.jenisKelamin; }}
radius="md" radius="md"
/> />
<NumberInput <NumberInput
@@ -90,7 +90,7 @@ export default function BalitaEditPage() {
min={0} min={0}
decimalScale={1} decimalScale={1}
value={form.beratBadanKg ?? ''} value={form.beratBadanKg ?? ''}
onChange={(v) => { form.beratBadanKg = v === '' ? undefined : Number(v); }} onChange={(v) => { balitaState.edit.form.beratBadanKg = v === '' ? undefined : Number(v); }}
radius="md" radius="md"
/> />
<NumberInput <NumberInput
@@ -99,21 +99,21 @@ export default function BalitaEditPage() {
min={0} min={0}
decimalScale={1} decimalScale={1}
value={form.tinggiBadanCm ?? ''} value={form.tinggiBadanCm ?? ''}
onChange={(v) => { form.tinggiBadanCm = v === '' ? undefined : Number(v); }} onChange={(v) => { balitaState.edit.form.tinggiBadanCm = v === '' ? undefined : Number(v); }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="Nama Orang Tua" label="Nama Orang Tua"
placeholder="Nama ayah/ibu" placeholder="Nama ayah/ibu"
value={form.namaOrtu} value={form.namaOrtu}
onChange={(e) => { form.namaOrtu = e.currentTarget.value; }} onChange={(e) => { balitaState.edit.form.namaOrtu = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="No. HP Orang Tua" label="No. HP Orang Tua"
placeholder="08xx-xxxx-xxxx" placeholder="08xx-xxxx-xxxx"
value={form.noHpOrtu} value={form.noHpOrtu}
onChange={(e) => { form.noHpOrtu = e.currentTarget.value; }} onChange={(e) => { balitaState.edit.form.noHpOrtu = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<Select <Select
@@ -125,7 +125,7 @@ export default function BalitaEditPage() {
{ value: 'STUNTING', label: 'Stunting' }, { value: 'STUNTING', label: 'Stunting' },
]} ]}
value={form.statusStunting} value={form.statusStunting}
onChange={(v) => { if (v) form.statusStunting = v as typeof form.statusStunting; }} onChange={(v) => { if (v) balitaState.edit.form.statusStunting = v as typeof form.statusStunting; }}
radius="md" radius="md"
/> />
</SimpleGrid> </SimpleGrid>
@@ -134,7 +134,7 @@ export default function BalitaEditPage() {
label="Alamat" label="Alamat"
placeholder="Alamat lengkap" placeholder="Alamat lengkap"
value={form.alamat} value={form.alamat}
onChange={(e) => { form.alamat = e.currentTarget.value; }} onChange={(e) => { balitaState.edit.form.alamat = e.currentTarget.value; }}
radius="md" radius="md"
/> />
@@ -142,17 +142,17 @@ export default function BalitaEditPage() {
<Checkbox <Checkbox
label="Imunisasi Lengkap" label="Imunisasi Lengkap"
checked={form.imunisasiLengkap} checked={form.imunisasiLengkap}
onChange={(e) => { form.imunisasiLengkap = e.currentTarget.checked; }} onChange={(e) => { balitaState.edit.form.imunisasiLengkap = e.currentTarget.checked; }}
/> />
<Checkbox <Checkbox
label="Gizi Baik" label="Gizi Baik"
checked={form.giziBaik} checked={form.giziBaik}
onChange={(e) => { form.giziBaik = e.currentTarget.checked; }} onChange={(e) => { balitaState.edit.form.giziBaik = e.currentTarget.checked; }}
/> />
<Checkbox <Checkbox
label="Pemeriksaan Rutin" label="Pemeriksaan Rutin"
checked={form.pemeriksaanRutin} checked={form.pemeriksaanRutin}
onChange={(e) => { form.pemeriksaanRutin = e.currentTarget.checked; }} onChange={(e) => { balitaState.edit.form.pemeriksaanRutin = e.currentTarget.checked; }}
/> />
</Group> </Group>
@@ -160,7 +160,7 @@ export default function BalitaEditPage() {
label="Catatan" label="Catatan"
placeholder="Catatan tambahan" placeholder="Catatan tambahan"
value={form.catatan} value={form.catatan}
onChange={(e) => { form.catatan = e.currentTarget.value; }} onChange={(e) => { balitaState.edit.form.catatan = e.currentTarget.value; }}
radius="md" radius="md"
rows={3} rows={3}
/> />

View File

@@ -25,9 +25,9 @@ export default function IbuHamilCreatePage() {
const form = state.create.form; const form = state.create.form;
const handleSubmit = async () => { const handleSubmit = async () => {
const ok = await state.create.submit(); const ok = await ibuHamilState.create.submit();
if (ok) { if (ok) {
state.create.reset(); ibuHamilState.create.reset();
router.push('/admin/kesehatan/ibu-hamil'); router.push('/admin/kesehatan/ibu-hamil');
} }
}; };
@@ -49,14 +49,14 @@ export default function IbuHamilCreatePage() {
required required
placeholder="Nama ibu hamil" placeholder="Nama ibu hamil"
value={form.nama} value={form.nama}
onChange={(e) => { form.nama = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.create.form.nama = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="NIK" label="NIK"
placeholder="Nomor Induk Kependudukan" placeholder="Nomor Induk Kependudukan"
value={form.nik} value={form.nik}
onChange={(e) => { form.nik = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.create.form.nik = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
@@ -64,28 +64,28 @@ export default function IbuHamilCreatePage() {
type="number" type="number"
placeholder="0" placeholder="0"
value={String(form.usiaKehamilan)} value={String(form.usiaKehamilan)}
onChange={(e) => { form.usiaKehamilan = Number(e.currentTarget.value) || 0; }} onChange={(e) => { ibuHamilState.create.form.usiaKehamilan = Number(e.currentTarget.value) || 0; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="No. HP" label="No. HP"
placeholder="08xx-xxxx-xxxx" placeholder="08xx-xxxx-xxxx"
value={form.noHp} value={form.noHp}
onChange={(e) => { form.noHp = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.create.form.noHp = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="HPHT (Hari Pertama Haid Terakhir)" label="HPHT (Hari Pertama Haid Terakhir)"
type="date" type="date"
value={form.hpht} value={form.hpht}
onChange={(e) => { form.hpht = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.create.form.hpht = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="Taksiran Persalinan" label="Taksiran Persalinan"
type="date" type="date"
value={form.taksiranLahir} value={form.taksiranLahir}
onChange={(e) => { form.taksiranLahir = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.create.form.taksiranLahir = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<Select <Select
@@ -98,7 +98,7 @@ export default function IbuHamilCreatePage() {
{ value: 'NONAKTIF', label: 'Nonaktif' }, { value: 'NONAKTIF', label: 'Nonaktif' },
]} ]}
value={form.status} value={form.status}
onChange={(v) => { if (v) form.status = v as typeof form.status; }} onChange={(v) => { if (v) ibuHamilState.create.form.status = v as typeof form.status; }}
radius="md" radius="md"
/> />
</SimpleGrid> </SimpleGrid>
@@ -107,7 +107,7 @@ export default function IbuHamilCreatePage() {
label="Alamat" label="Alamat"
placeholder="Alamat lengkap" placeholder="Alamat lengkap"
value={form.alamat} value={form.alamat}
onChange={(e) => { form.alamat = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.create.form.alamat = e.currentTarget.value; }}
radius="md" radius="md"
/> />
@@ -115,7 +115,7 @@ export default function IbuHamilCreatePage() {
label="Catatan" label="Catatan"
placeholder="Catatan tambahan" placeholder="Catatan tambahan"
value={form.catatan} value={form.catatan}
onChange={(e) => { form.catatan = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.create.form.catatan = e.currentTarget.value; }}
radius="md" radius="md"
rows={3} rows={3}
/> />

View File

@@ -28,11 +28,11 @@ export default function IbuHamilEditPage() {
const form = state.edit.form; const form = state.edit.form;
useEffect(() => { useEffect(() => {
if (id) state.edit.load(id); if (id) ibuHamilState.edit.load(id);
}, [id]); // eslint-disable-line react-hooks/exhaustive-deps }, [id]); // eslint-disable-line react-hooks/exhaustive-deps
const handleSubmit = async () => { const handleSubmit = async () => {
const ok = await state.edit.update(); const ok = await ibuHamilState.edit.update();
if (ok) router.push('/admin/kesehatan/ibu-hamil'); if (ok) router.push('/admin/kesehatan/ibu-hamil');
}; };
@@ -53,14 +53,14 @@ export default function IbuHamilEditPage() {
required required
placeholder="Nama ibu hamil" placeholder="Nama ibu hamil"
value={form.nama} value={form.nama}
onChange={(e) => { form.nama = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.edit.form.nama = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="NIK" label="NIK"
placeholder="Nomor Induk Kependudukan" placeholder="Nomor Induk Kependudukan"
value={form.nik} value={form.nik}
onChange={(e) => { form.nik = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.edit.form.nik = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
@@ -68,28 +68,28 @@ export default function IbuHamilEditPage() {
type="number" type="number"
placeholder="0" placeholder="0"
value={String(form.usiaKehamilan)} value={String(form.usiaKehamilan)}
onChange={(e) => { form.usiaKehamilan = Number(e.currentTarget.value) || 0; }} onChange={(e) => { ibuHamilState.edit.form.usiaKehamilan = Number(e.currentTarget.value) || 0; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="No. HP" label="No. HP"
placeholder="08xx-xxxx-xxxx" placeholder="08xx-xxxx-xxxx"
value={form.noHp} value={form.noHp}
onChange={(e) => { form.noHp = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.edit.form.noHp = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="HPHT" label="HPHT"
type="date" type="date"
value={form.hpht} value={form.hpht}
onChange={(e) => { form.hpht = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.edit.form.hpht = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<TextInput <TextInput
label="Taksiran Persalinan" label="Taksiran Persalinan"
type="date" type="date"
value={form.taksiranLahir} value={form.taksiranLahir}
onChange={(e) => { form.taksiranLahir = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.edit.form.taksiranLahir = e.currentTarget.value; }}
radius="md" radius="md"
/> />
<Select <Select
@@ -102,7 +102,7 @@ export default function IbuHamilEditPage() {
{ value: 'NONAKTIF', label: 'Nonaktif' }, { value: 'NONAKTIF', label: 'Nonaktif' },
]} ]}
value={form.status} value={form.status}
onChange={(v) => { if (v) form.status = v as typeof form.status; }} onChange={(v) => { if (v) ibuHamilState.edit.form.status = v as typeof form.status; }}
radius="md" radius="md"
/> />
</SimpleGrid> </SimpleGrid>
@@ -111,7 +111,7 @@ export default function IbuHamilEditPage() {
label="Alamat" label="Alamat"
placeholder="Alamat lengkap" placeholder="Alamat lengkap"
value={form.alamat} value={form.alamat}
onChange={(e) => { form.alamat = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.edit.form.alamat = e.currentTarget.value; }}
radius="md" radius="md"
/> />
@@ -119,7 +119,7 @@ export default function IbuHamilEditPage() {
label="Catatan" label="Catatan"
placeholder="Catatan tambahan" placeholder="Catatan tambahan"
value={form.catatan} value={form.catatan}
onChange={(e) => { form.catatan = e.currentTarget.value; }} onChange={(e) => { ibuHamilState.edit.form.catatan = e.currentTarget.value; }}
radius="md" radius="md"
rows={3} rows={3}
/> />