Files
bakery-ia/frontend/src/components/domain/unified-wizard/wizards/InventoryWizard.tsx
Claude ebabe4cd40 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.
2025-11-10 13:06:04 +00:00

844 lines
41 KiB
TypeScript

import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { WizardStep, WizardStepProps } from '../../../ui/WizardModal/WizardModal';
import { AdvancedOptionsSection } from '../../../ui/AdvancedOptionsSection';
import Tooltip from '../../../ui/Tooltip/Tooltip';
import { Info } from 'lucide-react';
interface WizardDataProps extends WizardStepProps {
data: Record<string, any>;
onDataChange: (data: Record<string, any>) => void;
}
// Single comprehensive step with all fields
const InventoryDetailsStep: React.FC<WizardDataProps> = ({ data, onDataChange }) => {
const { t } = useTranslation('wizards');
const [inventoryData, setInventoryData] = useState({
// Required fields
name: data.name || '',
unitOfMeasure: data.unitOfMeasure || '',
productType: data.productType || 'ingredient',
// Basic fields
sku: data.sku || '',
barcode: data.barcode || '',
ingredientCategory: data.ingredientCategory || '',
productCategory: data.productCategory || '',
description: data.description || '',
brand: data.brand || '',
// Pricing fields
averageCost: data.averageCost || '',
lastPurchasePrice: data.lastPurchasePrice || '',
standardCost: data.standardCost || '',
sellingPrice: data.sellingPrice || '',
minimumPrice: data.minimumPrice || '',
// Inventory management
lowStockThreshold: data.lowStockThreshold || '',
reorderPoint: data.reorderPoint || '',
reorderQuantity: data.reorderQuantity || '',
maxStockLevel: data.maxStockLevel || '',
leadTimeDays: data.leadTimeDays || '',
// Product information
packageSize: data.packageSize || '',
shelfLifeDays: data.shelfLifeDays || '',
displayLifeHours: data.displayLifeHours || '',
storageTempMin: data.storageTempMin || '',
storageTempMax: data.storageTempMax || '',
// Storage and handling
storageInstructions: data.storageInstructions || '',
isPerishable: data.isPerishable ?? true,
handlingInstructions: data.handlingInstructions || '',
// Supplier information
preferredSupplierId: data.preferredSupplierId || '',
supplierProductCode: data.supplierProductCode || '',
// Quality and compliance
allergenInfo: data.allergenInfo || '',
nutritionalInfo: data.nutritionalInfo || '',
certifications: data.certifications || '',
// Physical properties
weight: data.weight || '',
volume: data.volume || '',
dimensions: data.dimensions || '',
color: data.color || '',
// Status and tracking
isActive: data.isActive ?? true,
trackByLot: data.trackByLot ?? false,
trackByExpiry: data.trackByExpiry ?? true,
allowNegativeStock: data.allowNegativeStock ?? false,
// Metadata
notes: data.notes || '',
tags: data.tags || '',
customFields: data.customFields || '',
});
// Update parent whenever local state changes
const handleDataChange = (newInventoryData: any) => {
setInventoryData(newInventoryData);
onDataChange({ ...data, ...newInventoryData });
};
return (
<div className="space-y-6">
<div className="text-center pb-4 border-b border-[var(--border-primary)]">
<h3 className="text-lg font-semibold text-[var(--text-primary)] mb-2">
{t('inventory.inventoryDetails')}
</h3>
<p className="text-sm text-[var(--text-secondary)]">
{t('inventory.fillRequiredInfo')}
</p>
</div>
{/* Required Fields */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="md:col-span-2">
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.name')} *
</label>
<input
type="text"
value={inventoryData.name}
onChange={(e) => handleDataChange({ ...inventoryData, name: e.target.value })}
placeholder={t('inventory.fields.namePlaceholder')}
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">
{t('inventory.fields.productType')} *
</label>
<select
value={inventoryData.productType}
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">{t('inventory.productTypes.ingredient')}</option>
<option value="finished_product">{t('inventory.productTypes.finished_product')}</option>
<option value="packaging">{t('inventory.productTypes.packaging')}</option>
<option value="consumable">{t('inventory.productTypes.consumable')}</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.unitOfMeasure')} *
</label>
<select
value={inventoryData.unitOfMeasure}
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="">{t('inventory.units.select')}</option>
<option value="kg">{t('inventory.units.kg')}</option>
<option value="g">{t('inventory.units.g')}</option>
<option value="l">{t('inventory.units.l')}</option>
<option value="ml">{t('inventory.units.ml')}</option>
<option value="units">{t('inventory.units.units')}</option>
<option value="dozen">{t('inventory.units.dozen')}</option>
<option value="lb">{t('inventory.units.lb')}</option>
<option value="oz">{t('inventory.units.oz')}</option>
</select>
</div>
</div>
{/* Basic Information */}
<div className="border-t border-[var(--border-primary)] pt-4">
<h4 className="text-sm font-semibold text-[var(--text-primary)] mb-3">{t('inventory.sections.basicInformation')}</h4>
<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">
{t('inventory.fields.sku')} ({t('common.optional')})
<Tooltip content={t('inventory.fields.skuTooltip')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="text"
value={inventoryData.sku}
onChange={(e) => handleDataChange({ ...inventoryData, sku: e.target.value })}
placeholder={t('inventory.fields.skuPlaceholder')}
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">
{t('inventory.fields.barcode')}
</label>
<input
type="text"
value={inventoryData.barcode}
onChange={(e) => handleDataChange({ ...inventoryData, barcode: e.target.value })}
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' ? t('inventory.fields.ingredientCategory') : t('inventory.fields.productCategory')}
</label>
<select
value={inventoryData.productType === 'ingredient' ? inventoryData.ingredientCategory : inventoryData.productCategory}
onChange={(e) => handleDataChange({
...inventoryData,
[inventoryData.productType === 'ingredient' ? 'ingredientCategory' : 'productCategory']: 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)]"
>
{inventoryData.productType === 'ingredient' ? (
<>
<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="">{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>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.brand')}
</label>
<input
type="text"
value={inventoryData.brand}
onChange={(e) => handleDataChange({ ...inventoryData, brand: e.target.value })}
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">
{t('inventory.fields.description')}
</label>
<textarea
value={inventoryData.description}
onChange={(e) => handleDataChange({ ...inventoryData, description: e.target.value })}
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)]"
/>
</div>
</div>
</div>
{/* Advanced Options */}
<AdvancedOptionsSection
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">
{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">
{t('inventory.fields.averageCost')}
<Tooltip content={t('tooltips.averageCost')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="number"
value={inventoryData.averageCost}
onChange={(e) => handleDataChange({ ...inventoryData, averageCost: e.target.value })}
placeholder="0.00"
step="0.01"
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.lastPurchasePrice')}
</label>
<input
type="number"
value={inventoryData.lastPurchasePrice}
onChange={(e) => handleDataChange({ ...inventoryData, lastPurchasePrice: e.target.value })}
placeholder="0.00"
step="0.01"
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.standardCost')}
<Tooltip content={t('tooltips.standardCost')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="number"
value={inventoryData.standardCost}
onChange={(e) => handleDataChange({ ...inventoryData, standardCost: e.target.value })}
placeholder="0.00"
step="0.01"
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.sellingPrice')}
</label>
<input
type="number"
value={inventoryData.sellingPrice}
onChange={(e) => handleDataChange({ ...inventoryData, sellingPrice: e.target.value })}
placeholder="0.00"
step="0.01"
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.minimumPrice')}
</label>
<input
type="number"
value={inventoryData.minimumPrice}
onChange={(e) => handleDataChange({ ...inventoryData, minimumPrice: e.target.value })}
placeholder="0.00"
step="0.01"
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)]"
/>
</div>
</div>
</div>
{/* 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">
{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">
{t('inventory.fields.lowStockThreshold')}
<Tooltip content={t('tooltips.lowStockThreshold')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="number"
value={inventoryData.lowStockThreshold}
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.reorderPoint')}
<Tooltip content={t('tooltips.reorderPoint')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="number"
value={inventoryData.reorderPoint}
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.reorderQuantity')}
<Tooltip content={t('tooltips.reorderQuantity')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="number"
value={inventoryData.reorderQuantity}
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.maxStockLevel')}
</label>
<input
type="number"
value={inventoryData.maxStockLevel}
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.leadTimeDays')}
<Tooltip content={t('tooltips.leadTime')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="number"
value={inventoryData.leadTimeDays}
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)]"
/>
</div>
</div>
</div>
{/* 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">
{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">
{t('inventory.fields.packageSize')}
</label>
<input
type="text"
value={inventoryData.packageSize}
onChange={(e) => handleDataChange({ ...inventoryData, packageSize: e.target.value })}
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">
{t('inventory.fields.shelfLifeDays')}
</label>
<input
type="number"
value={inventoryData.shelfLifeDays}
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.displayLifeHours')}
<Tooltip content={t('tooltips.displayLife')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="number"
value={inventoryData.displayLifeHours}
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{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={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)]"
/>
<input
type="number"
value={inventoryData.storageTempMax}
onChange={(e) => handleDataChange({ ...inventoryData, storageTempMax: e.target.value })}
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)]"
/>
</div>
</div>
</div>
</div>
{/* 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">
{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">
{t('inventory.fields.storageInstructions')}
</label>
<textarea
value={inventoryData.storageInstructions}
onChange={(e) => handleDataChange({ ...inventoryData, storageInstructions: e.target.value })}
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.handlingInstructions')}
</label>
<textarea
value={inventoryData.handlingInstructions}
onChange={(e) => handleDataChange({ ...inventoryData, handlingInstructions: e.target.value })}
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)]"
/>
</div>
<div className="flex items-center gap-2">
<input
type="checkbox"
checked={inventoryData.isPerishable}
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)]">
{t('inventory.fields.isPerishable')}
</label>
</div>
</div>
</div>
{/* 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">
{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">
{t('inventory.fields.preferredSupplierId')}
</label>
<input
type="text"
value={inventoryData.preferredSupplierId}
onChange={(e) => handleDataChange({ ...inventoryData, preferredSupplierId: e.target.value })}
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">
{t('inventory.fields.supplierProductCode')}
</label>
<input
type="text"
value={inventoryData.supplierProductCode}
onChange={(e) => handleDataChange({ ...inventoryData, supplierProductCode: e.target.value })}
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>
</div>
</div>
{/* 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">
{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">
{t('inventory.fields.allergenInfo')}
<Tooltip content={t('tooltips.allergenInfo')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="text"
value={inventoryData.allergenInfo}
onChange={(e) => handleDataChange({ ...inventoryData, allergenInfo: e.target.value })}
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">
{t('inventory.fields.nutritionalInfo')}
<Tooltip content={t('tooltips.nutritionalInfo')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="text"
value={inventoryData.nutritionalInfo}
onChange={(e) => handleDataChange({ ...inventoryData, nutritionalInfo: e.target.value })}
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">
{t('inventory.fields.certifications')}
<Tooltip content={t('tooltips.certifications')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="text"
value={inventoryData.certifications}
onChange={(e) => handleDataChange({ ...inventoryData, certifications: e.target.value })}
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>
</div>
</div>
{/* 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">
{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">
{t('inventory.fields.weight')}
</label>
<input
type="number"
value={inventoryData.weight}
onChange={(e) => handleDataChange({ ...inventoryData, weight: e.target.value })}
placeholder="0.00"
step="0.01"
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.volume')}
</label>
<input
type="number"
value={inventoryData.volume}
onChange={(e) => handleDataChange({ ...inventoryData, volume: e.target.value })}
placeholder="0.00"
step="0.01"
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.dimensions')}
</label>
<input
type="text"
value={inventoryData.dimensions}
onChange={(e) => handleDataChange({ ...inventoryData, dimensions: e.target.value })}
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">
{t('inventory.fields.color')}
</label>
<input
type="text"
value={inventoryData.color}
onChange={(e) => handleDataChange({ ...inventoryData, color: e.target.value })}
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>
</div>
</div>
{/* 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">
{t('inventory.sections.statusAndTracking')}
</h5>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="flex items-center gap-2">
<input
type="checkbox"
checked={inventoryData.isActive}
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)]">
{t('inventory.fields.isActive')}
</label>
</div>
<div className="flex items-center gap-2">
<input
type="checkbox"
checked={inventoryData.trackByLot}
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)]">
{t('inventory.fields.trackByLot')}
</label>
</div>
<div className="flex items-center gap-2">
<input
type="checkbox"
checked={inventoryData.trackByExpiry}
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)]">
{t('inventory.fields.trackByExpiry')}
</label>
</div>
<div className="flex items-center gap-2">
<input
type="checkbox"
checked={inventoryData.allowNegativeStock}
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)]">
{t('inventory.fields.allowNegativeStock')}
</label>
</div>
</div>
</div>
{/* 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">
{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">
{t('inventory.fields.notes')}
</label>
<textarea
value={inventoryData.notes}
onChange={(e) => handleDataChange({ ...inventoryData, notes: e.target.value })}
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)]"
/>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('inventory.fields.tags')}
<Tooltip content={t('tooltips.tags')}>
<Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
</Tooltip>
</label>
<input
type="text"
value={inventoryData.tags}
onChange={(e) => handleDataChange({ ...inventoryData, tags: e.target.value })}
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">
{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={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"
/>
</div>
</div>
</div>
</AdvancedOptionsSection>
</div>
);
};
export const InventoryWizardSteps = (
data: Record<string, any>,
setData: (data: Record<string, any>) => void
): 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);
},
},
];
};