import React, { useState, useEffect } from "react";
import { FaMedal } from "react-icons/fa";
import axios from "axios";
import Apis from "../../APIs";
import { useAuth } from "../Auth/AuthContext";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import ToastWrapper from "../../../ToastWrapper";
import "react-toastify/dist/ReactToastify.css";
const See360Assessment = () => {
const { user, setUser } = useAuth();
const navigate = useNavigate();
const [questions, setQuestions] = useState([]);
const [answers, setAnswers] = useState([]);
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const [result, setResult] = useState(false);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [assessmentId, setAssessmentId] = useState(null);
const [redirectPage, setRedirectPage] = useState(null);
useEffect(() => {
const fetchQuestions = async () => {
try {
const response = await axios.get(Apis.See360_QUESTION_API);
const fetchedQuestions = response.data;
const savedProgress = JSON.parse(localStorage.getItem("assessmentProgress")) || {};
const { savedAnswers = [], savedQuestionIndex = 0 } = savedProgress;
setQuestions(fetchedQuestions);
setAnswers(savedAnswers.length ? savedAnswers : fetchedQuestions.map(() => null));
setCurrentQuestionIndex(savedQuestionIndex);
setLoading(false);
} catch (err) {
console.error("Error fetching questions:", err);
setError("Failed to load questions. Please try again later.");
setLoading(false);
}
};
fetchQuestions();
}, []);
const saveProgress = (newAnswers, newQuestionIndex) => {
const progress = {
savedAnswers: newAnswers,
savedQuestionIndex: newQuestionIndex,
};
localStorage.setItem("assessmentProgress", JSON.stringify(progress));
};
const handleOptionSelect = (oIndex) => {
const qIndex = currentQuestionIndex;
const optionId = questions[qIndex].options[oIndex]._id;
const newAnswers = [...answers];
newAnswers[qIndex] = optionId;
setAnswers(newAnswers);
saveProgress(newAnswers, qIndex);
};
const handleNextQuestion = () => {
if (!answers[currentQuestionIndex]) {
toast.error("Please select an option before moving to the next question.");
return;
}
const nextIndex = currentQuestionIndex + 1;
if (nextIndex < questions.length) {
setCurrentQuestionIndex(nextIndex);
saveProgress(answers, nextIndex);
} else {
handleSubmit();
}
};
const handleSubmit = async () => {
setLoading(true);
const formattedResponses = questions.map((question, qIndex) => ({
questionId: question._id,
answered: {
optionId: answers[qIndex],
},
}));
const payload = {
userId: user._id,
responses: formattedResponses,
};
try {
const response = await axios.post(Apis.See360_ASSESSMENT_API, payload);
const recordId = response.data._id;
setAssessmentId(recordId);
let calculatedRedirectPage = "/Pdf";
setRedirectPage(calculatedRedirectPage);
if (user.feedbackStatus === "newUser") {
const updatedUserData = { feedbackStatus: "feedbackPending" };
await axios.put(`${Apis.See360_USER_API}/${user._id}`, updatedUserData);
}
const pdfName = calculatedRedirectPage.replace("/", "");
const updatedPdfAccess = [...user.pdfAccess, pdfName];
setUser({ ...user, pdfAccess: updatedPdfAccess });
await axios.put(
`${Apis.See360_USER_API}/${user._id}`,
{ pdfAccess: updatedPdfAccess },
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
}
);
localStorage.removeItem("assessmentProgress");
} catch (error) {
console.error("Error during assessment submission process:", error);
toast.error("An error occurred while submitting the assessment. Please try again.");
} finally {
setResult(true);
setLoading(false);
}
};
const handleOkClick = async () => {
const getUser = await axios.get(`${Apis.See360_USER_API}/${user._id}`, {
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
});
const latestUserData = getUser.data;
setUser(latestUserData);
if (redirectPage) {
navigate(redirectPage, { state: { assessmentId } });
} else {
toast.error("PDF page could not be determined.");
}
};
if (loading) {
return (
<div className="min-h-screen w-full flex items-center justify-center bg-primary-gradient">
<l-infinity
size="200"
stroke="4"
stroke-length="0.15"
bg-opacity="0.1"
speed="1.3"
color="white"
></l-infinity>
</div>
);
}
if (error) {
return (
<section className="min-h-screen w-full bg-primary-gradient flex items-center justify-center">
<div className="text-white text-2xl">{error}</div>
</section>
);
}
return (
<>
<section className="min-h-screen w-full bg-primary-gradient flex flex-col items-center justify-center p-5">
{result ? (
<div className="min-h-[400px] w-80 md:w-[400px] rounded-lg bg-secondary p-5 flex items-center justify-center flex-col gap-5">
<h2 className="text-3xl text-center">
Thank you for giving the assessment
</h2>
<h2 className="text-3xl text-center">To See Your Result Click Ok</h2>
<FaMedal className="text-4xl text-yellow-400" />
<button
onClick={handleOkClick}
className="h-10 w-full rounded-lg bg-green-500 text-white hover:bg-green-700"
>
Ok
</button>
</div>
) : (
<>
<div className="w-screen max-w-[90%] md:max-w-[900px] rounded-lg bg-secondary p-5">
<h2 className="font-bold text-xl flex items-center justify-center">
SEE 360 Biz Scan Assessment
</h2>
</div>
<div className="w-screen max-w-[90%] md:max-w-[900px] mt-5 rounded-lg bg-secondary p-5">
<div className="text-lg text-black font-bold mb-3 flex items-center justify-center">
{currentQuestionIndex + 1} / {questions.length}
</div>
<h3 className="font-semibold text-lg mb-3">
{currentQuestionIndex + 1}. {questions[currentQuestionIndex].mainQuestion}
</h3>
<div className="flex flex-col gap-3">
{questions[currentQuestionIndex].options.map((option, oIndex) => (
<div
key={option._id}
className={`cursor-pointer p-3 border rounded-lg ${
answers[currentQuestionIndex] === option._id
? "bg-green-500 text-white"
: "hover:bg-gray-100"
}`}
onClick={() => handleOptionSelect(oIndex)}
>
{option.option}
</div>
))}
</div>
<div className="mt-5 flex justify-end">
<button
onClick={handleNextQuestion}
className="h-10 w-32 rounded-lg bg-green-500 text-white hover:bg-green-700"
>
Next
</button>
</div>
</div>
</>
)}
</section>
<ToastWrapper />
</>
);
};
export default See360Assessment;
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter