"use client"; import { useState } from "react"; import { SettingsSection, SettingsRow, SettingsInput } from "../ui"; import { useAuth } from "@/lib/auth-context"; import { api } from "@/lib/api"; import { useTwoFactor } from "../../hooks/useTwoFactor"; import { Modal } from "@/components/ui/Modal"; import { InlineStatus, StatusType } from "@/components/ui/InlineStatus"; export function AccountSection() { const { user } = useAuth(); // Password change state const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [changingPassword, setChangingPassword] = useState(false); const [showPasswordForm, setShowPasswordForm] = useState(false); const [passwordStatus, setPasswordStatus] = useState("idle"); const [passwordMessage, setPasswordMessage] = useState(""); // 2FA state const { twoFactorEnabled, settingUpTwoFactor, twoFactorQR, twoFactorSecret, recoveryCodes, showRecoveryCodes, load2FAStatus, setup2FA, enable2FA, disable2FA, cancel2FASetup, closeRecoveryCodes, } = useTwoFactor(); const [twoFactorToken, setTwoFactorToken] = useState(""); const [disablePassword, setDisablePassword] = useState(""); const [disableToken, setDisableToken] = useState(""); const [showDisableFlow, setShowDisableFlow] = useState(false); const [tfaStatus, setTfaStatus] = useState("idle"); const [tfaMessage, setTfaMessage] = useState(""); // Handle password change const handleChangePassword = async () => { if (!currentPassword || !newPassword || !confirmPassword) { setPasswordStatus("error"); setPasswordMessage("All fields required"); return; } if (newPassword.length < 6) { setPasswordStatus("error"); setPasswordMessage("Min 6 characters"); return; } if (newPassword !== confirmPassword) { setPasswordStatus("error"); setPasswordMessage("Passwords don't match"); return; } setChangingPassword(true); setPasswordStatus("loading"); try { await api.post("/auth/change-password", { currentPassword, newPassword, }); setPasswordStatus("success"); setPasswordMessage("Changed"); setCurrentPassword(""); setNewPassword(""); setConfirmPassword(""); setTimeout(() => setShowPasswordForm(false), 1500); } catch (error: any) { setPasswordStatus("error"); setPasswordMessage(error.response?.data?.message || "Failed"); } finally { setChangingPassword(false); } }; // Handle 2FA verification const handleVerify2FA = async () => { setTfaStatus("loading"); try { await enable2FA(twoFactorToken); setTfaStatus("success"); setTfaMessage("Enabled"); setTwoFactorToken(""); } catch (error: any) { setTfaStatus("error"); setTfaMessage(error.message || "Invalid code"); } }; // Handle 2FA disable const handleDisable2FA = async () => { setTfaStatus("loading"); try { await disable2FA(disablePassword, disableToken); setTfaStatus("success"); setTfaMessage("Disabled"); setDisablePassword(""); setDisableToken(""); setShowDisableFlow(false); } catch (error: any) { setTfaStatus("error"); setTfaMessage(error.message || "Failed"); } }; return ( <> {/* Username Display */} {user?.role} {/* Change Password */} {!showPasswordForm ? ( ) : ( )} {showPasswordForm && (
setPasswordStatus("idle")} />
)} {/* Two-Factor Authentication */} {!settingUpTwoFactor && !showDisableFlow && ( twoFactorEnabled ? ( ) : ( ) )} {/* 2FA Setup Flow */} {settingUpTwoFactor && (

Scan the QR code with your authenticator app, then enter the code below.

{twoFactorQR && (
2FA QR Code
)} {twoFactorSecret && (

Manual entry code:

{twoFactorSecret}
)} setTwoFactorToken(v.replace(/\D/g, "").slice(0, 6))} placeholder="Enter 6-digit code" />
setTfaStatus("idle")} />
)} {/* 2FA Disable Flow */} {showDisableFlow && (

Enter your password and current code to disable 2FA.

setDisableToken(v.replace(/\D/g, "").slice(0, 6))} placeholder="6-digit code" />
setTfaStatus("idle")} />
)}
{/* Recovery Codes Modal */}

Save these codes! You'll need them if you lose your authenticator.

{recoveryCodes.map((code, i) => ( {code} ))}
); }