import { useState } from 'react' import { useMutation, useQueryClient } from '@tanstack/react-query' import { CheckCircle2, XCircle, Wifi, WifiOff } from 'lucide-react' import { devicesApi, type SubnetScanResponse } from '@/lib/api' import { toast } from '@/components/ui/toast' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Checkbox } from '@/components/ui/checkbox' interface Props { tenantId: string results: SubnetScanResponse onDone: () => void } interface DeviceCredentials { username: string password: string } export function ScanResultsList({ tenantId, results, onDone }: Props) { const queryClient = useQueryClient() const [selected, setSelected] = useState>(new Set()) const [sharedCreds, setSharedCreds] = useState({ username: 'admin', password: '', }) const [useShared] = useState(true) const mutation = useMutation({ mutationFn: () => devicesApi.bulkAdd(tenantId, { devices: Array.from(selected).map((ip) => { const discovered = results.discovered.find((d) => d.ip_address === ip) return { ip_address: ip, hostname: discovered?.hostname ?? undefined, } }), shared_username: useShared ? sharedCreds.username : undefined, shared_password: useShared ? sharedCreds.password : undefined, }), onSuccess: (data) => { void queryClient.invalidateQueries({ queryKey: ['devices', tenantId] }) void queryClient.invalidateQueries({ queryKey: ['tenants'] }) const added = data.added.length const failed = data.failed.length toast({ title: `${added} device${added !== 1 ? 's' : ''} added${failed > 0 ? `, ${failed} failed` : ''}`, variant: failed > 0 ? 'destructive' : 'default', }) onDone() }, onError: () => { toast({ title: 'Bulk add failed', variant: 'destructive' }) }, }) const toggleSelect = (ip: string) => { setSelected((prev) => { const next = new Set(prev) if (next.has(ip)) next.delete(ip) else next.add(ip) return next }) } const selectAll = () => { setSelected(new Set(results.discovered.map((d) => d.ip_address))) } const deselectAll = () => setSelected(new Set()) const allSelected = results.discovered.length > 0 && selected.size === results.discovered.length return (
{/* Summary */}

Scan complete —{' '} {results.total_discovered} discovered {' '}of {results.total_scanned} addresses scanned

CIDR: {results.cidr}

{results.discovered.length === 0 ? (
No MikroTik devices found in this range
) : ( <> {/* Device checklist */}
{results.discovered.map((device) => ( toggleSelect(device.ip_address)} > ))}
(c ? selectAll() : deselectAll())} /> IP Address Hostname API TLS
e.stopPropagation()}> toggleSelect(device.ip_address)} /> {device.ip_address} {device.hostname ?? '—'} {device.api_port_open ? ( ) : ( )} {device.api_ssl_port_open ? ( ) : ( )}
{/* Credentials */} {selected.size > 0 && (

Credentials for {selected.size} selected device{selected.size !== 1 ? 's' : ''}

setSharedCreds((c) => ({ ...c, username: e.target.value })) } placeholder="admin" autoComplete="off" />
setSharedCreds((c) => ({ ...c, password: e.target.value })) } placeholder="••••••••" autoComplete="new-password" />

Shared credentials used for all selected devices

{mutation.isError && (

Failed to add devices. Please try again.

)}
)} )}
) }