@acms-subir/core 0.3.34 → 0.3.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/cli/migrations.generated.mjs +7 -1
  3. package/docs/mobile.md +9 -6
  4. package/docs/theme-authoring.md +5 -4
  5. package/integration.mjs +3 -1
  6. package/mobile-template/client/AGENTS.md +2 -1
  7. package/mobile-template/client/README.md +1 -1
  8. package/mobile-template/recipes/events/files/app/events/[slug].tsx +50 -22
  9. package/mobile-template/recipes/events/files/app/events/index.tsx +4 -3
  10. package/mobile-template/recipes/events/files/components/RsvpPanel.tsx +270 -0
  11. package/mobile-template/recipes/events/recipe.json +6 -3
  12. package/mobile-template/recipes/rsvp/files/components/RsvpPanel.tsx +270 -0
  13. package/mobile-template/recipes/rsvp/recipe.json +15 -0
  14. package/package.json +1 -1
  15. package/src/components/Announcements.tsx +14 -1
  16. package/src/components/LiveCard.astro +23 -10
  17. package/src/components/MobileApp.tsx +54 -4
  18. package/src/layouts/Site.astro +45 -38
  19. package/src/lib/announcements/api.ts +8 -4
  20. package/src/lib/announcements/store.ts +4 -0
  21. package/src/lib/cache/policy.ts +2 -2
  22. package/src/lib/calendar/hooks.ts +5 -1
  23. package/src/lib/legal/app-privacy.ts +5 -3
  24. package/src/lib/legal/text-en.ts +1 -0
  25. package/src/lib/legal/text-es.ts +1 -0
  26. package/src/lib/live/view.ts +28 -24
  27. package/src/lib/live/words.ts +94 -0
  28. package/src/lib/mobile/bookings.ts +17 -11
  29. package/src/lib/mobile/forms.ts +21 -11
  30. package/src/lib/mobile/manage.ts +2 -0
  31. package/src/lib/mobile/openapi.ts +8 -3
  32. package/src/lib/mobile/rsvp.ts +65 -0
  33. package/src/lib/mobile/schemas.ts +9 -1
  34. package/src/lib/mobile/site.ts +3 -1
  35. package/src/lib/push/api.ts +13 -1
  36. package/src/lib/push/service.ts +211 -24
  37. package/src/lib/push/store.ts +35 -8
  38. package/src/lib/push/types.ts +23 -2
  39. package/src/lib/repo/migrations.ts +6 -0
  40. package/src/lib/schema.ts +2 -1
  41. package/src/lib/search-i18n.ts +41 -4
  42. package/src/lib/site-chrome.ts +8 -0
  43. package/src/lib/site-words.ts +62 -0
  44. package/src/pages/admin/calendar/bookings.astro +3 -1
  45. package/src/pages/api/v1/events/[slug]/rsvp.ts +8 -0
  46. package/src/styles/mobile-app.css +7 -0
  47. package/src/theme-sdk/index.ts +2 -0
@@ -185,6 +185,8 @@ const emailNotice = !emailConfig.config.enabled || emailConfig.config.provider =
185
185
  : emailStatus.linkError;
186
186
  const TABS = [['upcoming', 'Upcoming'], ['unconfirmed', 'Needs approval'], ['past', 'Past'], ['cancelled', 'Cancelled']] as const;
187
187
  const statusLabel = (b: Booking) => (b.kind === 'block' ? 'Blocked' : b.status[0].toUpperCase() + b.status.slice(1));
188
+ // where it was made: the website, an app (/api/v1/bookings), staff, an API key or the booking agent
189
+ const SOURCES: Record<Booking['source'], string> = { web: 'Website', app: 'App', admin: 'Staff', api: 'API', agent: 'Agent' };
188
190
  const whenOf = (b: Booking) => (b.end - b.start >= 86_400_000 - 3_600_000 && ymd(b.start, tz) !== ymd(b.end - 1, tz)
189
191
  ? `${f.day.format(b.start)} – ${f.day.format(b.end - 1)}`
190
192
  : b.end - b.start >= 86_400_000 - 3_600_000 ? 'All day' : `${f.time.format(b.start)} – ${f.time.format(b.end)}`);
@@ -327,7 +329,7 @@ const activeLinks = links.filter((l) => l.active && resById.has(l.resourceId));
327
329
  <div><dt>{ev ? 'Event' : 'Where'}</dt><dd>{ev ? <a href={eventUrl(ev.slug)} target="_blank" rel="noopener">{ev.title}</a> : r?.name ?? '—'}{l ? ` · ${l.name}` : ''}</dd></div>
328
330
  {b.seats > 1 && <div><dt>Seats</dt><dd>{b.seats}</dd></div>}
329
331
  {Object.entries(b.answers).map(([k, v]) => <div><dt>{k}</dt><dd>{v}</dd></div>)}
330
- <div><dt>Booked</dt><dd>{f.day.format(b.createdAt)} · {b.source}</dd></div>
332
+ <div><dt>Booked</dt><dd>{f.day.format(b.createdAt)} · {SOURCES[b.source] ?? b.source}</dd></div>
331
333
  </dl>
332
334
  <form method="post" class="bk-notes">
333
335
  <input type="hidden" name="op" value="notes" /><input type="hidden" name="id" value={b.id} />
@@ -0,0 +1,8 @@
1
+ import { getRsvpStatus } from '../../../../../lib/mobile/rsvp';
2
+ import { readRoute } from '../../../../../lib/mobile/route';
3
+ import { methodNotAllowed } from '../../../../../lib/mobile/http';
4
+ export { preflight as OPTIONS } from '../../../../../lib/mobile/http';
5
+ // no-store: live seats; a cached "3 left" would invite RSVPs that fail
6
+ export const GET = readRoute(getRsvpStatus, false);
7
+ export const HEAD = GET;
8
+ export const ALL = () => methodNotAllowed();
@@ -81,6 +81,13 @@
81
81
  .ma-check:has(input:disabled) { cursor: default; opacity: 0.6; }
82
82
  .ma-dot { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 6px; vertical-align: 1px; }
83
83
  .ma-lead { max-width: 240px; margin: 10px 0 0; }
84
+ .ma-fields { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0 16px; }
85
+ .ma-fields .ma-lead { flex: 1 1 200px; }
86
+ .ma-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; min-height: 36px; padding: 4px 6px; background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md); }
87
+ .ma-tags:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
88
+ .ma-tag { display: inline-flex; align-items: center; gap: 5px; background: var(--sel); color: var(--text-2); font-size: 12px; font-weight: 600; padding: 2px 8px; border-radius: var(--r-full); }
89
+ .ma-tag button { background: none; border: 0; color: inherit; cursor: pointer; font-size: 10px; padding: 0; }
90
+ .ma-tags input { flex: 1; min-width: 70px; background: none !important; border: 0 !important; box-shadow: none !important; padding: 2px !important; }
84
91
  .ma .form-actions { margin-top: 6px; }
85
92
  .ma-saved { color: var(--green); font-size: 12.5px; font-weight: 500; }
86
93
 
@@ -22,6 +22,8 @@ export interface SectionProps<D = Record<string, unknown>> { data: D; variant: s
22
22
  export type { LinkValue, EventItem, PostItem, PostAuthor, BookingItem } from '../lib/sections';
23
23
  /** Props for templates/header.astro and templates/footer.astro. */
24
24
  export type { SiteChrome, ChromeLink } from '../lib/site-chrome';
25
+ // core's chrome labels for any language (a template already gets them as site.words)
26
+ export { siteStrings, type SiteStrings } from '../lib/site-words';
25
27
  import type { SiteChrome } from '../lib/site-chrome';
26
28
  export interface ChromeProps { site: SiteChrome }
27
29