changed native date to shadcn

This commit is contained in:
rgrgogu
2026-07-15 23:12:51 +08:00
parent 510370b4c3
commit 9ebe706ef9
+48 -7
View File
@@ -17,16 +17,19 @@
***********************************************************************************************************************************************************************/ ***********************************************************************************************************************************************************************/
import { useState } from 'react' import { useState } from 'react'
import { useNavigate, Link, useSearchParams } from 'react-router-dom' import { useNavigate, Link, useSearchParams } from 'react-router-dom'
import { useForm } from 'react-hook-form' import { useForm, Controller } from 'react-hook-form'
import { useAuth } from '@/contexts/AuthContext' import { useAuth } from '@/contexts/AuthContext'
import { z } from 'zod' import { z } from 'zod'
import { zodResolver } from '@hookform/resolvers/zod' import { zodResolver } from '@hookform/resolvers/zod'
import { format, parseISO, isValid as isValidDate } from 'date-fns'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { OtpVerifyForm } from './OtpVerifyForm' import { OtpVerifyForm } from './OtpVerifyForm'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Calendar } from '@/components/ui/calendar'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -36,7 +39,11 @@ import {
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
} from '@/components/ui/alert-dialog' } from '@/components/ui/alert-dialog'
import { Eye, EyeOff, LoaderCircle, Users, Check } from 'lucide-react' import { Eye, EyeOff, LoaderCircle, Users, Check, CalendarIcon } from 'lucide-react'
// Birthday must put the user between 13 and 120 years old (mirrors personalSchema below)
const MIN_BIRTHDATE = new Date(new Date().getFullYear() - 120, 0, 1)
const MAX_BIRTHDATE = new Date(new Date().getFullYear() - 13, new Date().getMonth(), new Date().getDate())
// ─── Step schemas ───────────────────────────────────────────────────────────── // ─── Step schemas ─────────────────────────────────────────────────────────────
const personalSchema = z.object({ const personalSchema = z.object({
@@ -141,6 +148,7 @@ export function RegisterForm({ className, ...props }) {
const [showConfirm, setShowConfirm] = useState(false) const [showConfirm, setShowConfirm] = useState(false)
const [errorDialogOpen, setErrorDialogOpen] = useState(false) const [errorDialogOpen, setErrorDialogOpen] = useState(false)
const [errorMessage, setErrorMessage] = useState('') const [errorMessage, setErrorMessage] = useState('')
const [birthdayOpen, setBirthdayOpen] = useState(false)
// Accumulated data across steps // Accumulated data across steps
const [personalData, setPersonalData] = useState({}) const [personalData, setPersonalData] = useState({})
@@ -149,6 +157,7 @@ export function RegisterForm({ className, ...props }) {
const { const {
register: regPersonal, register: regPersonal,
handleSubmit: submitPersonal, handleSubmit: submitPersonal,
control: controlPersonal,
formState: { errors: errPersonal }, formState: { errors: errPersonal },
} = useForm({ } = useForm({
resolver: zodResolver(personalSchema), resolver: zodResolver(personalSchema),
@@ -304,12 +313,44 @@ export function RegisterForm({ className, ...props }) {
<label htmlFor="date_of_birth" className="text-sm font-medium"> <label htmlFor="date_of_birth" className="text-sm font-medium">
Birthday <span className="text-destructive">*</span> Birthday <span className="text-destructive">*</span>
</label> </label>
<Input <Controller
name="date_of_birth"
control={controlPersonal}
render={({ field }) => {
const selectedDate = field.value ? parseISO(field.value) : undefined
const validSelected = selectedDate && isValidDate(selectedDate) ? selectedDate : undefined
return (
<Popover open={birthdayOpen} onOpenChange={setBirthdayOpen}>
<PopoverTrigger asChild>
<Button
type="button"
id="date_of_birth" id="date_of_birth"
type="date" variant="outline"
max={new Date().toISOString().split('T')[0]} className="w-full justify-between font-normal text-sm"
className="text-sm" >
{...regPersonal('date_of_birth')} {validSelected ? format(validSelected, 'MMM d, yyyy') : 'Select date'}
<CalendarIcon className="h-4 w-4 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={validSelected}
captionLayout="dropdown"
defaultMonth={validSelected ?? MAX_BIRTHDATE}
startMonth={MIN_BIRTHDATE}
endMonth={MAX_BIRTHDATE}
disabled={{ before: MIN_BIRTHDATE, after: MAX_BIRTHDATE }}
onSelect={(date) => {
field.onChange(date ? format(date, 'yyyy-MM-dd') : '')
setBirthdayOpen(false)
}}
/>
</PopoverContent>
</Popover>
)
}}
/> />
{errPersonal.date_of_birth && ( {errPersonal.date_of_birth && (
<p className="text-xs text-destructive">{errPersonal.date_of_birth.message}</p> <p className="text-xs text-destructive">{errPersonal.date_of_birth.message}</p>