Fix: improve Vendor stock parsing robustness and ASIN extraction for B0D14YBNWB

This commit is contained in:
Christian Vidal Wolf
2026-04-27 11:48:47 +02:00
parent e7f48af099
commit 490cb4a96b
4 changed files with 116 additions and 58 deletions
+59 -48
View File
@@ -1,4 +1,5 @@
import React, { useMemo, useState, useEffect, useCallback, useRef } from 'react';
import ReactDOM from 'react-dom';
import * as XLSX from 'xlsx';
import { CombinedKPIs, ColumnFilterCondition, SalesRecord } from '../types';
import { pivotWeeklySalesData, WeeklyPivotRow, PAN_EU_COUNTRIES, checkNumericConditions, filterData } from '../services/dataProcessor';
@@ -782,12 +783,8 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
</div>
</th>
{weeks.map((week, idx) => {
const [yearStr, weekNum] = week.split('-');
const prevYearWeek = `${parseInt(yearStr) - 1}-${weekNum}`;
const prevWeekTotals = allWeekTotals[weeks[idx + 1]];
const yoyTotals = allWeekTotals[prevYearWeek];
const cur = weekTotals[week];
const isHovered = hoveredTotalWeek === week;
return (
<th key={week} className="p-3 text-sm font-black text-white text-center border-r border-white/10"
@@ -825,50 +822,6 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
</div>
</div>
{isHovered && tooltipPos && (
<div className="pointer-events-none fixed z-[9999] w-64 bg-slate-900 border border-white/20 rounded-xl shadow-2xl p-3 text-left"
style={{ left: tooltipPos.x + 16, top: tooltipPos.y - 16, transform: 'translateY(-100%)' }}
>
<div className="text-[10px] font-black text-white/50 uppercase tracking-widest mb-2">{week}</div>
{/* Semana anterior */}
<div className="mb-2">
<div className="text-[9px] font-black text-indigo-300 uppercase tracking-widest mb-1">Semana anterior ({weeks[idx + 1] || '—'})</div>
{prevWeekTotals ? (
<div className="grid grid-cols-2 gap-x-3 gap-y-0.5 text-[11px]">
<span className="text-white/60">Units</span>
<span className="text-white font-bold text-right">{prevWeekTotals.units.toLocaleString('de-DE')} {renderGrowth(cur?.units || 0, prevWeekTotals.units)}</span>
<span className="text-white/60">Revenue</span>
<span className="text-white font-bold text-right">{prevWeekTotals.revenue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {renderGrowth(cur?.revenue || 0, prevWeekTotals.revenue)}</span>
<span className="text-white/60">Ads Spend</span>
<span className="text-rose-400 font-bold text-right">{prevWeekTotals.spend.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {renderGrowth(cur?.spend || 0, prevWeekTotals.spend)}</span>
<span className="text-white/60">GV</span>
<span className="text-teal-400 font-bold text-right">{prevWeekTotals.gv.toLocaleString('de-DE')} {renderGrowth(cur?.gv || 0, prevWeekTotals.gv)}</span>
</div>
) : (
<span className="text-white/30 text-[11px]">Sin datos</span>
)}
</div>
<div className="border-t border-white/10 pt-2">
<div className="text-[9px] font-black text-amber-300 uppercase tracking-widest mb-1">Misma semana año anterior ({prevYearWeek})</div>
{yoyTotals && (yoyTotals.units > 0 || yoyTotals.revenue > 0) ? (
<div className="grid grid-cols-2 gap-x-3 gap-y-0.5 text-[11px]">
<span className="text-white/60">Units</span>
<span className="text-white font-bold text-right">{yoyTotals.units.toLocaleString('de-DE')} {renderGrowth(cur?.units || 0, yoyTotals.units)}</span>
<span className="text-white/60">Revenue</span>
<span className="text-white font-bold text-right">{yoyTotals.revenue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {renderGrowth(cur?.revenue || 0, yoyTotals.revenue)}</span>
<span className="text-white/60">Ads Spend</span>
<span className="text-rose-400 font-bold text-right">{yoyTotals.spend.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {renderGrowth(cur?.spend || 0, yoyTotals.spend)}</span>
<span className="text-white/60">GV</span>
<span className="text-teal-400 font-bold text-right">{yoyTotals.gv.toLocaleString('de-DE')} {renderGrowth(cur?.revenue || 0, yoyTotals.gv)}</span>
</div>
) : (
<span className="text-white/30 text-[11px]">Sin datos del año anterior</span>
)}
</div>
</div>
)}
</th>
);
})}
@@ -928,6 +881,64 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
</div>
</div>
);
const tooltipPortal = hoveredTotalWeek && tooltipPos ? (() => {
const week = hoveredTotalWeek;
const idx = weeks.indexOf(week);
const [yearStr, weekNum] = week.split('-');
const prevYearWeek = `${parseInt(yearStr) - 1}-${weekNum}`;
const cur = weekTotals[week];
const prevWeekTotals = allWeekTotals[weeks[idx + 1]];
const yoyTotals = allWeekTotals[prevYearWeek];
return ReactDOM.createPortal(
<div
className="pointer-events-none fixed w-64 bg-slate-900 border border-white/20 rounded-xl shadow-2xl p-3 text-left"
style={{ left: tooltipPos.x + 16, top: tooltipPos.y - 16, transform: 'translateY(-100%)', zIndex: 999999 }}
>
<div className="text-[10px] font-black text-white/50 uppercase tracking-widest mb-2">{week}</div>
<div className="mb-2">
<div className="text-[9px] font-black text-indigo-300 uppercase tracking-widest mb-1">Semana anterior ({weeks[idx + 1] || '—'})</div>
{prevWeekTotals ? (
<div className="grid grid-cols-2 gap-x-3 gap-y-0.5 text-[11px]">
<span className="text-white/60">Units</span>
<span className="text-white font-bold text-right">{prevWeekTotals.units.toLocaleString('de-DE')} {renderGrowth(cur?.units || 0, prevWeekTotals.units)}</span>
<span className="text-white/60">Revenue</span>
<span className="text-white font-bold text-right">{prevWeekTotals.revenue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {renderGrowth(cur?.revenue || 0, prevWeekTotals.revenue)}</span>
<span className="text-white/60">Ads Spend</span>
<span className="text-rose-400 font-bold text-right">{prevWeekTotals.spend.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {renderGrowth(cur?.spend || 0, prevWeekTotals.spend)}</span>
<span className="text-white/60">GV</span>
<span className="text-teal-400 font-bold text-right">{prevWeekTotals.gv.toLocaleString('de-DE')} {renderGrowth(cur?.gv || 0, prevWeekTotals.gv)}</span>
</div>
) : (
<span className="text-white/30 text-[11px]">Sin datos</span>
)}
</div>
<div className="border-t border-white/10 pt-2">
<div className="text-[9px] font-black text-amber-300 uppercase tracking-widest mb-1">Misma semana año anterior ({prevYearWeek})</div>
{yoyTotals && (yoyTotals.units > 0 || yoyTotals.revenue > 0) ? (
<div className="grid grid-cols-2 gap-x-3 gap-y-0.5 text-[11px]">
<span className="text-white/60">Units</span>
<span className="text-white font-bold text-right">{yoyTotals.units.toLocaleString('de-DE')} {renderGrowth(cur?.units || 0, yoyTotals.units)}</span>
<span className="text-white/60">Revenue</span>
<span className="text-white font-bold text-right">{yoyTotals.revenue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {renderGrowth(cur?.revenue || 0, yoyTotals.revenue)}</span>
<span className="text-white/60">Ads Spend</span>
<span className="text-rose-400 font-bold text-right">{yoyTotals.spend.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {renderGrowth(cur?.spend || 0, yoyTotals.spend)}</span>
<span className="text-white/60">GV</span>
<span className="text-teal-400 font-bold text-right">{yoyTotals.gv.toLocaleString('de-DE')} {renderGrowth(cur?.gv || 0, yoyTotals.gv)}</span>
</div>
) : (
<span className="text-white/30 text-[11px]">Sin datos del año anterior</span>
)}
</div>
</div>,
document.body
);
})() : null;
return <>{mainContent}{tooltipPortal}</>;
};
export default WeeklyGrid;