Skip to content

Commit a349c67

Browse files
devakoneclaude
andcommitted
fix: add disconnect button to repos settings page
The API endpoint existed but the UI had no button to call it. Added a "Remove" button in settings mode that calls /api/repos/disconnect. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 95d986a commit a349c67

1 file changed

Lines changed: 60 additions & 14 deletions

File tree

apps/web/src/app/repos/ReposClient.tsx

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useCallback, useEffect, useMemo, useState } from "react";
44
import { useRouter } from "next/navigation";
5-
import { ChevronsUpDown, RefreshCw } from "lucide-react";
5+
import { ChevronsUpDown, RefreshCw, Trash2 } from "lucide-react";
66
import { cn } from "@/lib/utils";
77
import { wrappedTheme } from "@/lib/theme";
88
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
@@ -204,6 +204,39 @@ export default function ReposClient({
204204
}
205205
}
206206

207+
const [disconnecting, setDisconnecting] = useState<string | null>(null);
208+
209+
async function disconnectRepo(repoId: string, repoName: string) {
210+
if (!confirm(`Disconnect "${repoName}"? This will remove it from your profile but won't delete any analysis data.`)) {
211+
return;
212+
}
213+
214+
setDisconnecting(repoId);
215+
try {
216+
const response = await fetch("/api/repos/disconnect", {
217+
method: "POST",
218+
headers: { "Content-Type": "application/json" },
219+
body: JSON.stringify({ repo_id: repoId }),
220+
});
221+
222+
if (!response.ok) {
223+
const body = await response.json();
224+
throw new Error(body.error || "Could not disconnect repo");
225+
}
226+
227+
toast({ title: "Repo disconnected", description: `${repoName} has been removed.` });
228+
router.refresh();
229+
} catch (error) {
230+
toast({
231+
variant: "destructive",
232+
title: "Disconnect failed",
233+
description: error instanceof Error ? error.message : "Please try again",
234+
});
235+
} finally {
236+
setDisconnecting(null);
237+
}
238+
}
239+
207240
const connectedRepos = initialConnected.map((repo) => ({
208241
...repo,
209242
latestJobId: latestJobByRepoId[repo.repo_id] ?? null,
@@ -300,27 +333,40 @@ export default function ReposClient({
300333
<span className="text-sm font-semibold text-zinc-900">{repo.full_name}</span>
301334
{repo.latestJobId && <span className="text-[11px] text-zinc-500">Analyzed</span>}
302335
</div>
303-
{/* Only show action buttons in vibes mode */}
304-
{mode === "vibes" && (
305-
<div className="flex items-center gap-2">
306-
{repo.latestJobId ? (
336+
{/* Action buttons differ by mode */}
337+
<div className="flex items-center gap-2">
338+
{mode === "vibes" && (
339+
<>
340+
{repo.latestJobId ? (
341+
<button
342+
type="button"
343+
className={cn(wrappedTheme.secondaryButton, "px-3 py-1 text-sm font-semibold")}
344+
onClick={() => router.push(`/analysis/${repo.latestJobId}`)}
345+
>
346+
View vibe
347+
</button>
348+
) : null}
307349
<button
308350
type="button"
309-
className={cn(wrappedTheme.secondaryButton, "px-3 py-1 text-sm font-semibold")}
310-
onClick={() => router.push(`/analysis/${repo.latestJobId}`)}
351+
className="rounded-full border border-zinc-300/80 bg-white/70 px-3 py-1 text-sm font-semibold text-zinc-950 shadow-sm hover:bg-white"
352+
onClick={() => startAnalysis(repo.repo_id, repo.full_name)}
311353
>
312-
View vibe
354+
{repo.latestJobId ? "Re-run" : "Start vibe"}
313355
</button>
314-
) : null}
356+
</>
357+
)}
358+
{mode === "settings" && (
315359
<button
316360
type="button"
317-
className="rounded-full border border-zinc-300/80 bg-white/70 px-3 py-1 text-sm font-semibold text-zinc-950 shadow-sm hover:bg-white"
318-
onClick={() => startAnalysis(repo.repo_id, repo.full_name)}
361+
className="flex items-center gap-1.5 rounded-full border border-red-200 bg-white px-3 py-1 text-sm font-semibold text-red-600 transition hover:bg-red-50 hover:border-red-300 disabled:opacity-50"
362+
onClick={() => disconnectRepo(repo.repo_id, repo.full_name)}
363+
disabled={disconnecting === repo.repo_id}
319364
>
320-
{repo.latestJobId ? "Re-run" : "Start vibe"}
365+
<Trash2 className="h-3.5 w-3.5" />
366+
{disconnecting === repo.repo_id ? "Removing…" : "Remove"}
321367
</button>
322-
</div>
323-
)}
368+
)}
369+
</div>
324370
</div>
325371
))}
326372
</div>

0 commit comments

Comments
 (0)