mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
fix those failed test case
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
* May 23, 2026 lash0000 001 Initial creation - STAR Phase 1 Project
|
||||
* May 23, 2026 lash0000 002 birthday + occupation required; all calls via useAuth (register, verifyOTP, resendOTP)
|
||||
***********************************************************************************************************************************************************************/
|
||||
import { useState } from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useNavigate, Link, useSearchParams } from 'react-router-dom'
|
||||
import { useForm, Controller } from 'react-hook-form'
|
||||
import { useAuth } from '@/contexts/AuthContext'
|
||||
@@ -154,6 +154,27 @@ export function RegisterForm({ className, ...props }) {
|
||||
// Accumulated data across steps
|
||||
const [personalData, setPersonalData] = useState({})
|
||||
|
||||
// ── Pending-verification resume (email already has an unverified account) ──
|
||||
const [resumeDialogOpen, setResumeDialogOpen] = useState(false)
|
||||
const [isResuming, setIsResuming] = useState(false)
|
||||
const [pendingCreds, setPendingCreds] = useState(null)
|
||||
|
||||
// ── Warn before the tab is closed/reloaded mid-registration ────────────────
|
||||
// Once the user reaches Credentials, submitting can already create a
|
||||
// server-side account + send an OTP — losing the tab here (slow internet,
|
||||
// accidental reload) is what leaves an orphaned unverified account behind.
|
||||
useEffect(() => {
|
||||
if (step === 0) return
|
||||
|
||||
const handleBeforeUnload = (e) => {
|
||||
e.preventDefault()
|
||||
e.returnValue = ''
|
||||
}
|
||||
|
||||
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||
return () => window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||
}, [step])
|
||||
|
||||
// ── Step 1: Personal info ─────────────────────────────────────────────────
|
||||
const {
|
||||
register: regPersonal,
|
||||
@@ -180,45 +201,58 @@ export function RegisterForm({ className, ...props }) {
|
||||
defaultValues: { email: '', password: '', confirm_password: '', group_code: groupCode },
|
||||
})
|
||||
|
||||
const onCredentialsSubmit = async ({ email, password, group_code }) => {
|
||||
const buildPersonalInfo = () => ({
|
||||
name: {
|
||||
given_name: personalData.given_name,
|
||||
middle_name: personalData.middle_name || '',
|
||||
last_name: personalData.last_name,
|
||||
extension_name: personalData.extension_name || '',
|
||||
full_name: [
|
||||
`${personalData.last_name},`,
|
||||
personalData.given_name,
|
||||
personalData.middle_name || '',
|
||||
personalData.extension_name || '',
|
||||
].filter(Boolean).join(' ').trim(),
|
||||
},
|
||||
date_of_birth: personalData.date_of_birth,
|
||||
occupation: personalData.occupation,
|
||||
phone_number: personalData.phone
|
||||
? (() => {
|
||||
const digits = personalData.phone.replace(/\D/g, '')
|
||||
const number = digits.startsWith('63')
|
||||
? digits.slice(2) // strip country code if user typed +63...
|
||||
: digits.replace(/^0/, '') // strip leading 0 if user typed 09...
|
||||
return [{
|
||||
number,
|
||||
country_code: '63',
|
||||
full_number: `63${number}`,
|
||||
phone_type: 'mobile',
|
||||
}]
|
||||
})()
|
||||
: [],
|
||||
addresses: [],
|
||||
})
|
||||
|
||||
const submitRegistration = async ({ email, password, group_code }, { confirmResume = false } = {}) => {
|
||||
const result = await authRegister({
|
||||
email,
|
||||
password,
|
||||
personal_info: {
|
||||
name: {
|
||||
given_name: personalData.given_name,
|
||||
middle_name: personalData.middle_name || '',
|
||||
last_name: personalData.last_name,
|
||||
extension_name: personalData.extension_name || '',
|
||||
full_name: [
|
||||
`${personalData.last_name},`,
|
||||
personalData.given_name,
|
||||
personalData.middle_name || '',
|
||||
personalData.extension_name || '',
|
||||
].filter(Boolean).join(' ').trim(),
|
||||
},
|
||||
date_of_birth: personalData.date_of_birth,
|
||||
occupation: personalData.occupation,
|
||||
phone_number: personalData.phone
|
||||
? (() => {
|
||||
const digits = personalData.phone.replace(/\D/g, '')
|
||||
const number = digits.startsWith('63')
|
||||
? digits.slice(2) // strip country code if user typed +63...
|
||||
: digits.replace(/^0/, '') // strip leading 0 if user typed 09...
|
||||
return [{
|
||||
number,
|
||||
country_code: '63',
|
||||
full_number: `63${number}`,
|
||||
phone_type: 'mobile',
|
||||
}]
|
||||
})()
|
||||
: [],
|
||||
addresses: [],
|
||||
},
|
||||
personal_info: buildPersonalInfo(),
|
||||
...(group_code ? { group_code } : {}),
|
||||
...(confirmResume ? { confirm_resume: true } : {}),
|
||||
})
|
||||
|
||||
if (!result.success) {
|
||||
if (result.errors?.pendingVerification && !confirmResume) {
|
||||
// Same email already has an unverified account sitting server-side —
|
||||
// likely this same user retrying after a dropped connection. Ask
|
||||
// before resending the OTP and reusing that account rather than
|
||||
// dead-ending on a generic "already registered" error.
|
||||
setPendingCreds({ email, password, group_code })
|
||||
setResumeDialogOpen(true)
|
||||
return
|
||||
}
|
||||
|
||||
setErrorMessage(result.message)
|
||||
setErrorDialogOpen(true)
|
||||
return
|
||||
@@ -228,6 +262,19 @@ export function RegisterForm({ className, ...props }) {
|
||||
setStep(2)
|
||||
}
|
||||
|
||||
const onCredentialsSubmit = (data) => submitRegistration(data)
|
||||
|
||||
const handleConfirmResume = async () => {
|
||||
if (!pendingCreds) return
|
||||
setIsResuming(true)
|
||||
try {
|
||||
await submitRegistration(pendingCreds, { confirmResume: true })
|
||||
} finally {
|
||||
setIsResuming(false)
|
||||
setResumeDialogOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
return (
|
||||
<>
|
||||
@@ -576,6 +623,33 @@ export function RegisterForm({ className, ...props }) {
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
|
||||
<AlertDialog open={resumeDialogOpen} onOpenChange={(open) => !isResuming && setResumeDialogOpen(open)}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Pending verification found</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This email already started registration but was never verified — likely from a dropped
|
||||
connection. Resend the verification code and continue with the details you just entered?
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<Button variant="outline" disabled={isResuming} onClick={() => setResumeDialogOpen(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<AlertDialogAction onClick={handleConfirmResume} disabled={isResuming}>
|
||||
{isResuming ? (
|
||||
<span className="flex items-center gap-2">
|
||||
<LoaderCircle className="size-4 animate-spin" />
|
||||
Sending...
|
||||
</span>
|
||||
) : (
|
||||
'Resend code'
|
||||
)}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user