ayo commit lagi

This commit is contained in:
Randa Firman Putra
2026-02-22 00:21:37 +07:00
parent 3797daa557
commit 211fd9c955
4 changed files with 49 additions and 49 deletions

View File

@@ -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

View File

@@ -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)
}
];

View File

@@ -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',

View File

@@ -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: {