fix(book): a summary's and a country's look are optional, so a stored book reads and saves as it did

Absent means the classic look. Defaulting it wrote the field into every
element the auto layout and the templates build, which moved their parity
fixtures and grew the page tools past their schema ceiling; the new
descriptions are also shorter for the same reason.
This commit is contained in:
Maurice
2026-10-24 14:59:00 +02:00
parent a7b53988ff
commit 26a6147e8d
8 changed files with 15 additions and 38 deletions
@@ -253,7 +253,7 @@ export function CountryLookView({ el, frameStyle }: { el: BookCountriesElement;
const key = `${c.code}-${i}`;
if (el.look === 'stamp') return <Stamp key={key} el={el} c={c} size={Math.min(cellW, cellH)} />;
if (el.look === 'postcard') return <Postcard key={key} el={el} c={c} w={cellW} h={cellH} />;
const Look = MORE[el.look] ?? Visa;
const Look = MORE[el.look ?? 'visa'] ?? Visa;
return <Look key={key} el={el} code={c.code} name={c.name} w={cellW} h={cellH} />;
})}
</div>
@@ -509,7 +509,7 @@ export function StatsLookView({ el, frameStyle }: { el: BookStatsElement; frameS
...metricValue(metric, el.values, el.units, locale),
label: t(`journey.studio.metric.${metric}`),
}));
const Look = LOOKS[el.look] ?? PosterLook;
const Look = LOOKS[el.look ?? 'poster'] ?? PosterLook;
return (
<div
style={{
@@ -37,7 +37,7 @@ import { studioTravelContext } from '../studioTravelContext';
*/
/** The figures a summary offers: how far, how long, where, and how much was kept. */
export const SUMMARY_METRICS: BookMetric[] = ['distance', 'days', 'countries', 'photos'];
const SUMMARY_METRICS: BookMetric[] = ['distance', 'days', 'countries', 'photos'];
/** The looks of a summary, in the order the panel offers them. */
export const SUMMARY_LOOKS: BookStatsLook[] = [
-3
View File
@@ -146,7 +146,6 @@ export function statsEl(
frame,
metrics,
layout,
look: 'classic',
showIcons: true,
units: 'metric',
values: statsValues(stats),
@@ -206,7 +205,6 @@ export function countriesEl(
showFlag: false,
showName: true,
align: 'center',
look: 'classic',
...opts,
} as BookElement;
}
@@ -296,7 +294,6 @@ export function countryWatermark(newId: NewId, frame: BookFrame, code: string |
showFlag: false,
showName: false,
align: 'center',
look: 'classic',
opacity: 0.1,
} as BookElement;
}
@@ -156,7 +156,6 @@ export const AUTO_TEMPLATES: readonly AutoTemplate[] = [
kind: 'stats',
metrics: ['distance', 'days', 'steps', 'photos', 'countries', 'places'],
layout: 'grid',
look: 'classic',
showIcons: true,
units: 'metric',
values: {
@@ -223,7 +222,6 @@ export const AUTO_TEMPLATES: readonly AutoTemplate[] = [
showFlag: false,
showName: true,
align: 'center',
look: 'classic',
},
],
},
+4 -20
View File
@@ -110,11 +110,7 @@ export const bookRouteArcSchema = map.routeArc
.unwrap()
.describe('bow draws the long legs as a curve, the way a flight is shown.');
export const bookRouteDashSchema = map.routeDash.unwrap().describe('arcs dashes the bowed legs; solid dashes nothing.');
export const bookPinStyleSchema = map.pinStyle
.unwrap()
.describe(
'A stop as a dot, a small round photo of it, its number in the order travelled, or only the start and the end marked.',
);
export const bookPinStyleSchema = map.pinStyle.unwrap().describe('How the stops are marked.');
export const bookMapClipSchema = map.clip
.unwrap()
.describe('rect is a map in a box; country cuts it to the outline of its countries.');
@@ -126,24 +122,12 @@ export const bookMapSourceSchema = z
export const bookStatsLayoutSchema = bookStatsElementSchema.shape.layout
.unwrap()
.describe('The figures in a grid, one row or one column.');
export const bookStatsLookSchema = bookStatsElementSchema.shape.look
.unwrap()
.describe(
'How the figures are drawn: classic (icon, figure, caption), poster (one big figure, the rest beside it), ticket (a ticket stub), tiles (a tile per figure), band (one line of figures between hairlines), medal (a round medal per figure), odometer (the drums of a counter), sign (a road sign listing them), note (a handwritten note) or sketch (drawn by hand).',
);
export const bookStatsLookSchema = bookStatsElementSchema.shape.look.unwrap().describe('How the figures are drawn.');
export const bookCountriesLayoutSchema = bookCountriesElementSchema.shape.layout
.unwrap()
.describe('The countries as a list, a grid or one column.');
export const bookCountryLookSchema = bookCountriesElementSchema.shape.look
.unwrap()
.describe(
'How a country is drawn: classic (name over its outline), stamp (a round passport stamp), postcard, visa (an entry stamp), flag (the flag in cloth), pin (a map pin), label (a luggage label) or sketch (the outline drawn by hand).',
);
export const bookBadgeStyleSchema = bookBadgeElementSchema.shape.style
.unwrap()
.describe(
'plain words, a chip (filled capsule), an outline, stacked over its line, a passport stamp, a luggage tag, a pill with its icon in a disc, a ribbon, a die-cut sticker, an embroidered patch or a frame drawn by hand.',
);
export const bookCountryLookSchema = bookCountriesElementSchema.shape.look.unwrap().describe('How a country is drawn.');
export const bookBadgeStyleSchema = bookBadgeElementSchema.shape.style.unwrap().describe('How the mark is set.');
export const bookBadgeVariantSchema = z
.enum(BOOK_BADGES)
.describe(
-2
View File
@@ -257,7 +257,6 @@ export function bookTravelStats(
frame: input.frame,
metrics: [...input.metrics],
layout: 'grid',
look: 'classic',
showIcons: true,
units: 'metric',
values: liveMetrics(stats),
@@ -282,7 +281,6 @@ export function bookTravelCountries(
showFlag: false,
showName: true,
align: 'center',
look: 'classic',
};
}
+8 -8
View File
@@ -692,16 +692,16 @@ export const bookStatsElementSchema = z.object({
metrics: z.array(z.enum(BOOK_METRICS)).max(7).default(['distance', 'days', 'steps', 'photos']),
layout: z.enum(['grid', 'row', 'column']).default('grid'),
/**
* How the figures are drawn. `classic` is the icon, figure and caption every
* summary placed so far draws, and the default for exactly that reason: a
* stored book must not change the day it is opened. The others are newer
* How the figures are drawn. Absent, or `classic`, is the icon, figure and
* caption every summary placed so far draws: optional rather than defaulted,
* so a stored book reads and saves exactly as it did. The others are newer
* compositions: one figure set as a poster with the rest beside it, a ticket
* stub, a tile per figure, a band of figures between hairlines, a round
* medal per figure with its name running round the rim, the drums of an
* odometer, a road sign listing them, a handwritten note, and a pencil
* sketch with a hand-drawn frame.
*/
look: z.enum(BOOK_STATS_LOOKS).default('classic'),
look: z.enum(BOOK_STATS_LOOKS).optional(),
showIcons: z.boolean().default(true),
units: bookUnitsSchema.default('metric'),
/**
@@ -738,15 +738,15 @@ export const bookCountriesElementSchema = z.object({
showName: z.boolean().default(true),
align: z.enum(['left', 'center', 'right']).default('center'),
/**
* How a country is drawn. `classic` is the name over its silhouette that
* every country placed so far draws, kept as the default so a stored book
* stays as it was. `stamp` sets it as a round passport stamp, `postcard` as
* How a country is drawn. Absent, or `classic`, is the name over its
* silhouette that every country placed so far draws, so a stored book stays
* as it was. `stamp` sets it as a round passport stamp, `postcard` as
* an airmail card, `visa` as an entry stamp with cut corners, `flag` as the
* flag in cloth, `pin` as a map pin carrying the flag, and `label` as an old
* luggage label with the name on a ribbon, `sketch` as the outline drawn by
* hand and hatched, with the name written under it.
*/
look: z.enum(BOOK_COUNTRY_LOOKS).default('classic'),
look: z.enum(BOOK_COUNTRY_LOOKS).optional(),
});
export const BOOK_BADGES = [