import React, { useState, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { WizardStep, WizardStepProps } from '../../../ui/WizardModal/WizardModal'; import { AdvancedOptionsSection } from '../../../ui/AdvancedOptionsSection'; import { Building2, Package, Calendar, CheckCircle2, Plus, Trash2, Search, Loader2, AlertCircle, TrendingUp, } from 'lucide-react'; import { useTenant } from '../../../../stores/tenant.store'; import { useSuppliers } from '../../../../api/hooks/suppliers'; import { useIngredients } from '../../../../api/hooks/inventory'; import { suppliersService } from '../../../../api/services/suppliers'; import { useCreatePurchaseOrder } from '../../../../api/hooks/purchase-orders'; import { useTenantCurrency } from '../../../../hooks/useTenantCurrency'; // Step 1: Supplier Selection const SupplierSelectionStep: React.FC = ({ dataRef, onDataChange }) => { const data = dataRef?.current || {}; const { t } = useTranslation(['wizards', 'procurement']); const { currentTenant } = useTenant(); const [searchQuery, setSearchQuery] = useState(''); const [selectedSupplier, setSelectedSupplier] = useState(data.supplier || null); // Fetch suppliers const { data: suppliersData, isLoading, isError } = useSuppliers( currentTenant?.id || '', { limit: 100 }, { enabled: !!currentTenant?.id } ); const suppliers = (suppliersData || []).filter((s: any) => s.status === 'active'); const filteredSuppliers = suppliers.filter((supplier: any) => supplier.name.toLowerCase().includes(searchQuery.toLowerCase()) || supplier.supplier_code?.toLowerCase().includes(searchQuery.toLowerCase()) ); const handleSelectSupplier = (supplier: any) => { setSelectedSupplier(supplier); onDataChange?.({ ...data, supplier, supplier_id: supplier.id, }); }; return (

{t('purchaseOrder.supplierSelection.title')}

{t('purchaseOrder.supplierSelection.description')}

{isError && (
{t('purchaseOrder.supplierSelection.errorLoading')}
)} {isLoading ? (
{t('purchaseOrder.supplierSelection.loading')}
) : ( <> {/* Search Bar */}
setSearchQuery(e.target.value)} placeholder={t('purchaseOrder.supplierSelection.searchPlaceholder')} className="w-full pl-10 pr-4 py-3 border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)]" />
{/* Supplier List */}
{filteredSuppliers.length === 0 ? (

{t('purchaseOrder.supplierSelection.noSuppliers')}

{t('purchaseOrder.supplierSelection.tryDifferentSearch')}

) : ( filteredSuppliers.map((supplier: any) => ( )) )}
)}
); }; // Step 2: Add Items const AddItemsStep: React.FC = ({ dataRef, onDataChange }) => { const data = dataRef?.current || {}; const { t } = useTranslation(['wizards', 'procurement']); const { currentTenant } = useTenant(); const { currencySymbol } = useTenantCurrency(); const [supplierProductIds, setSupplierProductIds] = useState([]); const [isLoadingSupplierProducts, setIsLoadingSupplierProducts] = useState(false); // Fetch ALL ingredients const { data: allIngredientsData = [], isLoading: isLoadingIngredients } = useIngredients( currentTenant?.id || '', {}, { enabled: !!currentTenant?.id } ); // Fetch supplier products when supplier is available useEffect(() => { const fetchSupplierProducts = async () => { if (!data.supplier_id || !currentTenant?.id) { setSupplierProductIds([]); return; } setIsLoadingSupplierProducts(true); try { const products = await suppliersService.getSupplierProducts(currentTenant.id, data.supplier_id); const productIds = products.map((p: any) => p.inventory_product_id); setSupplierProductIds(productIds); } catch (error) { console.error('Error fetching supplier products:', error); setSupplierProductIds([]); } finally { setIsLoadingSupplierProducts(false); } }; fetchSupplierProducts(); }, [data.supplier_id, currentTenant?.id]); // Filter ingredients based on supplier products const ingredientsData = useMemo(() => { if (!data.supplier_id || supplierProductIds.length === 0) { return []; } return allIngredientsData.filter((ing: any) => supplierProductIds.includes(ing.id)); }, [allIngredientsData, supplierProductIds, data.supplier_id]); const handleAddItem = () => { onDataChange?.({ ...data, items: [ ...(data.items || []), { id: Date.now(), inventory_product_id: '', product_name: '', ordered_quantity: 1, unit_price: 0, unit_of_measure: 'kg', subtotal: 0, }, ], }); }; const handleUpdateItem = (index: number, field: string, value: any) => { const updated = (data.items || []).map((item: any, i: number) => { if (i === index) { const newItem = { ...item, [field]: value }; if (field === 'inventory_product_id') { const product = ingredientsData.find((p: any) => p.id === value); if (product) { newItem.product_name = product.name; newItem.unit_price = product.last_purchase_price || product.average_cost || 0; newItem.unit_of_measure = product.unit_of_measure; } } if (field === 'ordered_quantity' || field === 'unit_price' || field === 'inventory_product_id') { newItem.subtotal = (newItem.ordered_quantity || 0) * (newItem.unit_price || 0); } return newItem; } return item; }); onDataChange?.({ ...data, items: updated }); }; const handleRemoveItem = (index: number) => { onDataChange?.({ ...data, items: (data.items || []).filter((_: any, i: number) => i !== index) }); }; const calculateTotal = () => { return (data.items || []).reduce((sum: number, item: any) => sum + (item.subtotal || 0), 0); }; const unitOptions = [ { value: 'kg', label: t('purchaseOrder.orderItems.units.kg') }, { value: 'g', label: t('purchaseOrder.orderItems.units.g') }, { value: 'l', label: t('purchaseOrder.orderItems.units.l') }, { value: 'ml', label: t('purchaseOrder.orderItems.units.ml') }, { value: 'units', label: t('purchaseOrder.orderItems.units.units') }, { value: 'boxes', label: t('purchaseOrder.orderItems.units.boxes') }, { value: 'bags', label: t('purchaseOrder.orderItems.units.bags') }, ]; return (

{t('purchaseOrder.orderItems.titleHeader')}

{t('purchaseOrder.orderItems.supplier')}: {data.supplier?.name || 'N/A'}

{isLoadingIngredients || isLoadingSupplierProducts ? (
{t('purchaseOrder.orderItems.loadingProducts')}
) : ( <>
{ingredientsData.length === 0 && (
{t('purchaseOrder.orderItems.noIngredientsForSupplier')}
)} {(data.items || []).length === 0 ? (

{t('purchaseOrder.orderItems.noProducts')}

{t('purchaseOrder.orderItems.clickToAdd')}

) : (
{(data.items || []).map((item: any, index: number) => (
{t('purchaseOrder.orderItems.productNumber', { number: index + 1 })}
handleUpdateItem(index, 'ordered_quantity', parseFloat(e.target.value) || 0) } className="w-full px-3 py-2 text-sm border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)]" min="0" step="0.01" />
handleUpdateItem(index, 'unit_price', parseFloat(e.target.value) || 0)} className="w-full px-3 py-2 text-sm border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)]" min="0" step="0.01" />
{t('purchaseOrder.orderItems.subtotal')}: {currencySymbol}{item.subtotal.toFixed(2)}
))}
)} {(data.items || []).length > 0 && (
{t('purchaseOrder.orderItems.total')}: {currencySymbol}{calculateTotal().toFixed(2)}
)}
)}
); }; // Step 3: Order Details const OrderDetailsStep: React.FC = ({ dataRef, onDataChange }) => { const data = dataRef?.current || {}; const { t } = useTranslation(['wizards', 'procurement']); const getValue = (field: string, defaultValue: any = '') => { return data[field] ?? defaultValue; }; const handleFieldChange = (updates: Record) => { onDataChange?.({ ...data, ...updates }); }; const priorityOptions = [ { value: 'low', label: t('purchaseOrder.orderDetails.priorityOptions.low') }, { value: 'normal', label: t('purchaseOrder.orderDetails.priorityOptions.normal') }, { value: 'high', label: t('purchaseOrder.orderDetails.priorityOptions.high') }, { value: 'critical', label: t('purchaseOrder.orderDetails.priorityOptions.critical') }, ]; return (

{t('purchaseOrder.orderDetails.title')}

{t('purchaseOrder.orderDetails.description')}

handleFieldChange({ required_delivery_date: e.target.value })} min={new Date().toISOString().split('T')[0]} className="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)]" />