fix demo session 2
This commit is contained in:
@@ -22,7 +22,7 @@ interface DistributionTabProps {
|
||||
const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDate, onDateChange }) => {
|
||||
const { t } = useTranslation('dashboard');
|
||||
const { currencySymbol } = useTenantCurrency();
|
||||
|
||||
|
||||
// Get distribution data
|
||||
const {
|
||||
data: distributionOverview,
|
||||
@@ -34,8 +34,8 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
});
|
||||
|
||||
// Real-time SSE events
|
||||
const { events: sseEvents, isConnected: sseConnected } = useSSEEvents({
|
||||
channels: ['*.alerts', '*.notifications', 'recommendations']
|
||||
const { events: sseEvents, isConnected: sseConnected } = useSSEEvents({
|
||||
channels: ['*.alerts', '*.notifications', 'recommendations']
|
||||
});
|
||||
|
||||
// State for real-time delivery status
|
||||
@@ -63,8 +63,8 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
if (sseEvents.length === 0) return;
|
||||
|
||||
// Filter delivery and distribution-related events
|
||||
const deliveryEvents = sseEvents.filter(event =>
|
||||
event.event_type.includes('delivery_') ||
|
||||
const deliveryEvents = sseEvents.filter((event: any) =>
|
||||
event.event_type.includes('delivery_') ||
|
||||
event.event_type.includes('route_') ||
|
||||
event.event_type.includes('shipment_') ||
|
||||
event.entity_type === 'delivery' ||
|
||||
@@ -125,39 +125,7 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
|
||||
const isLoading = isDistributionLoading;
|
||||
|
||||
// Mock route data - in Phase 2 this will come from real API
|
||||
const mockRoutes = [
|
||||
{
|
||||
id: 'route-1',
|
||||
name: 'Madrid → Barcelona',
|
||||
status: 'in_transit',
|
||||
distance: '620 km',
|
||||
duration: '6h 30m',
|
||||
stops: 3,
|
||||
optimizationSavings: '12 km (1.9%)',
|
||||
vehicles: ['TRUCK-001', 'TRUCK-002']
|
||||
},
|
||||
{
|
||||
id: 'route-2',
|
||||
name: 'Barcelona → Valencia',
|
||||
status: 'completed',
|
||||
distance: '350 km',
|
||||
duration: '4h 15m',
|
||||
stops: 2,
|
||||
optimizationSavings: '8 km (2.3%)',
|
||||
vehicles: ['VAN-005']
|
||||
},
|
||||
{
|
||||
id: 'route-3',
|
||||
name: 'Central → Outlets (Daily)',
|
||||
status: 'pending',
|
||||
distance: '180 km',
|
||||
duration: '3h 00m',
|
||||
stops: 5,
|
||||
optimizationSavings: '25 km (13.9%)',
|
||||
vehicles: ['TRUCK-003', 'VAN-006', 'VAN-007']
|
||||
}
|
||||
];
|
||||
// No mockRoutes anymore, using distributionOverview.route_sequences
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
@@ -167,7 +135,7 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
<Truck className="w-6 h-6 text-[var(--color-primary)]" />
|
||||
{t('enterprise.distribution_summary')}
|
||||
</h2>
|
||||
|
||||
|
||||
{/* Date selector */}
|
||||
<div className="mb-4 flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -219,7 +187,7 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
{deliveryStatus.onTime}
|
||||
</div>
|
||||
<p className="text-xs text-[var(--text-secondary)] mt-1">
|
||||
{deliveryStatus.total > 0
|
||||
{deliveryStatus.total > 0
|
||||
? `${Math.round((deliveryStatus.onTime / deliveryStatus.total) * 100)}% ${t('enterprise.on_time_rate')}`
|
||||
: t('enterprise.no_deliveries')}
|
||||
</p>
|
||||
@@ -354,7 +322,7 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
{t('enterprise.active_routes')}
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{mockRoutes.map((route) => {
|
||||
{(distributionOverview?.route_sequences || []).map((route: any) => {
|
||||
// Determine status configuration
|
||||
const getStatusConfig = () => {
|
||||
switch (route.status) {
|
||||
@@ -364,15 +332,15 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
text: t('enterprise.route_completed'),
|
||||
icon: CheckCircle2
|
||||
};
|
||||
case 'delayed':
|
||||
case 'overdue':
|
||||
case 'failed':
|
||||
case 'cancelled':
|
||||
return {
|
||||
color: '#ef4444', // red-500
|
||||
text: t('enterprise.route_delayed'),
|
||||
icon: AlertTriangle,
|
||||
isCritical: true
|
||||
};
|
||||
case 'in_transit':
|
||||
case 'in_progress':
|
||||
return {
|
||||
color: '#3b82f6', // blue-500
|
||||
text: t('enterprise.route_in_transit'),
|
||||
@@ -390,29 +358,35 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
|
||||
const statusConfig = getStatusConfig();
|
||||
|
||||
// Format optimization savings
|
||||
const savings = route.vrp_optimization_savings || {};
|
||||
const distanceSavedText = savings.distance_saved_km
|
||||
? `${savings.distance_saved_km.toFixed(1)} km`
|
||||
: '0 km';
|
||||
|
||||
return (
|
||||
<StatusCard
|
||||
key={route.id}
|
||||
id={route.id}
|
||||
statusIndicator={statusConfig}
|
||||
title={route.name}
|
||||
subtitle={`${t('enterprise.distance')}: ${route.distance}`}
|
||||
primaryValue={route.duration}
|
||||
title={`${t('enterprise.route')} #${route.route_number || 'N/A'}`}
|
||||
subtitle={`${t('enterprise.distance')}: ${route.total_distance_km?.toFixed(1) || 0} km`}
|
||||
primaryValue={`${route.estimated_duration_minutes || 0} min`}
|
||||
primaryValueLabel={t('enterprise.estimated_duration')}
|
||||
secondaryInfo={{
|
||||
label: t('enterprise.stops'),
|
||||
value: `${route.stops}`
|
||||
value: `${route.route_sequence?.length || 0}`
|
||||
}}
|
||||
progress={{
|
||||
label: t('enterprise.optimization'),
|
||||
percentage: route.status === 'completed' ? 100 :
|
||||
route.status === 'in_transit' ? 75 :
|
||||
route.status === 'delayed' ? 50 : 25,
|
||||
percentage: route.status === 'completed' ? 100 :
|
||||
route.status === 'in_progress' ? 75 :
|
||||
route.status === 'failed' ? 50 : 25,
|
||||
color: statusConfig.color
|
||||
}}
|
||||
metadata={[
|
||||
`${t('enterprise.optimization_savings')}: ${route.optimizationSavings}`,
|
||||
`${t('enterprise.vehicles')}: ${route.vehicles.join(', ')}`
|
||||
`${t('enterprise.optimization_savings')}: ${distanceSavedText}`,
|
||||
`${t('enterprise.vehicles')}: ${route.vehicle_id || t('common:not_available', 'N/A')}`
|
||||
]}
|
||||
actions={[
|
||||
{
|
||||
@@ -420,19 +394,25 @@ const DistributionTab: React.FC<DistributionTabProps> = ({ tenantId, selectedDat
|
||||
icon: Map,
|
||||
variant: 'outline',
|
||||
onClick: () => {
|
||||
// In Phase 2, this will navigate to route tracking page
|
||||
console.log(`Track route ${route.name}`);
|
||||
console.log(`Track route ${route.route_number}`);
|
||||
},
|
||||
priority: 'primary'
|
||||
}
|
||||
]}
|
||||
onClick={() => {
|
||||
// In Phase 2, this will navigate to route detail page
|
||||
console.log(`View route ${route.name}`);
|
||||
console.log(`View route ${route.route_number}`);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{(!distributionOverview?.route_sequences || distributionOverview.route_sequences.length === 0) && (
|
||||
<div className="col-span-1 sm:col-span-2 lg:col-span-3 py-12">
|
||||
<div className="text-center text-[var(--text-secondary)]">
|
||||
<Truck className="w-12 h-12 mx-auto mb-4 opacity-20" />
|
||||
<p>{t('enterprise.no_active_routes')}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user