Files
TREK/shared/src/packing/packed-count.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

36 lines
1.4 KiB
TypeScript

/**
* The packed count of a multi-piece item (#2296) and its checkbox, kept in step.
*
* `packed_quantity` only holds a partial count: zero is stored as null, and a count
* that reaches the quantity is the checked box itself. That keeps one truth for
* "done" and lets every older client keep reading `checked`.
*/
export interface PackedState {
checked: number;
packed_quantity: number | null;
}
interface PackedInput {
/** The keys the write actually named, as the update's presence protocol has them. */
bodyKeys: string[];
checked?: number;
packed_quantity?: number | null;
/** The quantity after the write. */
quantity: number;
}
export function resolvePackedState(current: PackedState, input: PackedInput): PackedState {
const { bodyKeys, quantity } = input;
if (bodyKeys.includes('packed_quantity')) {
const count = Math.max(0, Math.min(quantity, Math.floor(Number(input.packed_quantity) || 0)));
if (count >= quantity) return { checked: 1, packed_quantity: null };
return { checked: 0, packed_quantity: count > 0 ? count : null };
}
// Ticking or unticking the box is a decision about the whole item.
if (bodyKeys.includes('checked')) return { checked: input.checked ? 1 : 0, packed_quantity: null };
// A lowered quantity the count already reaches finishes the item.
if (current.packed_quantity != null && current.packed_quantity >= quantity)
return { checked: 1, packed_quantity: null };
return current;
}