diff --git a/client/scripts/lib/format.mjs b/client/scripts/lib/format.mjs index 1814d11cd..1007e858e 100644 --- a/client/scripts/lib/format.mjs +++ b/client/scripts/lib/format.mjs @@ -31,11 +31,16 @@ export async function isFormatted(path) { if (!options) throw new RatchetError(`no Prettier config applies to ${path}`); try { return await prettier.check(readText(path), { ...options, filepath: path }); - } catch { + } catch (err) { + stopped.set(path, String(err instanceof Error ? err.message : err).split(' +')[0]); return false; } } +/** Why Prettier gave up on a file, by its path, so the failure line can say it was not about style. */ +const stopped = new Map(); + /** The files under root that Prettier would rewrite, keyed by their path from root. */ export async function unformatted(root) { const found = []; @@ -74,6 +79,8 @@ export async function check({ if (list) for (const key of found) log(`${allowed.has(key) ? 'listed' : 'new '} ${key}`); for (const key of fresh) { error(`FAIL ${key} is not formatted. Run: npx prettier --write ${key}`); + const why = stopped.get(join(root, key)); + if (why) error(` Prettier could not format it: ${why}`); } for (const key of stale) { error(`FAIL ${key} is listed in scripts/format-baseline.json but is formatted now or gone.`); diff --git a/client/src/components/Assistant/cards/atlas/AtlasCards.test.tsx b/client/src/components/Assistant/cards/atlas/AtlasCards.test.tsx index 0e91370e4..9539ff2d4 100644 --- a/client/src/components/Assistant/cards/atlas/AtlasCards.test.tsx +++ b/client/src/components/Assistant/cards/atlas/AtlasCards.test.tsx @@ -33,10 +33,7 @@ const passport: AtlasPassportCard = { kind: 'atlasPassport', countries: { visited: 23, planned: 4, idea: 0 }, totals: { trips: 48, days: 410, places: 990, cities: 312, flownKm: 182_300 }, - flags: [ - ...CODES.map((code) => ({ code, status: 'visited' as const })), - { code: 'MA', status: 'planned' as const }, - ], + flags: [...CODES.map((code) => ({ code, status: 'visited' as const })), { code: 'MA', status: 'planned' as const }], moreFlags: 4, continents: [ { name: 'Europe', visited: 14, planned: 2 }, diff --git a/client/src/components/Assistant/cards/atlas/atlasCardModel.ts b/client/src/components/Assistant/cards/atlas/atlasCardModel.ts index 2ee733113..fa27134c3 100644 --- a/client/src/components/Assistant/cards/atlas/atlasCardModel.ts +++ b/client/src/components/Assistant/cards/atlas/atlasCardModel.ts @@ -19,14 +19,13 @@ import type { ChangeItem } from '../../assistantParts'; */ /** How a country's or a region's standing reads. A table, so each word is named where it is read. */ -export const STATUS_LOOK: Readonly> = - { - visited: { Icon: Check, tone: 'success', labelKey: 'assistant.card.atlas.status.visited' }, - planned: { Icon: CalendarClock, tone: 'info', labelKey: 'assistant.card.atlas.status.planned' }, - idea: { Icon: Lightbulb, tone: 'neutral', labelKey: 'assistant.card.atlas.status.idea' }, - none: { Icon: CircleDashed, tone: 'neutral', labelKey: 'assistant.card.atlas.status.none' }, - unknown: { Icon: Briefcase, tone: 'info', labelKey: 'assistant.card.atlas.status.unknown' }, - }; +export const STATUS_LOOK: Readonly> = { + visited: { Icon: Check, tone: 'success', labelKey: 'assistant.card.atlas.status.visited' }, + planned: { Icon: CalendarClock, tone: 'info', labelKey: 'assistant.card.atlas.status.planned' }, + idea: { Icon: Lightbulb, tone: 'neutral', labelKey: 'assistant.card.atlas.status.idea' }, + none: { Icon: CircleDashed, tone: 'neutral', labelKey: 'assistant.card.atlas.status.none' }, + unknown: { Icon: Briefcase, tone: 'info', labelKey: 'assistant.card.atlas.status.unknown' }, +}; /** The continents in the Atlas page's own words. */ export const CONTINENT_LABEL: Readonly> = { diff --git a/client/src/components/Assistant/cards/budget/ExpensesCard.tsx b/client/src/components/Assistant/cards/budget/ExpensesCard.tsx index 88e5299eb..84e1b4b5e 100644 --- a/client/src/components/Assistant/cards/budget/ExpensesCard.tsx +++ b/client/src/components/Assistant/cards/budget/ExpensesCard.tsx @@ -126,7 +126,9 @@ export default function ExpensesCard({ cards }: { cards: readonly CardEntry[] }) actions={} /> - {card.rows.map((row, i) => )} + {card.rows.map((row, i) => ( + + ))} diff --git a/client/src/components/Assistant/cards/budget/PaymentsCard.tsx b/client/src/components/Assistant/cards/budget/PaymentsCard.tsx index a448d0537..4c6366e0b 100644 --- a/client/src/components/Assistant/cards/budget/PaymentsCard.tsx +++ b/client/src/components/Assistant/cards/budget/PaymentsCard.tsx @@ -65,7 +65,9 @@ export default function PaymentsCard({ cards }: { cards: readonly CardEntry[] }) actions={} /> - {card.rows.map((row, i) => )} + {card.rows.map((row, i) => ( + + ))} diff --git a/client/src/components/Assistant/cards/cardTypes.ts b/client/src/components/Assistant/cards/cardTypes.ts index 11e51ff12..03e8900e9 100644 --- a/client/src/components/Assistant/cards/cardTypes.ts +++ b/client/src/components/Assistant/cards/cardTypes.ts @@ -118,6 +118,3 @@ export interface CardView { runnable?(card: TrekCardOf): boolean; startsExcluded?(card: TrekCardOf): boolean; } - -/** The view of a kind not drawn yet: it renders nothing, so its cards are left out until a package fills it. */ -export const PENDING_VIEW = {} satisfies CardView; diff --git a/client/src/components/Assistant/cards/collab/CollabChatThread.tsx b/client/src/components/Assistant/cards/collab/CollabChatThread.tsx index cbd15dc87..0aa0a4af6 100644 --- a/client/src/components/Assistant/cards/collab/CollabChatThread.tsx +++ b/client/src/components/Assistant/cards/collab/CollabChatThread.tsx @@ -181,7 +181,9 @@ function Words({ bubble, spot, own }: Pick} > - {bubble.files.map((file) => )} + {bubble.files.map((file) => ( + + ))} ); } diff --git a/client/src/components/Assistant/cards/collab/CollabNotesCard.tsx b/client/src/components/Assistant/cards/collab/CollabNotesCard.tsx index 560e08f23..82a4f9df5 100644 --- a/client/src/components/Assistant/cards/collab/CollabNotesCard.tsx +++ b/client/src/components/Assistant/cards/collab/CollabNotesCard.tsx @@ -146,7 +146,9 @@ export default function CollabNotesBlock({ cards }: { cards: readonly CardEntry[ actions={} />
- {notes.map((note, index) => )} + {notes.map((note, index) => ( + + ))}
@@ -157,7 +159,9 @@ export default function CollabNotesBlock({ cards }: { cards: readonly CardEntry[ export function CollabNotesBody({ card, item }: { card: NotesCard; item: ChangeItem }) { return (
- {card.notes.map((note, index) => )} + {card.notes.map((note, index) => ( + + ))}
); } diff --git a/client/src/components/Assistant/cards/collab/CollabPollsCard.tsx b/client/src/components/Assistant/cards/collab/CollabPollsCard.tsx index 8210839dc..e16a9b472 100644 --- a/client/src/components/Assistant/cards/collab/CollabPollsCard.tsx +++ b/client/src/components/Assistant/cards/collab/CollabPollsCard.tsx @@ -133,7 +133,9 @@ export default function CollabPollsBlock({ cards }: { cards: readonly CardEntry[ actions={} />
- {polls.map((poll, index) => )} + {polls.map((poll, index) => ( + + ))}
@@ -144,7 +146,9 @@ export default function CollabPollsBlock({ cards }: { cards: readonly CardEntry[ export function CollabPollsBody({ card, item }: { card: PollsCard; item: ChangeItem }) { return (
- {card.polls.map((poll, index) => )} + {card.polls.map((poll, index) => ( + + ))}
); } diff --git a/client/src/components/Assistant/cards/collection/collectionCardModel.ts b/client/src/components/Assistant/cards/collection/collectionCardModel.ts index 919a6eb49..1f02961da 100644 --- a/client/src/components/Assistant/cards/collection/collectionCardModel.ts +++ b/client/src/components/Assistant/cards/collection/collectionCardModel.ts @@ -40,7 +40,7 @@ function placesCardOf(card: TrekCard | null): CollectionPlacesCard | null { } /** The saved place a change card is about: its only one. */ -export function firstPlace(card: TrekCard | null): CollectionCardPlace | null { +function firstPlace(card: TrekCard | null): CollectionCardPlace | null { const places = placesCardOf(card)?.places ?? []; return places.length === 1 ? (places[0] ?? null) : null; } diff --git a/client/src/components/Assistant/cards/journey/JourneyChangeSlots.tsx b/client/src/components/Assistant/cards/journey/JourneyChangeSlots.tsx index 933cfa26c..20a2ba317 100644 --- a/client/src/components/Assistant/cards/journey/JourneyChangeSlots.tsx +++ b/client/src/components/Assistant/cards/journey/JourneyChangeSlots.tsx @@ -91,7 +91,9 @@ export function JourneyEntryFacts({ item }: { card: JourneyEntriesCard; item: Ch tone="info" /> ))} - {states.map((row) => )} + {states.map((row) => ( + + ))} ); } diff --git a/client/src/components/Assistant/cards/packing/checklistModel.test.ts b/client/src/components/Assistant/cards/packing/checklistModel.test.ts index 1d9292c06..34cb8b25f 100644 --- a/client/src/components/Assistant/cards/packing/checklistModel.test.ts +++ b/client/src/components/Assistant/cards/packing/checklistModel.test.ts @@ -37,10 +37,7 @@ const row = (id: number | null, name: string, over: Partial = { ...over, }); -const packing = ( - groups: Array<[string, PackingCardItem[]]>, - over: Partial = {} -): PackingListCard => ({ +const packing = (groups: Array<[string, PackingCardItem[]]>, over: Partial = {}): PackingListCard => ({ kind: 'packingList', source: { type: 'trip' }, groupBy: 'category', diff --git a/client/src/components/Assistant/cards/packing/checklistParts.tsx b/client/src/components/Assistant/cards/packing/checklistParts.tsx index 8c00f27bb..9a2c11654 100644 --- a/client/src/components/Assistant/cards/packing/checklistParts.tsx +++ b/client/src/components/Assistant/cards/packing/checklistParts.tsx @@ -139,15 +139,7 @@ export interface RunEntry { } /** A change in a run: the round include choice, the tile of what it does, and the row. */ -function RunRow({ - entry, - excluded, - onToggle, -}: { - entry: RunEntry; - excluded: boolean; - onToggle: (id: string) => void; -}) { +function RunRow({ entry, excluded, onToggle }: { entry: RunEntry; excluded: boolean; onToggle: (id: string) => void }) { const { t } = useTranslation(); const { variant } = useAssistantView(); const glyph = ROW_GLYPH[entry.change]; diff --git a/client/src/components/Assistant/cards/packing/packingParts.tsx b/client/src/components/Assistant/cards/packing/packingParts.tsx index d6e11d40b..bde5e98c0 100644 --- a/client/src/components/Assistant/cards/packing/packingParts.tsx +++ b/client/src/components/Assistant/cards/packing/packingParts.tsx @@ -305,9 +305,7 @@ export function PackingGroup({ ))} )} - {group.items.length > 0 && ( - 0 ? t('tours.packing.more', { count: hidden }) : null} /> - )} + {group.items.length > 0 && 0 ? t('tours.packing.more', { count: hidden }) : null} />} ); } diff --git a/client/src/components/Assistant/cards/roadtrip/RoadtripBlock.tsx b/client/src/components/Assistant/cards/roadtrip/RoadtripBlock.tsx index 7485519d8..ab2111b0d 100644 --- a/client/src/components/Assistant/cards/roadtrip/RoadtripBlock.tsx +++ b/client/src/components/Assistant/cards/roadtrip/RoadtripBlock.tsx @@ -20,15 +20,7 @@ import { settingLabel } from './roadtripSettings'; */ /** One way of driving it, as a row to pick: saved or tried, how far and how long, how much to look at. */ -function VariantRow({ - card, - picked, - onPick, -}: { - card: RoadtripCard; - picked: boolean; - onPick: () => void; -}) { +function VariantRow({ card, picked, onPick }: { card: RoadtripCard; picked: boolean; onPick: () => void }) { const { t } = useTranslation(); const format = useCardFormat(); const warnings = card.days.filter(dayHasWarning).length; @@ -55,9 +47,7 @@ function VariantRow({ })} {warnings > 0 && ( - - {t('assistant.card.roadtrip.warnings', { count: warnings })} - + {t('assistant.card.roadtrip.warnings', { count: warnings })} )} diff --git a/client/src/components/Assistant/cards/tour/TourRouteActions.tsx b/client/src/components/Assistant/cards/tour/TourRouteActions.tsx index a042de7c3..e2e7de533 100644 --- a/client/src/components/Assistant/cards/tour/TourRouteActions.tsx +++ b/client/src/components/Assistant/cards/tour/TourRouteActions.tsx @@ -76,7 +76,9 @@ export default function TourRouteActions({ )} {take.visible && caption && ( -

{caption}

+

+ {caption} +

)} ); diff --git a/client/src/components/Assistant/cards/vacay/VacayChangeGroup.tsx b/client/src/components/Assistant/cards/vacay/VacayChangeGroup.tsx index 8601f4c48..4246b01ae 100644 --- a/client/src/components/Assistant/cards/vacay/VacayChangeGroup.tsx +++ b/client/src/components/Assistant/cards/vacay/VacayChangeGroup.tsx @@ -70,7 +70,11 @@ export default function VacayChangeGroup({ /> )} {placed.length > 0 && ( -
    {placed.map((entry) =>
  • {labelOf(entry)}
  • )}
+
    + {placed.map((entry) => ( +
  • {labelOf(entry)}
  • + ))} +
)} {twice && (
diff --git a/client/src/components/Assistant/cards/vacay/VacayMiniMonth.tsx b/client/src/components/Assistant/cards/vacay/VacayMiniMonth.tsx index e5053b7a9..3764205b7 100644 --- a/client/src/components/Assistant/cards/vacay/VacayMiniMonth.tsx +++ b/client/src/components/Assistant/cards/vacay/VacayMiniMonth.tsx @@ -96,7 +96,13 @@ function Cell({ {marks} ); - return cell.holiday ? {body} : body; + return cell.holiday ? ( + + {body} + + ) : ( + body + ); } export default function VacayMiniMonth({ view, month, placed, today, size, onToggle, labelOf }: MonthProps) { @@ -109,7 +115,9 @@ export default function VacayMiniMonth({ view, month, placed, today, size, onTog

{title}

{weekdays.map((name, column) => ( - + ))} {cells.map((cell, index) => cell ? ( diff --git a/client/src/components/Assistant/cards/vacay/VacayRowFacts.tsx b/client/src/components/Assistant/cards/vacay/VacayRowFacts.tsx index 685372a87..e3ef257b7 100644 --- a/client/src/components/Assistant/cards/vacay/VacayRowFacts.tsx +++ b/client/src/components/Assistant/cards/vacay/VacayRowFacts.tsx @@ -70,7 +70,9 @@ export default function VacayRowFacts({ card }: { card: VacayCard; item: ChangeI )} {proposal.notes.map((note) => ( - {t(NOTE_LOOK[note].labelKey)} + + {t(NOTE_LOOK[note].labelKey)} + ))} ); diff --git a/client/src/components/Collab/CollabNoteHead.tsx b/client/src/components/Collab/CollabNoteHead.tsx index b8d0bc064..63c686383 100644 --- a/client/src/components/Collab/CollabNoteHead.tsx +++ b/client/src/components/Collab/CollabNoteHead.tsx @@ -33,7 +33,7 @@ export function NoteHeadBand({ }) { return (
{/* The category is only its colour here; the name is in the tooltip and the filter above. */} diff --git a/server/src/nest/assistant/cards/collection/collection-applied.ts b/server/src/nest/assistant/cards/collection/collection-applied.ts index c157d070a..3867902b1 100644 --- a/server/src/nest/assistant/cards/collection/collection-applied.ts +++ b/server/src/nest/assistant/cards/collection/collection-applied.ts @@ -122,7 +122,7 @@ function labelApplied({ result, preview }: AppliedInput): CollectionPlacesCard | return { ...card, labels: [{ ...shown, id: positiveId(label.id), name, color }] }; } -export const COLLECTION_APPLIED: Readonly TrekCard | null>> = { +export const COLLECTION_APPLIED: Readonly TrekCard | null>>> = { save_place_to_collection: savedApplied, update_collection_place: placeApplied, set_collection_place_status: placeApplied, @@ -137,22 +137,23 @@ export const COLLECTION_APPLIED: Readonly number[]>> = { - create_collection: (_args, result) => idsOf(positiveId(recordOf(recordOf(result).collection).id)), - update_collection: (args) => idsOf(argId(args, 'collectionId')), - delete_collection: (args) => idsOf(argId(args, 'collectionId')), - save_trip_places_to_collection: (args) => idsOf(argId(args, 'collectionId')), - accept_collection_invite: (args) => idsOf(argId(args, 'collectionId')), - decline_collection_invite: (args) => idsOf(argId(args, 'collectionId')), - cancel_collection_invite: (args) => idsOf(argId(args, 'collectionId')), - create_collection_label: (args) => idsOf(argId(args, 'collection_id')), - update_collection_label: (_args, result) => idsOf(positiveId(recordOf(recordOf(result).label).collection_id)), - // The new trip places, so "Show on map" opens the first of them. - copy_collection_places_to_trip: (_args, result) => - rowsOf(recordOf(result).created) - .map((row) => positiveId(row.id)) - .filter((id): id is number => id !== null), -}; +export const COLLECTION_APPLIED_IDS: Readonly number[]>>> = + { + create_collection: (_args, result) => idsOf(positiveId(recordOf(recordOf(result).collection).id)), + update_collection: (args) => idsOf(argId(args, 'collectionId')), + delete_collection: (args) => idsOf(argId(args, 'collectionId')), + save_trip_places_to_collection: (args) => idsOf(argId(args, 'collectionId')), + accept_collection_invite: (args) => idsOf(argId(args, 'collectionId')), + decline_collection_invite: (args) => idsOf(argId(args, 'collectionId')), + cancel_collection_invite: (args) => idsOf(argId(args, 'collectionId')), + create_collection_label: (args) => idsOf(argId(args, 'collection_id')), + update_collection_label: (_args, result) => idsOf(positiveId(recordOf(recordOf(result).label).collection_id)), + // The new trip places, so "Show on map" opens the first of them. + copy_collection_places_to_trip: (_args, result) => + rowsOf(recordOf(result).created) + .map((row) => positiveId(row.id)) + .filter((id): id is number => id !== null), + }; function idsOf(id: number | null): number[] { return id === null ? [] : [id]; diff --git a/server/src/nest/assistant/cards/collection/collection-load.ts b/server/src/nest/assistant/cards/collection/collection-load.ts index 0cfa1a6db..3b11cdfe5 100644 --- a/server/src/nest/assistant/cards/collection/collection-load.ts +++ b/server/src/nest/assistant/cards/collection/collection-load.ts @@ -80,7 +80,7 @@ const oneLabel: Loader = async (args, read) => { return { ...NO_LOOKUP, items, collection: await collectionOf(read, positiveId(recordOf(label).collection_id)) }; }; -export const COLLECTION_LOADS: Readonly> = { +export const COLLECTION_LOADS: Readonly>> = { save_place_to_collection: async (args, read) => { const query = membershipQuery(args); const [collection, membership] = await Promise.all([