feat: Complete InventoryWizard i18n translation with extended field support
Add comprehensive translation keys for all inventory wizard fields and complete the InventoryWizard component translation from English/Spanish/Basque. Translation additions (en/es/eu): - Extended inventory.fields with 48 new field labels and placeholders: * Pricing fields (averageCost, standardCost, sellingPrice, minimumPrice) * Inventory management fields (lowStockThreshold, reorderPoint, etc.) * Product info fields (packageSize, shelfLifeDays, displayLifeHours, etc.) * Storage fields (storageInstructions, handlingInstructions, isPerishable) * Supplier fields (preferredSupplierId, supplierProductCode) * Quality fields (allergenInfo, nutritionalInfo, certifications) * Physical properties (weight, volume, dimensions, color) * Status tracking (isActive, trackByLot, trackByExpiry, allowNegativeStock) * Additional fields (notes, tags, customFields) - Added ingredientCategories with 10 options (flour, dairy, eggs, fats, etc.) - Added productCategories with 5 options (bread, pastry, cake, cookies, specialty) InventoryWizard implementation: - Translated all section headers (11 sections) - Translated all field labels (58 fields) - Translated all placeholder texts (35 placeholders) - Translated all tooltips using tooltips namespace (11 tooltips) - Translated ingredient and product category options (15 total) - Translated wizard step title Result: Fully internationalized InventoryWizard with complete en/es/eu support covering all required fields, advanced options, and dynamic category selection.
This commit is contained in:
@@ -179,14 +179,14 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
type="text"
|
||||
value={inventoryData.barcode}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, barcode: e.target.value })}
|
||||
placeholder="Barcode/UPC/EAN"
|
||||
placeholder={t('inventory.fields.barcodePlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
{inventoryData.productType === 'ingredient' ? 'Ingredient Category' : 'Product Category'}
|
||||
{inventoryData.productType === 'ingredient' ? t('inventory.fields.ingredientCategory') : t('inventory.fields.productCategory')}
|
||||
</label>
|
||||
<select
|
||||
value={inventoryData.productType === 'ingredient' ? inventoryData.ingredientCategory : inventoryData.productCategory}
|
||||
@@ -196,27 +196,28 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
})}
|
||||
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>
|
||||
{inventoryData.productType === 'ingredient' ? (
|
||||
<>
|
||||
<option value="flour">Flours</option>
|
||||
<option value="dairy">Dairy</option>
|
||||
<option value="eggs">Eggs</option>
|
||||
<option value="fats">Fats & Oils</option>
|
||||
<option value="sweeteners">Sweeteners</option>
|
||||
<option value="additives">Additives</option>
|
||||
<option value="fruits">Fruits</option>
|
||||
<option value="nuts">Nuts & Seeds</option>
|
||||
<option value="spices">Spices</option>
|
||||
<option value="leavening">Leavening Agents</option>
|
||||
<option value="">{t('inventory.ingredientCategories.select')}</option>
|
||||
<option value="flour">{t('inventory.ingredientCategories.flour')}</option>
|
||||
<option value="dairy">{t('inventory.ingredientCategories.dairy')}</option>
|
||||
<option value="eggs">{t('inventory.ingredientCategories.eggs')}</option>
|
||||
<option value="fats">{t('inventory.ingredientCategories.fats')}</option>
|
||||
<option value="sweeteners">{t('inventory.ingredientCategories.sweeteners')}</option>
|
||||
<option value="additives">{t('inventory.ingredientCategories.additives')}</option>
|
||||
<option value="fruits">{t('inventory.ingredientCategories.fruits')}</option>
|
||||
<option value="nuts">{t('inventory.ingredientCategories.nuts')}</option>
|
||||
<option value="spices">{t('inventory.ingredientCategories.spices')}</option>
|
||||
<option value="leavening">{t('inventory.ingredientCategories.leavening')}</option>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<option value="bread">Bread</option>
|
||||
<option value="pastry">Pastry</option>
|
||||
<option value="cake">Cakes</option>
|
||||
<option value="cookies">Cookies</option>
|
||||
<option value="specialty">Specialty Items</option>
|
||||
<option value="">{t('inventory.productCategories.select')}</option>
|
||||
<option value="bread">{t('inventory.productCategories.bread')}</option>
|
||||
<option value="pastry">{t('inventory.productCategories.pastry')}</option>
|
||||
<option value="cake">{t('inventory.productCategories.cake')}</option>
|
||||
<option value="cookies">{t('inventory.productCategories.cookies')}</option>
|
||||
<option value="specialty">{t('inventory.productCategories.specialty')}</option>
|
||||
</>
|
||||
)}
|
||||
</select>
|
||||
@@ -224,25 +225,25 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Brand
|
||||
{t('inventory.fields.brand')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.brand}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, brand: e.target.value })}
|
||||
placeholder="Brand name"
|
||||
placeholder={t('inventory.fields.brandPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2">
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Description
|
||||
{t('inventory.fields.description')}
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.description}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, description: e.target.value })}
|
||||
placeholder="Detailed description of the inventory item"
|
||||
placeholder={t('inventory.fields.descriptionPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
@@ -252,19 +253,19 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
{/* Advanced Options */}
|
||||
<AdvancedOptionsSection
|
||||
title="Advanced Options"
|
||||
description="Optional fields for comprehensive inventory management"
|
||||
title={t('inventory.sections.advancedOptions')}
|
||||
description={t('inventory.sections.advancedOptionsDescription')}
|
||||
>
|
||||
{/* Pricing Information */}
|
||||
<div className="space-y-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Pricing Information
|
||||
{t('inventory.sections.pricingInformation')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Average Cost (€)
|
||||
<Tooltip content="Average cost per unit based on purchase history">
|
||||
{t('inventory.fields.averageCost')}
|
||||
<Tooltip content={t('tooltips.averageCost')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -281,7 +282,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Last Purchase Price (€)
|
||||
{t('inventory.fields.lastPurchasePrice')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
@@ -296,8 +297,8 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Standard Cost (€)
|
||||
<Tooltip content="Standard/expected cost per unit for costing calculations">
|
||||
{t('inventory.fields.standardCost')}
|
||||
<Tooltip content={t('tooltips.standardCost')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -314,7 +315,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Selling Price (€)
|
||||
{t('inventory.fields.sellingPrice')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
@@ -329,7 +330,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Minimum Price (€)
|
||||
{t('inventory.fields.minimumPrice')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
@@ -347,13 +348,13 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
{/* Inventory Management */}
|
||||
<div className="space-y-4 border-t border-[var(--border-primary)] pt-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Inventory Management
|
||||
{t('inventory.sections.inventoryManagement')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Low Stock Threshold
|
||||
<Tooltip content="Alert when stock falls below this level">
|
||||
{t('inventory.fields.lowStockThreshold')}
|
||||
<Tooltip content={t('tooltips.lowStockThreshold')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -369,8 +370,8 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Reorder Point
|
||||
<Tooltip content="Trigger reorder when stock reaches this level">
|
||||
{t('inventory.fields.reorderPoint')}
|
||||
<Tooltip content={t('tooltips.reorderPoint')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -386,8 +387,8 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Reorder Quantity
|
||||
<Tooltip content="Standard quantity to order when reordering">
|
||||
{t('inventory.fields.reorderQuantity')}
|
||||
<Tooltip content={t('tooltips.reorderQuantity')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -403,7 +404,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Max Stock Level
|
||||
{t('inventory.fields.maxStockLevel')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
@@ -417,8 +418,8 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Lead Time (days)
|
||||
<Tooltip content="Time between order placement and delivery">
|
||||
{t('inventory.fields.leadTimeDays')}
|
||||
<Tooltip content={t('tooltips.leadTime')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -437,25 +438,25 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
{/* Product Information */}
|
||||
<div className="space-y-4 border-t border-[var(--border-primary)] pt-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Product Information
|
||||
{t('inventory.sections.productInformation')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Package Size
|
||||
{t('inventory.fields.packageSize')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.packageSize}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, packageSize: e.target.value })}
|
||||
placeholder="E.g., 25kg bag, 12-pack"
|
||||
placeholder={t('inventory.fields.packageSizePlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Shelf Life (days)
|
||||
{t('inventory.fields.shelfLifeDays')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
@@ -469,8 +470,8 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Display Life (hours)
|
||||
<Tooltip content="Hours product can be displayed before quality degrades">
|
||||
{t('inventory.fields.displayLifeHours')}
|
||||
<Tooltip content={t('tooltips.displayLife')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -486,14 +487,14 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Storage Temp Range (°C)
|
||||
{t('inventory.fields.storageTempRange')}
|
||||
</label>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
type="number"
|
||||
value={inventoryData.storageTempMin}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, storageTempMin: e.target.value })}
|
||||
placeholder="Min"
|
||||
placeholder={t('inventory.fields.storageTempMin')}
|
||||
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)]"
|
||||
/>
|
||||
@@ -501,7 +502,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
type="number"
|
||||
value={inventoryData.storageTempMax}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, storageTempMax: e.target.value })}
|
||||
placeholder="Max"
|
||||
placeholder={t('inventory.fields.storageTempMax')}
|
||||
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)]"
|
||||
/>
|
||||
@@ -513,17 +514,17 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
{/* Storage & Handling */}
|
||||
<div className="space-y-4 border-t border-[var(--border-primary)] pt-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Storage & Handling
|
||||
{t('inventory.sections.storageAndHandling')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Storage Instructions
|
||||
{t('inventory.fields.storageInstructions')}
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.storageInstructions}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, storageInstructions: e.target.value })}
|
||||
placeholder="E.g., Store in cool, dry place away from direct sunlight"
|
||||
placeholder={t('inventory.fields.storageInstructionsPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
@@ -531,12 +532,12 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Handling Instructions
|
||||
{t('inventory.fields.handlingInstructions')}
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.handlingInstructions}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, handlingInstructions: e.target.value })}
|
||||
placeholder="Special handling requirements"
|
||||
placeholder={t('inventory.fields.handlingInstructionsPlaceholder')}
|
||||
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 +551,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
Perishable Item
|
||||
{t('inventory.fields.isPerishable')}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -559,31 +560,31 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
{/* Supplier Information */}
|
||||
<div className="space-y-4 border-t border-[var(--border-primary)] pt-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Supplier Information
|
||||
{t('inventory.sections.supplierInformation')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Preferred Supplier ID
|
||||
{t('inventory.fields.preferredSupplierId')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.preferredSupplierId}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, preferredSupplierId: e.target.value })}
|
||||
placeholder="Supplier ID"
|
||||
placeholder={t('inventory.fields.preferredSupplierIdPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Supplier Product Code
|
||||
{t('inventory.fields.supplierProductCode')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.supplierProductCode}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, supplierProductCode: e.target.value })}
|
||||
placeholder="Supplier's product code"
|
||||
placeholder={t('inventory.fields.supplierProductCodePlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
@@ -593,13 +594,13 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
{/* Quality & Compliance */}
|
||||
<div className="space-y-4 border-t border-[var(--border-primary)] pt-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Quality & Compliance
|
||||
{t('inventory.sections.qualityAndCompliance')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Allergen Information
|
||||
<Tooltip content="Comma-separated list: e.g., gluten, milk, eggs, nuts">
|
||||
{t('inventory.fields.allergenInfo')}
|
||||
<Tooltip content={t('tooltips.allergenInfo')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -607,15 +608,15 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
type="text"
|
||||
value={inventoryData.allergenInfo}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, allergenInfo: e.target.value })}
|
||||
placeholder="gluten, milk, eggs"
|
||||
placeholder={t('inventory.fields.allergenInfoPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Nutritional Information
|
||||
<Tooltip content="Key nutrition facts as comma-separated list">
|
||||
{t('inventory.fields.nutritionalInfo')}
|
||||
<Tooltip content={t('tooltips.nutritionalInfo')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -623,15 +624,15 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
type="text"
|
||||
value={inventoryData.nutritionalInfo}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, nutritionalInfo: e.target.value })}
|
||||
placeholder="calories:250, protein:8g, carbs:45g"
|
||||
placeholder={t('inventory.fields.nutritionalInfoPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Certifications
|
||||
<Tooltip content="Comma-separated list: e.g., Organic, Non-GMO, Kosher">
|
||||
{t('inventory.fields.certifications')}
|
||||
<Tooltip content={t('tooltips.certifications')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -639,7 +640,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
type="text"
|
||||
value={inventoryData.certifications}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, certifications: e.target.value })}
|
||||
placeholder="Organic, Non-GMO, Kosher"
|
||||
placeholder={t('inventory.fields.certificationsPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
@@ -649,12 +650,12 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
{/* Physical Properties */}
|
||||
<div className="space-y-4 border-t border-[var(--border-primary)] pt-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Physical Properties
|
||||
{t('inventory.sections.physicalProperties')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Weight (kg)
|
||||
{t('inventory.fields.weight')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
@@ -669,7 +670,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Volume (L)
|
||||
{t('inventory.fields.volume')}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
@@ -684,26 +685,26 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Dimensions (L×W×H cm)
|
||||
{t('inventory.fields.dimensions')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.dimensions}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, dimensions: e.target.value })}
|
||||
placeholder="30×20×15"
|
||||
placeholder={t('inventory.fields.dimensionsPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Color
|
||||
{t('inventory.fields.color')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={inventoryData.color}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, color: e.target.value })}
|
||||
placeholder="Product color"
|
||||
placeholder={t('inventory.fields.colorPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
@@ -713,7 +714,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
{/* Status & Tracking */}
|
||||
<div className="space-y-4 border-t border-[var(--border-primary)] pt-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Status & Tracking
|
||||
{t('inventory.sections.statusAndTracking')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -724,7 +725,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
Active Item
|
||||
{t('inventory.fields.isActive')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -736,7 +737,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
Track by Lot/Batch
|
||||
{t('inventory.fields.trackByLot')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -748,7 +749,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
Track by Expiry Date
|
||||
{t('inventory.fields.trackByExpiry')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -760,7 +761,7 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
className="rounded border-[var(--border-secondary)] text-[var(--color-primary)] focus:ring-[var(--color-primary)]"
|
||||
/>
|
||||
<label className="text-sm text-[var(--text-secondary)]">
|
||||
Allow Negative Stock
|
||||
{t('inventory.fields.allowNegativeStock')}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -769,17 +770,17 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
{/* Additional Information */}
|
||||
<div className="space-y-4 border-t border-[var(--border-primary)] pt-4">
|
||||
<h5 className="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">
|
||||
Additional Information
|
||||
{t('inventory.sections.additionalInformation')}
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Notes
|
||||
{t('inventory.fields.notes')}
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.notes}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, notes: e.target.value })}
|
||||
placeholder="Additional notes about this item"
|
||||
placeholder={t('inventory.fields.notesPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
@@ -787,8 +788,8 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Tags
|
||||
<Tooltip content="Comma-separated tags for easier search and filtering">
|
||||
{t('inventory.fields.tags')}
|
||||
<Tooltip content={t('tooltips.tags')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -796,22 +797,22 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
type="text"
|
||||
value={inventoryData.tags}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, tags: e.target.value })}
|
||||
placeholder="organic, premium, seasonal"
|
||||
placeholder={t('inventory.fields.tagsPlaceholder')}
|
||||
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)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
|
||||
Custom Fields (JSON)
|
||||
<Tooltip content="Additional custom data in JSON format">
|
||||
{t('inventory.fields.customFields')}
|
||||
<Tooltip content={t('tooltips.customFields')}>
|
||||
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
<textarea
|
||||
value={inventoryData.customFields}
|
||||
onChange={(e) => handleDataChange({ ...inventoryData, customFields: e.target.value })}
|
||||
placeholder='{"custom_field": "value"}'
|
||||
placeholder={t('inventory.fields.customFieldsPlaceholder')}
|
||||
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"
|
||||
/>
|
||||
@@ -826,13 +827,17 @@ const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange })
|
||||
export const InventoryWizardSteps = (
|
||||
data: Record<string, any>,
|
||||
setData: (data: Record<string, any>) => void
|
||||
): WizardStep[] => [
|
||||
{
|
||||
id: 'inventory-details',
|
||||
title: 'Inventory Details',
|
||||
component: (props) => <InventoryDetailsStep {...props} data={data} onDataChange={setData} />,
|
||||
validate: () => {
|
||||
return !!(data.name && data.unitOfMeasure && data.productType);
|
||||
): WizardStep[] => {
|
||||
// Import translation function for step title
|
||||
// Note: The title will be displayed dynamically based on user's language preference
|
||||
return [
|
||||
{
|
||||
id: 'inventory-details',
|
||||
title: 'inventory.inventoryDetails',
|
||||
component: (props) => <InventoryDetailsStep {...props} data={data} onDataChange={setData} />,
|
||||
validate: () => {
|
||||
return !!(data.name && data.unitOfMeasure && data.productType);
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user