fix: sửa lại cho phép chỉnh sửa thời gian bắt đầu và kết thúc của điểm xuất phát và điểm kết thúc

This commit is contained in:
2026-06-17 19:46:55 +07:00
parent 2afb2971da
commit b6551da147
5 changed files with 23 additions and 12 deletions
+4 -2
View File
@@ -419,7 +419,7 @@ let TourController = class TourController {
}); });
} }
async updateTourStartPoint(tourId, body, req) { async updateTourStartPoint(tourId, body, req) {
const { latitude, longitude, name } = body; const { latitude, longitude, name, plannedEnd } = body;
console.log(`[USER ACTION] User ${req.user.id} set START point for Tour ${tourId}: "${name}" at [${latitude}, ${longitude}]`); console.log(`[USER ACTION] User ${req.user.id} set START point for Tour ${tourId}: "${name}" at [${latitude}, ${longitude}]`);
await this.prisma.location.deleteMany({ await this.prisma.location.deleteMany({
where: { where: {
@@ -441,6 +441,7 @@ let TourController = class TourController {
type: 'MOVE', type: 'MOVE',
legId: firstLeg.id, legId: firstLeg.id,
plannedStart: new Date(0), plannedStart: new Date(0),
plannedEnd: plannedEnd ? new Date(plannedEnd) : null,
} }
}).then(async (loc) => { }).then(async (loc) => {
await Promise.all([ await Promise.all([
@@ -452,7 +453,7 @@ let TourController = class TourController {
}); });
} }
async updateTourEndPoint(tourId, body, req) { async updateTourEndPoint(tourId, body, req) {
const { latitude, longitude, name } = body; const { latitude, longitude, name, plannedStart } = body;
console.log(`[USER ACTION] User ${req.user.id} set END point for Tour ${tourId}: "${name}" at [${latitude}, ${longitude}]`); console.log(`[USER ACTION] User ${req.user.id} set END point for Tour ${tourId}: "${name}" at [${latitude}, ${longitude}]`);
await this.prisma.location.deleteMany({ await this.prisma.location.deleteMany({
where: { where: {
@@ -473,6 +474,7 @@ let TourController = class TourController {
longitude, longitude,
type: 'MOVE', type: 'MOVE',
legId: lastLeg.id, legId: lastLeg.id,
plannedStart: plannedStart ? new Date(plannedStart) : null,
plannedEnd: new Date(0), plannedEnd: new Date(0),
} }
}).then(async (loc) => { }).then(async (loc) => {
+1 -1
View File
File diff suppressed because one or more lines are too long
+4 -2
View File
@@ -396,7 +396,7 @@ class TourController {
@UseGuards(JwtAuthGuard, TourRoleGuard) @UseGuards(JwtAuthGuard, TourRoleGuard)
@Post(':tourId/start-point') @Post(':tourId/start-point')
async updateTourStartPoint(@Param('tourId', ParseUUIDPipe) tourId: string, @Body() body: any, @Req() req: any) { async updateTourStartPoint(@Param('tourId', ParseUUIDPipe) tourId: string, @Body() body: any, @Req() req: any) {
const { latitude, longitude, name } = body; const { latitude, longitude, name, plannedEnd } = body;
console.log(`[USER ACTION] User ${req.user.id} set START point for Tour ${tourId}: "${name}" at [${latitude}, ${longitude}]`); console.log(`[USER ACTION] User ${req.user.id} set START point for Tour ${tourId}: "${name}" at [${latitude}, ${longitude}]`);
@@ -426,6 +426,7 @@ class TourController {
type: 'MOVE', type: 'MOVE',
legId: firstLeg.id, legId: firstLeg.id,
plannedStart: new Date(0), plannedStart: new Date(0),
plannedEnd: plannedEnd ? new Date(plannedEnd) : null,
} }
}).then(async (loc) => { }).then(async (loc) => {
await Promise.all([ await Promise.all([
@@ -441,7 +442,7 @@ class TourController {
@UseGuards(JwtAuthGuard, TourRoleGuard) @UseGuards(JwtAuthGuard, TourRoleGuard)
@Post(':tourId/end-point') @Post(':tourId/end-point')
async updateTourEndPoint(@Param('tourId', ParseUUIDPipe) tourId: string, @Body() body: any, @Req() req: any) { async updateTourEndPoint(@Param('tourId', ParseUUIDPipe) tourId: string, @Body() body: any, @Req() req: any) {
const { latitude, longitude, name } = body; const { latitude, longitude, name, plannedStart } = body;
console.log(`[USER ACTION] User ${req.user.id} set END point for Tour ${tourId}: "${name}" at [${latitude}, ${longitude}]`); console.log(`[USER ACTION] User ${req.user.id} set END point for Tour ${tourId}: "${name}" at [${latitude}, ${longitude}]`);
@@ -468,6 +469,7 @@ class TourController {
longitude, longitude,
type: 'MOVE', type: 'MOVE',
legId: lastLeg.id, legId: lastLeg.id,
plannedStart: plannedStart ? new Date(plannedStart) : null,
plannedEnd: new Date(0), // Đánh dấu đây là điểm kết thúc đặc biệt plannedEnd: new Date(0), // Đánh dấu đây là điểm kết thúc đặc biệt
} }
}).then(async (loc) => { }).then(async (loc) => {
+5 -1
View File
@@ -108,7 +108,9 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin
expenseDescription: expense?.description || '', expenseDescription: expense?.description || '',
expenseNote: expense?.note || '', expenseNote: expense?.note || '',
paidById: expense?.paidById || '', paidById: expense?.paidById || '',
plannedStart: editingLocation.plannedStart ? editingLocation.plannedStart.slice(0, 16) : '', plannedStart: isStartPoint
? (editingLocation.plannedEnd ? editingLocation.plannedEnd.slice(0, 16) : '')
: (editingLocation.plannedStart ? editingLocation.plannedStart.slice(0, 16) : ''),
plannedEnd: editingLocation.plannedEnd ? editingLocation.plannedEnd.slice(0, 16) : '' plannedEnd: editingLocation.plannedEnd ? editingLocation.plannedEnd.slice(0, 16) : ''
}); });
} else { } else {
@@ -291,12 +293,14 @@ export const AddLocationModal = ({ isOpen, onClose, tourId, initialLegId, editin
name: formData.name || "Điểm xuất phát", name: formData.name || "Điểm xuất phát",
latitude: parseFloat(formData.latitude as any), latitude: parseFloat(formData.latitude as any),
longitude: parseFloat(formData.longitude as any), longitude: parseFloat(formData.longitude as any),
plannedEnd: formData.plannedStart,
}); });
} else if (isEndPoint) { } else if (isEndPoint) {
await updateTourEndPoint(tourId, { await updateTourEndPoint(tourId, {
name: formData.name || "Điểm kết thúc", name: formData.name || "Điểm kết thúc",
latitude: parseFloat(formData.latitude as any), latitude: parseFloat(formData.latitude as any),
longitude: parseFloat(formData.longitude as any), longitude: parseFloat(formData.longitude as any),
plannedStart: formData.plannedStart,
}); });
} else { } else {
const payload: any = { const payload: any = {
@@ -352,16 +352,19 @@ export const ItineraryTimeline = ({
? calculateDistance(prevLocation.latitude, prevLocation.longitude, location.latitude, location.longitude) ? calculateDistance(prevLocation.latitude, prevLocation.longitude, location.latitude, location.longitude)
: null; : null;
const dwellMinutes = (location.plannedStart && location.plannedEnd)
? differenceInMinutes(parseISO(location.plannedEnd), parseISO(location.plannedStart))
: null;
const locationExpense = leg.expenses?.find((e: any) => e.locationId === location.id); const locationExpense = leg.expenses?.find((e: any) => e.locationId === location.id);
// Nhận diện điểm mốc dựa trên timestamp đặc biệt (0) thay vì chỉ số mảng // Nhận diện điểm mốc dựa trên timestamp đặc biệt (0) thay vì chỉ số mảng
const isStartPoint = location.plannedStart && new Date(location.plannedStart).getTime() === 0; const isStartPoint = location.plannedStart && new Date(location.plannedStart).getTime() === 0;
const isEndPoint = location.plannedEnd && new Date(location.plannedEnd).getTime() === 0; const isEndPoint = location.plannedEnd && new Date(location.plannedEnd).getTime() === 0;
const plannedTimeStr = isStartPoint ? location.plannedEnd : location.plannedStart;
const hasValidPlannedTime = plannedTimeStr && new Date(plannedTimeStr).getTime() !== 0;
const dwellMinutes = (location.plannedStart && location.plannedEnd && !isStartPoint && !isEndPoint)
? differenceInMinutes(parseISO(location.plannedEnd), parseISO(location.plannedStart))
: null;
return ( return (
<div key={location.id}> <div key={location.id}>
<div className="relative flex group mb-6"> <div className="relative flex group mb-6">
@@ -453,7 +456,7 @@ export const ItineraryTimeline = ({
</div> </div>
<div className="flex items-center text-sm font-black text-blue-600"> <div className="flex items-center text-sm font-black text-blue-600">
<Clock className="w-3 h-3 mr-1" /> <Clock className="w-3 h-3 mr-1" />
{location.plannedStart ? format(parseISO(location.plannedStart), 'HH:mm') : '--:--'} {hasValidPlannedTime ? format(parseISO(plannedTimeStr), 'HH:mm') : '--:--'}
</div> </div>
{location.status === 'COMPLETED' && location.actualStart && ( {location.status === 'COMPLETED' && location.actualStart && (
<div className="text-[10px] text-gray-400 mt-1 italic"> <div className="text-[10px] text-gray-400 mt-1 italic">
@@ -474,7 +477,7 @@ export const ItineraryTimeline = ({
</div> </div>
{/* Logic tính toán độ lệch thời gian */} {/* Logic tính toán độ lệch thời gian */}
<TimeVariance planned={location.plannedStart || ''} actual={location.actualStart || null} /> <TimeVariance planned={hasValidPlannedTime ? plannedTimeStr : ''} actual={location.actualStart || null} />
</div> </div>
</div> </div>