/**
* EqualizationDataPanel Component
* Right panel showing step-contextual data table for desktop view
*/
'use client';
import React, { useMemo } from 'react';
import { useTranslations, useLocale } from 'next-intl';
import { useVisualizerStore } from '@/hooks/useVisualizerStore';
import { useEqualizationData } from '@/contexts/EqualizationDataContext';
import { isTerritory } from '@/lib/visualizer/equalization/equalizationData';
export function EqualizationDataPanel() {
const tProvinces = useTranslations('provinces');
const locale = useLocale() as 'en' | 'fr';
const { equalizationStep, selectedProvince, setSelectedProvince } = useVisualizerStore();
const { data, formatPaymentAmount, formatPerCapitaAmount } = useEqualizationData();
// Get step-contextual data view
const tableData = useMemo(() => {
const allData = Object.values(data);
const provinces = allData.filter(d => !isTerritory(d.provinceCode));
const territories = allData.filter(d => isTerritory(d.provinceCode));
switch (equalizationStep) {
case 1:
case 2:
// Overview: Show all regions with status
return {
title: locale === 'en' ? 'Overview' : 'Aperçu',
columns: [
{ key: 'region', label: locale === 'en' ? 'Region' : 'Région', align: 'left' as const },
{ key: 'status', label: locale === 'en' ? 'Status' : 'Statut', align: 'right' as const },
{ key: 'payment', label: locale === 'en' ? 'Transfer' : 'Transfert', align: 'right' as const },
],
rows: [
...provinces.map(p => ({
code: p.provinceCode,
region: tProvinces(p.provinceCode),
status: p.isReceiving
? (locale === 'en' ? 'Receiving' : 'Bénéficiaire')
: (locale === 'en' ? 'Above std.' : 'Au-dessus'),
statusColor: p.isReceiving ? 'text-emerald-400' : 'text-gray-400',
payment: p.isReceiving ? formatPaymentAmount(p.paymentMillions, locale) : '—',
})),
...territories.map(p => ({
code: p.provinceCode,
region: tProvinces(p.provinceCode),
status: 'TFF',
statusColor: 'text-purple-400',
payment: formatPaymentAmount(p.paymentMillions, locale),
})),
],
};
case 3:
case 4:
case 5:
// Fiscal capacity comparison
return {
title: locale === 'en' ? 'Fiscal Capacity' : 'Capacité fiscale',
columns: [
{ key: 'region', label: locale === 'en' ? 'Region' : 'Région', align: 'left' as const },
{ key: 'capacity', label: locale === 'en' ? 'Index' : 'Indice', align: 'right' as const },
{ key: 'gap', label: locale === 'en' ? 'vs Avg' : 'vs Moy.', align: 'right' as const },
],
rows: [
...provinces
.sort((a, b) => b.fiscalCapacityIndex - a.fiscalCapacityIndex)
.map(p => ({
code: p.provinceCode,
region: tProvinces(p.provinceCode),
capacity: `${p.fiscalCapacityIndex}%`,
capacityColor: p.fiscalCapacityIndex > 105 ? 'text-blue-400' :
p.fiscalCapacityIndex >= 95 ? 'text-gray-400' : 'text-amber-400',
gap: p.fiscalCapacityIndex >= 100
? `+${p.fiscalCapacityIndex - 100}%`
: `${p.fiscalCapacityIndex - 100}%`,
gapColor: p.fiscalCapacityIndex >= 100 ? 'text-blue-400' : 'text-amber-400',
})),
...territories.map(p => ({
code: p.provinceCode,
region: tProvinces(p.provinceCode),
capacity: 'N/A',
capacityColor: 'text-purple-400',
gap: 'TFF',
gapColor: 'text-purple-400',
})),
],
};
case 6:
case 7:
// Payment results
return {
title: locale === 'en' ? 'Payments' : 'Paiements',
columns: [
{ key: 'region', label: locale === 'en' ? 'Region' : 'Région', align: 'left' as const },
{ key: 'payment', label: locale === 'en' ? 'Amount' : 'Montant', align: 'right' as const },
{ key: 'perCapita', label: locale === 'en' ? 'Per Cap.' : 'Par hab.', align: 'right' as const },
],
rows: [
...provinces
.sort((a, b) => b.paymentMillions - a.paymentMillions)
.map(p => ({
code: p.provinceCode,
region: tProvinces(p.provinceCode),
payment: p.paymentMillions > 0 ? formatPaymentAmount(p.paymentMillions, locale) : '—',
paymentColor: p.paymentMillions > 0 ? 'text-emerald-400' : 'text-gray-500',
perCapita: p.perCapitaPayment > 0 ? formatPerCapitaAmount(p.perCapitaPayment, locale) : '—',
})),
...territories.map(p => ({
code: p.provinceCode,
region: tProvinces(p.provinceCode),
payment: formatPaymentAmount(p.paymentMillions, locale),
paymentColor: 'text-purple-400',
perCapita: formatPerCapitaAmount(p.perCapitaPayment, locale),
})),
],
};
default:
return null;
}
}, [equalizationStep, data, locale, tProvinces, formatPaymentAmount, formatPerCapitaAmount]);
if (!tableData) return null;
return (
<div className="flex flex-col h-full">
{/* Table Title */}
<h3 className="text-sm font-semibold text-text-primary mb-3">
{tableData.title}
</h3>
{/* Data Table */}
<div className="flex-1 overflow-auto -mx-4 px-4">
<table className="w-full text-sm">
<thead className="bg-bg-elevated sticky top-0">
<tr>
{tableData.columns.map(col => (
<th
key={col.key}
className={`px-2 py-2 font-medium text-text-secondary text-${col.align}`}
>
{col.label}
</th>
))}
</tr>
</thead>
<tbody className="divide-y divide-border-subtle">
{tableData.rows.map((row) => (
<tr
key={row.code}
onClick={() => setSelectedProvince(selectedProvince === row.code ? null : row.code, 'table')}
className={`
cursor-pointer transition-colors
${selectedProvince === row.code ? 'bg-accent-red/10' : 'hover:bg-bg-elevated'}
`}
>
<td className="px-2 py-2 font-medium text-text-primary">
{row.region}
</td>
{tableData.columns.slice(1).map(col => (
<td
key={col.key}
className={`px-2 py-2 text-right ${
(row as Record<string, string>)[`${col.key}Color`] || 'text-text-secondary'
}`}
>
{(row as Record<string, string>)[col.key]}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
{/* Summary */}
{equalizationStep >= 6 && (
<div className="mt-3 pt-3 border-t border-border-subtle">
<div className="flex justify-between text-sm">
<span className="text-text-secondary">
{locale === 'en' ? 'Total Equalization' : 'Péréquation totale'}
</span>
<span className="font-semibold text-emerald-400">
{formatPaymentAmount(
Object.values(data)
.filter(d => !isTerritory(d.provinceCode) && d.isReceiving)
.reduce((sum, d) => sum + d.paymentMillions, 0),
locale
)}
</span>
</div>
<div className="flex justify-between text-sm mt-1">
<span className="text-text-secondary">
{locale === 'en' ? 'Total TFF' : 'FFT total'}
</span>
<span className="font-semibold text-purple-400">
{formatPaymentAmount(
Object.values(data)
.filter(d => isTerritory(d.provinceCode))
.reduce((sum, d) => sum + d.paymentMillions, 0),
locale
)}
</span>
</div>
</div>
)}
</div>
);
}