Skip to content

v2 milestone → main (review before merge)#516

Open
KishParikh13 wants to merge 379 commits into
mainfrom
v2
Open

v2 milestone → main (review before merge)#516
KishParikh13 wants to merge 379 commits into
mainfrom
v2

Conversation

@KishParikh13

@KishParikh13 KishParikh13 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

v2 milestone → main

Promotes the v2 branch to main. main is a clean ancestor of v2 (no divergence) so this merges without conflict — it's a stable-checkpoint cut, not a feature merge. Head tracks v2, so this PR always reflects the latest (currently af647f7).

How to review

This is ~368 commits / 445 files — not reviewable as a single diff. The work was reviewed incrementally as it landed (per-PR review, Codex review, QA passes), and the whole milestone is already deployed to prod and TestFlight, so it's been validated live. Review by area / spot-check rather than line-by-line.

What's in v2 (high level)

  • v2 app: unified Home, Explore, Feed, event detail + boards, invite-links flow, profile, onboarding.
  • janata.app short-link worker + universal links (live in prod).
  • Backend: invite-code gate, guest RSVP, moderation, boards, push, attribution; migrations through 0028.

Recent fixes also included

Status

  • MERGEABLE (clean). CI green. Deploying v2 → prod + a fresh TestFlight build alongside this update.

KishParikh13 and others added 30 commits May 28, 2026 16:50
The first-run overview (#294) gated on `boardPeek.length === 0`, but the
overview's "Latest on your board" peek renders only when posts exist — so the
peek could never show: the moment a post existed, isNewUser flipped false and
the overview disappeared.

Base "new user" on discovery state instead: hasn't joined an event yet
(`signedUpEvents.length === 0`), independent of posts. Now a member who has
joined no events still sees the tour + their center + a live peek of their
board's activity, and it self-resolves once they RSVP. Returning members with
joined events keep the normal home (which carries its own #293 boards peek).

Verified on web: seeded a post on the local center board and confirmed the
peek renders inside the overview. frontend tests: 187 pass.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(feed): tighten post-detail header — single bar, no gap, drop redundant subtitle

The native post-detail overlay rendered its own back/title bar *below* the
persistent "Feed" tab header, and NativeChatHeader re-applied the top safe-area
inset — producing a doubled header and a large empty gap.

- Hide the "Feed" tab header while a post is open so the detail's own
  back/title bar becomes the screen header (mirrors the Explore screen).
- Drop the "<Center>" subtitle under "Post" — redundant with the
  "<Center> - Board" chip directly below it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(feed): backdrop behind sliding post detail to hide header-toggle reflow

Hiding the "Feed" tab header reflows the feed list beneath the detail
overlay; the horizontal slide exposed that upward shift on the way in and
out. Add a static opaque backdrop behind the sliding panel so it slides
over a uniform surface — no visible layout shift either direction.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Simplify native navigation from 4 tabs to 3 (Home / Explore / Feed) by
removing Profile from the bottom tab bar and surfacing it as a consistent
avatar button in the top-right of every tab header.

- TabHeader: new `showProfile` prop (default true) renders the user avatar
  as a `/profile` entry point. Native-only — web keeps its existing
  WebHeader / WebBottomNav profile entry untouched.
- (tabs)/_layout: profile screen set to `href: null` so /profile stays
  routable (web's WebBottomNav + SettingsPanel still link to it) while
  dropping the native tab icon. Avatar is hidden on the profile screen's
  own header.

No web routing changes, to stay clear of the in-flight web-nav redesign.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iOS + web)

Foundation:
- utils/analytics.ts: useAnalytics() -> typed null-safe track(); LiteralUnion
  AnalyticsEvent (160 known names autocomplete, any string still accepted);
  AnalyticsScreenTracker fires one $screen per route change (native + web).
- _layout.tsx: explicit PostHogProvider config — captureAppLifecycleEvents on,
  autocapture screens/touches off (screens handled by the tracker).

Coverage: instrumented 31 page/feature files (each with its .web sibling) —
187 events added/migrated, existing posthog?.capture calls migrated to track().
Static/presentational surfaces (legal, intro, landing, onboarding) intentionally
rely on the central screen tracker only.

Verified: tsc clean (0 new errors; 6 pre-existing baseline). Live-validated on
iOS simulator + web — $screen, app-lifecycle, and track() interaction events
(login_failed, logout) all confirmed arriving server-side with props.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ish (#299)

Reworks the Explore sheet around the real journey — members have a center and
events are the point — and fixes two iOS polish issues.

Explore (app/(tabs)/explore.tsx):
- Combined the old co-equal Events/Centers tabs into one events-first sheet:
  search → center dropdown → Today/Going → events.
- The home-center card is now a dropdown. Tapping opens an in-sheet picker
  ("Show events near" + Close) listing every center with city + event count;
  selecting one re-sorts the events by nearness to that center. Defaults to the
  member's home center; sorts (never filters) so the list is never empty.
- Picker has an "All centers" option (events from everywhere) and a distinct
  per-row button to open that center's page, separate from selecting it.
- Dropped the redundant "Center" filter chip; per-state counts + inset
  separators on the grouped centers list.

Map (components/map/Map.native.tsx):
- Offset the zoom/locate controls below the top-right profile avatar so they
  no longer overlap (regression from the 3-tab nav change).

DetailSection (components/ui/DetailSection.tsx):
- Balanced the hairline spacing (24 above / 18 below) so dividers stop crowding
  the text above them on center/event detail.

Verified on the iOS simulator. frontend tests: 187 pass; no new tsc errors.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The notification bell in TabHeader pushes to /notifications, but no such
route existed — it fell through to +not-found. The backend API, D1 schema
and the NotificationCenter UI were already built; this connects them.

- Add app/notifications.tsx: StackHeader (back + title) + NotificationCenter
- Register the route in the root Stack (app/_layout.tsx)
- Theme NotificationCenter + NotificationItem via useColors (they hardcoded
  light #fff / iOS-blue #007AFF; now match light/dark + brand orange and no
  longer render a white panel in dark mode)
- NotificationCenter gains a `showHeader` prop so the route's StackHeader
  supplies the title without a duplicate

In-app notifications only. Push (APNs/FCM) remains future work.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rge-297

# Conflicts:
#	packages/frontend/app/(tabs)/explore.tsx
The Pages project is named "chinmaya-janata" (its pages.dev domain is
project-janatha.pages.dev); the script used "project-janatha" and hit
"Project not found [8000007]" on the Pages deploy. --branch v2preview now
correctly publishes the isolated v2preview.project-janatha.pages.dev preview.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring the web (.web.tsx) screens in line with the recent native iOS UX.

Fix 1 — Explore mobile-web (app/(tabs)/explore.web.tsx):
Rebuild the MobileDiscoverFallback bottom sheet to mirror native explore.tsx
(commits #289 + #299), events-first:
- Drop the Events/Centers UnderlineTabBar tab model; the sheet now always
  shows events (search -> center dropdown -> Today/Going -> events list).
- Replace the Center filter chip + FilterPickerModal with the in-sheet
  "Show events near <center>" dropdown: picking a center re-sorts events by
  distance (sort, never filter, so the list never empties); an "All centers"
  option (Globe) shows events everywhere; each row has a separate chevron
  button that opens that center's page.
- Add a Create button in the filter row for logged-in users ->
  router.push('/events/form').
- Reuse the great-circle milesBetween ranking from native.
Desktop layout (DiscoverScreenWeb) is preserved unchanged.

Fix 2 — Notifications bell on web (app/(tabs)/_layout.tsx):
Add a notifications Bell button to WebHeader next to the profile avatar for
logged-in users -> router.push('/notifications'). The shared /notifications
route + NotificationCenter (themed via useColors) render as-is on web.

Quality gates: backend typecheck clean; 187/187 frontend tests pass.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
At >=1024px on web, compose Home as a centered ~1040px container with a
primary schedule column (Up Next + This Week/Coming Up) and a ~320px right
rail (member's center + welcome tour + board activity), instead of a narrow
640px column stranded in empty gray. Section blocks are extracted and reused
verbatim — only their arrangement differs. Mobile web and native iOS keep the
original single centered column unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
At >=1024px the profile container widens to 1080px and Birthday + Center pair
into a two-column row, tightening the page so it no longer reads as a sparse
stranded column. Empty read-only fields (Birthday, Center, Bio) now show a
quiet italic placeholder ("Not added yet", "No center selected", etc.) instead
of a bare em-dash. Mobile web keeps the stacked single column; native iOS is
unaffected (separate layout). Editing flow, validation, and the center search
dropdown are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: gitignore .gstack/ local artifacts

* style(design): desktop two-column Home layout on wide web

At >=1024px on web, compose Home as a centered ~1040px container with a
primary schedule column (Up Next + This Week/Coming Up) and a ~320px right
rail (member's center + welcome tour + board activity), instead of a narrow
640px column stranded in empty gray. Section blocks are extracted and reused
verbatim — only their arrangement differs. Mobile web and native iOS keep the
original single centered column unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style(design): wider, two-column Profile on desktop web

At >=1024px the profile container widens to 1080px and Birthday + Center pair
into a two-column row, tightening the page so it no longer reads as a sparse
stranded column. Empty read-only fields (Birthday, Center, Bio) now show a
quiet italic placeholder ("Not added yet", "No center selected", etc.) instead
of a bare em-dash. Mobile web keeps the stacked single column; native iOS is
unaffected (separate layout). Editing flow, validation, and the center search
dropdown are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring the desktop DiscoverScreenWeb sidebar to the same events-first model
as the mobile-web fallback and native explore.tsx: drop the Events/Centers
UnderlineTabBar and the FilterPickerModal in favor of an in-panel center
dropdown ("Show events near <center>" / All centers), Today/Going filter
chips, and a single distance-sorted events list. Sorting (not filtering) by
nearness to the selected area center keeps the list from ever going empty.
The desktop map split-pane, fly-to, and click-to-open interactions are
unchanged. Removes now-dead CenterItem, comingUpHint, section collapse, and
unused imports.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Desktop previously showed three overlapping "no posts" messages: a top line
in the board list, repeated copy on every board card, and a separate right-
pane prompt. Consolidate to a single, friendly empty state: the left board
list stays (relabeled "Your boards", duplicated "no posts" copy removed) so
members can pick a board, and the right/detail pane shows one "Start the
conversation" prompt with a "Write a post" compose CTA. EmptyPanel gains an
optional action button. Reads cleanly on mobile-web and native (shared files).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The first-run state stacked a 3-row feature tour (Discover events / RSVP in
a tap / Join the conversation) above the real content, which duplicated the
Your Center, Up Next, and Coming Up sections right below it. Replace the tour
with a single tight welcome banner (one orienting line + Explore CTA) so Home
leads with useful content: greeting -> welcome -> Your Center -> Up Next ->
Coming Up. Greeting, Your Center, Up Next, and Coming Up are unchanged.
Removes the now-dead FeatureRow and unused icon imports.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract WelcomeBanner from FirstRunOverview so it renders full-width
under the greeting on wide desktop (and inline at the top of the column
on mobile), instead of being stranded in the right rail. The rail now
holds just Your Center + board peek.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Welcome banner subtitle drops the em-dash clause; now just
  'Find satsangs, camps, and classes near you.'
- setup-local-demo.sh seeds a few center-board posts via the API after
  role elevation, so Home's 'Latest on your board' feed preview renders
  locally (matches what the v2 preview seed already produces).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Redesign the desktop web Feed (layout B from design-shotgun), keeping the
mobile card style intact:
- Centered single feed column of post cards (the same BoardPostCard used on
  Home) + a right context rail with search and 'Your boards' (center badged
  YOUR CENTER). Mobile path unchanged.
- Clicking a post swaps the column to the thread in place (no URL), with a
  '← Feed' back row + board chip; rail stays.
- Remove redundancies: per-post board label only shows when the feed spans
  more than one board; drop the thread card's duplicate source chip.
- Fix bugs: kill the literal 'Post' title and the malformed 'Boston, MA -
  Nearby away' subtitle; stop defaulting the selection to the first post.
- Fix padding: thread content/composer now use a consistent 18px inset
  inside the card (was 4/0); 'Nearby' no longer gets ' away' appended.
- BoardPostCard gains an asCard prop (card chrome without forcing the
  source line) so single-board feeds use cards without redundant labels.

187/187 frontend tests pass; typecheck clean; 0 console errors on web.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add components/layout/DesktopColumns with shared geometry tokens
(MAX_WIDTH 1040, PAGE_PADDING 32, RAIL_WIDTH 320, COLUMN_GAP 28,
BREAKPOINT 1024) + a useDesktopLayout() web-only breakpoint hook + a
DesktopColumns scaffold (full-width header, flex main column, fixed
320px rail). Home and Feed both consume it, so their content band and
right rail now align pixel-for-pixel (rail measured at left 888 /
right 1208 / width 320 on both) under one breakpoint.

Previously they shared maxWidth 1040 but diverged on padding (40 vs 24),
gap (32 vs 24), and breakpoint (1024 vs 980). Mobile layout untouched
(this is desktop-web only; mobile pass is next).

187/187 frontend tests pass; typecheck clean; 0 console errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keeps the web header focused on navigation (Home / Explore / Feed).
Event creation still lives on the Explore page. Drops the now-unused
canCreate flag and Plus import.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CenterDetailPanel.web referenced an undefined 'board' in the tab-count
props (board.messages.length), throwing ReferenceError on every render
of the desktop center panel (opened from Explore). Use the in-scope
boardMessages array. Typecheck now clean for this file.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the iOS detail screens (which dropped tabs): the desktop center
and event detail panels (shown on Explore) now render their sections
stacked under DetailSection headers in the single existing ScrollView,
instead of UnderlineTabBar.

- Center: Details -> Upcoming Events -> Board
- Event (registered): Details -> People -> Discussion
- Removes UnderlineTabBar + activeTab state from both panels; uses the
  same DetailSection pattern as the mobile center screen.

187/187 frontend tests pass; typecheck clean for both files; verified
center + event (registered and unregistered) render with no tabs and
no console errors.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… view (#305)

Tapping a post on the desktop feed now expands that card inline to
reveal the thread (replies + composer) while the rest of the feed stays
visible, rather than swapping the whole column to a dedicated thread
view. One card expands at a time; a 'Hide' control (ChevronUp) collapses
it. The expanded card gets a subtle accent border.

- FeedWorkspace desktop renders the stream always; the selected post
  renders as <PostThread> in place, others as <BoardPostCard>.
- PostThread gains an optional onCollapse prop (renders the Hide control,
  trims top padding when inline-expanded). Removed the now-unused BackRow
  + ChevronLeft.
- Mobile/native behavior unchanged.

187/187 frontend tests pass; typecheck clean; verified inline expand +
collapse on local web with no console errors.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On mobile web the single-column order now leads with the schedule (Up
Next + Coming Up — the desktop 'main' column), then wraps the center /
boards content (the desktop right rail) below it, instead of showing
the center/board block before the schedule. Desktop two-column layout
unchanged.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…from one line (#307)

Reply + board composers now pin the avatar to the top and the send
button to the bottom, with the text field starting as a single
horizontal line and growing vertically with content (up to a cap).
Fixes the reply input rendering as a too-tall box with the placeholder
floating at the top. Works on mobile web and desktop web.

- ThreadReplyComposer: content-driven height (onContentSizeChange) from
  one line to 120px; row alignItems flex-end with avatar alignSelf
  flex-start; web outline removed.
- BoardComposer: avatar pinned to top (was bottom-aligned).

187/187 tests pass; typecheck clean; verified empty + multiline on
mobile (390px) and desktop (1440px).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
)

Match iOS: on mobile web the profile entry is now the avatar in the
top-right of TabHeader (was native-only), and Profile is removed from
the web bottom nav (Home / Explore / Feed only). Desktop web keeps its
WebHeader avatar.

- TabHeader: show the profile avatar on web too (drops the Platform!=web
  gate); removed now-unused Platform import.
- WebBottomNav: NAV_ITEMS = Home/Explore/Feed; removed the profile item +
  unused Avatar/useUser.
- Updated the WebBottomNav test to assert Profile is not a bottom tab.

187/187 tests pass; component typecheck clean; verified on mobile web
(avatar top-right + bell, bottom nav без Profile).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The zoom +/- group and locate button were two detached floating blobs
at the top-right; on mobile the transparent header (Create + the new
profile avatar) also sits top-right, so they overlapped. Merge them
into one rounded control stack (zoom in / zoom out / locate) positioned
top-LEFT on mobile (clear of the header actions) and bottom-right on
desktop (solid header above, no conflict).

187/187 tests pass; typecheck clean; verified mobile (390px, top-left,
no header overlap) and desktop (1440px, bottom-right).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
KishParikh13 and others added 14 commits June 16, 2026 23:35
…members

A signed-in member with no events saw three identical "Explore events"
buttons stacked — the AnchorCard's primary CTA plus empty-state pills in
"Up next for you" and "Coming up". Render those two sections only when they
actually have events to show; the AnchorCard's "Explore events" already
covers the empty case. On wide desktop, fall back to the centered single
column when the main column would otherwise be blank, so a sparse home
isn't a lopsided empty-left layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tgun)

NativeWind 4's CssInterop silently drops the `style={({ pressed }) => ...}`
function form on Pressable, stripping background/padding/border/radius. Where
the label is light/white this left white-on-transparent — invisible in light
mode. Reported on the event page's "Cancel Registration" button; the same
failure also hit EmptyPanel's accent CTA.

Convert off the function form:
- DestructiveButton → className + active: (matches PrimaryButton.native), exact
  red via arbitrary hex so it's theme-config-independent
- SecondaryButton / GhostButton / IconButton → array style + state-driven press
- EmptyPanel accent CTA → static style + state-driven press

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-check

Invalidate refresh tokens after password reset
…t-comment

[codex] Fix Pages project deploy comment
…ndancy

fix(home): de-dupe empty-state — one Explore CTA, hide empty Up-next/Coming-up
…ght-mode

fix(ui): event Cancel button invisible in light mode + button-style consistency sweep
…#525)

The "Manage attendees" roster (full list + emails/guests + CSV export) showed
on the event detail view, gated by canEdit/canManage. But the detail view
already lists attendees, so the roster was redundant there — and on localhost
the admin gate is force-true, so it surfaced "You do not have access to this
roster" to non-editors.

Move it into the EDIT form (edit-existing only) on both web and native:
- Remove from [id].tsx, [id].web.tsx, and both layouts in EventDetailPanel.web.tsx.
- Add to form.tsx, form.web.tsx, EventFormPanel.web.tsx, gated `isEdit && eventId`.

Only editors reach the edit form, so the roster is naturally editor-only.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
KishParikh13 and others added 2 commits June 17, 2026 09:29
)

appVersionSource is "local", so `autoIncrement: true` re-derived the build
number from app.json's static value (32 → 33) on every build without
persisting it — producing duplicate build 33s that App Store Connect
rejects. Pin an explicit buildNumber and bump it per release instead.
(For hands-off increments, switch cli.appVersionSource to "remote".)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rged early) (#527)

* fix(home): keep desktop two-column; only drop the redundant empty cards

Per feedback: don't collapse the wide-desktop layout to a single column.
Keep the original 2-col composition — the "Your Center" CTA card (with icon)
in the right rail, events in the main column. The empty "Up next"/"Coming up"
slots simply render nothing now, so the left column is sparse rather than
stacked with redundant Explore cards.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(home): populate the events column for members at a quiet center

A logged-in member whose center has no upcoming events saw a blank left
column (center-scoped "Coming up" was empty). Fall back to the broader
upcoming-events list in that case, so logged-in mirrors the logged-out
Explore list instead of going blank.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
KishParikh13 and others added 8 commits June 17, 2026 09:52
…ement (#528)

With appVersionSource: remote + autoIncrement, EAS tracks the iOS build
number server-side and bumps it for every production build — no more manual
app.json edits or the stuck-local-value duplicates. Seed buildNumber to 35
(34 is the last build on App Store Connect) so the first remote build lands
>=35 with no duplicate; after that EAS owns the value.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…er-only) (#529)

The Home "Latest on your board" peek only pulled the user's center board, so
it stayed empty even when there were posts on the Public board or on event
boards the user had joined — contradicting its own "your center and events
you've joined" copy.

Point the peek at the aggregated /feed (public + center + joined-event posts,
reverse-chronological) via a new useAggregatedFeed hook. The /feed query now
also returns each post's sourceKind + sourceLabel (Public / center name /
event title) so the peek labels the source correctly.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per feedback: the Home "Latest on your board" peek now renders the 3 most
recent aggregated-feed posts (public + center + joined events) with the same
FeedPostCard the Feed uses, so it matches the Feed's look. Tapping a post
still opens it on the feed post page (/feed?post=<id>).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(events): reliable isRegistered + live attendee count (authed endpoint)

The RSVP CTA + attendee count were derived from the public/cached /fetchEvent
and the admin-gated roster: a registered user could see "Attend" + "0 / No
attendees yet" because the gated roster 403'd and isRegistered was inferred
from it.

Add GET /events/:id/registration (authed) → { isRegistered, attendeeCount }
computed live from event_attendees (+ non-upgraded guests). useEventDetail now
uses it for the CTA + count instead of inferring from the gated roster. The
attendee LIST stays attendee/creator/admin-gated (names+avatars, no PII); the
"No attendees yet" message keys off the count, so a registered user without
roster access sees the accurate count rather than "0".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(events): Explore event panel People count uses live count, not gated list

The split-view panel's PeopleTab + 'People' section still read attendees.length
(the admin-gated roster, often empty) → 'PEOPLE 0 / No attendees yet' even with
attendees. Use event.attendees (the live count from useEventDetail) instead;
show 'No attendees yet' only when the count is truly 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(events): mark Going on event lists via registered-IDs, keep real count

Event list cards (Explore/Home) derived isRegistered + count from a per-event
gated roster fetch, so 'Going' didn't show until you opened the detail, and the
count could zero out. Add authed GET /events/registered → { eventIds } and mark
list events from that set in useDiscoverData; stop overriding the count with the
gated roster length.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(events): authenticate fetchEventUsers so the attendee names list loads

/getEventUsers is gated (attendee/creator/admin) but fetchEventUsers called it
via apiFetch, which sends no auth token -> 401 -> empty list. So even a
registered attendee saw only the count, never the names. Use authFetch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(events): lock RSVP CTA to 'You're going' after a guest RSVPs (session)

Guests have no account state, so the attend CTA stayed live after a guest RSVP
— they could re-open the sheet and resubmit, and it wasn't obvious it worked.
GuestRsvpSheet now fires onRsvped on success/already-RSVPed; the event detail,
the full-page web view, and the Explore panel lock their attend button to a
disabled 'You're going' for the session (reset when the panel switches events).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ata) (#532)

The native post-detail screen (app/feed/[id].tsx) built its post and thread
from __mocks__ fixtures (centerBoards/eventBoards), so opening a board/feed
post by id — e.g. a deep link or push-notification tap (/feed/:postId) —
rendered fake content instead of the real post.

Rewrite the screen to load the real post from the aggregated feed (the same
real-data source the Feed tab and Home peek read), match it by route id (raw
post id from deep links, or the board-scoped compound key the Feed tab uses),
map it via boardPostToMessage + buildFeedPostFromMessage, and render the shared
PostThread component — which already loads real replies and handles reactions,
replies, pin/edit/delete. Adds clean loading, error (retryable), and not-found
states matching existing patterns (NativeChatHeader + useColors tokens).

No mock imports remain in this screen; the __mocks__ file is left untouched
for other tests/screens.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Post) (#533)

reportBoardPost() existed in utils/api.ts but had no UI caller, so members
could not report posts and the moderation queue could only be filled from the
admin side. Surface a "Report" action in the shared PostThread action menu.

- canReportPost() gate in feedData: verified member, not the post author
  (own posts already expose edit/delete).
- Report row added to ActionMenuSheet with an inline confirm mirroring the
  existing delete-confirm, success notice on completion, graceful error.
- Shared PostThread covers web + native and every detail surface (feed,
  center, event boards), so one change wires them all.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Email verification links are opened from an inbox, typically while
logged out. The logged-out auth guard's public allowlist omitted
/verify-email, so the route was shadowed by a redirect to /landing and
the verification UI never rendered. Add /verify-email to the allowlist.

Caught during local QA of #534.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…domain

In CI, wrangler infers the Pages deployment branch from the checked-out
git ref (v2) and silently overrides the --branch __release flag, so every
production dispatch published to the v2 preview alias instead of the
__release production branch. chinmayajanata.org therefore served a stale
bundle. Pin CF_PAGES_BRANCH=__release to override the inference, and add a
diagnostic step printing the project's production branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants