The deploy's next build fails on react/no-unescaped-entities. Bump to 1.37.3; the handover now says to lint the whole frontend before tagging. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7.9 KiB
7.9 KiB
Handover — where things stand and how to carry on
Last updated: 2026-10-23, after 1.37.3. The plan itself is in ROADMAP-v2.md (decisions table at the end); the previous round of features is in FEATURES-ROUND-1.md.
Done so far (road to 2.0)
| Version | What |
|---|---|
| 1.32.0 | Early-bird ribbon on event cards |
| 1.33.0 | Multi-day events phase A — sessions, late joining + late pricing, per-session check-in, attendance register, session reminders, certificates (4 templates, verify page) |
| 1.34.0 | Background jobs on pg-boss (admin Background jobs page), Playwright e2e tests, Gitea CI workflow, scripts/deploy.sh |
| 1.35.0 | Multi-day events phase B — "pick sessions" (per-session tickets and prices, session capacity) |
| 1.37.3 | Fix: the production build failed on unescaped quotes in a help text |
| 1.37.2 | Payment status checks (PayFast transaction history; job every 15 min; Payments → Reconcile → Waiting for payment), PayFast Test connection |
| 1.37.1 | "Pay online" hidden when no provider is on or under R15; SnapScan/Zapper dropped from the roadmap |
| 1.37.0 | PayFast (signed form, ITN checks), ProviderCheckout with amount checks, the "Pay online" page (/pay/<id>) where payers choose a provider |
| 1.36.0 | Payment provider interface (backend/src/payments) with Yoco behind it, ProviderTransaction, Payment.provider, Site settings → Payments (on/off and order per provider), R15 minimum |
| 1.35.1 | Waitlist per session, session picker at the door, "All sessions" tickets let people tick sessions at one price; fixes (per-session stock limits, offline service worker serving stale scripts) |
Next up
- 1.38.0–1.39.0 — POPIA toolkit (spec §3 in the roadmap).
- 1.40.0 + Hub v1 — install/update tooling and the Hope Events Hub (separate repo
joshua/hope-events-hub).
Working on this repo
- Release routine: branch
feat/<name>→ commit → bump withnpm version X.Y.Z --no-git-tag-versionin.,backendandfrontend→ add the## [X.Y.Z] - dateheading under[Unreleased]in CHANGELOG.md →git merge --no-ffintomain→git tag vX.Y.Z→git push origin main <branch> vX.Y.Z. One minor version per feature. - Before tagging: run
npx eslint srcinfrontendover the whole app (the deploy runsnext build, which fails on any lint error, e.g. an unescaped ' or " in JSX text). If a dev server is running, a full check build needs its own folder:NEXT_DIST_DIR=.next-buildcheck npx next build(then delete it andgit checkout frontend/tsconfig.json). - Changelog: add entries to
[Unreleased]as you go, in plain language. - Docs to keep in step: CHANGELOG.md, FEATURES.md, README.md, SETTINGS.md,
backend/API_DOCUMENTATION.md, the
/docsroute list inbackend/src/index.js, and in-app help infrontend/src/content/help/(register new pages inregistry.ts). - Prisma migrations:
npx prisma migrate dev --create-only --name xagainst a local DB. Prisma 7 keeps adding an unrelated_EventNotifyRecipientsprimary-key/index change — delete those two blocks from the generated SQL. It also rewrites the comment inmigration_lock.toml;git checkoutthat file back. NewAdminAuditActionvalues need a migration. - Server Node version: the deployment notes install Node 20, so dependencies must support Node 20 (that's why pg-boss is pinned to 10.x).
- Pushing: pushing from some shells fails with "Failed to authenticate user" (a stale saved credential); pushing from your own terminal works.
Tests
- Backend unit tests:
cd backend && npm test(Jest). - PayFast e2e (
e2e/payfast.spec.ts) pays into a real PayFast sandbox account and is skipped unlessE2E_PAYFAST_MERCHANT_ID,E2E_PAYFAST_MERCHANT_KEYandE2E_PAYFAST_PASSPHRASEare set (from the Sandbox dashboard). PayFast's documented public test merchant (10000100) no longer accepts payments. ITNs can't reach localhost; they're covered by unit tests (backend/tests/payments.test.js) — to try one for real, use a tunnel, a publicBACKEND_URLandPAYFAST_SKIP_IP_CHECK=true. - End-to-end:
npm run test:e2efrom the repo root (first time:npm installandnpx playwright install chromium). They start their own backend (5100) and frontend (3100) against<your DATABASE_URL database>_e2e, which is dropped and re-seeded every run (e2e/support/prepare-db.js). The DB user must be able to create databases. ~5 minutes in dev mode. Locally, Playwright reuses servers already running on 5100/3100. If the run times out waiting for the frontend (the home page returns 500 until the e2e backend is up), start them yourself —node e2e/support/prepare-db.js, then the backend frombackend/withPORT=5100, the e2eDATABASE_URL,JOBS_ENABLED=false,TWO_FACTOR_REQUIRED_ROLES=false, andnpx next dev -p 3100fromfrontend/withNEXT_DIST_DIR=.next-e2e NEXT_PUBLIC_API_URL=http://localhost:5100— then runnpx playwright test. Don't edit frontend files while it runs. - Careful with ad-hoc scripts against a dev/test database that has SMTP set up:
registrations and check-ins send real email/WhatsApp. Use made-up
@test.localpeople only. - CI:
.gitea/workflows/ci.ymlruns everything once a Gitea Actions runner is registered (none yet). Tag deploys need theDEPLOY_HOST,DEPLOY_USER,DEPLOY_SSH_KEY(+ optionalDEPLOY_PATH) secrets.
Where the multi-day code lives
backend/src/utils/sessions.js— all session rules (dates, check-in window, late pricing, pick sessions, capacity, grouping); unit tests inbackend/tests/sessions.test.js.backend/src/utils/certificates.js,sessionReminders.js,controllers/attendanceController.js(register + certificates API).backend/src/jobs/index.js— the background job registry.- Frontend:
src/lib/sessions.ts,src/components/events/ScheduleEditor.tsx,SessionPicker.tsx,SessionSchedule.tsx,src/app/dashboard/supervisor/attendance/.
Where the payment code lives
backend/src/payments/index.js— the provider registry and thePaymentProviderinterface (documented at the top), provider on/off and order (AppSettingpayment_providers), the R15 minimum, andcreateCheckout. Tests:backend/tests/payments.test.js.backend/src/payments/providers/yoco.js— Yoco: checkouts, webhook signature check, webhook parsing. Keys/webhook admin stays inutils/yoco.js+controllers/yocoController.js.backend/src/payments/webhook.js— shared webhook processing (Payment withprovider, donation split, registration status, tickets, emails,ProviderTransaction).backend/src/payments/checkouts.js— registration checkouts (balance, part, + donation).backend/src/payments/status.js— status checks for notifications that never arrived (payment-statusjob, Payments → Reconcile → "Waiting for payment"). PayFast looks payments up in its transaction history (findPayments); Yoco's Checkout API documents no lookup, so Yoco checkouts are "can't check". Tests:backend/tests/paymentStatus.test.js.- Adding a provider: write
providers/<id>.jswith the same interface, add it toPROVIDERSinindex.js, mounthandleProviderWebhook('<id>')at/api/webhooks/<id>(routes/webhookRoutes.js), and give it a settings card infrontend/src/components/admin/PaymentsTab.tsx. New providers start switched off. Payment.methodstays the wallet type (card, apple_pay…) because cashups bucket on it; the provider isPayment.provider.
Known gaps / follow-ups
- At the door, per-session tickets are booked on new registrations only; editing an existing registration leaves its booked sessions as they are (the backend refuses changes to picked lines). "Add & charge" for a session at the scanner isn't built.
- Ticket scanning by camera isn't covered by the e2e tests (headless browsers have no camera); scans are tested through the API.