Add Pairing page with device list table, pairing code generation, and device revocation. Create useDevices hook for reusable device fetching. Wire /pairing route into App.tsx router. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react';
|
|
|
|
interface Device {
|
|
id: string;
|
|
name: string | null;
|
|
device_type: string | null;
|
|
paired_at: string;
|
|
last_seen: string;
|
|
ip_address: string | null;
|
|
}
|
|
|
|
export function useDevices() {
|
|
const [devices, setDevices] = useState<Device[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const token = localStorage.getItem('zeroclaw_token') || '';
|
|
|
|
const fetchDevices = useCallback(async () => {
|
|
try {
|
|
setLoading(true);
|
|
const res = await fetch('/api/devices', {
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
});
|
|
if (res.ok) {
|
|
const data = await res.json();
|
|
setDevices(data.devices || []);
|
|
setError(null);
|
|
} else {
|
|
setError(`HTTP ${res.status}`);
|
|
}
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [token]);
|
|
|
|
useEffect(() => {
|
|
fetchDevices();
|
|
}, [fetchDevices]);
|
|
|
|
return { devices, loading, error, refetch: fetchDevices };
|
|
}
|