Improve frontend traslations 2

This commit is contained in:
Urtzi Alfaro
2025-11-19 07:46:40 +01:00
parent bbf6658759
commit 1f6a679557
14 changed files with 1068 additions and 262 deletions

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect, useCallback } from 'react';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { PublicLayout } from '../../components/layout';
import { Button } from '../../components/ui';
import { getDemoAccounts, createDemoSession, DemoAccount, demoSessionAPI } from '../../api/services/demo';
@@ -10,6 +11,7 @@ import { markTourAsStartPending } from '../../features/demo-onboarding';
const POLL_INTERVAL_MS = 1500; // Poll every 1.5 seconds
export const DemoPage: React.FC = () => {
const { t } = useTranslation();
const [demoAccounts, setDemoAccounts] = useState<DemoAccount[]>([]);
const [loading, setLoading] = useState(true);
const [creatingSession, setCreatingSession] = useState(false);
@@ -23,7 +25,7 @@ export const DemoPage: React.FC = () => {
const accounts = await getDemoAccounts();
setDemoAccounts(accounts);
} catch (err) {
setError('Error al cargar las cuentas demo');
setError(t('demo:errors.loading_accounts', 'Error al cargar las cuentas demo'));
console.error('Error fetching demo accounts:', err);
} finally {
setLoading(false);
@@ -152,7 +154,7 @@ export const DemoPage: React.FC = () => {
clearInterval(pollInterval);
}
} catch (err: any) {
setError(err?.message || 'Error al crear sesión demo');
setError(err?.message || t('demo:errors.creating_session', 'Error al crear sesión demo'));
console.error('Error creating demo session:', err);
setCreatingSession(false);
}
@@ -176,7 +178,7 @@ export const DemoPage: React.FC = () => {
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-[var(--bg-primary)] via-[var(--bg-secondary)] to-[var(--color-primary)]/5">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[var(--color-primary)] mx-auto"></div>
<p className="mt-4 text-[var(--text-secondary)]">Cargando cuentas demo...</p>
<p className="mt-4 text-[var(--text-secondary)]">{t('demo:loading.initial', 'Cargando cuentas demo...')}</p>
</div>
</div>
</PublicLayout>
@@ -200,31 +202,31 @@ export const DemoPage: React.FC = () => {
<div className="mb-6">
<span className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-[var(--color-primary)]/10 text-[var(--color-primary)]">
<Play className="w-4 h-4 mr-2" />
Demo Interactiva
{t('demo:hero.badge', 'Demo Interactiva')}
</span>
</div>
<h1 className="text-4xl tracking-tight font-extrabold text-[var(--text-primary)] sm:text-5xl lg:text-6xl">
<span className="block">Prueba El Panadero Digital</span>
<span className="block text-[var(--color-primary)]">sin compromiso</span>
<span className="block">{t('demo:hero.title', 'Prueba El Panadero Digital')}</span>
<span className="block text-[var(--color-primary)]">{t('demo:hero.subtitle', 'sin compromiso')}</span>
</h1>
<p className="mt-6 max-w-3xl mx-auto text-lg text-[var(--text-secondary)] sm:text-xl">
Elige el tipo de panadería que se ajuste a tu negocio
{t('demo:hero.description', 'Elige el tipo de panadería que se ajuste a tu negocio')}
</p>
<div className="mt-8 flex items-center justify-center space-x-6 text-sm text-[var(--text-tertiary)]">
<div className="flex items-center">
<Check className="w-4 h-4 text-green-500 mr-2" />
Sin tarjeta de crédito
{t('demo:hero.benefits.no_credit_card', 'Sin tarjeta de crédito')}
</div>
<div className="flex items-center">
<Clock className="w-4 h-4 text-green-500 mr-2" />
30 minutos de acceso
{t('demo:hero.benefits.access_time', '30 minutos de acceso')}
</div>
<div className="flex items-center">
<Shield className="w-4 h-4 text-green-500 mr-2" />
Datos reales en español
{t('demo:hero.benefits.real_data', 'Datos reales en español')}
</div>
</div>
</div>
@@ -258,18 +260,18 @@ export const DemoPage: React.FC = () => {
<div className="ml-4">
<h2 className="text-2xl font-bold text-[var(--text-primary)]">
{account.account_type === 'individual_bakery'
? 'Panadería Individual con Producción local'
: 'Panadería Franquiciada con Obrador Central'}
? t('demo:accounts.individual_bakery.title', 'Panadería Individual con Producción local')
: t('demo:accounts.central_baker.title', 'Panadería Franquiciada con Obrador Central')}
</h2>
<p className="text-sm text-[var(--text-tertiary)] mt-1">
{account.account_type === 'individual_bakery'
? account.business_model
: 'Punto de Venta + Obrador Central'}
? t('demo:accounts.individual_bakery.subtitle', account.business_model)
: t('demo:accounts.central_baker.subtitle', 'Punto de Venta + Obrador Central')}
</p>
</div>
</div>
<span className="px-3 py-1 bg-[var(--color-primary)]/10 text-[var(--color-primary)] rounded-full text-xs font-semibold">
DEMO
{t('demo:accounts.demo_badge', 'DEMO')}
</span>
</div>
@@ -281,45 +283,47 @@ export const DemoPage: React.FC = () => {
{/* Key Characteristics */}
<div className="mb-6 p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-default)]">
<p className="text-xs font-semibold text-[var(--text-tertiary)] uppercase mb-3">
Características del negocio
{account.account_type === 'individual_bakery'
? t('demo:accounts.individual_bakery.characteristics.title', 'Características del negocio')
: t('demo:accounts.central_baker.characteristics.title', 'Características del negocio')}
</p>
<div className="grid grid-cols-2 gap-3 text-sm">
{account.account_type === 'individual_bakery' ? (
<>
<div>
<span className="text-[var(--text-tertiary)]">Empleados:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">~8</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.individual_bakery.characteristics.employees', 'Empleados')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.individual_bakery.characteristics.employees_value', '~8')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Turnos:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">1/día</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.individual_bakery.characteristics.shifts', 'Turnos')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.individual_bakery.characteristics.shifts_value', '1/día')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Ventas:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">Directas</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.individual_bakery.characteristics.sales', 'Ventas')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.individual_bakery.characteristics.sales_value', 'Directas')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Productos:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">Local</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.individual_bakery.characteristics.products', 'Productos')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.individual_bakery.characteristics.products_value', 'Local')}</span>
</div>
</>
) : (
<>
<div>
<span className="text-[var(--text-tertiary)]">Empleados:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">~5-6</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.central_baker.characteristics.employees', 'Empleados')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.central_baker.characteristics.employees_value', '~5-6')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Turnos:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">2/día</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.central_baker.characteristics.shifts', 'Turnos')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.central_baker.characteristics.shifts_value', '2/día')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Modelo:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">Franquicia</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.central_baker.characteristics.model', 'Modelo')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.central_baker.characteristics.model_value', 'Franquicia')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Productos:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">De obrador</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.central_baker.characteristics.products', 'Productos')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.central_baker.characteristics.products_value', 'De obrador')}</span>
</div>
</>
)}
@@ -330,7 +334,7 @@ export const DemoPage: React.FC = () => {
{account.features && account.features.length > 0 && (
<div className="mb-8 space-y-2">
<p className="text-sm font-semibold text-[var(--text-primary)] mb-3">
Funcionalidades incluidas:
{t('demo:accounts.features_title', 'Funcionalidades incluidas:')}
</p>
{account.features.map((feature, idx) => (
<div key={idx} className="flex items-center text-sm text-[var(--text-secondary)]">
@@ -349,7 +353,7 @@ export const DemoPage: React.FC = () => {
className="w-full bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-primary-dark)] hover:from-[var(--color-primary-dark)] hover:to-[var(--color-primary)] text-white shadow-lg hover:shadow-2xl transform hover:scale-[1.02] transition-all duration-200 font-semibold text-base py-4"
>
<Play className="mr-2 w-5 h-5" />
Iniciar Demo
{t('demo:accounts.start_demo', 'Iniciar Demo')}
<ArrowRight className="ml-2 w-5 h-5" />
</Button>
</div>
@@ -361,13 +365,13 @@ export const DemoPage: React.FC = () => {
{/* Footer CTA */}
<div className="mt-16 text-center">
<p className="text-[var(--text-secondary)] mb-4">
¿Ya tienes una cuenta?
{t('demo:footer.have_account', '¿Ya tienes una cuenta?')}
</p>
<Link
to="/login"
className="inline-flex items-center text-[var(--color-primary)] hover:text-[var(--color-primary-dark)] font-semibold transition-colors"
>
Inicia sesión aquí
{t('demo:footer.login_link', 'Inicia sesión aquí')}
<ArrowRight className="ml-2 w-4 h-4" />
</Link>
</div>
@@ -392,12 +396,14 @@ export const DemoPage: React.FC = () => {
</div>
<h2 className="text-2xl font-bold text-[var(--text-primary)] mb-2">
{progressPercentage >= 100 ? '¡Listo! Redirigiendo...' : 'Preparando tu Demo'}
{progressPercentage >= 100
? t('demo:loading.ready_title', '¡Listo! Redirigiendo...')
: t('demo:loading.preparing_title', 'Preparando tu Demo')}
</h2>
<p className="text-[var(--text-secondary)] mb-6">
{progressPercentage >= 100
? 'Tu entorno está listo. Accediendo al dashboard...'
: 'Configurando tu entorno personalizado con datos de muestra...'}
? t('demo:loading.ready_description', 'Tu entorno está listo. Accediendo al dashboard...')
: t('demo:loading.preparing_description', 'Configurando tu entorno personalizado con datos de muestra...')}
</p>
{/* Progress bar */}
@@ -412,7 +418,7 @@ export const DemoPage: React.FC = () => {
{progressPercentage < 100 && (
<div className="flex items-center justify-center text-sm text-[var(--text-tertiary)] mb-4">
<Clock className="w-4 h-4 mr-2" />
<span>Tiempo estimado: ~{estimatedTime}s</span>
<span>{t('demo:loading.estimated_time', 'Tiempo estimado: ~{{seconds}}s', { seconds: estimatedTime })}</span>
</div>
)}
@@ -420,7 +426,7 @@ export const DemoPage: React.FC = () => {
{progressPercentage < 100 && (
<div className="mt-2 p-4 bg-[var(--color-primary)]/5 rounded-lg border border-[var(--color-primary)]/20">
<p className="text-xs text-[var(--text-secondary)] italic">
💡 Tip: La demo incluye datos reales de panaderías españolas para que puedas explorar todas las funcionalidades
{t('demo:loading.tip', '💡 Tip: La demo incluye datos reales de panaderías españolas para que puedas explorar todas las funcionalidades')}
</p>
</div>
)}