diff --git a/apps/webapp/src/app/(app)/layout.tsx b/apps/webapp/src/app/(app)/layout.tsx
index 33677a3..ecdd40b 100644
--- a/apps/webapp/src/app/(app)/layout.tsx
+++ b/apps/webapp/src/app/(app)/layout.tsx
@@ -3,10 +3,12 @@ import { AppSidebar } from '@/components/sidebar/app-sidebar'
import { UsageBanner } from '@/components/upgrade/usage-banner'
import { UrlSync } from '@/components/url-sync'
import { CommandPalette } from '@/components/command-palette'
+import { SyncProvider } from '@/components/sync-provider'
export default function AppLayout({ children }: { children: React.ReactNode }) {
return (
+
@@ -16,6 +18,7 @@ export default function AppLayout({ children }: { children: React.ReactNode }) {
{children}
+
)
}
diff --git a/apps/webapp/src/components/history/query-history-panel.tsx b/apps/webapp/src/components/history/query-history-panel.tsx
index 5116abe..caac156 100644
--- a/apps/webapp/src/components/history/query-history-panel.tsx
+++ b/apps/webapp/src/components/history/query-history-panel.tsx
@@ -2,9 +2,9 @@
import { useState } from 'react'
import { Play, Trash2, CheckCircle, XCircle } from 'lucide-react'
-import { trpc } from '@/lib/trpc-client'
+import { useQueryHistory } from '@/hooks/use-query-history'
import { useConnectionStore } from '@/stores/connection-store'
-import { useQueryStore } from '@/stores/query-store'
+import { useQueryTabs } from '@/hooks/use-query-tabs'
function formatRelativeTime(date: Date | string): string {
const now = Date.now()
@@ -23,17 +23,8 @@ function formatRelativeTime(date: Date | string): string {
export function QueryHistoryPanel() {
const [statusFilter, setStatusFilter] = useState<'success' | 'error' | undefined>()
const { activeConnectionId } = useConnectionStore()
- const { activeTabId, updateSql } = useQueryStore()
- const utils = trpc.useUtils()
-
- const { data: entries, isLoading } = trpc.history.list.useQuery(
- { connectionId: activeConnectionId ?? undefined, status: statusFilter, limit: 100 },
- { enabled: !!activeConnectionId }
- )
-
- const deleteMutation = trpc.history.delete.useMutation({
- onSuccess: () => utils.history.list.invalidate(),
- })
+ const { activeTabId, updateSql } = useQueryTabs()
+ const { history, remove } = useQueryHistory(activeConnectionId ?? undefined, statusFilter)
if (!activeConnectionId) {
return (
@@ -64,11 +55,10 @@ export function QueryHistoryPanel() {
- {isLoading &&
Loading...
}
- {entries?.length === 0 && (
+ {history.length === 0 && (
No history yet
)}
- {entries?.map((entry) => (
+ {history.map((entry) => (
)}
- {entry.rowCount !== null && entry.status === 'success' && (
+ {entry.rowCount !== null && entry.rowCount !== undefined && entry.status === 'success' && (
· {entry.rowCount} rows
@@ -105,7 +95,7 @@ export function QueryHistoryPanel() {
- {isLoading && (
-
Loading...
- )}
- {queries?.length === 0 && (
+ {queries.length === 0 && (
No saved queries
)}
- {queries?.map((q) => (
+ {queries.map((q) => (
{q.name}
@@ -60,7 +49,7 @@ export function SavedQueriesPanel() {
{
updateSql(activeTabId, q.query)
- incrementMutation.mutate({ id: q.id })
+ incrementUsage(q.id)
}}
className="p-1 rounded text-muted-foreground hover:text-accent"
title="Load into editor"
@@ -68,7 +57,7 @@ export function SavedQueriesPanel() {
deleteMutation.mutate({ id: q.id })}
+ onClick={() => remove(q.id)}
className="p-1 rounded text-muted-foreground hover:text-destructive"
title="Delete"
>
diff --git a/apps/webapp/src/components/sync-provider.tsx b/apps/webapp/src/components/sync-provider.tsx
new file mode 100644
index 0000000..60fdc7a
--- /dev/null
+++ b/apps/webapp/src/components/sync-provider.tsx
@@ -0,0 +1,27 @@
+'use client'
+
+import { useEffect, useRef } from 'react'
+import { useAuth } from '@clerk/nextjs'
+import { trpc, type TRPCClient } from '@/lib/trpc-client'
+import { SyncManager } from '@/lib/sync-manager'
+
+export function SyncProvider({ children }: { children: React.ReactNode }) {
+ const { userId } = useAuth()
+ const syncRef = useRef(null)
+ const trpcClient = trpc.useUtils().client as TRPCClient
+
+ useEffect(() => {
+ if (!userId || !trpcClient) return
+
+ const manager = new SyncManager(userId, trpcClient)
+ syncRef.current = manager
+ manager.start()
+
+ return () => {
+ manager.stop()
+ syncRef.current = null
+ }
+ }, [userId, trpcClient])
+
+ return <>{children}>
+}