fix: gửi vị trí khẩn cấp trong Dashboard

This commit is contained in:
2026-06-23 12:44:38 +07:00
parent 6b15e7ff02
commit 5145835c8a
6 changed files with 250 additions and 69 deletions
+48 -44
View File
@@ -1,6 +1,6 @@
import { useState, useEffect, useMemo } from 'react';
import { format, differenceInMinutes, parseISO } from 'date-fns';
import { CheckCircle2, Circle, Clock, MapPin, AlertCircle, Zap, Navigation, Edit2, Trash2, Plus, List, X, Calendar as CalendarIcon, AlignLeft, MessageSquare, FileText, Flag } from 'lucide-react';
import { CheckCircle2, Circle, Clock, MapPin, AlertCircle, Zap, Navigation, Edit2, Trash2, Plus, List, X, Calendar as CalendarIcon, AlignLeft, MessageSquare, FileText, Flag, ChevronDown } from 'lucide-react';
import { useTourStore } from '@/store/useTourStore';
import { useConfirm } from '@/hooks/useConfirm';
import { useNotification } from '@/hooks/useNotification';
@@ -57,7 +57,6 @@ export const ItineraryTimeline = ({
const currentTour = useTourStore(state => state.currentTour);
const legs = useTourStore(state => state.legs);
const userRole = useTourStore(state => state.userRole);
const optimizeRouting = useTourStore(state => state.optimizeRouting);
const addLeg = useTourStore(state => state.addLeg);
const updateLeg = useTourStore(state => state.updateLeg);
// Removed: const { isPublicView } = useTourStore(state => state); // isPublicView is passed as a prop
@@ -259,32 +258,47 @@ export const ItineraryTimeline = ({
</div>
)}
</div>
<div className="flex items-center gap-2 ml-4" onClick={(e) => e.stopPropagation()}>
{canEdit && (
<>
<button
onClick={(e) => { e.stopPropagation(); onAddLocation?.(leg.id, legIdx === 0 && leg.locations.length === 0); }}
className="p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-xl transition-all"
title="Thêm địa điểm vào chặng này"
>
<Plus className="w-4 h-4" />
</button>
<button
onClick={(e) => { e.stopPropagation(); handleEditLeg(leg); }}
className="p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-xl transition-all"
>
<Edit2 className="w-4 h-4" />
</button>
<button
onClick={(e) => { e.stopPropagation(); handleDeleteLeg(leg.id); }}
className="p-2 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded-xl transition-all"
>
<Trash2 className="w-4 h-4" />
</button>
</>
)}
{leg.totalDistance !== undefined && (
<div className="hidden sm:flex items-center gap-2">
{/* Expand/Collapse indicator button */}
<button
onClick={(e) => { e.stopPropagation(); toggleStageExpanded(leg.id); }}
className="ml-2 p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-xl transition-all shrink-0"
title={expandedStageId === leg.id ? 'Collapse chặng này' : 'Expand chặng này'}
>
<ChevronDown
className={`w-5 h-5 transition-transform duration-300 ${
expandedStageId === leg.id ? 'rotate-180' : ''
}`}
/>
</button>
</div>
{/* Action Buttons Row - Below stage title */}
<div className="px-4 py-2 bg-white border-b border-gray-100 flex items-center gap-2 flex-wrap">
{canEdit && (
<>
<button
onClick={(e) => { e.stopPropagation(); onAddLocation?.(leg.id, legIdx === 0 && leg.locations.length === 0); }}
className="p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-xl transition-all"
title="Thêm địa điểm vào chặng này"
>
<Plus className="w-4 h-4" />
</button>
<button
onClick={(e) => { e.stopPropagation(); handleEditLeg(leg); }}
className="p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-xl transition-all"
>
<Edit2 className="w-4 h-4" />
</button>
<button
onClick={(e) => { e.stopPropagation(); handleDeleteLeg(leg.id); }}
className="p-2 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded-xl transition-all"
>
<Trash2 className="w-4 h-4" />
</button>
</>
)}
{leg.totalDistance !== undefined && (
<div className="flex items-center gap-2">
<div className="text-xs font-bold text-blue-600 bg-blue-50 px-2 py-1 rounded-lg border border-blue-100">
{leg.totalDistance} km
</div>
@@ -294,22 +308,12 @@ export const ItineraryTimeline = ({
</div>
</div>
)}
{totalDwellMinutes > 0 && ( // Always show dwell time
<div className="hidden md:flex text-xs font-bold text-amber-600 bg-amber-50 px-2 py-1 rounded-lg border border-amber-100 items-center gap-1">
<Clock className="w-3 h-3" />
Dừng: {formatTravelTime(totalDwellMinutes)}
</div>
)}
</div>
{['OWNER', 'MANAGER'].includes(userRole || '') && legs.length > 0 && (
<button
onClick={() => optimizeRouting(leg.id)}
className="ml-auto flex items-center gap-1.5 text-xs font-bold text-indigo-600 hover:text-indigo-700 bg-indigo-50 hover:bg-indigo-100 px-3 py-1.5 rounded-xl transition-all"
>
<Zap className="w-3 h-3" />
Tối ưu
</button>
)} {/* Only show optimize button if canEdit */}
{totalDwellMinutes > 0 && (
<div className="text-xs font-bold text-amber-600 bg-amber-50 px-2 py-1 rounded-lg border border-amber-100 items-center gap-1 flex">
<Clock className="w-3 h-3" />
Dừng: {formatTravelTime(totalDwellMinutes)}
</div>
)}
</div>
{/* Scrollable content body with proper z-index layering */}