Merge pull request #18 from ualsweb/claude/analyze-produccion-ui-ux-01EqW8hvN6ufZcMtqvuvzK9d

feat(analytics): Improve Production Analytics UI/UX and complete tran…
This commit is contained in:
ualsweb
2025-11-15 15:56:31 +01:00
committed by GitHub
5 changed files with 818 additions and 242 deletions

View File

@@ -131,11 +131,11 @@ export const AIInsightsWidget: React.FC = () => {
const getTypeColor = (type: AIInsight['type']) => {
switch (type) {
case 'optimization': return 'text-green-600';
case 'prediction': return 'text-blue-600';
case 'anomaly': return 'text-red-600';
case 'recommendation': return 'text-purple-600';
default: return 'text-gray-600';
case 'optimization': return 'text-[var(--color-success)]';
case 'prediction': return 'text-[var(--color-info)]';
case 'anomaly': return 'text-[var(--color-error)]';
case 'recommendation': return 'text-[var(--color-secondary)]';
default: return 'text-[var(--text-secondary)]';
}
};
@@ -207,43 +207,43 @@ export const AIInsightsWidget: React.FC = () => {
</div>
}
>
<div className="space-y-6">
<div className="space-y-5">
{/* AI Insights Overview Stats */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="text-center p-4 bg-[var(--bg-secondary)] rounded-lg">
<Brain className="w-8 h-8 mx-auto text-purple-600 mb-2" />
<div className="text-center p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] hover:border-[var(--border-focus)] transition-colors">
<Brain className="w-8 h-8 mx-auto text-[var(--color-secondary)] mb-2" />
<p className="text-2xl font-bold text-[var(--text-primary)]">{activeInsights.length}</p>
<p className="text-sm text-[var(--text-secondary)]">{t('ai.stats.active_insights')}</p>
<p className="text-sm text-[var(--text-secondary)] font-medium">{t('ai.stats.active_insights')}</p>
</div>
<div className="text-center p-4 bg-[var(--bg-secondary)] rounded-lg">
<AlertTriangle className="w-8 h-8 mx-auto text-red-600 mb-2" />
<p className="text-2xl font-bold text-[var(--text-primary)]">{highPriorityInsights.length}</p>
<p className="text-sm text-[var(--text-secondary)]">{t('ai.stats.high_priority')}</p>
<div className="text-center p-4 bg-[var(--color-error)]/10 rounded-lg border border-[var(--color-error)]/20 hover:border-[var(--color-error)]/40 transition-colors">
<AlertTriangle className="w-8 h-8 mx-auto text-[var(--color-error)] mb-2" />
<p className="text-2xl font-bold text-[var(--color-error)]">{highPriorityInsights.length}</p>
<p className="text-sm text-[var(--text-secondary)] font-medium">{t('ai.stats.high_priority')}</p>
</div>
<div className="text-center p-4 bg-[var(--bg-secondary)] rounded-lg">
<div className="w-8 h-8 mx-auto bg-green-100 dark:bg-green-900/20 rounded-full flex items-center justify-center mb-2">
<span className="text-green-600 font-bold text-sm"></span>
<div className="text-center p-4 bg-[var(--color-success)]/10 rounded-lg border border-[var(--color-success)]/20 hover:border-[var(--color-success)]/40 transition-colors">
<div className="w-8 h-8 mx-auto bg-[var(--color-success)]/20 rounded-full flex items-center justify-center mb-2">
<span className="text-[var(--color-success)] font-bold text-sm"></span>
</div>
<p className="text-2xl font-bold text-[var(--text-primary)]">{totalPotentialSavings}</p>
<p className="text-sm text-[var(--text-secondary)]">{t('ai.stats.potential_savings')}</p>
<p className="text-2xl font-bold text-[var(--color-success)]">{totalPotentialSavings}</p>
<p className="text-sm text-[var(--text-secondary)] font-medium">{t('ai.stats.potential_savings')}</p>
</div>
<div className="text-center p-4 bg-[var(--bg-secondary)] rounded-lg">
<div className="w-8 h-8 mx-auto bg-blue-100 dark:bg-blue-900/20 rounded-full flex items-center justify-center mb-2">
<span className="text-blue-600 font-bold text-sm">%</span>
<div className="text-center p-4 bg-[var(--color-info)]/10 rounded-lg border border-[var(--color-info)]/20 hover:border-[var(--color-info)]/40 transition-colors">
<div className="w-8 h-8 mx-auto bg-[var(--color-info)]/20 rounded-full flex items-center justify-center mb-2">
<span className="text-[var(--color-info)] font-bold text-sm">%</span>
</div>
<p className="text-2xl font-bold text-[var(--text-primary)]">{avgConfidence.toFixed(0)}%</p>
<p className="text-sm text-[var(--text-secondary)]">{t('ai.stats.avg_confidence')}</p>
<p className="text-2xl font-bold text-[var(--color-info)]">{avgConfidence.toFixed(0)}%</p>
<p className="text-sm text-[var(--text-secondary)] font-medium">{t('ai.stats.avg_confidence')}</p>
</div>
</div>
{/* AI Status */}
<div className="p-4 bg-green-50 dark:bg-green-900/20 rounded-lg">
<div className="p-4 bg-[var(--color-success)]/10 border border-[var(--color-success)]/20 rounded-lg">
<div className="flex items-center space-x-2">
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span className="text-sm font-medium text-green-600">
<div className="w-2 h-2 bg-[var(--color-success)] rounded-full animate-pulse"></div>
<span className="text-sm font-semibold text-[var(--color-success)]">
{t('ai.status.active')}
</span>
<span className="text-xs text-[var(--text-secondary)] ml-2">
<span className="text-xs text-[var(--text-secondary)] ml-2 font-medium">
{t('ai.last_updated')}
</span>
</div>
@@ -252,8 +252,8 @@ export const AIInsightsWidget: React.FC = () => {
{/* High Priority Insights */}
{highPriorityInsights.length > 0 && (
<div>
<h4 className="text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center">
<AlertTriangle className="w-4 h-4 mr-2 text-red-600" />
<h4 className="text-sm font-semibold text-[var(--text-primary)] mb-3 flex items-center">
<AlertTriangle className="w-4 h-4 mr-2 text-[var(--color-error)]" />
{t('ai.high_priority_insights')} ({highPriorityInsights.length})
</h4>
<div className="space-y-3">
@@ -262,7 +262,7 @@ export const AIInsightsWidget: React.FC = () => {
const ImpactIcon = getImpactIcon(insight.impact.type);
return (
<div key={insight.id} className="p-4 bg-[var(--bg-secondary)] rounded-lg border border-red-200 dark:border-red-800">
<div key={insight.id} className="p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--color-error)]/30 hover:border-[var(--color-error)]/50 transition-all duration-200">
<div className="flex items-start justify-between mb-3">
<div className="flex items-start space-x-3">
<TypeIcon className={`w-5 h-5 mt-1 ${getTypeColor(insight.type)}`} />
@@ -287,14 +287,14 @@ export const AIInsightsWidget: React.FC = () => {
</div>
{/* Impact */}
<div className="flex items-center justify-between p-3 bg-[var(--bg-tertiary)] rounded-lg">
<div className="flex items-center justify-between p-3 bg-[var(--color-success)]/5 border border-[var(--color-success)]/10 rounded-lg">
<div className="flex items-center space-x-2">
<ImpactIcon className="w-4 h-4 text-[var(--color-primary)]" />
<span className="text-sm font-medium text-[var(--text-primary)]">
<span className="text-sm font-semibold text-[var(--text-primary)]">
{t(`ai.impact.${insight.impact.type}`)}
</span>
</div>
<span className="text-lg font-bold text-green-600">
<span className="text-lg font-bold text-[var(--color-success)]">
{formatImpactValue(insight.impact)}
</span>
</div>
@@ -318,17 +318,17 @@ export const AIInsightsWidget: React.FC = () => {
{/* All Insights */}
<div>
<h4 className="text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center">
<Brain className="w-4 h-4 mr-2" />
<h4 className="text-sm font-semibold text-[var(--text-primary)] mb-3 flex items-center">
<Brain className="w-4 h-4 mr-2 text-[var(--color-secondary)]" />
{t('ai.all_insights')} ({activeInsights.length})
</h4>
<div className="space-y-3 max-h-96 overflow-y-auto">
<div className="space-y-2 max-h-96 overflow-y-auto pr-1">
{activeInsights.map((insight) => {
const TypeIcon = getTypeIcon(insight.type);
const ImpactIcon = getImpactIcon(insight.impact.type);
return (
<div key={insight.id} className="p-3 bg-[var(--bg-secondary)] rounded-lg hover:bg-[var(--bg-tertiary)] transition-colors">
<div key={insight.id} className="p-3 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] hover:border-[var(--border-focus)] hover:shadow-sm transition-all duration-200">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<TypeIcon className={`w-4 h-4 ${getTypeColor(insight.type)}`} />
@@ -362,16 +362,16 @@ export const AIInsightsWidget: React.FC = () => {
</div>
{/* AI Performance Summary */}
<div className="p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
<div className="flex items-start space-x-2">
<Brain className="w-5 h-5 text-blue-600 mt-0.5" />
<div>
<p className="text-sm font-medium text-blue-600">
<div className="p-4 bg-[var(--color-info)]/10 border border-[var(--color-info)]/20 rounded-lg">
<div className="flex items-start space-x-3">
<Brain className="w-5 h-5 text-[var(--color-info)] mt-0.5" />
<div className="flex-1">
<p className="text-sm font-semibold text-[var(--color-info)] mb-1">
{t('ai.performance.summary')}
</p>
<p className="text-xs text-[var(--text-secondary)] mt-1">
{implementedInsights.length} {t('ai.performance.insights_implemented')},
{totalPotentialSavings > 0 && `${totalPotentialSavings} ${t('ai.performance.in_savings_identified')}`}
<p className="text-xs text-[var(--text-secondary)]">
{implementedInsights.length} {t('ai.performance.insights_implemented')}
{totalPotentialSavings > 0 && `,${totalPotentialSavings} ${t('ai.performance.in_savings_identified')}`}
</p>
</div>
</div>

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Activity, Clock, AlertCircle, CheckCircle, Play, Pause } from 'lucide-react';
import { Activity, Clock, AlertCircle, CheckCircle, Play, Pause, Zap } from 'lucide-react';
import { AnalyticsWidget } from '../AnalyticsWidget';
import { Badge, ProgressBar, Button } from '../../../../ui';
import { useActiveBatches } from '../../../../../api/hooks/production';
@@ -86,6 +86,19 @@ export const LiveBatchTrackerWidget: React.FC = () => {
return 'info';
};
const getPriorityColor = (priority: string) => {
switch (priority) {
case 'URGENT':
return 'text-[var(--color-error)]';
case 'HIGH':
return 'text-[var(--color-warning)]';
case 'MEDIUM':
return 'text-[var(--color-info)]';
default:
return 'text-[var(--text-secondary)]';
}
};
return (
<AnalyticsWidget
title={t('tracker.live_batch_tracker')}
@@ -110,7 +123,7 @@ export const LiveBatchTrackerWidget: React.FC = () => {
<p className="text-sm">{t('messages.no_active_batches_description')}</p>
</div>
) : (
<div className="space-y-3 max-h-96 overflow-y-auto">
<div className="space-y-3 max-h-96 overflow-y-auto pr-1">
{batches.map((batch) => {
const StatusIcon = getStatusIcon(batch.status);
const progress = calculateProgress(batch);
@@ -119,16 +132,16 @@ export const LiveBatchTrackerWidget: React.FC = () => {
return (
<div
key={batch.id}
className="p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] hover:shadow-md transition-all"
className="p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] hover:border-[var(--border-focus)] hover:shadow-md transition-all duration-200"
>
{/* Header */}
<div className="flex items-start justify-between mb-3">
<div className="flex items-start space-x-3 flex-1">
<div className="w-8 h-8 bg-[var(--color-primary)]/10 rounded-lg flex items-center justify-center mt-0.5">
<div className="w-8 h-8 bg-[var(--color-primary)]/10 rounded-lg flex items-center justify-center flex-shrink-0 mt-0.5">
<StatusIcon className="w-4 h-4 text-[var(--color-primary)]" />
</div>
<div className="flex-1 min-w-0">
<h4 className="font-semibold text-[var(--text-primary)] mb-1">
<h4 className="font-semibold text-[var(--text-primary)] mb-1 truncate">
{batch.product_name}
</h4>
<p className="text-sm text-[var(--text-secondary)] mb-1">
@@ -144,7 +157,7 @@ export const LiveBatchTrackerWidget: React.FC = () => {
</div>
</div>
</div>
<Badge variant={getStatusBadgeVariant(batch.status)}>
<Badge variant={getStatusBadgeVariant(batch.status)} className="flex-shrink-0">
{t(`status.${batch.status.toLowerCase()}`)}
</Badge>
</div>
@@ -152,11 +165,11 @@ export const LiveBatchTrackerWidget: React.FC = () => {
{/* Progress Bar */}
{batch.status !== ProductionStatus.PENDING && (
<div className="mb-3">
<div className="flex items-center justify-between mb-1">
<span className="text-xs text-[var(--text-secondary)]">
<div className="flex items-center justify-between mb-1.5">
<span className="text-xs font-medium text-[var(--text-secondary)]">
{t('tracker.progress')}
</span>
<span className="text-xs font-medium text-[var(--text-primary)]">
<span className="text-xs font-semibold text-[var(--text-primary)]">
{progress}%
</span>
</div>
@@ -169,33 +182,29 @@ export const LiveBatchTrackerWidget: React.FC = () => {
)}
{/* Details */}
<div className="flex items-center justify-between text-xs">
<div className="flex items-center space-x-4">
<div className="flex items-center justify-between text-xs flex-wrap gap-2">
<div className="flex items-center space-x-3">
{batch.priority && (
<span className={`font-medium ${
batch.priority === 'URGENT' ? 'text-red-600' :
batch.priority === 'HIGH' ? 'text-orange-600' :
batch.priority === 'MEDIUM' ? 'text-blue-600' :
'text-gray-600'
}`}>
<span className={`font-semibold ${getPriorityColor(batch.priority)}`}>
{t(`priority.${batch.priority.toLowerCase()}`)}
</span>
)}
{batch.is_rush_order && (
<span className="text-red-600 font-medium">
<span className="text-[var(--color-error)] font-semibold flex items-center">
<Zap className="w-3 h-3 mr-1" />
{t('batch.rush_order')}
</span>
)}
</div>
<div className="flex items-center space-x-1 text-[var(--text-secondary)]">
<Clock className="w-3 h-3" />
<div className="flex items-center space-x-1.5 text-[var(--text-secondary)]">
<Clock className="w-3.5 h-3.5" />
<span>
{eta ? (
<span className={eta.includes('delayed') ? 'text-red-600' : ''}>
<span className={eta.includes('delayed') ? 'text-[var(--color-error)] font-medium' : 'font-medium'}>
ETA: {eta}
</span>
) : (
t('tracker.pending_start')
<span className="font-medium">{t('tracker.pending_start')}</span>
)}
</span>
</div>
@@ -203,15 +212,19 @@ export const LiveBatchTrackerWidget: React.FC = () => {
{/* Equipment & Staff */}
{(batch.equipment_used?.length > 0 || batch.staff_assigned?.length > 0) && (
<div className="mt-2 pt-2 border-t border-[var(--border-primary)] text-xs text-[var(--text-tertiary)]">
<div className="mt-3 pt-3 border-t border-[var(--border-secondary)] text-xs">
{batch.equipment_used?.length > 0 && (
<div className="mb-1">
{t('batch.equipment')}: {batch.equipment_used.join(', ')}
<div className="mb-1.5 flex items-start">
<span className="text-[var(--text-secondary)] font-medium mr-2">{t('batch.equipment')}:</span>
<span className="text-[var(--text-tertiary)] flex-1">{batch.equipment_used.join(', ')}</span>
</div>
)}
{batch.staff_assigned?.length > 0 && (
<div>
{t('batch.staff')}: {batch.staff_assigned.length} {t('common.assigned')}
<div className="flex items-center">
<span className="text-[var(--text-secondary)] font-medium mr-2">{t('batch.staff')}:</span>
<span className="text-[var(--text-tertiary)]">
{batch.staff_assigned.length} {t('common.assigned')}
</span>
</div>
)}
</div>
@@ -224,31 +237,31 @@ export const LiveBatchTrackerWidget: React.FC = () => {
{/* Summary */}
{batches.length > 0 && (
<div className="pt-3 border-t border-[var(--border-primary)]">
<div className="grid grid-cols-4 gap-4 text-center text-xs">
<div>
<p className="font-medium text-green-600">
<div className="pt-4 mt-2 border-t border-[var(--border-primary)]">
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3 text-center text-xs">
<div className="p-3 bg-[var(--color-success)]/10 rounded-lg border border-[var(--color-success)]/20">
<p className="text-2xl font-bold text-[var(--color-success)] mb-1">
{batches.filter(b => b.status === ProductionStatus.COMPLETED).length}
</p>
<p className="text-[var(--text-tertiary)]">{t('status.completed')}</p>
<p className="text-[var(--text-secondary)] font-medium">{t('status.completed')}</p>
</div>
<div>
<p className="font-medium text-blue-600">
<div className="p-3 bg-[var(--color-info)]/10 rounded-lg border border-[var(--color-info)]/20">
<p className="text-2xl font-bold text-[var(--color-info)] mb-1">
{batches.filter(b => b.status === ProductionStatus.IN_PROGRESS).length}
</p>
<p className="text-[var(--text-tertiary)]">{t('status.in_progress')}</p>
<p className="text-[var(--text-secondary)] font-medium">{t('status.in_progress')}</p>
</div>
<div>
<p className="font-medium text-orange-600">
<div className="p-3 bg-[var(--color-warning)]/10 rounded-lg border border-[var(--color-warning)]/20">
<p className="text-2xl font-bold text-[var(--color-warning)] mb-1">
{batches.filter(b => b.status === ProductionStatus.PENDING).length}
</p>
<p className="text-[var(--text-tertiary)]">{t('status.pending')}</p>
<p className="text-[var(--text-secondary)] font-medium">{t('status.pending')}</p>
</div>
<div>
<p className="font-medium text-red-600">
<div className="p-3 bg-[var(--color-error)]/10 rounded-lg border border-[var(--color-error)]/20">
<p className="text-2xl font-bold text-[var(--color-error)] mb-1">
{batches.filter(b => [ProductionStatus.FAILED, ProductionStatus.CANCELLED].includes(b.status)).length}
</p>
<p className="text-[var(--text-tertiary)]">{t('tracker.issues')}</p>
<p className="text-[var(--text-secondary)] font-medium">{t('tracker.issues')}</p>
</div>
</div>
</div>

View File

@@ -61,7 +61,7 @@ export const QualityScoreTrendsWidget: React.FC = () => {
id: 'quality-trend',
name: t('quality.daily_quality_score'),
type: 'line',
color: '#16a34a',
color: 'var(--color-success)',
data: scores
}
];
@@ -83,7 +83,7 @@ export const QualityScoreTrendsWidget: React.FC = () => {
id: 'quality-distribution',
name: t('quality.score_distribution'),
type: 'bar',
color: '#d97706',
color: 'var(--color-primary)',
data: distribution.map(item => ({
x: item.range,
y: item.count,
@@ -94,17 +94,17 @@ export const QualityScoreTrendsWidget: React.FC = () => {
};
const getScoreColor = (score: number) => {
if (score >= 9) return 'text-green-600';
if (score >= 8) return 'text-blue-600';
if (score >= 7) return 'text-orange-600';
return 'text-red-600';
if (score >= 9) return 'text-[var(--color-success)]';
if (score >= 8) return 'text-[var(--color-info)]';
if (score >= 7) return 'text-[var(--color-warning)]';
return 'text-[var(--color-error)]';
};
const getScoreStatus = (score: number) => {
if (score >= 9) return { status: 'excellent', bgColor: 'bg-green-100 dark:bg-green-900/20' };
if (score >= 8) return { status: 'good', bgColor: 'bg-blue-100 dark:bg-blue-900/20' };
if (score >= 7) return { status: 'acceptable', bgColor: 'bg-orange-100 dark:bg-orange-900/20' };
return { status: 'needs_improvement', bgColor: 'bg-red-100 dark:bg-red-900/20' };
if (score >= 9) return { status: 'excellent', bgColor: 'bg-[var(--color-success)]/10 border border-[var(--color-success)]/20' };
if (score >= 8) return { status: 'good', bgColor: 'bg-[var(--color-info)]/10 border border-[var(--color-info)]/20' };
if (score >= 7) return { status: 'acceptable', bgColor: 'bg-[var(--color-warning)]/10 border border-[var(--color-warning)]/20' };
return { status: 'needs_improvement', bgColor: 'bg-[var(--color-error)]/10 border border-[var(--color-error)]/20' };
};
const scoreStatus = getScoreStatus(qualityData.averageScore);
@@ -124,23 +124,24 @@ export const QualityScoreTrendsWidget: React.FC = () => {
</Button>
}
>
<div className="space-y-4">
<div className="space-y-5">
{/* Quality Score Display */}
<div className="text-center">
<div className="flex items-center justify-center space-x-2 mb-2">
<Star className={`w-6 h-6 ${getScoreColor(qualityData.averageScore)}`} />
<span className="text-3xl font-bold text-[var(--text-primary)]">
{qualityData.averageScore.toFixed(1)}/10
<div className="text-center p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)]">
<div className="flex items-center justify-center space-x-3 mb-3">
<Star className={`w-8 h-8 fill-current ${getScoreColor(qualityData.averageScore)}`} />
<span className="text-4xl font-bold text-[var(--text-primary)]">
{qualityData.averageScore.toFixed(1)}
</span>
<span className="text-xl text-[var(--text-secondary)] font-medium">/10</span>
</div>
<div className={`inline-flex items-center space-x-2 px-3 py-1 rounded-full text-sm ${scoreStatus.bgColor}`}>
<div className={`inline-flex items-center space-x-2 px-4 py-1.5 rounded-full text-sm font-medium ${scoreStatus.bgColor}`}>
<span className={getScoreColor(qualityData.averageScore)}>
{t(`quality.${scoreStatus.status}`)}
</span>
</div>
<div className="flex items-center justify-center space-x-1 mt-2">
<TrendIcon className={`w-4 h-4 ${qualityData.trend >= 0 ? 'text-green-600' : 'text-red-600'}`} />
<span className={`text-sm ${qualityData.trend >= 0 ? 'text-green-600' : 'text-red-600'}`}>
<div className="flex items-center justify-center space-x-1.5 mt-3 pt-3 border-t border-[var(--border-secondary)]">
<TrendIcon className={`w-4 h-4 ${qualityData.trend >= 0 ? 'text-[var(--color-success)]' : 'text-[var(--color-error)]'}`} />
<span className={`text-sm font-semibold ${qualityData.trend >= 0 ? 'text-[var(--color-success)]' : 'text-[var(--color-error)]'}`}>
{qualityData.trend > 0 ? '+' : ''}{qualityData.trend.toFixed(1)} {t('quality.vs_last_week')}
</span>
</div>
@@ -148,17 +149,17 @@ export const QualityScoreTrendsWidget: React.FC = () => {
{/* Key Metrics */}
<div className="grid grid-cols-2 gap-4">
<div className="p-4 bg-[var(--bg-secondary)] rounded-lg text-center">
<div className="text-2xl font-bold text-[var(--text-primary)] mb-1">
<div className="p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] text-center hover:border-[var(--border-focus)] transition-colors">
<div className="text-3xl font-bold text-[var(--text-primary)] mb-1">
{qualityData.totalChecks}
</div>
<p className="text-sm text-[var(--text-secondary)]">{t('stats.total_checks')}</p>
<p className="text-sm text-[var(--text-secondary)] font-medium">{t('stats.total_checks')}</p>
</div>
<div className="p-4 bg-[var(--bg-secondary)] rounded-lg text-center">
<div className="text-2xl font-bold text-green-600 mb-1">
<div className="p-4 bg-[var(--color-success)]/10 rounded-lg border border-[var(--color-success)]/20 text-center hover:border-[var(--color-success)]/40 transition-colors">
<div className="text-3xl font-bold text-[var(--color-success)] mb-1">
{qualityData.passRate.toFixed(1)}%
</div>
<p className="text-sm text-[var(--text-secondary)]">{t('stats.pass_rate')}</p>
<p className="text-sm text-[var(--text-secondary)] font-medium">{t('stats.pass_rate')}</p>
</div>
</div>
@@ -197,36 +198,36 @@ export const QualityScoreTrendsWidget: React.FC = () => {
{/* Quality Insights */}
<div className="grid grid-cols-3 gap-3 text-center">
<div className="p-3 bg-[var(--bg-secondary)] rounded-lg">
<p className="text-lg font-bold text-green-600">
<div className="p-3 bg-[var(--color-success)]/10 rounded-lg border border-[var(--color-success)]/20">
<p className="text-2xl font-bold text-[var(--color-success)] mb-1">
{Math.round(qualityData.totalChecks * 0.35)}
</p>
<p className="text-xs text-[var(--text-secondary)]">{t('quality.excellent_scores')}</p>
<p className="text-xs text-[var(--text-secondary)] font-medium">{t('quality.excellent_scores')}</p>
</div>
<div className="p-3 bg-[var(--bg-secondary)] rounded-lg">
<p className="text-lg font-bold text-blue-600">
<div className="p-3 bg-[var(--color-info)]/10 rounded-lg border border-[var(--color-info)]/20">
<p className="text-2xl font-bold text-[var(--color-info)] mb-1">
{Math.round(qualityData.totalChecks * 0.30)}
</p>
<p className="text-xs text-[var(--text-secondary)]">{t('quality.good_scores')}</p>
<p className="text-xs text-[var(--text-secondary)] font-medium">{t('quality.good_scores')}</p>
</div>
<div className="p-3 bg-[var(--bg-secondary)] rounded-lg">
<p className="text-lg font-bold text-red-600">
<div className="p-3 bg-[var(--color-error)]/10 rounded-lg border border-[var(--color-error)]/20">
<p className="text-2xl font-bold text-[var(--color-error)] mb-1">
{Math.round(qualityData.totalChecks * 0.15)}
</p>
<p className="text-xs text-[var(--text-secondary)]">{t('quality.needs_improvement')}</p>
<p className="text-xs text-[var(--text-secondary)] font-medium">{t('quality.needs_improvement')}</p>
</div>
</div>
{/* Quality Recommendations */}
{qualityData.averageScore < 8 && (
<div className="p-3 bg-orange-50 dark:bg-orange-900/20 rounded-lg">
<div className="flex items-start space-x-2">
<Star className="w-4 h-4 mt-0.5 text-orange-600" />
<div>
<p className="text-sm font-medium text-orange-600">
<div className="p-4 bg-[var(--color-warning)]/10 border border-[var(--color-warning)]/20 rounded-lg">
<div className="flex items-start space-x-3">
<Star className="w-5 h-5 mt-0.5 text-[var(--color-warning)]" />
<div className="flex-1">
<p className="text-sm font-semibold text-[var(--color-warning)] mb-1">
{t('quality.recommendations.improve_quality')}
</p>
<p className="text-xs text-[var(--text-secondary)] mt-1">
<p className="text-xs text-[var(--text-secondary)]">
{t('quality.recommendations.focus_consistency')}
</p>
</div>
@@ -235,14 +236,14 @@ export const QualityScoreTrendsWidget: React.FC = () => {
)}
{qualityData.averageScore >= 9 && (
<div className="p-3 bg-green-50 dark:bg-green-900/20 rounded-lg">
<div className="flex items-start space-x-2">
<Award className="w-4 h-4 mt-0.5 text-green-600" />
<div>
<p className="text-sm font-medium text-green-600">
<div className="p-4 bg-[var(--color-success)]/10 border border-[var(--color-success)]/20 rounded-lg">
<div className="flex items-start space-x-3">
<Award className="w-5 h-5 mt-0.5 text-[var(--color-success)]" />
<div className="flex-1">
<p className="text-sm font-semibold text-[var(--color-success)] mb-1">
{t('quality.recommendations.excellent_quality')}
</p>
<p className="text-xs text-[var(--text-secondary)] mt-1">
<p className="text-xs text-[var(--text-secondary)]">
{t('quality.recommendations.maintain_standards')}
</p>
</div>

View File

@@ -154,10 +154,10 @@ export const WasteDefectTrackerWidget: React.FC = () => {
const getWasteStatus = () => {
const totalWastePercentage = wasteData.wastePercentage + wasteData.defectPercentage;
if (totalWastePercentage <= 3) return { status: 'excellent', color: 'text-green-600', bgColor: 'bg-green-100 dark:bg-green-900/20' };
if (totalWastePercentage <= 5) return { status: 'good', color: 'text-blue-600', bgColor: 'bg-blue-100 dark:bg-blue-900/20' };
if (totalWastePercentage <= 8) return { status: 'warning', color: 'text-orange-600', bgColor: 'bg-orange-100 dark:bg-orange-900/20' };
return { status: 'critical', color: 'text-red-600', bgColor: 'bg-red-100 dark:bg-red-900/20' };
if (totalWastePercentage <= 3) return { status: 'excellent', color: 'text-[var(--color-success)]', bgColor: 'bg-[var(--color-success)]/10 border border-[var(--color-success)]/20' };
if (totalWastePercentage <= 5) return { status: 'good', color: 'text-[var(--color-info)]', bgColor: 'bg-[var(--color-info)]/10 border border-[var(--color-info)]/20' };
if (totalWastePercentage <= 8) return { status: 'warning', color: 'text-[var(--color-warning)]', bgColor: 'bg-[var(--color-warning)]/10 border border-[var(--color-warning)]/20' };
return { status: 'critical', color: 'text-[var(--color-error)]', bgColor: 'bg-[var(--color-error)]/10 border border-[var(--color-error)]/20' };
};
const wasteStatus = getWasteStatus();
@@ -177,43 +177,43 @@ export const WasteDefectTrackerWidget: React.FC = () => {
</Button>
}
>
<div className="space-y-4">
<div className="space-y-5">
{/* Overall Waste Metrics */}
<div className="grid grid-cols-3 gap-4">
<div className="p-3 bg-[var(--bg-secondary)] rounded-lg text-center">
<div className="p-4 bg-[var(--color-error)]/10 border border-[var(--color-error)]/20 rounded-lg text-center hover:border-[var(--color-error)]/40 transition-colors">
<div className="flex items-center justify-center space-x-2 mb-1">
<Trash2 className="w-4 h-4 text-red-600" />
<span className="text-lg font-bold text-[var(--text-primary)]">
<Trash2 className="w-5 h-5 text-[var(--color-error)]" />
<span className="text-2xl font-bold text-[var(--color-error)]">
{totalWastePercentage.toFixed(1)}%
</span>
</div>
<p className="text-xs text-[var(--text-secondary)]">{t('quality.total_waste')}</p>
<p className="text-xs text-[var(--text-secondary)] font-medium">{t('quality.total_waste')}</p>
</div>
<div className="p-3 bg-[var(--bg-secondary)] rounded-lg text-center">
<div className="p-4 bg-[var(--color-warning)]/10 border border-[var(--color-warning)]/20 rounded-lg text-center hover:border-[var(--color-warning)]/40 transition-colors">
<div className="flex items-center justify-center space-x-2 mb-1">
<AlertTriangle className="w-4 h-4 text-orange-600" />
<span className="text-lg font-bold text-[var(--text-primary)]">
<AlertTriangle className="w-5 h-5 text-[var(--color-warning)]" />
<span className="text-2xl font-bold text-[var(--color-warning)]">
{wasteData.totalDefects}
</span>
</div>
<p className="text-xs text-[var(--text-secondary)]">{t('quality.total_defects')}</p>
<p className="text-xs text-[var(--text-secondary)] font-medium">{t('quality.total_defects')}</p>
</div>
<div className="p-3 bg-[var(--bg-secondary)] rounded-lg text-center">
<div className="p-4 bg-[var(--color-success)]/10 border border-[var(--color-success)]/20 rounded-lg text-center hover:border-[var(--color-success)]/40 transition-colors">
<div className="flex items-center justify-center space-x-2 mb-1">
<TrendingDown className="w-4 h-4 text-green-600" />
<span className="text-lg font-bold text-[var(--text-primary)]">
<TrendingDown className="w-5 h-5 text-[var(--color-success)]" />
<span className="text-2xl font-bold text-[var(--color-success)]">
{totalWasteCost.toFixed(0)}
</span>
</div>
<p className="text-xs text-[var(--text-secondary)]">{t('cost.waste_cost')}</p>
<p className="text-xs text-[var(--text-secondary)] font-medium">{t('cost.waste_cost')}</p>
</div>
</div>
{/* Waste Status */}
<div className={`p-3 rounded-lg ${wasteStatus.bgColor}`}>
<div className={`p-4 rounded-lg ${wasteStatus.bgColor}`}>
<div className="flex items-center space-x-2">
<AlertTriangle className={`w-4 h-4 ${wasteStatus.color}`} />
<span className={`text-sm font-medium ${wasteStatus.color}`}>
<AlertTriangle className={`w-5 h-5 ${wasteStatus.color}`} />
<span className={`text-sm font-semibold ${wasteStatus.color}`}>
{t(`quality.status.${wasteStatus.status}`)}
</span>
</div>
@@ -285,28 +285,28 @@ export const WasteDefectTrackerWidget: React.FC = () => {
</div>
{/* Reduction Recommendations */}
<div className="space-y-2">
<div className="space-y-3">
{wasteSources.filter(s => s.severity === 'high').length > 0 && (
<div className="flex items-start space-x-2 p-3 bg-red-50 dark:bg-red-900/20 rounded-lg">
<AlertTriangle className="w-4 h-4 mt-0.5 text-red-600" />
<div>
<p className="text-sm font-medium text-red-600">
<div className="flex items-start space-x-3 p-4 bg-[var(--color-error)]/10 border border-[var(--color-error)]/20 rounded-lg">
<AlertTriangle className="w-5 h-5 mt-0.5 text-[var(--color-error)]" />
<div className="flex-1">
<p className="text-sm font-semibold text-[var(--color-error)] mb-1">
{t('quality.recommendations.high_waste_detected')}
</p>
<p className="text-xs text-[var(--text-secondary)] mt-1">
<p className="text-xs text-[var(--text-secondary)]">
{t('quality.recommendations.check_temperature_timing')}
</p>
</div>
</div>
)}
<div className="flex items-start space-x-2 p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
<Target className="w-4 h-4 mt-0.5 text-blue-600" />
<div>
<p className="text-sm font-medium text-blue-600">
<div className="flex items-start space-x-3 p-4 bg-[var(--color-info)]/10 border border-[var(--color-info)]/20 rounded-lg">
<Target className="w-5 h-5 mt-0.5 text-[var(--color-info)]" />
<div className="flex-1">
<p className="text-sm font-semibold text-[var(--color-info)] mb-1">
{t('quality.recommendations.improvement_opportunity')}
</p>
<p className="text-xs text-[var(--text-secondary)] mt-1">
<p className="text-xs text-[var(--text-secondary)]">
{totalWastePercentage > 5
? t('quality.recommendations.reduce_waste_target', { target: '3%' })
: t('quality.recommendations.maintain_quality_standards')

View File

@@ -1,88 +1,99 @@
{
"title": "Ekoizpena",
"subtitle": "Kudeatu zure ogindegiko ekoizpena",
"production_status": {
"PENDING": "Itxaroten",
"IN_PROGRESS": "Abian",
"COMPLETED": "Osatuta",
"CANCELLED": "Ezeztatuta",
"ON_HOLD": "Pausatuta",
"QUALITY_CHECK": "Kalitate-kontrola",
"FAILED": "Huts egin du"
},
"production_priority": {
"LOW": "Baxua",
"MEDIUM": "Ertaina",
"HIGH": "Altua",
"URGENT": "Larria"
},
"batch_status": {
"PLANNED": "Planifikatuta",
"IN_PROGRESS": "Abian",
"COMPLETED": "Osatuta",
"CANCELLED": "Ezeztatuta",
"ON_HOLD": "Pausatuta"
},
"quality_check_status": {
"PENDING": "Itxaroten",
"IN_PROGRESS": "Abian",
"PASSED": "Gaindituta",
"FAILED": "Huts egin du",
"REQUIRES_ATTENTION": "Arreta behar du"
},
"fields": {
"batch_number": "Sorta-zenbakia",
"production_date": "Ekoizpen-data",
"planned_quantity": "Planifikatutako kantitatea",
"actual_quantity": "Benetako kantitatea",
"yield_percentage": "Errendimendu-ehunekoa",
"priority": "Lehentasuna",
"assigned_staff": "Esleitutako langilea",
"production_notes": "Ekoizpen-oharrak",
"quality_score": "Kalitate-puntua",
"quality_notes": "Kalitate-oharrak",
"defect_rate": "Akats-tasa",
"rework_required": "Berregitea behar da",
"waste_quantity": "Hondakin-kantitatea",
"waste_reason": "Hondakinaren arrazoia",
"title": "Ekoizpen Kudeaketa",
"subtitle": "Planifikatu eta kontrolatu okindegiaren eguneroko ekoizpena",
"stats": {
"active_batches": "Sorta Aktiboak",
"todays_target": "Gaurko Helburua",
"capacity_utilization": "Ahalmen Erabilpena",
"on_time_completion": "Orduan Bukatuta",
"quality_score": "Kalitate Puntuazioa",
"total_output": "Ekoizpen Osoa",
"efficiency": "Eraginkortasuna",
"material_cost": "Material-kostua",
"labor_cost": "Lan-kostua",
"overhead_cost": "Indirektoko kostua",
"total_cost": "Kostu osoa",
"cost_per_unit": "Unitateko kostua"
"total_checks": "Kontrol Osoak",
"pass_rate": "Gainditu Tasa",
"average_score": "Batez Besteko Puntuazioa",
"failed_checks": "Huts Egindako Kontrolak",
"last_7_days": "Azken 7 egunak",
"passed": "gaindituta",
"out_of_10": "10etik",
"requiring_action": "Ekintza behar du",
"checks": "kontrolak",
"avg_score": "batez besteko puntuazioa",
"top_defects": "akats nagusiak",
"issues": "arazoak",
"defects": "akatsak",
"overall_efficiency": "Eraginkortasun Orokorra",
"vs_target_95": "vs %95 helburua",
"average_cost_per_unit": "Batez Besteko Kostua Unitateko",
"down_3_vs_last_week": "%3 aurreko astearekin alderatuta",
"active_equipment": "Ekipo Aktiboak",
"one_in_maintenance": "1 mantentze lanetan",
"excellent_standards": "Estandar bikainak",
"planned_batches": "Planifikatutako Sortak",
"batches": "sortak",
"best": "onena",
"no_yield_data": "Ez dago errendimendu daturik eskuragarri",
"product_leaderboard": "Produktuen Sailkapena",
"yield_comparison": "Errendimendu Konparaketa",
"weekly_yield_trend": "Asteko Errendimendu Joera",
"product_yield_rankings_trends": "Produktu errendimenduen sailkapena eta joera",
"average_yield": "Batez Besteko Errendimendua",
"best_yield": "Errendimendurik Onena",
"yield_trend": "Errendimendu Joera"
},
"actions": {
"start_production": "Hasi ekoizpena",
"complete_batch": "Osatu sorta",
"pause_production": "Pausatu ekoizpena",
"cancel_batch": "Ezeztatu sorta",
"quality_check": "Kalitate-kontrola",
"create_batch": "Sortu sorta",
"view_details": "Ikusi xehetasunak",
"edit_batch": "Editatu sorta",
"duplicate_batch": "Bikoiztu sorta"
"status": {
"pending": "Zain",
"in_progress": "Abian",
"completed": "Osatuta",
"cancelled": "Ezeztatuta",
"on_hold": "Pausatuta",
"quality_check": "Kalitate Kontrola",
"failed": "Huts Egin Du",
"operational": "Operatiboak",
"warning": "Abisua",
"maintenance": "Mantentze Lanak",
"down": "Itzalita",
"passed": "GAINDITUTA",
"complete": "Osoa",
"unknown": "Ezezaguna",
"excellent": "Bikaina",
"good": "Ona",
"critical": "Kritikoa"
},
"labels": {
"current_production": "Uneko ekoizpena",
"production_queue": "Ekoizpen-ilara",
"completed_today": "Gaur osatuta",
"efficiency_rate": "Eraginkortasun-tasa",
"quality_score": "Kalitate-puntua",
"active_batches": "Sorta aktiboak",
"pending_quality_checks": "Kalitate-kontrolak itxaroten"
"priority": {
"low": "Baxua",
"medium": "Ertaina",
"high": "Altua",
"urgent": "Larria"
},
"descriptions": {
"production_efficiency": "Uneko ekoizpenaren eraginkortasun-ehunekoa",
"quality_average": "Azken sorten batez besteko kalitate-puntua",
"waste_reduction": "Aurreko hilabetearekin alderatutako hondakin-murrizketa"
},
"equipment": {
"title": "Makinen egoera",
"subtitle": "Monitorizatu makinen osasuna eta errendimendua"
"batch": {
"title": "Ekoizpen Sorta",
"batch_number": "Sorta Zenbakia",
"product_name": "Produktu Izena",
"planned_quantity": "Planifikatutako Kantitatea",
"actual_quantity": "Benetako Kantitatea",
"planned_start": "Planifikatutako Hasiera",
"actual_start": "Benetako Hasiera",
"planned_end": "Planifikatutako Amaiera",
"actual_end": "Benetako Amaiera",
"staff_assigned": "Esleitutako Langilea",
"equipment_used": "Erabilitako Ekipoa",
"notes": "Oharrak",
"yield_percentage": "Errendimendua",
"duration": "Iraupena",
"cost": "Kostua",
"rush_order": "Eskaera Presazkoa",
"actual": "Erreala",
"staff": "Langilea",
"equipment": "Ekipoa"
},
"quality": {
"title": "Kalitate Kontrola",
"dashboard": {
"title": "Kalitate Panela",
"subtitle": "Jarraitu kalitate metrikak eta joerak",
"error": "Errorea kalitate datuak kargatzean"
},
"categories": {
"weight_check": "Pisu Kontrola",
"temperature_check": "Tenperatura Kontrola",
@@ -100,6 +111,557 @@
"time_check": "Denbora Kontrola",
"chemical": "Kimikoa",
"hygiene": "Higienea"
},
"check_types": {
"visual": "Ikusizko",
"visual_description": "Ikusizko inspekzioa",
"measurement": "Neurketa",
"measurement_description": "Neurri zehatzak",
"temperature": "Tenperatura",
"temperature_description": "Tenperatura kontrola",
"weight": "Pisua",
"weight_description": "Pisu kontrola",
"boolean": "Bai/Ez",
"boolean_description": "Bitar egiaztapena",
"timing": "Denbora",
"timing_description": "Denbora kontrola",
"checklist": "Egiaztapen zerrenda",
"checklist_description": "Egiaztapen zerrenda"
},
"inspection": {
"title": "Kalitate Inspekzioa",
"notes_placeholder": "Gehitu oharrak irizpide honetarako (aukerakoa)..."
},
"tabs": {
"overview": "Ikuspegi Orokorra",
"by_product": "Produktuka",
"categories": "Kategoriak",
"recent": "Azkenak",
"inspection": "Inspekzioa",
"photos": "Argazkiak",
"summary": "Laburpena"
},
"charts": {
"weekly_trends": "Asteko Kalitate Joera",
"placeholder": "Kalitate joera grafikoa hemen bistaratuko da"
},
"photos": {
"description": "Gehitu argazkiak kalitate arazoak edo frogak dokumentatzeko",
"upload": "Igo Argazkiak",
"upload_title": "Igo Kalitate Argazkiak",
"upload_help": "Hautatu irudi anitzak igotzeko"
},
"summary": {
"overall_score": "Kalitate Puntuazio Orokorra",
"results": "Inspekzio Emaitzak",
"final_notes": "Gehitu azken oharrak eta gomendioak..."
},
"actions": {
"new_check": "Kontrol Berria",
"view_trends": "Ikusi Joera",
"save_draft": "Gorde Zirriborroa",
"complete_inspection": "Osatu Inspekzioa",
"check_ingredients": "Egiaztatu Osagaiak",
"adjust_recipe": "Doitu Errezeta",
"view_details": "Ikusi Xehetasunak",
"reduce_waste": "Murriztu Hondakinak",
"focus_on": "Zentratu murriztean",
"investigate_increasing_defects": "Ikertu akats joeren hazkundea",
"review_process_controls": "Berrikusi prozesu kontrolak eta prestakuntza"
},
"required": "Derrigorrezkoa",
"optional": "Aukerakoa",
"trends": {
"vs_last_week": "vs aurreko astea"
},
"waste_defect_tracker": "Hondakin eta Akats Jarraitzailea",
"waste_sources_trends_costs": "Jarraitu hondakin iturriak, joerak eta kostu eragina",
"total_waste": "Hondakin Osoa",
"total_defects": "Akats Osoak",
"estimated_cost": "Estimatutako Kostua",
"no_waste_data": "Ez dago hondakin daturik eskuragarri",
"top_waste_sources": "Hondakin Iturri Nagusiak",
"waste_distribution": "Hondakin Banaketa",
"weekly_waste_trend": "Asteko Hondakin Joera",
"waste_percentage": "% Hondakinak",
"defect_percentage": "% Akatsak",
"incidents": "gertaerak",
"cost": "kostua",
"severity": {
"low": "Baxua",
"medium": "Ertaina",
"high": "Altua"
},
"trend": {
"up": "Igotzen",
"down": "Jaisten",
"stable": "Egonkorra"
},
"defects": {
"burnt": "Erreta",
"underproofed": "Gutxi Hartzituta",
"misshapen": "Desitxuratuta",
"color_issues": "Kolore Arazoak",
"texture_problems": "Testura Arazoak",
"temperature_issues": "Tenperatura Arazoak",
"expired": "Iraungita"
},
"recommendations": {
"high_waste_detected": "Hondakin maila altuak detektatuta",
"check_temperature_timing": "Egiaztatu labearen tenperaturak eta denbora ezarpenak emaitza optimoetarako.",
"improvement_opportunity": "Hondakin Murrizketa Aukera",
"reduce_waste_target": "Zentratu hondakinak {target} helburura murriztean.",
"maintain_quality_standards": "Jarraitu kalitate estandar bikainak mantentzen.",
"documentation": "Kalitate Dokumentazioa",
"photo_documentation_helps": "Argazki dokumentazioak akatsen sustraiko kausak identifikatzen laguntzen du.",
"critical_defects": "Akats Kritikoak Detektatuta",
"immediate_action_required": "Larritasun altuko akatsek arreta berehalakoa eta ekintza zuzentzailea behar dute.",
"improve_quality": "Kalitate Hobekuntza Beharrezkoa",
"focus_consistency": "Zentratu ekoizpen prozesuetan koherentzia hobetzean.",
"excellent_quality": "Kalitate Errendimendu Bikaina",
"maintain_standards": "Jarraitu estandar altu hauek mantentzen."
},
"recent_quality_scores": "Azken Kalitate Puntuazioak",
"daily_average_quality_trends": "Eguneroko batez besteko kalitate puntuazio joerak",
"daily_quality_score": "Eguneroko Kalitate Puntuazioa",
"score_distribution": "Puntuazio Banaketa",
"excellent": "Bikaina (9-10)",
"good": "Ona (8-9)",
"acceptable": "Onargarria (7-8)",
"poor": "Txarra (6-7)",
"failed": "Huts Egin Du (<6)",
"vs_last_week": "vs aurreko astea",
"no_quality_data": "Ez dago kalitate daturik eskuragarri",
"weekly_quality_trends": "Asteko Kalitate Joera",
"excellent_scores": "Bikaina",
"good_scores": "Ona",
"needs_improvement": "Hobekuntza Behar Du",
"top_defect_types_24h": "Akats Mota Nagusiak (Azken 24h)",
"defect_analysis_cost_impact": "Aztertu akats motak eta haien kostu eragina",
"no_defects_detected": "Ez da Akatsik Detektatu",
"excellent_quality_standards": "Kalitate estandar bikainak mantentzen produktu guztietan.",
"defect_breakdown": "Akats Xehetasuna",
"defect_distribution": "Akats Banaketa",
"top_defects_weekly_trend": "Akats Nagusiak - Asteko Joera",
"recommended_actions": "Gomendatutako Ekintzak"
},
"cost": {
"title": "Ekoizpen Kostu Jarraitzailea",
"subtitle": "Jarraitu eta optimizatu ekoizpen kostuak",
"total_cost": "Kostu Osoa",
"cost_per_unit": "Kostua Unitateko",
"labor": "Lan Kostua",
"materials": "Materialak",
"overhead": "Gastu Orokorrak",
"energy": "Energia",
"breakdown": "Kostu Banaketa",
"budget_usage": "Aurrekontu Erabilpena",
"over_budget": "Aurrekontu Gainetik",
"near_budget": "Aurrekontu Hurbil",
"on_budget": "Aurrekontuan",
"vs_yesterday": "vs atzo",
"average_today": "Batez bestekoa gaur",
"view_details": "Ikusi Xehetasunak",
"optimize": "Optimizatu Kostuak",
"error": "Errorea kostu datuak kargatzean",
"cost_per_unit_analysis": "Unitateko Kostu Analisia",
"estimated_vs_actual_costs": "Konparatu estimatutako vs benetako kostuak produktuka",
"average_cost_per_unit": "Batez Besteko Kostua Unitateko",
"total_production_cost": "Ekoizpen Kostu Osoa",
"no_cost_data_available": "Ez dago kostu daturik eskuragarri analisirako",
"estimated_vs_actual": "Estimatuta vs Erreala",
"product_cost_breakdown": "Kostu Banaketa Produktuka",
"estimated_cost": "Estimatutako Kostua",
"actual_cost": "Benetako Kostua",
"estimated": "Estimatuta",
"actual": "Erreala",
"variance": "Bariantza",
"cost_distribution": "Kostu Banaketa",
"units_produced": "Ekoitzitako unitateak",
"optimization_opportunity": "Kostu Optimizazio Aukera",
"high_variance_detected": "Kostu bariantza altua detektatuta produktu batzuetan. Berrikusi prezioak eta prozesuak.",
"costs_within_expected_range": "Kostuak espero den tartean daude. Jarraitu optimizazio aukerak monitorizatzen.",
"view_breakdown": "Ikusi Xehetasuna",
"waste_cost": "Hondakin Kostua"
},
"equipment": {
"title": "Ekipo Egoera",
"subtitle": "Jarraitu ekipoen osasuna eta errendimendua",
"manager": {
"title": "Ekipo Kudeaketa",
"subtitle": "Jarraitu eta kudeatu ekoizpen ekipoak"
},
"status": {
"operational": "Operatiboa",
"warning": "Abisua",
"maintenance": "Mantentze Lanak",
"down": "Itzalita",
"equipment_list": "Ekipo Zerrenda",
"distribution": "Egoera Banaketa"
},
"stats": {
"total": "Ekipo Osoak",
"operational": "Operatiboa",
"needs_attention": "Arreta Behar Du",
"efficiency": "Eraginkortasuna",
"avg_efficiency": "Batez Besteko Eraginkortasuna",
"alerts": "Alerta Aktiboak",
"by_equipment": "ekipoka"
},
"filter": {
"all": "Egoera Guztiak"
},
"tabs": {
"overview": "Ikuspegi Orokorra",
"maintenance": "Mantentze Lanak",
"alerts": "Alertak"
},
"maintenance": {
"title": "Mantentze Egutegia",
"subtitle": "Planifikatu eta jarraitu mantentze jarduerak",
"overdue": "Atzeratuta",
"scheduled": "Programatuta",
"last": "Azkena",
"next": "Hurrengoa",
"interval": "Tartea",
"history": "Historia",
"records": "erregistroak",
"avg_duration": "Batez Besteko Iraupena",
"total_cost": "Kostu Osoa",
"overdue_tasks": "Atzeratutako Zereginak",
"immediate_attention_required": "Arreta berehalakoa behar da",
"tasks": "Mantentze Zereginak",
"duration": "Iraupena",
"cost": "Kostua",
"technician": "Teknikaria",
"this_week": "Aste Honetako Egutegia",
"insights": {
"title": "Mantentze Ezaugarriak",
"completed_this_month": "zeregin osatuta hilabete honetan",
"scheduled_next_week": "programatutako zereginak hurrengo asterako"
},
"status": {
"scheduled": "Programatuta",
"in_progress": "Abian",
"completed": "Osatuta",
"overdue": "Atzeratuta"
},
"type": {
"preventive": "Prebentzioa",
"corrective": "Zuzentzailea",
"inspection": "Inspekzioa"
}
},
"alerts": {
"acknowledged": "Onartuta",
"new": "Berriak",
"acknowledge": "Onartu",
"maintenance_required": "Mantentze Lanak Beharrezkoak",
"equipment_in_maintenance": "ekipoak mantentze lanetan",
"active_alerts": "alerta aktiboak"
},
"search": {
"placeholder": "Bilatu ekipoak..."
},
"actions": {
"add": "Gehitu Ekipoa",
"export": "Esportatu",
"maintenance": "Mantentze Lanak",
"schedule_maintenance": "Programatu Mantentze Lanak",
"view_history": "Ikusi Historia"
},
"efficiency": {
"title": "Ekipo Eraginkortasuna",
"subtitle": "Jarraitu errendimendua eta optimizazio aukerak",
"average": "Batez Besteko Eraginkortasuna",
"current": "Unekoa",
"target": "Helburua",
"current_vs_target": "Uneko vs Helburu Eraginkortasuna",
"weekly_trends": "Asteko Eraginkortasun Joera",
"by_equipment": "Eraginkortasuna Ekipoka",
"analyze": "Aztertu",
"optimize": "Optimizatu",
"recommendations": "Eraginkortasun Gomendioak",
"recommendation_1": "Lehentasunezko Ekintza",
"recommendation_2": "Energia Optimizazioa",
"recommendation_3": "Prebentziozko Zaintza",
"needs_maintenance": "mantentze arreta behar du",
"optimize_energy_consumption": "Optimizatu energia kontsumoa punta orduetan",
"schedule_preventive_maintenance": "Programatu mantentze prebentiboa ekipo guztientzat"
},
"efficiency": "Eraginkortasuna",
"uptime": "Erabilgarritasun Denbora",
"location": "Kokapena",
"temperature": "Tenperatura",
"energy_usage": "Energia Erabilpena",
"energy_consumption": "Energia Kontsumoa",
"unread_alerts": "irakurri gabeko alertak",
"model": "Modeloa",
"serial": "Serie Zenbakia",
"install_date": "Instalazio Data",
"error": "Errorea ekipo datuak kargatzean",
"oven_capacity": "Labe Ahalmena",
"mixer_capacity": "Irabiagailu Ahalmena",
"coming_soon": "Laster",
"equipment_analytics_development": "Ekipo analisiak garatze prozesuan daude. Jarraitzaile aurreratua eta mantentze aurreikuspen ezaugarriak laster eskuragarri egongo dira.",
"units_per_hour": "unitateak/ordua",
"downtime": {
"total": "Geldi Egon Denbora Osoa"
},
"oee": {
"overall": "OEE Orokorra",
"breakdown": "OEE Xehetasuna",
"availability": "Erabilgarritasuna",
"performance": "Errendimendua",
"quality": "Kalitatea"
}
},
"ai": {
"title": "AI Ezaugarriak",
"subtitle": "AIaren gomendioak eta aurreikuspenak",
"high_impact": "Eragin Altua",
"potential_savings": "Aurrezpen Potentziala",
"confidence": "Batez Besteko Konfiantza",
"impact": "ERAGINA",
"insights": {
"reduce_energy_costs": "Murriztu Energia Kostuak %15ean",
"energy_description": "Doitu labearen ordutegiak elektrizitate tarifa merkeenak erabiltzeko. Estimatutako aurrezkia: €45/eguna",
"demand_increase": "Croissant Eskaera Igoera Aurreikusita",
"demand_description": "Eguraldiaren eta gertaeren datuek croissant eskaeran %40 igoera iradokitzen dute asteburu honetan",
"quality_decline": "Kalitate Puntuazio Beherakada Detektatuta",
"quality_description": "Ogiaren kalitatea %8 jaitsi da azken 3 egunetan. Egiaztatu irinaren hezetasun mailak",
"maintenance_due": "Mantentze Prebentiboa Gomendatuta",
"maintenance_description": "Irabiagailu #2k higadura goiztiar ereduak erakusten ditu. Programatu mantentzea akatsen prebentzioa"
},
"actions": {
"schedule_optimization": "Optimizatu Ordutegia",
"view_details": "Ikusi Xehetasunak",
"increase_production": "Handitu Ekoizpena",
"order_ingredients": "Eskatu Osagaiak",
"schedule_maintenance": "Programatu Mantentze Lanak",
"view_equipment": "Ikusi Ekipoa",
"train_model": "Trebatu Modeloa",
"implement_all": "Inplementatu Denak",
"acknowledge": "Onartu",
"implement": "Inplementatu"
},
"status": {
"active": "AI jarraitzailea aktibo",
"new": "Berria",
"acknowledged": "Onartuta",
"in_progress": "Abian",
"implemented": "Inplementatuta",
"dismissed": "Baztertuta"
},
"last_updated": "Eguneratuta duela 5m",
"error": "AI ezaugarriak aldi baterako ez daude eskuragarri",
"ai_insights_coming_soon": "AI Ezaugarriak Laster",
"ai_powered_recommendations_development": "AIak bultzatutako gomendioak eta aurreikuspen analisiak garatze prozesuan daude. Sartu beta programan goiz sarbidea izateko.",
"stats": {
"active_insights": "Ezaugarri Aktiboak",
"high_priority": "Lehentasun Altua",
"potential_savings": "Aurrezpen Potentziala",
"avg_confidence": "Batez Besteko Konfiantza"
},
"priority": {
"low": "Baxua",
"medium": "Ertaina",
"high": "Altua",
"critical": "Kritikoa"
},
"impact": {
"cost_savings": "Kostu Aurrezkia",
"efficiency_gain": "Eraginkortasun Irabazia",
"quality_improvement": "Kalitate Hobekuntza",
"risk_mitigation": "Arrisku Murrizketa"
},
"confidence": "Konfiantza",
"timeline": "Kronologia",
"equipment": "Ekipoa",
"high_priority_insights": "Lehentasun Altuko Ezaugarriak",
"all_insights": "Ezaugarri Guztiak",
"performance": {
"summary": "AI Errendimendu Laburpena",
"insights_implemented": "ezaugarriak inplementatuta hilabete honetan",
"in_savings_identified": "aurrezpen potentziala identifikatuta"
},
"predictive_maintenance": {
"title": "Mantentze Aurreikuspena",
"subtitle": "AIaren akatsen aurreikuspena eta mantentze optimizazioa",
"high_risk": "Arrisku Altuko Ekipoak",
"estimated_cost": "Estimatutako Kostua",
"potential_downtime": "Potentziala Geldi Egotea",
"avg_confidence": "Batez Besteko Konfiantza",
"high_risk_equipment": "Arrisku Altuko Ekipoak",
"immediate_attention_required": "Arreta berehalakoa behar da akatsak prebenitzeko",
"predictions": "Mantentze Aurreikuspenak",
"confidence": "Konfiantza",
"risk_score": "Arrisku Puntuazioa",
"days_until_failure": "Egun Akatsera Arte",
"condition": "Egoera",
"current_condition": "Uneko Egoera",
"affected_components": "Osagai Afektatuak",
"recommended_actions": "Gomendatutako Ekintzak",
"schedule": "Programatu",
"details": "Ikusi Xehetasunak",
"schedule_all": "Programatu Denak",
"retrain_model": "Berriro Trebatu Modeloa",
"condition_trends": "Ekipo Egoera Joera",
"risk_distribution": "Arrisku Banaketa",
"model_status": "ML Modelo Egoera",
"last_training": "Azken prestakuntza",
"yesterday": "atzo",
"accuracy": "Zehaztasuna",
"next_training": "Hurrengo prestakuntza",
"in_7_days": "7 egunetan",
"alert_type": {
"wear_prediction": "Higadura ereduak akats potentziala adierazten du",
"failure_risk": "Akats arrisku altua detektatuta",
"performance_degradation": "Errendimendu degradazioa detektatuta",
"component_replacement": "Osagaia ordezkatzea gomendatuta"
}
},
"severity": {
"low": "Baxua",
"medium": "Ertaina",
"high": "Altua",
"critical": "Kritikoa"
},
"risk": {
"low": "Arrisku Baxua",
"medium": "Arrisku Ertaina",
"high": "Arrisku Altua"
}
},
"actions": {
"create_batch": "Sortu Sorta",
"start_batch": "Hasi Sorta",
"complete_batch": "Osatu Sorta",
"view_details": "Ikusi Xehetasunak",
"edit": "Editatu",
"delete": "Ezabatu",
"schedule": "Programatu",
"optimize": "Optimizatu",
"export_report": "Esportatu Txostena",
"optimize_production": "Optimizatu Ekoizpena",
"analyze_delays": "Aztertu Atzerapenak",
"optimize_yields": "Optimizatu Errendimendua",
"refresh": "Freskatu",
"request_beta_access": "Eskatu Beta Sarbidea",
"join_ai_beta": "Sartu AI Beta",
"reduce_waste": "Murriztu Hondakinak",
"investigate_defects": "Ikertu Akatsak"
},
"tabs": {
"schedule": "Ordutegia",
"batches": "Ekoizpen Sortak",
"quality": "Kalitate Kontrola",
"overview": "Ikuspegi Orokorra",
"bakery_operations": "Okindegi Eragiketak",
"cost_efficiency": "Kostua eta Eraginkortasuna",
"quality_assurance": "Kalitate Bermea",
"equipment_maintenance": "Ekipoak eta Mantentze Lanak",
"ai_insights": "AI Ezaugarriak"
},
"forms": {
"batch_number": "Sorta Zenbakia",
"product_selection": "Produktu Hautapena",
"quantity": "Kantitatea",
"start_time": "Hasiera Ordua",
"end_time": "Amaiera Ordua",
"priority": "Lehentasuna",
"staff": "Esleitutako Langilea",
"equipment": "Ekipoa",
"notes": "Ekoizpen Oharrak"
},
"messages": {
"no_batches": "Ez da ekoizpen sortarik aurkitu",
"no_active_batches": "Ez dago ekoizpen sorta aktiborik. Sortu lehenengo sorta hasteko.",
"no_active_batches_description": "Sortu ekoizpen sorta berria progresioa jarraitzen hasteko.",
"no_batches_planned": "Ez dago sortarik planifikatuta gaurkoan",
"batch_created": "Ekoizpen sorta arrakastaz sortu da",
"batch_updated": "Ekoizpen sorta arrakastaz eguneratu da",
"batch_started": "Ekoizpen sorta hasi da",
"batch_completed": "Ekoizpen sorta osatu da"
},
"analytics": {
"production_analytics": "Ekoizpen Analisiak",
"advanced_insights_professionals_enterprises": "Analisi aurreratuak eta ezaugarriak profesionalentzat eta enpresentzat"
},
"subscription": {
"exclusive_professional_enterprise": "Eduki esklusiboa Professional eta Enterprise planentzat",
"advanced_production_analytics_description": "Ekoizpen analisi aurreratuak Professional eta Enterprise erabiltzaileentzat soilik eskuragarri daude. Eguneratu zure plana funtzionalitate guztietara sarbidea izateko.",
"upgrade_plan": "Eguneratu Plana"
},
"schedule": {
"todays_summary": "Gaurko Laburpena",
"shift_hours_batches_staff": "Txanda orduak, planifikatutako sortak eta langile kopurua",
"shift_hours": "Txanda Orduak",
"staff_count": "Langile Kopurua",
"capacity_utilization": "Ahalmen Erabilpena",
"planned_batches": "Planifikatutako Sortak",
"active": "Aktiboa",
"inactive": "Inaktiboa",
"finalized": "Finalizatuta",
"draft": "Zirriborroa",
"delayed": "atzeratuta",
"staff_capacity": "Langile Ahalmena",
"work_stations": "Lan Postuak"
},
"tracker": {
"live_batch_tracker": "Zuzeneko Sorta Jarraitzailea",
"current_batches_status_progress": "Uneko sortak egoera, progresio barra eta ETA",
"progress": "Progresioa",
"pending_start": "Hasiera Zain",
"issues": "Arazoak"
},
"insights": {
"on_time_vs_planned": "Sorta bukaerak vs planifikatutako ordutegia",
"vs_week_avg": "vs asteko batez bestekoa",
"target": "Helburua",
"progress_to_target": "Progresioa Helburura",
"weekly_trend": "Asteko Joera",
"performance_insight": "Errendimendu Ezaugarria",
"on_time_excellent": "Orduan bukatze errendimendu bikaina! Jarraitu lan bikainarekin.",
"on_time_good_room_improvement": "Errendimendu ona hobekuntza aukerarekin.",
"on_time_needs_attention": "Orduan bukatzeak arreta behar du. Berrikusi programazioa.",
"on_time_critical_delays": "Atzerapen kritikoak detektatuta. Ekintza berehalakoa behar da.",
"batches_on_time": "Orduan",
"batches_delayed": "Atzeratuta",
"avg_delay_minutes": "Batez Besteko Atzerapena (min)",
"resource_allocation_efficiency": "Jarraitu baliabide esleipena eta eraginkortasuna",
"resource_breakdown": "Baliabide Xehetasuna",
"hourly_utilization_pattern": "Orduko Erabilpen Eredua",
"peak_hours": "Punta Orduak",
"off_peak_optimal": "Puntaz Kanpo (Optimoa)",
"hourly_utilization": "Orduko Erabilpena"
},
"performance": {
"excellent": "Bikaina",
"good": "Ona",
"average": "Batez Bestekoa",
"poor": "Txarra",
"needs_improvement": "Hobekuntza Behar Du"
},
"recommendations": {
"yield_improvement": "Errendimendu Hobekuntza Aukera",
"focus_on_low_performers": "Zentratu errendimendu baxuko produktuak hobetzen eraginkortasun orokorra handitzeko.",
"maintain_high_standards": "Jarraitu errendimendu estandar altuak mantentzen produktu guztietan."
},
"common": {
"units": "unitateak",
"assigned": "esleituta",
"allocated": "esleituta",
"available": "eskuragarri"
},
"alerts": {
"capacity_critical": "Ahalmen Kritikoa",
"capacity_critical_description": "Baliabide batzuk gehieneko ahalmenean daude. Kontuan hartu lan karga birbanatzea.",
"capacity_high": "Ahalmen Erabilpen Altua",
"capacity_high_description": "Jarraitu hurbil eztarriak prebenitzeko."
},
"mobile": {
"optimized_experience": "Mugikorretarako Optimizatutako Esperientzia",
"swipe_scroll_interact": "Ukitu, korritu eta sakatu analisi widget guztiekin elkarreragiteko."
}
}
}