Improve the frontend 3

This commit is contained in:
Urtzi Alfaro
2025-10-30 21:08:07 +01:00
parent 36217a2729
commit 63f5c6d512
184 changed files with 21512 additions and 7442 deletions

View File

@@ -13,10 +13,11 @@ import { useDemoTour, shouldStartTour, clearTourStartPending } from '../../featu
import { useDashboardStats } from '../../api/hooks/dashboard';
import { usePurchaseOrder, useApprovePurchaseOrder, useRejectPurchaseOrder } from '../../api/hooks/purchase-orders';
import { useBatchDetails, useUpdateBatchStatus } from '../../api/hooks/production';
import { useRunDailyWorkflow } from '../../api';
import { ProductionStatusEnum } from '../../api';
import {
AlertTriangle,
Clock,
Clock,
Euro,
Package,
FileText,
@@ -28,9 +29,10 @@ import {
Factory,
Timer,
TrendingDown,
Leaf
Leaf,
Play
} from 'lucide-react';
import toast from 'react-hot-toast';
import { showToast } from '../../utils/toast';
const DashboardPage: React.FC = () => {
const { t } = useTranslation();
@@ -76,18 +78,43 @@ const DashboardPage: React.FC = () => {
const approvePOMutation = useApprovePurchaseOrder();
const rejectPOMutation = useRejectPurchaseOrder();
const updateBatchStatusMutation = useUpdateBatchStatus();
const orchestratorMutation = useRunDailyWorkflow();
const handleRunOrchestrator = async () => {
try {
await orchestratorMutation.mutateAsync(currentTenant?.id || '');
showToast.success('Flujo de planificación ejecutado exitosamente');
} catch (error) {
console.error('Error running orchestrator:', error);
showToast.error('Error al ejecutar flujo de planificación');
}
};
useEffect(() => {
console.log('[Dashboard] Demo mode:', isDemoMode);
console.log('[Dashboard] Should start tour:', shouldStartTour());
console.log('[Dashboard] SessionStorage demo_tour_should_start:', sessionStorage.getItem('demo_tour_should_start'));
console.log('[Dashboard] SessionStorage demo_tour_start_step:', sessionStorage.getItem('demo_tour_start_step'));
if (isDemoMode && shouldStartTour()) {
// Check if there's a tour intent from redirection (higher priority)
const shouldStartFromRedirect = sessionStorage.getItem('demo_tour_should_start') === 'true';
const redirectStartStep = parseInt(sessionStorage.getItem('demo_tour_start_step') || '0', 10);
if (isDemoMode && (shouldStartTour() || shouldStartFromRedirect)) {
console.log('[Dashboard] Starting tour in 1.5s...');
const timer = setTimeout(() => {
console.log('[Dashboard] Executing startTour()');
startTour();
clearTourStartPending();
if (shouldStartFromRedirect) {
// Start tour from the specific step that was intended
startTour(redirectStartStep);
// Clear the redirect intent
sessionStorage.removeItem('demo_tour_should_start');
sessionStorage.removeItem('demo_tour_start_step');
} else {
// Start tour normally (from beginning or resume)
startTour();
clearTourStartPending();
}
}, 1500);
return () => clearTimeout(timer);
@@ -114,10 +141,10 @@ const DashboardPage: React.FC = () => {
batchId,
statusUpdate: { status: ProductionStatusEnum.IN_PROGRESS }
});
toast.success('Lote iniciado');
showToast.success('Lote iniciado');
} catch (error) {
console.error('Error starting batch:', error);
toast.error('Error al iniciar lote');
showToast.error('Error al iniciar lote');
}
};
@@ -128,10 +155,10 @@ const DashboardPage: React.FC = () => {
batchId,
statusUpdate: { status: ProductionStatusEnum.ON_HOLD }
});
toast.success('Lote pausado');
showToast.success('Lote pausado');
} catch (error) {
console.error('Error pausing batch:', error);
toast.error('Error al pausar lote');
showToast.error('Error al pausar lote');
}
};
@@ -147,10 +174,10 @@ const DashboardPage: React.FC = () => {
poId,
notes: 'Aprobado desde el dashboard'
});
toast.success('Orden aprobada');
showToast.success('Orden aprobada');
} catch (error) {
console.error('Error approving PO:', error);
toast.error('Error al aprobar orden');
showToast.error('Error al aprobar orden');
}
};
@@ -161,10 +188,10 @@ const DashboardPage: React.FC = () => {
poId,
reason: 'Rechazado desde el dashboard'
});
toast.success('Orden rechazada');
showToast.success('Orden rechazada');
} catch (error) {
console.error('Error rejecting PO:', error);
toast.error('Error al rechazar orden');
showToast.error('Error al rechazar orden');
}
};
@@ -355,6 +382,18 @@ const DashboardPage: React.FC = () => {
<PageHeader
title={t('dashboard:title', 'Dashboard')}
description={t('dashboard:subtitle', 'Overview of your bakery operations')}
actions={[
{
id: 'run-orchestrator',
label: orchestratorMutation.isPending ? 'Ejecutando...' : 'Ejecutar Planificación Diaria',
icon: Play,
onClick: handleRunOrchestrator,
variant: 'primary', // Primary button for visibility
size: 'sm',
disabled: orchestratorMutation.isPending,
loading: orchestratorMutation.isPending
}
]}
/>
{/* Critical Metrics using StatsGrid */}
@@ -447,12 +486,12 @@ const DashboardPage: React.FC = () => {
poId: poDetails.id,
notes: 'Aprobado desde el dashboard'
});
toast.success('Orden aprobada');
showToast.success('Orden aprobada');
setShowPOModal(false);
setSelectedPOId(null);
} catch (error) {
console.error('Error approving PO:', error);
toast.error('Error al aprobar orden');
showToast.error('Error al aprobar orden');
}
},
variant: 'primary' as const,
@@ -467,12 +506,12 @@ const DashboardPage: React.FC = () => {
poId: poDetails.id,
reason: 'Rechazado desde el dashboard'
});
toast.success('Orden rechazada');
showToast.success('Orden rechazada');
setShowPOModal(false);
setSelectedPOId(null);
} catch (error) {
console.error('Error rejecting PO:', error);
toast.error('Error al rechazar orden');
showToast.error('Error al rechazar orden');
}
},
variant: 'outline' as const,
@@ -521,12 +560,12 @@ const DashboardPage: React.FC = () => {
batchId: batchDetails.id,
statusUpdate: { status: ProductionStatusEnum.IN_PROGRESS }
});
toast.success('Lote iniciado');
showToast.success('Lote iniciado');
setShowBatchModal(false);
setSelectedBatchId(null);
} catch (error) {
console.error('Error starting batch:', error);
toast.error('Error al iniciar lote');
showToast.error('Error al iniciar lote');
}
},
variant: 'primary' as const,
@@ -542,12 +581,12 @@ const DashboardPage: React.FC = () => {
batchId: batchDetails.id,
statusUpdate: { status: ProductionStatusEnum.ON_HOLD }
});
toast.success('Lote pausado');
showToast.success('Lote pausado');
setShowBatchModal(false);
setSelectedBatchId(null);
} catch (error) {
console.error('Error pausing batch:', error);
toast.error('Error al pausar lote');
showToast.error('Error al pausar lote');
}
},
variant: 'outline' as const,
@@ -561,4 +600,4 @@ const DashboardPage: React.FC = () => {
);
};
export default DashboardPage;
export default DashboardPage;