Sinkronisasi UI & API Admin - User Submenu Jumlah Pengangguran - Jumlah Penduduk Miskin
This commit is contained in:
@@ -1550,7 +1550,7 @@ model DataDemografiPekerjaan {
|
|||||||
model DetailDataPengangguran {
|
model DetailDataPengangguran {
|
||||||
id String @id @default(uuid()) @db.Uuid
|
id String @id @default(uuid()) @db.Uuid
|
||||||
month String @db.VarChar(20)
|
month String @db.VarChar(20)
|
||||||
year Int
|
year DateTime
|
||||||
totalUnemployment Int
|
totalUnemployment Int
|
||||||
educatedUnemployment Int
|
educatedUnemployment Int
|
||||||
uneducatedUnemployment Int
|
uneducatedUnemployment Int
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function EditJumlahPendudukMiskin() {
|
|||||||
// Set the ID before submitting
|
// Set the ID before submitting
|
||||||
stateJPM.update.id = id;
|
stateJPM.update.id = id;
|
||||||
await stateJPM.update.submit();
|
await stateJPM.update.submit();
|
||||||
router.push('/admin/ekonomi/jumlah-penduduk-miskin-2024-2025')
|
router.push('/admin/ekonomi/jumlah-penduduk-miskin')
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ function CreateJumlahPendudukMiskin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
resetForm();
|
resetForm();
|
||||||
router.push("/admin/ekonomi/jumlah-penduduk-miskin-2024-2025");
|
router.push("/admin/ekonomi/jumlah-penduduk-miskin");
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ function ListJumlahPendudukMiskin({ search }: { search: string }) {
|
|||||||
<Paper bg={colors['white-1']} p={'md'}>
|
<Paper bg={colors['white-1']} p={'md'}>
|
||||||
<JudulList
|
<JudulList
|
||||||
title='List Jumlah Penduduk Miskin'
|
title='List Jumlah Penduduk Miskin'
|
||||||
href='/admin/ekonomi/jumlah-penduduk-miskin-2024-2025/create'
|
href='/admin/ekonomi/jumlah-penduduk-miskin/create'
|
||||||
/>
|
/>
|
||||||
<Table striped withTableBorder withRowBorders>
|
<Table striped withTableBorder withRowBorders>
|
||||||
<TableThead>
|
<TableThead>
|
||||||
@@ -108,7 +108,7 @@ function ListJumlahPendudukMiskin({ search }: { search: string }) {
|
|||||||
<TableTd>{item.year}</TableTd>
|
<TableTd>{item.year}</TableTd>
|
||||||
<TableTd>{item.totalPoorPopulation}</TableTd>
|
<TableTd>{item.totalPoorPopulation}</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Button color='green' onClick={() => router.push(`/admin/ekonomi/jumlah-penduduk-miskin-2024-2025/${item.id}`)}>
|
<Button color='green' onClick={() => router.push(`/admin/ekonomi/jumlah-penduduk-miskin/${item.id}`)}>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
|
|||||||
@@ -8,29 +8,36 @@ import { useRouter } from 'next/navigation';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Cell, Pie, PieChart } from 'recharts';
|
import { Cell, Pie, PieChart } from 'recharts';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import JudulListTab from '../../../_com/judulListTab';
|
import HeaderSearch from '../../../_com/header';
|
||||||
|
import JudulList from '../../../_com/judulList';
|
||||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
import grafikNganggur from '../../../_state/ekonomi/usia-kerja-nganggur';
|
import grafikNganggur from '../../../_state/ekonomi/usia-kerja-nganggur';
|
||||||
|
|
||||||
function GrafikBerdasarkanPendidikan() {
|
function GrafikBerdasarkanPendidikan() {
|
||||||
|
const [search, setSearch] = useState("")
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Stack gap={"xs"}>
|
<Stack gap={"xs"}>
|
||||||
<Title order={3}>Grafik Pengangguran Berdasarkan Pendidikan</Title>
|
<HeaderSearch
|
||||||
<ListGrafikBerdasarkanPendidikan />
|
title='Detail Data Pengangguran Berdasarkan Pendidikan'
|
||||||
|
placeholder='pencarian'
|
||||||
|
searchIcon={<IconSearch size={20} />}
|
||||||
|
value={search}
|
||||||
|
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
<ListGrafikBerdasarkanPendidikan search={search}/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ListGrafikBerdasarkanPendidikan() {
|
function ListGrafikBerdasarkanPendidikan({search}: {search: string}) {
|
||||||
const stategrafik = useProxy(grafikNganggur.grafikBerdasarkanPendidikan)
|
const stategrafik = useProxy(grafikNganggur.grafikBerdasarkanPendidikan)
|
||||||
const [donutData, setDonutData] = useState<any[]>([]);
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const [modalHapus, setModalHapus] = useState(false)
|
const [modalHapus, setModalHapus] = useState(false)
|
||||||
const [selectedId, setSelectedId] = useState<string | null>(null)
|
const [selectedId, setSelectedId] = useState<string | null>(null)
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [search, setSearch] = useState("");
|
|
||||||
|
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
@@ -56,11 +63,11 @@ function ListGrafikBerdasarkanPendidikan() {
|
|||||||
const D3 = stategrafik.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.D3 || 0), 0);
|
const D3 = stategrafik.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.D3 || 0), 0);
|
||||||
const S1 = stategrafik.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.S1 || 0), 0);
|
const S1 = stategrafik.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.S1 || 0), 0);
|
||||||
setDonutData([
|
setDonutData([
|
||||||
{ name: 'SD', value: SD, color: colors['blue-button'], key: 'SD' },
|
{ name: 'SD', value: SD, color: '#4b6Ef5', key: 'SD' },
|
||||||
{ name: 'SMP', value: SMP, color: '#10A85AFF', key: 'SMP' },
|
{ name: 'SMP', value: SMP, color: '#14b885', key: 'SMP' },
|
||||||
{ name: 'SMA', value: SMA, color: '#C07B13FF', key: 'SMA' },
|
{ name: 'SMA', value: SMA, color: '#E6A03B', key: 'SMA' },
|
||||||
{ name: 'D3', value: D3, color: '#1094A8FF', key: 'D3' },
|
{ name: 'D3', value: D3, color: '#DB524D', key: 'D3' },
|
||||||
{ name: 'S1', value: S1, color: '#A83610FF', key: 'S1' },
|
{ name: 'S1', value: S1, color: '#1018A8FF', key: 'S1' },
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}, [stategrafik.findMany.data])
|
}, [stategrafik.findMany.data])
|
||||||
@@ -88,13 +95,9 @@ function ListGrafikBerdasarkanPendidikan() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack gap={"xs"}>
|
<Stack gap={"xs"}>
|
||||||
<Paper bg={colors['white-1']} p={"md"}>
|
<Paper bg={colors['white-1']} p={"md"}>
|
||||||
<JudulListTab
|
<JudulList
|
||||||
value={search}
|
|
||||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
|
||||||
title='List Grafik Pengangguran Berdasarkan Pendidikan'
|
title='List Grafik Pengangguran Berdasarkan Pendidikan'
|
||||||
href='/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/create'
|
href='/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/create'
|
||||||
placeholder='pencarian'
|
|
||||||
searchIcon={<IconSearch size={16} />}
|
|
||||||
/>
|
/>
|
||||||
<Table striped withTableBorder withRowBorders>
|
<Table striped withTableBorder withRowBorders>
|
||||||
<TableThead>
|
<TableThead>
|
||||||
|
|||||||
@@ -8,29 +8,37 @@ import { useRouter } from 'next/navigation';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Cell, Pie, PieChart } from 'recharts';
|
import { Cell, Pie, PieChart } from 'recharts';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import JudulListTab from '../../../_com/judulListTab';
|
import HeaderSearch from '../../../_com/header';
|
||||||
|
import JudulList from '../../../_com/judulList';
|
||||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
import grafikNganggur from '../../../_state/ekonomi/usia-kerja-nganggur';
|
import grafikNganggur from '../../../_state/ekonomi/usia-kerja-nganggur';
|
||||||
|
|
||||||
|
|
||||||
function GrafikBerdasarkanUsiaKerjaYangMenganggur() {
|
function GrafikBerdasarkanUsiaKerjaYangMenganggur() {
|
||||||
|
const [search, setSearch] = useState("")
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Stack gap={"xs"}>
|
<Stack gap={"xs"}>
|
||||||
<Title order={3}>Grafik Pengangguran Berdasarkan Usia Kerja</Title>
|
<HeaderSearch
|
||||||
<ListGrafikBerdasarkanUsiaKerjaYangMenganggur />
|
title='Detail Data Pengangguran'
|
||||||
|
placeholder='pencarian'
|
||||||
|
searchIcon={<IconSearch size={20} />}
|
||||||
|
value={search}
|
||||||
|
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
<ListGrafikBerdasarkanUsiaKerjaYangMenganggur search={search} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ListGrafikBerdasarkanUsiaKerjaYangMenganggur() {
|
function ListGrafikBerdasarkanUsiaKerjaYangMenganggur({search}: {search: string}) {
|
||||||
const stategrafik = useProxy(grafikNganggur.grafikBerdasarkanUsiaKerjaNganggur)
|
const stategrafik = useProxy(grafikNganggur.grafikBerdasarkanUsiaKerjaNganggur)
|
||||||
const [donutData, setDonutData] = useState<any[]>([]);
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const [modalHapus, setModalHapus] = useState(false)
|
const [modalHapus, setModalHapus] = useState(false)
|
||||||
const [selectedId, setSelectedId] = useState<string | null>(null)
|
const [selectedId, setSelectedId] = useState<string | null>(null)
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [search, setSearch] = useState("");
|
|
||||||
|
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
@@ -85,13 +93,9 @@ function ListGrafikBerdasarkanUsiaKerjaYangMenganggur() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack gap={"xs"}>
|
<Stack gap={"xs"}>
|
||||||
<Paper bg={colors['white-1']} p={"md"}>
|
<Paper bg={colors['white-1']} p={"md"}>
|
||||||
<JudulListTab
|
<JudulList
|
||||||
value={search}
|
|
||||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
|
||||||
title='List Pengangguran Berdasarkan Usia Kerja'
|
title='List Pengangguran Berdasarkan Usia Kerja'
|
||||||
href='/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/create'
|
href='/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/create'
|
||||||
placeholder='pencarian'
|
|
||||||
searchIcon={<IconSearch size={16} />}
|
|
||||||
/>
|
/>
|
||||||
<Table striped withTableBorder withRowBorders>
|
<Table striped withTableBorder withRowBorders>
|
||||||
<TableThead>
|
<TableThead>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function DetailJumlahPengangguran() {
|
|||||||
stateDetail.delete.byId(selectedId)
|
stateDetail.delete.byId(selectedId)
|
||||||
setModalHapus(false)
|
setModalHapus(false)
|
||||||
setSelectedId(null)
|
setSelectedId(null)
|
||||||
router.push("/admin/ekonomi/jumlah-pengangguran/detail-data-pengangguran")
|
router.push("/admin/ekonomi/jumlah-pengangguran")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ function DetailJumlahPengangguran() {
|
|||||||
color={"red"}>
|
color={"red"}>
|
||||||
<IconX size={20} />
|
<IconX size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => router.push(`/admin/ekonomi/jumlah-pengangguran/detail-data-pengangguran/${stateDetail.findUnique.data?.id}/edit`)} color="green">
|
<Button onClick={() => router.push(`/admin/ekonomi/jumlah-pengangguran/${stateDetail.findUnique.data?.id}/edit`)} color="green">
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ function CreateJumlahPengangguran() {
|
|||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Tahun"
|
label="Tahun"
|
||||||
type="number"
|
type="date"
|
||||||
value={stateDetail.create.form.year}
|
value={stateDetail.create.form.year}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
(stateDetail.create.form.year = Number(e.currentTarget.value))
|
(stateDetail.create.form.year = Number(e.currentTarget.value))
|
||||||
|
|||||||
@@ -8,21 +8,29 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
import { BarChart } from '@mantine/charts';
|
import { BarChart } from '@mantine/charts';
|
||||||
|
import HeaderSearch from '../../_com/header';
|
||||||
|
import JudulList from '../../_com/judulList';
|
||||||
import jumlahPengangguranState from '../../_state/ekonomi/jumlah-pengangguran';
|
import jumlahPengangguranState from '../../_state/ekonomi/jumlah-pengangguran';
|
||||||
import JudulListTab from '../../_com/judulListTab';
|
|
||||||
|
|
||||||
function DetailDataPengangguran() {
|
function DetailDataPengangguran() {
|
||||||
|
const [search, setSearch] = useState("")
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Stack gap={"xs"}>
|
<Stack gap={"xs"}>
|
||||||
<Title order={3}>Detail Data Pengangguran</Title>
|
<HeaderSearch
|
||||||
<ListDetailDataPengangguran />
|
title='Detail Data Pengangguran'
|
||||||
|
placeholder='pencarian'
|
||||||
|
searchIcon={<IconSearch size={20} />}
|
||||||
|
value={search}
|
||||||
|
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
<ListDetailDataPengangguran search={search} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ListDetailDataPengangguran() {
|
function ListDetailDataPengangguran({search}: {search: string}) {
|
||||||
|
|
||||||
type DetailDataPengangguran = {
|
type DetailDataPengangguran = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -37,7 +45,6 @@ function ListDetailDataPengangguran() {
|
|||||||
const [mounted, setMounted] = useState(false); // untuk memastikan DOM sudah ready
|
const [mounted, setMounted] = useState(false); // untuk memastikan DOM sudah ready
|
||||||
const stateDetail = useProxy(jumlahPengangguranState.jumlahPengangguran)
|
const stateDetail = useProxy(jumlahPengangguranState.jumlahPengangguran)
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [search, setSearch] = useState("")
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
setMounted(true)
|
setMounted(true)
|
||||||
@@ -78,13 +85,9 @@ function ListDetailDataPengangguran() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack gap={"md"}>
|
<Stack gap={"md"}>
|
||||||
<Paper bg={colors['white-1']} p={'md'}>
|
<Paper bg={colors['white-1']} p={'md'}>
|
||||||
<JudulListTab
|
<JudulList
|
||||||
title='List Detail Data Pengangguran'
|
title='List Detail Data Pengangguran'
|
||||||
href='/admin/ekonomi/jumlah-pengangguran/detail-data-pengangguran/create'
|
href='/admin/ekonomi/jumlah-pengangguran/create'
|
||||||
value={search}
|
|
||||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
|
||||||
placeholder='pencarian'
|
|
||||||
searchIcon={<IconSearch size={16} />}
|
|
||||||
/>
|
/>
|
||||||
<Table striped withTableBorder withRowBorders>
|
<Table striped withTableBorder withRowBorders>
|
||||||
<TableThead>
|
<TableThead>
|
||||||
@@ -102,7 +105,7 @@ function ListDetailDataPengangguran() {
|
|||||||
<TableTd>{item.educatedUnemployment}</TableTd>
|
<TableTd>{item.educatedUnemployment}</TableTd>
|
||||||
<TableTd>{item.uneducatedUnemployment}</TableTd>
|
<TableTd>{item.uneducatedUnemployment}</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Button onClick={() => router.push(`/admin/ekonomi/jumlah-pengangguran/detail-data-pengangguran/${item.id}`)}>
|
<Button onClick={() => router.push(`/admin/ekonomi/jumlah-pengangguran/${item.id}`)}>
|
||||||
<IconDeviceImac size={20} />
|
<IconDeviceImac size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
|
|||||||
@@ -1,119 +0,0 @@
|
|||||||
'use client'
|
|
||||||
import colors from '@/con/colors';
|
|
||||||
import { Box, CheckIcon, Combobox, ComboboxChevron, ComboboxOption, ComboboxOptions, ComboboxTarget, Group, InputBase, InputPlaceholder, Paper, SimpleGrid, Stack, Text, useCombobox } from '@mantine/core';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
|
||||||
import { BarChart } from '@mantine/charts';
|
|
||||||
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
tahun: '2024',
|
|
||||||
Penduduk: 400000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
tahun: '2025',
|
|
||||||
Penduduk: 450000
|
|
||||||
},
|
|
||||||
|
|
||||||
]
|
|
||||||
const tahun = [
|
|
||||||
'2024',
|
|
||||||
'2025'
|
|
||||||
];
|
|
||||||
function Page() {
|
|
||||||
const combobox = useCombobox({
|
|
||||||
onDropdownClose: () => combobox.resetSelectedOption(),
|
|
||||||
onDropdownOpen: (eventSource) => {
|
|
||||||
if (eventSource === 'keyboard') {
|
|
||||||
combobox.selectActiveOption();
|
|
||||||
} else {
|
|
||||||
combobox.updateSelectedOptionIndex('active');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const [value, setValue] = useState<string | null>('2024');
|
|
||||||
|
|
||||||
const options = tahun.map((item) => (
|
|
||||||
<ComboboxOption value={item} key={item} active={item === value}>
|
|
||||||
<Group gap="xs">
|
|
||||||
{item === value && <CheckIcon size={12} />}
|
|
||||||
<span>{item}</span>
|
|
||||||
</Group>
|
|
||||||
</ComboboxOption>
|
|
||||||
));
|
|
||||||
return (
|
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
|
||||||
<BackButton />
|
|
||||||
</Box>
|
|
||||||
<Box px={{ base: 'md', md: 100 }} >
|
|
||||||
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
|
||||||
Jumlah Penduduk Miskin Tahun 2024-2025
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<Stack gap={'lg'} justify='center'>
|
|
||||||
<SimpleGrid
|
|
||||||
pb={20}
|
|
||||||
cols={{
|
|
||||||
base: 1,
|
|
||||||
md: 2
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Paper p={'xl'}>
|
|
||||||
<Text fz={'h3'}>Tahun: 2024</Text>
|
|
||||||
<Text fw={"bold"} fz={'h1'}>4,800,000 Orang</Text>
|
|
||||||
</Paper>
|
|
||||||
<Paper p={'xl'}>
|
|
||||||
<Text>Pilih Tahun</Text>
|
|
||||||
<Combobox
|
|
||||||
store={combobox}
|
|
||||||
resetSelectionOnOptionHover
|
|
||||||
withinPortal={false}
|
|
||||||
onOptionSubmit={(val) => {
|
|
||||||
setValue(val);
|
|
||||||
combobox.updateSelectedOptionIndex('active');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ComboboxTarget targetType="button">
|
|
||||||
<InputBase
|
|
||||||
component="button"
|
|
||||||
type="button"
|
|
||||||
pointer
|
|
||||||
rightSection={<ComboboxChevron />}
|
|
||||||
rightSectionPointerEvents="none"
|
|
||||||
onClick={() => combobox.toggleDropdown()}
|
|
||||||
>
|
|
||||||
{value || <InputPlaceholder>Pick value</InputPlaceholder>}
|
|
||||||
</InputBase>
|
|
||||||
</ComboboxTarget>
|
|
||||||
|
|
||||||
<Combobox.Dropdown>
|
|
||||||
<ComboboxOptions>{options}</ComboboxOptions>
|
|
||||||
</Combobox.Dropdown>
|
|
||||||
</Combobox>
|
|
||||||
</Paper>
|
|
||||||
</SimpleGrid>
|
|
||||||
<Paper p={'xl'}>
|
|
||||||
<Text pb={10} fw={'bold'} fz={'h4'}>Jumlah Penduduk Miskin Per Tahun</Text>
|
|
||||||
<BarChart
|
|
||||||
p={10}
|
|
||||||
h={300}
|
|
||||||
data={data}
|
|
||||||
dataKey="tahun"
|
|
||||||
series={[
|
|
||||||
{ name: 'Penduduk', color: '#8785D3' },
|
|
||||||
]}
|
|
||||||
tickLine="y"
|
|
||||||
/>
|
|
||||||
</Paper>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Page;
|
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
'use client'
|
||||||
|
import jumlahPendudukMiskin from '@/app/admin/(dashboard)/_state/ekonomi/jumlah-penduduk-miskin';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { BarChart } from '@mantine/charts';
|
||||||
|
import { Box, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
|
function Page() {
|
||||||
|
type JPMGrafik = {
|
||||||
|
id: string;
|
||||||
|
year: number;
|
||||||
|
totalPoorPopulation: number;
|
||||||
|
}
|
||||||
|
const state = useProxy(jumlahPendudukMiskin)
|
||||||
|
const [chartData, setChartData] = useState<JPMGrafik[]>([])
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
state.findMany.load()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (state.findMany.data) {
|
||||||
|
setChartData(state.findMany.data.map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
year: Number(item.year),
|
||||||
|
totalPoorPopulation: Number(item.totalPoorPopulation),
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}, [state.findMany.data]);
|
||||||
|
|
||||||
|
if (!state.findMany.data) {
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
<Skeleton h={500} />
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||||
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
|
<BackButton />
|
||||||
|
</Box>
|
||||||
|
<Box px={{ base: 'md', md: 100 }} >
|
||||||
|
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||||
|
Jumlah Penduduk Miskin
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
|
<Stack gap={'lg'} justify='center'>
|
||||||
|
<Paper p={'xl'}>
|
||||||
|
<Text fz={'h3'}>Jumlah Data Penduduk Miskin</Text>
|
||||||
|
<Text fw={"bold"} fz={'h1'}>
|
||||||
|
{state.findMany.data?.reduce((sum, item) => sum + (Number(item.totalPoorPopulation) || 0), 0).toLocaleString()} Orang
|
||||||
|
</Text>
|
||||||
|
</Paper>
|
||||||
|
<Paper p={'xl'}>
|
||||||
|
<Text pb={10} fw={'bold'} fz={'h4'}>Jumlah Penduduk Miskin Per Tahun</Text>
|
||||||
|
<BarChart
|
||||||
|
h={300}
|
||||||
|
data={chartData}
|
||||||
|
dataKey="year"
|
||||||
|
series={[
|
||||||
|
{ name: 'totalPoorPopulation', color: 'blue.6', label: 'Jumlah Penduduk Miskin' },
|
||||||
|
]}
|
||||||
|
xAxisLabel="Tahun"
|
||||||
|
yAxisLabel="Jumlah Penduduk"
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Page;
|
||||||
@@ -1,62 +1,76 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
'use client'
|
||||||
|
import grafikNganggur from '@/app/admin/(dashboard)/_state/ekonomi/usia-kerja-nganggur';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Stack, Box, Text, Center, Paper, ColorSwatch, Flex } from '@mantine/core';
|
|
||||||
import React from 'react';
|
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
|
||||||
import { PieChart } from '@mantine/charts';
|
import { PieChart } from '@mantine/charts';
|
||||||
|
import { Box, Center, ColorSwatch, Flex, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
const datausiaKerja = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: '18 - 25',
|
|
||||||
value: 45,
|
|
||||||
color: 'indigo.6'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: '26 - 35',
|
|
||||||
value: 35,
|
|
||||||
color: 'teal.6'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: '36 - 45',
|
|
||||||
value: 15,
|
|
||||||
color: 'yellow.6'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: '46+',
|
|
||||||
value: 5,
|
|
||||||
color: 'red.6'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const datakerjaPendidikan = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'SD',
|
|
||||||
value: 10,
|
|
||||||
color: 'indigo.6'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'SMP',
|
|
||||||
value: 20,
|
|
||||||
color: 'teal.6'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: 'SMA/SMK',
|
|
||||||
value: 45,
|
|
||||||
color: 'yellow.6'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: 'D3/S1',
|
|
||||||
value: 25,
|
|
||||||
color: 'red.6'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
function Page() {
|
function Page() {
|
||||||
|
const stateGrafikNganggur = useProxy(grafikNganggur.grafikBerdasarkanUsiaKerjaNganggur)
|
||||||
|
const stateGrafikNganggurPendidikan = useProxy(grafikNganggur.grafikBerdasarkanPendidikan)
|
||||||
|
const [donutGrafikNganggurData, setDonutGrafikNganggurData] = useState<any[]>([])
|
||||||
|
const [donutGrafikNganggurDataPendidikan, setDonutGrafikNganggurDataPendidikan] = useState<any[]>([])
|
||||||
|
const [mounted, setMounted] = useState(false)
|
||||||
|
const [mounted2, setMounted2] = useState(false)
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
setMounted(true)
|
||||||
|
setMounted2(true)
|
||||||
|
stateGrafikNganggur.findMany.load()
|
||||||
|
stateGrafikNganggurPendidikan.findMany.load()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (stateGrafikNganggur.findMany.data) {
|
||||||
|
const totalUsia18_25 = stateGrafikNganggur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.usia18_25 || 0), 0);
|
||||||
|
const totalUsia26_35 = stateGrafikNganggur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.usia26_35 || 0), 0);
|
||||||
|
const totalUsia36_45 = stateGrafikNganggur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.usia36_45 || 0), 0);
|
||||||
|
const totalUsia46_keatas = stateGrafikNganggur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.usia46_keatas || 0), 0);
|
||||||
|
setDonutGrafikNganggurData([
|
||||||
|
{ name: 'usia 18 - 25', value: totalUsia18_25, color: '#4b6Ef5', key: 'usia18_25' },
|
||||||
|
{ name: 'usia 26 - 35', value: totalUsia26_35, color: '#14b885', key: 'usia26_35' },
|
||||||
|
{ name: 'usia 36 - 45', value: totalUsia36_45, color: '#E6A03B', key: 'usia36_45' },
|
||||||
|
{ name: 'usia 46 +', value: totalUsia46_keatas, color: '#DB524D', key: 'usia46_keatas' },
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}, [stateGrafikNganggur.findMany.data])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (stateGrafikNganggurPendidikan.findMany.data) {
|
||||||
|
const SD = stateGrafikNganggurPendidikan.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.SD || 0), 0);
|
||||||
|
const SMP = stateGrafikNganggurPendidikan.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.SMP || 0), 0);
|
||||||
|
const SMA = stateGrafikNganggurPendidikan.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.SMA || 0), 0);
|
||||||
|
const D3 = stateGrafikNganggurPendidikan.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.D3 || 0), 0);
|
||||||
|
const S1 = stateGrafikNganggurPendidikan.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.S1 || 0), 0);
|
||||||
|
setDonutGrafikNganggurDataPendidikan([
|
||||||
|
{ name: 'SD', value: SD, color: '#4b6Ef5', key: 'SD' },
|
||||||
|
{ name: 'SMP', value: SMP, color: '#14b885', key: 'SMP' },
|
||||||
|
{ name: 'SMA', value: SMA, color: '#E6A03B', key: 'SMA' },
|
||||||
|
{ name: 'D3', value: D3, color: '#DB524D', key: 'D3' },
|
||||||
|
{ name: 'S1', value: S1, color: '#1018A8FF', key: 'S1' },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}, [stateGrafikNganggurPendidikan.findMany.data])
|
||||||
|
|
||||||
|
if (!stateGrafikNganggur.findMany.data) {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Skeleton h={500} />
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stateGrafikNganggur.findMany.data) {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Skeleton h={500} />
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
@@ -71,9 +85,18 @@ function Page() {
|
|||||||
<Stack gap={'lg'} justify='center'>
|
<Stack gap={'lg'} justify='center'>
|
||||||
<Paper p={'lg'}>
|
<Paper p={'lg'}>
|
||||||
<Text fw={'bold'} fz={'h3'}>Pengangguran Berdasarkan Usia</Text>
|
<Text fw={'bold'} fz={'h3'}>Pengangguran Berdasarkan Usia</Text>
|
||||||
<Center>
|
{mounted && donutGrafikNganggurData.length > 0 ? (<Box style={{ width: '100%', height: 'auto', minHeight: 200 }}>
|
||||||
<PieChart size={300} withLabelsLine labelsPosition="outside" labelsType="percent" withLabels data={datausiaKerja} withTooltip tooltipDataSource="segment" mx="auto" />
|
<PieChart
|
||||||
</Center>
|
size={300}
|
||||||
|
withLabelsLine
|
||||||
|
labelsPosition="outside"
|
||||||
|
labelsType="percent"
|
||||||
|
withLabels
|
||||||
|
data={donutGrafikNganggurData}
|
||||||
|
withTooltip
|
||||||
|
tooltipDataSource="segment"
|
||||||
|
mx="auto" />
|
||||||
|
</Box>) : <Skeleton h={500} />}
|
||||||
<Flex pb={30} justify={'center'} gap={'xl'} align={'center'}>
|
<Flex pb={30} justify={'center'} gap={'xl'} align={'center'}>
|
||||||
<Box>
|
<Box>
|
||||||
<Flex gap={{ base: 5, md: 8 }} align={'center'}>
|
<Flex gap={{ base: 5, md: 8 }} align={'center'}>
|
||||||
@@ -103,9 +126,18 @@ function Page() {
|
|||||||
</Paper>
|
</Paper>
|
||||||
<Paper p={'lg'}>
|
<Paper p={'lg'}>
|
||||||
<Text fw={'bold'} fz={'h3'}>Pengangguran Berdasarkan Pendidikan</Text>
|
<Text fw={'bold'} fz={'h3'}>Pengangguran Berdasarkan Pendidikan</Text>
|
||||||
<Center>
|
{mounted2 && donutGrafikNganggurDataPendidikan.length > 0 ? (<Center>
|
||||||
<PieChart size={300} withLabelsLine labelsPosition="outside" labelsType="percent" withLabels data={datakerjaPendidikan} withTooltip tooltipDataSource="segment" mx="auto" />
|
<PieChart
|
||||||
</Center>
|
size={300}
|
||||||
|
withLabelsLine
|
||||||
|
labelsPosition="outside"
|
||||||
|
labelsType="percent"
|
||||||
|
withLabels
|
||||||
|
data={donutGrafikNganggurDataPendidikan}
|
||||||
|
withTooltip
|
||||||
|
tooltipDataSource="segment"
|
||||||
|
mx="auto" />
|
||||||
|
</Center>) : <Skeleton h={500} />}
|
||||||
<Flex pb={30} justify={'center'} gap={'xl'} align={'center'}>
|
<Flex pb={30} justify={'center'} gap={'xl'} align={'center'}>
|
||||||
<Box>
|
<Box>
|
||||||
<Flex gap={{ base: 5, md: 8 }} align={'center'}>
|
<Flex gap={{ base: 5, md: 8 }} align={'center'}>
|
||||||
@@ -127,10 +159,16 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
<Flex gap={{ base: 5, md: 8 }} align={'center'}>
|
<Flex gap={{ base: 5, md: 8 }} align={'center'}>
|
||||||
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>D3/S1</Text>
|
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>D3</Text>
|
||||||
<ColorSwatch color="#DB524D" size={30} />
|
<ColorSwatch color="#DB524D" size={30} />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Flex gap={{ base: 5, md: 8 }} align={'center'}>
|
||||||
|
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>S1</Text>
|
||||||
|
<ColorSwatch color="#1018A8FF" size={30} />
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,177 +0,0 @@
|
|||||||
import colors from '@/con/colors';
|
|
||||||
import { BarChart } from '@mantine/charts';
|
|
||||||
import { Box, Button, Center, ColorSwatch, Flex, Group, Paper, SimpleGrid, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
|
|
||||||
import { IconChevronDown, IconDownload, IconSchool, IconSchoolOff, IconUserOff } from '@tabler/icons-react';
|
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
|
||||||
|
|
||||||
const data1 = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
icon: <IconUserOff size={35} />,
|
|
||||||
judul: 'Total Pengangguran',
|
|
||||||
jumlah: '140',
|
|
||||||
persentase: <Text fz={'h4'} c={'green'}>-12.5% dari 2024</Text>
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
icon: <IconSchool size={35} />,
|
|
||||||
judul: 'Pengangguran Terdidik',
|
|
||||||
jumlah: '80',
|
|
||||||
persentase: <Text fz={'h4'} c={'gray'}>57.1% dari total</Text>
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
icon: <IconSchoolOff size={35} />,
|
|
||||||
judul: 'Pengangguran Tidak Terdidik',
|
|
||||||
jumlah: '60',
|
|
||||||
persentase: <Text fz={'h4'} c={'gray'}>42.9% dari total</Text>
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const dataPengangguran = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
bulan: 'Jan',
|
|
||||||
berpendidikan: 98,
|
|
||||||
takberpendidikan: 74,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
bulan: 'Feb',
|
|
||||||
berpendidikan: 85,
|
|
||||||
takberpendidikan: 74,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
bulan: 'Mar',
|
|
||||||
berpendidikan: 76,
|
|
||||||
takberpendidikan: 55,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
bulan: 'Apr',
|
|
||||||
berpendidikan: 98,
|
|
||||||
takberpendidikan: 74,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
bulan: 'Mei',
|
|
||||||
berpendidikan: 74,
|
|
||||||
takberpendidikan: 54,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
bulan: 'Jun',
|
|
||||||
berpendidikan: 55,
|
|
||||||
takberpendidikan: 50,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const dataTable = [
|
|
||||||
{ bulan: 'Jan', total: 160, terdidik: 95, takterdidik: 65, perubahan: '-' },
|
|
||||||
{ bulan: 'Feb', total: 155, terdidik: 90, takterdidik: 65, perubahan: '-3.1%' },
|
|
||||||
{ bulan: 'Mar', total: 150, terdidik: 88, takterdidik: 62, perubahan: '-3.2%' },
|
|
||||||
{ bulan: 'Apr', total: 148, terdidik: 85, takterdidik: 63, perubahan: '-1.3%' },
|
|
||||||
{ bulan: 'Mei', total: 145, terdidik: 82, takterdidik: 63, perubahan: '-2.0%' },
|
|
||||||
{ bulan: 'Jun', total: 140, terdidik: 80, takterdidik: 60, perubahan: '-3.4%' },
|
|
||||||
]
|
|
||||||
function Page() {
|
|
||||||
const rows = dataTable.map((element) => (
|
|
||||||
<TableTr key={element.bulan}>
|
|
||||||
<TableTd ta={'center'}>{element.bulan}</TableTd>
|
|
||||||
<TableTd ta={'center'}>{element.total}</TableTd>
|
|
||||||
<TableTd ta={'center'}>{element.terdidik}</TableTd>
|
|
||||||
<TableTd ta={'center'}>{element.takterdidik}</TableTd>
|
|
||||||
<TableTd ta={'center'}>{element.perubahan}</TableTd>
|
|
||||||
</TableTr>
|
|
||||||
));
|
|
||||||
return (
|
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
|
||||||
<BackButton />
|
|
||||||
</Box>
|
|
||||||
<Box px={{ base: 'md', md: 100 }} >
|
|
||||||
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
|
||||||
Jumlah Pengangguran 2024 - 2025
|
|
||||||
</Text>
|
|
||||||
<Group py={20} align='center' justify='space-between'>
|
|
||||||
<Text fz={'h4'} fw={"bold"}>DATA PENGANGGURAN DESA</Text>
|
|
||||||
<Flex gap={'xl'}>
|
|
||||||
<Button c={'black'} bg={colors['white-1']} rightSection={<IconChevronDown size={20} />}>2025</Button>
|
|
||||||
<Button leftSection={<IconDownload size={20} />}>Export</Button>
|
|
||||||
</Flex>
|
|
||||||
</Group>
|
|
||||||
</Box>
|
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<Stack gap={'lg'} justify='center'>
|
|
||||||
<SimpleGrid
|
|
||||||
cols={1}
|
|
||||||
pb={20}
|
|
||||||
>
|
|
||||||
{data1.map((v, k) => {
|
|
||||||
return (
|
|
||||||
<Paper px={25} key={k} py={'lg'} bg={colors['white-1']} shadow={'md'}>
|
|
||||||
<Flex justify={'space-between'} align={'center'}>
|
|
||||||
<Box>
|
|
||||||
<Stack>
|
|
||||||
<Text fz={'h4'}>{v.judul}</Text>
|
|
||||||
<Text fz={'h2'} fw={'bold'}>{v.jumlah}</Text>
|
|
||||||
{v.persentase}
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
{v.icon}
|
|
||||||
</Flex>
|
|
||||||
</Paper>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</SimpleGrid>
|
|
||||||
<Paper p={'lg'}>
|
|
||||||
<Flex pb={30} justify={'flex-end'} gap={'xl'} align={'center'}>
|
|
||||||
<Box>
|
|
||||||
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
|
||||||
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Pengangguran Berpendidikan</Text>
|
|
||||||
<ColorSwatch color="#5082EE" size={30} />
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
|
||||||
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Pengangguran Tak Berpendidikan</Text>
|
|
||||||
<ColorSwatch color="#DA524C" size={30} />
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
<Center>
|
|
||||||
<BarChart
|
|
||||||
p={10}
|
|
||||||
h={400}
|
|
||||||
data={dataPengangguran}
|
|
||||||
dataKey="bulan"
|
|
||||||
series={[
|
|
||||||
{ name: 'berpendidikan', color: '#5082EE' },
|
|
||||||
{ name: 'takberpendidikan', color: '#DA524C' },
|
|
||||||
]}
|
|
||||||
tickLine="y"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Paper>
|
|
||||||
<Paper p={'lg'}>
|
|
||||||
<Text fw={'bold'} fz={'h4'}>Detail Data Pengangguran</Text>
|
|
||||||
<Table striped highlightOnHover>
|
|
||||||
<TableThead>
|
|
||||||
<TableTr>
|
|
||||||
<TableTh ta={'center'}>Bulan</TableTh>
|
|
||||||
<TableTh ta={'center'}>Total</TableTh>
|
|
||||||
<TableTh ta={'center'}>Terdidik</TableTh>
|
|
||||||
<TableTh ta={'center'}>Tidak Terdidik</TableTh>
|
|
||||||
<TableTh ta={'center'}>Perubahan</TableTh>
|
|
||||||
</TableTr>
|
|
||||||
</TableThead>
|
|
||||||
<TableTbody>{rows}</TableTbody>
|
|
||||||
</Table>
|
|
||||||
</Paper>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Page;
|
|
||||||
190
src/app/darmasaba/(pages)/ekonomi/jumlah-pengangguran/page.tsx
Normal file
190
src/app/darmasaba/(pages)/ekonomi/jumlah-pengangguran/page.tsx
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
'use client'
|
||||||
|
import jumlahPengangguranState from '@/app/admin/(dashboard)/_state/ekonomi/jumlah-pengangguran';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { BarChart } from '@mantine/charts';
|
||||||
|
import { Box, ColorSwatch, Flex, Group, Paper, SimpleGrid, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconSchool, IconSchoolOff, IconUserOff } from '@tabler/icons-react';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
|
type DataPengangguran = {
|
||||||
|
id: string;
|
||||||
|
bulan: string;
|
||||||
|
berpendidikan: number;
|
||||||
|
takberpendidikan: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Page() {
|
||||||
|
const [chartData, setChartData] = useState<DataPengangguran[]>([])
|
||||||
|
const [mounted, setMounted] = useState(false)
|
||||||
|
const state = useProxy(jumlahPengangguranState.jumlahPengangguran)
|
||||||
|
// const [selectedYear, setSelectedYear] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
setMounted(true)
|
||||||
|
state.findMany.load()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
if (state.findMany.data) {
|
||||||
|
setChartData(state.findMany.data.map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
bulan: item.month,
|
||||||
|
berpendidikan: Number(item.educatedUnemployment),
|
||||||
|
takberpendidikan: Number(item.uneducatedUnemployment),
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}, [state.findMany.data]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||||
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
|
<BackButton />
|
||||||
|
</Box>
|
||||||
|
<Box px={{ base: 'md', md: 100 }} >
|
||||||
|
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||||
|
Jumlah Pengangguran
|
||||||
|
</Text>
|
||||||
|
<Group py={20} align='center' justify='space-between'>
|
||||||
|
<Text fz={'h4'} fw={"bold"}>DATA PENGANGGURAN DESA</Text>
|
||||||
|
{/* <Flex gap={'xl'}>
|
||||||
|
<Select
|
||||||
|
value={selectedYear || state.findMany.data?.[0]?.year.toString()}
|
||||||
|
placeholder="Pilih Tahun"
|
||||||
|
data={Array.from(new Set(state.findMany.data?.map(item => item.year.toString()) || []))}
|
||||||
|
onChange={setSelectedYear}
|
||||||
|
/>
|
||||||
|
</Flex> */}
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
|
<Stack gap={'lg'} justify='center'>
|
||||||
|
<SimpleGrid
|
||||||
|
cols={1}
|
||||||
|
pb={20}
|
||||||
|
>
|
||||||
|
<SimpleGrid cols={{ base: 1, md: 3 }} spacing="md">
|
||||||
|
{/* Total Unemployment Card */}
|
||||||
|
<Paper px={25} py={'lg'} bg={colors['white-1']} shadow="md">
|
||||||
|
<Flex direction="column" gap="md">
|
||||||
|
<IconUserOff size={35} color={colors['blue-button']} />
|
||||||
|
<Text fz="h4" fw={600}>Total Pengangguran</Text>
|
||||||
|
<Text fz="h2" fw={700} c={colors['blue-button']}>
|
||||||
|
{state.findMany.data?.[0]?.totalUnemployment || 0} Orang
|
||||||
|
</Text>
|
||||||
|
<Text fz="sm" c="dimmed">
|
||||||
|
Data tahun {state.findMany.data?.[0]?.year || ''}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* Educated Unemployment Card */}
|
||||||
|
<Paper px={25} py={'lg'} bg={colors['white-1']} shadow="md">
|
||||||
|
<Flex direction="column" gap="md">
|
||||||
|
<IconSchool size={35} color="#5082EE" />
|
||||||
|
<Text fz="h4" fw={600}>Pengangguran Terdidik</Text>
|
||||||
|
<Text fz="h2" fw={700} c="#5082EE">
|
||||||
|
{state.findMany.data?.[0]?.educatedUnemployment || 0} Orang
|
||||||
|
</Text>
|
||||||
|
<Text fz="sm" c="dimmed">
|
||||||
|
{state.findMany.data?.[0]?.totalUnemployment ?
|
||||||
|
`${Math.round((state.findMany.data[0].educatedUnemployment / state.findMany.data[0].totalUnemployment) * 100)}% dari total` :
|
||||||
|
'0% dari total'}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* Uneducated Unemployment Card */}
|
||||||
|
<Paper px={25} py={'lg'} bg={colors['white-1']} shadow="md">
|
||||||
|
<Flex direction="column" gap="md">
|
||||||
|
<IconSchoolOff size={35} color="#DA524C" />
|
||||||
|
<Text fz="h4" fw={600}>Pengangguran Tidak Terdidik</Text>
|
||||||
|
<Text fz="h2" fw={700} c="#DA524C">
|
||||||
|
{state.findMany.data?.[0]?.uneducatedUnemployment || 0} Orang
|
||||||
|
</Text>
|
||||||
|
<Text fz="sm" c="dimmed">
|
||||||
|
{state.findMany.data?.[0]?.totalUnemployment ?
|
||||||
|
`${Math.round((state.findMany.data[0].uneducatedUnemployment / state.findMany.data[0].totalUnemployment) * 100)}% dari total` :
|
||||||
|
'0% dari total'}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Paper>
|
||||||
|
</SimpleGrid>
|
||||||
|
</SimpleGrid>
|
||||||
|
<Paper p={'lg'}>
|
||||||
|
<Flex pb={30} justify={'flex-end'} gap={'xl'} align={'center'}>
|
||||||
|
<Box>
|
||||||
|
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
||||||
|
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Pengangguran Berpendidikan</Text>
|
||||||
|
<ColorSwatch color="#5082EE" size={30} />
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
||||||
|
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Pengangguran Tak Berpendidikan</Text>
|
||||||
|
<ColorSwatch color="#DA524C" size={30} />
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
{!mounted || chartData.length === 0 ? (
|
||||||
|
<Box style={{ width: '100%', minWidth: 300, height: 400, minHeight: 300 }}>
|
||||||
|
<Paper bg={colors['white-1']} p={'md'}>
|
||||||
|
<Title pb={10} order={3}>Data Pengangguran Terdidik dan Tidak Terdidik</Title>
|
||||||
|
<Text c='dimmed'>Belum ada data untuk ditampilkan dalam grafik</Text>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Box style={{ width: '100%', minWidth: 300, height: 550, minHeight: 300 }}>
|
||||||
|
<Paper bg={colors['white-1']} p={'md'}>
|
||||||
|
<Title pb={10} order={4}>Data Pengangguran Terdidik dan Tidak Terdidik</Title>
|
||||||
|
<Box w={{ base: '100%', md: '70%' }}>
|
||||||
|
<BarChart
|
||||||
|
h={450}
|
||||||
|
data={chartData}
|
||||||
|
dataKey="bulan"
|
||||||
|
series={[
|
||||||
|
{ name: 'berpendidikan', color: '#5082EE', label: 'Terdidik' },
|
||||||
|
{ name: 'takberpendidikan', color: '#DA524C', label: 'Tidak Terdidik' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</Paper>
|
||||||
|
<Paper p={'lg'}>
|
||||||
|
<Text fw={'bold'} fz={'h4'}>Detail Data Pengangguran</Text>
|
||||||
|
<Table striped highlightOnHover>
|
||||||
|
<TableThead>
|
||||||
|
<TableTr>
|
||||||
|
<TableTh ta={'center'}>Bulan</TableTh>
|
||||||
|
<TableTh ta={'center'}>Total</TableTh>
|
||||||
|
<TableTh ta={'center'}>Terdidik</TableTh>
|
||||||
|
<TableTh ta={'center'}>Tidak Terdidik</TableTh>
|
||||||
|
<TableTh ta={'center'}>Perubahan</TableTh>
|
||||||
|
</TableTr>
|
||||||
|
</TableThead>
|
||||||
|
<TableTbody>
|
||||||
|
{state.findMany.data?.map((item, index) => (
|
||||||
|
<TableTr key={item?.id ? String(item.id) : `row-${index}`}>
|
||||||
|
<TableTd ta={'center'}>{item.month}</TableTd>
|
||||||
|
<TableTd ta={'center'}>{item.totalUnemployment}</TableTd>
|
||||||
|
<TableTd ta={'center'}>{item.educatedUnemployment}</TableTd>
|
||||||
|
<TableTd ta={'center'}>{item.uneducatedUnemployment}</TableTd>
|
||||||
|
<TableTd ta={'center'}>{item.percentageChange}</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
))}
|
||||||
|
</TableTbody>
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Page;
|
||||||
@@ -197,8 +197,8 @@ const navbarListMenu = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5.5",
|
id: "5.5",
|
||||||
name: "Jumlah Pengangguran 2024-2025",
|
name: "Jumlah Pengangguran",
|
||||||
href: "/darmasaba/ekonomi/jumlah-pengangguran-2024-2025"
|
href: "/darmasaba/ekonomi/jumlah-pengangguran"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5.6",
|
id: "5.6",
|
||||||
@@ -207,8 +207,8 @@ const navbarListMenu = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5.7",
|
id: "5.7",
|
||||||
name: "Jumlah Penduduk Miskin 2024-2025",
|
name: "Jumlah Penduduk Miskin",
|
||||||
href: "/darmasaba/ekonomi/jumlah-penduduk-miskin-2024-2025"
|
href: "/darmasaba/ekonomi/jumlah-penduduk-miskin"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5.8",
|
id: "5.8",
|
||||||
|
|||||||
Reference in New Issue
Block a user