'use client' import { useEffect, useState, useCallback } from 'react' import { useAuth } from '@/lib/auth/context' import { getUserDevices, removeDevice, type TrustedDevice } from '@/lib/api/devices' import { Spinner, toast } from '@ciphera-net/ui' import { formatRelativeTime, formatDateTimeFull } from '@/lib/utils/formatDate' function getDeviceIcon(hint: string): string { const h = hint.toLowerCase() if (h.includes('iphone') || h.includes('android') || h.includes('ios')) { return 'M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3' } return 'M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25A2.25 2.25 0 015.25 3h13.5A2.25 2.25 0 0121 5.25z' } export default function TrustedDevicesCard() { const { user } = useAuth() const [devices, setDevices] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState('') const [removingId, setRemovingId] = useState(null) const fetchDevices = useCallback(async () => { try { const data = await getUserDevices() setDevices(data.devices ?? []) } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load devices') } }, []) useEffect(() => { if (!user) return setLoading(true) fetchDevices().finally(() => setLoading(false)) }, [user, fetchDevices]) const handleRemove = async (device: TrustedDevice) => { if (device.is_current) { toast.error('You cannot remove the device you are currently using.') return } setRemovingId(device.id) try { await removeDevice(device.id) setDevices(prev => prev.filter(d => d.id !== device.id)) toast.success('Device removed. A new sign-in from it will trigger an alert.') } catch (err) { toast.error(err instanceof Error ? err.message : 'Failed to remove device') } finally { setRemovingId(null) } } return (

Trusted Devices

Devices that have signed in to your account. Removing a device means the next sign-in from it will trigger a new device alert.

{loading ? (
) : error ? (

{error}

) : devices.length === 0 ? (

No trusted devices yet. They appear after you sign in.

) : (
{devices.map((device) => (
{device.display_hint || 'Unknown device'} {device.is_current && ( This device )}
First seen {formatRelativeTime(device.first_seen_at)} · Last seen {formatRelativeTime(device.last_seen_at)}
{!device.is_current && ( )}
))}
)}
) }