mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 12:55:23 +02:00
fix: remove rowStatuses prop from ProductDescriptions to fix app crash
The rowStatuses prop was merged from feature branch but is incompatible with main. Removed it and restored original tbody structure while keeping the Present/Missing filter fix. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
co-authored by
Qwen-Coder
parent
0d47f5be33
commit
71a4897f28
+29
-30
@@ -81,22 +81,22 @@ export default function App() {
|
||||
const articleNo = String(row[articleNoIdx]);
|
||||
const synced = syncedData[articleNo];
|
||||
const finalRow = synced ? synced.data : row;
|
||||
|
||||
|
||||
// Sync status_check
|
||||
if (synced && synced.status === 'pending') {
|
||||
setRowStatuses(prev => ({ ...prev, [articleNo]: 'pending' }));
|
||||
}
|
||||
|
||||
|
||||
// Format numeric/price fields to 2 decimal places
|
||||
return finalRow.map((val, idx) => {
|
||||
if (val === undefined || val === null || val === '') return val;
|
||||
const header = (rawHeaders[idx] || '').toLowerCase();
|
||||
|
||||
|
||||
// Skip Article No, Barcodes, and other code-like fields
|
||||
// But allow if it's a weight/measure column (e.g. Article NW (kg))
|
||||
if ((header.includes('id') || header.includes('no') || header.includes('code') ||
|
||||
header.includes('art.') || header.includes('barcode') || header.includes('article')) &&
|
||||
!(header.includes('nw') || header.includes('gw') || header.includes('weight') || header.includes('kg'))) {
|
||||
if ((header.includes('id') || header.includes('no') || header.includes('code') ||
|
||||
header.includes('art.') || header.includes('barcode') || header.includes('article')) &&
|
||||
!(header.includes('nw') || header.includes('gw') || header.includes('weight') || header.includes('kg'))) {
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ export default function App() {
|
||||
if (typeof val === 'number') {
|
||||
return Number(val.toFixed(2));
|
||||
}
|
||||
|
||||
|
||||
if (typeof val === 'string') {
|
||||
const normalized = val.trim().replace(',', '.');
|
||||
const num = parseFloat(normalized);
|
||||
@@ -156,18 +156,18 @@ export default function App() {
|
||||
const wsname = wb.SheetNames[0];
|
||||
const ws = wb.Sheets[wsname];
|
||||
const data = XLSX.utils.sheet_to_json<any[]>(ws, { header: 1 });
|
||||
|
||||
|
||||
if (data.length > 0) {
|
||||
const rawHeaders = data[0];
|
||||
const rawRows = data.slice(1);
|
||||
|
||||
|
||||
const processedRows = rawRows.map(row => {
|
||||
return row.map((val, idx) => {
|
||||
if (val === undefined || val === null || val === '') return val;
|
||||
const header = (rawHeaders[idx] || '').toLowerCase();
|
||||
|
||||
if (header.includes('id') || header.includes('no') || header.includes('code') ||
|
||||
header.includes('art.') || header.includes('barcode') || header.includes('article')) {
|
||||
|
||||
if (header.includes('id') || header.includes('no') || header.includes('code') ||
|
||||
header.includes('art.') || header.includes('barcode') || header.includes('article')) {
|
||||
// But allow if it's a weight/measure column (e.g. Article NW (kg))
|
||||
if (!(header.includes('nw') || header.includes('gw') || header.includes('weight') || header.includes('kg'))) {
|
||||
return val;
|
||||
@@ -190,7 +190,7 @@ export default function App() {
|
||||
if (typeof val === 'number') {
|
||||
return Number(val.toFixed(2));
|
||||
}
|
||||
|
||||
|
||||
if (typeof val === 'string') {
|
||||
const normalized = val.trim().replace(',', '.');
|
||||
const num = parseFloat(normalized);
|
||||
@@ -217,15 +217,15 @@ export default function App() {
|
||||
|
||||
const handleExport = () => {
|
||||
if (appState.data.length === 0) return;
|
||||
|
||||
|
||||
const wsData = [appState.headers, ...appState.data];
|
||||
const ws = XLSX.utils.aoa_to_sheet(wsData);
|
||||
const wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'Products');
|
||||
|
||||
|
||||
const dateStr = new Date().toISOString().split('T')[0];
|
||||
XLSX.writeFile(wb, `CRAZE_Products_Updated_${dateStr}.xlsx`);
|
||||
|
||||
|
||||
// 3. Post-export: Reset pending statuses in Supabase
|
||||
console.log('Resetting pending statuses in Supabase...');
|
||||
resetAllPendingRows().then(success => {
|
||||
@@ -254,12 +254,12 @@ export default function App() {
|
||||
// 2. Persist to Supabase
|
||||
const articleNo = String(updatedRow[COLUMNS.ARTICLE_NO]);
|
||||
console.log(`Saving article ${articleNo} to Supabase...`);
|
||||
|
||||
|
||||
// Update local status to pending
|
||||
setRowStatuses(prev => ({ ...prev, [articleNo]: 'pending' }));
|
||||
|
||||
|
||||
const success = await saveRowToSupabase(articleNo, updatedRow);
|
||||
|
||||
|
||||
if (success) {
|
||||
console.log(`Successfully saved ${articleNo}`);
|
||||
setAppState(prev => ({ ...prev, hasUnsavedChanges: false }));
|
||||
@@ -283,7 +283,7 @@ export default function App() {
|
||||
|
||||
const handleUndo = () => {
|
||||
if (undoHistory.length === 0) return;
|
||||
|
||||
|
||||
const [lastAction, ...remainingHistory] = undoHistory;
|
||||
setAppState(prev => ({
|
||||
...prev,
|
||||
@@ -366,10 +366,9 @@ export default function App() {
|
||||
) : (
|
||||
<>
|
||||
{activeModule === 'descriptions' && (
|
||||
<ProductDescriptions
|
||||
data={appState.data}
|
||||
onEdit={(index) => setEditingRowIndex(index)}
|
||||
rowStatuses={rowStatuses}
|
||||
<ProductDescriptions
|
||||
data={appState.data}
|
||||
onEdit={(index) => setEditingRowIndex(index)}
|
||||
/>
|
||||
)}
|
||||
{activeModule === 'matrix' && (
|
||||
@@ -409,15 +408,15 @@ export default function App() {
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<UndoToast
|
||||
undoState={undoHistory[0] || null}
|
||||
onUndo={handleUndo}
|
||||
onClose={() => setUndoHistory([])}
|
||||
<UndoToast
|
||||
undoState={undoHistory[0] || null}
|
||||
onUndo={handleUndo}
|
||||
onClose={() => setUndoHistory([])}
|
||||
/>
|
||||
|
||||
{editingRowIndex !== null && (
|
||||
<EditPanel
|
||||
row={appState.data[editingRowIndex]}
|
||||
<EditPanel
|
||||
row={appState.data[editingRowIndex]}
|
||||
rowIndex={editingRowIndex}
|
||||
onSave={handleSaveRow}
|
||||
onClose={() => setEditingRowIndex(null)}
|
||||
|
||||
@@ -304,47 +304,37 @@ export function ProductDescriptions({ data, onEdit }: ProductDescriptionsProps)
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-slate-700/50">
|
||||
{paginatedData.map(({ row, index }) => {
|
||||
const isPending = rowStatuses[String(row[COLUMNS.ARTICLE_NO])] === 'pending';
|
||||
return (
|
||||
<tr
|
||||
key={index}
|
||||
className={cn(
|
||||
"transition-colors",
|
||||
getRowColor(row),
|
||||
isPending ? "bg-yellow-400/20 border-l-4 border-l-yellow-400" : ""
|
||||
)}
|
||||
>
|
||||
<td className="px-4 py-3 font-mono text-slate-300 text-xs">{row[COLUMNS.ARTICLE_NO]}</td>
|
||||
<td className="px-4 py-3 font-medium text-white max-w-[200px] truncate" title={row[COLUMNS.ARTICLE_NAME]}>{row[COLUMNS.ARTICLE_NAME]}</td>
|
||||
<td className="px-4 py-3 text-slate-300 text-xs">{row[COLUMNS.LINE]}</td>
|
||||
<td className="px-4 py-3 text-slate-300 text-xs truncate max-w-[120px]" title={row[COLUMNS.LICENSE]}>{row[COLUMNS.LICENSE] || '—'}</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className={cn(
|
||||
"px-2 py-0.5 rounded text-[10px] font-bold border",
|
||||
String(row[COLUMNS.CLASSIFICATION]).includes('OOC')
|
||||
? "bg-amber-500/10 text-amber-500 border-amber-500/20"
|
||||
: "bg-slate-700/50 text-slate-400 border-slate-600/50"
|
||||
)}>
|
||||
{row[COLUMNS.CLASSIFICATION] || '—'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3"><Badge content={row[COLUMNS.LONG_DE]} row={row} /></td>
|
||||
<td className="px-4 py-3"><Badge content={row[COLUMNS.LONG_EN]} row={row} /></td>
|
||||
<td className="px-4 py-3"><Badge content={row[COLUMNS.SHORT_DE]} row={row} /></td>
|
||||
<td className="px-4 py-3"><Badge content={row[COLUMNS.SHORT_EN]} row={row} /></td>
|
||||
<td className="px-4 py-3 text-right">
|
||||
<button
|
||||
onClick={() => onEdit(index)}
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 bg-blue-600/10 text-blue-400 hover:bg-blue-600 hover:text-white rounded-md transition-colors font-medium"
|
||||
>
|
||||
<Edit2 className="w-4 h-4" />
|
||||
Edit
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
{paginatedData.map(({ row, index }) => (
|
||||
<tr key={index} className={cn("transition-colors", getRowColor(row))}>
|
||||
<td className="px-4 py-3 font-mono text-slate-300 text-xs">{row[COLUMNS.ARTICLE_NO]}</td>
|
||||
<td className="px-4 py-3 font-medium text-white max-w-[200px] truncate" title={row[COLUMNS.ARTICLE_NAME]}>{row[COLUMNS.ARTICLE_NAME]}</td>
|
||||
<td className="px-4 py-3 text-slate-300 text-xs">{row[COLUMNS.LINE]}</td>
|
||||
<td className="px-4 py-3 text-slate-300 text-xs truncate max-w-[120px]" title={row[COLUMNS.LICENSE]}>{row[COLUMNS.LICENSE] || '—'}</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className={cn(
|
||||
"px-2 py-0.5 rounded text-[10px] font-bold border",
|
||||
String(row[COLUMNS.CLASSIFICATION]).includes('OOC')
|
||||
? "bg-amber-500/10 text-amber-500 border-amber-500/20"
|
||||
: "bg-slate-700/50 text-slate-400 border-slate-600/50"
|
||||
)}>
|
||||
{row[COLUMNS.CLASSIFICATION] || '—'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3"><Badge content={row[COLUMNS.LONG_DE]} row={row} /></td>
|
||||
<td className="px-4 py-3"><Badge content={row[COLUMNS.LONG_EN]} row={row} /></td>
|
||||
<td className="px-4 py-3"><Badge content={row[COLUMNS.SHORT_DE]} row={row} /></td>
|
||||
<td className="px-4 py-3"><Badge content={row[COLUMNS.SHORT_EN]} row={row} /></td>
|
||||
<td className="px-4 py-3 text-right">
|
||||
<button
|
||||
onClick={() => onEdit(index)}
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 bg-blue-600/10 text-blue-400 hover:bg-blue-600 hover:text-white rounded-md transition-colors font-medium"
|
||||
>
|
||||
<Edit2 className="w-4 h-4" />
|
||||
Edit
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
{paginatedData.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={9} className="px-4 py-8 text-center text-slate-500">
|
||||
|
||||
Reference in New Issue
Block a user