"use client"; import { memo } from "react"; import { IconLoader2, IconFileInvoice, IconSend, IconChevronDown, IconPlus, } from "@tabler/icons-react"; import { Button } from "@kandev/ui/button"; import { DialogClose } from "@kandev/ui/dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@kandev/ui/dropdown-menu"; import { SHORTCUTS } from "@/lib/keyboard/constants"; import { KeyboardShortcutTooltip } from "@/components/keyboard-shortcut-tooltip"; type UpdateButtonProps = { isCreatingTask: boolean; hasTitle: boolean; onUpdate: () => void; }; function UpdateButton({ isCreatingTask, hasTitle, onUpdate }: UpdateButtonProps) { return ( ); } type StartTaskSplitButtonProps = { isCreatingTask: boolean; disabled: boolean; altDisabled: boolean; isEditMode: boolean; onAltAction: () => void; onPlanModeAction?: () => void; }; function StartTaskSplitButton({ isCreatingTask, disabled, altDisabled, isEditMode, onAltAction, onPlanModeAction, }: StartTaskSplitButtonProps) { const altLabel = isEditMode ? "Update task" : "Create only"; return (
{onPlanModeAction && ( Start task in plan mode )} {isEditMode ? "Update task" : "Create without starting agent"}
{/* Mobile-only: visible buttons for plan mode and creating without agent */} {onPlanModeAction && ( )}
); } type DefaultSubmitButtonProps = { isCreatingSession: boolean; isCreatingTask: boolean; isSessionMode: boolean; isCreateMode: boolean; isEditMode: boolean; hasDescription: boolean; isPassthroughProfile: boolean; disabled: boolean; }; function DefaultSubmitButton({ isCreatingSession, isCreatingTask, isSessionMode, isCreateMode, isEditMode, hasDescription, isPassthroughProfile, disabled, }: DefaultSubmitButtonProps) { const planModeStyle = isCreateMode && !hasDescription ? "bg-blue-600 border-blue-500 text-white hover:bg-blue-700 hover:text-white" : ""; return ( ); } export type TaskCreateDialogFooterProps = { isSessionMode: boolean; isCreateMode: boolean; isEditMode: boolean; isTaskStarted: boolean; isPassthroughProfile: boolean; isCreatingSession: boolean; isCreatingTask: boolean; hasTitle: boolean; hasDescription: boolean; hasRepositorySelection: boolean; branch: string; agentProfileId: string; workspaceId: string | null; effectiveWorkflowId: string | null; executorHint: string | null; onCancel: () => void; onUpdateWithoutAgent: () => void; onCreateWithoutAgent: () => void; onCreateWithPlanMode?: () => void; }; function isMissingWorkflowCtx( isCreateMode: boolean, workspaceId: string | null, effectiveWorkflowId: string | null, ) { return isCreateMode && (!workspaceId || !effectiveWorkflowId); } function computeBaseDisabled(props: TaskCreateDialogFooterProps) { const missingCtx = isMissingWorkflowCtx( props.isCreateMode, props.workspaceId, props.effectiveWorkflowId, ); return ( props.isCreatingTask || !props.hasTitle || !props.hasRepositorySelection || !props.branch || missingCtx ); } export type ButtonKind = "update" | "start-task" | "default"; export const REASON_TITLE = "Add a task title"; export const REASON_REPO = "Select a repository"; export const REASON_BRANCH = "Select a branch"; export const REASON_WORKSPACE = "Select a workspace"; export const REASON_WORKFLOW = "Select a workflow"; export const REASON_AGENT = "Select an agent"; export const REASON_DESCRIPTION = "Add a session description"; function baseReason(props: TaskCreateDialogFooterProps): string | null { if (!props.hasTitle) return REASON_TITLE; if (!props.hasRepositorySelection) return REASON_REPO; if (!props.branch) return REASON_BRANCH; if (props.isCreateMode && !props.workspaceId) return REASON_WORKSPACE; if (props.isCreateMode && !props.effectiveWorkflowId) return REASON_WORKFLOW; return null; } function missingSessionDescription(props: TaskCreateDialogFooterProps): boolean { return !props.hasDescription && !props.isPassthroughProfile; } function sessionDefaultReason(props: TaskCreateDialogFooterProps): string | null { if (!props.agentProfileId) return REASON_AGENT; if (missingSessionDescription(props)) return REASON_DESCRIPTION; return null; } export function computeDisabledReason( props: TaskCreateDialogFooterProps, kind: ButtonKind, ): string | null { if (props.isCreatingTask) return null; if (kind === "update") return props.hasTitle ? null : REASON_TITLE; if (kind === "default" && props.isSessionMode) return sessionDefaultReason(props); const base = baseReason(props); if (base) return base; if (kind === "start-task" && !props.agentProfileId) return REASON_AGENT; return null; } function resolveButtonKind(props: TaskCreateDialogFooterProps, showStartTask: boolean): ButtonKind { if (props.isTaskStarted) return "update"; if (showStartTask) return "start-task"; return "default"; } function computeFooterState(props: TaskCreateDialogFooterProps) { const showStartTask = (props.isCreateMode && (props.hasDescription || props.isPassthroughProfile)) || Boolean(props.isEditMode && props.agentProfileId); const altDisabled = computeBaseDisabled(props); const splitDisabled = altDisabled || !props.agentProfileId; const defaultDisabled = props.isSessionMode ? !props.agentProfileId : altDisabled; const disabledReason = computeDisabledReason(props, resolveButtonKind(props, showStartTask)); return { showStartTask, splitDisabled, altDisabled, defaultDisabled, disabledReason }; } export const TaskCreateDialogFooter = memo(function TaskCreateDialogFooter( props: TaskCreateDialogFooterProps, ) { const { isSessionMode, isCreateMode, isEditMode, isTaskStarted, isPassthroughProfile, isCreatingSession, isCreatingTask, hasTitle, hasDescription, executorHint, onCancel, onUpdateWithoutAgent, onCreateWithoutAgent, onCreateWithPlanMode, } = props; const { showStartTask, splitDisabled, altDisabled, defaultDisabled, disabledReason } = computeFooterState(props); return ( <> {!isSessionMode && !isTaskStarted && executorHint && (
{executorHint}
)} {(() => { if (isTaskStarted) { return ( ); } if (showStartTask) { return ( ); } return ( ); })()} ); });