"use client"; export const dynamic = "force-dynamic"; import { useState } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { SignInButton, SignedIn, SignedOut, useAuth } from "@/auth/clerk"; import { ApiError } from "@/api/mutator"; import { type listBoardsApiV1BoardsGetResponse, updateBoardApiV1BoardsBoardIdPatch, useListBoardsApiV1BoardsGet, } from "@/api/generated/boards/boards"; import { useCreateBoardGroupApiV1BoardGroupsPost } from "@/api/generated/board-groups/board-groups"; import type { BoardRead } from "@/api/generated/model"; import { DashboardSidebar } from "@/components/organisms/DashboardSidebar"; import { DashboardShell } from "@/components/templates/DashboardShell"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; const slugify = (value: string) => value .toLowerCase() .trim() .replace(/[^a-z0-9]+/g, "-") .replace(/(^-|-$)/g, "") || "group"; export default function NewBoardGroupPage() { const router = useRouter(); const { isSignedIn } = useAuth(); const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [error, setError] = useState(null); const [boardSearch, setBoardSearch] = useState(""); const [selectedBoardIds, setSelectedBoardIds] = useState>( () => new Set(), ); const boardsQuery = useListBoardsApiV1BoardsGet< listBoardsApiV1BoardsGetResponse, ApiError >( { limit: 200 }, { query: { enabled: Boolean(isSignedIn), refetchOnMount: "always", retry: false, }, }, ); const boards: BoardRead[] = boardsQuery.data?.status === 200 ? (boardsQuery.data.data.items ?? []) : []; const createMutation = useCreateBoardGroupApiV1BoardGroupsPost({ mutation: { onError: (err) => { setError(err.message || "Something went wrong."); }, }, }); const isCreating = createMutation.isPending; const isFormReady = Boolean(name.trim()); const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); if (!isSignedIn) return; const trimmedName = name.trim(); if (!trimmedName) { setError("Group name is required."); return; } setError(null); try { const created = await createMutation.mutateAsync({ data: { name: trimmedName, slug: slugify(trimmedName), description: description.trim() || null, }, }); if (created.status !== 200) { throw new Error("Unable to create group."); } const groupId = created.data.id; const boardIds = Array.from(selectedBoardIds); if (boardIds.length) { const failures: string[] = []; for (const boardId of boardIds) { try { const result = await updateBoardApiV1BoardsBoardIdPatch(boardId, { board_group_id: groupId, }); if (result.status !== 200) { failures.push(boardId); } } catch { failures.push(boardId); } } if (failures.length) { router.push( `/board-groups/${groupId}/edit?assign_failed=${failures.length}`, ); return; } } router.push(`/board-groups/${groupId}`); } catch (err) { setError(err instanceof Error ? err.message : "Something went wrong."); } }; return (

Sign in to create a board group.

Create board group

Groups help agents discover related work across boards.

setName(event.target.value)} placeholder="e.g. Release hardening" disabled={isCreating} />