Commit graph

145 commits

Author SHA1 Message Date
335a4db7cc fix(account): show payment history + next-charge for paid-then-$0 members
Three related changes on /member/account:

1. Payment History section now renders when contributionAmount > 0 OR
   past payments exist. Previously a paid member who switched to $0 lost
   visibility of their own past charges.

2. New "Next charge: $X on DATE" row renders above the transaction list
   when nextPaymentDate is available, using --candle dashed border.

3. server/api/helcim/subscription.get.js now reads dateBilling from
   Helcim's GET response and handles data as either object or array.
   Helcim's real shape is {data: {id, dateBilling, ...}} — the old code
   expected {data: [{nextBillingDate}]} and returned empty strings, so
   the Membership-card "Next payment" row never rendered for members
   whose cached date was missing. subscription.post.js and
   update-contribution.post.js have the same wrong field name in their
   CREATE flows; left for a follow-up — the GET refresh masks it.

Manual edit-flow and admin-flow tests also recorded in
docs/LAUNCH_READINESS.md.
2026-04-20 12:36:18 +01:00
a80728f0a8 feat(signup): unify cadence UX across accept-invite, join, and account
Extract shared SignupFlowOverlay component. Static "Monthly Contribution"
label on all three contribution inputs (was misleadingly dynamic).
"Per Year"/"Per Month" toggle copy; Per Year default on accept-invite,
Per Month default on join. Live billing-summary card on both signup
flows. Welcome-heading on dashboard via ?welcome=1 for new signups.
$0-member polish on account page (hide payment-history + Solidarity
Fund prompts). State-aware contribution-change hint. Invite accept now
creates Helcim customer and sets auth cookie server-side for both free
and paid branches. Pre-registrant invite + /join signup flows manually
verified against Cleo Nguyen preReg and $0-$50 variants.
2026-04-20 12:34:59 +01:00
7704557f16 merge: catch up with feature/helcim-plan-consolidation base
# Conflicts:
#	server/api/auth/member.get.js
#	server/api/members/update-contribution.post.js
#	tests/server/api/update-contribution.test.js
2026-04-19 21:33:40 +01:00
dfc03f851b fix(review): accept arbitrary amounts in payment-setup; rename m.tier → m.amount in activity text 2026-04-19 19:15:32 +01:00
b17e006d65 feat(frontend): rename contributionTier → contributionAmount across remaining pages 2026-04-19 19:08:57 +01:00
5ef0cc845f feat(account): replace tier control with amount input + guidance chips 2026-04-19 19:03:08 +01:00
4d10c4e0a2 feat(join): replace tier dropdown with amount input + guidance chips 2026-04-19 18:59:24 +01:00
5d6fcdd78d feat(account): show next payment date with lazy Helcim refresh
Persist nextBillingDate on subscription create/update; unset on
cancel or downgrade to free. Account page displays the cached
date and lazily refreshes from Helcim when the cached value is
within 24h of now (or missing).
2026-04-19 18:32:04 +01:00
19c77a3ab6 feat(account): in-app payment history + change card
Add Payment history section (live-read from Helcim, with loading/empty/error states)
and Change card flow (HelcimPay.js zero-dollar auth -> POST /api/helcim/update-card)
to /member/account. Relabel Helcim portal link to "Advanced billing in Helcim →"
and demote it to a secondary link at the bottom of the billing group.
2026-04-19 16:36:19 +01:00
f2e2cedb67 fix(join): redirect immediately on subscription success
Removes the 3-second setTimeout that deferred navigateTo('/welcome').
The overlay success state was a holdover from the pre-refactor Step-3
inline block; now that /welcome is the single welcome surface, the
delay just stalls a completed action and fights the continuous-flow
goal of the overlay.
2026-04-19 12:58:07 +01:00
968a127f96 fix(join): move flow overlay outside v-if so it survives auth flip
After createSubscription() calls checkMemberStatus(), isAuthenticated
flips to true and the <template v-else> branch unmounts, taking the
Teleport (and its overlay) with it. The authenticated 'You're already a
member' UI then showed for the 3-second pre-redirect delay, producing a
visible flash before navigateTo('/welcome') fired.

Teleport now lives at the root div alongside the v-if/v-else branches,
so the overlay stays mounted through the auth state transition and
covers the page continuously until the redirect.
2026-04-19 12:53:50 +01:00
f7c6bd88e7 refactor(join): move success state into overlay; remove step 2/3 UI 2026-04-19 12:23:19 +01:00
1bb59f07be refactor(join): auto-open Helcim modal after form submit 2026-04-19 12:21:10 +01:00
5a4c09f988 feat(join): add flow overlay scaffolding for submit→redirect states 2026-04-19 12:19:01 +01:00
a22a576bff fix(join): raise signup form above supporting copy 2026-04-19 12:16:30 +01:00
fd9ce5bc2c fix(ui): disambiguate annual tier labels
"$50/yr" was ambiguous — could mean the $5 tier in annual mode or the
$50 tier in monthly mode. On /join the dropdown now shows both prices
("$5/mo → $50/yr") in annual mode. On the account page TierPicker
gains a subtitle slot; annual mode shows "$N/mo tier" beneath the
annual price so members recognize which tier they're on.
2026-04-18 22:06:38 +01:00
fb337a4277 feat(account): display cadence and annual pricing in tier selector 2026-04-18 18:08:10 +01:00
748a84d001 chore(join): drop unused contributionOptions + formatTierAmount label param 2026-04-18 18:04:54 +01:00
673f881b54 refactor(join): use getTierAmount helper for cadence pricing 2026-04-18 18:02:04 +01:00
cd0d3f7167 feat(join): cadence selector with annual pricing (monthly×10)
Radio-pair cadence selector (Monthly / Annual) added to the join form,
reusing the existing .circle-radio styling. contributionItems computed
reactively; all tier labels and the left-column price list update on
toggle. cadence submitted with the subscription payload. payment-setup
hardcoded to monthly (annual upgrades go through /join).
2026-04-18 17:59:10 +01:00
c816d4b373 style(payment-setup): drop ColumnsLayout wrapper 2026-04-18 17:06:34 +01:00
37a58cb0eb feat(member): pending_payment retains access, soften status copy
pending_payment now grants the same RSVP/peer-support capabilities as active,
and status banner/label copy is rewritten to be non-threatening ("Setting up
payment", "Paused", "Closed"). Aligns member-facing copy across the account
page with the capability model.
2026-04-18 17:06:22 +01:00
c5e901ed24 feat(signup): community guidelines agreement and policies routes
Introduces /community-guidelines and /policies/{privacy,terms,[slug]} pages,
swaps the signup/invite checkbox from agreedToTerms to agreedToGuidelines,
adds Member.agreement.acceptedAt, and stamps the field when a Helcim
customer is created.
2026-04-18 17:06:10 +01:00
e0d11e47f4 chore: remove admin series-management stub actions 2026-04-17 17:27:27 +01:00
7e7672d52b New SiteContent. 2026-04-16 21:11:14 +01:00
02222a5c16 Copy and layout improvements. 2026-04-16 21:11:05 +01:00
1e9e9c4d97 fix(auth): stop wiki login loop to coming-soon and surface non-member state
Some checks failed
Test / vitest (push) Failing after 6m9s
Test / playwright (push) Has been skipped
Test / visual (push) Has been skipped
Test / Notify on failure (push) Successful in 2s
Members (and pre-registrants) hitting wiki.ghostguild.org were getting bounced
to /coming-soon with a "Pre-Register" link, even when the OIDC flow was
working correctly.

- Allowlist /auth/oidc-error, /auth/logout-confirm, /auth/logout-success,
  and /verify in the coming-soon middleware so OIDC errors and main-site
  magic links stop redirecting to the pre-register page.
- Raise OIDC Interaction TTL from 10m to 15m so it outlives the magic-link
  JWT and legitimate members don't hit expired-interaction errors when they
  click the email a few minutes late.
- Differentiate the "email isn't a registered member" response on the wiki
  login route and show a dedicated "Not a member yet" state with a
  pre-register link and contact email, instead of the misleading
  "Check your inbox" that silently failed.
2026-04-15 17:55:55 +01:00
2394248d53 Updates
Some checks failed
Test / vitest (push) Failing after 6m9s
Test / visual (push) Has been skipped
Test / playwright (push) Has been skipped
Test / Notify on failure (push) Successful in 2s
2026-04-15 17:45:09 +01:00
28040f44f4 refactor(board): atomic delete + query limit + composable cleanup
Some checks failed
Test / vitest (push) Failing after 7m17s
Test / playwright (push) Has been skipped
Test / visual (push) Has been skipped
Test / Notify on failure (push) Successful in 1s
Delete uses findOneAndDelete with author match (no TOCTOU window);
existence check only runs on miss to distinguish 403 vs 404. Posts
list capped at 200. Drop unused resolveTagChannel and refreshParams;
route slack URL building through the composable's slackUrl helper.
2026-04-15 12:47:53 +01:00
f691f095dc feat(board): inline delete confirmation + a11y polish
Some checks failed
Test / vitest (push) Failing after 6m2s
Test / playwright (push) Has been skipped
Test / visual (push) Has been skipped
Test / Notify on failure (push) Successful in 2s
Replace window.confirm with an inline Delete? / Cancel / Confirm flow on
post cards. Add focus-visible outlines, initials in avatar placeholders,
and promote post/form titles from h3 to h2 for heading order.
2026-04-14 22:15:50 +01:00
7292b11c0b feat(member): account/profile polish + tier upgrade flow
- Timezone: curated USelectMenu dropdown (app/config/timezones.js), preserves unknown saved values
- Profile save now uses useToast() for success/error; remove inline save banner
- Nav onboarding dot nudged down 1px for optical alignment with lowercase text
- Onboarding: skip a suggestion with POST /api/onboarding/track {skip}; member.onboarding.skipped map; does not affect graduation
- CirclePicker takes :saved-value so 'Current' badge stays until save completes
- PrivacyToggle is binary (USwitch labeled Private); member schema enum reduced to ['members','private']; zod coerces legacy 'public'
- New /member/payment-setup page: HelcimPay $0 verify + update-contribution, wired from account.vue via requiresPaymentSetup redirect
- Helcim portal: NUXT_PUBLIC_HELCIM_PORTAL_URL env + account.vue 'Manage billing in Helcim' link
- Migration script: scripts/migrate-privacy-public-to-members.js
2026-04-14 20:35:37 +01:00
9a560f2a3b feat(board): redesign classifieds + Slack channel creation
Adds AdminGhost bot token for admin-only Slack channel creation, refreshes
BoardPostCard/Form layouts, and expands admin board-channels management.
2026-04-14 20:20:17 +01:00
6f3d088763 fix(board): surface delete errors via toast 2026-04-14 17:38:32 +01:00
7707068f36 feat(board): admin page for managing board channels 2026-04-14 17:27:06 +01:00
4b3ba411dd fix(board): unwrap API envelope in composables, isolate member profile fetch 2026-04-14 17:24:30 +01:00
f8bc5502ba feat(board): replace board/peer support with posts list on member profile 2026-04-14 17:22:04 +01:00
698f786951 refactor(board): accept refresh params in useBoardPosts mutators 2026-04-14 17:19:48 +01:00
61d33f5db3 feat(board): replace profile board section with posts list 2026-04-14 17:17:09 +01:00
5bdc3244bd fix(board): handle submit errors + tolerate tag fetch failure 2026-04-14 17:14:22 +01:00
c06cdd71fd feat(board): rewrite board.vue with classifieds layout 2026-04-14 17:11:45 +01:00
19d519b153 Event fixes 2026-04-14 16:17:55 +01:00
a0f60bcdc0 fix: rename hasEngagedEcology → hasEngagedBoard in onboarding status, clean up stale ecology references 2026-04-14 12:25:24 +01:00
49c54764c6 rename ecologyTopics → boardTopics in member detail page 2026-04-14 12:18:16 +01:00
cdef868256 Rename communityEcology → board across frontend, add Board nav, update redirects
- Add Board to exploreItems in AppNavigation
- Update ecology.vue + connections.vue redirects to /board
- Rename all communityEcology refs to board in member profiles, dashboard, admin, onboarding
- Update API path /api/members/me/community-ecology → /api/members/me/board
2026-04-14 12:15:51 +01:00
3e5cedb1a6 refactor(board): rename ecology-prefixed vars to board-prefixed, remove duplicate count div
- Renamed ecologyTagOptions, ecologyFilterTags, ecologyTagLabel → board* throughout refs, computed, helpers, and template
- Removed .filter-bar div (duplicate count display)
- Updated pageSubtitle to use filteredSuggestions.length so subtitle reflects active tag filtering
2026-04-14 12:11:47 +01:00
f43fff0ba0 Extract ecology view into standalone /board page, simplify members to directory-only
- Create app/pages/board.vue with ecology suggestions, tag filtering, clipboard
- Create app/composables/useBoard.js (calls /api/board/suggestions)
- Delete app/composables/useEcology.js
- Strip all ecology code from members/index.vue (view toggle, ecology state,
  ecology template, ecology styles, conditional computeds)
2026-04-14 12:08:58 +01:00
59d6e97787 Member/Ecology revamp.
Some checks failed
Test / vitest (push) Failing after 7m23s
Test / playwright (push) Has been skipped
Test / visual (push) Has been skipped
Test / Notify on failure (push) Successful in 2s
2026-04-14 09:25:09 +01:00
fc7ec52574 restrict members page to authenticated users only, remove public access 2026-04-13 22:26:14 +01:00
1d469c3617 fix: use CircleBadge consistently, load directory on 401 revert, skip redundant API call in ecology mode 2026-04-13 21:13:50 +01:00
d4c1664e5c fix: mobile filter layout + ecology count reflects filtered set 2026-04-13 21:11:09 +01:00