'use client'; import { useEffect, useMemo, useState } from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; import { useTranslations } from 'next-intl'; import { Link, useRouter } from '@/i18n/navigation'; import { useSearchParams } from 'next/navigation'; import { Lock } from 'lucide-react'; import { useAuth } from '@/lib/hooks/useAuth'; import { authApi } from '@/lib/api/auth'; import { Button } from '@/components/ui/shared/Button'; import { Input } from '@/components/ui/shared/Input'; import { Toast } from '@/components/ui/shared/Toast'; type PasswordForm = { currentPassword: string; newPassword: string; confirmPassword: string; }; export default function AccountSettingsPage() { const t = useTranslations('settings'); const tAuth = useTranslations('auth'); const tCommon = useTranslations('common'); const tValidation = useTranslations('validation'); const { user, isAuthReady } = useAuth(); const router = useRouter(); const searchParams = useSearchParams(); const isResetFlow = searchParams.get('reset') === '1'; const [error, setError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); const passwordSchema = useMemo( () => z .object({ currentPassword: z.string(), newPassword: z .string() .min(8, tValidation('passwordMinLength')) .regex(/[A-Z]/, tValidation('passwordUppercase')) .regex(/[0-9]/, tValidation('passwordNumber')), confirmPassword: z.string(), }) .refine((data) => data.newPassword === data.confirmPassword, { message: tValidation('passwordsDoNotMatch'), path: ['confirmPassword'], }) .superRefine((data, ctx) => { if (!isResetFlow && !data.currentPassword.trim()) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: tValidation('passwordRequired'), path: ['currentPassword'], }); } }), [isResetFlow, tValidation], ); const { register, handleSubmit, reset, formState: { errors }, } = useForm({ resolver: zodResolver(passwordSchema), defaultValues: { currentPassword: '', newPassword: '', confirmPassword: '', }, }); useEffect(() => { if (isAuthReady && !user) { router.replace('/login'); } }, [isAuthReady, user, router]); const onSubmit = async (data: PasswordForm) => { try { setError(null); setSuccessMessage(null); setIsSubmitting(true); await authApi.changePassword({ ...(isResetFlow ? {} : { currentPassword: data.currentPassword }), newPassword: data.newPassword, }); reset(); setSuccessMessage(t('passwordChanged')); router.replace('/login'); } catch (err: unknown) { const message = err instanceof Error ? err.message : t('passwordChangeFailed'); setError(message || t('passwordChangeFailed')); } finally { setIsSubmitting(false); } }; const passwordToggleLabels = { show: tAuth('showPassword'), hide: tAuth('hidePassword'), }; if (!isAuthReady || !user) { return (

{tCommon('loadingEllipsis')}

); } return (
{tCommon('backToApp')}

{t('accountTitle')}

{isResetFlow ? t('resetPasswordSubtitle') : t('accountSubtitle')}

{isResetFlow ? t('resetPasswordTitle') : t('changePasswordTitle')}

{user.email} {user.mobile ? ` ยท ${user.mobile}` : ''}

{!isResetFlow && ( } passwordToggleLabels={passwordToggleLabels} /> )} } passwordToggleLabels={passwordToggleLabels} /> } passwordToggleLabels={passwordToggleLabels} /> {error && (

{error}

)}
{successMessage && ( {successMessage} )}
); }