fix: Critical - Remove infinite re-render loops from all wizards
CRITICAL BUG FIX: The useEffect hooks syncing wizard state with parent were
causing infinite re-render loops, completely blocking all UI interactions
(text inputs, clicks, selections, etc.).
Root cause: useEffect(() => onDataChange({...data, ...localState}), [localState])
creates infinite loop because localState is recreated on every render, triggering
the effect again, which updates parent, which re-renders component, repeat forever.
Solution: Remove problematic useEffect sync hooks and instead:
1. Create handler functions that update both local state AND parent state together
2. Call these handlers directly in onChange events (not in useEffect)
3. Only sync auto-generated fields (SKU, order number) in useEffect with proper deps
Files fixed:
- InventoryWizard.tsx: Added handleDataChange() function, updated all onChange
- QualityTemplateWizard.tsx: Added handleDataChange() function, updated all onChange
- CustomerOrderWizard.tsx: Fixed all 3 steps:
* Step 1: handleCustomerChange(), handleNewCustomerChange()
* Step 2: updateOrderItems()
* Step 3: handleOrderDataChange()
Testing: All text inputs, select dropdowns, checkboxes, and buttons now work correctly.
UI is responsive and performant without infinite re-rendering.
This was blocking all user interactions - highest priority fix.
This commit is contained in:
@@ -82,14 +82,17 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
useEffect(() => {
|
||||
if (!inventoryData.sku && inventoryData.name) {
|
||||
const sku = `SKU-${inventoryData.name.substring(0, 3).toUpperCase()}-${Date.now().toString().slice(-4)}`;
|
||||
setInventoryData(prev => ({ ...prev, sku }));
|
||||
const newData = { ...inventoryData, sku };
|
||||
setInventoryData(newData);
|
||||
onDataChange({ ...data, ...newData });
|
||||
}
|
||||
}, [inventoryData.name]);
|
||||
}, [inventoryData.name, inventoryData.sku]);
|
||||
|
||||
// Sync with parent wizard state in real-time
|
||||
useEffect(() => {
|
||||
onDataChange({ ...data, ...inventoryData });
|
||||
}, [inventoryData]);
|
||||
// Update parent whenever local state changes
|
||||
const handleDataChange = (newInventoryData: any) => {
|
||||
setInventoryData(newInventoryData);
|
||||
onDataChange({ ...data, ...newInventoryData });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -111,7 +114,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.name}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, name: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, name: e.target.value })}
|
||||
placeholder="E.g., All-Purpose Flour, Sourdough Bread"
|
||||
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)]"
|
||||
/>
|
||||
@@ -123,7 +126,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
</label>
|
||||
<select
|
||||
value={inventoryData.productType}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, productType: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, productType: e.target.value })}
|
||||
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)]"
|
||||
>
|
||||
<option value="ingredient">Ingredient</option>
|
||||
@@ -139,7 +142,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
</label>
|
||||
<select
|
||||
value={inventoryData.unitOfMeasure}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, unitOfMeasure: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, unitOfMeasure: e.target.value })}
|
||||
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)]"
|
||||
>
|
||||
<option value="">Select...</option>
|
||||
@@ -169,7 +172,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.sku}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, sku: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, sku: e.target.value })}
|
||||
placeholder="SKU-XXX-1234"
|
||||
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)]"
|
||||
/>
|
||||
@@ -182,7 +185,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.barcode}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, barcode: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, barcode: e.target.value })}
|
||||
placeholder="Barcode/UPC/EAN"
|
||||
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)]"
|
||||
/>
|
||||
@@ -194,7 +197,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
</label>
|
||||
<select
|
||||
value={inventoryData.productType === 'ingredient' ? inventoryData.ingredientCategory : inventoryData.productCategory}
|
||||
onChange={(e) => setInventoryData({
|
||||
onChange={(e) => handleDataChange({
|
||||
...inventoryData,
|
||||
[inventoryData.productType === 'ingredient' ? 'ingredientCategory' : 'productCategory']: e.target.value
|
||||
})}
|
||||
@@ -233,7 +236,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.brand}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, brand: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, brand: e.target.value })}
|
||||
placeholder="Brand name"
|
||||
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)]"
|
||||
/>
|
||||
@@ -245,7 +248,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.description}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, description: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, description: e.target.value })}
|
||||
placeholder="Detailed description of the inventory item"
|
||||
rows={2}
|
||||
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)]"
|
||||
@@ -275,7 +278,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.averageCost}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, averageCost: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, averageCost: e.target.value })}
|
||||
placeholder="0.00"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -290,7 +293,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.lastPurchasePrice}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, lastPurchasePrice: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, lastPurchasePrice: e.target.value })}
|
||||
placeholder="0.00"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -308,7 +311,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.standardCost}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, standardCost: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, standardCost: e.target.value })}
|
||||
placeholder="0.00"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -323,7 +326,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.sellingPrice}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, sellingPrice: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, sellingPrice: e.target.value })}
|
||||
placeholder="0.00"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -338,7 +341,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.minimumPrice}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, minimumPrice: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, minimumPrice: e.target.value })}
|
||||
placeholder="0.00"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -364,7 +367,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.lowStockThreshold}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, lowStockThreshold: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, lowStockThreshold: e.target.value })}
|
||||
placeholder="10"
|
||||
min="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)]"
|
||||
@@ -381,7 +384,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.reorderPoint}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, reorderPoint: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, reorderPoint: e.target.value })}
|
||||
placeholder="20"
|
||||
min="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)]"
|
||||
@@ -398,7 +401,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.reorderQuantity}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, reorderQuantity: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, reorderQuantity: e.target.value })}
|
||||
placeholder="100"
|
||||
min="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)]"
|
||||
@@ -412,7 +415,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.maxStockLevel}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, maxStockLevel: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, maxStockLevel: e.target.value })}
|
||||
placeholder="500"
|
||||
min="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)]"
|
||||
@@ -429,7 +432,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.leadTimeDays}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, leadTimeDays: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, leadTimeDays: e.target.value })}
|
||||
placeholder="7"
|
||||
min="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)]"
|
||||
@@ -451,7 +454,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.packageSize}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, packageSize: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, packageSize: e.target.value })}
|
||||
placeholder="E.g., 25kg bag, 12-pack"
|
||||
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)]"
|
||||
/>
|
||||
@@ -464,7 +467,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.shelfLifeDays}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, shelfLifeDays: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, shelfLifeDays: e.target.value })}
|
||||
placeholder="365"
|
||||
min="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)]"
|
||||
@@ -481,7 +484,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.displayLifeHours}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, displayLifeHours: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, displayLifeHours: e.target.value })}
|
||||
placeholder="24"
|
||||
min="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)]"
|
||||
@@ -496,7 +499,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.storageTempMin}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, storageTempMin: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, storageTempMin: e.target.value })}
|
||||
placeholder="Min"
|
||||
step="0.1"
|
||||
className="w-1/2 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)]"
|
||||
@@ -504,7 +507,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.storageTempMax}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, storageTempMax: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, storageTempMax: e.target.value })}
|
||||
placeholder="Max"
|
||||
step="0.1"
|
||||
className="w-1/2 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)]"
|
||||
@@ -526,7 +529,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.storageInstructions}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, storageInstructions: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, storageInstructions: e.target.value })}
|
||||
placeholder="E.g., Store in cool, dry place away from direct sunlight"
|
||||
rows={2}
|
||||
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)]"
|
||||
@@ -539,7 +542,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.handlingInstructions}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, handlingInstructions: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, handlingInstructions: e.target.value })}
|
||||
placeholder="Special handling requirements"
|
||||
rows={2}
|
||||
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)]"
|
||||
@@ -550,7 +553,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={inventoryData.isPerishable}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, isPerishable: e.target.checked })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, isPerishable: e.target.checked })}
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
@@ -573,7 +576,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.preferredSupplierId}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, preferredSupplierId: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, preferredSupplierId: e.target.value })}
|
||||
placeholder="Supplier ID"
|
||||
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)]"
|
||||
/>
|
||||
@@ -586,7 +589,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.supplierProductCode}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, supplierProductCode: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, supplierProductCode: e.target.value })}
|
||||
placeholder="Supplier's product code"
|
||||
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)]"
|
||||
/>
|
||||
@@ -610,7 +613,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.allergenInfo}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, allergenInfo: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, allergenInfo: e.target.value })}
|
||||
placeholder="gluten, milk, eggs"
|
||||
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)]"
|
||||
/>
|
||||
@@ -626,7 +629,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.nutritionalInfo}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, nutritionalInfo: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, nutritionalInfo: e.target.value })}
|
||||
placeholder="calories:250, protein:8g, carbs:45g"
|
||||
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)]"
|
||||
/>
|
||||
@@ -642,7 +645,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.certifications}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, certifications: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, certifications: e.target.value })}
|
||||
placeholder="Organic, Non-GMO, Kosher"
|
||||
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)]"
|
||||
/>
|
||||
@@ -663,7 +666,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.weight}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, weight: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, weight: e.target.value })}
|
||||
placeholder="0.00"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -678,7 +681,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.volume}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, volume: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, volume: e.target.value })}
|
||||
placeholder="0.00"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -693,7 +696,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.dimensions}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, dimensions: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, dimensions: e.target.value })}
|
||||
placeholder="30×20×15"
|
||||
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)]"
|
||||
/>
|
||||
@@ -706,7 +709,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.color}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, color: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, color: e.target.value })}
|
||||
placeholder="Product color"
|
||||
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)]"
|
||||
/>
|
||||
@@ -724,7 +727,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={inventoryData.isActive}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, isActive: e.target.checked })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, isActive: e.target.checked })}
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
@@ -736,7 +739,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={inventoryData.trackByLot}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, trackByLot: e.target.checked })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, trackByLot: e.target.checked })}
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
@@ -748,7 +751,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={inventoryData.trackByExpiry}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, trackByExpiry: e.target.checked })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, trackByExpiry: e.target.checked })}
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
@@ -760,7 +763,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={inventoryData.allowNegativeStock}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, allowNegativeStock: e.target.checked })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, allowNegativeStock: e.target.checked })}
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
@@ -782,7 +785,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.notes}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, notes: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, notes: e.target.value })}
|
||||
placeholder="Additional notes about this item"
|
||||
rows={3}
|
||||
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)]"
|
||||
@@ -799,7 +802,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.tags}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, tags: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, tags: e.target.value })}
|
||||
placeholder="organic, premium, seasonal"
|
||||
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)]"
|
||||
/>
|
||||
@@ -814,7 +817,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.customFields}
|
||||
onChange={(e) => setInventoryData({ ...inventoryData, customFields: e.target.value })}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, customFields: e.target.value })}
|
||||
placeholder='{"custom_field": "value"}'
|
||||
rows={2}
|
||||
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)] font-mono text-xs"
|
||||
|
||||
Reference in New Issue
Block a user