import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useCreateIngredient } from '../../../api/hooks/inventory'; import type { Ingredient } from '../../../api/types/inventory'; interface QuickAddIngredientModalProps { isOpen: boolean; onClose: () => void; onCreated: (ingredient: Ingredient) => void; tenantId: string; context: 'recipe' | 'supplier' | 'standalone'; } export const QuickAddIngredientModal: React.FC = ({ isOpen, onClose, onCreated, tenantId, context }) => { const { t } = useTranslation(); const createIngredient = useCreateIngredient(); // Form state - minimal required fields const [formData, setFormData] = useState({ name: '', category: '', unit_of_measure: 'kg', // Optional fields (collapsed by default) stock_quantity: 0, cost_per_unit: 0, estimated_shelf_life_days: 30, low_stock_threshold: 0, reorder_point: 0, requires_refrigeration: false, requires_freezing: false, is_seasonal: false, notes: '', }); const [showOptionalFields, setShowOptionalFields] = useState(false); const [errors, setErrors] = useState>({}); const [isSubmitting, setIsSubmitting] = useState(false); const categoryOptions = [ 'Baking Ingredients', 'Dairy', 'Fruits', 'Vegetables', 'Meat', 'Seafood', 'Spices', 'Other' ]; const unitOptions = ['kg', 'g', 'L', 'ml', 'units', 'dozen']; const validateForm = (): boolean => { const newErrors: Record = {}; if (!formData.name.trim()) { newErrors.name = 'El nombre es requerido'; } if (!formData.category) { newErrors.category = 'La categoría es requerida'; } if (!formData.unit_of_measure) { newErrors.unit_of_measure = 'La unidad es requerida'; } // Validate optional fields if shown if (showOptionalFields) { if (formData.stock_quantity < 0) { newErrors.stock_quantity = 'El stock no puede ser negativo'; } if (formData.cost_per_unit < 0) { newErrors.cost_per_unit = 'El costo no puede ser negativo'; } if (formData.estimated_shelf_life_days <= 0) { newErrors.estimated_shelf_life_days = 'Los días de caducidad deben ser mayores a 0'; } } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!validateForm()) return; setIsSubmitting(true); try { const ingredientData = { name: formData.name.trim(), product_type: 'ingredient', category: formData.category, unit_of_measure: formData.unit_of_measure, low_stock_threshold: showOptionalFields ? formData.low_stock_threshold : 1, max_stock_level: showOptionalFields ? formData.stock_quantity * 2 : 100, reorder_point: showOptionalFields ? formData.reorder_point : 2, shelf_life_days: showOptionalFields ? formData.estimated_shelf_life_days : 30, requires_refrigeration: formData.requires_refrigeration, requires_freezing: formData.requires_freezing, is_seasonal: formData.is_seasonal, average_cost: showOptionalFields ? formData.cost_per_unit : 0, notes: formData.notes || `Creado durante ${context === 'recipe' ? 'configuración de receta' : 'configuración de proveedor'}`, // Track that this was created inline metadata: { created_context: context, is_complete: showOptionalFields, needs_review: !showOptionalFields, } }; const createdIngredient = await createIngredient.mutateAsync({ tenantId, ingredientData }); // Call parent with created ingredient onCreated(createdIngredient); // Reset and close resetForm(); onClose(); } catch (error) { console.error('Error creating ingredient:', error); setErrors({ submit: 'Error al crear el ingrediente. Inténtalo de nuevo.' }); } finally { setIsSubmitting(false); } }; const resetForm = () => { setFormData({ name: '', category: '', unit_of_measure: 'kg', stock_quantity: 0, cost_per_unit: 0, estimated_shelf_life_days: 30, low_stock_threshold: 0, reorder_point: 0, requires_refrigeration: false, requires_freezing: false, is_seasonal: false, notes: '', }); setShowOptionalFields(false); setErrors({}); }; const handleClose = () => { resetForm(); onClose(); }; if (!isOpen) return null; const getContextMessage = () => { switch (context) { case 'recipe': return 'El ingrediente se agregará al inventario y estará disponible para usar en esta receta.'; case 'supplier': return 'El ingrediente se agregará al inventario y podrás asociarlo con este proveedor.'; default: return 'El ingrediente se agregará a tu inventario.'; } }; const getCtaText = () => { switch (context) { case 'recipe': return 'Agregar y Usar en Receta'; case 'supplier': return 'Agregar y Asociar con Proveedor'; default: return 'Agregar Ingrediente'; } }; return ( <> {/* Backdrop */}
{/* Modal */}
e.stopPropagation()} > {/* Header */}

⚡ Agregar Ingrediente Rápido

{getContextMessage()}

{/* Form */}
{/* Required Fields */}
setFormData({ ...formData, name: e.target.value })} className="w-full px-3 py-2.5 bg-[var(--bg-secondary)] border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent text-[var(--text-primary)] transition-all" placeholder="Ej: Harina de trigo integral" autoFocus /> {errors.name && (

{errors.name}

)}
{errors.category && (

{errors.category}

)}
{errors.unit_of_measure && (

{errors.unit_of_measure}

)}
{/* Optional Fields Toggle */}
{/* Optional Fields */} {showOptionalFields && (
setFormData({ ...formData, stock_quantity: parseFloat(e.target.value) || 0 })} className="w-full px-3 py-2.5 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)]" /> {errors.stock_quantity && (

{errors.stock_quantity}

)}
setFormData({ ...formData, cost_per_unit: parseFloat(e.target.value) || 0 })} className="w-full px-3 py-2.5 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)]" /> {errors.cost_per_unit && (

{errors.cost_per_unit}

)}
setFormData({ ...formData, estimated_shelf_life_days: parseInt(e.target.value) || 30 })} className="w-full px-3 py-2.5 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)]" /> {errors.estimated_shelf_life_days && (

{errors.estimated_shelf_life_days}

)}
setFormData({ ...formData, reorder_point: parseInt(e.target.value) || 0 })} className="w-full px-3 py-2.5 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)]" />
)}
{/* Info Box */} {!showOptionalFields && (

💡 Puedes completar los detalles de stock y costos después en la gestión de inventario.

)} {/* Error Message */} {errors.submit && (

{errors.submit}

)} {/* Actions */}
{/* Animation Styles */} ); };