1- // src/components/statementWizard/StatementWizard.tsx
21'use client' ;
32
43import { useState , useEffect } from 'react' ;
@@ -10,16 +9,15 @@ import {
109} from '../ui/dialog' ;
1110import { Button } from '../ui/button' ;
1211import { Input } from '../ui/input' ;
13- import { ArrowLeft } from 'lucide-react' ;
1412import { motion , AnimatePresence } from 'framer-motion' ;
1513import { useEntries } from '../../hooks/useEntries' ;
1614import { postNewEntry } from '../../api/entriesApi' ;
1715import type { Entry , SetQuestion , Step } from '../../../types/entries' ;
1816import { SubjectTiles } from './SubjectTiles' ;
19- // import { VerbTiles } from './VerbTiles';
2017import SentimentVerbPicker from './SentimentVerbPicker' ;
2118import { PrivacySelector } from './PrivacySelector' ;
2219import statementsCategories from '../../../data/statementsCategories.json' ;
20+ import StepContainer from './StepContainer' ;
2321
2422interface StatementWizardProps {
2523 username : string ;
@@ -28,7 +26,7 @@ interface StatementWizardProps {
2826 onClose : ( ) => void ;
2927}
3028
31- // Default questions for each step
29+ // Default sub- questions for each step
3230const defaultQuestions = ( username : string , selection : Entry ) => ( {
3331 subject : `This statement applies to ${ username } or someone/something else?` ,
3432 verb : `What's happening with ${ selection . atoms . subject } ? How do they feel or what do they experience?` ,
@@ -39,17 +37,6 @@ const defaultQuestions = (username: string, selection: Entry) => ({
3937 privacy : `Who can see this statement?` ,
4038} ) ;
4139
42- // A reusable container for each step screen
43- const StepContainer : React . FC < {
44- question : string ;
45- children : React . ReactNode ;
46- } > = ( { question, children } ) => (
47- < div className = 'space-y-4 p-6' >
48- < h2 className = 'text-2xl font-semibold text-center mb-6' > { question } </ h2 >
49- { children }
50- </ div >
51- ) ;
52-
5340const StatementWizard : React . FC < StatementWizardProps > = ( {
5441 username,
5542 presetQuestion,
@@ -59,12 +46,11 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
5946 const { setData } = useEntries ( ) ;
6047 const isPreset = Boolean ( presetQuestion ) ;
6148
62- // Define the steps; skip 'category' if using a preset question.
49+ // Define steps; skip 'category' if using a preset question.
6350 const steps : Step [ ] = isPreset
6451 ? [ 'subject' , 'verb' , 'object' , 'privacy' ]
6552 : [ 'subject' , 'verb' , 'object' , 'category' , 'privacy' ] ;
6653
67- // Define a mapping of step names to border color classes.
6854 const stepBorderColors : Record < Exclude < Step , 'closed' > , string > = {
6955 subject : 'border-subjectSelector' ,
7056 verb : 'border-verbSelector' ,
@@ -87,7 +73,6 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
8773 category : '' ,
8874 } ) ;
8975
90- // If the preset question indicates a preset subject, default to username.
9176 useEffect ( ( ) => {
9277 if ( presetQuestion ?. steps ?. subject ?. preset ) {
9378 setSelection ( ( prev ) => ( {
@@ -97,8 +82,8 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
9782 }
9883 } , [ presetQuestion , username ] ) ;
9984
100- // Get the question text for the current step
101- const getQuestion = ( currentStep : Exclude < Step , 'closed' > ) =>
85+ // Get the sub- question for each step.
86+ const getSubQuestion = ( currentStep : Exclude < Step , 'closed' > ) =>
10287 presetQuestion ?. steps ?. [ currentStep ] ?. question ||
10388 defaultQuestions ( username , selection ) [ currentStep ] ;
10489
@@ -116,7 +101,6 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
116101 } ;
117102
118103 const handleComplete = async ( ) => {
119- // Build the full input string from atoms.
120104 const { subject, verb, object, adverbial } = selection . atoms ;
121105 const adverbialText =
122106 adverbial && adverbial . length > 0 ? adverbial . join ( ' ' ) : '' ;
@@ -129,7 +113,6 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
129113 id : Date . now ( ) . toString ( ) ,
130114 input : fullInput ,
131115 presetId : presetQuestion ? presetQuestion . id : undefined ,
132- // If using a preset question, use its category; otherwise, use selection.category.
133116 category :
134117 presetQuestion ?. category || selection . category || 'Uncategorized' ,
135118 } ;
@@ -140,14 +123,13 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
140123 onClose ( ) ;
141124 } ;
142125
143- // Render functions for each step
144-
126+ // Render steps
145127 const renderSubjectStep = ( ) => {
146- const question = getQuestion ( 'subject' ) ;
128+ const subQuestion = getSubQuestion ( 'subject' ) ;
147129 const allowDescriptors = presetQuestion ?. steps ?. subject ?. allowDescriptors ;
148130 if ( allowDescriptors === false ) {
149131 return (
150- < StepContainer question = { question } >
132+ < StepContainer subQuestion = { subQuestion } >
151133 < div className = 'text-center p-4 border rounded' >
152134 < p > { username } </ p >
153135 </ div >
@@ -167,7 +149,7 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
167149 ) ;
168150 }
169151 return (
170- < StepContainer question = { question } >
152+ < StepContainer subQuestion = { subQuestion } >
171153 < SubjectTiles
172154 username = { username }
173155 activePresetQuestion = { presetQuestion }
@@ -189,24 +171,13 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
189171 } ;
190172
191173 const renderVerbStep = ( ) => {
192- const question = getQuestion ( 'verb' ) ;
174+ const subQuestion = getSubQuestion ( 'verb' ) ;
193175 return (
194- < StepContainer question = { question } >
176+ < StepContainer subQuestion = { subQuestion } showBack onBack = { handleBack } >
195177 < div className = 'flex flex-col h-[60vh] p-4 rounded-md' >
196- { /* <VerbTiles
197- selectedVerb={selection.atoms.verb}
198- onSelect={(verb) => {
199- setSelection((prev) => ({
200- ...prev,
201- atoms: { ...prev.atoms, verb },
202- }));
203- handleNext('object');
204- }}
205- /> */ }
206178 < SentimentVerbPicker
207179 selectedVerb = { selection . atoms . verb }
208180 onVerbSelect = { ( verb ) => {
209- // Update the selection and move to the next step when a verb is selected.
210181 setSelection ( ( prev ) => ( {
211182 ...prev ,
212183 atoms : { ...prev . atoms , verb : verb . name } ,
@@ -220,11 +191,10 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
220191 } ;
221192
222193 const renderObjectStep = ( ) => {
223- const question = getQuestion ( 'object' ) ;
224- // Next step depends on whether we need to show the category screen.
194+ const subQuestion = getSubQuestion ( 'object' ) ;
225195 const nextStep : Step = presetQuestion ? 'privacy' : 'category' ;
226196 return (
227- < StepContainer question = { question } >
197+ < StepContainer subQuestion = { subQuestion } showBack onBack = { handleBack } >
228198 < div className = 'p-4 rounded-md' >
229199 < Input
230200 autoFocus
@@ -251,10 +221,10 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
251221 } ;
252222
253223 const renderCategoryStep = ( ) => {
254- const question = getQuestion ( 'category' ) ;
224+ const subQuestion = getSubQuestion ( 'category' ) ;
255225 const categories = statementsCategories . categories || [ ] ;
256226 return (
257- < StepContainer question = { question } >
227+ < StepContainer subQuestion = { subQuestion } showBack onBack = { handleBack } >
258228 < div className = 'grid grid-cols-2 gap-3 max-h-[60vh] overflow-y-auto p-2' >
259229 { categories . map ( ( cat : { id : string ; name : string } ) => (
260230 < Button
@@ -281,9 +251,9 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
281251 } ;
282252
283253 const renderPrivacyStep = ( ) => {
284- const question = getQuestion ( 'privacy' ) ;
254+ const subQuestion = getSubQuestion ( 'privacy' ) ;
285255 return (
286- < StepContainer question = { question } >
256+ < StepContainer subQuestion = { subQuestion } showBack onBack = { handleBack } >
287257 < PrivacySelector
288258 isPublic = { selection . isPublic }
289259 onChange = { ( isPublic ) =>
@@ -315,49 +285,35 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
315285 return (
316286 < Dialog open onOpenChange = { onClose } >
317287 < DialogContent
318- className = { `sm:max-w-[600px] pt-6 border-8 ${
288+ className = { `sm:max-w-[600px] p-0 w-full border-8 ${
319289 stepBorderColors [ step as Exclude < Step , 'closed' > ]
320290 } `}
321291 >
292+ { /* Top header: only render if there's a preset question */ }
322293 { presetQuestion && (
323- < div className = 'p -4 bg-gray-200 text-center ' >
294+ < div className = 'px -4 py-3 bg-gray-200 border-b ' >
324295 < h2 className = 'text-xl font-bold' > { presetQuestion . mainQuestion } </ h2 >
325296 </ div >
326297 ) }
327- < DialogDescription className = 'sr-only' >
328- Confirmation Dialog
329- </ DialogDescription >
330- < DialogTitle className = 'sr-only' > Confirmation Dialog</ DialogTitle >
331- < div className = 'relative' >
332- { step !== 'subject' && (
333- < Button
334- variant = 'ghost'
335- size = 'icon'
336- className = 'absolute left-4 top-4 z-10'
337- onClick = { ( e ) => {
338- e . stopPropagation ( ) ;
339- handleBack ( ) ;
340- } }
341- >
342- < ArrowLeft className = 'w-4 h-4' />
343- </ Button >
344- ) }
345- < AnimatePresence
346- mode = 'wait'
347- initial = { false }
348- onExitComplete = { ( ) => null }
298+
299+ < DialogDescription className = 'sr-only' > Wizard Steps</ DialogDescription >
300+ < DialogTitle className = 'sr-only' > Wizard Steps</ DialogTitle >
301+
302+ < AnimatePresence
303+ mode = 'wait'
304+ initial = { false }
305+ onExitComplete = { ( ) => null }
306+ >
307+ < motion . div
308+ key = { step }
309+ initial = { { opacity : 0 , y : 20 } }
310+ animate = { { opacity : 1 , y : 0 } }
311+ exit = { { opacity : 0 , y : - 20 } }
312+ transition = { { duration : 0.2 } }
349313 >
350- < motion . div
351- key = { step }
352- initial = { { opacity : 0 , y : 20 } }
353- animate = { { opacity : 1 , y : 0 } }
354- exit = { { opacity : 0 , y : - 20 } }
355- transition = { { duration : 0.2 } }
356- >
357- { renderCurrentStep ( ) }
358- </ motion . div >
359- </ AnimatePresence >
360- </ div >
314+ { renderCurrentStep ( ) }
315+ </ motion . div >
316+ </ AnimatePresence >
361317 </ DialogContent >
362318 </ Dialog >
363319 ) ;
0 commit comments