From 6cdb7afa6aa135c036658e165a29a49832558f71 Mon Sep 17 00:00:00 2001 From: Oliver Bryan <04oliverbryan@gmail.com> Date: Mon, 12 Jan 2026 02:53:09 +0000 Subject: [PATCH] select sprint --- .../src/components/issue-detail-pane.tsx | 31 ++++++++++++- .../frontend/src/components/sprint-select.tsx | 46 +++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 packages/frontend/src/components/sprint-select.tsx diff --git a/packages/frontend/src/components/issue-detail-pane.tsx b/packages/frontend/src/components/issue-detail-pane.tsx index adfa19e..0def8fa 100644 --- a/packages/frontend/src/components/issue-detail-pane.tsx +++ b/packages/frontend/src/components/issue-detail-pane.tsx @@ -1,4 +1,4 @@ -import type { IssueResponse, ProjectResponse, UserRecord } from "@issue/shared"; +import type { IssueResponse, ProjectResponse, SprintRecord, UserRecord } from "@issue/shared"; import { Check, Link, Trash, X } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { useSession } from "@/components/session-provider"; @@ -13,9 +13,11 @@ import { SelectTrigger } from "@/components/ui/select"; import { UserSelect } from "@/components/user-select"; import { issue } from "@/lib/server"; import { issueID } from "@/lib/utils"; +import { SprintSelect } from "./sprint-select"; export function IssueDetailPane({ project, + sprints, issueData, members, statuses, @@ -24,6 +26,7 @@ export function IssueDetailPane({ onIssueDelete, }: { project: ProjectResponse; + sprints: SprintRecord[]; issueData: IssueResponse; members: UserRecord[]; statuses: Record; @@ -35,15 +38,17 @@ export function IssueDetailPane({ const [assigneeId, setAssigneeId] = useState( issueData.Issue.assigneeId?.toString() ?? "unassigned", ); + const [sprintId, setSprintId] = useState(issueData.Issue.sprintId?.toString() ?? "unassigned"); const [status, setStatus] = useState(issueData.Issue.status); const [deleteOpen, setDeleteOpen] = useState(false); const [linkCopied, setLinkCopied] = useState(false); const copyTimeoutRef = useRef(null); useEffect(() => { + setSprintId(issueData.Issue.sprintId?.toString() ?? "unassigned"); setAssigneeId(issueData.Issue.assigneeId?.toString() ?? "unassigned"); setStatus(issueData.Issue.status); - }, [issueData.Issue.assigneeId, issueData.Issue.status]); + }, [issueData.Issue.sprintId, issueData.Issue.assigneeId, issueData.Issue.status]); useEffect(() => { return () => { @@ -53,6 +58,23 @@ export function IssueDetailPane({ }; }, []); + const handleSprintChange = async (value: string) => { + setSprintId(value); + const newSprintId = value === "unassigned" ? null : Number(value); + + await issue.update({ + issueId: issueData.Issue.id, + sprintId: newSprintId, + onSuccess: () => { + onIssueUpdate?.(); + }, + onError: (error) => { + console.error("error updating sprint:", error); + setSprintId(issueData.Issue.sprintId?.toString() ?? "unassigned"); + }, + }); + }; + const handleAssigneeChange = async (value: string) => { setAssigneeId(value); const newAssigneeId = value === "unassigned" ? null : Number(value); @@ -178,6 +200,11 @@ export function IssueDetailPane({

{issueData.Issue.description}

)} +
+ Sprint: + +
+
Assignee: void; + fallbackUser?: UserRecord | null; + placeholder?: string; +}) { + const [isOpen, setIsOpen] = useState(false); + + return ( + + ); +}