fix: rename Gemini API key to VITE_GEMINI_API_KEY and improve logging

This commit is contained in:
Christian Vidal Wolf
2026-04-24 13:27:34 +02:00
parent e6207dff64
commit 2c1efc44d6
2 changed files with 35 additions and 17 deletions
+9 -3
View File
@@ -188,16 +188,22 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed
return formData[field] !== (row[colIndex] !== undefined && row[colIndex] !== null ? String(row[colIndex]) : ''); return formData[field] !== (row[colIndex] !== undefined && row[colIndex] !== null ? String(row[colIndex]) : '');
}; };
const handleGenerate = async (field: keyof typeof formData) => { const handleGenerate = (field: keyof typeof formData) => {
console.log('[EditPanel] handleGenerate called for field:', field);
setError(null); // Clear any previous error
setPendingGeminiField(field); setPendingGeminiField(field);
}; };
const executeGenerate = async () => { const executeGenerate = async () => {
if (!pendingGeminiField) return; if (!pendingGeminiField) {
console.warn('[EditPanel] executeGenerate called but no field pending');
return;
}
const field = pendingGeminiField; const field = pendingGeminiField;
console.log('[EditPanel] Starting generation for field:', field);
setLoadingField(field); setLoadingField(field);
setError(null); setError(null);
try { try {
let prompt = ''; let prompt = '';
const baseContext = `Article Name: ${row[COLUMNS.ARTICLE_NAME]}\nArticle Details (EN): ${formData.detailsEn || 'N/A'}\nArticle Details (DE): ${formData.detailsDe || 'N/A'}`; const baseContext = `Article Name: ${row[COLUMNS.ARTICLE_NAME]}\nArticle Details (EN): ${formData.detailsEn || 'N/A'}\nArticle Details (DE): ${formData.detailsDe || 'N/A'}`;
+26 -14
View File
@@ -618,6 +618,18 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
}; };
}, [pinnedColumns, columnOrder, columnWidths]); }, [pinnedColumns, columnOrder, columnWidths]);
// Calculate z-index for sticky columns (so they stack correctly)
const getStickyRank = useMemo(() => {
const pinnedOrder = columnOrder.filter(k => pinnedColumns.has(k));
return (key: string): number | null => {
if (!pinnedColumns.has(key)) return null;
const idx = pinnedOrder.indexOf(key);
if (idx === -1) return null;
// Higher rank = on top
return pinnedOrder.length - idx + 10;
};
}, [pinnedColumns, columnOrder]);
const isPinned = (key: string) => pinnedColumns.has(key); const isPinned = (key: string) => pinnedColumns.has(key);
// ═ Unique values for dynamic pricing columns ═════════════════════════════ // ═ Unique values for dynamic pricing columns ═════════════════════════════
@@ -1120,9 +1132,9 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
<table ref={tableRef} className="w-full text-sm border-collapse table-fixed"> <table ref={tableRef} className="w-full text-sm border-collapse table-fixed">
<thead className="sticky top-0 z-10 bg-slate-900 border-b border-slate-700"> <thead className="sticky top-0 z-10 bg-slate-900 border-b border-slate-700">
<tr> <tr>
<th style={{ width: columnWidths.articleNo, ...(isPinned('articleNo') ? { left: getStickyLeft('articleNo') ?? 0 } : {}) }} className={cn( <th style={{ width: columnWidths.articleNo, ...(isPinned('articleNo') ? { left: getStickyLeft('articleNo') ?? 0, zIndex: getStickyRank('articleNo') ?? 0 } : {}) }} className={cn(
"text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative", "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
isPinned('articleNo') && "sticky bg-slate-900 z-20" isPinned('articleNo') && "sticky bg-slate-900"
)} onClick={() => handleSort('articleNo')}> )} onClick={() => handleSort('articleNo')}>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="truncate flex items-center gap-1"> <span className="truncate flex items-center gap-1">
@@ -1148,9 +1160,9 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
)} )}
<ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'articleNo', columnWidths.articleNo); }} /> <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'articleNo', columnWidths.articleNo); }} />
</th> </th>
<th style={{ width: columnWidths.articleName, ...(isPinned('articleName') ? { left: getStickyLeft('articleName') ?? 0 } : {}) }} className={cn( <th style={{ width: columnWidths.articleName, ...(isPinned('articleName') ? { left: getStickyLeft('articleName') ?? 0, zIndex: getStickyRank('articleName') ?? 0 } : {}) }} className={cn(
"text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative", "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
isPinned('articleName') && "sticky bg-slate-900 z-20" isPinned('articleName') && "sticky bg-slate-900"
)} onClick={() => handleSort('articleName')}> )} onClick={() => handleSort('articleName')}>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="truncate flex items-center gap-1"> <span className="truncate flex items-center gap-1">
@@ -1175,9 +1187,9 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
)} )}
<ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'articleName', columnWidths.articleName); }} /> <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'articleName', columnWidths.articleName); }} />
</th> </th>
<th style={{ width: columnWidths.line, ...(isPinned('line') ? { left: getStickyLeft('line') ?? 0 } : {}) }} className={cn( <th style={{ width: columnWidths.line, ...(isPinned('line') ? { left: getStickyLeft('line') ?? 0, zIndex: getStickyRank('line') ?? 0 } : {}) }} className={cn(
"text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative", "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
isPinned('line') && "sticky bg-slate-900 z-20" isPinned('line') && "sticky bg-slate-900"
)} onClick={() => handleSort('line')}> )} onClick={() => handleSort('line')}>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="truncate flex items-center gap-1"> <span className="truncate flex items-center gap-1">
@@ -1205,9 +1217,9 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
)} )}
<ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'line', columnWidths.line); }} /> <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'line', columnWidths.line); }} />
</th> </th>
<th style={{ width: columnWidths.classification, ...(isPinned('classification') ? { left: getStickyLeft('classification') ?? 0 } : {}) }} className={cn( <th style={{ width: columnWidths.classification, ...(isPinned('classification') ? { left: getStickyLeft('classification') ?? 0, zIndex: getStickyRank('classification') ?? 0 } : {}) }} className={cn(
"text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative", "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
isPinned('classification') && "sticky bg-slate-900 z-20" isPinned('classification') && "sticky bg-slate-900"
)} onClick={() => handleSort('classification')}> )} onClick={() => handleSort('classification')}>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="truncate flex items-center gap-1"> <span className="truncate flex items-center gap-1">
@@ -1236,9 +1248,9 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
<ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'classification', columnWidths.classification); }} /> <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'classification', columnWidths.classification); }} />
</th> </th>
<th style={{ width: columnWidths.productType, ...(isPinned('productType') ? { left: getStickyLeft('productType') ?? 0 } : {}) }} className={cn( <th style={{ width: columnWidths.productType, ...(isPinned('productType') ? { left: getStickyLeft('productType') ?? 0, zIndex: getStickyRank('productType') ?? 0 } : {}) }} className={cn(
"text-left px-3 py-3 text-xs font-semibold text-purple-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative", "text-left px-3 py-3 text-xs font-semibold text-purple-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
isPinned('productType') && "sticky bg-slate-900 z-20" isPinned('productType') && "sticky bg-slate-900"
)} onClick={() => handleSort('productType')}> )} onClick={() => handleSort('productType')}>
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
{isPinned('productType') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />} {isPinned('productType') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
@@ -1263,9 +1275,9 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
<ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'productType', columnWidths.productType); }} /> <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'productType', columnWidths.productType); }} />
</th> </th>
<th style={{ width: columnWidths.itemToLogistic, ...(isPinned('itemToLogistic') ? { left: getStickyLeft('itemToLogistic') ?? 0 } : {}) }} className={cn( <th style={{ width: columnWidths.itemToLogistic, ...(isPinned('itemToLogistic') ? { left: getStickyLeft('itemToLogistic') ?? 0, zIndex: getStickyRank('itemToLogistic') ?? 0 } : {}) }} className={cn(
"text-left px-3 py-3 text-xs font-semibold text-pink-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative", "text-left px-3 py-3 text-xs font-semibold text-pink-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
isPinned('itemToLogistic') && "sticky bg-slate-900 z-20" isPinned('itemToLogistic') && "sticky bg-slate-900"
)} onClick={() => handleSort('itemToLogistic')}> )} onClick={() => handleSort('itemToLogistic')}>
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
{isPinned('itemToLogistic') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />} {isPinned('itemToLogistic') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
@@ -1279,7 +1291,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
return ( return (
<th key={col.index} style={{ width, ...(isPinned(colKey) ? { left: getStickyLeft(colKey) ?? 0 } : {}) }} className={cn( <th key={col.index} style={{ width, ...(isPinned(colKey) ? { left: getStickyLeft(colKey) ?? 0 } : {}) }} className={cn(
"text-left px-3 py-3 text-xs font-semibold text-blue-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative", "text-left px-3 py-3 text-xs font-semibold text-blue-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
isPinned(colKey) && "sticky bg-slate-900 z-20" isPinned(colKey) && "sticky bg-slate-900"
)} onClick={() => handleSort(col.index)}> )} onClick={() => handleSort(col.index)}>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="truncate flex items-center gap-1"> <span className="truncate flex items-center gap-1">
@@ -1448,7 +1460,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
return ( return (
<th key={col.index} style={{ width, ...(isPinned(colKey) ? { left: getStickyLeft(colKey) ?? 0 } : {}) }} className={cn( <th key={col.index} style={{ width, ...(isPinned(colKey) ? { left: getStickyLeft(colKey) ?? 0 } : {}) }} className={cn(
"text-left px-3 py-3 text-xs font-semibold text-orange-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative", "text-left px-3 py-3 text-xs font-semibold text-orange-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
isPinned(colKey) && "sticky bg-slate-900 z-20" isPinned(colKey) && "sticky bg-slate-900"
)} onClick={() => handleSort(col.index)}> )} onClick={() => handleSort(col.index)}>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="truncate flex items-center gap-1"> <span className="truncate flex items-center gap-1">