Add improved production UI 4

This commit is contained in:
Urtzi Alfaro
2025-09-23 22:11:34 +02:00
parent 7892c5a739
commit 87310ced5f
17 changed files with 1658 additions and 296 deletions

View File

@@ -1,10 +1,9 @@
import React, { useState, useMemo } from 'react';
import { Calendar, TrendingUp, AlertTriangle, BarChart3, Download, Settings, Loader, Zap, Brain, Target, CloudRain, Sun, Thermometer, Package, Activity, Clock } from 'lucide-react';
import { Button, Card, Badge, Table, StatsGrid, StatusCard, getStatusColor } from '../../../../components/ui';
import type { TableColumn } from '../../../../components/ui';
import { Calendar, TrendingUp, AlertTriangle, BarChart3, Settings, Loader, Zap, Brain, Target, Activity } from 'lucide-react';
import { Button, Card, Badge, StatsGrid, StatusCard, getStatusColor } from '../../../../components/ui';
import { PageHeader } from '../../../../components/layout';
import { LoadingSpinner } from '../../../../components/shared';
import { DemandChart, ForecastTable } from '../../../../components/domain/forecasting';
import { DemandChart } from '../../../../components/domain/forecasting';
import { useTenantForecasts, useCreateSingleForecast } from '../../../../api/hooks/forecasting';
import { useIngredients } from '../../../../api/hooks/inventory';
import { useModels } from '../../../../api/hooks/training';
@@ -16,7 +15,6 @@ import { formatters } from '../../../../components/ui/Stats/StatsPresets';
const ForecastingPage: React.FC = () => {
const [selectedProduct, setSelectedProduct] = useState('');
const [forecastPeriod, setForecastPeriod] = useState('7');
const [viewMode, setViewMode] = useState<'chart' | 'table'>('chart');
const [isGenerating, setIsGenerating] = useState(false);
const [hasGeneratedForecast, setHasGeneratedForecast] = useState(false);
const [currentForecastData, setCurrentForecastData] = useState<ForecastResponse[]>([]);
@@ -132,63 +130,8 @@ const ForecastingPage: React.FC = () => {
}
};
// Transform forecast data for table display - only real data
const transformForecastsForTable = (forecasts: ForecastResponse[]) => {
return forecasts.map(forecast => ({
id: forecast.id,
product: forecast.inventory_product_id,
forecastDate: forecast.forecast_date,
forecastDemand: forecast.predicted_demand,
confidence: Math.round(forecast.confidence_level * 100),
confidenceRange: `${forecast.confidence_lower?.toFixed(1) || 'N/A'} - ${forecast.confidence_upper?.toFixed(1) || 'N/A'}`,
algorithm: forecast.algorithm,
}));
};
const forecastColumns: TableColumn[] = [
{
key: 'product',
title: 'Producto ID',
dataIndex: 'product',
},
{
key: 'forecastDate',
title: 'Fecha',
dataIndex: 'forecastDate',
render: (value) => new Date(value).toLocaleDateString('es-ES'),
},
{
key: 'forecastDemand',
title: 'Demanda Prevista',
dataIndex: 'forecastDemand',
render: (value) => (
<span className="font-medium text-[var(--color-info)]">{value?.toFixed(2) || 'N/A'}</span>
),
},
{
key: 'confidence',
title: 'Confianza',
dataIndex: 'confidence',
render: (value) => `${value}%`,
},
{
key: 'confidenceRange',
title: 'Rango de Confianza',
dataIndex: 'confidenceRange',
},
{
key: 'algorithm',
title: 'Algoritmo',
dataIndex: 'algorithm',
},
];
// Use either current forecast data or fetched data
const forecasts = currentForecastData.length > 0 ? currentForecastData : (forecastsData?.forecasts || []);
const transformedForecasts = transformForecastsForTable(forecasts);
const isLoading = forecastsLoading || ingredientsLoading || modelsLoading || isGenerating;
const hasError = forecastsError || ingredientsError || modelsError;
@@ -467,47 +410,19 @@ const ForecastingPage: React.FC = () => {
{products.find(p => p.id === selectedProduct)?.name} {forecastPeriod} días
</p>
</div>
<div className="flex items-center space-x-3">
<div className="flex rounded-lg border border-[var(--border-secondary)] overflow-hidden">
<Button
variant={viewMode === 'chart' ? 'primary' : 'outline'}
onClick={() => setViewMode('chart')}
size="sm"
>
<BarChart3 className="w-4 h-4 mr-1" />
Gráfico
</Button>
<Button
variant={viewMode === 'table' ? 'primary' : 'outline'}
onClick={() => setViewMode('table')}
size="sm"
>
<Package className="w-4 h-4 mr-1" />
Tabla
</Button>
</div>
<Button variant="outline" size="sm">
<Download className="w-4 h-4 mr-2" />
Exportar
</Button>
</div>
</div>
{/* Chart or Table */}
{/* Chart View */}
<div className="min-h-96">
{viewMode === 'chart' ? (
<DemandChart
data={forecasts}
product={selectedProduct}
period={forecastPeriod}
loading={isLoading}
error={hasError ? 'Error al cargar las predicciones' : null}
height={400}
title=""
/>
) : (
<ForecastTable forecasts={transformedForecasts} />
)}
<DemandChart
data={forecasts}
product={selectedProduct}
period={forecastPeriod}
loading={isLoading}
error={hasError ? 'Error al cargar las predicciones' : null}
height={400}
title=""
/>
</div>
</Card>