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:
Claude
2025-11-10 12:47:52 +00:00
parent 36a62a2a71
commit 680b97f6de

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next';
import { import {
Package, Package,
Building2, Building2,
@@ -114,6 +115,85 @@ interface ItemTypeSelectorProps {
} }
export const ItemTypeSelector: React.FC<ItemTypeSelectorProps> = ({ onSelect }) => { 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 ( return (
<div className="space-y-6"> <div className="space-y-6">
{/* Header */} {/* Header */}
@@ -124,16 +204,16 @@ export const ItemTypeSelector: React.FC<ItemTypeSelectorProps> = ({ onSelect })
</div> </div>
</div> </div>
<h2 className="text-2xl font-bold text-[var(--text-primary)] mb-2"> <h2 className="text-2xl font-bold text-[var(--text-primary)] mb-2">
¿Qué te gustaría agregar? {t('itemTypeSelector.title')}
</h2> </h2>
<p className="text-[var(--text-secondary)] max-w-md mx-auto"> <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> </p>
</div> </div>
{/* Item Type Grid */} {/* Item Type Grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 md:gap-4"> <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 Icon = itemType.icon;
const isHighlighted = itemType.isHighlighted; const isHighlighted = itemType.isHighlighted;
@@ -198,7 +278,7 @@ export const ItemTypeSelector: React.FC<ItemTypeSelectorProps> = ({ onSelect })
{/* Help Text */} {/* Help Text */}
<div className="text-center pt-4 border-t border-[var(--border-primary)]"> <div className="text-center pt-4 border-t border-[var(--border-primary)]">
<p className="text-sm text-[var(--text-tertiary)]"> <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> </p>
</div> </div>
</div> </div>