Files
TREK/client/src/utils/dayLabel.ts
T
Maurice 8fd46c4c18 feat: quality of life sweep from the feature discussions
Small requests from the discussions, each built end to end: planner and
map (cycling mode, date first headings, clear a day, stay times per day,
off-route stops, map lock, compact unplanned markers, pending stays,
cable car, transit quick picks), places (location filter, category from
OSM, open in maps, geo: link, image from an attachment, enrichment on
file import, places near a pin, place name language, Amap first in
China), lists and costs (packed counter, inherited sharing, Markdown
to-dos, payment notes, bookings CSV, my plan PDF), sharing (unplanned
places, travel only, without photos), journey (photo zoom, drafts,
photo order, trip suggestion, day jump), atlas (region counter, region
bucket list, places per country), vacay half company holidays, studio
copy and paste plus the book's own layouts, and RESTORE_FROM_BACKUP for
a first start restore.
2026-09-30 23:00:12 +02:00

41 lines
2.0 KiB
TypeScript

import type { Day } from '../types'
type Translate = (key: string, params?: Record<string, string | number>) => string
/**
* How a day is named wherever days are listed as a whole: its title, else its
* date as a short weekday and day of the month, else "Day n" by its position.
*
* The reorder dialog, the phone's day sheet and the delete question all name a
* day, and they have to name it the same way, or the question asks about a day
* the list beside it calls something else. The date is read as a local calendar
* date, and a value that does not parse falls through to the position.
*/
export function dayLabel(day: Pick<Day, 'title' | 'date'>, index: number, t: Translate, locale: string): string {
if (day.title) return day.title
return (day.date && dayDate(day.date, locale)) || t('dayplan.dayN', { n: index + 1 })
}
/**
* A calendar date the way the day list writes it: short weekday, day, month,
* and no year, which the trip around it already says. Anything that talks
* about the days in that list (the next day to add, a moved check-out, the new
* end of the trip) writes its dates this way too, so a date reads the same in
* the button as in the row it becomes. Null when the value does not parse.
*/
export function dayDate(iso: string, locale: string): string | null {
const date = new Date(`${iso.slice(0, 10)}T00:00:00`)
if (Number.isNaN(date.getTime())) return null
return date.toLocaleDateString(locale, { weekday: 'short', day: 'numeric', month: 'short' })
}
/**
* A day heading's two parts in reading order. The day's name ("Day 3" or its own
* title) leads, unless the traveller plans by the calendar and asked for the date
* first (#1953). A day without a date always leads with its name.
*/
export function dayHeadingParts(name: string, date: string | null | undefined, dateFirst: boolean): { primary: string; secondary: string | null } {
if (dateFirst && date) return { primary: date, secondary: name }
return { primary: name, secondary: date || null }
}