import React, { useState, useEffect } from 'react'; import { WizardStep, WizardStepProps } from '../../../ui/WizardModal/WizardModal'; import { AdvancedOptionsSection } from '../../../ui/AdvancedOptionsSection'; import Tooltip from '../../../ui/Tooltip/Tooltip'; import { Users, Plus, Package, Truck, CreditCard, Search, Calendar, MapPin, Info, Loader2, CheckCircle2, } from 'lucide-react'; import { useTenant } from '../../../../stores/tenant.store'; import OrdersService from '../../../../api/services/orders'; import { inventoryService } from '../../../../api/services/inventory'; import { ProductType } from '../../../../api/types/inventory'; interface WizardDataProps extends WizardStepProps { data: Record; onDataChange: (data: Record) => void; } // Step 1: Customer Selection const CustomerSelectionStep: React.FC = ({ data, onDataChange }) => { const { currentTenant } = useTenant(); const [searchQuery, setSearchQuery] = useState(''); const [showNewCustomerForm, setShowNewCustomerForm] = useState(false); const [selectedCustomer, setSelectedCustomer] = useState(data.customer || null); const [customers, setCustomers] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [newCustomer, setNewCustomer] = useState({ name: data.newCustomerName || '', type: data.newCustomerType || 'retail', phone: data.newCustomerPhone || '', email: data.newCustomerEmail || '', }); useEffect(() => { fetchCustomers(); }, []); // Sync with parent wizard state in real-time useEffect(() => { onDataChange({ ...data, customer: selectedCustomer, showNewCustomerForm, newCustomerName: newCustomer.name, newCustomerType: newCustomer.type, newCustomerPhone: newCustomer.phone, newCustomerEmail: newCustomer.email, }); }, [selectedCustomer, showNewCustomerForm, newCustomer]); const fetchCustomers = async () => { if (!currentTenant?.id) return; setLoading(true); setError(null); try { const result = await OrdersService.getCustomers({ tenant_id: currentTenant.id, active_only: true, }); setCustomers(result); } catch (err: any) { console.error('Error loading customers:', err); setError('Error loading customers'); } finally { setLoading(false); } }; const filteredCustomers = customers.filter((customer) => customer.name.toLowerCase().includes(searchQuery.toLowerCase()) ); const handleSelectCustomer = (customer: any) => { setSelectedCustomer(customer); setShowNewCustomerForm(false); }; return (

Select Customer

Search for an existing customer or create a new one

{error && (
{error}
)} {loading ? (
Loading customers...
) : !showNewCustomerForm ? ( <> {/* Search Bar */}
setSearchQuery(e.target.value)} placeholder="Search customer by name..." 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)]" />
{/* Customer List */}
{filteredCustomers.length === 0 ? (

No customers found

Try a different search term

) : ( filteredCustomers.map((customer) => ( )) )}
{/* Create New Customer Button */} ) : ( <> {/* New Customer Form */}

New Customer

setNewCustomer({ ...newCustomer, name: e.target.value })} placeholder="E.g., The Mill Restaurant" 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)]" />
setNewCustomer({ ...newCustomer, phone: e.target.value })} placeholder="+34 123 456 789" 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)]" />
setNewCustomer({ ...newCustomer, email: e.target.value })} placeholder="contact@restaurant.com" 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)]" />
)}
); }; // Step 2: Order Items const OrderItemsStep: React.FC = ({ data, onDataChange }) => { const { currentTenant } = useTenant(); const [orderItems, setOrderItems] = useState(data.orderItems || []); const [products, setProducts] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); useEffect(() => { fetchProducts(); }, []); // Sync with parent wizard state in real-time useEffect(() => { const totalAmount = orderItems.reduce((sum: number, item: any) => sum + (item.subtotal || 0), 0); onDataChange({ ...data, orderItems, totalAmount }); }, [orderItems]); const fetchProducts = async () => { if (!currentTenant?.id) return; setLoading(true); setError(null); try { const allIngredients = await inventoryService.getIngredients(currentTenant.id); const finishedProducts = allIngredients.filter( (ingredient) => ingredient.product_type === ProductType.FINISHED_PRODUCT ); setProducts(finishedProducts); } catch (err: any) { console.error('Error loading products:', err); setError('Error loading products'); } finally { setLoading(false); } }; const handleAddItem = () => { setOrderItems([ ...orderItems, { id: Date.now(), productId: '', productName: '', quantity: 1, unitPrice: 0, customRequirements: '', subtotal: 0, unitOfMeasure: 'units', }, ]); }; const handleUpdateItem = (index: number, field: string, value: any) => { const updated = orderItems.map((item: any, i: number) => { if (i === index) { const newItem = { ...item, [field]: value }; if (field === 'productId') { const product = products.find((p) => p.id === value); if (product) { newItem.productName = product.name; newItem.unitPrice = product.average_cost || product.last_purchase_price || 0; newItem.unitOfMeasure = product.unit_of_measure; } } if (field === 'quantity' || field === 'unitPrice' || field === 'productId') { newItem.subtotal = (newItem.quantity || 0) * (newItem.unitPrice || 0); } return newItem; } return item; }); setOrderItems(updated); }; const handleRemoveItem = (index: number) => { setOrderItems(orderItems.filter((_: any, i: number) => i !== index)); }; const calculateTotal = () => { return orderItems.reduce((sum: number, item: any) => sum + (item.subtotal || 0), 0); }; return (

Order Items

Customer: {data.customer?.name || 'New Customer'}

{error && (
{error}
)} {loading ? (
Loading products...
) : ( <>
{orderItems.length === 0 ? (

No products in order

Click "Add Product" to start

) : (
{orderItems.map((item: any, index: number) => (
Product #{index + 1}
handleUpdateItem(index, '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="1" />
handleUpdateItem(index, 'unitPrice', 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, 'customRequirements', e.target.value)} placeholder="E.g., No nuts, extra chocolate..." 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)]" />
Subtotal: €{item.subtotal.toFixed(2)}
))}
)} {orderItems.length > 0 && (
Order Total: €{calculateTotal().toFixed(2)}
)}
)}
); }; // Step 3: Delivery & Payment with ALL fields const DeliveryPaymentStep: React.FC = ({ data, onDataChange }) => { const [orderData, setOrderData] = useState({ // Required fields requestedDeliveryDate: data.requestedDeliveryDate || '', orderNumber: data.orderNumber || '', // Basic order info orderType: data.orderType || 'standard', priority: data.priority || 'normal', status: data.status || 'pending', // Delivery fields deliveryMethod: data.deliveryMethod || 'pickup', deliveryAddress: data.deliveryAddress || '', deliveryInstructions: data.deliveryInstructions || '', deliveryContactName: data.deliveryContactName || '', deliveryContactPhone: data.deliveryContactPhone || '', deliveryTimeWindow: data.deliveryTimeWindow || '', deliveryFee: data.deliveryFee || '', // Payment fields paymentMethod: data.paymentMethod || 'invoice', paymentTerms: data.paymentTerms || 'net_30', paymentStatus: data.paymentStatus || 'pending', paymentDueDate: data.paymentDueDate || '', // Pricing fields subtotalAmount: data.subtotalAmount || '', taxAmount: data.taxAmount || '', discountPercentage: data.discountPercentage || '', discountAmount: data.discountAmount || '', shippingCost: data.shippingCost || '', // Production & scheduling productionStartDate: data.productionStartDate || '', productionDueDate: data.productionDueDate || '', productionBatchNumber: data.productionBatchNumber || '', productionNotes: data.productionNotes || '', // Fulfillment actualDeliveryDate: data.actualDeliveryDate || '', pickupLocation: data.pickupLocation || '', shippingTrackingNumber: data.shippingTrackingNumber || '', shippingCarrier: data.shippingCarrier || '', // Source & channel orderSource: data.orderSource || 'manual', salesChannel: data.salesChannel || 'direct', salesRepId: data.salesRepId || '', // Communication customerPurchaseOrder: data.customerPurchaseOrder || '', internalNotes: data.internalNotes || '', customerNotes: data.customerNotes || '', specialInstructions: data.specialInstructions || '', // Notifications notifyCustomerOnStatusChange: data.notifyCustomerOnStatusChange ?? true, notifyCustomerOnDelivery: data.notifyCustomerOnDelivery ?? true, customerNotificationEmail: data.customerNotificationEmail || '', customerNotificationPhone: data.customerNotificationPhone || '', // Quality & requirements qualityCheckRequired: data.qualityCheckRequired ?? false, qualityCheckStatus: data.qualityCheckStatus || '', packagingInstructions: data.packagingInstructions || '', labelingRequirements: data.labelingRequirements || '', // Advanced options isRecurring: data.isRecurring ?? false, recurringSchedule: data.recurringSchedule || '', parentOrderId: data.parentOrderId || '', relatedOrderIds: data.relatedOrderIds || '', tags: data.tags || '', metadata: data.metadata || '', }); // Auto-generate order number if not provided useEffect(() => { if (!orderData.orderNumber) { const orderNum = `ORD-${Date.now().toString().slice(-8)}`; setOrderData(prev => ({ ...prev, orderNumber: orderNum })); } }, []); // Sync with parent wizard state in real-time useEffect(() => { onDataChange({ ...data, ...orderData }); }, [orderData]); return (

Delivery & Payment Details

Configure delivery, payment, and order details

{/* Required Fields */}
setOrderData({ ...orderData, requestedDeliveryDate: 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)]" />
setOrderData({ ...orderData, orderNumber: e.target.value })} placeholder="ORD-12345678" 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)]" />
{/* Basic Order Info */}

Basic Order Information

{/* Delivery Details */}

Delivery Details

{(orderData.deliveryMethod === 'delivery' || orderData.deliveryMethod === 'shipping') && (