diff --git a/apps/mana/apps/web/src/lib/data/database.ts b/apps/mana/apps/web/src/lib/data/database.ts index 10a9c30fa..cb3ec6bef 100644 --- a/apps/mana/apps/web/src/lib/data/database.ts +++ b/apps/mana/apps/web/src/lib/data/database.ts @@ -433,6 +433,15 @@ db.version(7).stores({ cycleSymptoms: 'id, name, category, count, updatedAt', }); +// ─── Version 8: Events tombstones (orphaned snapshot cleanup) ─ +// Local-only retry queue. When the events store fails to DELETE a +// server snapshot during unpublish/delete, the (eventId, token) is +// pushed here so a later drain attempt can clean it up. NOT synced. + +db.version(8).stores({ + _eventsTombstones: 'id, token, attempts, createdAt', +}); + // ─── Sync App Map ────────────────────────────────────────── // Maps each table to its appId for sync routing. // The SyncEngine uses this to group pending changes and push to /sync/{appId}. diff --git a/apps/mana/apps/web/src/lib/modules/events/ListView.svelte b/apps/mana/apps/web/src/lib/modules/events/ListView.svelte index af30c53d6..d6fb74ef3 100644 --- a/apps/mana/apps/web/src/lib/modules/events/ListView.svelte +++ b/apps/mana/apps/web/src/lib/modules/events/ListView.svelte @@ -1,6 +1,8 @@ - {data.event.title} — RSVP + {data.event.title} {t.pageTitleSuffix}
@@ -92,7 +94,8 @@
👥
- {data.summary.totalAttending} Personen kommen + {data.summary.totalAttending} + {t.peopleAttending} {#if data.event.capacity} / {data.event.capacity} {/if} @@ -106,16 +109,20 @@ {/if} {#if data.cancelled} -
⚠️ Dieses Event wurde abgesagt.
+
{t.cancelledNotice}
{:else if submitted}
-

Danke für deine Antwort!

+

{t.successHeading}

- Du hast mit + {t.successYou} - {status === 'yes' ? '„Ja, komme“' : status === 'no' ? '„Nein“' : '„Vielleicht“'} + {status === 'yes' + ? t.successComing + : status === 'no' + ? t.successNotComing + : t.successMaybe} - geantwortet. Du kannst diese Seite jederzeit erneut öffnen, um deine Antwort zu ändern. + {t.successHint}

{:else}
-

Sag bitte zu

+

{t.formHeading}

- Kommst du? + {t.areYouComing}
{#if status === 'yes'} {/if} @@ -198,14 +201,14 @@ {/if}
{/if}
- Powered by Mana + {t.poweredBy} Mana
diff --git a/apps/mana/apps/web/src/routes/rsvp/[token]/strings.ts b/apps/mana/apps/web/src/routes/rsvp/[token]/strings.ts new file mode 100644 index 000000000..b4783d0c3 --- /dev/null +++ b/apps/mana/apps/web/src/routes/rsvp/[token]/strings.ts @@ -0,0 +1,108 @@ +/** + * Inline i18n dictionary for the public RSVP page. + * Kept tiny and local — this page is the only public consumer. + */ + +export type Lang = 'de' | 'en'; + +interface Strings { + rsvpTitle: string; + pageTitleSuffix: string; + allDay: string; + peopleAttending: string; + cancelledNotice: string; + successHeading: string; + successYou: string; + successComing: string; + successNotComing: string; + successMaybe: string; + successHint: string; + changeAnswer: string; + formHeading: string; + yourName: string; + yourNamePlaceholder: string; + emailLabel: string; + emailPlaceholder: string; + areYouComing: string; + yesComing: string; + maybe: string; + no: string; + bringingPeople: (count: number) => string; + noteLabel: string; + notePlaceholder: string; + send: string; + sending: string; + genericError: string; + poweredBy: string; + dateLocale: string; +} + +const DICTS: Record = { + de: { + rsvpTitle: 'Sag bitte zu', + pageTitleSuffix: '— RSVP', + allDay: 'Ganztägig', + peopleAttending: 'Personen kommen', + cancelledNotice: '⚠️ Dieses Event wurde abgesagt.', + successHeading: 'Danke für deine Antwort!', + successYou: 'Du hast mit', + successComing: '„Ja, komme“', + successNotComing: '„Nein“', + successMaybe: '„Vielleicht“', + successHint: + 'geantwortet. Du kannst diese Seite jederzeit erneut öffnen, um deine Antwort zu ändern.', + changeAnswer: 'Antwort ändern', + formHeading: 'Sag bitte zu', + yourName: 'Dein Name', + yourNamePlaceholder: 'z. B. Anna Schmidt', + emailLabel: 'E-Mail (optional)', + emailPlaceholder: 'anna@example.com', + areYouComing: 'Kommst du?', + yesComing: '✓ Ja, komme', + maybe: '? Vielleicht', + no: '✕ Nein', + bringingPeople: (count) => `Bringst du jemanden mit? (${count})`, + noteLabel: 'Notiz (optional)', + notePlaceholder: 'z. B. „Komme erst um 20 Uhr“', + send: 'Antwort senden', + sending: 'Sende...', + genericError: 'Konnte nicht senden', + poweredBy: 'Powered by', + dateLocale: 'de-DE', + }, + en: { + rsvpTitle: 'Please RSVP', + pageTitleSuffix: '— RSVP', + allDay: 'All day', + peopleAttending: 'people attending', + cancelledNotice: '⚠️ This event has been cancelled.', + successHeading: 'Thanks for your reply!', + successYou: 'You answered', + successComing: '"Yes, coming"', + successNotComing: '"No"', + successMaybe: '"Maybe"', + successHint: '. You can reopen this page anytime to change your answer.', + changeAnswer: 'Change answer', + formHeading: 'Please RSVP', + yourName: 'Your name', + yourNamePlaceholder: 'e.g. Anna Smith', + emailLabel: 'Email (optional)', + emailPlaceholder: 'anna@example.com', + areYouComing: 'Are you coming?', + yesComing: '✓ Yes, coming', + maybe: '? Maybe', + no: '✕ No', + bringingPeople: (count) => `Bringing anyone? (${count})`, + noteLabel: 'Note (optional)', + notePlaceholder: 'e.g. "Will arrive at 8pm"', + send: 'Send reply', + sending: 'Sending...', + genericError: 'Could not send', + poweredBy: 'Powered by', + dateLocale: 'en-US', + }, +}; + +export function getStrings(lang: Lang): Strings { + return DICTS[lang] ?? DICTS.de; +}