fix: replace new Date() with dayjs for DATE column display and sorting (refs #237)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 1m19s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 44s
Deploy to Staging / Verify Staging (pull_request) Successful in 4s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 4s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 1m19s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 44s
Deploy to Staging / Verify Staging (pull_request) Successful in 4s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 4s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
new Date("YYYY-MM-DD") parses as UTC midnight per ES2015. toLocaleDateString()
then displays in local time, shifting the date back one day for users west of
UTC. This caused the list view and edit dialog to show different dates.
Fixed in: MaintenanceRecordsList (display + sort + delete confirm),
VehicleDetailPage (display + sort), VehicleDetailMobile (display + sort),
MaintenanceRecordForm (receipt title), OwnershipCostsList (formatDate).
Sorting now uses string comparison (YYYY-MM-DD is lexicographically sortable).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -190,7 +190,7 @@ export const MaintenanceRecordForm: React.FC<MaintenanceRecordFormProps> = ({ ve
|
|||||||
const doc = await documentsApi.create({
|
const doc = await documentsApi.create({
|
||||||
vehicleId: data.vehicle_id,
|
vehicleId: data.vehicle_id,
|
||||||
documentType: 'manual',
|
documentType: 'manual',
|
||||||
title: `Maintenance Receipt - ${new Date(data.date).toLocaleDateString()}`,
|
title: `Maintenance Receipt - ${dayjs(data.date).format('M/D/YYYY')}`,
|
||||||
});
|
});
|
||||||
await documentsApi.upload(doc.id, capturedReceiptFile);
|
await documentsApi.upload(doc.id, capturedReceiptFile);
|
||||||
receiptDocumentId = doc.id;
|
receiptDocumentId = doc.id;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -74,14 +75,14 @@ export const MaintenanceRecordsList: React.FC<MaintenanceRecordsListProps> = ({
|
|||||||
|
|
||||||
// Sort records by date DESC (newest first)
|
// Sort records by date DESC (newest first)
|
||||||
const sortedRecords = [...records].sort(
|
const sortedRecords = [...records].sort(
|
||||||
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
|
(a, b) => b.date.localeCompare(a.date)
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
{sortedRecords.map((record) => {
|
{sortedRecords.map((record) => {
|
||||||
const dateText = new Date(record.date).toLocaleDateString();
|
const dateText = dayjs(record.date).format('M/D/YYYY');
|
||||||
const categoryDisplay = getCategoryDisplayName(record.category);
|
const categoryDisplay = getCategoryDisplayName(record.category);
|
||||||
const subtypeCount = record.subtypeCount || record.subtypes?.length || 0;
|
const subtypeCount = record.subtypeCount || record.subtypes?.length || 0;
|
||||||
|
|
||||||
@@ -204,7 +205,7 @@ export const MaintenanceRecordsList: React.FC<MaintenanceRecordsListProps> = ({
|
|||||||
</Typography>
|
</Typography>
|
||||||
{recordToDelete && (
|
{recordToDelete && (
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
|
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
|
||||||
{new Date(recordToDelete.date).toLocaleDateString()} -{' '}
|
{dayjs(recordToDelete.date).format('M/D/YYYY')} -{' '}
|
||||||
{getCategoryDisplayName(recordToDelete.category)}
|
{getCategoryDisplayName(recordToDelete.category)}
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import type { OwnershipCost, OwnershipCostType } from '../types/ownership-costs.types';
|
import type { OwnershipCost, OwnershipCostType } from '../types/ownership-costs.types';
|
||||||
import { useOwnershipCostsList, useDeleteOwnershipCost } from '../hooks/useOwnershipCosts';
|
import { useOwnershipCostsList, useDeleteOwnershipCost } from '../hooks/useOwnershipCosts';
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ export const OwnershipCostsList: React.FC<OwnershipCostsListProps> = ({ vehicleI
|
|||||||
};
|
};
|
||||||
|
|
||||||
const formatDate = (dateString: string): string => {
|
const formatDate = (dateString: string): string => {
|
||||||
return new Date(dateString).toLocaleDateString();
|
return dayjs(dateString).format('M/D/YYYY');
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { Box, Typography, Button, Card, CardContent, Divider, FormControl, InputLabel, Select, MenuItem, List, ListItem, ListItemButton, Dialog, DialogTitle, DialogContent } from '@mui/material';
|
import { Box, Typography, Button, Card, CardContent, Divider, FormControl, InputLabel, Select, MenuItem, List, ListItem, ListItemButton, Dialog, DialogTitle, DialogContent } from '@mui/material';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import { Vehicle } from '../types/vehicles.types';
|
import { Vehicle } from '../types/vehicles.types';
|
||||||
@@ -123,7 +124,7 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
return list.sort((a, b) => b.date.localeCompare(a.date));
|
||||||
}, [fuelLogs]);
|
}, [fuelLogs]);
|
||||||
|
|
||||||
const filteredRecords = useMemo(() => {
|
const filteredRecords = useMemo(() => {
|
||||||
@@ -286,7 +287,7 @@ export const VehicleDetailMobile: React.FC<VehicleDetailMobileProps> = ({
|
|||||||
</Box>
|
</Box>
|
||||||
{/* Secondary line: Grade • Date • Type */}
|
{/* Secondary line: Grade • Date • Type */}
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.25 }}>
|
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.25 }}>
|
||||||
{rec.secondary || `${new Date(rec.date).toLocaleDateString()} • ${rec.type}`}
|
{rec.secondary || `${dayjs(rec.date).format('M/D/YYYY')} • ${rec.type}`}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useMemo, useState, useEffect } from 'react';
|
import React, { useMemo, useState, useEffect } from 'react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
|
import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
|
||||||
import { Box, Typography, Button as MuiButton, Divider, FormControl, InputLabel, Select, MenuItem, Table, TableHead, TableRow, TableCell, TableBody, Dialog, DialogTitle, DialogContent, useMediaQuery, IconButton } from '@mui/material';
|
import { Box, Typography, Button as MuiButton, Divider, FormControl, InputLabel, Select, MenuItem, Table, TableHead, TableRow, TableCell, TableBody, Dialog, DialogTitle, DialogContent, useMediaQuery, IconButton } from '@mui/material';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
@@ -132,7 +133,7 @@ export const VehicleDetailPage: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
return list.sort((a, b) => b.date.localeCompare(a.date));
|
||||||
}, [fuelLogs, documents]);
|
}, [fuelLogs, documents]);
|
||||||
|
|
||||||
const filteredRecords = useMemo(() => {
|
const filteredRecords = useMemo(() => {
|
||||||
@@ -490,7 +491,7 @@ export const VehicleDetailPage: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
{!isFuelLoading && !isDocumentsLoading && filteredRecords.map((rec) => (
|
{!isFuelLoading && !isDocumentsLoading && filteredRecords.map((rec) => (
|
||||||
<TableRow key={rec.id} hover sx={{ cursor: rec.type === 'Documents' ? 'default' : 'pointer' }} onClick={() => handleRowClick(rec.id, rec.type)}>
|
<TableRow key={rec.id} hover sx={{ cursor: rec.type === 'Documents' ? 'default' : 'pointer' }} onClick={() => handleRowClick(rec.id, rec.type)}>
|
||||||
<TableCell>{new Date(rec.date).toLocaleDateString()}</TableCell>
|
<TableCell>{dayjs(rec.date).format('M/D/YYYY')}</TableCell>
|
||||||
<TableCell>{rec.type}</TableCell>
|
<TableCell>{rec.type}</TableCell>
|
||||||
<TableCell>{rec.summary}</TableCell>
|
<TableCell>{rec.summary}</TableCell>
|
||||||
<TableCell align="right">{rec.amount || '—'}</TableCell>
|
<TableCell align="right">{rec.amount || '—'}</TableCell>
|
||||||
|
|||||||
Reference in New Issue
Block a user