Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

W10 | project-survey-vite | Xing Y. & Erika O. #83

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
55c0537
add - collaborator with Erika
xingyin2024 Oct 15, 2024
b0f1739
add - branch flow for test
xingyin2024 Oct 15, 2024
2c724a2
add - create components file and Header/QuestionOne/Result.jsx
xingyin2024 Oct 15, 2024
e1aa9f4
update - add content for test in all jsx
xingyin2024 Oct 15, 2024
19a8b83
update - style for body and text
xingyin2024 Oct 15, 2024
4d15b89
Merge branch 'xing' into dev
xingyin2024 Oct 15, 2024
f5d0241
update - content in header
xingyin2024 Oct 15, 2024
11fe1fd
Merge branch 'dev' into xing
xingyin2024 Oct 15, 2024
42c14ce
update - header
xingyin2024 Oct 15, 2024
2a0b309
Update: header
Oct 15, 2024
8e2bb34
add & update - set up the foundation for multistepform
xingyin2024 Oct 15, 2024
ee79660
add - button in Welcome
xingyin2024 Oct 15, 2024
7293ee5
add - comment in Welcome
xingyin2024 Oct 15, 2024
d7ff288
update Welcome
xingyin2024 Oct 15, 2024
f605497
pull from dev for setted up of foundation
xingyin2024 Oct 15, 2024
0e48c89
ClassNames for qa and styling
Oct 16, 2024
f23bc4f
update - Q1 and MultiStepForm
xingyin2024 Oct 16, 2024
4a008e1
update - content of Q2 & Q3 and fix some small bug in MultiStepForm
xingyin2024 Oct 16, 2024
ea7b19a
[XY] merge and fix conflict in jsx between branches erika and xing
xingyin2024 Oct 16, 2024
629ac4d
[XY]update - put welcome into multistepform and update APP
xingyin2024 Oct 16, 2024
2a55d13
[XY] debug - modified the currentstep to show the welcome first and t…
xingyin2024 Oct 16, 2024
e460718
[XY]update - delete name attribute in Q1 input
xingyin2024 Oct 17, 2024
c9ebd66
[XY]update - add className for question&input&button and adjust struc…
xingyin2024 Oct 17, 2024
0d90a06
[XY]update - add className for previous button
xingyin2024 Oct 17, 2024
f333938
[XY]update - modify input text in Q3 and alert in MSF
xingyin2024 Oct 17, 2024
a64d2cd
update
xingyin2024 Oct 17, 2024
10a6950
merge conflicts
Oct 17, 2024
745fc27
update q3, q4, q5
Oct 17, 2024
f3c58cd
new file for q4, q4new
Oct 17, 2024
b363a98
update: styling
Oct 17, 2024
979fa8f
update: styling
Oct 18, 2024
91f505c
update: styling buttons mobil, desktop
Oct 19, 2024
c1f36fb
[XY]update - button style, page height and Q4 file name
xingyin2024 Oct 19, 2024
4b392ac
update media query logic and fix small bug with text and button posit…
xingyin2024 Oct 19, 2024
265d323
add netlift link and collaborators in PR md
xingyin2024 Oct 19, 2024
0bf4049
update title in html
xingyin2024 Oct 19, 2024
4d68b8d
update radio button style
xingyin2024 Oct 19, 2024
73b4394
clean up the code
xingyin2024 Oct 21, 2024
0036528
clean up, add validation status for buttons and alert message for eac…
xingyin2024 Oct 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Survey - Project - Week 6</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Survey - Project - Week 10</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>

</html>
5 changes: 2 additions & 3 deletions pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
## Netlify link
Add your Netlify link here.
PS. Don't forget to add it in your readme as well.
https://survey-personality.netlify.app

## Collaborators
Add any collaborators here, as well as in the title of the PR.
Xing Y. & Erika O.
11 changes: 10 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import "./index.css";

import { MultiStepForm } from "./components/MultiStepForm";

export const App = () => {
return <div>Find me in src/app.jsx!</div>;
return (
<>
<MultiStepForm />
</>

);
};
216 changes: 216 additions & 0 deletions src/components/MultiStepForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/**
* This component represents a multi-step form that collects user information such as preference of pet & season, personality, favorite music & artist. It uses React's useState hook to manage form data and track the current step.
* The form has validation for each step to ensure the user enters valid data before moving to the next step.
* Once submitted, the form data is displayed, and the user can choose to reset the form and start over.
* This component demonstrates step-by-step form handling with React state management.
*/

import { useState } from "react";
import "./Questions.css";

import { Welcome } from "./Welcome";
import { PetPreference } from "./Q1";
import { SeasonPreference } from "./Q2";
import { Personality } from "./Q3";
import { TimePreference } from "./Q4"
import { FavoriteMusic } from "./Q5";
import { Artist } from "./Q6";



// Component: MultiStepForm
export const MultiStepForm = () => {
// State to store form data for each field (petPreference, seasonPreference, personality,...)
const [formData, setFormData] = useState({
petPreference: "",
seasonPreference: "",
personality: "",
timePreference: "",
favoriteMusic: "",
favoriteArtist: "",
});

// State to track whether the form has been submitted
const [formSubmitted, setFormSubmitted] = useState(false);

// State to track the current step (0 for welcome screen and 1-6 for questions)
const [currentStep, setCurrentStep] = useState(0);

// ---
const [validationMessage, setValidationMessage] = useState("");
// ---

// Function to update form data based on the provided field (key) and value
const updateFormData = (field, value) => {
setFormData((previous) => ({ ...previous, [field]: value }));
setValidationMessage("");
};

// Function to move to the first step in the form
const startForm = () => {
setCurrentStep(1); // Set current step to 1 when the form starts
};


// Function to determine personality type based on the slider value
const getPersonalityType = (value) => {
if (value < 50) {
return `
you are ${100 - value}% extroverted.
`;
} else if (value > 50) {
return `
you are ${value}% introverted.
`;
} else {
return `
you are equally extroverted and introverted.
`;
}
}

// Function to combine validation and checks current step and provides feedback if invalid
const validateStep = () => {
switch (currentStep) {
case 1:
return formData.petPreference.trim() === "" ? "Please select dog or cat or none!" : null;
case 2:
return formData.seasonPreference.trim() === "" ? "Please select your favorite season!" : null;
case 3:
return formData.personality.trim() === "" ? "Please rate your personality!" : null;
case 4:
return formData.timePreference.trim() === "" ? "Please select what time of day suits you!" : null;
case 5:
return formData.favoriteMusic.trim() === "" ? "Please select your favorite type of music!" : null;
case 6:
return formData.favoriteArtist.trim() === "" ? "Please select your favorite artist!" : null;
default:
return null;
}
};

// Function to move to the next step in the form
const nextStep = () => {
const validationMessage = validateStep();

!validationMessage ? setCurrentStep(currentStep + 1) : setValidationMessage(validationMessage);
}

// Function to move back to the previous step in the form
const prevStep = () => {
if (currentStep > 1) setCurrentStep(currentStep - 1);
};

// Function to submit the form, log the form data, and display it
const submitForm = () => {
setFormSubmitted(true);

const formattedData = `
Pet: ${formData.petPreference}
Season: ${formData.seasonPreference}
Personality: ${formData.personality}
Time of day: ${formData.timePreference}
Favorite Music: ${formData.favoriteMusic}
Favorite Artist: ${formData.favoriteArtist}
`;

alert(formattedData);
};

// Function to reset the form data and start the process over
const startOver = () => {
setFormData({
petPreference: "",
seasonPreference: "",
personality: "",
timePreference: "",
favoriteMusic: "",
favoriteArtist: "",
});
setFormSubmitted(false);
setCurrentStep(0);
setValidationMessage("");
};

// ---
// ---

return (
<div>
{/* Display the welcome page and the form data after submission */}
{formSubmitted ? (
<div className="result-form">
<h2>Thank you for taking the survey and here is your answear!</h2>
<hr />
<p>You prefer {formData.petPreference}</p>
<p>You favorite season is {formData.seasonPreference}</p>
<p>And you think {getPersonalityType(formData.personality)}</p>
<p>How fun it is! Same like me 🌞 </p>
<p>Time of day: {formData.timePreference}</p>
<p>Favorite Music: {formData.favoriteMusic}</p>
<p>Favorite Artist: {formData.favoriteArtist}</p>
<hr />
<h3>Hope you enjoy the survey</h3>
<p>❤️❤️❤️</p>
<button className="button-header" onClick={startOver}>Start Over</button>
</div>
) : (
currentStep === 0 && <Welcome startForm={startForm} />
)}

{currentStep === 1 && (
<PetPreference value={formData.petPreference} updateFormData={updateFormData} />
)}

{currentStep === 2 && (
<SeasonPreference value={formData.seasonPreference} updateFormData={updateFormData} />
)}

{currentStep === 3 && (
<Personality value={formData.personality} updateFormData={updateFormData} />
)}

{currentStep === 4 && (
<TimePreference value={formData.timePreference} updateFormData={updateFormData} />
)}

{currentStep === 5 && (
<FavoriteMusic value={formData.favoriteMusic} updateFormData={updateFormData} />
)}

{!formSubmitted && currentStep === 6 && (
<Artist value={formData.favoriteArtist} updateFormData={updateFormData} />
)}

{/* Navigation buttons for moving between steps */}
{!formSubmitted && currentStep > 0 && (
<div className="cta-box">
{currentStep > 1 && <button className="button-qa prev-step" onClick={prevStep}>Previous</button>}

{currentStep < 6 ? (
<button
className={`button-qa ${validateStep() ? "disabled-btn" : "next-step"}`} onClick={nextStep}
disabled={!!validationMessage}
>
Next
</button>
) : (
<button
className={`button-qa ${validateStep() ? "disabled-btn" : "submit-btn"}`}
onClick={submitForm}
disabled={!!validationMessage}
>
Submit Form
</button>
)}


</div>

)}
{validationMessage && <p className="validation-message">{validationMessage}</p>}
</div>

);

};
65 changes: 65 additions & 0 deletions src/components/Q1.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* This component is used to collect and update the user's pet preference in a multi-step form.
* The selected option is stored in formData.petPreference.
* It demonstrates how to handle input type Radio in React using the useState hook indirectly (from a parent component).
* The PetPreference component receives the current petPreference value and an update function as props,
* and updates the form data using radio buttons to let the user choose between "Dog" and "Cat."
* Each radio button is associated with a unique id and has proper labels for accessibility.
* Both radio buttons use the same name ("petPreference"), which groups them together,
* ensuring only one radio button can be selected at a time.
*/

export const PetPreference = ({ updateFormData, value }) => {
// Function to handle user input and update the form's petPreference field
const handlePetChange = (e) => {
// Call updateFormData to update the "petPreference" field with the input's current value
updateFormData("petPreference", e.target.value);
};

return (
<div className="border-box-qa">
<div className="qa-label flex-column">
<p>1. </p>
<p>Are you a dog or a cat person?</p>
</div>

<div className="qa-input flex-row">
<form className="flex-column">
{/* Radio button for Dog */}
<label className="radio-label" htmlFor="dog">
<input
type="radio"
id="dog"
value="dog"
checked={value === "dog"}
onChange={handlePetChange}
/>
<span>Dog</span>
</label>

<label className="radio-label" htmlFor="cat">
<input
type="radio"
id="cat"
value="cat"
checked={value === "cat"}
onChange={handlePetChange}
/>
<span>Cat</span>
</label>

<label className="radio-label" htmlFor="none">
<input
type="radio"
id="none"
value="none"
checked={value === "none"}
onChange={handlePetChange}
/>
<span>Neither</span>
</label>
</form>
</div>
</div>
);
};
37 changes: 37 additions & 0 deletions src/components/Q2.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* This component is used to collect and update the user's favorite season in a multi-step form.
* It demonstrates how to handle select dropdowns in React using the useState hook indirectly (from a parent component).
* The SeasonPreference component receives the current favorite season value and an update function as props, and updates the form data when the user selects an artist.
*/

export const SeasonPreference = ({ updateFormData, value }) => {
// Function to handle user input and update the form's age field
const handleSeasonChange = (e) => {
// Call updateFormData to update the "age" field with the input's current value
updateFormData("seasonPreference", e.target.value);
};

return (
<div className="border-box-qa">
<div className="qa-label flex-column">
<p>2. </p>
<p>Which season do you like most?</p>
</div>

<div className="qa-input flex-column">
<label htmlFor="season"> Choose a season:</label>
<select
id="season"
value={value}
onChange={handleSeasonChange}
>
<option value="">Select a season</option>
<option value="spring">Spring</option>
<option value="summer">Summer</option>
<option value="autumn">Autumn</option>
<option value="winter">Winter</option>
</select>
</div>
</div>
);
};
Loading