import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "sonner";
import { BoardSettingsNav } from "../components/BoardSettingsNav";
import { Button } from "../components/ui/button";
import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../components/ui/card";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "../components/ui/dialog";
import { Input } from "../components/ui/input";
import { Label } from "../components/ui/label";
import { Skeleton } from "../components/ui/skeleton";
import { Switch } from "../components/ui/switch";
import { Textarea } from "../components/ui/textarea";
import { useBoard, useDeleteBoard, useUpdateBoard } from "../hooks/useBoard";
interface BoardSettingsBoard {
id: string;
name: string;
description?: string | null;
visibility: "private" | "public";
share_slug: string | null;
}
const BADGE_TYPES = [
{ type: "agents", label: "Agents", alt: "AK agents badge" },
{ type: "tasks", label: "Tasks", alt: "AK tasks badge" },
{ type: "tokens", label: "Tokens", alt: "AK tokens badge" },
] as const;
type BadgeType = (typeof BADGE_TYPES)[number]["type"];
export function BoardSettingsPage() {
const { boardId } = useParams<{ boardId: string }>();
const { board, loading } = useBoard(boardId);
if (loading) return ;
if (!board || !boardId) return ;
return ;
}
function BoardSettingsContent({ board, boardId }: { board: BoardSettingsBoard; boardId: string }) {
return (
{board.name}
Board settings
);
}
function BoardDetailsSection({ board, boardId }: { board: BoardSettingsBoard; boardId: string }) {
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const updateBoard = useUpdateBoard();
useEffect(() => {
setName(board.name);
setDescription(board.description || "");
}, [board.id]);
const hasChanges = name.trim() !== board.name || description.trim() !== (board.description || "");
async function save() {
try {
await updateBoard.mutateAsync({ id: boardId, name: name.trim(), description: description.trim() });
toast.success("Board settings saved");
} catch {
toast.error("Failed to save board settings");
}
}
return (
setName(event.target.value)} />
);
}
function BoardSharingSection({ board, boardId }: { board: BoardSettingsBoard; boardId: string }) {
const updateBoard = useUpdateBoard();
const isPublic = board.visibility === "public";
const shareUrl = board.share_slug ? `${window.location.origin}/share/${board.share_slug}` : null;
const badgeBaseUrl = board.share_slug ? `${window.location.origin}/api/share/${board.share_slug}/badge.svg` : null;
async function toggleVisibility() {
const nextVisibility = isPublic ? "private" : "public";
try {
await updateBoard.mutateAsync({ id: boardId, visibility: nextVisibility });
toast.success(nextVisibility === "public" ? "Sharing enabled" : "Sharing disabled");
} catch {
toast.error("Failed to update sharing");
}
}
async function copyShareText(type: "link" | BadgeType) {
if (!shareUrl || !badgeBaseUrl) return;
const text = type === "link" ? shareUrl : badgeMarkdown(shareUrl, badgeBaseUrl, type);
try {
await copyTextToClipboard(text);
toast.success(type === "link" ? "Share link copied" : `${badgeLabel(type)} badge copied`);
} catch {
toast.error("Failed to copy");
}
}
return (
Sharing
Enable a public read-only board link and README badge.
{isPublic ? "On" : "Off"}
{isPublic && shareUrl && badgeBaseUrl && (
)}
);
}
function ShareLinks({ badgeBaseUrl, shareUrl, onCopy }: { badgeBaseUrl: string; shareUrl: string; onCopy: (type: "link" | BadgeType) => void }) {
return (
Badge previews
{BADGE_TYPES.map((badge) => (
))}
Share link
{shareUrl}
);
}
function badgeUrl(baseUrl: string, type: BadgeType) {
return `${baseUrl}?type=${type}`;
}
function badgeMarkdown(shareUrl: string, baseUrl: string, type: BadgeType) {
return `[})](${shareUrl})`;
}
function badgeLabel(type: BadgeType) {
return BADGE_TYPES.find((badge) => badge.type === type)!.label;
}
async function copyTextToClipboard(text: string) {
try {
await navigator.clipboard.writeText(text);
return;
} catch {
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.style.position = "fixed";
textarea.style.opacity = "0";
document.body.appendChild(textarea);
textarea.select();
const copied = document.execCommand("copy");
textarea.remove();
if (!copied) throw new Error("Copy failed");
}
}
function BoardDangerSection({ board }: { board: BoardSettingsBoard }) {
const [deleteOpen, setDeleteOpen] = useState(false);
const [confirmId, setConfirmId] = useState("");
const deleteBoard = useDeleteBoard();
const navigate = useNavigate();
async function deleteCurrentBoard() {
await deleteBoard.mutateAsync(board.id);
navigate("/");
}
return (
Delete board
Deletes this board and its tasks. This cannot be undone.
);
}
function BoardSettingsLoading() {
return (
);
}
function BoardSettingsNotFound() {
return (
);
}