Skip to content

Commit ce48478

Browse files
committed
feat: moved all navigation and logic to same buttons
1 parent a6b5256 commit ce48478

File tree

9 files changed

+125
-189
lines changed

9 files changed

+125
-189
lines changed

src/components/statementWizard/PrivacySelector.tsx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@ import { Mail } from 'lucide-react';
55
interface PrivacySelectorProps {
66
isPublic: boolean;
77
onChange: (isPublic: boolean) => void;
8-
onComplete: () => void;
98
isSubmitting?: boolean;
109
}
1110

1211
export const PrivacySelector: React.FC<PrivacySelectorProps> = ({
1312
isPublic,
1413
onChange,
15-
onComplete,
16-
isSubmitting = false,
1714
}) => {
1815
return (
1916
<div className='space-y-6'>
@@ -55,14 +52,6 @@ export const PrivacySelector: React.FC<PrivacySelectorProps> = ({
5552
</div>
5653
</Button>
5754
</div>
58-
<Button
59-
variant='pink'
60-
className='mx-auto'
61-
onClick={onComplete}
62-
disabled={isSubmitting}
63-
>
64-
{isSubmitting ? 'Submitting...' : 'Create Statement'}
65-
</Button>
6655
</div>
6756
);
6857
};

src/components/statementWizard/StatementWizard.tsx

Lines changed: 63 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { CategoryStep } from './steps/CategoryStep';
1818
import { PrivacyStep } from './steps/PrivacyStep';
1919
import { ComplementStep } from './steps/ComplementStep';
2020
import StatementPreview from './StatementPreview';
21+
import { Button } from '../ui/button';
2122

2223
interface StatementWizardProps {
2324
username: string;
@@ -36,11 +37,11 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
3637
const isPreset = Boolean(presetQuestion);
3738

3839
// Define steps: if preset, skip "category" and add "complement"
39-
const steps: Step[] = isPreset
40+
const steps: Exclude<Step, 'closed'>[] = isPreset
4041
? ['subject', 'verb', 'object', 'privacy', 'complement']
4142
: ['subject', 'verb', 'object', 'category', 'privacy'];
4243

43-
//
44+
// Use design tokens for border colors via Tailwind’s arbitrary value syntax:
4445
const stepBorderColors: Record<Exclude<Step, 'closed'>, string> = {
4546
subject: 'border-[var(--subject-selector)]',
4647
verb: 'border-[var(--verb-selector)]',
@@ -63,8 +64,8 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
6364
},
6465
category: '',
6566
});
67+
const [isSubmitting, setIsSubmitting] = useState(false);
6668

67-
// If using a preset that presets subject, set it to username
6869
useEffect(() => {
6970
if (presetQuestion?.steps?.subject?.preset) {
7071
setSelection((prev) => ({
@@ -76,10 +77,7 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
7677

7778
const currentStep = steps[currentStepIndex];
7879

79-
const [isSubmitting, setIsSubmitting] = useState(false);
80-
8180
const handleComplete = async () => {
82-
// Prevent multiple clicks if already submitting
8381
if (isSubmitting) return;
8482
setIsSubmitting(true);
8583
const { subject, verb, object, adverbial } = selection.atoms;
@@ -110,7 +108,6 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
110108
}
111109
};
112110

113-
// Advance to the next step or finish if on the last step
114111
const goNext = () => {
115112
if (currentStepIndex < steps.length - 1) {
116113
setCurrentStepIndex((prev) => prev + 1);
@@ -127,6 +124,30 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
127124
}
128125
};
129126

127+
// Optional: Define a validation function for the current step.
128+
// This function should return true if the current step’s required data is valid.
129+
const isStepValid = (step: Exclude<Step, 'closed'>): boolean => {
130+
switch (step) {
131+
case 'subject':
132+
return selection.atoms.subject.trim().length > 0;
133+
case 'verb':
134+
return selection.atoms.verb.trim().length > 0;
135+
case 'object':
136+
return selection.atoms.object.trim().length > 0;
137+
case 'category':
138+
return selection.category.trim().length > 0;
139+
case 'privacy':
140+
// Always valid since it's a boolean toggle.
141+
return true;
142+
case 'complement':
143+
// Complement is optional; consider it valid.
144+
return true;
145+
default:
146+
return false;
147+
}
148+
};
149+
150+
// Render the current step component without navigation buttons.
130151
const renderStep = () => {
131152
switch (currentStep) {
132153
case 'subject':
@@ -141,8 +162,6 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
141162
atoms: { ...prev.atoms, subject: val },
142163
}))
143164
}
144-
onNext={goNext}
145-
onBack={goBack}
146165
/>
147166
);
148167
case 'verb':
@@ -156,8 +175,6 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
156175
atoms: { ...prev.atoms, verb: val },
157176
}))
158177
}
159-
onNext={goNext}
160-
onBack={goBack}
161178
/>
162179
);
163180
case 'object':
@@ -172,8 +189,6 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
172189
atoms: { ...prev.atoms, object: val },
173190
}))
174191
}
175-
onNext={goNext}
176-
onBack={goBack}
177192
/>
178193
);
179194
case 'category':
@@ -186,27 +201,10 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
186201
category: val,
187202
}))
188203
}
189-
onNext={goNext}
190-
onBack={goBack}
191204
/>
192205
);
193206
case 'privacy':
194-
return isPreset ? (
195-
// In preset flow, privacy isn't final (next goes to complement)
196-
<PrivacyStep
197-
isPublic={selection.isPublic}
198-
onUpdate={(val) =>
199-
setSelection((prev) => ({
200-
...prev,
201-
isPublic: val,
202-
}))
203-
}
204-
onNext={goNext}
205-
onBack={goBack}
206-
isSubmitting={isSubmitting}
207-
/>
208-
) : (
209-
// In custom flow, privacy is the final step so we call handleComplete
207+
return (
210208
<PrivacyStep
211209
isPublic={selection.isPublic}
212210
onUpdate={(val) =>
@@ -215,32 +213,26 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
215213
isPublic: val,
216214
}))
217215
}
218-
onNext={handleComplete}
219-
onBack={goBack}
220-
isSubmitting={isSubmitting}
221216
/>
222217
);
223218
case 'complement':
224-
return (
225-
<ComplementStep
226-
onComplete={handleComplete}
227-
onBack={goBack}
228-
isSubmitting={isSubmitting}
229-
/>
230-
);
219+
return <ComplementStep />;
231220
default:
232221
return null;
233222
}
234223
};
235224

225+
// Helper function to get the border color class
226+
const getBorderColor = (step: Exclude<Step, 'closed'>): string => {
227+
return stepBorderColors[step];
228+
};
229+
236230
return (
237231
<Dialog open onOpenChange={onClose}>
238232
<DialogContent
239-
className={`sm:max-w-[600px] p-0 w-full border-8 ${
240-
currentStep !== 'closed'
241-
? stepBorderColors[currentStep as Exclude<Step, 'closed'>]
242-
: ''
243-
}`}
233+
className={`sm:max-w-[600px] p-0 w-full border-8 ${getBorderColor(
234+
currentStep
235+
)}`}
244236
>
245237
{presetQuestion && (
246238
<div className='px-4 py-3 bg-gray-200 border-b'>
@@ -261,6 +253,31 @@ const StatementWizard: React.FC<StatementWizardProps> = ({
261253
</motion.div>
262254
</AnimatePresence>
263255
<StatementPreview selection={selection} />
256+
{/* Navigation Panel */}
257+
<div className='flex justify-between p-4 border-t'>
258+
<Button
259+
onClick={goBack}
260+
disabled={currentStepIndex === 0}
261+
variant='pink'
262+
className='mx-auto'
263+
>
264+
Back
265+
</Button>
266+
<Button
267+
variant='pink'
268+
className='mx-auto'
269+
onClick={
270+
currentStepIndex === steps.length - 1 ? handleComplete : goNext
271+
}
272+
disabled={!isStepValid(currentStep) || isSubmitting}
273+
>
274+
{isSubmitting
275+
? 'Submitting...'
276+
: currentStepIndex === steps.length - 1
277+
? 'Create Statement'
278+
: 'Next'}
279+
</Button>
280+
</div>
264281
</DialogContent>
265282
</Dialog>
266283
);

src/components/statementWizard/steps/CategoryStep.tsx

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,20 @@ import { Button } from '../../ui/button';
55
import statementsCategories from '../../../../data/statementsCategories.json';
66

77
interface CategoryStepProps {
8-
selection: string; // current category
9-
onUpdate: (category: string) => void;
10-
onNext: () => void;
11-
onBack: () => void;
8+
selection: string;
9+
onUpdate: (val: string) => void;
1210
}
1311

1412
export const CategoryStep: React.FC<CategoryStepProps> = ({
1513
selection,
1614
onUpdate,
17-
onNext,
18-
onBack,
1915
}) => {
2016
const subQuestion = `You can set a category for your statement`;
2117
const categories = statementsCategories.categories || [];
2218
const uncategorisedSelected = !selection || selection === 'uncategorised';
2319

2420
return (
25-
<StepContainer subQuestion={subQuestion} showBack onBack={onBack}>
21+
<StepContainer subQuestion={subQuestion} showBack>
2622
<div className='grid grid-cols-2 gap-3 max-h-[60vh] overflow-y-auto p-2'>
2723
{categories.map((cat: { id: string; name: string }) => (
2824
<Button
@@ -56,18 +52,6 @@ export const CategoryStep: React.FC<CategoryStepProps> = ({
5652
<span className='font-medium'>Uncategorised</span>
5753
</Button>
5854
</div>
59-
<Button
60-
onClick={() => {
61-
if (!selection) {
62-
onUpdate('uncategorised');
63-
}
64-
onNext();
65-
}}
66-
variant='pink'
67-
className='mx-auto'
68-
>
69-
Next
70-
</Button>
7155
</StepContainer>
7256
);
7357
};
Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,16 @@
11
import React from 'react';
22
import StepContainer from '../StepContainer';
3-
import { Button } from '../../ui/button';
43

5-
interface ComplementStepProps {
6-
onComplete: () => void;
7-
onBack: () => void;
8-
isSubmitting?: boolean;
9-
}
10-
11-
export const ComplementStep: React.FC<ComplementStepProps> = ({
12-
onComplete,
13-
onBack,
14-
isSubmitting = false,
15-
}) => {
4+
export const ComplementStep: React.FC = () => {
165
const subQuestion = 'Add additional statement if needed';
176
return (
18-
<StepContainer subQuestion={subQuestion} showBack onBack={onBack}>
7+
<StepContainer subQuestion={subQuestion}>
198
<div className='text-center p-4'>
209
<p className='text-lg'>
2110
If you feel your statement didn't fully answer the question, you can
2211
later add custom statements to complement it.
2312
</p>
2413
</div>
25-
<Button
26-
onClick={onComplete}
27-
variant='pink'
28-
className='mx-auto mt-4'
29-
disabled={isSubmitting}
30-
>
31-
{isSubmitting ? 'Submitting...' : 'Finish'}
32-
</Button>
3314
</StepContainer>
3415
);
3516
};

src/components/statementWizard/steps/ObjectStep.tsx

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,24 @@
22
import React from 'react';
33
import StepContainer from '../StepContainer';
44
import { Input } from '../../ui/input';
5-
import { Button } from '../../ui/button';
65

76
interface ObjectStepProps {
87
subject: string;
98
verb: string;
10-
selection: string; // the current object value
11-
onUpdate: (objectText: string) => void;
12-
onNext: () => void;
13-
onBack: () => void;
9+
selection: string;
10+
onUpdate: (val: string) => void;
1411
}
1512

1613
export const ObjectStep: React.FC<ObjectStepProps> = ({
1714
subject,
1815
verb,
1916
selection,
2017
onUpdate,
21-
onNext,
22-
onBack,
2318
}) => {
2419
const subQuestion = `In what way does ${subject} ${verb}? What's the context?`;
2520

2621
return (
27-
<StepContainer subQuestion={subQuestion} showBack onBack={onBack}>
22+
<StepContainer subQuestion={subQuestion} showBack>
2823
<div className='p-4 rounded-md'>
2924
<Input
3025
autoFocus
@@ -34,14 +29,6 @@ export const ObjectStep: React.FC<ObjectStepProps> = ({
3429
className='text-lg p-4 rounded'
3530
/>
3631
</div>
37-
<Button
38-
onClick={() => selection.trim() && onNext()}
39-
disabled={!selection.trim()}
40-
variant='pink'
41-
className='mx-auto'
42-
>
43-
Next
44-
</Button>
4532
</StepContainer>
4633
);
4734
};

0 commit comments

Comments
 (0)