|
| 1 | +# Signup Name Implementation Plan |
| 2 | + |
| 3 | +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| 4 | +
|
| 5 | +**Goal:** Require a name during Firebase email/password signup, persist it to the Firebase profile, and clear stale form errors when switching authentication modes. |
| 6 | + |
| 7 | +**Architecture:** Keep the change inside the existing `FirebaseAuth.vue` component. The component will conditionally render and validate the name, call Firebase `updateProfile` immediately after account creation, and use a dedicated mode-toggle handler to clear errors. |
| 8 | + |
| 9 | +**Tech Stack:** Nuxt 4, Vue 3 Composition API, Vuetify 4, TypeScript, Firebase Authentication |
| 10 | + |
| 11 | +## Global Constraints |
| 12 | + |
| 13 | +- The visible field label must be `Name`. |
| 14 | +- The name is required only for email/password signup. |
| 15 | +- Persist the trimmed name as Firebase `displayName`. |
| 16 | +- Do not add a new test framework; this web project currently has no configured tests. |
| 17 | + |
| 18 | +--- |
| 19 | + |
| 20 | +### Task 1: Add signup name collection and profile persistence |
| 21 | + |
| 22 | +**Files:** |
| 23 | +- Modify: `web/app/components/FirebaseAuth.vue` |
| 24 | + |
| 25 | +**Interfaces:** |
| 26 | +- Consumes: Firebase `createUserWithEmailAndPassword(auth, email, password)` and `updateProfile(user, { displayName })` |
| 27 | +- Produces: `toggleAuthMode(): void`, required signup `name` state, and Firebase users with a populated `displayName` |
| 28 | + |
| 29 | +- [ ] **Step 1: Confirm the current web test command** |
| 30 | + |
| 31 | +Run: |
| 32 | + |
| 33 | +```bash |
| 34 | +cd web |
| 35 | +pnpm test |
| 36 | +``` |
| 37 | + |
| 38 | +Expected: PASS with `No tests configured yet`. Do not introduce a test framework for this focused change. |
| 39 | + |
| 40 | +- [ ] **Step 2: Add Firebase profile support and name state** |
| 41 | + |
| 42 | +In `web/app/components/FirebaseAuth.vue`, add `updateProfile` to the existing |
| 43 | +`firebase/auth` import: |
| 44 | + |
| 45 | +```ts |
| 46 | +import { |
| 47 | + getAuth, |
| 48 | + signInWithPopup, |
| 49 | + GoogleAuthProvider, |
| 50 | + GithubAuthProvider, |
| 51 | + signInWithEmailAndPassword, |
| 52 | + createUserWithEmailAndPassword, |
| 53 | + sendPasswordResetEmail, |
| 54 | + updateProfile, |
| 55 | +} from 'firebase/auth' |
| 56 | +``` |
| 57 | + |
| 58 | +Add the name state beside the existing email and password state: |
| 59 | + |
| 60 | +```ts |
| 61 | +const name = ref('') |
| 62 | +const email = ref('') |
| 63 | +const password = ref('') |
| 64 | +``` |
| 65 | + |
| 66 | +- [ ] **Step 3: Require the name during signup validation** |
| 67 | + |
| 68 | +At the start of `validateLoginForm`, after `let valid = true`, add: |
| 69 | + |
| 70 | +```ts |
| 71 | +if (isSignUp.value && !name.value.trim()) { |
| 72 | + errorMessages.value.add('name', 'Please provide your name') |
| 73 | + valid = false |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +This preserves sign-in validation while requiring a non-whitespace name only |
| 78 | +in signup mode. |
| 79 | + |
| 80 | +- [ ] **Step 4: Persist the name after Firebase account creation** |
| 81 | + |
| 82 | +Replace the signup branch in `submitEmail` with: |
| 83 | + |
| 84 | +```ts |
| 85 | +if (isSignUp.value) { |
| 86 | + result = await createUserWithEmailAndPassword( |
| 87 | + auth, |
| 88 | + email.value.trim(), |
| 89 | + password.value, |
| 90 | + ) |
| 91 | + await updateProfile(result.user, { |
| 92 | + displayName: name.value.trim(), |
| 93 | + }) |
| 94 | +} else { |
| 95 | + result = await signInWithEmailAndPassword( |
| 96 | + auth, |
| 97 | + email.value.trim(), |
| 98 | + password.value, |
| 99 | + ) |
| 100 | +} |
| 101 | +``` |
| 102 | + |
| 103 | +Keep the existing `onSuccess(result.user, 'email')` call after the branch so |
| 104 | +the auth store receives the updated Firebase user before redirecting. |
| 105 | + |
| 106 | +- [ ] **Step 5: Clear errors when switching sign-in and signup modes** |
| 107 | + |
| 108 | +Add this function beside the existing form navigation helpers: |
| 109 | + |
| 110 | +```ts |
| 111 | +function toggleAuthMode() { |
| 112 | + clearErrors() |
| 113 | + isSignUp.value = !isSignUp.value |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +Change the mode-toggle button handler from: |
| 118 | + |
| 119 | +```vue |
| 120 | +@click="isSignUp = !isSignUp" |
| 121 | +``` |
| 122 | + |
| 123 | +to: |
| 124 | + |
| 125 | +```vue |
| 126 | +@click="toggleAuthMode" |
| 127 | +``` |
| 128 | + |
| 129 | +- [ ] **Step 6: Render the signup-only Name field** |
| 130 | + |
| 131 | +Before the email field in the sign-in/sign-up form, add: |
| 132 | + |
| 133 | +```vue |
| 134 | +<v-text-field |
| 135 | + v-if="isSignUp" |
| 136 | + v-model="name" |
| 137 | + label="Name" |
| 138 | + color="primary" |
| 139 | + type="text" |
| 140 | + variant="outlined" |
| 141 | + density="comfortable" |
| 142 | + class="mb-2" |
| 143 | + :error="errorMessages.has('name')" |
| 144 | + :error-messages="errorMessages.get('name')" |
| 145 | +/> |
| 146 | +``` |
| 147 | + |
| 148 | +- [ ] **Step 7: Run focused web validation** |
| 149 | + |
| 150 | +Run: |
| 151 | + |
| 152 | +```bash |
| 153 | +cd web |
| 154 | +pnpm exec eslint app/components/FirebaseAuth.vue |
| 155 | +pnpm exec prettier --check app/components/FirebaseAuth.vue |
| 156 | +pnpm exec stylelint app/components/FirebaseAuth.vue |
| 157 | +``` |
| 158 | + |
| 159 | +Expected: all three commands exit successfully with no lint, formatting, or |
| 160 | +style errors. |
| 161 | + |
| 162 | +- [ ] **Step 8: Commit the implementation** |
| 163 | + |
| 164 | +```bash |
| 165 | +git add web/app/components/FirebaseAuth.vue |
| 166 | +git commit -m "feat(web): collect name during signup" |
| 167 | +``` |
0 commit comments