import { api } from "$lib/api"; import type { LocalCard, LocalDeck, LocalNote, SyncQueueItem } from "$lib/db"; import { syncStore } from "$lib/sync-store"; import type { Column } from "$ui/DataTable"; import { DataTable } from "$ui/DataTable"; import { createResource, createSignal, Show } from "solid-js"; type SyncRecord = { id: string; type: "deck" | "note" | "card"; title: string; status: string; version: number; updatedAt: string; }; type QueueRecord = { id: string; entityType: string; entityId: string; operation: string; retryCount: number; createdAt: string; lastError?: string; }; export function SyncDataTable() { const [activeTab, setActiveTab] = createSignal<"records" | "queue">("records"); const [refreshKey, setRefreshKey] = createSignal(0); const [data, { refetch }] = createResource(refreshKey, async () => { const result = await syncStore.getAllLocalData(); return result; }); const syncRecords = (): SyncRecord[] => { const d = data(); if (!d) return []; const decks: SyncRecord[] = d.decks.map((deck: LocalDeck) => ({ id: deck.id, type: "deck" as const, title: deck.title, status: deck.syncStatus, version: deck.localVersion, updatedAt: deck.updatedAt, })); const notes: SyncRecord[] = d.notes.map((note: LocalNote) => ({ id: note.id, type: "note" as const, title: note.title, status: note.syncStatus, version: note.localVersion, updatedAt: note.updatedAt, })); const cards: SyncRecord[] = d.cards.map((card: LocalCard) => ({ id: card.id, type: "card" as const, title: card.front.slice(0, 50) + (card.front.length > 50 ? "..." : ""), status: card.syncStatus, version: card.localVersion, updatedAt: "", })); return [...decks, ...notes, ...cards]; }; const queueRecords = (): QueueRecord[] => { const d = data(); if (!d) return []; return d.queue.map((item: SyncQueueItem) => ({ id: String(item.id || ""), entityType: item.entityType, entityId: item.entityId, operation: item.operation, retryCount: item.retryCount, createdAt: item.createdAt, lastError: item.lastError, })); }; const handleSync = async (type: string, id: string) => { await syncStore.queueForSync(type as "deck" | "card" | "note", id, "push"); await syncStore.processQueue(); setRefreshKey((k) => k + 1); }; const handleResolve = async ( type: string, id: string, strategy: "last_write_wins" | "keep_local" | "keep_remote", ) => { await api.resolveConflict(type, id, strategy); setRefreshKey((k) => k + 1); }; const handleClear = async () => { if (confirm("Clear all local sync data? This cannot be undone.")) { await syncStore.clearAll(); setRefreshKey((k) => k + 1); } }; const recordColumns: Column[] = [ { key: "type", header: "Type", sortable: true, width: "80px" }, { key: "title", header: "Title", sortable: true }, { key: "status", header: "Status", sortable: true, width: "120px", render: (row) => ( {row.status} ), }, { key: "version", header: "Ver", sortable: true, width: "60px" }, { key: "actions", header: "Actions", width: "150px", render: (row) => (
), }, ]; const queueColumns: Column[] = [ { key: "entityType", header: "Type", sortable: true, width: "80px" }, { key: "entityId", header: "Entity ID", sortable: true }, { key: "operation", header: "Op", width: "60px" }, { key: "retryCount", header: "Retries", sortable: true, width: "80px" }, { key: "lastError", header: "Error" }, ]; return (
Loading...
0} fallback={
No local records
}> r.id} />
0} fallback={
No pending queue items
}> r.id} />
); }