ayo commit lagi
This commit is contained in:
@@ -26,6 +26,7 @@ export default function JenisPendaftaranPerAngkatanChart({ tahunAngkatan }: Prop
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [data, setData] = useState<JenisPendaftaranData[]>([]);
|
||||
const [series, setSeries] = useState<number[]>([]);
|
||||
const [chartColors, setChartColors] = useState<string[]>([]);
|
||||
const [options, setOptions] = useState<ApexOptions>({
|
||||
chart: {
|
||||
type: 'pie',
|
||||
@@ -43,7 +44,7 @@ export default function JenisPendaftaranPerAngkatanChart({ tahunAngkatan }: Prop
|
||||
}
|
||||
},
|
||||
labels: [],
|
||||
colors: ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899', '#06B6D4', '#F97316'],
|
||||
colors: [],
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
fontSize: '14px',
|
||||
@@ -101,9 +102,11 @@ export default function JenisPendaftaranPerAngkatanChart({ tahunAngkatan }: Prop
|
||||
tooltip: {
|
||||
...prev.tooltip,
|
||||
theme: theme === 'dark' ? 'dark' : 'light'
|
||||
}
|
||||
},
|
||||
// Preserve computed colors across theme changes
|
||||
colors: chartColors.length > 0 ? chartColors : prev.colors,
|
||||
}));
|
||||
}, [theme]);
|
||||
}, [theme, chartColors]);
|
||||
|
||||
// Update dataLabels formatter when data changes
|
||||
useEffect(() => {
|
||||
@@ -141,29 +144,46 @@ export default function JenisPendaftaranPerAngkatanChart({ tahunAngkatan }: Prop
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const response = await fetch(`/api/mahasiswa/jenis-pendaftaran?tahun_angkatan=${tahunAngkatan}`);
|
||||
// Fetch year-filtered data and global data in parallel
|
||||
const [response, allResponse] = await Promise.all([
|
||||
fetch(`/api/mahasiswa/jenis-pendaftaran?tahun_angkatan=${tahunAngkatan}`),
|
||||
fetch('/api/mahasiswa/jenis-pendaftaran'),
|
||||
]);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch data: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
const allResult = allResponse.ok ? await allResponse.json() : result;
|
||||
|
||||
if (!Array.isArray(result)) {
|
||||
throw new Error('Invalid data format received from server');
|
||||
}
|
||||
|
||||
// Build global sorted jenis list (same order as bar chart) for stable color assignment
|
||||
const colorPalette = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899', '#06B6D4', '#F97316'];
|
||||
const allJenis: string[] = [...new Set((allResult as any[]).map(item => item.jenis_pendaftaran as string))].sort() as string[];
|
||||
|
||||
// Process data for pie chart
|
||||
const jenisPendaftaran = [...new Set(result.map(item => item.jenis_pendaftaran))].sort();
|
||||
const jumlahData = jenisPendaftaran.map(jenis => {
|
||||
const item = result.find(d => d.jenis_pendaftaran === jenis);
|
||||
const jenisPendaftaran = [...new Set(result.map(item => item.jenis_pendaftaran))].sort() as string[];
|
||||
const jumlahData = jenisPendaftaran.map((jenis: string) => {
|
||||
const item = result.find((d: any) => d.jenis_pendaftaran === jenis);
|
||||
return item ? item.jumlah : 0;
|
||||
});
|
||||
|
||||
// Assign colors based on global sorted position to match bar chart colors
|
||||
const computedColors = jenisPendaftaran.map((jenis: string) => {
|
||||
const idx = allJenis.indexOf(jenis);
|
||||
return idx >= 0 ? colorPalette[idx % colorPalette.length] : '#999999';
|
||||
});
|
||||
|
||||
setChartColors(computedColors);
|
||||
setSeries(jumlahData);
|
||||
setOptions(prev => ({
|
||||
...prev,
|
||||
labels: jenisPendaftaran,
|
||||
colors: computedColors,
|
||||
}));
|
||||
|
||||
// Store processed data
|
||||
|
||||
@@ -73,15 +73,10 @@ export default function StatistikMahasiswaChart({
|
||||
const seriesIndex = opts.seriesIndex;
|
||||
const dataPointIndex = opts.dataPointIndex;
|
||||
|
||||
// Jika series Total (index 2), tampilkan angka
|
||||
if (seriesIndex === 2) {
|
||||
return val.toString();
|
||||
}
|
||||
|
||||
// Untuk Laki-laki (index 0) dan Perempuan (index 1), hitung persentase
|
||||
// Ambil data total dari series Total (index 2)
|
||||
const totalSeriesData = opts.w.config.series[2]?.data || [];
|
||||
const totalValue = totalSeriesData[dataPointIndex] || 0;
|
||||
// Hitung total dari Laki-laki (index 0) dan Perempuan (index 1)
|
||||
const lakiLakiData = opts.w.config.series[0]?.data || [];
|
||||
const perempuanData = opts.w.config.series[1]?.data || [];
|
||||
const totalValue = (lakiLakiData[dataPointIndex] || 0) + (perempuanData[dataPointIndex] || 0);
|
||||
|
||||
if (totalValue === 0 || val === 0) return '0%';
|
||||
|
||||
@@ -97,7 +92,7 @@ export default function StatistikMahasiswaChart({
|
||||
stroke: {
|
||||
show: true,
|
||||
width: 2,
|
||||
colors: ['transparent', 'transparent', 'transparent'],
|
||||
colors: ['transparent', 'transparent'],
|
||||
curve: 'straight' as const
|
||||
},
|
||||
xaxis: {
|
||||
@@ -153,7 +148,7 @@ export default function StatistikMahasiswaChart({
|
||||
colors: '#000'
|
||||
}
|
||||
},
|
||||
colors: ['#3B82F6', '#EC4899', '#10B981'],
|
||||
colors: ['#3B82F6', '#EC4899'],
|
||||
tooltip: {
|
||||
theme: 'light',
|
||||
shared: true,
|
||||
@@ -161,7 +156,7 @@ export default function StatistikMahasiswaChart({
|
||||
custom: function({ series, seriesIndex, dataPointIndex, w }: any) {
|
||||
const lakiLaki = series[0][dataPointIndex];
|
||||
const perempuan = series[1][dataPointIndex];
|
||||
const total = series[2][dataPointIndex];
|
||||
const total = lakiLaki + perempuan;
|
||||
const tahun = w.globals.labels[dataPointIndex];
|
||||
|
||||
return `
|
||||
@@ -199,7 +194,6 @@ export default function StatistikMahasiswaChart({
|
||||
display: flex;
|
||||
align-items: center;
|
||||
">
|
||||
<div style="width: 8px; height: 8px; background: #10B981; border-radius: 50%; margin-right: 8px;"></div>
|
||||
<span style="font-size: 12px; font-weight: 600; color: #1f2937;">Total</span>
|
||||
<span style="font-size: 13px; font-weight: 700; color: #10B981; margin-left: auto;">${total}</span>
|
||||
</div>
|
||||
@@ -248,18 +242,11 @@ export default function StatistikMahasiswaChart({
|
||||
dataLabels: {
|
||||
...prev.dataLabels,
|
||||
formatter: function (val: number, opts: any) {
|
||||
const seriesIndex = opts.seriesIndex;
|
||||
const dataPointIndex = opts.dataPointIndex;
|
||||
|
||||
// Jika series Total (index 2), tampilkan angka
|
||||
if (seriesIndex === 2) {
|
||||
return val.toString();
|
||||
}
|
||||
|
||||
// Untuk Laki-laki (index 0) dan Perempuan (index 1), hitung persentase
|
||||
// Ambil data total dari series Total (index 2)
|
||||
const totalSeriesData = opts.w.config.series[2]?.data || [];
|
||||
const totalValue = totalSeriesData[dataPointIndex] || 0;
|
||||
const lakiLakiData = opts.w.config.series[0]?.data || [];
|
||||
const perempuanData = opts.w.config.series[1]?.data || [];
|
||||
const totalValue = (lakiLakiData[dataPointIndex] || 0) + (perempuanData[dataPointIndex] || 0);
|
||||
|
||||
if (totalValue === 0 || val === 0) return '0%';
|
||||
|
||||
@@ -320,13 +307,9 @@ export default function StatistikMahasiswaChart({
|
||||
custom: function({ series, seriesIndex, dataPointIndex, w }: any) {
|
||||
const lakiLaki = series[0][dataPointIndex];
|
||||
const perempuan = series[1][dataPointIndex];
|
||||
const total = series[2][dataPointIndex];
|
||||
const total = lakiLaki + perempuan;
|
||||
const tahun = w.globals.labels[dataPointIndex];
|
||||
|
||||
const bgColor = currentTheme === 'dark' ? '#1e293b' : 'white';
|
||||
const textColor = currentTheme === 'dark' ? '#fff' : '#000';
|
||||
const borderColor = currentTheme === 'dark' ? '#475569' : '#ccc';
|
||||
|
||||
const isDark = currentTheme === 'dark';
|
||||
|
||||
return `
|
||||
@@ -364,7 +347,6 @@ export default function StatistikMahasiswaChart({
|
||||
display: flex;
|
||||
align-items: center;
|
||||
">
|
||||
<div style="width: 8px; height: 8px; background: #10B981; border-radius: 50%; margin-right: 8px;"></div>
|
||||
<span style="font-size: 12px; font-weight: 600; color: ${isDark ? '#f1f5f9' : '#1f2937'};">Total</span>
|
||||
<span style="font-size: 13px; font-weight: 700; color: #10B981; margin-left: auto;">${total}</span>
|
||||
</div>
|
||||
@@ -404,11 +386,6 @@ export default function StatistikMahasiswaChart({
|
||||
name: 'Perempuan',
|
||||
type: 'bar' as const,
|
||||
data: statistikData.map(item => item.wanita)
|
||||
},
|
||||
{
|
||||
name: 'Total',
|
||||
type: 'bar' as const,
|
||||
data: statistikData.map(item => item.total_mahasiswa)
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ export default function StatusMahasiswaFilterPieChart({ selectedYear, selectedSt
|
||||
background: theme === 'dark' ? '#0F172B' : '#fff',
|
||||
},
|
||||
labels: ['Laki-laki', 'Perempuan'],
|
||||
colors: ['#3B82F6', '#EC4899'],
|
||||
colors: ['#008FFB', '#EC4899'],
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
fontSize: '14px',
|
||||
|
||||
@@ -65,9 +65,18 @@ export default function StatusMahasiswaPieChartPerangkatan({ selectedYear }: Pro
|
||||
fetchData();
|
||||
}, [selectedYear]);
|
||||
|
||||
// Color mapping consistent with StatusMahasiswaChart bar chart
|
||||
const STATUS_COLOR_MAP: { [key: string]: string } = {
|
||||
'Aktif': '#008FFB',
|
||||
'Lulus': '#00E396',
|
||||
'Cuti': '#FEB019',
|
||||
'Non Aktif': '#EF4444',
|
||||
};
|
||||
|
||||
// Prepare data for pie chart
|
||||
const series = data.map(item => item.jumlah);
|
||||
const labels = data.map(item => item.status_kuliah);
|
||||
const colors = data.map(item => STATUS_COLOR_MAP[item.status_kuliah] || '#775DD0');
|
||||
|
||||
const chartOptions: ApexOptions = {
|
||||
chart: {
|
||||
@@ -103,13 +112,7 @@ export default function StatusMahasiswaPieChartPerangkatan({ selectedYear }: Pro
|
||||
colors: theme === 'dark' ? '#fff' : '#000'
|
||||
}
|
||||
},
|
||||
colors: [
|
||||
'#00E396', // Aktif - Green
|
||||
'#008FFB', // Lulus - Blue
|
||||
'#FEB019', // Cuti - Orange
|
||||
'#FF4560', // Non-Aktif - Red
|
||||
'#775DD0', // Lainnya - Purple
|
||||
],
|
||||
colors: colors,
|
||||
tooltip: {
|
||||
theme: theme === 'dark' ? 'dark' : 'light',
|
||||
y: {
|
||||
|
||||
Reference in New Issue
Block a user