MotorSignal-App/website/components/session-manager.tsx

30 lines
1.6 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
type Session = { id: string; device_name: string | null; created_at: string; expires_at: string; current: boolean };
export function SessionManager() {
const [sessions, setSessions] = useState<Session[]>([]);
const [message, setMessage] = useState('');
async function load() {
const response = await fetch('/api/account/sessions', { cache: 'no-store' });
if (response.ok) setSessions(await response.json());
}
useEffect(() => { void load(); }, []);
async function revoke(id: string) {
const response = await fetch(`/api/account/sessions/${id}`, { method: 'DELETE' });
if (response.ok) { setMessage('Session revoked.'); await load(); }
}
async function logoutAll() {
const response = await fetch('/api/account/sessions', { method: 'POST' });
if (response.ok) { setMessage('All sessions revoked.'); await load(); }
}
return <div className="session-manager"><div className="session-heading"><h2>Sessions</h2><button className="text-button" onClick={() => void logoutAll()} type="button">Revoke all</button></div>{sessions.length ? sessions.map((session) => <div className="session-row" key={session.id}><div><strong>{session.device_name ?? 'Unnamed device'} {session.current && '(this device)'}</strong><p>Created {new Date(session.created_at).toLocaleString()}</p></div>{!session.current && <button className="text-button" onClick={() => void revoke(session.id)} type="button">Revoke</button>}</div>) : <p>No active sessions.</p>}{message && <p className="form-message" role="status">{message}</p>}</div>;
}