Skip to content

Commit ed8a7a0

Browse files
committed
fix: make email and display name optional during checkout
1 parent f86b4ea commit ed8a7a0

2 files changed

Lines changed: 179 additions & 4 deletions

File tree

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
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+
```

web/app/pages/billing/index.vue

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,12 @@ const checkoutURL = computed(() => {
148148
const user = authStore.authUser
149149
if (user) {
150150
url.searchParams.append('checkout[custom][user_id]', user.id)
151-
url.searchParams.append('checkout[email]', user.email || '')
152-
url.searchParams.append('checkout[name]', user.displayName || '')
151+
if (user.email) {
152+
url.searchParams.append('checkout[email]', user.email)
153+
}
154+
if (user.displayName) {
155+
url.searchParams.append('checkout[name]', user.displayName)
156+
}
153157
}
154158
return url.toString()
155159
})
@@ -159,8 +163,12 @@ const enterpriseCheckoutURL = computed(() => {
159163
const user = authStore.authUser
160164
if (user) {
161165
url.searchParams.append('checkout[custom][user_id]', user.id)
162-
url.searchParams.append('checkout[email]', user.email || '')
163-
url.searchParams.append('checkout[name]', user.displayName || '')
166+
if (user.email) {
167+
url.searchParams.append('checkout[email]', user.email)
168+
}
169+
if (user.displayName) {
170+
url.searchParams.append('checkout[name]', user.displayName)
171+
}
164172
}
165173
return url.toString()
166174
})

0 commit comments

Comments
 (0)