Files
CrazeAnalytix/components/TopMoversPage.tsx
T
Christian 9ba63ab8f8 feat: Initialize Craze Analytix project structure
Sets up the project with Vite, React, Tailwind CSS, Gemini AI integration, and necessary dependencies for data analysis. Includes initial configuration for TypeScript, Tailwind, and project metadata.
2025-12-11 11:25:26 +01:00

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;