Unify AI suggestions step UI with recipe step design
✨ Complete UI redesign of UploadSalesDataStep to match beautiful recipe step pattern: - Add "Why This Matters" info box with icon and explanation - Replace summary section with clean progress indicator showing count and success state - Change product list from vertical layout to responsive 2-column grid - Implement custom checkboxes with visual checkmark instead of native inputs - Separate edit form into gradient-background section (matching recipe templates) - Update file format guide colors from hardcoded blue to CSS variables - Clean up actions sections and remove unnecessary comments - Add emojis for visual interest (❄️ refrigeration, 🧊 freezing, 🌿 seasonal, 📊 sales) - Improve spacing, hierarchy, and overall visual consistency throughout The AI suggestions step now has the same beautiful, modern, and easy-to-use UI/UX as the recipe step, providing a consistent onboarding experience.
This commit is contained in:
@@ -374,90 +374,165 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
if (showInventoryStep) {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="text-center">
|
||||
<p className="text-[var(--text-secondary)] mb-6">
|
||||
¡Perfecto! Hemos analizado automáticamente tus datos de ventas y generado estas sugerencias de inventario inteligentes.
|
||||
Revisa y selecciona los artículos que te gustaría agregar a tu inventario.
|
||||
{/* Why This Matters */}
|
||||
<div className="bg-[var(--color-info)]/10 border border-[var(--color-info)]/20 rounded-lg p-4">
|
||||
<h3 className="font-semibold text-[var(--text-primary)] mb-2 flex items-center gap-2">
|
||||
<svg className="w-5 h-5 text-[var(--color-info)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
{t('onboarding:ai_suggestions.why_title', 'AI Smart Inventory')}
|
||||
</h3>
|
||||
<p className="text-sm text-[var(--text-secondary)]">
|
||||
{t('onboarding:ai_suggestions.why_desc', '¡Perfecto! Hemos analizado tus datos de ventas y generado sugerencias inteligentes de inventario. Selecciona los artículos que deseas agregar.')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Summary */}
|
||||
<div className="bg-[var(--bg-secondary)] rounded-lg p-4">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center space-y-3 sm:space-y-0">
|
||||
<div className="text-center sm:text-left">
|
||||
<p className="font-medium text-sm sm:text-base">
|
||||
{selectedCount} de {inventoryItems.length} artículos seleccionados
|
||||
</p>
|
||||
<p className="text-xs sm:text-sm text-[var(--text-secondary)]">
|
||||
Los artículos con alta confianza están preseleccionados
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
{/* Progress indicator */}
|
||||
<div className="flex items-center justify-between p-3 bg-[var(--bg-secondary)] rounded-lg">
|
||||
<div className="flex items-center gap-2">
|
||||
<svg className="w-5 h-5 text-[var(--text-secondary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium text-[var(--text-primary)]">
|
||||
{selectedCount} de {inventoryItems.length} {t('onboarding:ai_suggestions.items_selected', 'artículos seleccionados')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{selectedCount >= 1 && (
|
||||
<div className="flex items-center gap-1 text-xs text-[var(--color-success)]">
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
{t('onboarding:ai_suggestions.minimum_met', 'Mínimo alcanzado')}
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSelectAll}
|
||||
className="w-full sm:w-auto"
|
||||
className="text-xs px-3 py-1.5 bg-[var(--bg-primary)] border border-[var(--border-secondary)] rounded hover:border-[var(--color-primary)] hover:text-[var(--color-primary)] transition-colors"
|
||||
>
|
||||
{allSelected ? 'Deseleccionar Todos' : 'Seleccionar Todos'}
|
||||
</Button>
|
||||
{allSelected ? t('common:deselect_all', 'Deseleccionar Todos') : t('common:select_all', 'Seleccionar Todos')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Inventory Items */}
|
||||
<div className="space-y-4 max-h-96 overflow-y-auto">
|
||||
{inventoryItems.map((item) => (
|
||||
<div
|
||||
key={item.suggestion_id}
|
||||
className={`border rounded-lg p-4 transition-colors ${
|
||||
item.selected
|
||||
? 'border-[var(--color-primary)] bg-[var(--color-primary)]/5'
|
||||
: 'border-[var(--border-secondary)]'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex-shrink-0 pt-1">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={item.selected}
|
||||
onChange={() => handleToggleSelection(item.suggestion_id)}
|
||||
className="w-4 h-4 text-[var(--color-primary)] border-[var(--border-secondary)] rounded focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 space-y-3">
|
||||
<div>
|
||||
<h3 className="font-medium text-[var(--text-primary)]">
|
||||
{item.suggested_name}
|
||||
</h3>
|
||||
<p className="text-sm text-[var(--text-secondary)]">
|
||||
{item.category} • Unidad: {item.unit_of_measure}
|
||||
</p>
|
||||
<div className="flex items-center gap-2 mt-1 flex-wrap">
|
||||
<span className="text-xs bg-[var(--bg-primary)] px-2 py-0.5 rounded-full text-[var(--text-secondary)]">
|
||||
Confianza: {Math.round(item.confidence_score * 100)}%
|
||||
</span>
|
||||
{item.requires_refrigeration && (
|
||||
<span className="text-xs bg-[var(--color-info)]/10 text-[var(--color-info)] px-2 py-0.5 rounded-full">
|
||||
Requiere refrigeración
|
||||
</span>
|
||||
)}
|
||||
{item.requires_freezing && (
|
||||
<span className="text-xs bg-[var(--color-info)]/10 text-[var(--color-info)] px-2 py-0.5 rounded-full">
|
||||
Requiere congelación
|
||||
</span>
|
||||
)}
|
||||
{item.is_seasonal && (
|
||||
<span className="text-xs bg-[var(--color-success)]/10 text-[var(--color-success)] px-2 py-0.5 rounded-full">
|
||||
Producto estacional
|
||||
</span>
|
||||
{/* Product suggestions grid */}
|
||||
<div>
|
||||
<h4 className="text-sm font-medium text-[var(--text-secondary)] mb-3">
|
||||
{t('onboarding:ai_suggestions.suggested_products', 'Productos Sugeridos')}
|
||||
</h4>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 max-h-96 overflow-y-auto">
|
||||
{inventoryItems.map((item) => (
|
||||
<div
|
||||
key={item.suggestion_id}
|
||||
onClick={() => handleToggleSelection(item.suggestion_id)}
|
||||
className={`p-4 border rounded-lg cursor-pointer transition-all ${
|
||||
item.selected
|
||||
? 'border-[var(--color-primary)] bg-[var(--color-primary)]/5 shadow-sm'
|
||||
: 'border-[var(--border-secondary)] hover:border-[var(--border-primary)] hover:bg-[var(--bg-secondary)]'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
{/* Checkbox */}
|
||||
<div className="flex-shrink-0 pt-1">
|
||||
<div
|
||||
className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-colors ${
|
||||
item.selected
|
||||
? 'border-[var(--color-primary)] bg-[var(--color-primary)]'
|
||||
: 'border-[var(--border-secondary)]'
|
||||
}`}
|
||||
>
|
||||
{item.selected && (
|
||||
<svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{item.selected && (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4 pt-3 border-t border-[var(--border-secondary)]">
|
||||
<Input
|
||||
label="Stock Inicial"
|
||||
{/* Product info */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<h5 className="font-medium text-[var(--text-primary)] truncate">
|
||||
{item.suggested_name}
|
||||
</h5>
|
||||
<p className="text-sm text-[var(--text-secondary)] mt-0.5">
|
||||
{item.category} • {item.unit_of_measure}
|
||||
</p>
|
||||
|
||||
{/* Tags */}
|
||||
<div className="flex items-center gap-1.5 mt-2 flex-wrap">
|
||||
<span className="text-xs bg-[var(--bg-primary)] px-2 py-0.5 rounded-full text-[var(--text-secondary)]">
|
||||
{Math.round(item.confidence_score * 100)}% confianza
|
||||
</span>
|
||||
{item.requires_refrigeration && (
|
||||
<span className="text-xs bg-[var(--color-info)]/10 text-[var(--color-info)] px-2 py-0.5 rounded-full">
|
||||
❄️ Refrigeración
|
||||
</span>
|
||||
)}
|
||||
{item.requires_freezing && (
|
||||
<span className="text-xs bg-[var(--color-info)]/10 text-[var(--color-info)] px-2 py-0.5 rounded-full">
|
||||
🧊 Congelación
|
||||
</span>
|
||||
)}
|
||||
{item.is_seasonal && (
|
||||
<span className="text-xs bg-[var(--color-success)]/10 text-[var(--color-success)] px-2 py-0.5 rounded-full">
|
||||
🌿 Estacional
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Sales data preview */}
|
||||
{item.sales_data && (
|
||||
<div className="mt-2 pt-2 border-t border-[var(--border-secondary)]">
|
||||
<div className="flex items-center gap-3 text-xs text-[var(--text-secondary)]">
|
||||
<span title="Promedio diario">
|
||||
📊 {item.sales_data.average_daily_sales.toFixed(1)}/día
|
||||
</span>
|
||||
<span title="Cantidad total">
|
||||
📦 {item.sales_data.total_quantity} total
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Edit selected items section */}
|
||||
{selectedCount > 0 && (
|
||||
<div className="space-y-3 border-2 border-[var(--color-primary)] rounded-lg p-4 bg-gradient-to-br from-[var(--color-primary)]/5 to-transparent">
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<h3 className="font-semibold text-[var(--text-primary)] flex items-center gap-2">
|
||||
<svg className="w-5 h-5 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
{t('onboarding:ai_suggestions.edit_details', 'Configurar Detalles')}
|
||||
</h3>
|
||||
<p className="text-sm text-[var(--text-secondary)] mt-1">
|
||||
{t('onboarding:ai_suggestions.edit_desc', 'Ajusta el stock inicial y costos para los artículos seleccionados')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3 max-h-80 overflow-y-auto">
|
||||
{inventoryItems.filter(item => item.selected).map((item) => (
|
||||
<div
|
||||
key={item.suggestion_id}
|
||||
className="p-3 bg-[var(--bg-primary)] rounded-lg border border-[var(--border-secondary)]"
|
||||
>
|
||||
<div className="font-medium text-[var(--text-primary)] mb-3 text-sm">
|
||||
{item.suggested_name}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--text-primary)] mb-1.5">
|
||||
{t('onboarding:ai_suggestions.initial_stock', 'Stock Inicial')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
value={item.stock_quantity.toString()}
|
||||
@@ -466,10 +541,16 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
'stock_quantity',
|
||||
Number(e.target.value)
|
||||
)}
|
||||
size="sm"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] text-[var(--text-primary)]"
|
||||
placeholder="0"
|
||||
/>
|
||||
<Input
|
||||
label="Costo por Unidad (€)"
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--text-primary)] mb-1.5">
|
||||
{t('onboarding:ai_suggestions.cost_per_unit', 'Costo por Unidad')} (€)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
step="0.01"
|
||||
@@ -479,10 +560,16 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
'cost_per_unit',
|
||||
Number(e.target.value)
|
||||
)}
|
||||
size="sm"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] text-[var(--text-primary)]"
|
||||
placeholder="0.00"
|
||||
/>
|
||||
<Input
|
||||
label="Días de Caducidad"
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--text-primary)] mb-1.5">
|
||||
{t('onboarding:ai_suggestions.shelf_life_days', 'Días de Caducidad')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
value={(item.estimated_shelf_life_days || 30).toString()}
|
||||
@@ -491,16 +578,17 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
'estimated_shelf_life_days',
|
||||
Number(e.target.value)
|
||||
)}
|
||||
size="sm"
|
||||
className="sm:col-span-2 lg:col-span-1"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] text-[var(--text-primary)]"
|
||||
placeholder="30"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="bg-[var(--color-error)]/10 border border-[var(--color-error)]/20 rounded-lg p-4">
|
||||
@@ -509,8 +597,7 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
)}
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex flex-col sm:flex-row justify-end gap-3 sm:gap-0">{/* Removed back button */}
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button
|
||||
onClick={handleCreateInventory}
|
||||
isLoading={isCreating}
|
||||
@@ -540,19 +627,19 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
</div>
|
||||
|
||||
{/* File Format Guide */}
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||
<div className="bg-[var(--color-info)]/10 border border-[var(--color-info)]/20 rounded-lg p-4">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<svg className="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg className="w-5 h-5 text-[var(--color-info)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<h3 className="font-semibold text-blue-900">
|
||||
<h3 className="font-semibold text-[var(--text-primary)]">
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.title', 'Guía de Formato de Archivo')}
|
||||
</h3>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowGuide(!showGuide)}
|
||||
className="text-blue-600 hover:text-blue-800 text-sm font-medium"
|
||||
className="text-[var(--color-info)] hover:text-[var(--color-primary)] text-sm font-medium"
|
||||
>
|
||||
{showGuide
|
||||
? t('onboarding:steps.inventory_setup.file_format_guide.collapse_guide', 'Ocultar Guía')
|
||||
@@ -562,13 +649,13 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
</div>
|
||||
|
||||
{/* Quick Summary - Always Visible */}
|
||||
<div className="text-sm text-blue-800 space-y-1">
|
||||
<div className="text-sm text-[var(--text-secondary)] space-y-1">
|
||||
<p>
|
||||
<strong>{t('onboarding:steps.inventory_setup.file_format_guide.supported_formats.title', 'Formatos Soportados')}:</strong>{' '}
|
||||
<strong className="text-[var(--text-primary)]">{t('onboarding:steps.inventory_setup.file_format_guide.supported_formats.title', 'Formatos Soportados')}:</strong>{' '}
|
||||
CSV, JSON, Excel (XLSX) • {t('onboarding:steps.inventory_setup.file_format_guide.supported_formats.max_size', 'Tamaño máximo: 10MB')}
|
||||
</p>
|
||||
<p>
|
||||
<strong>{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.title', 'Columnas Requeridas')}:</strong>{' '}
|
||||
<strong className="text-[var(--text-primary)]">{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.title', 'Columnas Requeridas')}:</strong>{' '}
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.date', 'Fecha')},{' '}
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.product', 'Nombre del Producto')},{' '}
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.quantity', 'Cantidad Vendida')}
|
||||
@@ -577,28 +664,28 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
|
||||
{/* Detailed Guide - Collapsible */}
|
||||
{showGuide && (
|
||||
<div className="mt-4 pt-4 border-t border-blue-200 space-y-4">
|
||||
<div className="mt-4 pt-4 border-t border-[var(--border-secondary)] space-y-4">
|
||||
{/* Required Columns Detail */}
|
||||
<div>
|
||||
<h4 className="font-semibold text-blue-900 mb-2">
|
||||
<h4 className="font-semibold text-[var(--text-primary)] mb-2">
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.title', 'Columnas Requeridas')}
|
||||
</h4>
|
||||
<div className="text-sm text-blue-800 space-y-1 pl-4">
|
||||
<div className="text-sm text-[var(--text-secondary)] space-y-1 pl-4">
|
||||
<p>
|
||||
• <strong>{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.date', 'Fecha')}:</strong>{' '}
|
||||
<span className="font-mono text-xs bg-blue-100 px-1 rounded">
|
||||
• <strong className="text-[var(--text-primary)]">{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.date', 'Fecha')}:</strong>{' '}
|
||||
<span className="font-mono text-xs bg-[var(--bg-secondary)] px-1.5 py-0.5 rounded">
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.date_examples', 'date, fecha, data')}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
• <strong>{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.product', 'Nombre del Producto')}:</strong>{' '}
|
||||
<span className="font-mono text-xs bg-blue-100 px-1 rounded">
|
||||
• <strong className="text-[var(--text-primary)]">{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.product', 'Nombre del Producto')}:</strong>{' '}
|
||||
<span className="font-mono text-xs bg-[var(--bg-secondary)] px-1.5 py-0.5 rounded">
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.product_examples', 'product, producto, product_name')}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
• <strong>{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.quantity', 'Cantidad Vendida')}:</strong>{' '}
|
||||
<span className="font-mono text-xs bg-blue-100 px-1 rounded">
|
||||
• <strong className="text-[var(--text-primary)]">{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.quantity', 'Cantidad Vendida')}:</strong>{' '}
|
||||
<span className="font-mono text-xs bg-[var(--bg-secondary)] px-1.5 py-0.5 rounded">
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.required_columns.quantity_examples', 'quantity, cantidad, quantity_sold')}
|
||||
</span>
|
||||
</p>
|
||||
@@ -607,10 +694,10 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
|
||||
{/* Optional Columns */}
|
||||
<div>
|
||||
<h4 className="font-semibold text-blue-900 mb-2">
|
||||
<h4 className="font-semibold text-[var(--text-primary)] mb-2">
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.optional_columns.title', 'Columnas Opcionales')}
|
||||
</h4>
|
||||
<div className="text-sm text-blue-800 space-y-1 pl-4">
|
||||
<div className="text-sm text-[var(--text-secondary)] space-y-1 pl-4">
|
||||
<p>• {t('onboarding:steps.inventory_setup.file_format_guide.optional_columns.revenue', 'Ingresos (revenue, ingresos, ventas)')}</p>
|
||||
<p>• {t('onboarding:steps.inventory_setup.file_format_guide.optional_columns.unit_price', 'Precio Unitario (unit_price, precio, price)')}</p>
|
||||
<p>• {t('onboarding:steps.inventory_setup.file_format_guide.optional_columns.category', 'Categoría (category, categoria)')}</p>
|
||||
@@ -621,10 +708,10 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
|
||||
{/* Date Formats */}
|
||||
<div>
|
||||
<h4 className="font-semibold text-blue-900 mb-2">
|
||||
<h4 className="font-semibold text-[var(--text-primary)] mb-2">
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.date_formats.title', 'Formatos de Fecha Soportados')}
|
||||
</h4>
|
||||
<div className="text-sm text-blue-800 pl-4">
|
||||
<div className="text-sm text-[var(--text-secondary)] pl-4">
|
||||
<p>{t('onboarding:steps.inventory_setup.file_format_guide.date_formats.formats', 'YYYY-MM-DD, DD/MM/YYYY, MM/DD/YYYY, DD-MM-YYYY, y más')}</p>
|
||||
<p className="text-xs mt-1">{t('onboarding:steps.inventory_setup.file_format_guide.date_formats.with_time', 'También se admiten formatos con hora')}</p>
|
||||
</div>
|
||||
@@ -632,10 +719,10 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
|
||||
{/* Automatic Features */}
|
||||
<div>
|
||||
<h4 className="font-semibold text-blue-900 mb-2">
|
||||
<h4 className="font-semibold text-[var(--text-primary)] mb-2">
|
||||
{t('onboarding:steps.inventory_setup.file_format_guide.features.title', 'Características Automáticas')}
|
||||
</h4>
|
||||
<div className="text-sm text-blue-800 space-y-1 pl-4">
|
||||
<div className="text-sm text-[var(--text-secondary)] space-y-1 pl-4">
|
||||
<p>✓ {t('onboarding:steps.inventory_setup.file_format_guide.features.multilingual', 'Detección multiidioma de columnas')}</p>
|
||||
<p>✓ {t('onboarding:steps.inventory_setup.file_format_guide.features.validation', 'Validación automática con reporte detallado')}</p>
|
||||
<p>✓ {t('onboarding:steps.inventory_setup.file_format_guide.features.ai_classification', 'Clasificación de productos con IA')}</p>
|
||||
@@ -757,27 +844,24 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex flex-col sm:flex-row justify-end gap-3 sm:gap-0">{/* Removed back button */}
|
||||
|
||||
{selectedFile && !showInventoryStep && (
|
||||
<div className="flex items-center justify-center px-4 py-2 bg-[var(--bg-secondary)] rounded-lg">
|
||||
{isValidating ? (
|
||||
<>
|
||||
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-[var(--color-primary)] mr-2"></div>
|
||||
<span className="text-sm text-[var(--text-secondary)]">Procesando automáticamente...</span>
|
||||
</>
|
||||
) : validationResult ? (
|
||||
<>
|
||||
<svg className="w-4 h-4 text-[var(--color-success)] mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
<span className="text-sm text-[var(--color-success)]">Archivo procesado exitosamente</span>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* Status indicator */}
|
||||
{selectedFile && !showInventoryStep && (
|
||||
<div className="flex items-center justify-center px-4 py-2 bg-[var(--bg-secondary)] rounded-lg">
|
||||
{isValidating ? (
|
||||
<>
|
||||
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-[var(--color-primary)] mr-2"></div>
|
||||
<span className="text-sm text-[var(--text-secondary)]">Procesando automáticamente...</span>
|
||||
</>
|
||||
) : validationResult ? (
|
||||
<>
|
||||
<svg className="w-4 h-4 text-[var(--color-success)] mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
<span className="text-sm text-[var(--color-success)]">Archivo procesado exitosamente</span>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user