Support multiple languages

This commit is contained in:
Urtzi Alfaro
2025-09-25 12:14:46 +02:00
parent 6d4090f825
commit f02a980c87
66 changed files with 3274 additions and 333 deletions

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { Card, CardHeader, CardBody } from '../../ui/Card';
import { Badge } from '../../ui/Badge';
import { Button } from '../../ui/Button';
@@ -41,6 +42,7 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
className,
maxAlerts = 10
}) => {
const { t } = useTranslation(['dashboard']);
const [expandedAlert, setExpandedAlert] = useState<string | null>(null);
const { notifications, isConnected, markAsRead, removeNotification } = useNotifications();
@@ -108,11 +110,13 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
const diffMs = now.getTime() - date.getTime();
const diffMins = Math.floor(diffMs / (1000 * 60));
if (diffMins < 1) return 'Ahora';
if (diffMins < 60) return `${diffMins}m`;
if (diffMins < 1) return t('dashboard:alerts.time.now', 'Ahora');
if (diffMins < 60) return t('dashboard:alerts.time.minutes_ago', 'hace {{count}} min', { count: diffMins });
const diffHours = Math.floor(diffMins / 60);
if (diffHours < 24) return `${diffHours}h`;
return date.toLocaleDateString('es-ES', { day: '2-digit', month: '2-digit' });
if (diffHours < 24) return t('dashboard:alerts.time.hours_ago', 'hace {{count}} h', { count: diffHours });
return date.toLocaleDateString() === new Date(now.getTime() - 24 * 60 * 60 * 1000).toLocaleDateString()
? t('dashboard:alerts.time.yesterday', 'Ayer')
: date.toLocaleDateString('es-ES', { day: '2-digit', month: '2-digit' });
};
const toggleExpanded = (alertId: string) => {
@@ -147,7 +151,7 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
</div>
<div>
<h3 className="text-base font-semibold" style={{ color: 'var(--text-primary)' }}>
Alertas
{t('dashboard:alerts.title', 'Alertas')}
</h3>
<div className="flex items-center gap-2">
{isConnected ? (
@@ -156,7 +160,10 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
<WifiOff className="w-3 h-3" style={{ color: 'var(--color-error)' }} />
)}
<span className="text-xs" style={{ color: 'var(--text-secondary)' }}>
{isConnected ? 'En vivo' : 'Desconectado'}
{isConnected
? t('dashboard:alerts.live', 'En vivo')
: t('dashboard:alerts.offline', 'Desconectado')
}
</span>
</div>
</div>
@@ -182,7 +189,7 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
<div className="p-6 text-center">
<CheckCircle className="w-6 h-6 mx-auto mb-2" style={{ color: 'var(--color-success)' }} />
<p className="text-sm" style={{ color: 'var(--text-secondary)' }}>
No hay alertas activas
{t('dashboard:alerts.no_alerts', 'No hay alertas activas')}
</p>
</div>
) : (
@@ -241,7 +248,10 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
{alert.severity.toUpperCase()}
</Badge>
<Badge variant="secondary" size="sm">
{alert.item_type === 'alert' ? '🚨 Alerta' : '💡 Recomendación'}
{alert.item_type === 'alert'
? `🚨 ${t('dashboard:alerts.types.alert', 'Alerta')}`
: `💡 ${t('dashboard:alerts.types.recommendation', 'Recomendación')}`
}
</Badge>
</div>
@@ -277,7 +287,7 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
{alert.actions && alert.actions.length > 0 && (
<div className="mb-4">
<p className="text-xs font-semibold mb-2 uppercase tracking-wide" style={{ color: 'var(--text-primary)' }}>
Acciones Recomendadas
{t('dashboard:alerts.recommended_actions', 'Acciones Recomendadas')}
</p>
<div className="space-y-1">
{alert.actions.map((action, index) => (
@@ -298,7 +308,7 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
{alert.metadata && Object.keys(alert.metadata).length > 0 && (
<div className="mb-4 p-2 rounded-md" style={{ backgroundColor: 'var(--bg-secondary)' }}>
<p className="text-xs font-semibold mb-1 uppercase tracking-wide" style={{ color: 'var(--text-primary)' }}>
Detalles Adicionales
{t('dashboard:alerts.additional_details', 'Detalles Adicionales')}
</p>
<div className="text-xs space-y-1" style={{ color: 'var(--text-secondary)' }}>
{Object.entries(alert.metadata).map(([key, value]) => (
@@ -323,7 +333,7 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
className="h-8 px-3 text-xs font-medium"
>
<Check className="w-3 h-3 mr-1" />
Marcar como leído
{t('dashboard:alerts.mark_as_read', 'Marcar como leído')}
</Button>
<Button
variant="ghost"
@@ -335,7 +345,7 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
className="h-8 px-3 text-xs font-medium text-red-600 hover:text-red-700 hover:bg-red-50"
>
<Trash2 className="w-3 h-3 mr-1" />
Eliminar
{t('dashboard:alerts.remove', 'Eliminar')}
</Button>
</div>
</div>
@@ -355,7 +365,7 @@ const RealTimeAlerts: React.FC<RealTimeAlertsProps> = ({
}}
>
<p className="text-xs" style={{ color: 'var(--text-secondary)' }}>
{activeAlerts.length} alertas activas
{t('dashboard:alerts.active_count', '{{count}} alertas activas', { count: activeAlerts.length })}
</p>
</div>
)}