Skip to content

Commit c94248b

Browse files
committed
refactor: split FormStructure component
1 parent 394530c commit c94248b

File tree

5 files changed

+133
-126
lines changed

5 files changed

+133
-126
lines changed

src/features/form/components/AdminFormPreviewPage.tsx

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { FormsSection } from "@nycu-sdc/core-system-sdk";
77
import { useEffect, useMemo, useState, type CSSProperties } from "react";
88
import { useParams } from "react-router-dom";
99
import styles from "./AdminFormPreviewPage.module.css";
10+
import { FormStructure } from "./FormDetail/components/FormStructure/FormStructure";
1011
import formStyles from "./FormFilloutPage.module.css";
1112
import { FormQuestionRenderer } from "./FormQuestionRenderer";
1213

@@ -60,6 +61,7 @@ export const AdminFormPreviewPage = () => {
6061
}, [sections]);
6162

6263
const safeCurrentStep = sections.length > 0 ? Math.min(currentStep, sections.length - 1) : currentStep;
64+
const currentSection = sections[safeCurrentStep];
6365
const isFirstStep = safeCurrentStep === 0;
6466
const isLastStep = sections.length === 0 || safeCurrentStep === sections.length - 1;
6567
const isOnPreviewStep = isLastStep && sections[safeCurrentStep]?.id === "preview";
@@ -130,21 +132,12 @@ export const AdminFormPreviewPage = () => {
130132
<div className={formStyles.container} style={themedContainerStyle}>
131133
<div className={formStyles.header}>
132134
<h1 className={formStyles.title}>{form.title}</h1>
133-
{safeCurrentStep === 0 ? <p className={formStyles.description}>{form.description}</p> : <h2 className={formStyles.sectionHeader}>{sections[safeCurrentStep]?.title}</h2>}
135+
{safeCurrentStep === 0 && form.description && <div className={formStyles.description} dangerouslySetInnerHTML={{ __html: form.description }} />}
136+
<h2 className={formStyles.sectionHeader}>{currentSection?.title}</h2>
137+
{currentSection?.description && <div className={formStyles.sectionDescription} dangerouslySetInnerHTML={{ __html: currentSection.description }} />}
134138
</div>
135139

136-
<div className={formStyles.structure}>
137-
<div className={formStyles.structureTitle}>
138-
<h2>表單結構</h2>
139-
</div>
140-
<div className={formStyles.workflow}>
141-
{sections.map((section, index) => (
142-
<button key={section.id} type="button" className={`${formStyles.workflowButton} ${index === safeCurrentStep ? formStyles.active : ""}`} onClick={() => goToStep(index)}>
143-
{section.title}
144-
</button>
145-
))}
146-
</div>
147-
</div>
140+
<FormStructure sections={sections} currentStep={safeCurrentStep} onSectionClick={goToStep} />
148141

149142
<div className={formStyles.form}>
150143
{sections[safeCurrentStep] && (
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
.structure {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 1rem;
5+
background-color: var(--background-color-tertiary);
6+
padding: 1.5rem;
7+
border-radius: 3px;
8+
}
9+
10+
.structureTitle {
11+
display: flex;
12+
align-items: flex-end;
13+
}
14+
15+
.structureTitle h2 {
16+
font-size: 1.5rem;
17+
margin-block: 0;
18+
}
19+
20+
.structureTitle p {
21+
font-size: 1rem;
22+
}
23+
24+
.structureLegendRow {
25+
display: flex;
26+
gap: 0.625rem;
27+
}
28+
29+
.structureLegend {
30+
display: flex;
31+
font-size: 0.875rem;
32+
color: var(--color-caption);
33+
align-items: center;
34+
gap: 0.3rem;
35+
}
36+
37+
.structureLegend span {
38+
width: 0.75rem;
39+
height: 0.75rem;
40+
}
41+
42+
.structureLegendDotCompleted {
43+
background-color: var(--color-caption);
44+
}
45+
46+
.structureLegendDotPending {
47+
background-color: var(--code-foreground);
48+
}
49+
50+
.structureLegendDotCurrent {
51+
background-color: var(--form-theme-color, var(--orange));
52+
}
53+
54+
.workflow {
55+
display: flex;
56+
flex-wrap: wrap;
57+
gap: 0.5rem;
58+
}
59+
60+
.workflowButton {
61+
padding: 0.5rem 1rem;
62+
background-color: var(--code-foreground);
63+
border: 0.0625rem solid var(--code-foreground);
64+
color: var(--background);
65+
font-size: 1rem;
66+
cursor: pointer;
67+
transition: all 0.2s ease;
68+
}
69+
70+
.workflowButton.active {
71+
background-color: var(--form-theme-color, var(--orange));
72+
border-color: var(--form-theme-color, var(--orange));
73+
color: var(--background);
74+
}
75+
76+
.workflowButton.completed {
77+
background-color: var(--color-caption);
78+
border-color: var(--color-caption);
79+
color: var(--background);
80+
}
81+
82+
.workflowButton.completed.active {
83+
background-color: var(--form-theme-color, var(--orange));
84+
border-color: var(--form-theme-color, var(--orange));
85+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { FormsSection } from "@nycu-sdc/core-system-sdk";
2+
import styles from "./FormStructure.module.css";
3+
4+
interface FormStructureProps {
5+
sections: FormsSection[];
6+
currentStep: number;
7+
onSectionClick: (index: number) => void;
8+
}
9+
10+
export const FormStructure = ({ sections, currentStep, onSectionClick }: FormStructureProps) => {
11+
return (
12+
<div className={styles.structure}>
13+
<div className={styles.structureTitle}>
14+
<h2>表單結構</h2>
15+
<p>(可點擊項目返回編輯)</p>
16+
</div>
17+
<div className={styles.structureLegendRow}>
18+
<div className={styles.structureLegend}>
19+
<span className={styles.structureLegendDotCompleted}></span>
20+
<p>完成填寫</p>
21+
</div>
22+
<div className={styles.structureLegend}>
23+
<span className={styles.structureLegendDotPending}></span>
24+
<p>待填寫</p>
25+
</div>
26+
<div className={styles.structureLegend}>
27+
<span className={styles.structureLegendDotCurrent}></span>
28+
<p>目前位置</p>
29+
</div>
30+
</div>
31+
<div className={styles.workflow}>
32+
{sections.map((section, index) => (
33+
<button key={section.id} type="button" className={`${styles.workflowButton} ${index === currentStep ? styles.active : ""}`} onClick={() => onSectionClick(index)}>
34+
{section.title}
35+
</button>
36+
))}
37+
</div>
38+
</div>
39+
);
40+
};

src/features/form/components/FormFilloutPage.module.css

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -89,75 +89,6 @@
8989
font-family: var(--form-question-font, inherit);
9090
}
9191

92-
.structure {
93-
display: flex;
94-
flex-direction: column;
95-
gap: 1rem;
96-
background-color: var(--background-color-tertiary);
97-
padding: 1.5rem;
98-
border-radius: 3px;
99-
}
100-
101-
.structureTitle {
102-
display: flex;
103-
align-items: flex-end;
104-
}
105-
106-
.structureTitle h2 {
107-
font-size: 1.5rem;
108-
margin-block: 0;
109-
}
110-
111-
.structureTitle p {
112-
font-size: 1rem;
113-
}
114-
115-
.structureLegend {
116-
display: flex;
117-
font-size: 0.875rem;
118-
color: var(--color-caption);
119-
align-items: center;
120-
gap: 0.3rem;
121-
}
122-
123-
.structureLegend span {
124-
width: 0.75rem;
125-
height: 0.75rem;
126-
}
127-
128-
.workflow {
129-
display: flex;
130-
flex-wrap: wrap;
131-
gap: 0.5rem;
132-
}
133-
134-
.workflowButton {
135-
padding: 0.5rem 1rem;
136-
background-color: var(--code-foreground);
137-
border: 0.0625rem solid var(--code-foreground);
138-
color: var(--background);
139-
font-size: 1rem;
140-
cursor: pointer;
141-
transition: all 0.2s ease;
142-
}
143-
144-
.workflowButton.active {
145-
background-color: var(--form-theme-color, var(--orange));
146-
border-color: var(--form-theme-color, var(--orange));
147-
color: var(--background);
148-
}
149-
150-
.workflowButton.completed {
151-
background-color: var(--color-caption);
152-
border-color: var(--color-caption);
153-
color: var(--background);
154-
}
155-
156-
.workflowButton.completed.active {
157-
background-color: var(--form-theme-color, var(--orange));
158-
border-color: var(--form-theme-color, var(--orange));
159-
}
160-
16192
.form {
16293
display: flex;
16394
flex-direction: column;
@@ -438,23 +369,6 @@
438369
color: var(--color-caption);
439370
}
440371

441-
.structureLegendRow {
442-
display: flex;
443-
gap: 0.625rem;
444-
}
445-
446-
.structureLegendDotCompleted {
447-
background-color: var(--color-caption);
448-
}
449-
450-
.structureLegendDotPending {
451-
background-color: var(--code-foreground);
452-
}
453-
454-
.structureLegendDotCurrent {
455-
background-color: var(--form-theme-color, var(--orange));
456-
}
457-
458372
.loadingCenter {
459373
display: flex;
460374
justify-content: center;

src/features/form/components/FormFilloutPage.tsx

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
import { AlertCircle, Check, ChevronLeft, LoaderCircle } from "lucide-react";
2323
import { useEffect, useMemo, useRef, useState, type CSSProperties } from "react";
2424
import { useNavigate, useParams } from "react-router-dom";
25+
import { FormStructure } from "./FormDetail/components/FormStructure/FormStructure";
2526
import styles from "./FormFilloutPage.module.css";
2627
import { FormQuestionRenderer } from "./FormQuestionRenderer";
2728

@@ -610,33 +611,7 @@ export const FormFilloutPage = () => {
610611
{currentSection.description && <div className={styles.sectionDescription} dangerouslySetInnerHTML={{ __html: currentSection.description }} />}
611612
</div>
612613

613-
<div className={styles.structure}>
614-
<div className={styles.structureTitle}>
615-
<h2>表單結構</h2>
616-
<p>(可點擊項目返回編輯)</p>
617-
</div>
618-
<div className={styles.structureLegendRow}>
619-
<div className={styles.structureLegend}>
620-
<span className={styles.structureLegendDotCompleted}></span>
621-
<p>完成填寫</p>
622-
</div>
623-
<div className={styles.structureLegend}>
624-
<span className={styles.structureLegendDotPending}></span>
625-
<p>待填寫</p>
626-
</div>
627-
<div className={styles.structureLegend}>
628-
<span className={styles.structureLegendDotCurrent}></span>
629-
<p>目前位置</p>
630-
</div>
631-
</div>
632-
<div className={styles.workflow}>
633-
{sections.map((section, index) => (
634-
<button key={section.id} type="button" className={`${styles.workflowButton} ${index === currentStep ? styles.active : ""}`} onClick={() => handleSectionClick(index)}>
635-
{section.title}
636-
</button>
637-
))}
638-
</div>
639-
</div>
614+
<FormStructure sections={sections} currentStep={currentStep} onSectionClick={handleSectionClick} />
640615

641616
<form className={styles.form}>
642617
{sections[currentStep] && (

0 commit comments

Comments
 (0)