Skip to content

Commit f140638

Browse files
bennyv8LoTerence
authored andcommitted
Feat/qualifier pages (hackforla#668)
* update qualifier page 1 - aligned qualifier nav - use grid system instead of flex box for items * Refactor: update button styles for primary-dark theme * Feat: add ProgressIndicator component and integrate it into QualifierPage2 * Refactor: update border style in QualifierNav component * Refactor: dynamic grid layout in QualifierPage1 for responsive design * Feat: enhance RadioButtonForm to support skill selection callback * Feat: update RadioButtonForm dynamically render skill & experience levels * Add selectCOP and experience levels props to qualifiers * Feat: use context in QualiferPage2 to keep track of chosen experience level * Feat: integrate qualifiers context to manage selected COP in QualifierPage1 * Feat: refactor QualifierPage2 layout and improve skill selection handling * Refactor: - renamed experienceLevels to skills_matrix - refactored to use tw-components/Buttons.tsx & added second style - Ran npm run lint in frontend directory * update tech stack * feat: use new tw-button variant, fix merge --------- Co-authored-by: Terence Lo <[email protected]>
1 parent 62c448e commit f140638

File tree

9 files changed

+260
-102
lines changed

9 files changed

+260
-102
lines changed

frontend/src/components/Buttons/_Button.scss

+6-6
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,18 @@ $theme-values: (
102102
),
103103
),
104104
"primary-dark": (
105-
"background-color": $color-blue,
106-
"color": $color-white,
105+
"background-color": $color-white,
106+
"color": $color-blue-dark,
107107
"focus": (
108-
"background-color": $color-blue-focused,
108+
"background-color": $color-blue-dark-focused,
109109
),
110110
"hover": (
111-
"background-color": $color-white,
111+
"background-color": $color-blue-dark-hover,
112112
"box-shadow": 0 4px 4px rgb(0 0 0 / 20%),
113-
"color": $color-charcoal,
113+
"color": $color-white,
114114
),
115115
"active": (
116-
"background-color": $color-blue-focused,
116+
"background-color": $color-blue-dark-focused,
117117
),
118118
),
119119
);

frontend/src/context/QualifiersContext.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ type QualifiersType = {
66
COPs: {
77
[copName: string]: string[];
88
};
9+
selectedCOP?: string;
10+
skills_matrix?: { [skill: string]: string };
911
// availabilityTimeSlots: string[];
1012
};
1113

@@ -53,6 +55,7 @@ export const QualifiersProvider: React.FC<{ children: ReactNode }> = ({
5355
const [qualifiers, setQualifiers] = useState<QualifiersType>(initialState);
5456

5557
const updateQualifiers = (newQualifiers: QualifiersType) => {
58+
console.log("Updated Qualifiers:", newQualifiers); // Log the updated qualifiers TO DELETE
5659
setQualifiers(newQualifiers);
5760
};
5861

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import React from "react";
2+
3+
interface ProgressIndicatorProps {
4+
currentPart: number;
5+
totalParts: number;
6+
title: string;
7+
progressPercentage: number; // New prop
8+
}
9+
10+
export const ProgressIndicator: React.FC<ProgressIndicatorProps> = ({
11+
currentPart,
12+
totalParts,
13+
title,
14+
progressPercentage,
15+
}) => {
16+
// Ensure progressPercentage is clamped between 0 and 100
17+
const validProgressPercentage = Math.min(
18+
Math.max(progressPercentage, 0),
19+
100,
20+
);
21+
const strokeDashoffset = 62.8 - (62.8 * validProgressPercentage) / 100;
22+
23+
return (
24+
<div className="flex items-center gap-2">
25+
<svg
26+
className="text-blue-dark"
27+
width="40"
28+
height="40"
29+
viewBox="0 0 36 36"
30+
xmlns="http://www.w3.org/2000/svg"
31+
>
32+
<circle
33+
cx="18"
34+
cy="18"
35+
r="10"
36+
fill="none"
37+
stroke="#e6e6e6"
38+
strokeWidth="4"
39+
/>
40+
<circle
41+
cx="18"
42+
cy="18"
43+
r="10"
44+
fill="none"
45+
stroke="currentColor"
46+
strokeWidth="4"
47+
strokeDasharray="62.8, 62.8"
48+
strokeDashoffset={strokeDashoffset}
49+
transform="rotate(-90 18 18)"
50+
/>
51+
</svg>
52+
<div className="flex flex-col">
53+
<span className="font-bold text-charcoal">
54+
Part {currentPart} of {totalParts}
55+
</span>
56+
<span className="text-charcoal">{title}</span>
57+
</div>
58+
</div>
59+
);
60+
};

frontend/src/pages/QualifierPage/components/QualifierNav.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ function QualifierNav({ className, children }: QualifierNavProps) {
1111
return (
1212
<div
1313
className={clsx(
14-
"border-px sticky bottom-0 box-content flex h-20 w-4/5 flex-wrap items-center rounded-lg border-[#D8D8D8] bg-[#FDFDFD] px-6 opacity-80 shadow-[0_8px_25px_#00000014] hover:opacity-100",
14+
"sticky bottom-0 box-content flex h-16 w-full flex-wrap items-center rounded-lg border border-[#E0E0E0] bg-[#FDFDFD] opacity-80 shadow-[0_8px_25px_#00000014] hover:opacity-100",
1515
className,
1616
)}
1717
>
18-
{children}
18+
<div className="flex w-full items-center justify-between px-6">
19+
{children}
20+
</div>
1921
</div>
2022
);
2123
}

frontend/src/pages/QualifierPage/components/RadioButtonForm.tsx

+70-22
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,36 @@ import React from "react";
33
// Internal Imports
44
import Typography from "tw-components/Typography";
55

6-
function RadioButtonForm() {
6+
interface RadioButtonFormProps {
7+
onSkillSelect: (skill: string, level: string) => void;
8+
selectedSkillsLevel: Record<string, string>;
9+
}
10+
11+
const skills = [
12+
{
13+
name: "User Research Methods",
14+
description: "Interviews, surveys, and usability testing",
15+
},
16+
{
17+
name: "User Personas & Journey Mapping",
18+
description:
19+
"Developing representative user profiles and mapping user journeys",
20+
},
21+
{
22+
name: "Information Architecture",
23+
description:
24+
"E.g., creating site maps, navigation flows, or using card sorting",
25+
},
26+
{
27+
name: "Wireframing & Sketching",
28+
description: "low-fidelity layouts to visualize structure and flow",
29+
},
30+
];
31+
32+
function RadioButtonForm({
33+
onSkillSelect,
34+
selectedSkillsLevel,
35+
}: RadioButtonFormProps) {
736
return (
837
<table className="w-full table-fixed border-collapse text-charcoal">
938
<thead>
@@ -29,22 +58,15 @@ function RadioButtonForm() {
2958
</tr>
3059
</thead>
3160
<tbody>
32-
<SkillRow
33-
skillName="User Research Methods"
34-
description="Interviews, surveys, and usability testing"
35-
/>
36-
<SkillRow
37-
skillName="User Personas & Journey Mapping"
38-
description="Developing representative user profiles and mapping user journeys"
39-
/>
40-
<SkillRow
41-
skillName="Information Architecture"
42-
description="E.g., creating site maps, navigation flows, or using card sorting"
43-
/>
44-
<SkillRow
45-
skillName="Wireframing & Sketching"
46-
description="low-fidelity layouts to visualize structure and flow"
47-
/>
61+
{skills.map((skill) => (
62+
<SkillRow
63+
key={skill.name}
64+
skillName={skill.name}
65+
description={skill.description}
66+
onSkillSelect={onSkillSelect}
67+
selectedLevel={selectedSkillsLevel[skill.name]}
68+
/>
69+
))}
4870
</tbody>
4971
</table>
5072
);
@@ -53,9 +75,16 @@ function RadioButtonForm() {
5375
interface SkillRowProps {
5476
skillName: string;
5577
description: string;
78+
onSkillSelect: (skill: string, level: string) => void;
79+
selectedLevel?: string;
5680
}
5781

58-
function SkillRow({ skillName, description }: SkillRowProps) {
82+
function SkillRow({
83+
skillName,
84+
description,
85+
onSkillSelect,
86+
selectedLevel,
87+
}: SkillRowProps) {
5988
return (
6089
<tr className="border-b-2 border-grey last:border-0">
6190
<td className="pb-7 pt-6">
@@ -65,13 +94,28 @@ function SkillRow({ skillName, description }: SkillRowProps) {
6594
</Typography.Paragraph3>
6695
</td>
6796
<td>
68-
<RadioButton name={skillName} value="0-2yrs" />
97+
<RadioButton
98+
name={skillName}
99+
value="0-2yrs"
100+
checked={selectedLevel === "0-2yrs"}
101+
onChange={() => onSkillSelect(skillName, "0-2yrs")}
102+
/>
69103
</td>
70104
<td>
71-
<RadioButton name={skillName} value="2-4yrs" />
105+
<RadioButton
106+
name={skillName}
107+
value="2-4yrs"
108+
checked={selectedLevel === "2-4yrs"}
109+
onChange={() => onSkillSelect(skillName, "2-4yrs")}
110+
/>
72111
</td>
73112
<td>
74-
<RadioButton name={skillName} value="4+yrs" />
113+
<RadioButton
114+
name={skillName}
115+
value="4+yrs"
116+
checked={selectedLevel === "4+yrs"}
117+
onChange={() => onSkillSelect(skillName, "4+yrs")}
118+
/>
75119
</td>
76120
</tr>
77121
);
@@ -80,14 +124,18 @@ function SkillRow({ skillName, description }: SkillRowProps) {
80124
interface RadioButtonProps {
81125
value: string;
82126
name: string;
127+
checked?: boolean;
128+
onChange: () => void;
83129
}
84130

85-
function RadioButton({ value, name }: RadioButtonProps) {
131+
function RadioButton({ value, name, checked, onChange }: RadioButtonProps) {
86132
return (
87133
<input
88134
type="radio"
89135
name={name}
90136
value={value}
137+
checked={checked}
138+
onChange={onChange}
91139
className="size-8 border-2 border-grey-dark checked:bg-blue-dark"
92140
/>
93141
);

0 commit comments

Comments
 (0)