Skip to content

Commit d5dd0df

Browse files
authored
Add profile edit page (#1029)
1 parent deb4b82 commit d5dd0df

File tree

20 files changed

+1016
-479
lines changed

20 files changed

+1016
-479
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import React from "react"
2+
3+
import {
4+
styled,
5+
Grid,
6+
Container,
7+
ChoiceBox,
8+
RadioChoiceField,
9+
} from "ol-components"
10+
import {
11+
CertificateDesiredEnum,
12+
CertificateDesiredEnumDescriptions,
13+
} from "api/v0"
14+
15+
import type { ProfileFieldUpdateProps, ProfileFieldStateHook } from "./types"
16+
17+
const CHOICES = [
18+
CertificateDesiredEnum.Yes,
19+
CertificateDesiredEnum.No,
20+
CertificateDesiredEnum.NotSureYet,
21+
].map((value) => ({
22+
value,
23+
label: CertificateDesiredEnumDescriptions[value],
24+
}))
25+
26+
type State = CertificateDesiredEnum | ""
27+
type Props = ProfileFieldUpdateProps<"certificate_desired">
28+
29+
const useCertificateChoiceState: ProfileFieldStateHook<
30+
"certificate_desired"
31+
> = (value, onUpdate) => {
32+
const [certificateDesired, setCertificateDesired] = React.useState<State>(
33+
value || "",
34+
)
35+
36+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
37+
setCertificateDesired(() => {
38+
return event.target.value as CertificateDesiredEnum
39+
})
40+
}
41+
42+
React.useEffect(() => {
43+
onUpdate("certificate_desired", certificateDesired)
44+
}, [certificateDesired, onUpdate])
45+
46+
return [certificateDesired, handleChange]
47+
}
48+
49+
const CertificateChoiceBoxField: React.FC<Props> = ({
50+
value,
51+
label,
52+
onUpdate,
53+
}) => {
54+
const [certificateDesired, handleChange] = useCertificateChoiceState(
55+
value,
56+
onUpdate,
57+
)
58+
59+
return (
60+
<>
61+
{label}
62+
<Container maxWidth="md">
63+
<Grid
64+
container
65+
spacing={2}
66+
justifyContent="center"
67+
columns={{
68+
md: 12,
69+
xs: 4,
70+
}}
71+
>
72+
{Object.values(CertificateDesiredEnum).map((value, index) => {
73+
const checked = value === certificateDesired
74+
return (
75+
<Grid item xs={4} key={index}>
76+
<ChoiceBox
77+
type="radio"
78+
label={CertificateDesiredEnumDescriptions[value]}
79+
value={value}
80+
onChange={handleChange}
81+
checked={checked}
82+
/>
83+
</Grid>
84+
)
85+
})}
86+
</Grid>
87+
</Container>
88+
</>
89+
)
90+
}
91+
92+
const RadioContainer = styled.div(({ theme }) => ({
93+
[theme.breakpoints.up("md")]: {
94+
"& .MuiFormGroup-root": {
95+
flexDirection: "row",
96+
},
97+
},
98+
}))
99+
100+
const CertificateRadioChoiceField: React.FC<Props> = ({
101+
value,
102+
label,
103+
onUpdate,
104+
}) => {
105+
const [certificateDesired, handleChange] = useCertificateChoiceState(
106+
value,
107+
onUpdate,
108+
)
109+
110+
return (
111+
<RadioContainer>
112+
<RadioChoiceField
113+
name="certificate_desired"
114+
choices={CHOICES}
115+
label={label}
116+
value={certificateDesired}
117+
onChange={handleChange}
118+
/>
119+
</RadioContainer>
120+
)
121+
}
122+
123+
export { CertificateChoiceBoxField, CertificateRadioChoiceField }
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from "react"
2+
3+
import {
4+
Select,
5+
MenuItem,
6+
FormControl,
7+
FormLabel,
8+
SelectChangeEvent,
9+
} from "ol-components"
10+
import { CurrentEducationEnum, CurrentEducationEnumDescriptions } from "api/v0"
11+
12+
import { ProfileFieldUpdateProps } from "./types"
13+
14+
const EducationLevelSelect: React.FC<
15+
ProfileFieldUpdateProps<"current_education">
16+
> = ({ label, value, onUpdate }) => {
17+
const [educationLevel, setEducationLevel] = React.useState<
18+
CurrentEducationEnum | ""
19+
>(value || "")
20+
21+
const handleChange = (event: SelectChangeEvent<typeof educationLevel>) => {
22+
setEducationLevel(event.target.value as CurrentEducationEnum)
23+
}
24+
25+
React.useEffect(() => {
26+
onUpdate("current_education", educationLevel)
27+
}, [educationLevel, onUpdate])
28+
29+
return (
30+
<FormControl component="fieldset" fullWidth>
31+
<FormLabel component="label">{label}</FormLabel>
32+
<Select displayEmpty onChange={handleChange} value={educationLevel}>
33+
<MenuItem disabled value="">
34+
<em>Please select</em>
35+
</MenuItem>
36+
{Object.values(CurrentEducationEnum).map((value, index) => {
37+
return (
38+
<MenuItem value={value} key={index}>
39+
{CurrentEducationEnumDescriptions[value]}
40+
</MenuItem>
41+
)
42+
})}
43+
</Select>
44+
</FormControl>
45+
)
46+
}
47+
48+
export { EducationLevelSelect }
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import React from "react"
2+
import {
3+
styled,
4+
Checkbox,
5+
CheckboxChoiceBoxField,
6+
ChoiceBoxGridProps,
7+
FormLabel,
8+
FormControl,
9+
} from "ol-components"
10+
import { GoalsEnum, GoalsEnumDescriptions, PatchedProfileRequest } from "api/v0"
11+
12+
import type { ProfileFieldUpdateProps, ProfileFieldUpdateFunc } from "./types"
13+
14+
const CHOICES = [
15+
{
16+
value: GoalsEnum.CareerGrowth,
17+
label: GoalsEnumDescriptions[GoalsEnum.CareerGrowth],
18+
description: "Looking for career growth through new skills & certification",
19+
},
20+
{
21+
value: GoalsEnum.SupplementalLearning,
22+
label: GoalsEnumDescriptions[GoalsEnum.SupplementalLearning],
23+
description: "Additional learning to integrate with degree work",
24+
},
25+
{
26+
value: GoalsEnum.JustToLearn,
27+
label: GoalsEnumDescriptions[GoalsEnum.JustToLearn],
28+
description: "I just want more knowledge",
29+
},
30+
]
31+
32+
type State = GoalsEnum[]
33+
34+
const useGoalsChoice = (
35+
value: PatchedProfileRequest["goals"],
36+
onUpdate: ProfileFieldUpdateFunc<"goals">,
37+
): [State, React.ChangeEventHandler] => {
38+
const [goals, setGoals] = React.useState<State>(value || [])
39+
40+
const handleToggle = (event: React.SyntheticEvent) => {
41+
setGoals((prevGoals) => {
42+
const target = event.target as HTMLInputElement
43+
if (target.checked) {
44+
return [...prevGoals, target.value as GoalsEnum]
45+
} else {
46+
return prevGoals.filter((goal) => goal !== target.value)
47+
}
48+
})
49+
}
50+
51+
React.useEffect(() => {
52+
onUpdate("goals", goals)
53+
}, [goals, onUpdate])
54+
55+
return [goals, handleToggle]
56+
}
57+
58+
function GoalsChoiceBoxField({
59+
value,
60+
label,
61+
gridProps,
62+
gridItemProps,
63+
onUpdate,
64+
}: ProfileFieldUpdateProps<"goals"> & ChoiceBoxGridProps) {
65+
const [goals, handleToggle] = useGoalsChoice(value, onUpdate)
66+
67+
return (
68+
<CheckboxChoiceBoxField
69+
label={label}
70+
choices={CHOICES}
71+
values={goals}
72+
onChange={handleToggle}
73+
gridProps={Object.assign(
74+
{
75+
justifyContent: "center",
76+
columns: {
77+
lg: 12,
78+
xs: 4,
79+
},
80+
maxWidth: "md",
81+
margin: "0 auto",
82+
},
83+
gridProps,
84+
)}
85+
gridItemProps={Object.assign({ xs: 4 }, gridItemProps)}
86+
/>
87+
)
88+
}
89+
90+
const CheckboxContainer = styled.div(({ theme }) => ({
91+
display: "flex",
92+
flexDirection: "column",
93+
flexWrap: "wrap",
94+
"& label": {
95+
flexShrink: 0,
96+
},
97+
[theme.breakpoints.up("md")]: {
98+
display: "flex",
99+
flexDirection: "row",
100+
"& label": {
101+
marginRight: theme.spacing(3),
102+
},
103+
},
104+
}))
105+
106+
function GoalsCheckboxChoiceField({
107+
label,
108+
value,
109+
onUpdate,
110+
}: ProfileFieldUpdateProps<"goals">) {
111+
const [goals, handleToggle] = useGoalsChoice(value, onUpdate)
112+
113+
return (
114+
<FormControl component="fieldset" sx={{ width: "100%" }}>
115+
<FormLabel component="legend" sx={{ width: "100%" }}>
116+
{label}
117+
</FormLabel>
118+
<CheckboxContainer>
119+
{CHOICES.map((choice) => {
120+
return (
121+
<label key={choice.value}>
122+
<Checkbox
123+
edge="start"
124+
checked={goals.indexOf(choice.value) !== -1}
125+
onChange={handleToggle}
126+
value={choice.value}
127+
disableRipple
128+
/>
129+
{choice.label}
130+
</label>
131+
)
132+
})}
133+
</CheckboxContainer>
134+
</FormControl>
135+
)
136+
}
137+
export { GoalsChoiceBoxField, GoalsCheckboxChoiceField }

0 commit comments

Comments
 (0)