Support multiple languages
This commit is contained in:
@@ -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>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user