feat: add email verification check for cloud onboarding (#5636)

## Summary
- Added email verification flow for new users during onboarding
- Implemented invite code claiming with proper validation 
- Updated API endpoints from `/invite/` to `/invite_code/` for
consistency

## Changes

### Email Verification
- Added `CloudVerifyEmailView` component with email verification UI
- Added email verification check after login in `CloudLoginView`
- Added `isEmailVerified` property to Firebase auth store
- Users must verify email before claiming invite codes

### Invite Code Flow
- Enhanced `CloudClaimInviteView` with full claim invite functionality
- Updated `InviteCheckView` to route users based on email verification
status
- Modified API to return both `claimed` and `expired` status for invite
codes
- Added proper error handling and Sentry logging for invite operations

### API Updates
- Changed endpoint paths from `/invite/` to `/invite_code/` 
- Updated `getInviteCodeStatus()` to return `{ claimed: boolean;
expired: boolean }`
- Updated `claimInvite()` to return `{ success: boolean; message: string
}`

### UI/UX Improvements
- Added Korean translations for all new strings
- Improved button styling and layout in survey and waitlist views
- Added proper loading states and error handling

## Test Plan
- [ ] Test new user signup flow with email verification
- [ ] Test invite code validation (expired/claimed/valid codes)
- [ ] Test email verification redirect flow
- [ ] Test invite claiming after email verification
- [ ] Verify Korean translations display correctly

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Jin Yi
2025-09-21 12:29:56 +09:00
committed by GitHub
parent d3a5d9e995
commit 8ca541e850
15 changed files with 423 additions and 130 deletions

View File

@@ -9,6 +9,7 @@ import {
browserLocalPersistence,
createUserWithEmailAndPassword,
onAuthStateChanged,
sendEmailVerification,
sendPasswordResetEmail,
setPersistence,
signInWithEmailAndPassword,
@@ -75,6 +76,9 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
const isAuthenticated = computed(() => !!currentUser.value)
const userEmail = computed(() => currentUser.value?.email)
const userId = computed(() => currentUser.value?.uid)
const isEmailVerified = computed(
() => currentUser.value?.emailVerified ?? false
)
// Get auth from VueFire and listen for auth state changes
// From useFirebaseAuth docs:
@@ -289,6 +293,14 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
await updatePassword(currentUser.value, newPassword)
}
/** Send email verification to current user */
const verifyEmail = async (): Promise<void> => {
if (!currentUser.value) {
throw new FirebaseAuthStoreError(t('toastMessages.userNotAuthenticated'))
}
await sendEmailVerification(currentUser.value)
}
const addCredits = async (
requestBodyContent: CreditPurchasePayload
): Promise<CreditPurchaseResponse> => {
@@ -364,6 +376,7 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
// State
loading,
currentUser,
isEmailVerified,
isInitialized,
balance,
lastBalanceUpdateTime,
@@ -387,6 +400,7 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
accessBillingPortal,
sendPasswordReset,
updatePassword: _updatePassword,
getAuthHeader
getAuthHeader,
verifyEmail
}
})