Fix UI Admin Menu Kesehatan, Login Admin, OTP

This commit is contained in:
2025-09-08 14:02:21 +08:00
parent 8817b937b1
commit 797713ef49
80 changed files with 7648 additions and 4924 deletions

View File

@@ -4,7 +4,17 @@
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import jadwalKegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import colors from '@/con/colors';
import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
import {
Box,
Button,
Group,
Paper,
Stack,
Text,
TextInput,
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
@@ -128,33 +138,14 @@ function EditJadwalKegiatan() {
stateJadwalKegiatan.edit.form = {
...stateJadwalKegiatan.edit.form,
content: formData.content,
informasiJadwalKegiatan: {
name: formData.informasiJadwalKegiatan.name,
tanggal: formData.informasiJadwalKegiatan.tanggal,
waktu: formData.informasiJadwalKegiatan.waktu,
lokasi: formData.informasiJadwalKegiatan.lokasi,
},
deskripsiJadwalKegiatan: {
deskripsi: formData.deskripsiJadwalKegiatan.deskripsi,
},
layananJadwalKegiatan: {
content: formData.layananJadwalKegiatan.content,
},
syaratKetentuanJadwalKegiatan: {
content: formData.syaratKetentuanJadwalKegiatan.content,
},
dokumenJadwalKegiatan: {
content: formData.dokumenJadwalKegiatan.content,
},
pendaftaranJadwalKegiatan: {
name: formData.pendaftaranJadwalKegiatan.name,
tanggal: formData.pendaftaranJadwalKegiatan.tanggal,
namaOrangtua: formData.pendaftaranJadwalKegiatan.namaOrangtua,
nomor: formData.pendaftaranJadwalKegiatan.nomor,
alamat: formData.pendaftaranJadwalKegiatan.alamat,
catatan: formData.pendaftaranJadwalKegiatan.catatan,
},
informasiJadwalKegiatan: { ...formData.informasiJadwalKegiatan },
deskripsiJadwalKegiatan: { ...formData.deskripsiJadwalKegiatan },
layananJadwalKegiatan: { ...formData.layananJadwalKegiatan },
syaratKetentuanJadwalKegiatan: { ...formData.syaratKetentuanJadwalKegiatan },
dokumenJadwalKegiatan: { ...formData.dokumenJadwalKegiatan },
pendaftaranJadwalKegiatan: { ...formData.pendaftaranJadwalKegiatan },
};
const success = await stateJadwalKegiatan.edit.submit();
if (success) {
toast.success("Jadwal kegiatan berhasil diperbarui!");
@@ -165,241 +156,164 @@ function EditJadwalKegiatan() {
toast.error(error instanceof Error ? error.message : "Gagal memperbarui data jadwal kegiatan");
}
};
return (
<Box>
<Box mb={10}>
<Button onClick={() => router.back()} variant="subtle" color="blue">
<IconArrowBack color={colors['blue-button']} size={25} />
</Button>
</Box>
<Stack gap="xs">
<Paper bg={colors['white-1']} p="md" w={{ base: '100%', md: '50%' }}>
<Stack gap="xs">
<Title order={3}>Edit Jadwal Kegiatan</Title>
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Jadwal Kegiatan
</Title>
</Group>
{/* Form */}
<Paper
w={{ base: '100%', md: '50%' }}
bg={colors['white-1']}
p="lg"
radius="md"
shadow="sm"
style={{ border: '1px solid #e0e0e0' }}
>
<Stack gap="md">
{/* Nama Jadwal */}
<TextInput
label={<Text fz="sm" fw="bold">Nama Jadwal Kegiatan</Text>}
placeholder="masukkan nama jadwal kegiatan"
label="Nama Jadwal Kegiatan"
placeholder="Masukkan nama jadwal kegiatan"
value={formData.content}
onChange={(e) => {
setFormData(prev => ({
...prev,
content: e.target.value
}));
}}
onChange={(e) => setFormData((prev) => ({ ...prev, content: e.target.value }))}
/>
<Box>
<Text fz="sm" fw="bold">Deskripsi Jadwal Kegiatan</Text>
<EditEditor
value={formData.deskripsiJadwalKegiatan.deskripsi}
onChange={(e) => {
setFormData(prev => ({
...prev,
deskripsiJadwalKegiatan: {
...prev.deskripsiJadwalKegiatan,
deskripsi: e
}
}));
}}
/>
</Box>
{/* Deskripsi */}
<Box>
<Text fz="md" fw="bold">Informasi Jadwal Kegiatan</Text>
<TextInput
label={<Text fz="sm" fw="bold">Nama</Text>}
placeholder="masukkan nama"
value={formData.informasiJadwalKegiatan.name}
onChange={(e) => {
setFormData(prev => ({
...prev,
informasiJadwalKegiatan: {
...prev.informasiJadwalKegiatan,
name: e.target.value
}
}));
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Tanggal</Text>}
placeholder="masukkan tanggal"
value={formData.informasiJadwalKegiatan.tanggal}
onChange={(e) => {
setFormData(prev => ({
...prev,
informasiJadwalKegiatan: {
...prev.informasiJadwalKegiatan,
tanggal: e.target.value
}
}));
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Waktu</Text>}
placeholder="masukkan waktu"
value={formData.informasiJadwalKegiatan.waktu}
onChange={(e) => {
setFormData(prev => ({
...prev,
informasiJadwalKegiatan: {
...prev.informasiJadwalKegiatan,
waktu: e.target.value
}
}));
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Lokasi</Text>}
placeholder="masukkan lokasi"
value={formData.informasiJadwalKegiatan.lokasi}
onChange={(e) => {
setFormData(prev => ({
...prev,
informasiJadwalKegiatan: {
...prev.informasiJadwalKegiatan,
lokasi: e.target.value
}
}));
}}
<Text fz="sm" fw="bold">Deskripsi Jadwal Kegiatan</Text>
<EditEditor
value={formData.deskripsiJadwalKegiatan.deskripsi}
onChange={(val) => setFormData((prev) => ({
...prev,
deskripsiJadwalKegiatan: { deskripsi: val }
}))}
/>
</Box>
{/* Informasi Jadwal */}
<Box>
<Text fz="md" fw="bold">Informasi Jadwal Kegiatan</Text>
<TextInput label="Nama" value={formData.informasiJadwalKegiatan.name}
onChange={(e) => setFormData((prev) => ({
...prev, informasiJadwalKegiatan: { ...prev.informasiJadwalKegiatan, name: e.target.value }
}))}
/>
<TextInput type="date" label="Tanggal" value={formData.informasiJadwalKegiatan.tanggal}
onChange={(e) => setFormData((prev) => ({
...prev, informasiJadwalKegiatan: { ...prev.informasiJadwalKegiatan, tanggal: e.target.value }
}))}
/>
<TextInput label="Waktu" value={formData.informasiJadwalKegiatan.waktu}
onChange={(e) => setFormData((prev) => ({
...prev, informasiJadwalKegiatan: { ...prev.informasiJadwalKegiatan, waktu: e.target.value }
}))}
/>
<TextInput label="Lokasi" value={formData.informasiJadwalKegiatan.lokasi}
onChange={(e) => setFormData((prev) => ({
...prev, informasiJadwalKegiatan: { ...prev.informasiJadwalKegiatan, lokasi: e.target.value }
}))}
/>
</Box>
{/* Layanan */}
<Box>
<Text fz="md" fw="bold">Layanan Jadwal Kegiatan</Text>
<EditEditor
value={formData.layananJadwalKegiatan.content}
onChange={(e) => {
setFormData(prev => ({
...prev,
layananJadwalKegiatan: {
...prev.layananJadwalKegiatan,
content: e
}
}));
}}
onChange={(val) => setFormData((prev) => ({
...prev,
layananJadwalKegiatan: { content: val }
}))}
/>
</Box>
{/* Syarat */}
<Box>
<Text fz="md" fw="bold">Syarat dan Ketentuan Jadwal Kegiatan</Text>
<Text fz="md" fw="bold">Syarat dan Ketentuan</Text>
<EditEditor
value={formData.syaratKetentuanJadwalKegiatan.content}
onChange={(e) => {
setFormData(prev => ({
...prev,
syaratKetentuanJadwalKegiatan: {
...prev.syaratKetentuanJadwalKegiatan,
content: e
}
}));
}}
onChange={(val) => setFormData((prev) => ({
...prev,
syaratKetentuanJadwalKegiatan: { content: val }
}))}
/>
</Box>
{/* Dokumen */}
<Box>
<Text fz="md" fw="bold">Dokumen Jadwal Kegiatan</Text>
<EditEditor
value={formData.dokumenJadwalKegiatan.content}
onChange={(e) => {
setFormData(prev => ({
...prev,
dokumenJadwalKegiatan: {
...prev.dokumenJadwalKegiatan,
content: e
}
}));
}}
/>
</Box>
<Box>
<Text fz="md" fw="bold">Pendaftaran Jadwal Kegiatan</Text>
<TextInput
label={<Text fz="sm" fw="bold">Nama</Text>}
placeholder="masukkan nama"
value={formData.pendaftaranJadwalKegiatan.name}
onChange={(e) => {
setFormData(prev => ({
...prev,
pendaftaranJadwalKegiatan: {
...prev.pendaftaranJadwalKegiatan,
name: e.target.value
}
}));
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Tanggal</Text>}
placeholder="masukkan tanggal"
value={formData.pendaftaranJadwalKegiatan.tanggal}
onChange={(e) => {
setFormData(prev => ({
...prev,
pendaftaranJadwalKegiatan: {
...prev.pendaftaranJadwalKegiatan,
tanggal: e.target.value
}
}));
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Nama Orangtua</Text>}
placeholder="masukkan nama orangtua"
value={formData.pendaftaranJadwalKegiatan.namaOrangtua}
onChange={(e) => {
setFormData(prev => ({
...prev,
pendaftaranJadwalKegiatan: {
...prev.pendaftaranJadwalKegiatan,
namaOrangtua: e.target.value
}
}));
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Nomor</Text>}
placeholder="masukkan nomor"
value={formData.pendaftaranJadwalKegiatan.nomor}
onChange={(e) => {
setFormData(prev => ({
...prev,
pendaftaranJadwalKegiatan: {
...prev.pendaftaranJadwalKegiatan,
nomor: e.target.value
}
}));
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Alamat</Text>}
placeholder="masukkan alamat"
value={formData.pendaftaranJadwalKegiatan.alamat}
onChange={(e) => {
setFormData(prev => ({
...prev,
pendaftaranJadwalKegiatan: {
...prev.pendaftaranJadwalKegiatan,
alamat: e.target.value
}
}));
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Catatan</Text>}
placeholder="masukkan catatan"
value={formData.pendaftaranJadwalKegiatan.catatan}
onChange={(e) => {
setFormData(prev => ({
...prev,
pendaftaranJadwalKegiatan: {
...prev.pendaftaranJadwalKegiatan,
catatan: e.target.value
}
}));
}}
onChange={(val) => setFormData((prev) => ({
...prev,
dokumenJadwalKegiatan: { content: val }
}))}
/>
</Box>
<Button onClick={handleSubmit} bg={colors['blue-button']}>
Simpan
</Button>
{/* Pendaftaran */}
<Box>
<Text fz="md" fw="bold">Pendaftaran Jadwal Kegiatan</Text>
<TextInput label="Nama" value={formData.pendaftaranJadwalKegiatan.name}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, name: e.target.value }
}))}
/>
<TextInput type="date" label="Tanggal" value={formData.pendaftaranJadwalKegiatan.tanggal}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, tanggal: e.target.value }
}))}
/>
<TextInput label="Nama Orangtua" value={formData.pendaftaranJadwalKegiatan.namaOrangtua}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, namaOrangtua: e.target.value }
}))}
/>
<TextInput label="Nomor" value={formData.pendaftaranJadwalKegiatan.nomor}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, nomor: e.target.value }
}))}
/>
<TextInput label="Alamat" value={formData.pendaftaranJadwalKegiatan.alamat}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, alamat: e.target.value }
}))}
/>
<TextInput label="Catatan" value={formData.pendaftaranJadwalKegiatan.catatan}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, catatan: e.target.value }
}))}
/>
</Box>
{/* Submit */}
<Group justify="right">
<Button
onClick={handleSubmit}
radius="md"
size="md"
style={{
background: `linear-gradient(135deg, ${colors['blue-button']}, #4facfe)`,
color: '#fff',
boxShadow: '0 4px 15px rgba(79, 172, 254, 0.4)',
}}
>
Simpan
</Button>
</Group>
</Stack>
</Paper>
</Stack>
</Paper>
</Box>
);
}

View File

@@ -2,9 +2,9 @@
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import jadwalKegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import colors from '@/con/colors';
import { Box, Button, Flex, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
@@ -32,83 +32,128 @@ function DetailJadwalKegiatan() {
if (!stateJadwalKegiatan.findUnique.data) {
return (
<Stack py={10}>
<Skeleton h={500} />
<Skeleton height={500} radius="md" />
</Stack>
)
}
const data = stateJadwalKegiatan.findUnique.data
return (
<Box>
<Box mb={10}>
<Button variant="subtle" onClick={() => router.back()}>
<IconArrowBack color={colors['blue-button']} size={25} />
</Button>
</Box>
<Paper w={{ base: "100%", md: "50%" }} bg={colors['white-1']} p={'md'}>
<Stack>
<Text fz={"xl"} fw={"bold"}>Detail Jadwal Kegiatan</Text>
{stateJadwalKegiatan.findUnique.data ? (
<Paper bg={colors['BG-trans']} p={'md'}>
<Stack gap={"xs"}>
<Box>
<Text fz={"lg"} fw={"bold"}>Nama Kegiatan</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.content}</Text>
</Box>
<Box>
<Text fz={"lg"} fw={"bold"}>Informasi</Text>
<Text fz={"md"} fw={"bold"}>Nama</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.informasijadwalkegiatan.name}</Text>
<Text fz={"md"} fw={"bold"}>Tanggal</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.informasijadwalkegiatan.tanggal}</Text>
<Text fz={"md"} fw={"bold"}>Waktu</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.informasijadwalkegiatan.waktu}</Text>
<Text fz={"md"} fw={"bold"}>Lokasi</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.informasijadwalkegiatan.lokasi}</Text>
</Box>
<Box>
<Text fz={"lg"} fw={"bold"}>Deskripsi</Text>
<Text fz={"md"} dangerouslySetInnerHTML={{ __html: stateJadwalKegiatan.findUnique.data.deskripsijadwalkegiatan.deskripsi }} />
</Box>
<Box>
<Text fz={"lg"} fw={"bold"}>Layanan</Text>
<Text fz={"md"} dangerouslySetInnerHTML={{ __html: stateJadwalKegiatan.findUnique.data.layananjadwalkegiatan.content }} />
</Box>
<Box>
<Text fz={"lg"} fw={"bold"}>Syarat Ketentuan</Text>
<Text fz={"md"} dangerouslySetInnerHTML={{ __html: stateJadwalKegiatan.findUnique.data.syaratketentuanjadwalkegiatan.content}} />
</Box>
<Box>
<Text fz={"lg"} fw={"bold"}>Dokumen</Text>
<Text fz={"md"} dangerouslySetInnerHTML={{ __html: stateJadwalKegiatan.findUnique.data.dokumenjadwalkegiatan.content }} />
</Box>
<Box>
<Text fz={"lg"} fw={"bold"}>Prosedur Pendaftaran</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.pendaftaranjadwalkegiatan.name}</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.pendaftaranjadwalkegiatan.tanggal}</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.pendaftaranjadwalkegiatan.namaOrangtua}</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.pendaftaranjadwalkegiatan.nomor}</Text>
<Text fz={"md"}>{stateJadwalKegiatan.findUnique.data.pendaftaranjadwalkegiatan.alamat}</Text>
<Text fz={"md"} dangerouslySetInnerHTML={{ __html: stateJadwalKegiatan.findUnique.data.pendaftaranjadwalkegiatan.catatan }} />
</Box>
<Box>
<Flex gap={"xs"}>
<Button color="red" onClick={() => {
if (stateJadwalKegiatan.findUnique.data) {
setSelectedId(stateJadwalKegiatan.findUnique.data.id)
setModalHapus(true)
}
}}>
<IconX size={20} />
</Button>
<Button onClick={() => router.push(`/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan/${stateJadwalKegiatan.findUnique.data?.id}/edit`)} color="green">
<IconEdit size={20} />
</Button>
</Flex>
</Box>
</Stack>
</Paper>
) : null}
<Box py={10}>
{/* Tombol Back */}
<Button
variant="subtle"
onClick={() => router.back()}
leftSection={<IconArrowBack size={24} color={colors['blue-button']} />}
mb={15}
>
Kembali
</Button>
{/* Wrapper Detail */}
<Paper
withBorder
w={{ base: "100%", md: "50%" }}
bg={colors['white-1']}
p="lg"
radius="md"
shadow="sm"
>
<Stack gap="md">
<Text fz="2xl" fw="bold" c={colors['blue-button']}>
Detail Jadwal Kegiatan
</Text>
<Paper bg="#ECEEF8" p="md" radius="md" shadow="xs">
<Stack gap="sm">
{/* Nama Kegiatan */}
<Box>
<Text fz="lg" fw="bold">Nama Kegiatan</Text>
<Text fz="md" c="dimmed">{data.content || '-'}</Text>
</Box>
{/* Informasi */}
<Box>
<Text fz="lg" fw="bold">Informasi</Text>
<Text fz="md" fw="bold">Nama</Text>
<Text fz="md" c="dimmed">{data.informasijadwalkegiatan.name || '-'}</Text>
<Text fz="md" fw="bold">Tanggal</Text>
<Text fz="md" c="dimmed">{data.informasijadwalkegiatan.tanggal || '-'}</Text>
<Text fz="md" fw="bold">Waktu</Text>
<Text fz="md" c="dimmed">{data.informasijadwalkegiatan.waktu || '-'}</Text>
<Text fz="md" fw="bold">Lokasi</Text>
<Text fz="md" c="dimmed">{data.informasijadwalkegiatan.lokasi || '-'}</Text>
</Box>
{/* Deskripsi */}
<Box>
<Text fz="lg" fw="bold">Deskripsi</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data.deskripsijadwalkegiatan.deskripsi }} />
</Box>
{/* Layanan */}
<Box>
<Text fz="lg" fw="bold">Layanan</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data.layananjadwalkegiatan.content }} />
</Box>
{/* Syarat Ketentuan */}
<Box>
<Text fz="lg" fw="bold">Syarat Ketentuan</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data.syaratketentuanjadwalkegiatan.content }} />
</Box>
{/* Dokumen */}
<Box>
<Text fz="lg" fw="bold">Dokumen</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data.dokumenjadwalkegiatan.content }} />
</Box>
{/* Prosedur Pendaftaran */}
<Box>
<Text fz="lg" fw="bold">Prosedur Pendaftaran</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.name}</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.tanggal}</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.namaOrangtua}</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.nomor}</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.alamat}</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data.pendaftaranjadwalkegiatan.catatan }} />
</Box>
{/* Aksi */}
<Group gap="sm">
<Tooltip label="Hapus Data" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id)
setModalHapus(true)
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Data" withArrow position="top">
<Button
color="green"
onClick={() =>
router.push(`/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan/${data.id}/edit`)
}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>
</Stack>
</Paper>

View File

@@ -2,127 +2,158 @@
import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor';
import jadwalKegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import colors from '@/con/colors';
import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
import {
Box,
Button,
Group,
Paper,
Stack,
Text,
TextInput,
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { toast } from 'react-toastify';
import { useProxy } from 'valtio/utils';
function CreateJadwalKegiatan() {
const stateJadwalKegiatan = useProxy(jadwalKegiatanState)
const stateJadwalKegiatan = useProxy(jadwalKegiatanState);
const router = useRouter();
const resetForm = () => {
stateJadwalKegiatan.edit.form = {
content: "",
stateJadwalKegiatan.create.form = {
content: '',
informasiJadwalKegiatan: {
name: "",
tanggal: "",
waktu: "",
lokasi: "",
name: '',
tanggal: '',
waktu: '',
lokasi: '',
},
deskripsiJadwalKegiatan: {
deskripsi: "",
deskripsi: '',
},
layananJadwalKegiatan: {
content: "",
content: '',
},
syaratKetentuanJadwalKegiatan: {
content: "",
content: '',
},
dokumenJadwalKegiatan: {
content: "",
content: '',
},
pendaftaranJadwalKegiatan: {
name: "",
tanggal: "",
namaOrangtua: "",
nomor: "",
alamat: "",
catatan: "",
name: '',
tanggal: '',
namaOrangtua: '',
nomor: '',
alamat: '',
catatan: '',
},
};
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await stateJadwalKegiatan.create.submit();
toast.success("Data berhasil disimpan");
toast.success('Data berhasil disimpan');
resetForm();
// After successful submission, redirect to the list page
router.push('/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan');
}
};
return (
<Box component="form" onSubmit={handleSubmit}>
<Box mb={10}>
<Button variant="subtle" onClick={() => router.back()}>
<IconArrowBack color={colors['blue-button']} size={25} />
</Button>
</Box>
<Box px={{ base: 'sm', md: 'lg' }} py="md" component="form" onSubmit={handleSubmit}>
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Jadwal Kegiatan
</Title>
</Group>
<Paper bg={colors['white-1']} p="md" w={{ base: '100%', md: '50%' }}>
<Stack gap="xs">
<Title order={3}>Create Jadwal Kegiatan</Title>
{/* Form */}
<Paper
w={{ base: '100%', md: '50%' }}
bg={colors['white-1']}
p="lg"
radius="md"
shadow="sm"
style={{ border: '1px solid #e0e0e0' }}
>
<Stack gap="md">
<TextInput
label={<Text fz="sm" fw="bold">Nama Jadwal Kegiatan</Text>}
placeholder="masukkan nama jadwal kegiatan"
label="Nama Jadwal Kegiatan"
placeholder="Masukkan nama jadwal kegiatan"
value={stateJadwalKegiatan.create.form.content}
onChange={(e) => {
stateJadwalKegiatan.create.form.content = e.target.value;
}}
required
/>
<Box>
<Text fz="sm" fw="bold">Deskripsi Jadwal Kegiatan</Text>
<CreateEditor
value={stateJadwalKegiatan.create.form.deskripsiJadwalKegiatan.deskripsi}
onChange={(e) => {
stateJadwalKegiatan.create.form.deskripsiJadwalKegiatan.deskripsi = e;
}}
/>
</Box>
<Box>
<Text fz="md" fw="bold">Informasi Jadwal Kegiatan</Text>
<Text fz="sm" fw="bold" mb={4}>Deskripsi Jadwal Kegiatan</Text>
<CreateEditor
value={stateJadwalKegiatan.create.form.deskripsiJadwalKegiatan.deskripsi}
onChange={(e) => {
stateJadwalKegiatan.create.form.deskripsiJadwalKegiatan.deskripsi = e;
}}
/>
</Box>
<Box>
<Text fz="md" fw="bold" mb="sm">Informasi Jadwal Kegiatan</Text>
<TextInput
label={<Text fz="sm" fw="bold">Nama</Text>}
placeholder="masukkan nama"
label="Nama"
required
placeholder="Masukkan nama"
value={stateJadwalKegiatan.create.form.informasiJadwalKegiatan.name}
onChange={(e) => {
stateJadwalKegiatan.create.form.informasiJadwalKegiatan.name = e.target.value;
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Tanggal</Text>}
placeholder="masukkan tanggal"
type="date"
required
label="Tanggal"
value={stateJadwalKegiatan.create.form.informasiJadwalKegiatan.tanggal}
onChange={(e) => {
stateJadwalKegiatan.create.form.informasiJadwalKegiatan.tanggal = e.target.value;
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Waktu</Text>}
placeholder="masukkan waktu"
label="Waktu"
required
placeholder="Masukkan waktu"
value={stateJadwalKegiatan.create.form.informasiJadwalKegiatan.waktu}
onChange={(e) => {
stateJadwalKegiatan.create.form.informasiJadwalKegiatan.waktu = e.target.value;
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Lokasi</Text>}
placeholder="masukkan lokasi"
label="Lokasi"
required
placeholder="Masukkan lokasi"
value={stateJadwalKegiatan.create.form.informasiJadwalKegiatan.lokasi}
onChange={(e) => {
stateJadwalKegiatan.create.form.informasiJadwalKegiatan.lokasi = e.target.value;
}}
/>
</Box>
<Box>
<Text fz="md" fw="bold">Layanan Jadwal Kegiatan</Text>
<Text fz="md" fw="bold" mb="sm">Layanan Jadwal Kegiatan</Text>
<CreateEditor
value={stateJadwalKegiatan.create.form.layananJadwalKegiatan.content}
onChange={(e) => {
@@ -130,8 +161,9 @@ function CreateJadwalKegiatan() {
}}
/>
</Box>
<Box>
<Text fz="md" fw="bold">Syarat dan Ketentuan Jadwal Kegiatan</Text>
<Text fz="md" fw="bold" mb="sm">Syarat & Ketentuan</Text>
<CreateEditor
value={stateJadwalKegiatan.create.form.syaratKetentuanJadwalKegiatan.content}
onChange={(e) => {
@@ -139,8 +171,9 @@ function CreateJadwalKegiatan() {
}}
/>
</Box>
<Box>
<Text fz="md" fw="bold">Dokumen Jadwal Kegiatan</Text>
<Text fz="md" fw="bold" mb="sm">Dokumen</Text>
<CreateEditor
value={stateJadwalKegiatan.create.form.dokumenJadwalKegiatan.content}
onChange={(e) => {
@@ -148,51 +181,58 @@ function CreateJadwalKegiatan() {
}}
/>
</Box>
<Box>
<Text fz="md" fw="bold">Pendaftaran Jadwal Kegiatan</Text>
<Text fz="md" fw="bold" mb="sm">Pendaftaran Jadwal Kegiatan</Text>
<TextInput
label={<Text fz="sm" fw="bold">Nama</Text>}
placeholder="masukkan nama"
label="Nama"
required
placeholder="Masukkan nama"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.name}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.name = e.target.value;
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Tanggal</Text>}
placeholder="masukkan tanggal"
type="date"
required
label="Tanggal"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.tanggal}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.tanggal = e.target.value;
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Nama Orangtua</Text>}
placeholder="masukkan nama orangtua"
label="Nama Orangtua"
required
placeholder="Masukkan nama orangtua"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.namaOrangtua}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.namaOrangtua = e.target.value;
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Nomor</Text>}
placeholder="masukkan nomor"
label="Nomor"
required
placeholder="Masukkan nomor"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.nomor}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.nomor = e.target.value;
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Alamat</Text>}
placeholder="masukkan alamat"
label="Alamat"
required
placeholder="Masukkan alamat"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.alamat}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.alamat = e.target.value;
}}
/>
<TextInput
label={<Text fz="sm" fw="bold">Catatan</Text>}
placeholder="masukkan catatan"
label="Catatan"
required
placeholder="Masukkan catatan"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.catatan}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.catatan = e.target.value;
@@ -200,9 +240,21 @@ function CreateJadwalKegiatan() {
/>
</Box>
<Button onClick={handleSubmit} bg={colors['blue-button']}>
Simpan
</Button>
{/* Save Button */}
<Group justify="right">
<Button
type="submit"
radius="md"
size="md"
style={{
background: `linear-gradient(135deg, ${colors['blue-button']}, #4facfe)`,
color: '#fff',
boxShadow: '0 4px 15px rgba(79, 172, 254, 0.4)',
}}
>
Simpan
</Button>
</Group>
</Stack>
</Paper>
</Box>

View File

@@ -1,96 +1,185 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
import {
Box,
Button,
Center,
Group,
Paper,
Pagination,
Skeleton,
Stack,
Table,
TableTbody,
TableTd,
TableTh,
TableThead,
TableTr,
Text,
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import { IconArrowBack, IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../../_com/header';
import JudulList from '../../../_com/judulList';
import jadwalKegiatanState from '../../../_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import { useState } from 'react';
function JadwalKegiatan() {
const router = useRouter();
const [search, setSearch] = useState("");
return (
<Box>
{/* Tombol Back */}
<Box mb={10}>
<Button variant="subtle" onClick={() => router.back()}>
<IconArrowBack color={colors["blue-button"]} size={25} />
</Button>
</Box>
{/* Header Search */}
<HeaderSearch
title='Jadwal Kegiatan'
placeholder='pencarian'
title="Jadwal Kegiatan"
placeholder="Cari nama, tanggal, lokasi..."
searchIcon={<IconSearch size={20} />}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
<ListJadwalKegiatan search={search}/>
<ListJadwalKegiatan search={search} />
</Box>
);
}
function ListJadwalKegiatan({ search }: { search: string }) {
const stateJadwalKegiatan = useProxy(jadwalKegiatanState)
const state = useProxy(jadwalKegiatanState);
const router = useRouter();
const { data, page, totalPages, loading, load } = state.findMany;
useShallowEffect(() => {
stateJadwalKegiatan.findMany.load()
}, [])
load(page, 10, search);
}, [page, search]);
const filteredData = (stateJadwalKegiatan.findMany.data || []).filter(item => {
const keyword = search.toLowerCase();
const filteredData = data || [];
if (loading || !data) {
return (
item.informasijadwalkegiatan.name.toLowerCase().includes(keyword) ||
item.informasijadwalkegiatan.tanggal.toLowerCase().includes(keyword) ||
item.informasijadwalkegiatan.waktu.toLowerCase().includes(keyword) ||
item.informasijadwalkegiatan.lokasi.toLowerCase().includes(keyword)
<Stack py={10}>
<Skeleton height={600} radius="md" />
</Stack>
);
});
if (!stateJadwalKegiatan.findMany.data) {
return (
<Box py={10}>
<Skeleton h={500}/>
</Box>
)
}
return (
<Box py={10}>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<JudulList
title='List Jadwal Kegiatan'
href='/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan/create'
/>
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
{/* Judul + Tombol Tambah */}
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Jadwal Kegiatan</Title>
<Tooltip label="Tambah Jadwal Kegiatan" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() =>
router.push('/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan/create')
}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
{/* Tabel */}
<Box style={{ overflowX: "auto" }}>
<Table striped withRowBorders withTableBorder style={{ minWidth: '700px' }}>
<Table highlightOnHover>
<TableThead>
<TableTr>
<TableTh>Nama</TableTh>
<TableTh>Tanggal</TableTh>
<TableTh>Waktu</TableTh>
<TableTh>Lokasi</TableTh>
<TableTh>Detail</TableTh>
<TableTh>Aksi</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.informasijadwalkegiatan.name}</TableTd>
<TableTd>{item.informasijadwalkegiatan.tanggal}</TableTd>
<TableTd>{item.informasijadwalkegiatan.waktu}</TableTd>
<TableTd>{item.informasijadwalkegiatan.lokasi}</TableTd>
<TableTd>
<Button onClick={() => router.push(`/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan/${item.id}`)}>
<IconDeviceImacCog size={25} />
</Button>
{filteredData.length > 0 ? (
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Text fw={500} truncate="end" lineClamp={1}>
{item.informasijadwalkegiatan.name}
</Text>
</TableTd>
<TableTd>
{new Date(item.informasijadwalkegiatan.tanggal).toLocaleDateString(
'id-ID',
{
day: '2-digit',
month: 'long',
year: 'numeric',
}
)}
</TableTd>
<TableTd>{item.informasijadwalkegiatan.waktu}</TableTd>
<TableTd>
<Text truncate fz="sm" c="dimmed">
{item.informasijadwalkegiatan.lokasi}
</Text>
</TableTd>
<TableTd>
<Button
variant="light"
color="blue"
onClick={() =>
router.push(
`/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan/${item.id}`
)
}
>
<IconDeviceImacCog size={20} />
<Text ml={5}>Detail</Text>
</Button>
</TableTd>
</TableTr>
))
) : (
<TableTr>
<TableTd colSpan={5}>
<Center py={20}>
<Text color="dimmed">
Tidak ada jadwal kegiatan yang cocok
</Text>
</Center>
</TableTd>
</TableTr>
))}
)}
</TableTbody>
</Table>
</Box>
</Stack>
</Paper>
</Box>
)
</Paper>
{/* Pagination */}
<Center>
<Pagination
value={page}
onChange={(newPage) => {
load(newPage, 10);
window.scrollTo({ top: 0, behavior: 'smooth' });
}}
total={totalPages}
mt="md"
mb="md"
color="blue"
radius="md"
/>
</Center>
</Box>
);
}
export default JadwalKegiatan;