From 7248fa9b562267cef8e50b8feb98fc7ceb79975a Mon Sep 17 00:00:00 2001 From: kushwahramkumar2003 Date: Wed, 13 Dec 2023 01:28:48 +0530 Subject: [PATCH 1/3] Refactor code for better performance --- public/graduate.svg | 20 +++ public/index.html | 29 +---- src/App.js | 4 +- src/Components/Admin/EditQuestion.jsx | 7 -- src/Components/Admin/QuestionCard.jsx | 44 +++++-- src/Components/Admin/UpdateQuestion.jsx | 159 ++++++++++++++++++++++++ src/index.css | 2 +- src/index.js | 5 +- src/pages/home/navbar.css | 8 +- src/pages/login/Login.css | 8 +- src/pages/login/login.jsx | 5 +- src/services/user.js | 3 + 12 files changed, 229 insertions(+), 65 deletions(-) create mode 100644 public/graduate.svg delete mode 100644 src/Components/Admin/EditQuestion.jsx create mode 100644 src/Components/Admin/UpdateQuestion.jsx diff --git a/public/graduate.svg b/public/graduate.svg new file mode 100644 index 0000000..3fc0f93 --- /dev/null +++ b/public/graduate.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/public/index.html b/public/index.html index af1beb7..a1a8b26 100755 --- a/public/index.html +++ b/public/index.html @@ -2,7 +2,7 @@ - + - - + - - Online-Quiz App + QuizGrad
- diff --git a/src/App.js b/src/App.js index adecdff..fb1290b 100755 --- a/src/App.js +++ b/src/App.js @@ -1,7 +1,7 @@ import Login from "./pages/login/login.jsx"; import Signup from "./pages/signup/SignUp.jsx"; import Home from "./pages/home/Home.jsx"; -import { Toaster } from "react-hot-toast"; + import { Routes, Route } from "react-router-dom"; import "./App.css"; @@ -21,7 +21,7 @@ function App() { }> }> - + ); } diff --git a/src/Components/Admin/EditQuestion.jsx b/src/Components/Admin/EditQuestion.jsx deleted file mode 100644 index 92fa452..0000000 --- a/src/Components/Admin/EditQuestion.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; - -const EditQuestion = () => { - return
EditQuestion
; -}; - -export default EditQuestion; diff --git a/src/Components/Admin/QuestionCard.jsx b/src/Components/Admin/QuestionCard.jsx index 1316aa9..2c38ec3 100644 --- a/src/Components/Admin/QuestionCard.jsx +++ b/src/Components/Admin/QuestionCard.jsx @@ -1,7 +1,9 @@ -import React from "react"; +import React, { useState } from "react"; import { useMutation } from "@tanstack/react-query"; import toast from "react-hot-toast"; import { deleteQuestionByQuizId } from "../../services/quiz"; +import Modal from "../modal/Modal"; +import UpdateQuestion from "./UpdateQuestion"; const QuestionCard = ({ question, @@ -11,6 +13,9 @@ const QuestionCard = ({ quizId, setRefresh, }) => { + const [isEdit, setIsEdit] = useState(false); + + const { mutate, isLoading } = useMutation({ mutationFn: ({ questionId, quizId }) => { return deleteQuestionByQuizId({ @@ -34,18 +39,33 @@ const QuestionCard = ({ }; return (
+ {isEdit && ( + + + + )}
-

{question}

-
    - {options.map((option, index) => { - return
  • {option}
  • ; - })} -
-

Answer: {answer}

-
-
- - +
+

{question}

+
    + {options.map((option, index) => { + return
  • {option}
  • ; + })} +
+

Answer: {answer}

+
+
+ + +
); diff --git a/src/Components/Admin/UpdateQuestion.jsx b/src/Components/Admin/UpdateQuestion.jsx new file mode 100644 index 0000000..a9f2edd --- /dev/null +++ b/src/Components/Admin/UpdateQuestion.jsx @@ -0,0 +1,159 @@ +import React, { useState, useEffect } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { useMutation } from "@tanstack/react-query"; +import toast from "react-hot-toast"; +import { updateQuestionByQuizId } from "../../services/quiz"; + +const UpdateQuestion = ({ + quizId, + setIsOpen, + question, + options: initialOptions, + questionId, + answer: initialAnswer, + setRefresh, + setIsEdit, +}) => { + const [selectedOption, setSelectedOption] = useState(initialAnswer || ""); + const [answer, setAnswer] = useState(initialAnswer || ""); + + const [options, setOptions] = useState( + initialOptions.map((value, id) => ({ id: id + 1, value })) + ); + + useEffect(() => { + setSelectedOption(initialAnswer); + setAnswer(initialAnswer); + setOptions(initialOptions.map((value, id) => ({ id: id + 1, value }))); + }, [initialAnswer, initialOptions]); + + const { mutate, isLoading } = useMutation({ + mutationFn: ({ question, options, correctAnswer, quizId }) => { + return updateQuestionByQuizId({ + question, + options, + correctAnswer, + quizId, + questionId, + }); + }, + onSuccess: (data) => { + toast.success("Question updated successfully"); + setIsEdit(false); + setRefresh((prev) => !prev); + console.log(data); + }, + onError: (error) => { + toast.error(error.message); + console.log(error); + }, + }); + + const { + control, + handleSubmit, + formState: { errors }, + register, + setValue, + } = useForm(); + + const handleOptionChange = (option, value) => { + setSelectedOption(option); + setAnswer(value); + }; + + const handleInputChange = (id, value) => { + setOptions((prevOptions) => + prevOptions.map((option) => + option.id === id ? { ...option, value } : option + ) + ); + + setValue(`option${id}`, value); + }; + + const onSubmit = (data) => { + const { question, option1, option2, option3, option4 } = data; + mutate({ + question, + options: [option1, option2, option3, option4], + correctAnswer: answer, + quizId, + questionId, + }); + }; + + return ( +
+

Edit Question

+
+
+
+ + + {errors.question &&

{errors.question.message}

} +
+
+ + {options.map((option) => ( +
+ ( + <> + + handleOptionChange(`option${option.id}`, field.value) + } + /> + + + handleInputChange(option.id, e.target.value) + } + /> + + )} + /> +
+ ))} +
+
+ + + {errors.answer &&

{errors.answer.message}

} +
+ + +
+
+
+ ); +}; + +export default UpdateQuestion; diff --git a/src/index.css b/src/index.css index 3ec2e08..08b5915 100755 --- a/src/index.css +++ b/src/index.css @@ -1,5 +1,5 @@ body { - margin: 0; + /* margin: 0; */ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; diff --git a/src/index.js b/src/index.js index b2f6ff7..cfaa3d2 100755 --- a/src/index.js +++ b/src/index.js @@ -3,8 +3,8 @@ import ReactDOM from "react-dom/client"; import { BrowserRouter } from "react-router-dom"; import { QueryClientProvider, QueryClient } from "@tanstack/react-query"; import { Provider } from "react-redux"; +import { Toaster } from "react-hot-toast"; import store from "./store"; - import "./index.css"; import App from "./App"; @@ -16,6 +16,9 @@ root.render( + diff --git a/src/pages/home/navbar.css b/src/pages/home/navbar.css index 15d35e3..c027dda 100644 --- a/src/pages/home/navbar.css +++ b/src/pages/home/navbar.css @@ -1,10 +1,4 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - overflow-x: hidden !important; - /* background-color: rgba(86, 83, 83, 0.216); */ -} + .landinpage{ height: 44rem; overflow-y: hidden; diff --git a/src/pages/login/Login.css b/src/pages/login/Login.css index 98f2af0..0940a4c 100644 --- a/src/pages/login/Login.css +++ b/src/pages/login/Login.css @@ -1,10 +1,4 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - font-family: 'Poppins', sans-serif; - overflow-x: hidden; -} + .main { height: 100vh; width: 100%; diff --git a/src/pages/login/login.jsx b/src/pages/login/login.jsx index 9f9343f..d24cecc 100644 --- a/src/pages/login/login.jsx +++ b/src/pages/login/login.jsx @@ -30,10 +30,11 @@ export default function Login() { }, onSuccess: (data) => { const { user } = data; - toast.success("Login successfully"); + dispatch(userActions.setUserInfo(data.user)); localStorage.setItem("account", JSON.stringify(data)); - + toast.success("Login successfully"); + // console.log("User.role : ", user.role); if (user.role === "USER") { diff --git a/src/services/user.js b/src/services/user.js index 38e546b..5a87abd 100644 --- a/src/services/user.js +++ b/src/services/user.js @@ -1,4 +1,5 @@ import axios from "axios"; +import { toast } from "react-hot-toast"; export const signup = async ({ name, email, password }) => { try { @@ -23,6 +24,8 @@ export const login = async ({ email, password }) => { email, password, }); + + return data; } catch (error) { console.log(error); From 8aba0206173859a5e1bb6c620f08398ee3b20a3f Mon Sep 17 00:00:00 2001 From: kushwahramkumar2003 Date: Wed, 13 Dec 2023 01:38:09 +0530 Subject: [PATCH 2/3] Add title, description, and category to quiz creation --- Server/src/controllers/quiz.controllers.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Server/src/controllers/quiz.controllers.js b/Server/src/controllers/quiz.controllers.js index 0c25694..ec941ce 100755 --- a/Server/src/controllers/quiz.controllers.js +++ b/Server/src/controllers/quiz.controllers.js @@ -4,7 +4,7 @@ const QuizResult = require("../models/Result.model.js"); const asyncHandler = require("./../services/asyncHandler.js"); /********************************************************************** - * @desc Create a quiz + * @desc Create a quiz with title, description and category * @route POST /api/v1/quiz/create * @access Private/Admin * @kushwahramkumar2003 @@ -281,9 +281,9 @@ exports.getQuizForAttempt = asyncHandler(async (req, res) => { }); /************************************************************************* - * @desc Submit quiz answers - * @route POST /api/quizzes/:id/submit - * @access Public + * @desc Submit quiz answers * + * @route POST /api/quizzes/:id/submit * + * @access Public * *************************************************************************/ exports.submitQuizAnswers = asyncHandler(async (req, res) => { const quizId = req.params.id; @@ -334,9 +334,9 @@ exports.submitQuizAnswers = asyncHandler(async (req, res) => { }); /************************************************************************* - * @desc Get quiz results - * @route GET /api/quizzes/:id/results - * @access Private/Admin + * @desc Get quiz results * + * @route GET /api/quizzes/:id/results * + * @access Private/Admin * *************************************************************************/ exports.getQuizResults = asyncHandler(async (req, res) => { try { From 54e5e801f6445894a0b68a21bb1f88c1dd821eaa Mon Sep 17 00:00:00 2001 From: kushwahramkumar2003 Date: Wed, 13 Dec 2023 10:34:22 +0530 Subject: [PATCH 3/3] Add react-scroll package and update Navbar component --- package-lock.json | 24 +++++-- package.json | 1 + src/App.js | 2 - src/Components/homePage/Navbar.jsx | 24 +++++-- src/index.js | 6 +- src/pages/home/Home.jsx | 101 ++++++----------------------- 6 files changed, 62 insertions(+), 96 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10e64da..eb7d3f7 100755 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "react-icons": "^4.12.0", "react-redux": "^9.0.2", "react-router-dom": "^6.19.0", + "react-scroll": "^1.9.0", "web-vitals": "^2.1.4" }, "devDependencies": { @@ -13212,6 +13213,11 @@ "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", "dev": true }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" + }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -13681,7 +13687,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -15601,7 +15606,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -15611,8 +15615,7 @@ "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -16471,6 +16474,19 @@ "node": ">=4.0.0" } }, + "node_modules/react-scroll": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/react-scroll/-/react-scroll-1.9.0.tgz", + "integrity": "sha512-mamNcaX9Ng+JeSbBu97nWwRhYvL2oba+xR2GxvyXsbDeGP+gkYIKZ+aDMMj/n20TbV9SCWm/H7nyuNTSiXA6yA==", + "dependencies": { + "lodash.throttle": "^4.1.1", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^15.5.4 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.5.4 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/package.json b/package.json index f9c6c6c..f48c549 100755 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "react-icons": "^4.12.0", "react-redux": "^9.0.2", "react-router-dom": "^6.19.0", + "react-scroll": "^1.9.0", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/App.js b/src/App.js index fb1290b..dcfe806 100755 --- a/src/App.js +++ b/src/App.js @@ -16,12 +16,10 @@ function App() { }> }> }> - }> }> }> - ); } diff --git a/src/Components/homePage/Navbar.jsx b/src/Components/homePage/Navbar.jsx index 05a2941..6ec6a4a 100644 --- a/src/Components/homePage/Navbar.jsx +++ b/src/Components/homePage/Navbar.jsx @@ -1,11 +1,12 @@ import React from "react"; import image from "../../constants/images.js"; import { Link } from "react-router-dom"; +import { Link as Link2 } from "react-scroll"; const menuLinks = [ - { name: "How it works", link: "/works" }, - { name: "Features", link: "/features" }, - { name: "About Us", link: "/about" }, - { name: "Login", link: "/Login" }, + { name: "How it works", link: "works" }, + { name: "Features", link: "features" }, + { name: "About Us", link: "about" }, + // { name: "Login", link: "/Login" }, ]; const Navbar = () => { return ( @@ -20,9 +21,22 @@ const Navbar = () => { {menuLinks?.map((menu, i) => (
  • {/* {menu?.name} */} - {menu?.name} + + {menu?.name} +
  • ))} +
  • + Login +
  • diff --git a/src/index.js b/src/index.js index cfaa3d2..035c7c6 100755 --- a/src/index.js +++ b/src/index.js @@ -15,10 +15,8 @@ root.render( - - + + diff --git a/src/pages/home/Home.jsx b/src/pages/home/Home.jsx index 146604f..986c5d8 100644 --- a/src/pages/home/Home.jsx +++ b/src/pages/home/Home.jsx @@ -1,23 +1,7 @@ import React from "react"; -// import capLogo from "./Images/logo.svg"; -// import rightimg from "./Images/Right-img.svg"; import { Link } from "react-router-dom"; +import { Link as Link2 } from "react-scroll"; -// import cornerD from './Images/icons/leftcorner-design.svg' -// import fb from "./Images/icons/facebook.svg"; -// import ld from "./Images/icons/linkedin.svg"; -// import insta from "./Images/icons/square-instagram.svg"; -// import email from "./Images/icons/email-mesage.svg"; -// import phone from "./Images/icons/phone-call.svg"; -// import location from "./Images/icons/location.svg"; -// import twitter from "./Images/icons/twitter.svg"; - -// import feature_1 from "./Images/Features images/Diverse Language Coverage.svg"; -// import feature_2 from "./Images/Features images/Personalized Skill Profiles.svg"; -// import feature_3 from "./Images/Features images/Detailed Explanations.jpg"; -// import feature_4 from "./Images/Features images/Feedback for Improvement.svg"; -// import feature_5 from "./Images/Features images/Timed Programming Quizzes.svg"; -// import feature_6 from "./Images/Features images/Aptitude Speed Challenges.svg"; import "./navbar.css"; import Navbar from "../../Components/homePage/Navbar"; import images from "../../constants/images.js"; @@ -28,7 +12,7 @@ const Home = () => { <> {/***************** Page 1 start here ******************/} -
    +
    {/************** Navbar end here *********************/} @@ -50,7 +34,7 @@ const Home = () => {

    We help you prepare for exams and quizes

    -
    @@ -61,13 +45,13 @@ const Home = () => {
    - + {/* Go to Login - + */}
    {/***************** How does it Works? page **********************************/} -
    +

    How does it works?

    @@ -143,68 +127,11 @@ const Home = () => {
    - - {/*
    - -
    -
    - -
    -

    User Registration/Login

    -

    - Seamlessly log in or register to establish your personalized account, unlocking a tailored quiz experience. -

    -
    - -
    -
    - -
    - -
    -
    -

    Real-time Feedback

    -

    Receive instant feedback for each question, providing immediate clarity on the correctness of your responses. -

    -
    - -
    - -
    - -
    - -
    -
    -
    - -
    -

    Completion and Results

    -

    Instantly access a comprehensive result summary upon completing a quiz, offering insights into your performance.

    -
    -
    -
    - -
    - -
    -
    -
    - -
    -

    Cross-Platform Accessibility

    -

    Whether on mobile, tablet, or desktop, our quizzes are designed for a consistent and enjoyable experience.

    -
    - - -
    -
    -
    */} {/************** Our Features & Services Page *******************/} -
    +

    Our features & Services

    @@ -301,6 +228,8 @@ const Home = () => {
    + +
    {/********** features & services end here ***********/} {/****************** footer section start here ******************/} @@ -309,7 +238,17 @@ const Home = () => {
    {/************ Box - 1 ****************/}
    - + + + +

    Home | About | Contact | Quizes

    Copyright @2023 QuizGrad All right reserved