// The basket of the reader: the choices not sent yet, kept for the tab (a reload // or a look at another article does not lose them), one basket per document. import { kept, type Picks, type Votable } from './basket'; import type { Choice } from './types'; export class BasketState { picks = $state({}); #key = ''; /** * Takes back the basket of this document, keeping only the choices still open: a * version gone leaves it, and so does a « for » on a version an objection holds back. */ load(docId: string, known: Votable) { const key = `ld:basket:${docId}`; if (key === this.#key) { this.#keep(known); return; } this.#key = key; let saved: Picks = {}; try { saved = JSON.parse(sessionStorage.getItem(key) ?? '{}') as Picks; } catch { saved = {}; } this.picks = {}; this.set(saved); this.#keep(known); } #keep(known: Votable) { const still = kept(this.picks, known); if (Object.keys(still).length !== Object.keys(this.picks).length) this.set(still); } set(picks: Picks) { const clean: Picks = {}; for (const [id, c] of Object.entries(picks)) if (c === 'for' || c === 'against' || c === 'none') clean[id] = c; this.picks = clean; try { sessionStorage.setItem(this.#key, JSON.stringify(clean)); } catch { /* private mode: the basket lives as long as the page */ } } /** Picks a choice; the same choice again takes it out of the basket. */ pick(id: string, choice: Choice) { const next = { ...this.picks }; if (next[id] === choice) delete next[id]; else next[id] = choice; this.set(next); } clear() { this.set({}); } get size(): number { return Object.keys(this.picks).length; } }