diff --git a/App.tsx b/App.tsx index 0e9fc12..731f517 100644 --- a/App.tsx +++ b/App.tsx @@ -251,7 +251,7 @@ const App: React.FC = () => { const handleExperimentsFetch = useCallback(async () => { try { - const allAsins = Array.from(new Set(rawData.map(r => r.asin.toUpperCase()))); + const allAsins: string[] = Array.from(new Set(rawData.map(r => String(r.asin).toUpperCase()))); const expMap = await getActiveExperimentsForASINs(allAsins); setExperimentMap(expMap); console.log('[App] Loaded experiments for', expMap.size, 'ASINs'); diff --git a/components/ExperimentBadge.tsx b/components/ExperimentBadge.tsx index ee95b70..6a5c858 100644 --- a/components/ExperimentBadge.tsx +++ b/components/ExperimentBadge.tsx @@ -7,25 +7,24 @@ interface ExperimentBadgeProps { onClick?: (experimentId: string) => void; } +const getStatusBadge = (status: ExperimentStatus) => { + switch (status) { + case 'active': return '🟢'; + case 'planned': return '🟡'; + case 'completed': return '⚪'; + case 'paused': return '⏸️'; + } +}; + export const ExperimentBadge: React.FC = ({ experiments, onClick }) => { if (!experiments || experiments.length === 0) return null; const activeExp = experiments.find(e => e.status === 'active'); const plannedExp = experiments.find(e => e.status === 'planned'); - const hasPast = experiments.some(e => e.status === 'completed' || e.status === 'paused'); // Priority: active > planned > past const displayExp = activeExp || plannedExp || experiments[0]; - const getStatusBadge = (status: ExperimentStatus) => { - switch (status) { - case 'active': return '🟢'; - case 'planned': return '🟡'; - case 'completed': return '⚪'; - case 'paused': return '⏸️'; - } - }; - const daysText = displayExp.days_remaining !== undefined ? displayExp.days_remaining > 0 ? `${displayExp.days_remaining}d left` diff --git a/components/WeeklyGrid.tsx b/components/WeeklyGrid.tsx index deaa6ff..a0670c8 100644 --- a/components/WeeklyGrid.tsx +++ b/components/WeeklyGrid.tsx @@ -159,7 +159,9 @@ const WeeklyRow: React.FC<{ velocityMap?: Map; buyBoxLostMap?: Map }>; primaryMetric: 'units' | 'revenue'; -}> = React.memo(({ row, weeks, onDrillDown, stockMap, top50Ranking, top50Mode, sortConfig, renderGrowth, customerFilters, vendorStockMap, velocityMap, buyBoxLostMap, primaryMetric }) => { + experimentMap?: Map; + onOpenExperiment?: (experimentId: string) => void; +}> = React.memo(({ row, weeks, onDrillDown, stockMap, top50Ranking, top50Mode, sortConfig, renderGrowth, customerFilters, vendorStockMap, velocityMap, buyBoxLostMap, primaryMetric, experimentMap, onOpenExperiment }) => { const ranks: { rank: number; label: string; theme: 'amber' | 'blue' | 'indigo' }[] = []; const asin = row.asin.trim().toUpperCase(); @@ -346,7 +348,9 @@ const WeeklyGrid: React.FC = ({ customerFilters, top50Mode, velocityMap, - buyBoxLostMap + buyBoxLostMap, + experimentMap, + onOpenExperiment }) => { // Pivot data - memoized const { rows, weeks: allWeeks } = useMemo(() => pivotWeeklySalesData(data), [data]); @@ -1030,6 +1034,8 @@ const WeeklyGrid: React.FC = ({ velocityMap={velocityMap} buyBoxLostMap={buyBoxLostMap} primaryMetric={primaryMetric} + experimentMap={experimentMap} + onOpenExperiment={onOpenExperiment} /> ))} {displayCount < sortedRows.length && ( diff --git a/services/experiments.ts b/services/experiments.ts index 41ca479..1a5a3fb 100644 --- a/services/experiments.ts +++ b/services/experiments.ts @@ -163,16 +163,16 @@ export const getActiveExperimentsForASINs = async ( if (error) throw error; const map = new Map(); - + for (const asin of asins) { const experiments = (data || []) - .filter((exp: any) => exp.asins?.includes(asin)) + .filter((exp: any) => Array.isArray(exp.asins) && exp.asins.includes(asin)) .map((exp: any) => { const endDate = exp.end_date ? new Date(exp.end_date) : null; const daysRemaining = endDate ? Math.ceil((endDate.getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24)) : undefined; - + return { asin, experiment_id: exp.id, @@ -184,7 +184,7 @@ export const getActiveExperimentsForASINs = async ( days_remaining: daysRemaining, } as ActiveExperiment; }); - + if (experiments.length > 0) { map.set(asin, experiments); } diff --git a/services/supabase.ts b/services/supabase.ts index 78dce18..1c22e42 100644 --- a/services/supabase.ts +++ b/services/supabase.ts @@ -2,6 +2,8 @@ import { createClient, SupabaseClient } from '@supabase/supabase-js'; import { VendorDailyRow } from '../types'; +export type { VendorDailyRow }; + const supabaseUrl = process.env.SUPABASE_URL || ''; const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || '';