"use client"; import { useState, useCallback } from "react"; import { IconBrandGithub, IconPlus } from "@tabler/icons-react"; import { Button } from "@kandev/ui/button"; import { Card, CardContent } from "@kandev/ui/card"; import { Separator } from "@kandev/ui/separator"; import { TooltipProvider } from "@kandev/ui/tooltip"; import { useToast } from "@/components/toast-provider"; import { SettingsSection } from "@/components/settings/settings-section"; import { GitHubStatusCard } from "./github-status"; import { ReviewWatchTable } from "./review-watch-table"; import { ReviewWatchDialog } from "./review-watch-dialog"; import { IssueWatchTable } from "./issue-watch-table"; import { IssueWatchDialog } from "./issue-watch-dialog"; import { PRStatsPanel } from "./pr-stats"; import { useReviewWatches } from "@/hooks/domains/github/use-review-watches"; import { useIssueWatches } from "@/hooks/domains/github/use-issue-watches"; import type { ReviewWatch, IssueWatch } from "@/lib/types/github"; type GitHubSettingsProps = { workspaceId: string; }; function useWatchActions(workspaceId: string | null) { const { items: watches, create, update, remove, trigger } = useReviewWatches(workspaceId); const { toast } = useToast(); const handleDelete = useCallback( async (id: string) => { try { await remove(id); toast({ description: "Review watch deleted", variant: "success" }); } catch { toast({ description: "Failed to delete review watch", variant: "error" }); } }, [remove, toast], ); const handleTrigger = useCallback( async (id: string) => { try { const result = await trigger(id); const count = result?.new_prs_found ?? 0; if (count > 0) { toast({ description: `Found ${count} new PR${count > 1 ? "s" : ""}`, variant: "success", }); } else { toast({ description: "No new PRs found" }); } } catch { toast({ description: "Failed to check for PRs", variant: "error" }); } }, [trigger, toast], ); const handleToggleEnabled = useCallback( async (watch: ReviewWatch) => { try { await update(watch.id, { enabled: !watch.enabled }); toast({ description: watch.enabled ? "Watch paused" : "Watch enabled", variant: "success", }); } catch { toast({ description: "Failed to update watch", variant: "error" }); } }, [update, toast], ); return { watches, create, update, handleDelete, handleTrigger, handleToggleEnabled }; } function useIssueWatchActions(workspaceId: string | null) { const { items: watches, create, update, remove, trigger } = useIssueWatches(workspaceId); const { toast } = useToast(); const handleDelete = useCallback( async (id: string) => { try { await remove(id); toast({ description: "Issue watch deleted", variant: "success" }); } catch { toast({ description: "Failed to delete issue watch", variant: "error" }); } }, [remove, toast], ); const handleTrigger = useCallback( async (id: string) => { try { const result = await trigger(id); const count = result?.new_issues_found ?? 0; if (count > 0) { toast({ description: `Found ${count} new issue${count > 1 ? "s" : ""}`, variant: "success", }); } else { toast({ description: "No new issues found" }); } } catch { toast({ description: "Failed to check for issues", variant: "error" }); } }, [trigger, toast], ); const handleToggleEnabled = useCallback( async (watch: IssueWatch) => { try { await update(watch.id, { enabled: !watch.enabled }); toast({ description: watch.enabled ? "Watch paused" : "Watch enabled", variant: "success", }); } catch { toast({ description: "Failed to update watch", variant: "error" }); } }, [update, toast], ); return { watches, create, update, handleDelete, handleTrigger, handleToggleEnabled }; } export function GitHubSettings({ workspaceId }: GitHubSettingsProps) { return (

GitHub Integration

Configure GitHub PR monitoring, issue tracking, and review queue automation.

); } function ReviewWatchSection({ workspaceId }: { workspaceId: string }) { const { watches, create, update, handleDelete, handleTrigger, handleToggleEnabled } = useWatchActions(workspaceId); const { toast } = useToast(); const [dialogOpen, setDialogOpen] = useState(false); const [editingWatch, setEditingWatch] = useState(null); const handleEdit = useCallback((watch: ReviewWatch) => { setEditingWatch(watch); setDialogOpen(true); }, []); return ( <> { setEditingWatch(null); setDialogOpen(true); }} className="cursor-pointer" > Add Watch } > { await create(req); toast({ description: "Review watch created", variant: "success" }); }} onUpdate={async (id, req) => { await update(id, req); toast({ description: "Review watch updated", variant: "success" }); }} /> ); } function IssueWatchSection({ workspaceId }: { workspaceId: string }) { const issueActions = useIssueWatchActions(workspaceId); const { toast } = useToast(); const [dialogOpen, setDialogOpen] = useState(false); const [editingWatch, setEditingIssueWatch] = useState(null); const handleEdit = useCallback((watch: IssueWatch) => { setEditingIssueWatch(watch); setDialogOpen(true); }, []); return ( <> { setEditingIssueWatch(null); setDialogOpen(true); }} className="cursor-pointer" > Add Watch } > { await issueActions.create(req); toast({ description: "Issue watch created", variant: "success" }); }} onUpdate={async (id, req) => { await issueActions.update(id, req); toast({ description: "Issue watch updated", variant: "success" }); }} /> ); }