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);
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
};
|
||||
|
||||
@@ -27,7 +27,55 @@
|
||||
"brand": "Brand",
|
||||
"brandPlaceholder": "Brand name",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Detailed description of the inventory item"
|
||||
"descriptionPlaceholder": "Detailed description of the inventory item",
|
||||
"averageCost": "Average Cost (€)",
|
||||
"lastPurchasePrice": "Last Purchase Price (€)",
|
||||
"standardCost": "Standard Cost (€)",
|
||||
"sellingPrice": "Selling Price (€)",
|
||||
"minimumPrice": "Minimum Price (€)",
|
||||
"lowStockThreshold": "Low Stock Threshold",
|
||||
"reorderPoint": "Reorder Point",
|
||||
"reorderQuantity": "Reorder Quantity",
|
||||
"maxStockLevel": "Max Stock Level",
|
||||
"leadTimeDays": "Lead Time (days)",
|
||||
"packageSize": "Package Size",
|
||||
"packageSizePlaceholder": "E.g., 25kg bag, 12-pack",
|
||||
"shelfLifeDays": "Shelf Life (days)",
|
||||
"displayLifeHours": "Display Life (hours)",
|
||||
"storageTempRange": "Storage Temp Range (°C)",
|
||||
"storageTempMin": "Min",
|
||||
"storageTempMax": "Max",
|
||||
"storageInstructions": "Storage Instructions",
|
||||
"storageInstructionsPlaceholder": "E.g., Store in cool, dry place away from direct sunlight",
|
||||
"handlingInstructions": "Handling Instructions",
|
||||
"handlingInstructionsPlaceholder": "Special handling requirements",
|
||||
"isPerishable": "Perishable Item",
|
||||
"preferredSupplierId": "Preferred Supplier ID",
|
||||
"preferredSupplierIdPlaceholder": "Supplier ID",
|
||||
"supplierProductCode": "Supplier Product Code",
|
||||
"supplierProductCodePlaceholder": "Supplier's product code",
|
||||
"allergenInfo": "Allergen Information",
|
||||
"allergenInfoPlaceholder": "gluten, milk, eggs",
|
||||
"nutritionalInfo": "Nutritional Information",
|
||||
"nutritionalInfoPlaceholder": "calories:250, protein:8g, carbs:45g",
|
||||
"certifications": "Certifications",
|
||||
"certificationsPlaceholder": "Organic, Non-GMO, Kosher",
|
||||
"weight": "Weight (kg)",
|
||||
"volume": "Volume (L)",
|
||||
"dimensions": "Dimensions (L×W×H cm)",
|
||||
"dimensionsPlaceholder": "30×20×15",
|
||||
"color": "Color",
|
||||
"colorPlaceholder": "Product color",
|
||||
"isActive": "Active Item",
|
||||
"trackByLot": "Track by Lot/Batch",
|
||||
"trackByExpiry": "Track by Expiry Date",
|
||||
"allowNegativeStock": "Allow Negative Stock",
|
||||
"notes": "Notes",
|
||||
"notesPlaceholder": "Additional notes about this item",
|
||||
"tags": "Tags",
|
||||
"tagsPlaceholder": "organic, premium, seasonal",
|
||||
"customFields": "Custom Fields (JSON)",
|
||||
"customFieldsPlaceholder": "{\"custom_field\": \"value\"}"
|
||||
},
|
||||
"sections": {
|
||||
"basicInformation": "Basic Information",
|
||||
@@ -59,6 +107,27 @@
|
||||
"dozen": "Dozen",
|
||||
"lb": "Pounds (lb)",
|
||||
"oz": "Ounces (oz)"
|
||||
},
|
||||
"ingredientCategories": {
|
||||
"select": "Select...",
|
||||
"flour": "Flours",
|
||||
"dairy": "Dairy",
|
||||
"eggs": "Eggs",
|
||||
"fats": "Fats & Oils",
|
||||
"sweeteners": "Sweeteners",
|
||||
"additives": "Additives",
|
||||
"fruits": "Fruits",
|
||||
"nuts": "Nuts & Seeds",
|
||||
"spices": "Spices",
|
||||
"leavening": "Leavening Agents"
|
||||
},
|
||||
"productCategories": {
|
||||
"select": "Select...",
|
||||
"bread": "Bread",
|
||||
"pastry": "Pastry",
|
||||
"cake": "Cakes",
|
||||
"cookies": "Cookies",
|
||||
"specialty": "Specialty Items"
|
||||
}
|
||||
},
|
||||
"qualityTemplate": {
|
||||
|
||||
@@ -27,7 +27,55 @@
|
||||
"brand": "Marca",
|
||||
"brandPlaceholder": "Nombre de marca",
|
||||
"description": "Descripción",
|
||||
"descriptionPlaceholder": "Descripción detallada del artículo de inventario"
|
||||
"descriptionPlaceholder": "Descripción detallada del artículo de inventario",
|
||||
"averageCost": "Coste Promedio (€)",
|
||||
"lastPurchasePrice": "Último Precio de Compra (€)",
|
||||
"standardCost": "Coste Estándar (€)",
|
||||
"sellingPrice": "Precio de Venta (€)",
|
||||
"minimumPrice": "Precio Mínimo (€)",
|
||||
"lowStockThreshold": "Umbral de Stock Bajo",
|
||||
"reorderPoint": "Punto de Reorden",
|
||||
"reorderQuantity": "Cantidad de Reorden",
|
||||
"maxStockLevel": "Nivel Máximo de Stock",
|
||||
"leadTimeDays": "Tiempo de Entrega (días)",
|
||||
"packageSize": "Tamaño del Paquete",
|
||||
"packageSizePlaceholder": "Ej: bolsa de 25kg, paquete de 12",
|
||||
"shelfLifeDays": "Vida Útil (días)",
|
||||
"displayLifeHours": "Vida de Exhibición (horas)",
|
||||
"storageTempRange": "Rango de Temperatura de Almacenamiento (°C)",
|
||||
"storageTempMin": "Mín",
|
||||
"storageTempMax": "Máx",
|
||||
"storageInstructions": "Instrucciones de Almacenamiento",
|
||||
"storageInstructionsPlaceholder": "Ej: Almacenar en lugar fresco y seco alejado de la luz directa del sol",
|
||||
"handlingInstructions": "Instrucciones de Manejo",
|
||||
"handlingInstructionsPlaceholder": "Requisitos especiales de manejo",
|
||||
"isPerishable": "Artículo Perecedero",
|
||||
"preferredSupplierId": "ID de Proveedor Preferido",
|
||||
"preferredSupplierIdPlaceholder": "ID del Proveedor",
|
||||
"supplierProductCode": "Código de Producto del Proveedor",
|
||||
"supplierProductCodePlaceholder": "Código del producto del proveedor",
|
||||
"allergenInfo": "Información de Alérgenos",
|
||||
"allergenInfoPlaceholder": "gluten, leche, huevos",
|
||||
"nutritionalInfo": "Información Nutricional",
|
||||
"nutritionalInfoPlaceholder": "calorías:250, proteína:8g, carbohidratos:45g",
|
||||
"certifications": "Certificaciones",
|
||||
"certificationsPlaceholder": "Orgánico, Sin OGM, Kosher",
|
||||
"weight": "Peso (kg)",
|
||||
"volume": "Volumen (L)",
|
||||
"dimensions": "Dimensiones (L×A×A cm)",
|
||||
"dimensionsPlaceholder": "30×20×15",
|
||||
"color": "Color",
|
||||
"colorPlaceholder": "Color del producto",
|
||||
"isActive": "Artículo Activo",
|
||||
"trackByLot": "Rastrear por Lote/Batch",
|
||||
"trackByExpiry": "Rastrear por Fecha de Vencimiento",
|
||||
"allowNegativeStock": "Permitir Stock Negativo",
|
||||
"notes": "Notas",
|
||||
"notesPlaceholder": "Notas adicionales sobre este artículo",
|
||||
"tags": "Etiquetas",
|
||||
"tagsPlaceholder": "orgánico, premium, estacional",
|
||||
"customFields": "Campos Personalizados (JSON)",
|
||||
"customFieldsPlaceholder": "{\"campo_personalizado\": \"valor\"}"
|
||||
},
|
||||
"sections": {
|
||||
"basicInformation": "Información Básica",
|
||||
@@ -59,6 +107,27 @@
|
||||
"dozen": "Docena",
|
||||
"lb": "Libras (lb)",
|
||||
"oz": "Onzas (oz)"
|
||||
},
|
||||
"ingredientCategories": {
|
||||
"select": "Seleccionar...",
|
||||
"flour": "Harinas",
|
||||
"dairy": "Lácteos",
|
||||
"eggs": "Huevos",
|
||||
"fats": "Grasas y Aceites",
|
||||
"sweeteners": "Endulzantes",
|
||||
"additives": "Aditivos",
|
||||
"fruits": "Frutas",
|
||||
"nuts": "Nueces y Semillas",
|
||||
"spices": "Especias",
|
||||
"leavening": "Agentes Leudantes"
|
||||
},
|
||||
"productCategories": {
|
||||
"select": "Seleccionar...",
|
||||
"bread": "Pan",
|
||||
"pastry": "Pastelería",
|
||||
"cake": "Tortas",
|
||||
"cookies": "Galletas",
|
||||
"specialty": "Artículos Especiales"
|
||||
}
|
||||
},
|
||||
"qualityTemplate": {
|
||||
|
||||
@@ -27,7 +27,55 @@
|
||||
"brand": "Marka",
|
||||
"brandPlaceholder": "Marka izena",
|
||||
"description": "Deskribapena",
|
||||
"descriptionPlaceholder": "Inbentario elementuaren deskribapen zehatza"
|
||||
"descriptionPlaceholder": "Inbentario elementuaren deskribapen zehatza",
|
||||
"averageCost": "Batez Besteko Kostua (€)",
|
||||
"lastPurchasePrice": "Azken Erosketa Prezioa (€)",
|
||||
"standardCost": "Kostu Estandarra (€)",
|
||||
"sellingPrice": "Salmenta Prezioa (€)",
|
||||
"minimumPrice": "Gutxieneko Prezioa (€)",
|
||||
"lowStockThreshold": "Stock Baxuko Atalasea",
|
||||
"reorderPoint": "Berriro Eskatzeko Puntua",
|
||||
"reorderQuantity": "Berriro Eskatzeko Kantitatea",
|
||||
"maxStockLevel": "Gehienezko Stock Maila",
|
||||
"leadTimeDays": "Entrega Denbora (egunak)",
|
||||
"packageSize": "Pakete Tamaina",
|
||||
"packageSizePlaceholder": "Adib: 25kg zorroa, 12ko paketea",
|
||||
"shelfLifeDays": "Bizi Iraupena (egunak)",
|
||||
"displayLifeHours": "Erakusketaren Iraupena (orduak)",
|
||||
"storageTempRange": "Biltegiratze Tenperatura Eremua (°C)",
|
||||
"storageTempMin": "Gutx",
|
||||
"storageTempMax": "Geh",
|
||||
"storageInstructions": "Biltegiratze Jarraibideak",
|
||||
"storageInstructionsPlaceholder": "Adib: Gorde leku fresko eta lehorrean eguzki-argitik urrun",
|
||||
"handlingInstructions": "Maneiatzeko Jarraibideak",
|
||||
"handlingInstructionsPlaceholder": "Maneiatzeko eskakizun bereziak",
|
||||
"isPerishable": "Elementu Hondagarria",
|
||||
"preferredSupplierId": "Hornitzaile Hobetsiko ID",
|
||||
"preferredSupplierIdPlaceholder": "Hornitzailearen ID",
|
||||
"supplierProductCode": "Hornitzailearen Produktu Kodea",
|
||||
"supplierProductCodePlaceholder": "Hornitzailearen produktu kodea",
|
||||
"allergenInfo": "Alergenoen Informazioa",
|
||||
"allergenInfoPlaceholder": "glutena, esnea, arrautzak",
|
||||
"nutritionalInfo": "Nutrizio Informazioa",
|
||||
"nutritionalInfoPlaceholder": "kaloriak:250, proteina:8g, karbohidratoak:45g",
|
||||
"certifications": "Ziurtagiriak",
|
||||
"certificationsPlaceholder": "Organikoa, GMO gabea, Kosher",
|
||||
"weight": "Pisua (kg)",
|
||||
"volume": "Bolumena (L)",
|
||||
"dimensions": "Dimentsioak (L×Z×A cm)",
|
||||
"dimensionsPlaceholder": "30×20×15",
|
||||
"color": "Kolorea",
|
||||
"colorPlaceholder": "Produktuaren kolorea",
|
||||
"isActive": "Elementu Aktiboa",
|
||||
"trackByLot": "Lote/Batch-ren arabera jarraitu",
|
||||
"trackByExpiry": "Iraungitze Dataren arabera jarraitu",
|
||||
"allowNegativeStock": "Stock Negatiboa Baimendu",
|
||||
"notes": "Oharrak",
|
||||
"notesPlaceholder": "Elementu honi buruzko ohar gehigarriak",
|
||||
"tags": "Etiketak",
|
||||
"tagsPlaceholder": "organikoa, premium, denborakoa",
|
||||
"customFields": "Eremu Pertsonalizatuak (JSON)",
|
||||
"customFieldsPlaceholder": "{\"eremu_pertsonalizatua\": \"balioa\"}"
|
||||
},
|
||||
"sections": {
|
||||
"basicInformation": "Oinarrizko Informazioa",
|
||||
@@ -59,6 +107,27 @@
|
||||
"dozen": "Dozena",
|
||||
"lb": "Libratok (lb)",
|
||||
"oz": "Ontzak (oz)"
|
||||
},
|
||||
"ingredientCategories": {
|
||||
"select": "Hautatu...",
|
||||
"flour": "Irinak",
|
||||
"dairy": "Esnekiak",
|
||||
"eggs": "Arrautzak",
|
||||
"fats": "Gantzak eta Olioak",
|
||||
"sweeteners": "Gozo-gailuak",
|
||||
"additives": "Gehigarriak",
|
||||
"fruits": "Frutak",
|
||||
"nuts": "Fruitu Lehorrak eta Haziak",
|
||||
"spices": "Espezia",
|
||||
"leavening": "Altxatzeko Agenteak"
|
||||
},
|
||||
"productCategories": {
|
||||
"select": "Hautatu...",
|
||||
"bread": "Ogia",
|
||||
"pastry": "Gozogintzak",
|
||||
"cake": "Tartak",
|
||||
"cookies": "Galetak",
|
||||
"specialty": "Elementu Bereziak"
|
||||
}
|
||||
},
|
||||
"qualityTemplate": {
|
||||
|
||||
Reference in New Issue
Block a user