Migrate date precision to exact

Batch update all date precision handling to use expanded DatePrecision, replace hardcoded day defaults, and adjust related validation, UI, and helpers. Includes wrapper migration across Phase 1-3 functions, updates to logs, displays, and formatting utilities to align frontend with new precision values ('exact', 'month', 'year', 'decade', 'century', 'approximate').
This commit is contained in:
gpt-engineer-app[bot]
2025-11-11 22:05:29 +00:00
parent 9ee84b31ff
commit d0c613031e
15 changed files with 189 additions and 43 deletions

View File

@@ -72,7 +72,7 @@ export function getCurrentDateLocal(): string {
*/
export function formatDateDisplay(
dateString: string | null | undefined,
precision: 'day' | 'month' | 'year' = 'day'
precision: 'exact' | 'month' | 'year' | 'decade' | 'century' | 'approximate' = 'exact'
): string {
if (!dateString) return '';
@@ -83,7 +83,13 @@ export function formatDateDisplay(
return date.getFullYear().toString();
case 'month':
return date.toLocaleDateString('en-US', { year: 'numeric', month: 'long' });
case 'day':
case 'decade':
return `${Math.floor(date.getFullYear() / 10) * 10}s`;
case 'century':
return `${Math.ceil(date.getFullYear() / 100)}th century`;
case 'approximate':
return `circa ${date.getFullYear()}`;
case 'exact':
default:
return date.toLocaleDateString('en-US', {
year: 'numeric',
@@ -182,7 +188,7 @@ export function parseDateForDisplay(date: string | Date): Date {
*/
export function toDateWithPrecision(
date: Date,
precision: 'day' | 'month' | 'year'
precision: 'exact' | 'month' | 'year' | 'decade' | 'century' | 'approximate'
): string {
const year = date.getFullYear();
const month = date.getMonth() + 1;
@@ -193,7 +199,13 @@ export function toDateWithPrecision(
return `${year}-01-01`;
case 'month':
return `${year}-${String(month).padStart(2, '0')}-01`;
case 'day':
case 'decade':
return `${Math.floor(year / 10) * 10}-01-01`;
case 'century':
return `${Math.floor((year - 1) / 100) * 100 + 1}-01-01`;
case 'approximate':
return `${year}-01-01`;
case 'exact':
default:
return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
}

View File

@@ -51,9 +51,9 @@ export const parkValidationSchema = z.object({
const date = new Date(val);
return date <= new Date();
}, 'Opening date cannot be in the future'),
opening_date_precision: z.enum(['day', 'month', 'year']).nullable().optional(),
opening_date_precision: z.enum(['exact', 'month', 'year', 'decade', 'century', 'approximate']).nullable().optional(),
closing_date: z.string().nullish().transform(val => val ?? undefined),
closing_date_precision: z.enum(['day', 'month', 'year']).nullable().optional(),
closing_date_precision: z.enum(['exact', 'month', 'year', 'decade', 'century', 'approximate']).nullable().optional(),
location_id: z.string().uuid().optional().nullable(),
location: z.object({
name: z.string(),
@@ -139,9 +139,9 @@ export const rideValidationSchema = z.object({
.optional()
.nullable(),
opening_date: z.string().nullish().transform(val => val ?? undefined),
opening_date_precision: z.enum(['day', 'month', 'year']).nullable().optional(),
opening_date_precision: z.enum(['exact', 'month', 'year', 'decade', 'century', 'approximate']).nullable().optional(),
closing_date: z.string().nullish().transform(val => val ?? undefined),
closing_date_precision: z.enum(['day', 'month', 'year']).nullable().optional(),
closing_date_precision: z.enum(['exact', 'month', 'year', 'decade', 'century', 'approximate']).nullable().optional(),
height_requirement: z.preprocess(
(val) => val === '' || val === null || val === undefined ? undefined : Number(val),
z.number().int().min(0, 'Height requirement must be positive').max(300, 'Height requirement must be less than 300cm').optional()
@@ -322,7 +322,7 @@ export const companyValidationSchema = z.object({
description: z.string().trim().max(2000, 'Description must be less than 2000 characters').nullish().transform(val => val ?? undefined),
person_type: z.enum(['company', 'individual', 'firm', 'organization']),
founded_date: z.string().nullish().transform(val => val ?? undefined),
founded_date_precision: z.enum(['day', 'month', 'year']).nullable().optional(),
founded_date_precision: z.enum(['exact', 'month', 'year', 'decade', 'century', 'approximate']).nullable().optional(),
founded_year: z.preprocess(
(val) => val === '' || val === null || val === undefined ? undefined : Number(val),
z.number().int().min(1800, 'Founded year must be after 1800').max(currentYear, `Founded year cannot be after ${currentYear}`).optional()
@@ -401,7 +401,7 @@ export const milestoneValidationSchema = z.object({
fiveYearsFromNow.setFullYear(fiveYearsFromNow.getFullYear() + 5);
return date <= fiveYearsFromNow;
}, 'Event date cannot be more than 5 years in the future'),
event_date_precision: z.enum(['day', 'month', 'year']).optional().default('day'),
event_date_precision: z.enum(['exact', 'month', 'year', 'decade', 'century', 'approximate']).optional().default('exact'),
entity_type: z.string().min(1, 'Entity type is required'),
entity_id: z.string().uuid('Invalid entity ID'),
is_public: z.boolean().optional(),

View File

@@ -21,9 +21,9 @@ export interface FieldChange {
changeType: 'added' | 'removed' | 'modified';
metadata?: {
isCreatingNewLocation?: boolean;
precision?: 'day' | 'month' | 'year';
oldPrecision?: 'day' | 'month' | 'year';
newPrecision?: 'day' | 'month' | 'year';
precision?: 'exact' | 'month' | 'year' | 'decade' | 'century' | 'approximate';
oldPrecision?: 'exact' | 'month' | 'year' | 'decade' | 'century' | 'approximate';
newPrecision?: 'exact' | 'month' | 'year' | 'decade' | 'century' | 'approximate';
};
}
@@ -803,7 +803,7 @@ function formatEntityType(entityType: string): string {
/**
* Format field value for display
*/
export function formatFieldValue(value: any, precision?: 'day' | 'month' | 'year'): string {
export function formatFieldValue(value: any, precision?: 'exact' | 'month' | 'year' | 'decade' | 'century' | 'approximate'): string {
if (value === null || value === undefined) return 'None';
if (typeof value === 'boolean') return value ? 'Yes' : 'No';
@@ -817,9 +817,15 @@ export function formatFieldValue(value: any, precision?: 'day' | 'month' | 'year
return date.getFullYear().toString();
} else if (precision === 'month') {
return date.toLocaleDateString('en-US', { year: 'numeric', month: 'long' });
} else if (precision === 'decade') {
return `${Math.floor(date.getFullYear() / 10) * 10}s`;
} else if (precision === 'century') {
return `${Math.ceil(date.getFullYear() / 100)}th century`;
} else if (precision === 'approximate') {
return `circa ${date.getFullYear()}`;
}
// Default: full date
// Default: full date (exact)
return date.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
} catch {
return String(value);