import { Card, CardContent, CardHeader, CardTitle } from "@/Components/ui/card"
import { StatsCard } from "@/Components/StatsCard"
import { GraduationCap, HomeIcon } from "lucide-react";
import { Head } from "@inertiajs/react";
import { MapContainer, GeoJSON } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import { PathOptions, StyleFunction } from 'leaflet';
import React, { useEffect, useState } from "react";
import { Feature, Geometry, GeoJsonObject } from 'geojson';
import ColorRangeLegend from "@/Components/Map/ColorRangeLegend";
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/Components/ui/table";
import { NameType, ValueType } from 'recharts/types/component/DefaultTooltipContent';
import { TooltipProps } from 'recharts';
// import type { TooltipContentProps } from "recharts/types/component/Tooltip";
import GuestLayout from '@/Layouts/GuestLayout';
export default function DashboardPage({ tahun, tanggal, jumlahKota, jumlahKecamatan, jumlahPelatihan, jumlahPeserta, dataPeta, sebaranPesertaPerKota, grafikPesertaJenisKelamin, kotas, tableData, organisasi }: { tahun: number, tanggal: string, jumlahKota: number, jumlahKecamatan: number, jumlahPelatihan: number, jumlahPeserta: number, dataPeta: any, sebaranPesertaPerKota: any, grafikPesertaJenisKelamin: any, kotas: any, tableData: any, organisasi: any }) {
const position: [number, number] = [0.5022, 117.1536];
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [geoJsonData, setGeoJsonData] = useState<GeoJsonObject | null>(null);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const colors = ['#FFEDA0', '#FED976', '#FEB24C', '#FD8D3C', '#FC4E2A', '#E31A1C', '#BD0026', '#800026'];
const labels = ['>0', '>10', '>20', '>50', '>100', '>200', '>500', '>1000'];
const transformedData = organisasi.map((org:any) => {
var result : any = {};
result['organisasi'] = org.name;
result['jumlah'] = org.jumlah;
for (let x = 0; x < org.jumlah_anggotas.length; x++) {
const ja = org.jumlah_anggotas[x];
result[`U${ja.umur}_L`] = ja.jumlah_l;
result[`U${ja.umur}_P`] = ja.jumlah_p;
}
return result;
});
const CustomTooltip = ({ active, payload, label }:any) => {
if (active && payload && payload.length) {
// Filter out entries with value 0
const nonZeroData = payload.filter((entry:any) => entry.value > 0);
return (
<div className="p-2 bg-white border border-gray-200 rounded-md shadow-md max-w-4xl">
<p className="font-bold mb-2">{label}</p>
<div className="grid grid-cols-6 gap-2 mb-2">
{nonZeroData.map((entry:any, index:any) => (
<div key={index} style={{ color: entry.color }} className="flex gap-2">
<span>{entry.name} :</span>
<span className="text-right p-1">{entry.value}</span>
</div>
))}
</div>
<p className="font-bold">
Total : {nonZeroData.reduce((sum:any, entry:any) => sum + (entry.value as number), 0)}
</p>
</div>
);
}
return null;
};
const getColor = (value: number) => {
return value > 1000 ? '#800026' :
value > 500 ? '#BD0026' :
value > 200 ? '#E31A1C' :
value > 100 ? '#FC4E2A' :
value > 50 ? '#FD8D3C' :
value > 20 ? '#FEB24C' :
value > 10 ? '#FED976' :
'#FFEDA0';
};
const formatTooltip = (feature: Feature<Geometry, any>): string => {
const properties = feature.properties
let content = `<strong>${properties.WADMKK}</strong><br/>`
// for (const [key, value] of Object.entries(properties)) {
// if (key !== "name") {
// content += `${key}: ${value}<br/>`
// }
// }
content += `Peserta: ${dataPeta[properties.KDPKAB]}<br/>`
return content
}
const style: StyleFunction = (feature: any): PathOptions => {
//const regionId = feature.properties.id;
// const value = regionData[regionId]?.value || 0;
return {
fillColor: getColor(dataPeta[feature.properties.KDPKAB]),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
};
useEffect(() => {
console.log(kotas);
const loadGeoJson = async () => {
try {
const response = await fetch('/geojson/kaltim.geojson');
if (!response.ok) {
throw new Error('Failed to load GeoJSON data');
}
const data: GeoJsonObject = await response.json();
setGeoJsonData(data);
setLoading(false);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load GeoJSON data');
setLoading(false);
}
};
loadGeoJson();
}, []);
return (
<GuestLayout>
<div className="min-h-screen bg-gray-50">
<Head title="Home" />
{/* Breadcrumb */}
<div className="container mx-auto px-4 py-2">
<div className="flex items-center gap-2 text-sm text-gray-600">
<HomeIcon className="h-4 w-4" />
<span>/</span>
<span>Home</span>
<span className="ml-auto">{tanggal}</span>
</div>
</div>
<div className="container mx-auto mb-4">
<select
name="tahun"
defaultValue={tahun}
onChange={(e) => {
//router.get(`?tahun=${e.target.value}`, {})
window.location.href = `?tahun=${e.target.value}`;
}}
className=" w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-hidden"
>
<option value="2024" {...(tahun == 2024 ? { selected: true } : {})}>Tahun 2024</option>
<option value="2025" {...(tahun == 2025 ? { selected: true } : {})}>Tahun 2025</option>
</select>
</div>
{/* Stats Grid */}
<div className="container mx-auto mb-4">
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
<StatsCard title="Kabupaten/Kota" value={`${jumlahKota}`} className="bg-[#4CAF50] text-white" />
<StatsCard title="Kecamatan" value={`${jumlahKecamatan}`} className="bg-[#2196F3] text-white" />
<StatsCard title="Pelatihan" value={`${jumlahPelatihan}`} className="bg-[#FFC107] text-white" />
<StatsCard title="Peserta" value={`${jumlahPeserta}`} className="bg-[#00BCD4] text-white" />
</div>
</div>
<Card className="container mx-auto overflow-hidden mb-4">
<CardHeader className="bg-blue-500 text-white ">
<CardTitle><h1>Persebaran Data Peserta</h1></CardTitle>
</CardHeader>
<CardContent className="h-[600px] py-6">
<MapContainer
center={position}
zoom={7}
style={{ height: '100%', width: '100%' }}
scrollWheelZoom={false}
>
{geoJsonData && <GeoJSON
data={geoJsonData}
style={style}
onEachFeature={(feature, layer) => {
const tooltipContent = formatTooltip(feature)
layer.bindTooltip(tooltipContent, {
permanent: false,
direction: "top",
opacity: 0.9,
className: "custom-tooltip",
})
layer.bindPopup(tooltipContent)
}}
/>}
<ColorRangeLegend colors={colors} labels={labels} />
</MapContainer>
</CardContent>
</Card>
<Card className="container mx-auto overflow-hidden mb-4">
<CardHeader className="bg-blue-500 text-white ">
<CardTitle><h1>Persebaran Data Peserta</h1></CardTitle>
</CardHeader>
<CardContent className="px-6 py-6">
<ResponsiveContainer width="100%" height={600}>
<BarChart
layout="vertical"
data={sebaranPesertaPerKota}
margin={{
top: 20,
right: 0,
left: 0,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis type="number" />
<YAxis dataKey="name" type="category" width={200} />
<Tooltip />
<Legend />
<Bar dataKey="value" fill="#8884d8" name={"Peserta"} />
</BarChart>
</ResponsiveContainer>
</CardContent>
</Card>
<Card className="container mx-auto overflow-hidden mb-4">
<CardHeader className="bg-blue-500 text-white ">
<CardTitle><h1>Grafik Peserta</h1></CardTitle>
</CardHeader>
<CardContent className="px-6 py-6">
<div className="mb-4">
<ResponsiveContainer width="100%" height={200}>
<BarChart
layout="vertical"
data={grafikPesertaJenisKelamin}
margin={{
top: 20,
right: 0,
left: 0,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis type="number" />
<YAxis dataKey="name" type="category" width={200} />
<Tooltip />
<Legend />
<Bar dataKey="value" fill="#8884d8" name={"Peserta"} />
</BarChart>
</ResponsiveContainer>
</div>
<div className="mb-4">
<h1>Persebaran Data Peserta</h1>
<Table className="min-w-full">
<TableHeader>
<TableRow>
<TableHead>Jenis Kelamin</TableHead>
{kotas.map((kota: any, index: number) => (
<TableHead key={`kota-${index}`}>{kota.name}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
<TableRow >
<TableCell>Laki-Laki</TableCell>
{kotas.map((kota: any, index: number) => (
<TableCell key={`kota-l-${index}`}>{tableData['laki-laki'][kota.id]}</TableCell>
))}
</TableRow>
<TableRow >
<TableCell>Perempuan</TableCell>
{kotas.map((kota: any, index: number) => (
<TableCell key={`kota-p-${index}`}>{tableData['perempuan'][kota.id]}</TableCell>
))}
</TableRow>
</TableBody>
</Table>
</div>
</CardContent>
</Card>
<Card className="container mx-auto overflow-hidden mb-4">
<CardHeader className="bg-blue-500 text-white ">
<CardTitle><h1>Anggota Aktif Pada Organisasi Kepemudaan dan Organisasi Sosial Masyarakat</h1></CardTitle>
</CardHeader>
<CardContent>
<ResponsiveContainer width="100%" height={400}>
<BarChart data={transformedData}>
<XAxis dataKey="organisasi" tick={{ fontSize: 10 }} tickFormatter={(value) => {
return `${value}`.substring(0, 10) + "...";
}} />
<YAxis />
<Tooltip />
<Legend />
<Bar dataKey="jumlah" fill="#8884d8" name="Jumlah Anggota" />
</BarChart>
</ResponsiveContainer>
</CardContent>
</Card>
<Card className="container mx-auto overflow-hidden mb-4">
<CardHeader className="bg-blue-500 text-white ">
<CardTitle><h1>Anggota Aktif Pada Organisasi Kepemudaan dan Organisasi Sosial Masyarakat</h1></CardTitle>
</CardHeader>
<CardContent>
<ResponsiveContainer width="100%" height={2600}>
<BarChart
data={transformedData}
layout="vertical"
margin={{
top: 20,
right: 0,
left: 0,
bottom: 20
}}
>
{/* <XAxis
dataKey="organisasi"
angle={-45}
textAnchor="end"
tick={{ fontSize: 10 }} tickFormatter={(value) => value.substring(0, 10) + "..."}
height={100}
/>
<YAxis /> */}
<XAxis type="number" />
<YAxis
type="category"
dataKey="organisasi"
width={200}
tick={{ fontSize: 10 }} tickFormatter={(value) => `${value}`.substring(0, 40) + "..."}
/>
<Tooltip content={CustomTooltip} />
<Legend />
<Bar dataKey="U16_L" fill="#E91E63" stackId="male" />
<Bar dataKey="U17_L" fill="#C2185B" stackId="male" />
<Bar dataKey="U18_L" fill="#880E4F" stackId="male" />
<Bar dataKey="U19_L" fill="#5D0934" stackId="male" />
<Bar dataKey="U20_L" fill="#3D0623" stackId="male" />
<Bar dataKey="U21_L" fill="#370520" stackId="male" />
<Bar dataKey="U22_L" fill="#31051c" stackId="male" />
<Bar dataKey="U22_L" fill="#2b0419" stackId="male" />
<Bar dataKey="U23_L" fill="#250415" stackId="male" />
<Bar dataKey="U24_L" fill="#1f0312" stackId="male" />
<Bar dataKey="U25_L" fill="#18020e" stackId="male" />
<Bar dataKey="U26_L" fill="#12020b" stackId="male" />
<Bar dataKey="U27_L" fill="#0c0107" stackId="male" />
<Bar dataKey="U28_L" fill="#060104" stackId="male" />
<Bar dataKey="U29_L" fill="#1a1a1a" stackId="male" />
<Bar dataKey="U30_L" fill="#000000" stackId="male" />
<Bar dataKey="U16_P" fill="#E91E63" stackId="female" />
<Bar dataKey="U17_P" fill="#C2185B" stackId="female" />
<Bar dataKey="U18_P" fill="#880E4F" stackId="female" />
<Bar dataKey="U19_P" fill="#5D0934" stackId="female" />
<Bar dataKey="U20_P" fill="#3D0623" stackId="female" />
<Bar dataKey="U21_P" fill="#370520" stackId="female" />
<Bar dataKey="U22_P" fill="#31051c" stackId="female" />
<Bar dataKey="U22_P" fill="#2b0419" stackId="female" />
<Bar dataKey="U23_P" fill="#250415" stackId="female" />
<Bar dataKey="U24_P" fill="#1f0312" stackId="female" />
<Bar dataKey="U25_P" fill="#18020e" stackId="female" />
<Bar dataKey="U26_P" fill="#12020b" stackId="female" />
<Bar dataKey="U27_P" fill="#0c0107" stackId="female" />
<Bar dataKey="U28_P" fill="#060104" stackId="female" />
<Bar dataKey="U29_P" fill="#1a1a1a" stackId="female" />
<Bar dataKey="U30_P" fill="#000000" stackId="female" />
</BarChart>
</ResponsiveContainer>
</CardContent>
</Card>
<Card className="container mx-auto overflow-hidden mb-4">
<CardHeader className="bg-blue-500 text-white ">
<CardTitle><h1>Anggota Aktif Pada Organisasi Kepemudaan dan Organisasi Sosial Masyarakat</h1></CardTitle>
</CardHeader>
<CardContent>
<div className="overflow-auto max-w-full">
<Table>
<TableHeader>
<TableRow>
<TableHead>No</TableHead>
<TableHead>Organisasi Kepemudaan</TableHead>
{[...Array(14)].map((x, i) =>
<React.Fragment key={i}>
<TableHead>U{i + 16} L</TableHead>
<TableHead>U{i + 16} P</TableHead>
</React.Fragment>
)}
<TableHead>Jumlah</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{organisasi.map((item: any, index: number) => (
<TableRow key={"organisasi" + index}>
<TableCell>{index + 1}</TableCell>
<TableCell>{item.name}</TableCell>
{[...Array(14)].map((x, i) =>
<React.Fragment key={i}>
<TableCell>{item.jumlah_anggotas[i] != null ? item.jumlah_anggotas[i].jumlah_l : 0}</TableCell>
<TableCell>{item.jumlah_anggotas[i] != null ? item.jumlah_anggotas[i].jumlah_p : 0}</TableCell>
</React.Fragment>
)}
<TableCell>{item.jumlah}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</CardContent>
</Card>
</div>
</GuestLayout>
)
}
Anons79 File Manager Version 1.0, Coded By Anons79
Email: [email protected]