mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 12:25:22 +02:00
Restore ForecastView UI, Fix default YTD logic, and Refine Seasonality (Specific > Global fallback)
This commit is contained in:
@@ -147,6 +147,7 @@ const ForecastRow: React.FC<{
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
data,
|
||||
filters,
|
||||
@@ -164,7 +165,6 @@ const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
const [displayCount, setDisplayCount] = useState(50);
|
||||
|
||||
const lastDataMonthIdx = useMemo(() => {
|
||||
// Find the last month with actual data
|
||||
let maxDataMonth = 0;
|
||||
for (let i = MONTH_ORDER.length - 1; i >= 0; i--) {
|
||||
if (data.some(p => (p.monthlyData?.[MONTH_ORDER[i]]?.actualUnits || 0) > 0)) {
|
||||
@@ -172,12 +172,7 @@ const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clamp to current month to ensure we don't show future months in "Period" view
|
||||
// This fixes the issue where "Period" shows Annual forecast if there is any stray future data
|
||||
const currentMonth = new Date().getMonth(); // 0 for Jan
|
||||
// We assume the data is for the current year if we are in FC 26 view.
|
||||
// If we want to support past years, we'd need to check the year context, but for now this fixes the user's immediate issue.
|
||||
return Math.min(maxDataMonth, currentMonth);
|
||||
}, [data]);
|
||||
|
||||
@@ -185,8 +180,10 @@ const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
if (filters.month && filters.month.length > 0) {
|
||||
return filters.month.map(m => m.split('-')[0]);
|
||||
}
|
||||
return MONTH_ORDER.slice(0, lastDataMonthIdx + 1);
|
||||
}, [filters.month, lastDataMonthIdx]);
|
||||
// Default to YTD: Current month and all before it this year
|
||||
const currentMonthIdx = new Date().getMonth();
|
||||
return MONTH_ORDER.slice(0, currentMonthIdx + 1);
|
||||
}, [filters.month]);
|
||||
|
||||
const baseFilteredData = useMemo(() => {
|
||||
let result = data;
|
||||
@@ -198,7 +195,6 @@ const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
|
||||
const globalSummary = useMemo(() => {
|
||||
return baseFilteredData.reduce((acc, curr) => {
|
||||
// Calculate Forecast Period (YTD) for this item
|
||||
const itemPeriodForecast = activeMonths.reduce((sum, month) => {
|
||||
return sum + (curr.monthlyData?.[month]?.forecastUnits || 0);
|
||||
}, 0);
|
||||
@@ -260,26 +256,20 @@ const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6 animate-fade-in p-6 h-full overflow-hidden">
|
||||
{/* Top Section: Metrics & Graph */}
|
||||
<div className="flex flex-col xl:flex-row gap-6 h-[400px] shrink-0">
|
||||
{/* Metrics Cards */}
|
||||
<div className="flex flex-col gap-4 min-w-[300px] xl:w-[25%]">
|
||||
{/* Annual Forecast */}
|
||||
<div className="bg-slate-900 border border-white/5 p-4 rounded-xl shadow-lg flex-1 flex flex-col justify-center">
|
||||
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest mb-1">Annual Forecast Total</span>
|
||||
<div className="text-2xl font-black text-white">{(globalSummary.annualForecast || 0).toLocaleString('de-DE')} <span className="text-sm font-bold text-slate-500">Units</span></div>
|
||||
</div>
|
||||
{/* Period Forecast */}
|
||||
<div className="bg-slate-900 border border-white/5 p-4 rounded-xl shadow-lg flex-1 flex flex-col justify-center">
|
||||
<span className="text-[10px] font-black text-indigo-400 uppercase tracking-widest mb-1">Total Forecast (Period)</span>
|
||||
<div className="text-2xl font-black text-white">{(globalSummary.forecastUnits || 0).toLocaleString('de-DE')} <span className="text-sm font-bold text-slate-500">Units</span></div>
|
||||
</div>
|
||||
{/* Actual Sales */}
|
||||
<div className="bg-slate-900 border border-white/5 p-4 rounded-xl shadow-lg flex-1 flex flex-col justify-center">
|
||||
<span className="text-[10px] font-black text-emerald-400 uppercase tracking-widest mb-1">Total Actual Sales (Period)</span>
|
||||
<div className="text-2xl font-black text-emerald-400">{(globalSummary.actualUnits || 0).toLocaleString('de-DE')} <span className="text-sm font-bold text-emerald-600/70">Units</span></div>
|
||||
</div>
|
||||
{/* Fulfillment */}
|
||||
<div className="flex gap-4 flex-1">
|
||||
<div className="bg-slate-900 border border-white/5 p-4 rounded-xl shadow-lg flex-1 flex flex-col justify-center">
|
||||
<span className="text-[10px] font-black text-blue-400 uppercase tracking-widest mb-1">Fulfillment (Period)</span>
|
||||
@@ -295,7 +285,6 @@ const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Graph */}
|
||||
<div className="flex-1 bg-slate-900 border border-white/5 rounded-xl shadow-lg p-6 flex flex-col">
|
||||
<h3 className="flex items-center gap-2 text-sm font-bold text-white mb-6">
|
||||
<TrendingIcon /> Monthly Evolution: Forecast vs Actual
|
||||
@@ -329,11 +318,10 @@ const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Section: Table */}
|
||||
<div className="bg-slate-900 border border-white/10 rounded-2xl overflow-hidden shadow-2xl flex-1 flex flex-col min-h-0">
|
||||
<div className="p-4 border-b border-white/5 flex flex-col md:flex-row justify-between gap-4 bg-slate-800/20 shrink-0">
|
||||
<h3 className="text-lg font-bold text-white uppercase tracking-tight">
|
||||
Product Performance Comparison <span className="text-xs text-slate-500 font-normal normal-case ml-2">(v2.2 Updated)</span>
|
||||
Product Performance Comparison <span className="text-xs text-slate-500 font-normal normal-case ml-2">(v2.4 Final)</span>
|
||||
</h3>
|
||||
<div className="flex items-center gap-4">
|
||||
{top50Ranking && (top50Ranking.eu.size > 0 || top50Ranking.uk.size > 0) && (
|
||||
@@ -374,7 +362,7 @@ const ForecastView: React.FC<ForecastViewProps> = ({
|
||||
<ForecastRow
|
||||
key={item.asin}
|
||||
item={item}
|
||||
activeMonths={filters.month.length > 0 ? filters.month : MONTH_ORDER}
|
||||
activeMonths={activeMonths}
|
||||
top50Ranking={top50Ranking}
|
||||
top50Mode={top50Mode}
|
||||
stockMap={stockMap}
|
||||
|
||||
Reference in New Issue
Block a user