/* eslint-disable unicorn/filename-case */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { ClipboardIcon, EllipsisHorizontalIcon } from '@heroicons/react/24/outline' import { type ActionFunctionArgs, json, type LoaderFunctionArgs } from '@remix-run/node' import { Link, useFetcher, useLoaderData } from '@remix-run/react' import clsx from 'clsx' import { useState } from 'react' import { toast } from 'react-hot-toast/headless' import Dropdown from '~/components/Dropdown' import useModal from '~/components/Modal' import StatusCircle from '~/components/StatusCircle' import { type Machine } from '~/types' import { del, pull } from '~/utils/headscale' import { getSession } from '~/utils/sessions' import { useLiveData } from '~/utils/useLiveData' export async function loader({ request }: LoaderFunctionArgs) { const session = await getSession(request.headers.get('Cookie')) const data = await pull<{ nodes: Machine[] }>('v1/node', session.get('hsApiKey')!) return data.nodes } export async function action({ request }: ActionFunctionArgs) { const data = await request.json() as { id?: string } if (!data.id) { return json({ message: 'No ID provided' }, { status: 400 }) } const session = await getSession(request.headers.get('Cookie')) if (!session.has('hsApiKey')) { return json({ message: 'Unauthorized' }, { status: 401 }) } await del(`v1/node/${data.id}`, session.get('hsApiKey')!) return json({ message: 'Machine removed' }) } export default function Page() { useLiveData({ interval: 3000 }) const data = useLoaderData() const fetcher = useFetcher() const { Modal, open } = useModal() return ( <> {Modal} {data.map(machine => { const tags = [...machine.forcedTags, ...machine.validTags] return ( ) })}
Name IP Addresses Last Seen

{machine.givenName}

{machine.name}
{tags.map(tag => ( {tag} ))}
{machine.ipAddresses.map((ip, index) => ( ))}

{machine.online ? 'Connected' : new Date( machine.lastSeen ).toLocaleString()}

)} >
) }