'use client'; import { useState, useTransition, useEffect } from 'react'; import { useTranslations } from 'next-intl'; import { useRouter } from 'next/navigation'; import { fetchCurrentUser } from '@/lib/auth-actions'; import { useAuthStore } from '@/lib/stores/auth-store'; const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001'; /** * Change password page (D-06 force-change + voluntary change). * Inside (portal) route group -- has sidebar/header. * Shows a notice when user was forced here by mustChangePassword flag. * On success, redirects to dashboard. */ export default function ChangePasswordPage() { const t = useTranslations('auth'); const router = useRouter(); const { user, setUser } = useAuthStore(); const [isPending, startTransition] = useTransition(); const [error, setError] = useState(null); const [passwordMismatch, setPasswordMismatch] = useState(false); const [isForced, setIsForced] = useState(false); // Detect if this is a forced password change useEffect(() => { async function checkForceChange() { const currentUser = await fetchCurrentUser(); if (currentUser?.mustChangePassword) { setIsForced(true); } } checkForceChange(); }, []); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setError(null); setPasswordMismatch(false); const formData = new FormData(e.currentTarget); const currentPassword = formData.get('currentPassword') as string; const newPassword = formData.get('newPassword') as string; const confirmPassword = formData.get('confirmPassword') as string; if (newPassword !== confirmPassword) { setPasswordMismatch(true); return; } startTransition(async () => { try { // Get the session cookie to send with the request const response = await fetch(`${API_URL}/auth/change-password`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ currentPassword, newPassword }), credentials: 'include', }); if (!response.ok) { const data = await response.json().catch(() => null); if (data?.message === 'Current password is incorrect') { setError('wrongCurrentPassword'); } else { setError('networkError'); } return; } // Update auth store to clear mustChangePassword if (user) { setUser({ ...user }); } // Redirect to dashboard router.push('/'); router.refresh(); } catch { setError('networkError'); } }); } return (

{t('changePassword.title')}

{/* Force-change notice (D-06) */} {isForced && (
{t('changePassword.forceChangeNotice')}
)} {/* Error message */} {error && (
{t(`changePassword.${error}`)}
)} {/* Password mismatch */} {passwordMismatch && (
{t('changePassword.passwordMismatch')}
)}
{/* Current password */}
{/* New password */}
{/* Confirm new password */}
); }