feat: Implement i18n in ItemTypeSelector component
IMPLEMENTATION: Updated ItemTypeSelector to use react-i18next translations
following the pattern documented in WIZARD_I18N_IMPLEMENTATION_GUIDE.md
CHANGES:
- Added useTranslation('wizards') hook
- Replaced hardcoded ITEM_TYPES array with dynamic translation-based generation
- Updated all strings to use t() translation function
- Maintained all styling and functionality
TRANSLATIONS USED:
- itemTypeSelector.title → "What would you like to add?" / "¿Qué te gustaría agregar?" / "Zer gehitu nahi duzu?"
- itemTypeSelector.description → Localized descriptions
- itemTypeSelector.types.*.title → All 9 item type titles
- itemTypeSelector.types.*.description → All 9 item type descriptions
- itemTypeSelector.helpText → Footer help text
- Badge translations with defaultValue fallbacks
BENEFITS:
✅ Component now fully multilingual (en/es/eu)
✅ Automatically updates when user changes language
✅ Fallback values provided for safety
✅ Zero functionality changes - only translation layer added
EXAMPLE:
When language is ES: Shows "Inventario", "Agregar ingredientes o productos..."
When language is EN: Shows "Inventory", "Add ingredients or products..."
When language is EU: Shows "Inbentarioa", "Gehitu osagaiak edo produktuak..."
This demonstrates the pattern for all other wizard components to follow.
Remaining wizards (InventoryWizard, QualityTemplateWizard, etc.) can be
updated using the same approach.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Package,
|
||||
Building2,
|
||||
@@ -114,6 +115,85 @@ interface ItemTypeSelectorProps {
|
||||
}
|
||||
|
||||
export const ItemTypeSelector: React.FC<ItemTypeSelectorProps> = ({ onSelect }) => {
|
||||
const { t } = useTranslation('wizards');
|
||||
|
||||
// Generate item types from translations
|
||||
const itemTypes: ItemTypeConfig[] = [
|
||||
{
|
||||
id: 'sales-entry',
|
||||
title: t('itemTypeSelector.types.sales-entry.title'),
|
||||
subtitle: t('itemTypeSelector.types.sales-entry.description'),
|
||||
icon: Euro,
|
||||
badge: '⭐ ' + t('itemTypeSelector.mostCommon', { defaultValue: 'Most Common' }),
|
||||
badgeColor: 'bg-gradient-to-r from-amber-100 to-orange-100 text-orange-800 font-semibold',
|
||||
isHighlighted: true,
|
||||
},
|
||||
{
|
||||
id: 'inventory',
|
||||
title: t('itemTypeSelector.types.inventory.title'),
|
||||
subtitle: t('itemTypeSelector.types.inventory.description'),
|
||||
icon: Package,
|
||||
badge: t('itemTypeSelector.configuration', { defaultValue: 'Configuration' }),
|
||||
badgeColor: 'bg-blue-100 text-blue-700',
|
||||
},
|
||||
{
|
||||
id: 'supplier',
|
||||
title: t('itemTypeSelector.types.supplier.title'),
|
||||
subtitle: t('itemTypeSelector.types.supplier.description'),
|
||||
icon: Building2,
|
||||
badge: t('itemTypeSelector.configuration', { defaultValue: 'Configuration' }),
|
||||
badgeColor: 'bg-blue-100 text-blue-700',
|
||||
},
|
||||
{
|
||||
id: 'recipe',
|
||||
title: t('itemTypeSelector.types.recipe.title'),
|
||||
subtitle: t('itemTypeSelector.types.recipe.description'),
|
||||
icon: ChefHat,
|
||||
badge: t('itemTypeSelector.common', { defaultValue: 'Common' }),
|
||||
badgeColor: 'bg-green-100 text-green-700',
|
||||
},
|
||||
{
|
||||
id: 'equipment',
|
||||
title: t('itemTypeSelector.types.equipment.title'),
|
||||
subtitle: t('itemTypeSelector.types.equipment.description'),
|
||||
icon: Wrench,
|
||||
badge: t('itemTypeSelector.configuration', { defaultValue: 'Configuration' }),
|
||||
badgeColor: 'bg-blue-100 text-blue-700',
|
||||
},
|
||||
{
|
||||
id: 'quality-template',
|
||||
title: t('itemTypeSelector.types.quality-template.title'),
|
||||
subtitle: t('itemTypeSelector.types.quality-template.description'),
|
||||
icon: ClipboardCheck,
|
||||
badge: t('itemTypeSelector.configuration', { defaultValue: 'Configuration' }),
|
||||
badgeColor: 'bg-blue-100 text-blue-700',
|
||||
},
|
||||
{
|
||||
id: 'customer-order',
|
||||
title: t('itemTypeSelector.types.customer-order.title'),
|
||||
subtitle: t('itemTypeSelector.types.customer-order.description'),
|
||||
icon: ShoppingCart,
|
||||
badge: t('itemTypeSelector.daily', { defaultValue: 'Daily' }),
|
||||
badgeColor: 'bg-amber-100 text-amber-700',
|
||||
},
|
||||
{
|
||||
id: 'customer',
|
||||
title: t('itemTypeSelector.types.customer.title'),
|
||||
subtitle: t('itemTypeSelector.types.customer.description'),
|
||||
icon: Users,
|
||||
badge: t('itemTypeSelector.common', { defaultValue: 'Common' }),
|
||||
badgeColor: 'bg-green-100 text-green-700',
|
||||
},
|
||||
{
|
||||
id: 'team-member',
|
||||
title: t('itemTypeSelector.types.team-member.title'),
|
||||
subtitle: t('itemTypeSelector.types.team-member.description'),
|
||||
icon: UserPlus,
|
||||
badge: t('itemTypeSelector.configuration', { defaultValue: 'Configuration' }),
|
||||
badgeColor: 'bg-blue-100 text-blue-700',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Header */}
|
||||
@@ -124,16 +204,16 @@ export const ItemTypeSelector: React.FC<ItemTypeSelectorProps> = ({ onSelect })
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-[var(--text-primary)] mb-2">
|
||||
¿Qué te gustaría agregar?
|
||||
{t('itemTypeSelector.title')}
|
||||
</h2>
|
||||
<p className="text-[var(--text-secondary)] max-w-md mx-auto">
|
||||
Selecciona el tipo de contenido que deseas añadir a tu panadería
|
||||
{t('itemTypeSelector.description')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Item Type Grid */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 md:gap-4">
|
||||
{ITEM_TYPES.map((itemType) => {
|
||||
{itemTypes.map((itemType) => {
|
||||
const Icon = itemType.icon;
|
||||
const isHighlighted = itemType.isHighlighted;
|
||||
|
||||
@@ -198,7 +278,7 @@ export const ItemTypeSelector: React.FC<ItemTypeSelectorProps> = ({ onSelect })
|
||||
{/* Help Text */}
|
||||
<div className="text-center pt-4 border-t border-[var(--border-primary)]">
|
||||
<p className="text-sm text-[var(--text-tertiary)]">
|
||||
Selecciona una opción para comenzar el proceso guiado paso a paso
|
||||
{t('itemTypeSelector.helpText', { defaultValue: 'Select an option to start the guided step-by-step process' })}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user