Skip to content

Commit 5fd3b38

Browse files
committed
feat: created intermediate component StepContainer
1 parent f68287f commit 5fd3b38

File tree

3 files changed

+71
-126
lines changed

3 files changed

+71
-126
lines changed

src/components/statementWizard/StatementWizard.tsx

Lines changed: 38 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// src/components/statementWizard/StatementWizard.tsx
21
'use client';
32

43
import { useState, useEffect } from 'react';
@@ -10,16 +9,15 @@ import {
109
} from '../ui/dialog';
1110
import { Button } from '../ui/button';
1211
import { Input } from '../ui/input';
13-
import { ArrowLeft } from 'lucide-react';
1412
import { motion, AnimatePresence } from 'framer-motion';
1513
import { useEntries } from '../../hooks/useEntries';
1614
import { postNewEntry } from '../../api/entriesApi';
1715
import type { Entry, SetQuestion, Step } from '../../../types/entries';
1816
import { SubjectTiles } from './SubjectTiles';
19-
// import { VerbTiles } from './VerbTiles';
2017
import SentimentVerbPicker from './SentimentVerbPicker';
2118
import { PrivacySelector } from './PrivacySelector';
2219
import statementsCategories from '../../../data/statementsCategories.json';
20+
import StepContainer from './StepContainer';
2321

2422
interface 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
3230
const 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-
5340
const 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
);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use client';
2+
3+
import React from 'react';
4+
import { Button } from '../ui/button';
5+
import { ArrowLeft } from 'lucide-react';
6+
7+
interface StepContainerProps {
8+
subQuestion: string;
9+
showBack?: boolean;
10+
onBack?: () => void;
11+
children: React.ReactNode;
12+
}
13+
14+
const StepContainer: React.FC<StepContainerProps> = ({
15+
subQuestion,
16+
showBack = false,
17+
onBack,
18+
children,
19+
}) => (
20+
<div className='p-2 space-y-4'>
21+
<div className='flex items-center'>
22+
{showBack && onBack && (
23+
<Button variant='ghost' size='icon' onClick={onBack} className='mr-2'>
24+
<ArrowLeft className='w-4 h-4' />
25+
</Button>
26+
)}
27+
<h2 className='text-xl font-semibold'>{subQuestion}</h2>
28+
</div>
29+
{children}
30+
</div>
31+
);
32+
33+
export default StepContainer;

src/components/statementWizard/VerbTiles.tsx.DELETE

Lines changed: 0 additions & 44 deletions
This file was deleted.

0 commit comments

Comments
 (0)