Refactor New Ui Sosial, Keamanan, & Bantuan
This commit is contained in:
69
src/components/sosial/beasiswa.tsx
Normal file
69
src/components/sosial/beasiswa.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Card, Group, Stack, Text, ThemeIcon, Title } from "@mantine/core";
|
||||
import { useMantineColorScheme } from "@mantine/core";
|
||||
import { IconAward } from "@tabler/icons-react";
|
||||
|
||||
interface ScholarshipData {
|
||||
penerima: number;
|
||||
dana: string;
|
||||
tahunAjaran: string;
|
||||
}
|
||||
|
||||
interface BeasiswaProps {
|
||||
data?: ScholarshipData;
|
||||
}
|
||||
|
||||
export const Beasiswa = ({ data }: BeasiswaProps) => {
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const dark = colorScheme === "dark";
|
||||
|
||||
const defaultData: ScholarshipData = {
|
||||
penerima: 45,
|
||||
dana: "Rp 1.200.000.000",
|
||||
tahunAjaran: "2025/2026",
|
||||
};
|
||||
|
||||
const displayData = data || defaultData;
|
||||
|
||||
return (
|
||||
<Card
|
||||
p="md"
|
||||
radius="xl"
|
||||
withBorder
|
||||
shadow="sm"
|
||||
bg={dark ? "#141D34" : "white"}
|
||||
style={{ borderColor: dark ? "#141D34" : "#e5e7eb" }}
|
||||
h={"100%"}
|
||||
>
|
||||
<Group justify="space-between" align="center">
|
||||
<Stack gap={2}>
|
||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"} fw={500}>
|
||||
Beasiswa Desa
|
||||
</Text>
|
||||
<Text size="xl" fw={700} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
Penerima: {displayData.penerima}
|
||||
</Text>
|
||||
</Stack>
|
||||
<ThemeIcon
|
||||
variant="light"
|
||||
color="darmasaba-success"
|
||||
size="xl"
|
||||
radius="xl"
|
||||
>
|
||||
<IconAward size={24} />
|
||||
</ThemeIcon>
|
||||
</Group>
|
||||
<Stack gap="xs" mt="md">
|
||||
<Group justify="space-between">
|
||||
<Text c={dark ? "dark.3" : "dimmed"}>Dana Tersalurkan:</Text>
|
||||
<Text fw={700} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{displayData.dana}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group justify="space-between">
|
||||
<Text c={dark ? "dark.3" : "dimmed"}>Tahun Ajaran:</Text>
|
||||
<Text c={dark ? "dark.0" : "#1e3a5f"}>{displayData.tahunAjaran}</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
94
src/components/sosial/event-calendar.tsx
Normal file
94
src/components/sosial/event-calendar.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import { Card, Group, Stack, Text, Title, ThemeIcon } from "@mantine/core";
|
||||
import { useMantineColorScheme } from "@mantine/core";
|
||||
import { IconCalendarEvent } from "@tabler/icons-react";
|
||||
|
||||
interface EventItem {
|
||||
id: string;
|
||||
nama: string;
|
||||
tanggal: string;
|
||||
lokasi: string;
|
||||
}
|
||||
|
||||
interface EventCalendarProps {
|
||||
data?: EventItem[];
|
||||
}
|
||||
|
||||
export const EventCalendar = ({ data }: EventCalendarProps) => {
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const dark = colorScheme === "dark";
|
||||
|
||||
const defaultData: EventItem[] = [
|
||||
{
|
||||
id: "1",
|
||||
nama: "Hari Kesaktian Pancasila",
|
||||
tanggal: "1 Oktober 2025",
|
||||
lokasi: "Balai Desa",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
nama: "Festival Budaya Desa",
|
||||
tanggal: "20 Mei 2026",
|
||||
lokasi: "Lapangan Desa",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
nama: "Perayaan HUT Desa",
|
||||
tanggal: "17 Agustus 2026",
|
||||
lokasi: "Balai Desa",
|
||||
},
|
||||
];
|
||||
|
||||
const displayData = data || defaultData;
|
||||
|
||||
return (
|
||||
<Card
|
||||
p="md"
|
||||
radius="xl"
|
||||
withBorder
|
||||
shadow="sm"
|
||||
bg={dark ? "#141D34" : "white"}
|
||||
style={{ borderColor: dark ? "#141D34" : "#e5e7eb" }}
|
||||
>
|
||||
<Title order={3} mb="md" c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
Kalender Event Budaya
|
||||
</Title>
|
||||
<Stack gap="sm">
|
||||
{displayData.map((event) => (
|
||||
<Card
|
||||
key={event.id}
|
||||
p="md"
|
||||
radius="md"
|
||||
withBorder
|
||||
bg={dark ? "#263852ff" : "#F1F5F9"}
|
||||
style={{ borderColor: dark ? "#263852ff" : "#F1F5F9" }}
|
||||
hoverable
|
||||
>
|
||||
<Group justify="space-between" mb="xs">
|
||||
<Group gap="sm" align="center">
|
||||
<ThemeIcon
|
||||
color="darmasaba-blue"
|
||||
size="md"
|
||||
radius="xl"
|
||||
variant="light"
|
||||
>
|
||||
<IconCalendarEvent size={16} />
|
||||
</ThemeIcon>
|
||||
<Text fw={600} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{event.nama}
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"} fw={500}>
|
||||
{event.lokasi}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group pl={36}>
|
||||
<Text size="sm" c={dark ? "dark.4" : "gray.6"}>
|
||||
{event.tanggal}
|
||||
</Text>
|
||||
</Group>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
66
src/components/sosial/health-stats.tsx
Normal file
66
src/components/sosial/health-stats.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import { Card, Group, Progress, Stack, Text, Title } from "@mantine/core";
|
||||
import { useMantineColorScheme } from "@mantine/core";
|
||||
|
||||
interface HealthProgressItem {
|
||||
label: string;
|
||||
value: number;
|
||||
color: string;
|
||||
}
|
||||
|
||||
interface HealthStatsProps {
|
||||
data?: HealthProgressItem[];
|
||||
}
|
||||
|
||||
export const HealthStats = ({ data }: HealthStatsProps) => {
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const dark = colorScheme === "dark";
|
||||
|
||||
const defaultData: HealthProgressItem[] = [
|
||||
{ label: "Imunisasi Lengkap", value: 92, color: "green" },
|
||||
{ label: "Pemeriksaan Rutin", value: 88, color: "blue" },
|
||||
{ label: "Gizi Baik", value: 86, color: "teal" },
|
||||
{ label: "Target Stunting", value: 14, color: "red" },
|
||||
];
|
||||
|
||||
const displayData = data || defaultData;
|
||||
|
||||
return (
|
||||
<Card
|
||||
p="md"
|
||||
radius="xl"
|
||||
withBorder
|
||||
shadow="sm"
|
||||
bg={dark ? "#141D34" : "white"}
|
||||
style={{ borderColor: dark ? "#141D34" : "#e5e7eb" }}
|
||||
h={'100%'}
|
||||
>
|
||||
<Title order={3} mb="md" c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
Statistik Kesehatan
|
||||
</Title>
|
||||
<Stack gap="md">
|
||||
{displayData.map((item, index) => (
|
||||
<div key={index}>
|
||||
<Group justify="space-between" mb={5}>
|
||||
<Text size="sm" fw={500} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{item.label}
|
||||
</Text>
|
||||
<Text
|
||||
size="sm"
|
||||
fw={600}
|
||||
c={item.color === "red" ? "red" : dark ? "dark.0" : "#1e3a5f"}
|
||||
>
|
||||
{item.value}%
|
||||
</Text>
|
||||
</Group>
|
||||
<Progress
|
||||
value={item.value}
|
||||
size="lg"
|
||||
radius="xl"
|
||||
color={item.color}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
114
src/components/sosial/pendidikan.tsx
Normal file
114
src/components/sosial/pendidikan.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
import { Card, Group, Stack, Text, Title } from "@mantine/core";
|
||||
import { useMantineColorScheme } from "@mantine/core";
|
||||
|
||||
interface EducationData {
|
||||
siswa: {
|
||||
tk: number;
|
||||
sd: number;
|
||||
smp: number;
|
||||
sma: number;
|
||||
};
|
||||
sekolah: {
|
||||
jumlah: number;
|
||||
guru: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface PendidikanProps {
|
||||
data?: EducationData;
|
||||
}
|
||||
|
||||
export const Pendidikan = ({ data }: PendidikanProps) => {
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const dark = colorScheme === "dark";
|
||||
|
||||
const defaultData: EducationData = {
|
||||
siswa: {
|
||||
tk: 125,
|
||||
sd: 480,
|
||||
smp: 210,
|
||||
sma: 150,
|
||||
},
|
||||
sekolah: {
|
||||
jumlah: 8,
|
||||
guru: 42,
|
||||
},
|
||||
};
|
||||
|
||||
const displayData = data || defaultData;
|
||||
|
||||
return (
|
||||
<Card
|
||||
p="md"
|
||||
radius="xl"
|
||||
withBorder
|
||||
shadow="sm"
|
||||
bg={dark ? "#141D34" : "white"}
|
||||
style={{ borderColor: dark ? "#141D34" : "#e5e7eb" }}
|
||||
>
|
||||
<Title order={3} mb="md" c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
Pendidikan
|
||||
</Title>
|
||||
<Stack gap="md">
|
||||
<Group justify="space-between">
|
||||
<Text fw={500} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
TK / PAUD
|
||||
</Text>
|
||||
<Text fw={700} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{displayData.siswa.tk}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group justify="space-between">
|
||||
<Text fw={500} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
SD
|
||||
</Text>
|
||||
<Text fw={700} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{displayData.siswa.sd}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group justify="space-between">
|
||||
<Text fw={500} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
SMP
|
||||
</Text>
|
||||
<Text fw={700} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{displayData.siswa.smp}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group justify="space-between">
|
||||
<Text fw={500} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
SMA
|
||||
</Text>
|
||||
<Text fw={700} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{displayData.siswa.sma}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<Card
|
||||
withBorder
|
||||
radius="md"
|
||||
p="md"
|
||||
mt="md"
|
||||
bg={dark ? "#263852ff" : "#F1F5F9"}
|
||||
style={{ borderColor: dark ? "#263852ff" : "#F1F5F9" }}
|
||||
>
|
||||
<Group justify="space-between">
|
||||
<Text fw={500} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
Jumlah Lembaga Pendidikan
|
||||
</Text>
|
||||
<Text fw={700} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{displayData.sekolah.jumlah}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group justify="space-between" mt="sm">
|
||||
<Text fw={500} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
Jumlah Tenaga Pengajar
|
||||
</Text>
|
||||
<Text fw={700} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{displayData.sekolah.guru}
|
||||
</Text>
|
||||
</Group>
|
||||
</Card>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
89
src/components/sosial/posyandu-schedule.tsx
Normal file
89
src/components/sosial/posyandu-schedule.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import { Badge, Card, Group, Stack, Text, Title } from "@mantine/core";
|
||||
import { useMantineColorScheme } from "@mantine/core";
|
||||
|
||||
interface PosyanduItem {
|
||||
id: string;
|
||||
nama: string;
|
||||
tanggal: string;
|
||||
jam: string;
|
||||
}
|
||||
|
||||
interface PosyanduScheduleProps {
|
||||
data?: PosyanduItem[];
|
||||
}
|
||||
|
||||
export const PosyanduSchedule = ({ data }: PosyanduScheduleProps) => {
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const dark = colorScheme === "dark";
|
||||
|
||||
const defaultData: PosyanduItem[] = [
|
||||
{
|
||||
id: "1",
|
||||
nama: "Posyandu Mawar",
|
||||
tanggal: "Senin, 15 Feb 2026",
|
||||
jam: "08:00 - 11:00",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
nama: "Posyandu Melati",
|
||||
tanggal: "Selasa, 16 Feb 2026",
|
||||
jam: "08:00 - 11:00",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
nama: "Posyandu Dahlia",
|
||||
tanggal: "Rabu, 17 Feb 2026",
|
||||
jam: "08:00 - 11:00",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
nama: "Posyandu Anggrek",
|
||||
tanggal: "Kamis, 18 Feb 2026",
|
||||
jam: "08:00 - 11:00",
|
||||
},
|
||||
];
|
||||
|
||||
const displayData = data || defaultData;
|
||||
|
||||
return (
|
||||
<Card
|
||||
p="md"
|
||||
radius="xl"
|
||||
withBorder
|
||||
shadow="sm"
|
||||
bg={dark ? "#141D34" : "white"}
|
||||
style={{ borderColor: dark ? "#141D34" : "#e5e7eb" }}
|
||||
>
|
||||
<Title order={3} mb="md" c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
Jadwal Posyandu
|
||||
</Title>
|
||||
<Stack gap="sm">
|
||||
{displayData.map((item) => (
|
||||
<Card
|
||||
key={item.id}
|
||||
p="md"
|
||||
radius="md"
|
||||
withBorder
|
||||
bg={dark ? "#263852ff" : "#F1F5F9"}
|
||||
style={{ borderColor: dark ? "#263852ff" : "#F1F5F9" }}
|
||||
hoverable
|
||||
>
|
||||
<Group justify="space-between">
|
||||
<Stack gap={0}>
|
||||
<Text fw={600} c={dark ? "dark.0" : "#1e3a5f"}>
|
||||
{item.nama}
|
||||
</Text>
|
||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"}>
|
||||
{item.tanggal}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Badge variant="light" color="darmasaba-blue" size="md">
|
||||
{item.jam}
|
||||
</Badge>
|
||||
</Group>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
132
src/components/sosial/summary-cards.tsx
Normal file
132
src/components/sosial/summary-cards.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import { Card, Grid, GridCol, Group, Stack, Text, ThemeIcon } from "@mantine/core";
|
||||
import { useMantineColorScheme } from "@mantine/core";
|
||||
import {
|
||||
IconBabyCarriage,
|
||||
IconHeartbeat,
|
||||
IconMedicalCross,
|
||||
IconStethoscope,
|
||||
} from "@tabler/icons-react";
|
||||
|
||||
interface SummaryCardProps {
|
||||
title: string;
|
||||
value: number;
|
||||
subtitle?: string;
|
||||
icon: React.ReactNode;
|
||||
color: string;
|
||||
highlight?: boolean;
|
||||
backgroundColor: string;
|
||||
}
|
||||
|
||||
const SummaryCard = ({
|
||||
title,
|
||||
value,
|
||||
subtitle,
|
||||
icon,
|
||||
color,
|
||||
highlight = false,
|
||||
backgroundColor,
|
||||
}: SummaryCardProps) => {
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const dark = colorScheme === "dark";
|
||||
|
||||
return (
|
||||
<Card
|
||||
p="md"
|
||||
radius="xl"
|
||||
withBorder
|
||||
shadow="sm"
|
||||
bg={dark ? "#141D34" : "white"}
|
||||
style={{ borderColor: dark ? "#141D34" : "#e5e7eb" }}
|
||||
>
|
||||
<Group justify="space-between" align="center">
|
||||
<Stack gap={2}>
|
||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"} fw={500}>
|
||||
{title}
|
||||
</Text>
|
||||
<Text
|
||||
size="xl"
|
||||
fw={700}
|
||||
c={highlight ? "red" : dark ? "dark.0" : "#1e3a5f"}
|
||||
>
|
||||
{value}
|
||||
</Text>
|
||||
{subtitle && (
|
||||
<Text size="xs" c={dark ? "dark.4" : "gray.6"}>
|
||||
{subtitle}
|
||||
</Text>
|
||||
)}
|
||||
</Stack>
|
||||
<ThemeIcon bg={backgroundColor} color={color} size="xl" radius="xl">
|
||||
{icon}
|
||||
</ThemeIcon>
|
||||
</Group>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
interface HealthSummaryData {
|
||||
ibuHamil: number;
|
||||
balita: number;
|
||||
alertStunting: number;
|
||||
posyanduAktif: number;
|
||||
}
|
||||
|
||||
interface SummaryCardsProps {
|
||||
data?: HealthSummaryData;
|
||||
}
|
||||
|
||||
export const SummaryCards = ({ data }: SummaryCardsProps) => {
|
||||
const defaultData: HealthSummaryData = {
|
||||
ibuHamil: 87,
|
||||
balita: 342,
|
||||
alertStunting: 12,
|
||||
posyanduAktif: 8,
|
||||
};
|
||||
|
||||
const displayData = data || defaultData;
|
||||
|
||||
return (
|
||||
<Grid gutter="md">
|
||||
<GridCol span={{ base: 12, sm: 6, lg: 3 }}>
|
||||
<SummaryCard
|
||||
title="Ibu Hamil Aktif"
|
||||
value={displayData.ibuHamil}
|
||||
subtitle="Aktif"
|
||||
icon={<IconHeartbeat size={20} />}
|
||||
color= "white"
|
||||
backgroundColor= "#1E3A5F"
|
||||
/>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, sm: 6, lg: 3 }}>
|
||||
<SummaryCard
|
||||
title="Balita Terdaftar"
|
||||
value={displayData.balita}
|
||||
subtitle="Terdaftar"
|
||||
icon={<IconBabyCarriage size={20} />}
|
||||
color= "white"
|
||||
backgroundColor= "#1E3A5F"
|
||||
/>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, sm: 6, lg: 3 }}>
|
||||
<SummaryCard
|
||||
title="Alert Stunting"
|
||||
value={displayData.alertStunting}
|
||||
subtitle="Perhatian"
|
||||
icon={<IconStethoscope size={20} />}
|
||||
color= "white"
|
||||
backgroundColor= "#1E3A5F"
|
||||
/>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, sm: 6, lg: 3 }}>
|
||||
<SummaryCard
|
||||
title="Posyandu Aktif"
|
||||
value={displayData.posyanduAktif}
|
||||
subtitle="Aktif"
|
||||
icon={<IconMedicalCross size={20} />}
|
||||
color= "white"
|
||||
backgroundColor= "#1E3A5F"
|
||||
/>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user