Add Symfony payload mapping, fixtures, and QA tooling
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { type ClassValue, clsx } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export type Coordinates = {
|
||||
lat: number
|
||||
lng: number
|
||||
}
|
||||
|
||||
export function cn(...inputs: ClassValue[]): string {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
export function formatCoordinate(value: number): string {
|
||||
const formatter = new Intl.NumberFormat('en-US', {
|
||||
minimumFractionDigits: 3,
|
||||
maximumFractionDigits: 3,
|
||||
})
|
||||
return formatter.format(value)
|
||||
}
|
||||
|
||||
export function formatRelativeTime(dateIso: string): string {
|
||||
const date = new Date(dateIso)
|
||||
const now = new Date()
|
||||
const diff = Math.max(0, now.getTime() - date.getTime())
|
||||
|
||||
const seconds = Math.floor(diff / 1000)
|
||||
if (seconds < 60) {
|
||||
return `${seconds}s ago`
|
||||
}
|
||||
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
if (minutes < 60) {
|
||||
return `${minutes}m ago`
|
||||
}
|
||||
|
||||
const hours = Math.floor(minutes / 60)
|
||||
if (hours < 24) {
|
||||
return `${hours}h ago`
|
||||
}
|
||||
|
||||
const days = Math.floor(hours / 24)
|
||||
if (days < 7) {
|
||||
return `${days}d ago`
|
||||
}
|
||||
|
||||
const weeks = Math.floor(days / 7)
|
||||
return `${weeks}w ago`
|
||||
}
|
||||
|
||||
export function formatTimestamp(dateIso: string): string {
|
||||
const date = new Date(dateIso)
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
}).format(date)
|
||||
}
|
||||
|
||||
const EARTH_RADIUS_KM = 6371
|
||||
|
||||
export function distanceInKm(a: Coordinates, b: Coordinates): number {
|
||||
const lat1 = toRadians(a.lat)
|
||||
const lat2 = toRadians(b.lat)
|
||||
const deltaLat = toRadians(b.lat - a.lat)
|
||||
const deltaLng = toRadians(b.lng - a.lng)
|
||||
|
||||
const haversine =
|
||||
Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
|
||||
Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2)
|
||||
|
||||
const c = 2 * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine))
|
||||
return EARTH_RADIUS_KM * c
|
||||
}
|
||||
|
||||
function toRadians(value: number): number {
|
||||
return (value * Math.PI) / 180
|
||||
}
|
||||
Reference in New Issue
Block a user