Collect gender during onboarding and from existing users - #641
Merged
Conversation
Add a SetupGender step to profile setup between academic information and resume, writing the selection to PrivateUserInfo.gender. "Prefer not to say" is the opt-out, so the step cannot be skipped and every user who sees it writes a value. Existing accounts never pass through ProfileSetup again, so GenderPromptModal is mounted in MainStack to collect the value in-app. It renders only when gender is undefined and cannot be dismissed, and it writes to Firestore before updating local state so a failed write leaves the prompt open. Also extract the profile-setup progress dashes into a ProgressDashes component so adding the sixth step did not mean editing every screen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9reuKppqcRRaeTGPyxPbV
Ohmarkg
reviewed
Sep 1, 2026
Ohmarkg
reviewed
Sep 1, 2026
Brings up the Firebase Auth and Firestore emulators in a container so the app can be developed and tested without touching the production project. - firebase-emulator/Dockerfile pre-downloads the emulator JARs at image build time so `up` does not refetch them per container. - firebase-emulator/start.sh passes --import only when saved state exists, because Firebase treats a missing import directory as a fatal error on a clean checkout. It lives in its own file rather than inline in the compose command because a YAML folded scalar silently splits the flags onto separate lines. - docker-compose.yml sets stop_signal: SIGINT so --export-on-exit actually flushes; Compose sends SIGTERM by default, which loses the data. - firebase-emulator/seed.js writes two idempotent accounts, one with a gender value and one without, so the existing-user gender prompt can be exercised locally. It refuses to run unless FIRESTORE_EMULATOR_HOST is set. - firebase.json exposes the UI, hub, and logging ports on 0.0.0.0 so they are reachable from the host. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J7Xu8Pxwqs2czY79M239vU
Both gender pickers left their options tappable during the save. Because the handler closes over the value that was selected when it was pressed, changing the selection mid-write meant the highlighted option could end up different from what was actually stored: the popup then closes and the onboarding screen advances, so there is no chance to correct it. Marking the options disabled while loading matches the Save/Continue buttons, which were already guarded, and the opacity-50 treatment follows the existing idiom in SettingsComponents. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J7Xu8Pxwqs2czY79M239vU
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds gender collection to the app, stored on
PrivateUserInfo.gender(private — not shown on a user's profile).SetupGendersits between academic information and resume inProfileSetupStack, making profile setup six steps. Options come from the newGENDER_OPTIONSinsrc/types/user.ts: Male / Female / Other / Prefer not to say. Since "Prefer not to say" is the opt-out, the step has no skip button and every user who reaches it writes a value.ProfileSetupagain, soGenderPromptModalis mounted inMainStackand shown whengender === undefined. It has no close button and an inertsetVisible, so neither a backdrop tap nor the Android back button dismisses it. It writes to Firestore first and only then updatesAsyncStorage+UserContext, so a failed write leaves the prompt open rather than silently claiming success. Once new-user onboarding has been live long enough, the component and its mount can be deleted.<View>s repeated per screen. Extracted into aProgressDashescomponent driven byTOTAL_SETUP_STEPS, so adding the sixth step didn't mean editing all five screens.shpe-app-web/app/types/user.tssync comment fromsrc/types/user.ts— that project was removed in 6e8c922.Test plan
npx tsc --noEmitreports no new errors in the touched files (the repo has pre-existing errors elsewhere).🤖 Generated with Claude Code
https://claude.ai/code/session_01T9reuKppqcRRaeTGPyxPbV