add: revised phone nubmer input UI

This commit is contained in:
rgrgogu
2026-07-16 03:15:03 +08:00
parent ec8ea14ed2
commit dc992c7f77
6 changed files with 309 additions and 14 deletions
+25 -14
View File
@@ -22,11 +22,14 @@ import { useAuth } from '@/contexts/AuthContext'
import { z } from 'zod'
import { zodResolver } from '@hookform/resolvers/zod'
import { format, parseISO, isValid as isValidDate } from 'date-fns'
import { isValidPhoneNumber, parsePhoneNumber } from 'react-phone-number-input'
import { cn } from '@/lib/utils'
import { useDetectedCountry } from '@/hooks/useDetectedCountry'
import { OtpVerifyForm } from './OtpVerifyForm'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { PhoneInput } from '@/components/ui/phone-input'
import { Badge } from '@/components/ui/badge'
import { Calendar } from '@/components/ui/calendar'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
@@ -61,7 +64,10 @@ const personalSchema = z.object({
return yearsAgo >= 3 && yearsAgo <= 120
}, { message: 'Must be at least 3 years old' }),
occupation: z.string().min(1, 'Occupation is required').max(100),
phone: z.string().min(1, 'Phone number is required').regex(/^\+?[0-9\s\-()]{7,20}$/, 'Invalid phone number'),
phone: z
.string()
.min(1, 'Phone number is required')
.refine((v) => isValidPhoneNumber(v), { message: 'Invalid phone number' }),
})
const credentialsSchema = z
@@ -151,6 +157,8 @@ export function RegisterForm({ className, ...props }) {
const [errorMessage, setErrorMessage] = useState('')
const [birthdayOpen, setBirthdayOpen] = useState(false)
const detectedCountry = useDetectedCountry()
// Accumulated data across steps
const [personalData, setPersonalData] = useState({})
@@ -223,14 +231,11 @@ export function RegisterForm({ className, ...props }) {
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...
const parsed = parsePhoneNumber(personalData.phone)
return [{
number,
country_code: '63',
full_number: `63${number}`,
number: parsed.nationalNumber,
country_code: parsed.countryCallingCode,
full_number: `${parsed.countryCallingCode}${parsed.nationalNumber}`,
phone_type: 'mobile',
}]
})()
@@ -449,12 +454,18 @@ export function RegisterForm({ className, ...props }) {
<label htmlFor="phone" className="text-sm font-medium">
Phone number <span className="text-destructive">*</span>
</label>
<Input
id="phone"
type="tel"
placeholder="+63 912 345 6789"
className="text-sm"
{...regPersonal('phone')}
<Controller
name="phone"
control={controlPersonal}
render={({ field }) => (
<PhoneInput
{...field}
id="phone"
international
defaultCountry={detectedCountry}
className="text-sm"
/>
)}
/>
{errPersonal.phone && (
<p className="text-xs text-destructive">{errPersonal.phone.message}</p>