├── src ├── logo.png ├── backend │ ├── db │ │ ├── categories.js │ │ ├── users.js │ │ └── quizzes.js │ ├── utils │ │ └── authUtils.js │ └── controllers │ │ ├── CategoryController.js │ │ ├── AuthController.js │ │ └── QuizesController.js ├── index.js ├── index.css ├── App.css ├── App.js └── server.js ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── .gitignore ├── package.json └── README.md /src/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivinayakg/mockbee-quiz-template/HEAD/src/logo.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivinayakg/mockbee-quiz-template/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivinayakg/mockbee-quiz-template/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivinayakg/mockbee-quiz-template/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/backend/db/categories.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuid } from "uuid"; 2 | 3 | /** 4 | * Category Database can be added here. 5 | * You can add category of your wish with different attributes 6 | * */ 7 | 8 | export const categories = [ 9 | { 10 | _id: uuid(), 11 | categoryName: "TV Show", 12 | description: "Quizes based on TV shows", 13 | }, 14 | ]; 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import { makeServer } from "./server"; 6 | 7 | // Call make Server 8 | makeServer(); 9 | 10 | ReactDOM.render( 11 | 12 | 13 | , 14 | document.getElementById("root") 15 | ); 16 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | .eslintcache 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/backend/db/users.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuid } from "uuid"; 2 | import { formatDate } from "../utils/authUtils"; 3 | /** 4 | * User Database can be added here. 5 | * You can add default users of your wish with different attributes 6 | * Every user will have cart (Quantity of all Products in Cart is set to 1 by default), wishList by default 7 | * */ 8 | 9 | export const users = [ 10 | { 11 | _id: 1007, 12 | firstName: "Adarsh", 13 | lastName: "Balika", 14 | email: "admin@gmail.com", 15 | password: "123456", 16 | createdAt: formatDate(), 17 | updatedAt: formatDate(), 18 | }, 19 | ]; 20 | -------------------------------------------------------------------------------- /src/backend/utils/authUtils.js: -------------------------------------------------------------------------------- 1 | import { Response } from "miragejs"; 2 | import dayjs from "dayjs"; 3 | import jwt_decode from "jwt-decode"; 4 | 5 | export const requiresAuth = function (request) { 6 | const encodedToken = request.requestHeaders.authorization; 7 | console.log(encodedToken, process.env.REACT_APP_JWT_SECRET); 8 | const decodedToken = jwt_decode( 9 | encodedToken, 10 | process.env.REACT_APP_JWT_SECRET 11 | ); 12 | if (decodedToken) { 13 | const user = this.db.users.findBy({ email: decodedToken.email }); 14 | if (user) { 15 | return user._id; 16 | } 17 | } 18 | return new Response( 19 | 401, 20 | {}, 21 | { errors: ["The token is invalid. Unauthorized access error."] } 22 | ); 23 | }; 24 | 25 | export const formatDate = () => dayjs().format("YYYY-MM-DDTHH:mm:ssZ"); 26 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #22201c; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | color: white; 24 | } 25 | 26 | .App-link { 27 | color: #61dafb; 28 | } 29 | 30 | .brand-title { 31 | font-size: 3rem; 32 | color: #d9d9d9; 33 | } 34 | 35 | .brand-title span { 36 | color: #ffde59; 37 | } 38 | 39 | .brand-description { 40 | font-size: 1.4rem; 41 | } 42 | 43 | .links { 44 | display: flex; 45 | } 46 | 47 | .links a { 48 | color: #d9d9d9; 49 | font-size: 1.2rem; 50 | margin: 1rem; 51 | } 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quiz-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "axios": "^0.21.4", 7 | "dayjs": "^1.10.7", 8 | "jwt-decode": "^3.1.2", 9 | "jwt-encode": "^1.0.1", 10 | "miragejs": "^0.1.41", 11 | "mockman-js": "^1.0.5", 12 | "react": "^17.0.2", 13 | "react-dom": "^17.0.2", 14 | "react-scripts": "4.0.3", 15 | "uuid": "^8.3.2", 16 | "web-vitals": "^0.2.4" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/backend/db/quizzes.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuid } from "uuid"; 2 | 3 | /** 4 | * Product Database can be added here. 5 | * You can add products of your wish with different attributes 6 | * */ 7 | 8 | export const quizzes = [ 9 | { 10 | _id: "3fe39675-140b-4075-82f3-949a4dc95d18", 11 | title: "You Can WIN", 12 | totalScore: 20, 13 | mcqs: [ 14 | { 15 | _id: "dddcd7a2-a479-482e-ae82-d55e2468534d", 16 | question: "Which season Harvey is the Most Badass One", 17 | options: ["Season 1", "Season 2", "Season 6", "Every Season"], 18 | answer: "Every Season", 19 | }, 20 | { 21 | _id: "93664683-d515-44bf-80c4-cd52c279aeb6", 22 | question: "In which season does Mike was imprisoned", 23 | options: ["Season 3", "Season 5", "Season 7", "Season 4"], 24 | answer: "Season 4", 25 | }, 26 | { 27 | _id: "7e70f8e5-0760-4b5e-b833-38dab109ec54", 28 | question: "Harvey had what kind of emotional problems", 29 | options: ["Attachment Issues", "Panic Attack", "Trauma", "Stress"], 30 | answer: "Attachment Issues", 31 | }, 32 | ], 33 | catergoryName: "TV Show", 34 | }, 35 | ]; 36 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import "./App.css"; 2 | import logo from "./logo.png"; 3 | import Mockman from "mockman-js"; 4 | 5 | function App() { 6 | return ( 7 |
8 | {/*
9 | mockBee logo 10 |

11 | Welcome to mockBee! 12 |

13 |

14 | Get started by editing src/App.js 15 |

16 |
17 | 22 | Explore mockBee 23 | 24 | 29 | API Documentation 30 | 31 | 36 | Contribute 37 | 38 |
39 |
*/} 40 | 41 |
42 | ); 43 | } 44 | 45 | export default App; 46 | -------------------------------------------------------------------------------- /src/backend/controllers/CategoryController.js: -------------------------------------------------------------------------------- 1 | import { Response } from "miragejs"; 2 | 3 | /** 4 | * All the routes related to Category are present here. 5 | * These are Publicly accessible routes. 6 | * */ 7 | 8 | /** 9 | * This handler handles gets all categories in the db. 10 | * send GET Request at /api/categories 11 | * */ 12 | 13 | export const getAllCategoriesHandler = function () { 14 | try { 15 | return new Response(200, {}, { categories: this.db.categories }); 16 | } catch (error) { 17 | return new Response( 18 | 500, 19 | {}, 20 | { 21 | error, 22 | } 23 | ); 24 | } 25 | }; 26 | 27 | /** 28 | * This handler handles gets all categories in the db. 29 | * send GET Request at /api/user/category/:categoryId 30 | * */ 31 | 32 | export const getCategoryHandler = function (schema, request) { 33 | const categoryId = request.params.categoryId; 34 | try { 35 | const category = schema.categories.findBy({ _id: categoryId }); 36 | return new Response(200, {}, { category }); 37 | } catch (error) { 38 | return new Response( 39 | 500, 40 | {}, 41 | { 42 | error, 43 | } 44 | ); 45 | } 46 | }; 47 | 48 | export const getAllCatergoryQuizesHandler = function (schema, request) { 49 | const categoryId = request.params.categoryId; 50 | 51 | try { 52 | const category = schema.categories.findBy({ _id: categoryId }); 53 | const catergoryQuizes = this.db.quizzes.filter( 54 | (quiz) => 55 | quiz.catergoryName.toLowerCase() === category.categoryName.toLowerCase() 56 | ); 57 | return new Response(200, {}, { quizzes: catergoryQuizes }); 58 | } catch (error) { 59 | return new Response( 60 | 500, 61 | {}, 62 | { 63 | error, 64 | } 65 | ); 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 32 | 33 | 34 | 35 |
36 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/server.js: -------------------------------------------------------------------------------- 1 | import { Server, Model, RestSerializer } from "miragejs"; 2 | import { 3 | loginHandler, 4 | signupHandler, 5 | checkToken, 6 | } from "./backend/controllers/AuthController"; 7 | import { 8 | getAllCategoriesHandler, 9 | getCategoryHandler, 10 | getAllCatergoryQuizesHandler, 11 | } from "./backend/controllers/CategoryController"; 12 | import { 13 | addQuizHandler, 14 | getAllQuizesHandler, 15 | getSingleQuizHandler, 16 | getSingleQuizQuestionAnswer, 17 | postQuizResultHandler, 18 | } from "./backend/controllers/QuizesController"; 19 | 20 | import { categories } from "./backend/db/categories"; 21 | import { quizzes } from "./backend/db/quizzes"; 22 | import { users } from "./backend/db/users"; 23 | 24 | export function makeServer({ environment = "development" } = {}) { 25 | return new Server({ 26 | serializers: { 27 | application: RestSerializer, 28 | }, 29 | environment, 30 | models: { 31 | quiz: Model, 32 | category: Model, 33 | user: Model, 34 | totalScore: Model, 35 | knowledgeLevel: Model, 36 | quizTaken: Model, 37 | }, 38 | 39 | // Runs on the start of the server 40 | seeds(server) { 41 | // disballing console logs from Mirage 42 | server.logging = false; 43 | quizzes.forEach((item) => { 44 | server.create("quiz", item); 45 | // console.log(item); 46 | }); 47 | 48 | users.forEach((item) => 49 | server.create("user", { 50 | ...item, 51 | totalScore: { current: 0 }, 52 | knowledgeLevel: { current: "rookie" }, 53 | quizTaken: [], 54 | }) 55 | ); 56 | 57 | categories.forEach((item) => server.create("category", { ...item })); 58 | }, 59 | 60 | routes() { 61 | this.namespace = "api"; 62 | // auth routes (public) 63 | this.post("/auth/signup", signupHandler.bind(this)); 64 | this.post("/auth/login", loginHandler.bind(this)); 65 | 66 | //check token (private) 67 | this.post("/auth/checktoken", checkToken.bind(this)); 68 | 69 | // quizes routes (public) 70 | this.get("/quizzes", getAllQuizesHandler.bind(this)); 71 | this.get("/quizzes/:quizId", getSingleQuizHandler.bind(this)); 72 | this.get( 73 | "/quizzes/:quizId/:questionId", 74 | getSingleQuizQuestionAnswer.bind(this) 75 | ); 76 | 77 | // categories routes (public) 78 | this.get("/categories", getAllCategoriesHandler.bind(this)); 79 | this.get("/categories/:categoryId", getCategoryHandler.bind(this)); 80 | this.get( 81 | "/categories/quizzes/:categoryId", 82 | getAllCatergoryQuizesHandler.bind(this) 83 | ); 84 | 85 | // quizes routes (private) 86 | this.post("/quizzes", addQuizHandler.bind(this)); 87 | this.post("/quizzes/result", postQuizResultHandler.bind(this)); 88 | }, 89 | }); 90 | } 91 | -------------------------------------------------------------------------------- /src/backend/controllers/AuthController.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuid } from "uuid"; 2 | import { Response } from "miragejs"; 3 | import { formatDate } from "../utils/authUtils"; 4 | const sign = require("jwt-encode"); 5 | /** 6 | * All the routes related to Auth are present here. 7 | * These are Publicly accessible routes. 8 | * */ 9 | 10 | /** 11 | * This handler handles user signups. 12 | * send POST Request at /api/auth/signup 13 | * body contains {firstName, lastName, email, password} 14 | * */ 15 | 16 | export const signupHandler = function (schema, request) { 17 | const { email, password, ...rest } = JSON.parse(request.requestBody); 18 | try { 19 | // check if email already exists 20 | const foundUser = schema.users.findBy({ email }); 21 | if (foundUser) { 22 | return new Response( 23 | 422, 24 | {}, 25 | { 26 | errors: ["Unprocessable Entity. Email Already Exists."], 27 | } 28 | ); 29 | } 30 | const _id = uuid(); 31 | const newUser = { 32 | _id, 33 | email, 34 | password, 35 | createdAt: formatDate(), 36 | updatedAt: formatDate(), 37 | ...rest, 38 | totalScore: { current: 0 }, 39 | knowledgeLevel: { current: "rookie" }, 40 | quizTaken: [], 41 | }; 42 | const createdUser = schema.users.create(newUser); 43 | const encodedToken = sign({ _id, email }, process.env.REACT_APP_JWT_SECRET); 44 | return new Response(201, {}, { createdUser, encodedToken }); 45 | } catch (error) { 46 | return new Response( 47 | 500, 48 | {}, 49 | { 50 | error, 51 | } 52 | ); 53 | } 54 | }; 55 | 56 | /** 57 | * This handler handles user login. 58 | * send POST Request at /api/auth/login 59 | * body contains {email, password} 60 | * */ 61 | 62 | export const loginHandler = function (schema, request) { 63 | const { email, password } = JSON.parse(request.requestBody); 64 | try { 65 | const foundUser = schema.users.findBy({ email }); 66 | if (!foundUser) { 67 | return new Response( 68 | 404, 69 | {}, 70 | { errors: ["The email you entered is not Registered. Not Found error"] } 71 | ); 72 | } 73 | if (password === foundUser.password) { 74 | const encodedToken = sign( 75 | { _id: foundUser._id, email }, 76 | process.env.REACT_APP_JWT_SECRET 77 | ); 78 | foundUser.password = undefined; 79 | return new Response(200, {}, { foundUser, encodedToken }); 80 | } 81 | return new Response( 82 | 401, 83 | {}, 84 | { 85 | errors: [ 86 | "The credentials you entered are invalid. Unauthorized access error.", 87 | ], 88 | } 89 | ); 90 | } catch (error) { 91 | return new Response( 92 | 500, 93 | {}, 94 | { 95 | error, 96 | } 97 | ); 98 | } 99 | }; 100 | 101 | export const checkToken = function (schema, request) { 102 | const userId = requiresAuth.call(this, request); 103 | try { 104 | if (!userId) { 105 | new Response(404, {}, { result: "User Not available / Token not valid" }); 106 | } 107 | } catch (error) { 108 | return new Response( 109 | 500, 110 | {}, 111 | { 112 | error, 113 | } 114 | ); 115 | } 116 | }; 117 | -------------------------------------------------------------------------------- /src/backend/controllers/QuizesController.js: -------------------------------------------------------------------------------- 1 | import { Response } from "miragejs"; 2 | import { requiresAuth } from "../utils/authUtils"; 3 | import { v4 as uuid } from "uuid"; 4 | 5 | export const getAllQuizesHandler = function () { 6 | return new Response(200, {}, { quizes: this.db.quizzes }); 7 | }; 8 | 9 | export const getSingleQuizHandler = function (schema, request) { 10 | const Id = request.params.quizId; 11 | try { 12 | const quiz = schema.quizzes.findBy({ _id: Id }); 13 | return new Response(200, {}, { quiz }); 14 | } catch (error) { 15 | return new Response( 16 | 500, 17 | {}, 18 | { 19 | error, 20 | } 21 | ); 22 | } 23 | }; 24 | 25 | export const getSingleQuizQuestionAnswer = function (schema, request) { 26 | const quizId = request.params.quizId; 27 | const questionId = request.params.questionId; 28 | try { 29 | const quiz = schema.quizzes.findBy({ _id: quizId }); 30 | const question = quiz.mcqs.find((item) => item._id === questionId); 31 | return new Response(200, {}, { question }); 32 | } catch (error) { 33 | return new Response( 34 | 500, 35 | {}, 36 | { 37 | error, 38 | } 39 | ); 40 | } 41 | }; 42 | 43 | export const postQuizResultHandler = function (schema, request) { 44 | const userId = requiresAuth.call(this, request); 45 | try { 46 | if (!userId) { 47 | return new Response( 48 | 404, 49 | {}, 50 | { 51 | errors: ["The email you entered is not Registered. Not Found error"], 52 | } 53 | ); 54 | } 55 | const { score, quizTaken } = JSON.parse(request.requestBody); 56 | if (!schema.quizzes.findBy({ _id: quizTaken._id })) { 57 | return new Response( 58 | 404, 59 | {}, 60 | { result: "this quiz is not present in the server" } 61 | ); 62 | } 63 | const user = schema.users.findBy({ _id: userId }); 64 | const newUserScore = 65 | Number(score) > 0 66 | ? Number(score) + Number(user.totalScore.current) 67 | : Number(user.totalScore.current); 68 | const knowledgeLevel = 69 | newUserScore >= 15 70 | ? newUserScore >= 25 71 | ? "Expert" 72 | : "Amateur" 73 | : "Rookie"; 74 | const quizTakenByUser = user.quizTaken; 75 | quizTakenByUser.push({ ...quizTaken }); 76 | this.db.users.update( 77 | { _id: userId }, 78 | { 79 | totalScore: { current: newUserScore }, 80 | knowledgeLevel: { current: knowledgeLevel }, 81 | quizTaken: quizTakenByUser, 82 | } 83 | ); 84 | return new Response(201, {}, { user }); 85 | } catch (error) { 86 | return new Response( 87 | 500, 88 | {}, 89 | { 90 | error, 91 | } 92 | ); 93 | } 94 | }; 95 | 96 | export const addQuizHandler = function (schema, request) { 97 | const userId = requiresAuth.call(this, request); 98 | try { 99 | if (!userId) { 100 | return new Response( 101 | 404, 102 | {}, 103 | { 104 | errors: ["The email you entered is not Registered. Not Found error"], 105 | } 106 | ); 107 | } 108 | const { quiz } = JSON.parse(request.requestBody); 109 | if (quiz.mcqs.length <= 0 || !quiz.mcqs || !quiz.title) { 110 | return new Response( 111 | 500, 112 | {}, 113 | { result: "The data format is not supported" } 114 | ); 115 | } 116 | const newQuiz = { 117 | _id: uuid(), 118 | createdAt: formatDate(), 119 | updatedAt: formatDate(), 120 | catergoryName: "", 121 | ...quiz, 122 | }; 123 | const createdQuiz = schema.quizzes.create(newQuiz); 124 | return new Response(201, {}, { createdQuiz }); 125 | } catch (error) { 126 | return new Response( 127 | 500, 128 | {}, 129 | { 130 | error, 131 | } 132 | ); 133 | } 134 | }; 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Quiz Backend 2 | 3 | This folder contains the Mock Backend created for Quiz App. It contains different API end-points and database configuration for building Quiz; so that you can focus on building Frontend. 4 | 5 | 6 | # Documentation for Quiz App 7 | This template is especially created with keeping in mind that people who are making a quiz app can have a temporary running API without thinking about backend development. 8 | 9 | ### Note for fellow neog students 10 | (if not then skip this, not relevant for you) 11 | This backend is made identical to how we use mockbackend for development, so the limitation as well as the shortcomings of that project is by default inherited by this template, but i tried to include 1-2 new API's which i believe will help everyone. 12 | Most of the Documentation for this is copied from the official mockbee docs. Find out more [here](https://mockbee.netlify.app/) 13 | 14 | 15 | ## Getting started first fork this and then clone it on your github and local environment. 16 | 17 | ## Setting up JWT Secret for Authentication# 18 | For Authentication, mockBee provides JWT authentication strategy out of the box. The JWT requires a JWT_SECRET Key, which is essentially a secret stored on your hosted backend setup as an environment variable. Read more about JWT here. Since, we are working with mock backend servers; we need to give our mock backend access to the JWT secret key. So, for that go ahead and create a .env file in your root directory of the app and add the below code in it: 19 | 20 | > REACT_APP_JWT_SECRET= write_any_gibberish_you_want_to_here 21 | 22 | Note that REACT_APP_ prefix is important for our frontend to identify the variables in our development setup. Read more about adding custom environment variables here. 23 | 24 | 25 | ## Authentication 26 | It works the same as it does on the mockbee templates, you can read about it more [here](https://mockbee.netlify.app/docs/api/general/auth) 27 | Apart from it i added one additional API which i beilive is going to be useful for everyone and is ging to solve a major security concern. 28 | 29 | ### Check Token ('/api/auth/checktoken') 30 | You just make a post request with the token in the header and it will return wether or not that token is accurate or not, in cases like refresh pages or 'Remeber Me' i belive it can be useful as you can check the authentication of your token. 31 | 32 | ``` 33 | axios.post('/api/auth/checktoken', { 34 | headers : { 35 | authorization : "token" 36 | } 37 | }) 38 | ``` 39 | 40 | ## Catergories 41 | It has catergories API which works identical to any catergory API you can find to mockbee, check [here](https://mockbee.netlify.app/docs/api/apps/e-commerce#1-get-apicategories) for reference. 42 | 43 | ### Get All quizes of a particular catergory 44 | * API Route : '/api/categories/quizzes/:categoryId' 45 | * Type : 'GET' 46 | * Request Headers : 'Default' 47 | * Functionality: 'Get Quizes of a particular ctaergory by id from the backend' 48 | * Response : 49 | ``` 50 | { 51 | data : { 52 | quizzes 53 | } 54 | } 55 | ``` 56 | 57 | ## Quizzes 58 | 59 | ### Data Structure Of Quiz in the backend 60 | this structure needed to be followed in the exact way only to get all the APIs working perfectly.
61 | `(Note- you can use your custom data structure if want to there is no problem with that but keep in mind that the API for getting a question by if using the route '/api/quizzes/:quizId/:questionId' will not work)` 62 | ``` 63 | { 64 | _id: "3fe39675-140b-4075-82f3-949a4dc95d18", 65 | title: "You Can WIN", 66 | totalScore: 20, 67 | mcqs: [ 68 | { "this below is the how a question should look like in every quiz" 69 | _id: "dddcd7a2-a479-482e-ae82-d55e2468534d", 70 | question: "Which season Harvey is the Most Badass One", 71 | options: ["Season 1", "Season 2", "Season 6", "Every Season"], 72 | answer: "Every Season", 73 | }, etc. 74 | ], 75 | catergoryName: "TV Show", 76 | } 77 | ``` 78 | 79 | 80 | ### Get All quizes 81 | * API Route : '/api/quizzes' 82 | * Type : 'GET' 83 | * Request Headers : 'Default' 84 | * Functionality: 'Get All Quizzes from the backend' 85 | * Response : 86 | ``` 87 | { 88 | data : { 89 | quizes 90 | } 91 | } 92 | ``` 93 | 94 | ## Get Quiz By Id 95 | * API Route : '/api/quizzes/:quizId' 96 | * Type : 'GET' 97 | * Request Headers : 'Default' 98 | * Functionality: 'Get Quiz by id from the backend' 99 | * Response : 100 | ``` 101 | { 102 | data : { 103 | quiz 104 | } 105 | } 106 | ``` 107 | 108 | ## Get question by id 109 | * API Route : '/api/quizzes/:quizId/:questionId' 110 | * Type : 'GET' 111 | * Request Headers : 'Default' 112 | * Functionality: 'Get question by id of a particular question by id from the backend' 113 | * Response : 114 | ``` 115 | { 116 | data : { 117 | question 118 | } 119 | } 120 | ``` 121 | 122 | ## Create a quiz 123 | * API Route : '/api/quizzes' 124 | * Type : 'POST' 125 | * Request Headers : 'authorization: encodedToken' 126 | * Functionality: 'Create A Quiz' 127 | * Request Body : 128 | ``` 129 | { 130 | quiz 131 | } 132 | ``` 133 | * Response : 134 | ``` 135 | { 136 | createdQuiz 137 | } 138 | ``` 139 | * Structure for quiz in request body :
140 | ``` 141 | {"here you dont need to add _id as it would be added from the backend"\ 142 | title: "You Can WIN", 143 | totalScore: 20, 144 | mcqs: [ 145 | { "this below is the how a question should look like in every quiz" 146 | _id: uuid, 147 | question: "Which season Harvey is the Most Badass One", 148 | options: ["Season 1", "Season 2", "Season 6", "Every Season"], 149 | answer: "Every Season", 150 | }, etc. 151 | ], 152 | catergoryName: "TV Show", 153 | } 154 | ``` 155 | 156 | ## Post result of quiz on the backend 157 | * API Route : '/api/quizzes/result' 158 | * Type : 'POST' 159 | * Request Headers : 'authorization: encodedToken' 160 | * Functionality: 'Create A Qui' 161 | * Request Body : 162 | ``` 163 | { 164 | score : "The points awarded" 165 | quizTaken : quiz (quiz which is taken by the user) 166 | } 167 | ``` 168 | * Response : 169 | ``` 170 | { 171 | user (with new score, and knwoledge level) 172 | } 173 | ``` 174 | --------------------------------------------------------------------------------