55 lines
2.0 KiB
TypeScript
55 lines
2.0 KiB
TypeScript
'use client'
|
|
import { DndContext, closestCenter, type DragEndEvent } from '@dnd-kit/core'
|
|
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'
|
|
import SiteRow from './SiteRow'
|
|
import { useSites, useReorderSites } from '@/hooks/useSites'
|
|
|
|
export default function SitesTable() {
|
|
const { data: sites } = useSites()
|
|
const reorder = useReorderSites()
|
|
|
|
const handleDragEnd = ({ active, over }: DragEndEvent) => {
|
|
if (!over || active.id === over.id || !sites) return
|
|
const ids = sites.map((s) => s.id)
|
|
const from = ids.indexOf(Number(active.id))
|
|
const to = ids.indexOf(Number(over.id))
|
|
const newOrder = [...ids]
|
|
newOrder.splice(to, 0, newOrder.splice(from, 1)[0])
|
|
reorder.mutate(newOrder)
|
|
}
|
|
|
|
return (
|
|
<div className="g-card overflow-hidden">
|
|
<DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
|
<SortableContext items={(sites ?? []).map((s) => s.id)} strategy={verticalListSortingStrategy}>
|
|
<div className="overflow-x-auto">
|
|
<table className="g-table">
|
|
<thead>
|
|
<tr>
|
|
<th className="w-8"></th>
|
|
<th>Name</th>
|
|
<th>URL template</th>
|
|
<th>Health</th>
|
|
<th>AI confidence</th>
|
|
<th>Enabled</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{(sites ?? []).map((s) => <SiteRow key={s.id} site={s} />)}
|
|
</tbody>
|
|
</table>
|
|
{!(sites ?? []).length && (
|
|
<div className="flex flex-col items-center justify-center py-14 text-g-faint gap-2">
|
|
<span className="text-3xl opacity-20">⬡</span>
|
|
<p className="text-sm">No sites added yet</p>
|
|
<p className="text-xs opacity-60">Add a site below to start scraping</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</SortableContext>
|
|
</DndContext>
|
|
</div>
|
|
)
|
|
}
|