Improve the frontend 3
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user