mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 11:55:22 +02:00
92 lines
4.2 KiB
TypeScript
92 lines
4.2 KiB
TypeScript
import React, { useState, useMemo } from 'react';
|
|||
|
|
import { SalesRecord } from '../types';
|
||
|
|
import { calculateItemMovers, getUniqueValues, generateItemMoversCSV } from '../services/dataProcessor'; // Import generateItemMoversCSV
|
||
|
|
import ItemGrowthTable from './ItemGrowthTable';
|
||
|
|
import { ExpandableCard } from './Dashboard'; // Re-use ExpandableCard from Dashboard
|
||
|
|
|
||
|
|
interface TopMoversPageProps {
|
||
|
|
filteredData: SalesRecord[]; // Data already filtered by global customer, year, month, etc.
|
||
|
|
}
|
||
|
|
|
||
|
|
const TopMoversPage: React.FC<TopMoversPageProps> = ({ filteredData }) => {
|
||
|
|
// Local state for the specific comparison year, initially null for auto-selection
|
||
|
|
const [selectedComparisonYear, setSelectedComparisonYear] = useState<string | null>(null);
|
||
|
|
|
||
|
|
// Derive available years from the *currently filtered data* for the comparison year dropdown
|
||
|
|
const availableYearsForComparisonDropdown = useMemo(() => {
|
||
|
|
const yearsInFilteredData = getUniqueValues(filteredData, 'year');
|
||
|
|
// Sort descending for the dropdown
|
||
|
|
return yearsInFilteredData.sort((a,b) => parseInt(b) - parseInt(a));
|
||
|
|
}, [filteredData]);
|
||
|
|
|
||
|
|
// Derive top/bottom movers based on selections
|
||
|
|
const { topMovers, bottomMovers, comparisonPeriods } = useMemo(() => {
|
||
|
|
const comparisonYearNum = selectedComparisonYear ? parseInt(selectedComparisonYear) : null;
|
||
|
|
// Pass the globally filtered data. The global filter bar now handles customer/line/sku/etc filtering.
|
||
|
|
// We pass null for the local customer override as it is no longer used.
|
||
|
|
return calculateItemMovers(filteredData, null, comparisonYearNum);
|
||
|
|
}, [filteredData, selectedComparisonYear]);
|
||
|
|
|
||
|
|
// Handlers for export
|
||
|
|
const handleExportGainers = () => {
|
||
|
|
generateItemMoversCSV(topMovers, comparisonPeriods, 'Gainers');
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleExportLosers = () => {
|
||
|
|
generateItemMoversCSV(bottomMovers, comparisonPeriods, 'Losers');
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="p-6 space-y-6 max-w-7xl mx-auto animate-fade-in pb-24">
|
||
|
|
<div className="flex flex-wrap justify-between items-center gap-4 mb-6">
|
||
|
|
<h2 className="text-2xl font-bold text-white">Top Item Movers</h2>
|
||
|
|
|
||
|
|
<div className="bg-slate-900 border border-border rounded-xl px-4 py-2 flex items-center gap-3">
|
||
|
|
<label className="text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap">Comparison Year</label>
|
||
|
|
<select
|
||
|
|
value={selectedComparisonYear || ''}
|
||
|
|
onChange={(e) => setSelectedComparisonYear(e.target.value || null)}
|
||
|
|
className="bg-surface border border-border hover:border-slate-600 text-sm rounded-lg py-1.5 px-3 focus:outline-none focus:ring-2 focus:ring-primary/50 transition-colors text-white"
|
||
|
|
>
|
||
|
|
<option value="">Auto (Latest 2 Years)</option>
|
||
|
|
{availableYearsForComparisonDropdown.map(year => (
|
||
|
|
<option key={year} value={year}>{year}</option>
|
||
|
|
))}
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Top 20 Gainers Table */}
|
||
|
|
<ExpandableCard
|
||
|
|
title={`Top 20 Gainers (${comparisonPeriods.current} vs ${comparisonPeriods.previous})`}
|
||
|
|
className="h-[500px]"
|
||
|
|
onExport={handleExportGainers} // Pass export handler
|
||
|
|
exportFileName={`Top_20_Gainers_${comparisonPeriods.current}_vs_${comparisonPeriods.previous}`}
|
||
|
|
>
|
||
|
|
<ItemGrowthTable
|
||
|
|
title={`Top 20 Gainers (${comparisonPeriods.current} vs ${comparisonPeriods.previous})`}
|
||
|
|
data={topMovers}
|
||
|
|
type="growth"
|
||
|
|
periods={comparisonPeriods}
|
||
|
|
/>
|
||
|
|
</ExpandableCard>
|
||
|
|
|
||
|
|
{/* Top 20 Losers Table */}
|
||
|
|
<ExpandableCard
|
||
|
|
title={`Top 20 Losers (${comparisonPeriods.current} vs ${comparisonPeriods.previous})`}
|
||
|
|
className="h-[500px]"
|
||
|
|
onExport={handleExportLosers} // Pass export handler
|
||
|
|
exportFileName={`Top_20_Losers_${comparisonPeriods.current}_vs_${comparisonPeriods.previous}`}
|
||
|
|
>
|
||
|
|
<ItemGrowthTable
|
||
|
|
title={`Top 20 Losers (${comparisonPeriods.current} vs ${comparisonPeriods.previous})`}
|
||
|
|
data={bottomMovers}
|
||
|
|
type="decline"
|
||
|
|
periods={comparisonPeriods}
|
||
|
|
/>
|
||
|
|
</ExpandableCard>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default TopMoversPage;
|