import { useState } from 'react' import { useForm } from 'react-hook-form' import { z } from 'zod' import { zodResolver } from '@hookform/resolvers/zod' import { Fingerprint, KeyRound, Loader2, Plus, Trash2 } from 'lucide-react' import { authClient } from '../lib/auth-client' import { Button, Input, Label } from '../components/ui' const changePasswordSchema = z .object({ currentPassword: z.string().min(1, 'Ingresá tu contraseña actual'), newPassword: z.string().min(8, 'La nueva contraseña debe tener al menos 8 caracteres'), }) .refine((v) => v.currentPassword !== v.newPassword, { message: 'La nueva contraseña debe ser distinta', path: ['newPassword'], }) type ChangePasswordValues = z.infer function PasskeyList({ onRefresh }: { onRefresh: () => void }) { const { data, isPending } = authClient.useListPasskeys() const [deletingId, setDeletingId] = useState(null) const handleDelete = async (id: string) => { setDeletingId(id) const { error } = await authClient.$fetch('/passkey/delete-passkey', { method: 'POST', body: { id }, }) setDeletingId(null) if (!error) onRefresh() } if (isPending) { return } const passkeys = data ?? [] if (passkeys.length === 0) { return

Todavía no registraste ninguna passkey.

} return (
    {passkeys.map((passkey) => (
  • {passkey.name ?? 'Passkey'}

    {passkey.deviceType === 'singleDevice' ? 'Dispositivo' : 'Llave de seguridad'} ·{' '} {new Date(passkey.createdAt).toLocaleDateString('es-AR')}

  • ))}
) } export function SecurityPage() { const [passkeyKeys, setPasskeyKeys] = useState(0) const [feedback, setFeedback] = useState(null) const { register, handleSubmit, reset, setError, formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(changePasswordSchema) }) const refreshPasskeys = () => { setPasskeyKeys((k) => k + 1) } const handleAddPasskey = async () => { setFeedback(null) const { error } = await authClient.passkey.addPasskey() if (error) setFeedback(`No se pudo agregar: ${error.message}`) else { setFeedback('Passkey registrada correctamente.') refreshPasskeys() } } const onChangePassword = handleSubmit(async ({ currentPassword, newPassword }) => { setFeedback(null) const { error } = await authClient.changePassword({ currentPassword, newPassword, revokeOtherSessions: true, }) if (error) { setError('currentPassword', { message: error.message ?? 'No se pudo cambiar la contraseña' }) return } reset({ currentPassword: '', newPassword: '' }) setFeedback('Contraseña actualizada.') }) return (

Seguridad

Gestioná tu contraseña y tus llaves de acceso (passkeys).

{feedback ? (

{feedback}

) : null}

Cambiar contraseña

{errors.currentPassword ? (

{errors.currentPassword.message}

) : null}
{errors.newPassword ? (

{errors.newPassword.message}

) : null}

Passkeys

) }