@@ -16,7 +16,14 @@ import {
1616} from "@/lib/wizard-config"
1717import { loadWizardState , persistWizardState } from "@/lib/wizard-storage"
1818import { buildDefaultSummaryData , buildStepsForStack } from "@/lib/wizard-summary-data"
19- import type { FileOutputConfig , Responses , WizardQuestion , WizardAnswer , WizardStep } from "@/types/wizard"
19+ import type {
20+ FileOutputConfig ,
21+ FreeTextResponses ,
22+ Responses ,
23+ WizardQuestion ,
24+ WizardAnswer ,
25+ WizardStep ,
26+ } from "@/types/wizard"
2027import type { GeneratedFileResult } from "@/types/output"
2128import { WizardEditAnswerDialog } from "@/components/wizard-edit-answer-dialog"
2229
@@ -30,6 +37,7 @@ type StackSummaryPageProps = {
3037export function StackSummaryPage ( { stackId, mode } : StackSummaryPageProps ) {
3138 const [ wizardSteps , setWizardSteps ] = useState < WizardStep [ ] | null > ( null )
3239 const [ responses , setResponses ] = useState < Responses | null > ( null )
40+ const [ freeTextResponses , setFreeTextResponses ] = useState < FreeTextResponses > ( { } )
3341 const [ autoFilledMap , setAutoFilledMap ] = useState < Record < string , boolean > > ( { } )
3442 const [ stackLabel , setStackLabel ] = useState < string | null > ( null )
3543 const [ autoFillNotice , setAutoFillNotice ] = useState < string | null > ( null )
@@ -53,7 +61,13 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
5361 setErrorMessage ( null )
5462 try {
5563 if ( mode === "default" ) {
56- const { steps, responses : defaultResponses , autoFilledMap : defaultsMap , stackLabel : label } =
64+ const {
65+ steps,
66+ responses : defaultResponses ,
67+ freeTextResponses : defaultFreeTextResponses ,
68+ autoFilledMap : defaultsMap ,
69+ stackLabel : label ,
70+ } =
5771 await buildDefaultSummaryData ( stackId )
5872
5973 if ( ! isActive ) {
@@ -62,6 +76,7 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
6276
6377 setWizardSteps ( steps )
6478 setResponses ( defaultResponses )
79+ setFreeTextResponses ( defaultFreeTextResponses )
6580 setAutoFilledMap ( defaultsMap )
6681 setStackLabel ( label )
6782 setAutoFillNotice ( "We applied the recommended defaults for you. Tweak any section before generating." )
@@ -70,6 +85,7 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
7085 stackId,
7186 stackLabel : label ,
7287 responses : defaultResponses ,
88+ freeTextResponses : defaultFreeTextResponses ,
7389 autoFilledMap : defaultsMap ,
7490 updatedAt : Date . now ( ) ,
7591 } )
@@ -85,6 +101,7 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
85101 if ( ! storedState ) {
86102 setWizardSteps ( steps )
87103 setResponses ( null )
104+ setFreeTextResponses ( { } )
88105 setAutoFilledMap ( { } )
89106 setStackLabel ( computedLabel )
90107 setAutoFillNotice ( null )
@@ -99,6 +116,7 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
99116
100117 setWizardSteps ( steps )
101118 setResponses ( normalizedResponses )
119+ setFreeTextResponses ( storedState . freeTextResponses ?? { } )
102120 setAutoFilledMap ( storedState . autoFilledMap ?? { } )
103121 setStackLabel ( storedState . stackLabel ?? computedLabel )
104122 setAutoFillNotice ( null )
@@ -133,10 +151,11 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
133151 null ,
134152 wizardSteps ,
135153 responses ,
154+ freeTextResponses ,
136155 autoFilledMap ,
137156 false
138157 )
139- } , [ wizardSteps , responses , autoFilledMap ] )
158+ } , [ wizardSteps , responses , freeTextResponses , autoFilledMap ] )
140159
141160 const handleGenerate = useCallback (
142161 async ( fileOption : FileOutputConfig ) => {
@@ -148,7 +167,7 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
148167 setGeneratedFile ( null )
149168
150169 try {
151- const payload = serializeWizardResponses ( wizardSteps , responses , fileOption . id )
170+ const payload = serializeWizardResponses ( wizardSteps , responses , freeTextResponses , fileOption . id )
152171
153172 const result = await generateInstructions ( {
154173 stackSegment : stackId ,
@@ -167,7 +186,7 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
167186 setIsGeneratingMap ( ( prev ) => ( { ...prev , [ fileOption . id ] : false } ) )
168187 }
169188 } ,
170- [ wizardSteps , responses , stackId ]
189+ [ wizardSteps , responses , freeTextResponses , stackId ]
171190 )
172191
173192 const summaryHeader = stackLabel ??
@@ -187,9 +206,56 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
187206 setEditingQuestionId ( questionId )
188207 }
189208
190- const handleCloseEdit = ( ) => {
209+ const handleCloseEdit = useCallback ( ( ) => {
191210 setEditingQuestionId ( null )
192- }
211+ } , [ ] )
212+
213+ const applyFreeTextUpdate = useCallback (
214+ ( question : WizardQuestion , submittedValue : string ) => {
215+ if ( ! responses ) {
216+ return
217+ }
218+
219+ const trimmed = submittedValue . trim ( )
220+ const nextFreeText : FreeTextResponses = ( ( ) => {
221+ if ( trimmed . length === 0 ) {
222+ if ( ! ( question . id in freeTextResponses ) ) {
223+ return { ...freeTextResponses }
224+ }
225+
226+ const next = { ...freeTextResponses }
227+ delete next [ question . id ]
228+ return next
229+ }
230+
231+ return {
232+ ...freeTextResponses ,
233+ [ question . id ] : trimmed ,
234+ }
235+ } ) ( )
236+
237+ const nextAutoFilledMap = { ...autoFilledMap }
238+ delete nextAutoFilledMap [ question . id ]
239+
240+ setFreeTextResponses ( nextFreeText )
241+ setAutoFilledMap ( nextAutoFilledMap )
242+ setAutoFillNotice ( null )
243+
244+ if ( stackId ) {
245+ persistWizardState ( {
246+ stackId,
247+ stackLabel : stackLabel ?? summaryHeader ,
248+ responses,
249+ freeTextResponses : nextFreeText ,
250+ autoFilledMap : nextAutoFilledMap ,
251+ updatedAt : Date . now ( ) ,
252+ } )
253+ }
254+
255+ handleCloseEdit ( )
256+ } ,
257+ [ responses , freeTextResponses , autoFilledMap , stackId , stackLabel , summaryHeader , handleCloseEdit ]
258+ )
193259
194260 const applyAnswerUpdate = useCallback (
195261 ( question : WizardQuestion , answer : WizardAnswer ) => {
@@ -226,6 +292,7 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
226292 stackId,
227293 stackLabel : stackLabel ?? summaryHeader ,
228294 responses : currentResponses ,
295+ freeTextResponses,
229296 autoFilledMap : currentAutoMap ,
230297 updatedAt : Date . now ( ) ,
231298 } )
@@ -235,7 +302,7 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
235302 handleCloseEdit ( )
236303 }
237304 } ,
238- [ responses , autoFilledMap , stackId , stackLabel , summaryHeader ]
305+ [ responses , freeTextResponses , autoFilledMap , stackId , stackLabel , summaryHeader , handleCloseEdit ]
239306 )
240307
241308 if ( isLoading ) {
@@ -386,11 +453,16 @@ export function StackSummaryPage({ stackId, mode }: StackSummaryPageProps) {
386453 return null
387454 }
388455 const currentValue = responses ? responses [ editingQuestion . id ] : undefined
456+ const currentFreeText = typeof freeTextResponses [ editingQuestion . id ] === "string"
457+ ? freeTextResponses [ editingQuestion . id ]
458+ : ""
389459 return (
390460 < WizardEditAnswerDialog
391461 question = { editingQuestion }
392462 value = { currentValue }
393463 onAnswerSelect = { ( answer ) => applyAnswerUpdate ( editingQuestion , answer ) }
464+ freeTextValue = { currentFreeText }
465+ onFreeTextSave = { ( nextValue ) => applyFreeTextUpdate ( editingQuestion , nextValue ) }
394466 onClose = { handleCloseEdit }
395467 />
396468 )
0 commit comments