Commit Graph
70 Commits
Author SHA1 Message Date
joshuaandClaude Sonnet 5 f0f8d4c242 Fix early-bird price blending and mislabeling; add contact-only events
- Early-bird pricing: RegistrationOption now tracks each purchase as a
  separate price tranche instead of overwriting a single price/quantity
  on repeat purchases, so buying more tickets after a tier expires no
  longer re-prices tickets already bought at the old price. Stock-limit
  checks, total-due calculation, and the Finance report's revenue-by-
  option are all tranche-aware; pages that showed one blended price per
  line now render/total each tranche. Viewing a pending/partially-paid
  registration (dashboard, detail page, or an event's registration
  list) now refreshes stale pricing on the spot instead of only at
  payment time.
- Fixed the "(early bird)" dashboard label incorrectly firing on any
  line priced below the base option price (e.g. a plain cheaper
  variant) — it now checks the real applied-tier flag.
- Added contact-only events (e.g. baptism): no registration/payment
  flow, shown on the public site with a "Contact us" popup instead of
  a Register button. Configurable via the admin event wizard.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-20 17:26:35 +02:00
joshua f2c3172e16 Merge branch 'feature/site-branding-customization' into main 2026-08-20 14:57:44 +02:00
joshuaandClaude Sonnet 5 fd9e917b62 Bump version to 1.7.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.7.0
2026-08-20 14:57:23 +02:00
joshuaandClaude Sonnet 5 86af7093ac Add admin-configurable branding (colors, logo, favicon) and generic default fallbacks
Site Settings -> Branding now supports a Primary/Secondary/Accent brand color
system applied site-wide (buttons, nav, hover states, links) and to outgoing
email header/CTA colors, plus a favicon upload alongside the existing logo
upload, a live preview panel (website/email x desktop/mobile), and
logo-based color suggestions. The setup wizard's Branding step got the same
treatment. Fixes two related bugs found along the way: the setup wizard's
logo/favicon upload was missing its auth token, and a static favicon.ico in
Next's special app/ convention path was silently overriding the dynamic one.

Also replaces every "Hope Events"/"Hope Family Church" default (org name,
email subjects, WhatsApp messages, report metadata, API docs) with a neutral
"Cross Code" placeholder, and the optional legal settings (operator name, IO
details, website URL, effective date) with obviously-generic placeholders
instead of defaulting to real personal/organisational details -- since this
platform is deployed for multiple organisations. Adds SETTINGS.md documenting
every setting's default behaviour.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-20 14:49:51 +02:00
joshua 2d99b7cafe Merge branch 'feature/supervisor-payments-improvements' into main 2026-08-08 01:24:52 +02:00
joshuaandClaude Sonnet 5 906c79a8e8 Bump version to 1.6.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.6.0
2026-08-08 01:19:49 +02:00
joshuaandClaude Sonnet 5 47b79181b7 Add search and event filter to the Assigned donations list
Finding a specific leg to unassign meant scanning the whole list by
eye. Adds a text search (matches registrant, donor, or event) and an
event dropdown (built from events that actually have assigned legs)
above the list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 01:15:45 +02:00
joshuaandClaude Sonnet 5 34f9826829 Fix donation-assignment admin email reading as a real payment
The internal admin notice for applying a donation to a registration
reused buildPaymentAdminNotice as-is, so it read "Payment recorded" /
"Registration payment" — indistinguishable from an actual incoming
payment even though no new money changed hands. Adds a dedicated
buildDonationAssignmentAdminNotice wrapper (mirroring the one already
added for unassignment) so the subject, heading, and Type field all
say "Donation applied" instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 00:59:24 +02:00
joshuaandClaude Sonnet 5 252f80fadb Add ability to unassign a donation from a registration
Assigning a donation to a registration was one-way: the refund flow
could reverse the money but left the donation's "leg" payment in
place, permanently locking that portion of the donation as used even
though it had been refunded back out. Adds POST
/api/payments/unassign-donation, which deletes the leg, reverts the
registration's status/tickets the same way a refund downgrade already
does, and notifies the registrant. New "Assigned donations" list on
the supervisor Payments page surfaces existing legs with an Unassign
action, since no such list existed before.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 00:53:21 +02:00
joshuaandClaude Sonnet 5 0a5b08020f Speed up payment/refund processing on the supervisor dashboard
Reconciling a Yoco payment and sending payment links blocked the HTTP
response on ticket-PDF generation and email/WhatsApp sends; they now
run in the background like the other payment flows already did.
Registration/payment option loops (pricing, stock checks, ticket
generation) now resolve concurrently instead of sequentially. The
Payments page dropped a per-registration N+1 fetch and now refreshes
its lists in parallel after each action. Added missing indexes for
dashboard stats and donation-leg lookups, and made GET
/api/registrations optionally paginated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 00:00:29 +02:00
joshua 6759e9c2d3 Merge branch 'fix/join-us-button-logged-in' into main v1.5.4 2026-08-07 01:57:23 +02:00
joshuaandClaude Sonnet 5 8799eec717 Bump version to 1.5.4
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 01:57:02 +02:00
joshuaandClaude Sonnet 5 56e0c8a31f Fix Join Us button linking logged-in users to register page
Send logged-in users to their dashboard instead of the registration
form, matching how the Navbar already treats logged-in vs guest users.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 01:52:35 +02:00
joshua 4bcb07f9d1 Merge branch 'fix/help-modal-mobile-overflow' into main v1.5.3 2026-08-07 01:17:08 +02:00
joshuaandClaude Sonnet 5 a0a3dc2416 Bump version to 1.5.3
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 01:16:53 +02:00
joshuaandClaude Sonnet 5 51639322e2 Fix help guide popups overflowing the screen on mobile
The popup card had no overall height cap, only the tab content area
did, so the header/quick-links/footer could push the close button off
screen on short mobile viewports. The card is now capped to the
screen height with the header and footer pinned in place, and only
the tab content scrolls internally.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 01:14:44 +02:00
joshuaandClaude Sonnet 5 1f186d6d2a Bump version to 1.5.2
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.5.2
2026-08-07 00:47:54 +02:00
joshua 55e7ca9546 Merge branch 'fix/dashboard-mobile-styling' into main 2026-08-07 00:47:14 +02:00
joshua 8f69e58aa2 Add tab icons and fix mobile dashboard styling issues
- Add matching lucide-react icons to tab/mode switcher buttons on
  payments, at-the-door, manual, email-attendees, whatsapp-attendees,
  and admin cashup pages, mirroring icons already used in their help menus
- Fix navbar Logout button sitting lower than other nav links (missing
  border/padding classes that other links use for their active-underline)
- Fix stat card labels getting truncated on mobile by removing the
  ellipsis-cut label and widening the mobile grid to one column
- Fix Revenue trend / Top performing events rendering outside the
  viewport on mobile by containing horizontal overflow and truncating
  long event titles in the table
2026-08-07 00:41:52 +02:00
joshuaandClaude Sonnet 5 1b2f2a7c79 Stop tracking banner.json runtime data store
Same reasoning as scheduled-emails.json: it's mutated by the running
app (site banner content), not source. readBanner() already falls
back to sane defaults when the file is missing, so untracking it is
safe for fresh checkouts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 00:04:45 +02:00
joshuaandClaude Sonnet 5 7906248c67 Stop tracking scheduled-emails.json runtime data store
It's mutated by the running app (scheduled job queue), not source -
committing it churns the repo with live recipient/message content.
Kept on disk, just untracked; a fresh checkout will get an empty
store created on demand by ensureStore().

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 00:03:04 +02:00
joshua 22ffbf201e Merge branch 'fix/whatsapp-scheduling-channel-bug' into main (1.5.1) v1.5.1 2026-08-07 00:01:01 +02:00
joshuaandClaude Sonnet 5 be499f0d66 Fix scheduled job list/edit dropping message content
toClient() never returned the message body (html/text for email,
message for WhatsApp), so "Manage scheduled" showed nothing to view
or edit even though the content existed in storage. Editing a
scheduled WhatsApp message also saved to the wrong payload field
(text instead of message), silently discarding the edit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 00:00:43 +02:00
joshuaandClaude Sonnet 5 75b2f8ccc5 Bump version to 1.5.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 23:41:43 +02:00
joshua 4f003f1628 Merge branch 'fix/whatsapp-scheduling-channel-bug' 2026-08-06 23:40:32 +02:00
joshuaandClaude Sonnet 5 b3ff2b9c5e Fix scheduled WhatsApp messages sending as email; add 24h cleanup and recipient display
The scheduled-job store never persisted the channel field, so the
send worker always fell through to its email branch regardless of
what was requested. Also purges sent jobs 24h after sending instead
of keeping them forever, and surfaces who each scheduled job will go
to in the admin "manage scheduled" lists (now correctly filtered per
channel too).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 23:37:35 +02:00
joshuaandClaude Sonnet 5 0833888eaa Bump version to 1.5.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.5.0
2026-08-06 15:29:17 +02:00
joshuaandClaude Sonnet 5 b626404640 Merge branch 'feature/site-redesign' (1.5.0)
Full site visual redesign, site-wide contextual help system, dashboard
KPI overhaul (rolling trailing-month window), and assorted fixes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 15:27:39 +02:00
joshuaandClaude Sonnet 5 0f2b5afa74 Help guide opens on demand only; add At the door to admin quick actions
- The site-wide help guide no longer auto-opens on first visit to a page
  — it only opens when the help button is clicked. Removed the
  now-pointless "Don't show this again" checkbox and the per-page
  dismissal tracking it drove.
- Admin dashboard quick actions was missing "At the door" (walk-in
  registration, payments, ticket printing), which Supervisor already had.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 15:17:12 +02:00
joshuaandClaude Sonnet 5 8e6cb542d9 Full site redesign, help system, and dashboard stats fixes
Multi-phase visual facelift (design tokens, dashboards, sidebar/navbar
shell, per-page help guides, and a layout/content pass across every
remaining page) plus backend fixes to the dashboard KPI stats:

- Admin/Supervisor dashboard KPIs (revenue, donations, registrations,
  tickets sold) now use a rolling trailing-month window (today back one
  calendar month, e.g. 9 May - 8 June if today is 8 June) instead of
  calendar month-to-date, which under-counted for most of the month.
  The comparison window shifts the same way, so like is still compared
  with like.
- Reports deep-links from those stat tiles now match the same window
  (range=trailing_month, replacing range=this_month).
- Design tokens (brand-* Tailwind scale + shadcn CSS variables), a
  site-wide contextual help button, fixed dashboard sidebar/navbar,
  Admin/Supervisor/Staff/User dashboard rebuilds backed by a new
  GET /api/stats/overview endpoint, a dedicated Contact page, Site
  Settings restyle with WhatsApp config folded in, and an Account
  activity feed backed by a new SecurityEvent model.
- Every remaining page (home, events, registration flow, auth, legal,
  payment results, and every Admin/Supervisor/Staff/User tool page)
  restyled onto the same design tokens, several with real layout
  upgrades (home hero, events list/detail, donate page, auth pages).
- 20+ new dedicated help guides so the whole site has page-specific
  help content instead of falling back to a generic guide.
- Assorted fixes surfaced along the way: donation-leg double-counting
  in payment stats, donations not counting toward revenue, refund
  netting in per-method report breakdowns, and donation
  over-allocation after a refund.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 15:00:10 +02:00
joshuaandClaude Sonnet 5 d74fec3a5c Bump version to 1.4.2
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.4.2
2026-08-06 09:13:04 +02:00
joshuaandClaude Sonnet 5 4bee1b24f7 Fix supervisor payments mobile tabs, reconcile donor, report method buckets, and refund/donation accounting
- Supervisor Payments: mode tabs now wrap on mobile instead of overflowing off-screen.
- Reconciling a Yoco transaction as a donation now lets staff pick who it's from.
- Reports payment-method breakdown now buckets into Cash/Card/EFT/Other everywhere,
  folding Apple Pay, Google Pay, and Yoco-portal payments into Card.
- Refunds now net against their original method's bucket (Cashup/Finance/Profit reports,
  My Payments filtering/display) instead of vanishing or falling into "Other".
- Refund form's method dropdown mirrors the real payment methods and auto-fills from the
  payment being refunded, replacing an ambiguous generic "Refund" option.
- Fixed donation remaining/unallocated balance inflating instead of shrinking when a
  donation is refunded (assign-donation endpoint, cashup reports, donations reports,
  and the Assign Donation panel all summed refund legs with the wrong sign).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 09:08:53 +02:00
joshuaandClaude Sonnet 5 70605923bf Bump version to 1.4.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.4.1
2026-08-05 15:00:44 +02:00
joshuaandClaude Sonnet 5 424141f216 Fix Reports mobile layout overflow and desktop date range overflow
Report popup buttons and the page's search/Back controls overflowed
off-screen on mobile instead of wrapping, and the sidebar's custom
date range inputs spilled outside the filter box on desktop.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 14:57:09 +02:00
joshuaandClaude Sonnet 5 d6ea4c37d7 Sync root package.json version to 1.4.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.4.0
2026-08-04 15:49:03 +02:00
joshua ebf521e64e Merge branch 'feature/reports-and-cashup-overhaul' (1.4.0) 2026-08-04 15:46:55 +02:00
joshuaandClaude Sonnet 5 e5fbcc2222 Bump version to 1.4.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 15:46:09 +02:00
joshuaandClaude Sonnet 5 1b4446c828 Hide dashboard sidebar on staff/supervisor/admin sub-pages; fix mobile overflow
- Sidebar now shows only on each role's root landing page
  (/dashboard/staff, /dashboard/supervisor, /dashboard/admin) and hides on
  every sub-page beneath them, not just Reports. Navbar's "Dashboard" link
  always leads back to the role root.
- Fixed two dropdown panels (EventsDropdown, the Email/WhatsApp Attendees
  recipient picker) that could extend past the viewport's right edge on
  narrow screens; both now stretch to their trigger's width like other
  dropdowns in the app already do.
- Wrapped the Admin Cashup event-costs table in the same overflow-auto
  container every sibling table on that page already uses, so it scrolls
  horizontally on narrow screens instead of squeezing its columns.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 15:30:56 +02:00
joshuaandClaude Sonnet 5 0de3f4be7d Fix financial double-counting, rebuild cashup accountability, and redesign the Reports page
Financial correctness (donation-leg model):
- Donations are no longer mutated when assigned to a registration; assignment now
  creates an immutable "leg" record referencing the original donation instead.
- Fixed several places where money was double-counted once a donation was partially
  or fully assigned (Payments, Revenue summary, Cashup reconciliation, Finance
  report, Profit report, Master Orders, Revenue Detailed).
- Payments now record who recorded them (recordedBy), separate from who they're for.

Cashup:
- Per-user cash denomination counting (optional, any time) replaces the single
  event-wide manual entry; the event's cash actual is the live sum of these counts.
- New "Payment accountability by staff member" breakdown across all methods, and a
  read-only "Report" tab that opens automatically once an event is closed.

Reports page redesign:
- New shell: sidebar of universal filters (events, date range, past/inactive/closed
  toggles), searchable/categorized report grid, and a popup viewer with
  Print/Email/Excel/WhatsApp actions plus an in-app Reporting Guide.
- Visual pass: colored stat tiles and bar charts on most reports, matching mockups.
- PDF exports (download/Print/Email/WhatsApp) now share a branded design mirroring
  the web report — colored header, stat tiles, bar chart, highlighted totals.
- Excel export now produces a styled .xlsx (via exceljs) instead of a plain CSV.
- Master Orders' "Donations made" table is now included in every export channel.

Bug fixes discovered while testing exports:
- Report emails now go through the shared, DB-configurable mail utility instead of
  a one-off transporter that ignored Site Settings SMTP config.
- WhatsApp report sends now surface the actual WAWP API error and auto-recover a
  disconnected session, instead of a bare axios status-code message.

Also: Admin-editable notification preference, richer Admin Registrations dashboard,
{{payment.link}} placeholder for Email/WhatsApp Attendees, and background
email/WhatsApp attendee sending.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 14:52:54 +02:00
joshua 56f2a9f7fc Merge branch 'fix/self-service-kiosk-lookup' v1.3.2 2026-08-03 13:03:12 +02:00
joshuaandClaude Sonnet 5 b081ed3c8b Rework self-service kiosk account lookup for privacy and safety (1.3.2)
Replaces the explicit "look up existing account" search field with automatic
lookup as email/phone are entered, requires operator confirmation before any
matched account's name/email/phone/preference is changed, adds a password
show/hide toggle, and fixes two bugs found during testing: entering a phone
number belonging to a different account could silently overwrite the form
with that account's details, and re-checking an unchanged field (e.g. from
tapping a ticket quantity button) could revert edits already made. Also adds
a server-side check rejecting registrations whose email and phone resolve to
two different existing accounts, as defense in depth.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 12:56:26 +02:00
joshua 8a75c9155b Bump version to 1.3.1 v1.3.1 2026-07-28 16:17:37 +02:00
joshua 8850984055 Merge branch 'fix/self-service-kiosk' 2026-07-28 16:16:31 +02:00
joshua 21176e1e0b Populate email/phone from an unmatched kiosk search query
When the account lookup finds no match, carry the typed query into whichever
of Email/Phone it resembles (email-shaped or phone-shaped) instead of
discarding it, so the operator doesn't have to retype it. Leaves both blank
if it matches neither shape, and resets Name/notification preference for a
fresh entry.
2026-07-28 16:05:41 +02:00
joshua b4cd140168 Replace as-you-type account check with an explicit search field
The kiosk previously ran a debounced background lookup on every keystroke
in the visitor Email/Phone fields, silently autofilling matches. Replaced
with a dedicated "Look up existing account" field that only searches when
the operator presses Enter or clicks Search, and matches exactly against
either email or phone (never both from one query, to avoid digits in an
email being misread as an unrelated phone number). Also simplified the
"account already exists" banner wording.
2026-07-28 14:35:28 +02:00
joshua 5167706d1b Update changelog for self-service kiosk fixes 2026-07-28 14:24:21 +02:00
joshua 047f61b627 Fix self-service kiosk: hide closed events and autofill known visitors
- GET /api/events/all gains an opt-in excludeClosed=true param, used only by
  the kiosk, so closed events no longer show as selectable there while other
  admin/supervisor screens that still need to see closed events are unaffected.
- GET /api/users/check-exists now also returns the matched account's name,
  email, phone, and notification preference (safe fields only). The kiosk's
  existing debounced lookup uses this to autofill whichever fields are still
  blank when a visitor enters an email or phone that matches an existing
  account, without overwriting anything already typed.
2026-07-28 14:21:47 +02:00
joshuaandClaude Sonnet 5 1815f78c85 Bump version to 1.3.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.3.0
2026-07-27 15:06:08 +02:00
joshuaandClaude Sonnet 5 29036d0612 Merge branch 'feature/door-checkin'
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 15:04:51 +02:00
joshuaandClaude Sonnet 5 c07e9c928a Add door check-in flow for Main Tickets
Lets staff redeem a registration's Main Tickets by quantity at the door
(via the Payment/registration flow) instead of scanning each QR code,
and automatically emails/WhatsApps a check-in confirmation to the
attendee. Also routes the At The Door "Open" button and post-payment
flow dynamically: paid registrations jump straight to Check-In instead
of a forced ticket print, since tickets are already sent automatically.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 14:56:31 +02:00