Skip to content

Commit fce573e

Browse files
entire compare page
1 parent e4db213 commit fce573e

7 files changed

Lines changed: 481 additions & 61 deletions

File tree

frontend/package-lock.json

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"@testing-library/jest-dom": "^5.17.0",
1111
"@testing-library/react": "^13.4.0",
1212
"@testing-library/user-event": "^13.5.0",
13+
"axios": "^1.6.8",
1314
"dotenv": "^16.4.5",
1415
"framer-motion": "^11.0.20",
1516
"react": "^18.2.0",
Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
import React, { useState, useEffect } from "react";
2+
import {
3+
Box,
4+
Text,
5+
Checkbox,
6+
CheckboxGroup,
7+
Button,
8+
VStack,
9+
Slide,
10+
HStack,
11+
Image,
12+
Progress,
13+
} from "@chakra-ui/react";
14+
import "./quiz.css";
15+
import data from "../data.json";
16+
17+
const ColorAnalysis = () => {
18+
const [selectedOptions, setSelectedOptions] = useState([]);
19+
const [recommended, setRecommended] = useState([]);
20+
const [slideDirection, setSlideDirection] = useState("left");
21+
const titleList = [
22+
"Access your color analysis",
23+
"Assess your skin's sebum production",
24+
"Assess your skin's underlying inflammation",
25+
"Lifestyle habits",
26+
"Suncare Habits",
27+
"Check all the following concerns that you would like to address",
28+
"Let's help you find the right sunscreen",
29+
"Help us color match your sunscreen",
30+
];
31+
const questionList = [
32+
"[Question 1]",
33+
"Check the color that is closest to your natural hair color",
34+
"Check all the following that you have had in the last 4 weeks: (Multiple answers allowed)",
35+
"Check all that apply to you. (Multiple answers allowed)",
36+
"Check all that apply to you. (Multiple answers allowed)",
37+
"If you have any other issues you would like us to recommend products for, please select them here. You can scroll down and select 'None of the above' if nothing applies",
38+
"The most important step to prevent aging is wearing sunscreen on a daily basis and re-applying through the day, even when indoors.",
39+
"What tint of daily facial sunscreen do you prefer?",
40+
];
41+
const answersList = [
42+
[
43+
"I can use any soap to wash my face without developing dryness.",
44+
"I do not apply any products to my facial skin after cleansing.",
45+
"I never or only occasionally apply a moisturizer.",
46+
"I apply a moisturizer to my face once a day.",
47+
"I apply a moisturizer to my face twice a day.",
48+
],
49+
[
50+
"My facial skin is rough or dry.",
51+
"My facial skin is oily in some areas.",
52+
"My face is very oily.",
53+
"My face is uncomfortable if I do not use a moisturizer.",
54+
"I like the feel of heavy creams and/or oil on my skin.",
55+
"None of the above",
56+
],
57+
[
58+
"Acne (pimples)",
59+
"Facial redness and/or flushing",
60+
"Stinging or burning",
61+
"A rash with itching, scaling and redness",
62+
"Irritation from shaving the face",
63+
"None of the above",
64+
],
65+
[
66+
"I am exposed to second hand smoke on a weekly basis.",
67+
"I currently smoke cigarettes or cigars",
68+
"I often get less than 7 hours of sleep a night.",
69+
"I feel stress at least 2 hours a day.",
70+
"I eat sugary foods over 3 times a week.",
71+
"I exercise less than 3 hours a week.",
72+
"I do not eat fruit or vegetables every day.",
73+
"None of the above",
74+
],
75+
[
76+
"I have been to a tanning bed more than 3 times in my life.",
77+
"I am exposed to the sun for over 3 hours a week.",
78+
"I spend over 3 hrs/wk near a window during daylight (including driving).",
79+
"My face has been sunburned and peeled more than twice in my life.",
80+
"I do not take daily antioxidant supplements like vitamin E and C.",
81+
"One of my parents has more wrinkles than others their age.",
82+
"I do not wear sunscreen every day",
83+
"I do not wear sunscreen during outdoor activities",
84+
"None of the above",
85+
],
86+
[
87+
"Dandruff or itching/flaking scalp",
88+
"Dry skin",
89+
"Eczema",
90+
"Hair loss or thinning hair",
91+
"Psoriasis",
92+
"Shaving irritation",
93+
"Acne Scars",
94+
"Broken blood vessels on face or body",
95+
"Cellulite",
96+
"Loss of fullness",
97+
"Sagging skin",
98+
"Stretch marks",
99+
"Wrinkles",
100+
"None of the above",
101+
],
102+
[
103+
"Chemical Block (Less White)",
104+
"Chemical Free Physical Block (Zinc Oxide, May Be White)",
105+
"No Preference",
106+
],
107+
["Tinted (Has Color)", "Untinted (White Or Clear)", "No Preference"],
108+
];
109+
110+
const [currentIndex, setIndex] = useState(0);
111+
112+
const [questionStates, setQuestionStates] = useState([
113+
"green",
114+
"unseen",
115+
"unseen",
116+
"unseen",
117+
"unseen",
118+
"unseen",
119+
"unseen",
120+
"unseen",
121+
]);
122+
123+
const handleOptionChange = (option) => {
124+
const isSelected = selectedOptions.includes(option);
125+
setSelectedOptions(
126+
isSelected
127+
? selectedOptions.filter((o) => o !== option)
128+
: [...selectedOptions, option]
129+
);
130+
};
131+
132+
const handleContinue = () => {
133+
setSlideDirection("slide-out");
134+
setTimeout(() => {
135+
setSlideDirection("slide-in");
136+
setSelectedOptions([]);
137+
138+
const updatedStates = [...questionStates];
139+
updatedStates[currentIndex + 1] = "green";
140+
for (let i = 0; i < currentIndex + 1; i++) {
141+
updatedStates[i] = "light-green";
142+
}
143+
setIndex(currentIndex + 1);
144+
145+
setQuestionStates(updatedStates);
146+
}, 500);
147+
};
148+
const [slideProgress, setSlideProgress] = useState(0);
149+
150+
useEffect(() => {
151+
const handleSlideProgress = () => {
152+
const slideInElement = document.querySelector(".slide-out");
153+
if (slideInElement) {
154+
const slideInRect = slideInElement.getBoundingClientRect();
155+
const slideInWidth = slideInRect.width;
156+
const windowWidth = window.innerWidth;
157+
const progress = (windowWidth - slideInWidth) / windowWidth;
158+
setSlideProgress(progress);
159+
}
160+
};
161+
162+
window.addEventListener("resize", handleSlideProgress);
163+
handleSlideProgress();
164+
165+
return () => {
166+
window.removeEventListener("resize", handleSlideProgress);
167+
};
168+
}, []);
169+
170+
const buttonOpacity = slideDirection === "slide-out" ? 0 : 1;
171+
172+
function displayQuestions(index) {
173+
console.log(index);
174+
const answers = answersList[index];
175+
176+
// Calculate the number of answers per column based on the total number of answers
177+
178+
const columns = Math.ceil(answers.length / 6);
179+
const answersPerColumn = Math.ceil(answers.length / columns);
180+
181+
// Create an array of buttons for each column
182+
const buttons = answers.map((answer, i) => (
183+
<Button
184+
backgroundColor={
185+
selectedOptions.includes("option" + i) ? "beige" : "whitesmoke"
186+
}
187+
_hover={{
188+
backgroundColor: "beige",
189+
borderColor: "brown",
190+
}}
191+
onClick={() => handleOptionChange("option" + i)}
192+
borderRadius="md"
193+
borderColor={selectedOptions.includes("option" + i) ? "beige" : "grey"}
194+
borderWidth={1.5}
195+
px={4}
196+
py={6}
197+
width={answers.length > 6 ? "100%" : "700px"}
198+
style={{ opacity: buttonOpacity }}
199+
>
200+
<Text color="black">{answer}</Text>
201+
</Button>
202+
));
203+
204+
if (answers.length > 6) {
205+
return (
206+
<HStack spacing={3}>
207+
{Array(columns)
208+
.fill()
209+
.map((_, i) => (
210+
<VStack key={i}>
211+
{buttons.slice(
212+
i * answersPerColumn,
213+
(i + 1) * answersPerColumn
214+
)}
215+
</VStack>
216+
))}
217+
</HStack>
218+
);
219+
}
220+
221+
// Render buttons in a single column if there are 6 or fewer answers
222+
return <VStack spacing={4}>{buttons}</VStack>;
223+
}
224+
225+
function getRec() {
226+
const productNumber = Math.floor(Math.random() * data.length);
227+
setRecommended(data[productNumber]);
228+
// return (
229+
// <Box flex="1" height="100%">
230+
// <Image mt={5} ml={5} src={recommended.url} alt="Dan Abramov" />
231+
// </Box>
232+
// );
233+
}
234+
235+
useEffect(() => {
236+
if (currentIndex === 8) {
237+
getRec();
238+
}
239+
}, [currentIndex]);
240+
241+
// function displayProgressCircles() {
242+
// const circles = [];
243+
// for (let i = 0; i < 6; i++) {
244+
// circles.push(
245+
// <Box
246+
// key={i}
247+
// w="50px" // Width of the circle
248+
// h="50px" // Height of the circle
249+
// borderRadius="50%" // Makes the box shape circular
250+
// bg={
251+
// i > currentIndex
252+
// ? "gray"
253+
// : i === currentIndex
254+
// ? "green"
255+
// : "light-green"
256+
// } // Background color based on condition
257+
// />
258+
// );
259+
// }
260+
// return circles;
261+
// }
262+
263+
return (
264+
<HStack ml={5} mr={5} w="100%">
265+
<Box mt={-14} w="100%">
266+
<Text mb={4}>{titleList[currentIndex]}</Text>
267+
<Text mb={4}>{questionList[currentIndex]}</Text>
268+
<CheckboxGroup
269+
colorScheme="green"
270+
value={selectedOptions}
271+
onChange={(values) => setSelectedOptions(values)}
272+
>
273+
<VStack
274+
position="relative"
275+
className={slideDirection}
276+
style={{ zIndex: 0 }}
277+
>
278+
{" "}
279+
{currentIndex < 8 ? (
280+
<CheckboxGroup
281+
colorScheme="green"
282+
value={selectedOptions}
283+
onChange={(values) => setSelectedOptions(values)}
284+
>
285+
<VStack
286+
position="relative"
287+
className={slideDirection}
288+
style={{ zIndex: 0 }}
289+
>
290+
{displayQuestions(currentIndex)}
291+
</VStack>
292+
</CheckboxGroup>
293+
) : (
294+
<Box flex="1" height="100%">
295+
{recommended && (
296+
<Image
297+
mt={5}
298+
ml={5}
299+
src={recommended.url}
300+
alt="Recommended Product"
301+
/>
302+
)}
303+
</Box>
304+
)}
305+
</VStack>
306+
</CheckboxGroup>
307+
{currentIndex < 8 && (
308+
<Button
309+
position="absolute"
310+
colorScheme="blackAlpha"
311+
onClick={handleContinue}
312+
borderRadius={"25px"}
313+
mt={"30px"}
314+
>
315+
{currentIndex < 7 ? "CONTINUE" : "SUBMIT"}
316+
</Button>
317+
)}
318+
</Box>
319+
<VStack ml={4} spacing={4} style={{ zIndex: 1 }}>
320+
{questionStates.map((state, index) => (
321+
<Box key={index} className={`circle ${state}`} />
322+
))}
323+
/
324+
</VStack>
325+
</HStack>
326+
);
327+
};
328+
329+
export default ColorAnalysis;

0 commit comments

Comments
 (0)