1+ import { useMutation } from "@tanstack/react-query" ;
12import {
23 VscodeIcon ,
34 VscodeOption ,
45 VscodeProgressRing ,
56 VscodeSingleSelect ,
67} from "@vscode-elements/react-elements" ;
7- import { useEffect , useState } from "react" ;
8+ import { useState } from "react" ;
89
910import { useTasksApi } from "../hooks/useTasksApi" ;
1011
11- import type { TaskTemplate } from "@repo/shared" ;
12+ import type { CreateTaskParams , TaskTemplate } from "@repo/shared" ;
1213
1314interface CreateTaskSectionProps {
1415 templates : readonly TaskTemplate [ ] ;
@@ -19,61 +20,33 @@ export function CreateTaskSection({ templates }: CreateTaskSectionProps) {
1920 const [ prompt , setPrompt ] = useState ( "" ) ;
2021 const [ templateId , setTemplateId ] = useState ( templates [ 0 ] ?. id || "" ) ;
2122 const [ presetId , setPresetId ] = useState ( "" ) ;
22- const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
23- const [ error , setError ] = useState < string | null > ( null ) ;
23+
24+ const { mutate, isPending, error } = useMutation ( {
25+ mutationFn : ( vars : CreateTaskParams ) => api . createTask ( vars ) ,
26+ onSuccess : ( ) => setPrompt ( "" ) ,
27+ } ) ;
2428
2529 const selectedTemplate = templates . find ( ( t ) => t . id === templateId ) ;
2630 const presets = selectedTemplate ?. presets ?? [ ] ;
31+ const canSubmit = prompt . trim ( ) . length > 0 && selectedTemplate && ! isPending ;
2732
28- // Sync templateId when templates prop changes
29- useEffect ( ( ) => {
30- if ( templates . length > 0 && ! templates . find ( ( t ) => t . id === templateId ) ) {
31- setTemplateId ( templates [ 0 ] . id ) ;
32- setPresetId ( "" ) ;
33- }
34- } , [ templates , templateId ] ) ;
35-
36- const handleTemplateChange = ( e : Event ) => {
37- const target = e . target as HTMLSelectElement ;
38- const newTemplateId = target . value ;
39- setTemplateId ( newTemplateId ) ;
40- setPresetId ( "" ) ;
41- } ;
42-
43- const handlePresetChange = ( e : Event ) => {
44- const target = e . target as HTMLSelectElement ;
45- setPresetId ( target . value ) ;
46- } ;
47-
48- const handleSubmit = async ( ) => {
49- if ( ! prompt . trim ( ) || ! selectedTemplate || isSubmitting ) return ;
50-
51- setIsSubmitting ( true ) ;
52- setError ( null ) ;
53- try {
54- await api . createTask ( {
33+ const handleSubmit = ( ) => {
34+ if ( canSubmit ) {
35+ mutate ( {
5536 templateVersionId : selectedTemplate . activeVersionId ,
5637 prompt : prompt . trim ( ) ,
5738 presetId : presetId || undefined ,
5839 } ) ;
59- setPrompt ( "" ) ;
60- } catch ( err ) {
61- setError ( err instanceof Error ? err . message : "Failed to create task" ) ;
62- } finally {
63- setIsSubmitting ( false ) ;
6440 }
6541 } ;
6642
6743 const handleKeyDown = ( e : React . KeyboardEvent < HTMLTextAreaElement > ) => {
68- if ( e . key === "Enter" && ( e . metaKey || e . ctrlKey ) && ! isSubmitting ) {
44+ if ( e . key === "Enter" && ( e . metaKey || e . ctrlKey ) ) {
6945 e . preventDefault ( ) ;
70- void handleSubmit ( ) ;
46+ handleSubmit ( ) ;
7147 }
7248 } ;
7349
74- const canSubmit =
75- prompt . trim ( ) . length > 0 && selectedTemplate && ! isSubmitting ;
76-
7750 return (
7851 < div className = "create-task-section" >
7952 < div className = "prompt-input-container" >
@@ -83,31 +56,34 @@ export function CreateTaskSection({ templates }: CreateTaskSectionProps) {
8356 value = { prompt }
8457 onChange = { ( e ) => setPrompt ( e . target . value ) }
8558 onKeyDown = { handleKeyDown }
86- disabled = { isSubmitting }
59+ disabled = { isPending }
8760 />
8861 < div className = "prompt-send-button" >
89- { isSubmitting ? (
62+ { isPending ? (
9063 < VscodeProgressRing />
9164 ) : (
9265 < VscodeIcon
9366 actionIcon
9467 name = "send"
9568 label = "Send"
96- onClick = { canSubmit ? ( ) => void handleSubmit ( ) : undefined }
97- className = { ! canSubmit ? "disabled " : "" }
69+ onClick = { ( ) => void handleSubmit ( ) }
70+ className = { canSubmit ? "" : "disabled " }
9871 />
9972 ) }
10073 </ div >
10174 </ div >
102- { error && < div className = "create-task-error" > { error } </ div > }
75+ { error && < div className = "create-task-error" > { error . message } </ div > }
10376 < div className = "create-task-options" >
10477 < div className = "option-row" >
10578 < span className = "option-label" > Template:</ span >
10679 < VscodeSingleSelect
10780 className = "option-select"
10881 value = { templateId }
109- onChange = { handleTemplateChange }
110- disabled = { isSubmitting }
82+ onChange = { ( e ) => {
83+ setTemplateId ( ( e . target as HTMLSelectElement ) . value ) ;
84+ setPresetId ( "" ) ;
85+ } }
86+ disabled = { isPending }
11187 >
11288 { templates . map ( ( template ) => (
11389 < VscodeOption key = { template . id } value = { template . id } >
@@ -122,8 +98,10 @@ export function CreateTaskSection({ templates }: CreateTaskSectionProps) {
12298 < VscodeSingleSelect
12399 className = "option-select"
124100 value = { presetId }
125- onChange = { handlePresetChange }
126- disabled = { isSubmitting }
101+ onChange = { ( e ) =>
102+ setPresetId ( ( e . target as HTMLSelectElement ) . value )
103+ }
104+ disabled = { isPending }
127105 >
128106 < VscodeOption value = "" > No preset</ VscodeOption >
129107 { presets . map ( ( preset ) => (
0 commit comments