├── .gitignore ├── README.md ├── assets ├── Screenshot (21).png ├── Screenshot (22).png ├── Screenshot (24).png ├── Screenshot (25).png ├── Screenshot (26).png ├── Screenshot (27).png ├── Screenshot (28).png ├── Screenshot (29).png ├── Screenshot (30).png ├── Screenshot (31).png └── qgen-final.gif ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.css ├── App.js ├── app └── store.js ├── components ├── Auth │ ├── Auth.css │ ├── Auth.js │ └── functions.js ├── CustomModal │ ├── CustomModal.css │ └── CustomModal.js ├── Main │ ├── Main.css │ └── Main.js └── Quiz │ ├── Quiz.css │ └── Quiz.js ├── const.js ├── features └── counter │ ├── Counter.js │ ├── Counter.module.css │ └── counterSlice.js ├── index.css └── index.js /.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.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Qgen

2 | 3 |               [![](https://img.shields.io/badge/Made_with-ReactJs-blue?style=for-the-badge&logo=ReactJs)](https://www.djangoproject.com/) 4 |   5 | [![](https://img.shields.io/badge/IDE-Visual_Studio_Code-blue?style=for-the-badge&logo=visual-studio-code)](https://code.visualstudio.com/ "Visual Studio Code") 6 |   7 | 8 |

About

9 |

10 | Many times, we read our notes again and again, without ever getting any information inside our head. Havent you noticed that whenver there is a quiz, or whenever you take a test, you learn the material better? Hence, we have created an app, which used Machine Learning and Natural Language Processing to generate flashcards, quizzes, and summary from your notes! Moreover, we have three types of questions: MCQ, Fill in the blanks, and True or False questions to test you on your notes. 11 | You can also upload handwritten notes to generate quizzes so that you can directly upload a photo and generate a quiz. 12 |

13 | 14 | ----------------------------------- 15 | 16 | ### Demo 17 | 18 |

19 | 20 |

21 | 22 | ----------------------------------- 23 | 24 | ### 🚀 Features 25 | 26 |

27 |

44 |

45 | 46 | 47 | ----------------------------------- 48 | ### 💻 Tech stack 49 | `Backend` : Django
50 | `Database` : SQLite
51 | `Frontend` : ReactJs, CSS, HTML, Bootstrap, jQuery
52 | `ML`: BERT, Spacy, NLTK 53 | 54 | ----------------------------------- 55 | 56 | ### :guide_dog: Installation Guide 57 | 58 | A step by step series of examples that tell you how to get a development env running 59 | 60 | In your cmd: 61 | 62 | ``` 63 | git clone https://github.com/Deep-Matrix/qgen-frontend 64 | ``` 65 | 66 | Then, 67 | 68 | ``` 69 | cd qgen-frontend 70 | npm install 71 | npm start 72 | ``` 73 | 74 | You are done with the setup now! 75 | 76 | ------------------------------------------ 77 | -------------------------------------------------------------------------------- /assets/Screenshot (21).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (21).png -------------------------------------------------------------------------------- /assets/Screenshot (22).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (22).png -------------------------------------------------------------------------------- /assets/Screenshot (24).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (24).png -------------------------------------------------------------------------------- /assets/Screenshot (25).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (25).png -------------------------------------------------------------------------------- /assets/Screenshot (26).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (26).png -------------------------------------------------------------------------------- /assets/Screenshot (27).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (27).png -------------------------------------------------------------------------------- /assets/Screenshot (28).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (28).png -------------------------------------------------------------------------------- /assets/Screenshot (29).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (29).png -------------------------------------------------------------------------------- /assets/Screenshot (30).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (30).png -------------------------------------------------------------------------------- /assets/Screenshot (31).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/Screenshot (31).png -------------------------------------------------------------------------------- /assets/qgen-final.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/assets/qgen-final.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@ckeditor/ckeditor5-build-classic": "^27.0.0", 7 | "@ckeditor/ckeditor5-react": "^3.0.2", 8 | "@material-ui/core": "^4.11.3", 9 | "@material-ui/icons": "^4.11.2", 10 | "@material-ui/lab": "^4.0.0-alpha.57", 11 | "@reduxjs/toolkit": "^1.5.1", 12 | "@testing-library/jest-dom": "^4.2.4", 13 | "@testing-library/react": "^9.5.0", 14 | "@testing-library/user-event": "^7.2.1", 15 | "axios": "^0.21.1", 16 | "react": "^17.0.2", 17 | "react-dom": "^17.0.2", 18 | "react-editext": "^3.18.0", 19 | "react-icons-kit": "^1.3.1", 20 | "react-redux": "^7.2.3", 21 | "react-router-dom": "^5.2.0", 22 | "react-scripts": "4.0.3" 23 | }, 24 | "scripts": { 25 | "start": "react-scripts start", 26 | "build": "react-scripts build", 27 | "test": "react-scripts test", 28 | "eject": "react-scripts eject" 29 | }, 30 | "eslintConfig": { 31 | "extends": "react-app" 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React Redux App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Deep-Matrix/qgen-frontend/3b37933b5c0c72f30e1498b19e861d90003388f1/public/logo512.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /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-float infinite 3s ease-in-out; 13 | } 14 | } 15 | 16 | .App-header { 17 | min-height: 100vh; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | justify-content: center; 22 | font-size: calc(10px + 2vmin); 23 | } 24 | 25 | .App-link { 26 | color: rgb(112, 76, 182); 27 | } 28 | 29 | @keyframes App-logo-float { 30 | 0% { 31 | transform: translateY(0); 32 | } 33 | 50% { 34 | transform: translateY(10px) 35 | } 36 | 100% { 37 | transform: translateY(0px) 38 | } 39 | } 40 | 41 | 42 | 43 | :root { 44 | --color-primary: #342d96; 45 | /* --color-primary-light: #FF3366; 46 | --color-primary-dark: #BA265D; 47 | 48 | --color-grey-light-1: #faf9f9; 49 | --color-grey-light-2: #f4f2f2; 50 | --color-grey-light-3: #f0eeee; 51 | --color-grey-light-4: #ccc; 52 | 53 | --color-grey-dark-1: #333; 54 | --color-grey-dark-2: #777; 55 | --color-grey-dark-3: #999; */ 56 | 57 | --shadow-dark: 0 2rem 6rem rgba(0,0,0,0.3); 58 | } 59 | 60 | body { 61 | box-sizing: border-box; 62 | 63 | } 64 | 65 | *{ 66 | padding: 0px; 67 | margin: 0px; 68 | } 69 | 70 | .header-primary{ 71 | font-size: 30px; 72 | font-weight: 800; 73 | } 74 | 75 | .header-secondary{ 76 | font-size: 20px; 77 | font-weight: 600; 78 | } 79 | 80 | 81 | html{ 82 | box-sizing: border-box; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./App.css"; 3 | import Main from "./components/Main/Main"; 4 | import { 5 | BrowserRouter as Router, 6 | Switch, 7 | Route, 8 | Link 9 | } from "react-router-dom"; 10 | import Quiz from "./components/Quiz/Quiz"; 11 | import Auth from "./components/Auth/Auth"; 12 | import CustomModal from "./components/CustomModal/CustomModal"; 13 | 14 | function App() { 15 | return ( 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 |
34 | ); 35 | } 36 | 37 | export default App; 38 | -------------------------------------------------------------------------------- /src/app/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit'; 2 | import counterReducer from '../features/counter/counterSlice'; 3 | 4 | export default configureStore({ 5 | reducer: { 6 | counter: counterReducer, 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /src/components/Auth/Auth.css: -------------------------------------------------------------------------------- 1 | .auth{ 2 | background-color: aqua; 3 | display: flex; 4 | flex-direction: row; 5 | height: 100vh; 6 | } 7 | 8 | .auth__left{ 9 | background-image: url('https://images.unsplash.com/photo-1589652717521-10c0d092dea9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=750&q=80'); 10 | background-size: cover; 11 | flex: 0.7; 12 | } 13 | 14 | .auth__right{ 15 | background-color: violet; 16 | flex: 0.3; 17 | } 18 | 19 | @media screen and (max-width: 480px) { 20 | .auth__left { 21 | display: none; 22 | } 23 | .auth__right{ 24 | flex: 1; 25 | } 26 | } -------------------------------------------------------------------------------- /src/components/Auth/Auth.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Avatar from '@material-ui/core/Avatar'; 3 | import Button from '@material-ui/core/Button'; 4 | import CssBaseline from '@material-ui/core/CssBaseline'; 5 | import TextField from '@material-ui/core/TextField'; 6 | import FormControlLabel from '@material-ui/core/FormControlLabel'; 7 | import Checkbox from '@material-ui/core/Checkbox'; 8 | import Link from '@material-ui/core/Link'; 9 | import Paper from '@material-ui/core/Paper'; 10 | import Box from '@material-ui/core/Box'; 11 | import Grid from '@material-ui/core/Grid'; 12 | import LockOutlinedIcon from '@material-ui/icons/LockOutlined'; 13 | import Typography from '@material-ui/core/Typography'; 14 | import { makeStyles } from '@material-ui/core/styles'; 15 | import { deepOrange, deepPurple } from '@material-ui/core/colors'; 16 | import { registerApi,loginApi,secureRequest } from './functions' 17 | import { CLIENT_URL } from '../../const' 18 | import { Redirect } from 'react-router-dom'; 19 | function Copyright() { 20 | return ( 21 | 22 | {'Copyright © '} 23 | 24 | Your Website 25 | {' '} 26 | {new Date().getFullYear()} 27 | {'.'} 28 | 29 | ); 30 | } 31 | 32 | const useStyles = makeStyles((theme) => ({ 33 | root: { 34 | height: '100vh', 35 | }, 36 | image: { 37 | backgroundImage: 'url(https://source.unsplash.com/random)', 38 | backgroundRepeat: 'no-repeat', 39 | backgroundColor: 40 | theme.palette.type === 'light' ? theme.palette.grey[50] : theme.palette.grey[900], 41 | backgroundSize: 'cover', 42 | backgroundPosition: 'center', 43 | }, 44 | paper: { 45 | margin: theme.spacing(8, 4), 46 | display: 'flex', 47 | flexDirection: 'column', 48 | alignItems: 'center', 49 | }, 50 | avatar: { 51 | margin: theme.spacing(1), 52 | }, 53 | avatar__login: { 54 | backgroundColor: deepPurple[500], 55 | }, 56 | avatar__register: { 57 | backgroundColor: deepOrange[500], 58 | }, 59 | form: { 60 | width: '100%', // Fix IE 11 issue. 61 | marginTop: theme.spacing(1), 62 | }, 63 | submit: { 64 | margin: theme.spacing(3, 0, 2), 65 | }, 66 | orange: { 67 | color: theme.palette.getContrastText(deepOrange[500]), 68 | backgroundColor: deepOrange[500], 69 | }, 70 | purple: { 71 | color: theme.palette.getContrastText(deepPurple[500]), 72 | backgroundColor: deepPurple[500], 73 | }, 74 | })); 75 | 76 | export default function Auth() { 77 | const classes = useStyles(); 78 | 79 | const [isLogin, setIsLogin] = useState(true) 80 | const [email, setEmail] = useState('') 81 | const [password, setPassword] = useState('') 82 | const [redirect, setRedirect] = useState(false) 83 | 84 | const handleSubmit = async (e) => { 85 | e.preventDefault() 86 | console.log(email) 87 | console.log(password) 88 | let data={ 89 | email, 90 | password 91 | } 92 | console.log('in register') 93 | let response= null 94 | if(isLogin){ 95 | response = await loginApi(data) 96 | const token = response.data.token || 'NA' 97 | console.log(token) 98 | localStorage.setItem('token',token) 99 | if(token){ 100 | setRedirect(true) 101 | } 102 | } 103 | else{ 104 | response = await registerApi(data) 105 | } 106 | 107 | // response = await secureRequest() 108 | // console.log(response) 109 | // alert(JSON.stringify(response)) 110 | } 111 | 112 | if(redirect){ 113 | return ; 114 | } 115 | 116 | return ( 117 | 118 | 119 | 120 | 121 |
122 | 123 | 124 | 125 | 126 | {isLogin ? "Sign In" : "Sign up"} 127 | 128 |
129 | setEmail(e.target.value)} 140 | /> 141 | setPassword(e.target.value)} 152 | /> 153 | } 155 | label="Remember me" 156 | /> 157 | 166 | 167 | 168 | 169 | Forgot password? 170 | 171 | 172 | 173 | setIsLogin(!isLogin)} href="#" variant="body2"> 174 | {isLogin ? "Don't have an account? Sign Up" : "Already have an account? Sign In"} 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 |
183 |
184 |
185 | ); 186 | } -------------------------------------------------------------------------------- /src/components/Auth/functions.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import { CLIENT_URL } from '../../const' 3 | 4 | export const registerApi = async(data)=> { 5 | const result = await axios.post(`${CLIENT_URL}/api/register`,{ 6 | username : data.email, 7 | email_id : data.email, 8 | password : data.password, 9 | }) 10 | 11 | return result 12 | } 13 | 14 | export const loginApi = async(data)=> { 15 | const result = await axios.post(`${CLIENT_URL}/api/login`,{ 16 | email_id : data.email, 17 | password : data.password, 18 | }) 19 | // JSON.stringify, JSON.parse 20 | localStorage.setItem('user', JSON.stringify(result.data.user)) 21 | localStorage.setItem('token', result.data.token) 22 | return result 23 | } 24 | 25 | export const secureRequest = async (data) => { 26 | const sendData = { 27 | note_title : 'note_title by rugzzz', 28 | user_id : 3 29 | } 30 | const headers = { 31 | headers:{ 32 | 'Authorization':''+localStorage.token, 33 | // 'token':''+localStorage.token, 34 | // 'Content-Type': 'application/x-www-form-urlencoded' 35 | } 36 | } 37 | const result= await axios.post(`${CLIENT_URL}/api/put_note`,sendData,headers) 38 | return result 39 | } -------------------------------------------------------------------------------- /src/components/CustomModal/CustomModal.css: -------------------------------------------------------------------------------- 1 | .cusmodal{ 2 | height: 100vh; 3 | width: 100%; 4 | display: flex; 5 | background-color: rgba(0,0,0, .8); 6 | justify-content: center; 7 | align-items: center; 8 | z-index: 9999; 9 | /* opacity: 0; */ 10 | /* visibility: hidden; */ 11 | transition: all .3s; 12 | box-sizing: border-box; 13 | } 14 | 15 | .cusmodal__main{ 16 | width: 80%; 17 | /* height: 70vh; */ 18 | /* background-color: red; */ 19 | padding: 30px; 20 | display: flex; 21 | flex-wrap: wrap; 22 | } 23 | 24 | .cusmodal__left{ 25 | flex: .35; 26 | background-color: var(--color-primary); 27 | color: white; 28 | display: flex; 29 | padding: 20px; 30 | justify-content: center; 31 | flex-direction: column; 32 | } 33 | 34 | .cusmodal__right{ 35 | flex: .65; 36 | height: inherit; 37 | overflow-y: auto; 38 | padding: 0 20px; 39 | background-color: white; 40 | position: relative; 41 | } 42 | 43 | .heading__primary{ 44 | font-size: 48px; 45 | font-weight: 800; 46 | } 47 | 48 | .heading__secondary{ 49 | margin-top: 10px; 50 | font-size: 16px; 51 | font-weight: 500; 52 | } 53 | 54 | .cusmodal__form{ 55 | margin: 70px 30px; 56 | } 57 | 58 | .cusmodal__form small{ 59 | font-weight: 900; 60 | color: darkgray; 61 | } 62 | 63 | .cusmodal__slider{ 64 | height: 150px; 65 | display: flex; 66 | align-items: center; 67 | } 68 | 69 | .cusmodal__button-container{ 70 | display: flex; 71 | flex-wrap: wrap; 72 | } 73 | 74 | .cusmodal__button-container__button{ 75 | display: flex; 76 | justify-content: center; 77 | align-items: center; 78 | text-align: center; 79 | padding: 5px 10px; 80 | margin: 1rem 1rem 0 0; 81 | height: 2.5rem; 82 | width: 8rem; 83 | border-radius: 25px; 84 | color: white; 85 | font-weight: 700; 86 | cursor: pointer; 87 | transition: .36s ease; 88 | border: none; 89 | outline: none; 90 | } 91 | 92 | .cusmodal__button-container__button:hover{ 93 | transform: scale(1.05); 94 | } 95 | 96 | .cusmodal__submit{ 97 | display: flex; 98 | justify-content: center; 99 | } -------------------------------------------------------------------------------- /src/components/CustomModal/CustomModal.js: -------------------------------------------------------------------------------- 1 | import { Grid, Paper, Slider } from "@material-ui/core"; 2 | import CancelIcon from '@material-ui/icons/Cancel'; 3 | import React, { useState } from "react"; 4 | import { Link } from "react-router-dom"; 5 | import "./CustomModal.css"; 6 | 7 | function CustomModal(props) { 8 | 9 | const [noOfQuestions, setNoOfQuestions] = useState(5) 10 | const [fib, setFib] = useState(false) 11 | const [mcq, setMcq] = useState(false) 12 | const [tf, setTf] = useState(false) 13 | 14 | function submitQuizForm(){ 15 | props.submitQuizForm(noOfQuestions,fib,mcq,tf) 16 | props.setOpenQuizForm(false) 17 | } 18 | 19 | return ( 20 |
21 | 22 | 23 |
24 |
25 |

Quiz Settings

26 |

Alright let's jump into the settings for how your quiz will be.

27 |
28 |
29 |
30 | props.setOpenQuizForm(false)} fontSize="large"/> 31 |
32 |
33 |

Quiz length

34 | Choose how long your quiz will be. You can always take another quiz after this one! 35 |
36 | valuetext} 39 | aria-labelledby="discrete-slider" 40 | valueLabelDisplay="on" 41 | step={1} 42 | marks 43 | min={1} 44 | max={99} 45 | onChange={(e,data) => setNoOfQuestions(data)} 46 | /> 47 |
48 | 49 |

Quiz type

50 | Unselect the question types you do not want on your quiz. Scroll to view more 51 |
52 | 56 | 60 | 64 | {/* */} 65 | {/* */} 66 |
67 | 68 |
69 | 74 |
75 |
76 |
77 |
78 |
79 | ); 80 | } 81 | 82 | export default CustomModal; 83 | -------------------------------------------------------------------------------- /src/components/Main/Main.css: -------------------------------------------------------------------------------- 1 | .main{ 2 | display: flex; 3 | flex-wrap: wrap; 4 | padding: 10px; 5 | } 6 | 7 | .main__left{ 8 | flex: 0.3; 9 | height: 1000px; 10 | border-right: 1px solid rgb(211, 199, 199); 11 | } 12 | 13 | .main__right{ 14 | flex: 0.7; 15 | margin-left: 2%; 16 | margin-top: 1%; 17 | } 18 | 19 | .ck-editor__editable { 20 | min-height: 90vh !important; 21 | border: none !important; 22 | } 23 | 24 | .ck-toolbar { 25 | background-color: black; 26 | border: none !important; 27 | } 28 | 29 | .ck-editor { 30 | background-color: black; 31 | } 32 | 33 | .main__right__toolbar{ 34 | margin-bottom: 2%; 35 | } 36 | 37 | .main__right__buttons{ 38 | display: flex; 39 | flex-direction: row; 40 | /* justify-content: space-between; */ 41 | /* margin-bottom: 5%; */ 42 | } 43 | 44 | .main__right__icons{ 45 | /* position: absolute; */ 46 | /* display: inline-flex; */ 47 | /* float: right; */ 48 | flex-direction: row; 49 | justify-content: flex-end; 50 | /* justifyContent: 'flex-end'; */ 51 | text-align: right; 52 | margin: 15px!important; 53 | } 54 | 55 | .main__header{ 56 | height: 50px; 57 | display: flex; 58 | align-items: center; 59 | margin-bottom: 30px; 60 | } 61 | 62 | .icon_container{ 63 | margin: 5px; 64 | background-color: var(--color-primary); 65 | padding: 5px; 66 | color: white; 67 | border-radius: 50%; 68 | display: flex; 69 | align-items: center; 70 | justify-content: center; 71 | } 72 | 73 | .main__header__title{ 74 | font-weight: 400; 75 | font-size: 28px; 76 | } 77 | 78 | .main__searchBar{ 79 | display: flex; 80 | justify-content: center; 81 | margin-bottom: 30px; 82 | } 83 | 84 | .searchBar{ 85 | font-family: inherit; 86 | color: inherit; 87 | padding: 5px 10px; 88 | border-radius: 2px; 89 | background-color: rbga(#fff, 0.5); 90 | border: none; 91 | outline: none; 92 | border-bottom: 3px solid transparent; 93 | width: 100%; 94 | display: block; 95 | transition: all .3s; 96 | } 97 | 98 | .main__list-item{ 99 | width: 95%; 100 | height: 100px; 101 | overflow: hidden; 102 | } 103 | 104 | .main__list-item:hover{ 105 | width: 100%; 106 | background-color: rgba(168, 131, 131, 0.1); 107 | cursor: pointer; 108 | } 109 | 110 | .main__item-content{ 111 | margin: 10px 10px; 112 | } 113 | 114 | 115 | .main__item-content-sub{ 116 | margin-top: 5px; 117 | font-size: small; 118 | color: gray; 119 | } 120 | 121 | .main__item__selected::before{ 122 | content: ""; 123 | position: absolute; 124 | top: 0; 125 | left: 0; 126 | height: 100%; 127 | width: 3px; 128 | background-color: var(--color-primary); 129 | transform: scaleY(0); 130 | transition: all 0.2s; 131 | } 132 | 133 | .main__item__selected:hover::before{ 134 | transform: scaleY(1); 135 | } 136 | 137 | .line-breaker{ 138 | margin: 4px 0; 139 | } 140 | 141 | .card__modal{ 142 | box-shadow: 0px 0px 3px 3px rgba(68, 68, 68, 0.6); 143 | /* 0 0 5px 5px gray!important; */ 144 | border-radius: 30px!important; 145 | min-width: 250px!important; 146 | min-height: 50px!important; 147 | } 148 | 149 | .card__container{ 150 | /* min-width: 60% !important; */ 151 | /* min-height: 80vh !important; */ 152 | height: 100%; 153 | overflow-y: auto; 154 | } 155 | 156 | .text_container{ 157 | size: 40px; 158 | margin: 0%!important; 159 | padding: 0%!important; 160 | } 161 | .main__header__btn{ 162 | display: flex; 163 | justify-content: center; 164 | align-items: center; 165 | text-align: center; 166 | color: white; 167 | padding: 5px 10px; 168 | margin: 1rem 1rem 0 0; 169 | height: 2.5rem; 170 | /* width: 5rem; */ 171 | border-radius: 25px; 172 | color: white; 173 | font-weight: 700; 174 | cursor: pointer; 175 | transition: .36s ease; 176 | border: none; 177 | outline: none; 178 | } 179 | -------------------------------------------------------------------------------- /src/components/Main/Main.js: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useEffect, useMemo, useState } from 'react' 2 | import './Main.css' 3 | import MenuIcon from '@material-ui/icons/Menu'; 4 | import { IconButton, InputAdornment, TextField } from '@material-ui/core'; 5 | import SearchIcon from "@material-ui/icons/Search"; 6 | import Button from '@material-ui/core/Button'; 7 | import { CKEditor } from '@ckeditor/ckeditor5-react'; 8 | import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; 9 | import EdiText from 'react-editext' 10 | import DeleteIcon from '@material-ui/icons/Delete'; 11 | import CancelIcon from '@material-ui/icons/Cancel'; 12 | import CloudUploadIcon from '@material-ui/icons/CloudUpload'; 13 | import Pagination from '@material-ui/lab/Pagination'; 14 | import axios from 'axios'; 15 | 16 | import { makeStyles } from '@material-ui/core/styles'; 17 | import Modal from '@material-ui/core/Modal'; 18 | import Card from '@material-ui/core/Card'; 19 | import CardActions from '@material-ui/core/CardActions'; 20 | import CardContent from '@material-ui/core/CardContent'; 21 | import Backdrop from '@material-ui/core/Backdrop'; 22 | import Fade from '@material-ui/core/Fade'; 23 | import { MicNone } from '@material-ui/icons'; 24 | import CustomModal from '../CustomModal/CustomModal'; 25 | import Quiz from '../Quiz/Quiz'; 26 | import { CLIENT_URL } from '../../const' 27 | import AddCircleIcon from '@material-ui/icons/AddCircle'; 28 | 29 | const useStyles = makeStyles((theme) => ({ 30 | modal: { 31 | display: 'flex', 32 | alignItems: 'center', 33 | justifyContent: 'center', 34 | }, 35 | paper: { 36 | backgroundColor: theme.palette.background.paper, 37 | boxShadow: theme.shadows[5], 38 | borderRadius: "20px", 39 | padding: theme.spacing(2, 4, 3), 40 | outline:"none", 41 | minHeight: "450px", 42 | minWidth: "200px", 43 | }, 44 | root: { 45 | '& > *': { 46 | marginTop: theme.spacing(2), 47 | }, 48 | }, 49 | })); 50 | 51 | function Main() { 52 | 53 | const [notes, setNotes] = useState([]) 54 | const [selectedNote, setSelectedNote] = useState(null) 55 | const [addData, setVal] = useState(""); 56 | const [titleValue, settitleValue] = useState('Enter title') 57 | // const [selectedFile, setSelectedFile] = useState(null); 58 | 59 | const classes = useStyles(); 60 | const [open, setOpen] = React.useState(false); 61 | const [summaryOpen, setSummaryOpen] = useState(false) 62 | const [summaryContent, setSummaryContent] = useState('') 63 | 64 | const [cards, setCards] = React.useState([]); 65 | const [questionsFetached, setQuestionsFetached] = useState([]) 66 | 67 | 68 | const [openQuizForm, setOpenQuizForm] = useState(false) 69 | const [showQuizPage, setShowQuizPage] = useState([]) // [selectedNote,noOfQuestions,fib,mcq,tf] 70 | 71 | async function getFlashCards(){ 72 | // request here to get cards 73 | let result = await axios.post(`${CLIENT_URL}/api/get_flashcards`, 74 | { 75 | number_of_flashcards : 7, 76 | note_id : selectedNote.id, 77 | }, 78 | { 79 | headers:{ 80 | 'Authorization':''+localStorage.token, 81 | } 82 | }) 83 | console.log(result) 84 | 85 | const card_array = [ 86 | { 87 | "antonyms": [ 88 | "fail", 89 | "reject", 90 | "disapprove", 91 | "pass" 92 | ], 93 | "meaning": { 94 | "Noun": [ 95 | "someone chosen to judge and decide a disputed issue" 96 | ] 97 | }, 98 | "synonyms": [ 99 | "arbiter", 100 | "judge", 101 | "third party", 102 | "evaluator" 103 | ], 104 | "word": "arbitrators" 105 | }, 106 | { 107 | "antonyms": [ 108 | "civilian", 109 | "nonworker" 110 | ], 111 | "meaning": { 112 | "Noun": [ 113 | "a person responsible for the editorial aspects of publication; the person who determines the final content of a text (especially of a newspaper or magazine", 114 | "(computer science" 115 | ] 116 | }, 117 | "synonyms": [ 118 | "skilled workman", 119 | "text editor", 120 | "reviser", 121 | "skilled worker" 122 | ], 123 | "word": "editors" 124 | }] 125 | 126 | setCards(result.data.data) 127 | } 128 | useEffect(() => { 129 | // 130 | axios.post(`${CLIENT_URL}/api/get_notes`, 131 | { 132 | user_id : JSON.parse(localStorage.user)[0].id 133 | }, 134 | { 135 | headers:{ 136 | 'Authorization':''+localStorage.token, 137 | } 138 | }) 139 | .then(response =>{ 140 | setNotes(response.data.data); 141 | return ({status : 'Success' ,message:"Document has been delivered"}) 142 | }) 143 | .catch(err =>{ 144 | return ({status : 'fail' ,message:"Unable to retreive document!",error:err}) 145 | }); 146 | 147 | }, []) 148 | // getNotes() 149 | 150 | // if(fetched_notes.length > 0){ 151 | // setSelectedNote(notes[0]) 152 | // setVal(notes[0].content) 153 | // settitleValue(notes[0].note_title) 154 | // } 155 | // }, []) 156 | 157 | async function saveNote() { 158 | console.log(addData) 159 | console.log(titleValue) 160 | console.log(selectedNote) 161 | let updated_note; 162 | let updated_notes_list = notes.map(async (n) => { 163 | if(n.id == selectedNote.id){ 164 | 165 | // UPDATE IN DATABASE TOO 166 | n.content = addData 167 | n.note_title = titleValue 168 | updated_note = n; 169 | } 170 | return n 171 | }) 172 | let n = updated_note; 173 | let result = await axios.post(`${CLIENT_URL}/api/update_note`, 174 | { 175 | note_id : n.id, 176 | note_title : n.note_title, 177 | note_content : n.content 178 | }, 179 | { 180 | headers:{ 181 | 'Authorization':''+localStorage.token, 182 | } 183 | }) 184 | result = await axios.post(`${CLIENT_URL}/api/get_notes`, 185 | 186 | { 187 | user_id : JSON.parse(localStorage.user)[0].id 188 | }, 189 | { 190 | headers:{ 191 | 'Authorization':''+localStorage.token, 192 | } 193 | }) 194 | setNotes(result.data.data) 195 | } 196 | 197 | async function addNote(){ 198 | // save data to db and get new note in return 199 | let result = await axios.post(`${CLIENT_URL}/api/put_note`, 200 | { 201 | user_id : JSON.parse(localStorage.user)[0].id, 202 | note_title : 'Dummy title', 203 | note_content : 'Enter your notes here :))' 204 | }, 205 | { 206 | headers:{ 207 | 'Authorization':''+localStorage.token, 208 | } 209 | }) 210 | result = await axios.post(`${CLIENT_URL}/api/get_notes`, 211 | 212 | { 213 | user_id : JSON.parse(localStorage.user)[0].id 214 | }, 215 | { 216 | headers:{ 217 | 'Authorization':''+localStorage.token, 218 | } 219 | }) 220 | setNotes(result.data.data) 221 | 222 | } 223 | 224 | const handleChangeforPage = (event, value) => { 225 | console.log(value); 226 | setCards(value); 227 | } 228 | 229 | const handleChange = (e, editor) => { 230 | const data = editor.getData(); 231 | setVal(data); 232 | } 233 | 234 | const handleSave = (val) => { 235 | // console.log('Edited Value -> ', val) 236 | settitleValue(val) 237 | } 238 | 239 | const submitFileForm = (e) => { 240 | const formData = new FormData(); 241 | formData.append("name", 'name'); 242 | formData.append("file", e.target.files[0]); 243 | 244 | console.log(formData) 245 | 246 | // Add form data here properly and access it by name of "file" in backend 247 | console.log('ocr called') 248 | axios 249 | .post(`${CLIENT_URL}/api/get_image_content`, formData, { headers: { 'Content-Type': 'multipart/form-data', 'Authorization':''+localStorage.token, } }) 250 | .then((res) => { 251 | // return Response({'Message':"recieved all questions", 'data': questions},status=status.HTTP_200_OK) 252 | alert(JSON.stringify(res.data)) 253 | 254 | setQuestionsFetached(res.data.data) 255 | // submitQuizForm(res.data.data.length,false,true,true) 256 | }) 257 | .catch((err) => alert(JSON.stringify(err))); 258 | 259 | } 260 | 261 | 262 | const generateSummary = async() => { 263 | // send axios req here 264 | let result = await axios.post(`${CLIENT_URL}/api/get_summary`, 265 | { 266 | note_id : selectedNote.id, 267 | }, 268 | { 269 | headers:{ 270 | 'Authorization':''+localStorage.token, 271 | } 272 | }) 273 | 274 | 275 | // const summaryResponse = 'akjsd amwend ndend we dwne dnwe nwe dwnb ed wn ednwb efn be fwebf' 276 | setSummaryOpen(true) 277 | setSummaryContent(result.data.data) 278 | } 279 | 280 | const handleOpen = () => { 281 | getFlashCards() 282 | setOpen(true); 283 | }; 284 | 285 | const handleClose = () => { 286 | setOpen(false); 287 | }; 288 | 289 | const handleSummaryOpen = () => { 290 | setSummaryOpen(true); 291 | }; 292 | 293 | const handleSummaryClose = () => { 294 | setSummaryOpen(false); 295 | }; 296 | 297 | 298 | 299 | function submitQuizForm(noOfQuestions,fib,mcq,tf){ 300 | // Number 301 | console.log(noOfQuestions) 302 | // true/false values 303 | console.log(fib) 304 | console.log(mcq) 305 | console.log(tf) 306 | 307 | // using currently selected note and above variables generate list of questions 308 | setShowQuizPage([selectedNote,noOfQuestions,fib,mcq,tf]) 309 | 310 | } 311 | 312 | 313 | if(openQuizForm){ 314 | return 315 | } 316 | if((showQuizPage && showQuizPage.length > 0) || (questionsFetached && questionsFetached.length > 0)){ 317 | return 318 | } 319 | 320 | return ( 321 |
322 |
323 | 324 |
325 |
326 | 327 |
328 |
329 | Qgen 330 |
331 | 332 |
333 | submitFileForm(e)} style={{display:"none"}} id="myfile" type="file" name="myfile" /> 334 | 335 |
336 |
337 |
338 | 339 |
340 | {/* */} 341 | 342 | {/* 349 | 350 | 351 | 352 | 353 | ) 354 | }} 355 | /> */} 356 |
357 | 358 |
359 |

363 | {notes.length} notes 364 |

365 |
366 | 367 | 368 | {/* List */} 369 |
370 | 371 | {notes.map(data => { 372 | return
{ 374 | setSelectedNote(data) 375 | setVal(data.content) 376 | settitleValue(data.note_title) 377 | }} 378 | style={{ 379 | position:"relative", 380 | backgroundColor:selectedNote && selectedNote.id == data.id ? null : null 381 | }} 382 | > 383 |
384 |
385 |

{data.note_title}

386 |

387 | {data.content} 388 |

389 |
390 |
391 |
392 |
393 | })} 394 | 395 |
396 | 397 |
398 | 399 | 400 |
401 | 402 |
403 |
404 | 405 |
406 | 407 | 419 | 420 |
421 |
422 | 423 |
424 |

425 |

Flashcards

426 |

The perfect flashes for your last minute revision

427 |

428 |

429 |
430 | {cards.map(data => { 431 | return
432 | 433 | 434 |

{ data.word }

435 |

436 |

Meaning

437 | { JSON.stringify(data.meaning) } 438 |



439 |

Synonymns

440 | { JSON.stringify(data.synonyms) } 441 |



442 |

Antonyms

443 | { JSON.stringify(data.antonyms) } 444 |
445 |
446 |

447 |
} 448 | )} 449 |
450 |
451 |
452 |
453 | 454 | 455 | 456 | {/* summary */} 457 | 469 | 470 |
471 |
472 | 473 |
474 |

475 |

Summary

476 |

Gist of your notes for easy learning

477 |

478 |

479 |
480 | {summaryContent} 481 |
482 |
483 |
484 |
485 | 486 | 487 | 488 | 489 | 490 |
491 |
492 | 498 | 504 | 511 |
512 |
513 |
514 | 515 |
516 | 517 |
518 |
519 | 522 | 523 | 524 |
525 | 531 |
532 | 533 | 537 |
538 | 539 |
540 | 541 |
542 | ) 543 | } 544 | 545 | 546 | export default Main 547 | -------------------------------------------------------------------------------- /src/components/Quiz/Quiz.css: -------------------------------------------------------------------------------- 1 | .quiz__grid{ 2 | display: flex; 3 | flex-wrap: wrap; 4 | } 5 | 6 | .quiz__grid__item{ 7 | border-radius: 50%; 8 | padding: 20px; 9 | background-color: #a9a9a9; 10 | color: white; 11 | margin: 5px; 12 | /* box-shadow: var(--shadow-dark); */ 13 | transition: all .3s; 14 | border: none; 15 | outline: none; 16 | text-align: center; 17 | cursor: pointer; 18 | } 19 | 20 | .quiz__grid__item:hover{ 21 | transform: scale(1.15); 22 | } 23 | 24 | .quiz__question__container{ 25 | margin: 30px 20px; 26 | padding: 30px; 27 | /* background-color: pink; */ 28 | } 29 | 30 | .quiz__question{ 31 | font-size: 24px; 32 | } 33 | 34 | .quiz__options{ 35 | margin: 10px 0; 36 | } 37 | 38 | .quiz__option{ 39 | display: flex; 40 | align-items: center; 41 | } 42 | 43 | .quiz__option__green{ 44 | background-color: green; 45 | } 46 | 47 | .quiz__option__text{ 48 | margin-left: 10px; 49 | } 50 | 51 | .quiz__option__selected{ 52 | background-color: var(--color-primary); 53 | } 54 | 55 | .quiz__submit_container{ 56 | display: flex; 57 | justify-content: center; 58 | margin: 20px 0; 59 | } 60 | 61 | .quiz__submit__button{ 62 | background-color: black; 63 | color: white; 64 | outline: none; 65 | border: none; 66 | font-size: 20px; 67 | border-radius: 20px; 68 | padding: 10px; 69 | transition: all .3s; 70 | cursor: pointer; 71 | } 72 | 73 | .quiz__submit__button:hover{ 74 | transform: scale(1.3); 75 | } -------------------------------------------------------------------------------- /src/components/Quiz/Quiz.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import './Quiz.css' 3 | import CancelIcon from '@material-ui/icons/Cancel'; 4 | import axios from 'axios'; 5 | import { CLIENT_URL } from '../../const' 6 | function Quiz(props) { 7 | 8 | const [questions, setQuestions] = useState([]) 9 | const [showResult, setShowResult] = useState(false) 10 | 11 | useEffect(() => { 12 | 13 | if(props.questionsFetached.length > 0){ 14 | setQuestions(props.questionsFetached) 15 | return 16 | } 17 | 18 | // Based on below data generate and retrieve question-answers from database 19 | // props.showQuizPage => [selectedNote,noOfQuestions,fib,mcq,tf] 20 | console.log(props.showQuizPage) 21 | 22 | 23 | async function getQuestions(){ 24 | // request here 25 | let result = await axios.post(`${CLIENT_URL}/api/get_questions`, 26 | { 27 | note_id : props.showQuizPage[0].id, 28 | number_of_questions : props.showQuizPage[1], 29 | types_of_questions : [props.showQuizPage[2], props.showQuizPage[3], props.showQuizPage[4]] 30 | }, 31 | { 32 | headers:{ 33 | 'Authorization':''+localStorage.token, 34 | } 35 | }) 36 | const questions_array =[ 37 | { 38 | "id":"1", 39 | "question":"jwenbj mwe n ewjd njwe wemnjcwhe jwn ncwe", 40 | "options":["asasxcas","3knej3","sank","sdcsdcs"], 41 | "correct_answer":"sdcsdcs", 42 | "marked_answer":-1, 43 | "type":"mcq", 44 | }, 45 | { 46 | "id":"29", 47 | "question":"njwe wemnjcwhe jwn ncwe jwenbj mwe n ewjd njwe wemnjcwhe jwn ncwe", 48 | "options":["asasxcas","3knej3","sank","sdcsdcs"], 49 | "correct_answer":"sank", 50 | "marked_answer":-1, 51 | "type":"mcq" 52 | }, 53 | { 54 | "id":"90", 55 | "question":"jwenbj mwe n ewjd njwe wemnjcwhe jwn ncwe", 56 | "options":["asasxcas","3knej3","sank","sdcsdcs"], 57 | "correct_answer":"3knej3", 58 | "marked_answer":-1, 59 | "type":"mcq" 60 | }, 61 | { 62 | "id":"671", 63 | "question":"njwe wemnjcwhe jwn ncwe jwenbj mwe n ewjd njwe wemnjcwhe jwn ncwe", 64 | "options":["asasxcas","3knej3","sank","sdcsdcs"], 65 | "correct_answer":"asasxcas", 66 | "marked_answer":-1, 67 | "type":"mcq" 68 | }, 69 | { 70 | "id":"11", 71 | "question":"jwenbj mwe n ewjd njwe wemnjcwhe jwn ncwe", 72 | "options":["asasxcas","3knej3","sank","sdcsdcs"], 73 | "correct_answer":"sdcsdcs", 74 | "marked_answer":-1, 75 | "type":"mcq", 76 | }, 77 | { 78 | "id":"291", 79 | "question":"njwe wemnjcwhe jwn ncwe jwenbj mwe n ewjd njwe wemnjcwhe jwn ncwe", 80 | "options":["asasxcas","3knej3","sank","sdcsdcs"], 81 | "correct_answer":"sank", 82 | "marked_answer":-1, 83 | "type":"mcq" 84 | }, 85 | { 86 | "id":"901", 87 | "question":"jwenbj mwe n ewjd njwe wemnjcwhe jwn ncwe", 88 | "options":["asasxcas","3knej3","sank","sdcsdcs"], 89 | "correct_answer":"3knej3", 90 | "marked_answer":-1, 91 | "type":"mcq" 92 | }, 93 | { 94 | "id":"67", 95 | "question":"njwe wemnjcwhe jwn ncwe jwenbj mwe n ewjd njwe wemnjcwhe jwn ncwe", 96 | "options":["asasxcas","3knej3","sank","sdcsdcs"], 97 | "correct_answer":"asasxcas", 98 | "marked_answer":-1, 99 | "type":"mcq" 100 | } 101 | ] 102 | 103 | setQuestions(result.data.data) 104 | } 105 | getQuestions() 106 | }, []) 107 | 108 | function markAnswer(q,optn,j){ 109 | let updated_list = questions.map((obj) => { 110 | if(obj.id === q.id){ 111 | obj = { 112 | ...obj, 113 | marked_answer : optn 114 | } 115 | } 116 | return obj 117 | }); 118 | setQuestions(updated_list) 119 | } 120 | 121 | function evaluate(){ 122 | let score = 0 123 | setShowResult(true) 124 | console.log(questions) 125 | for(var i=0;i 136 | 137 |
138 |
139 |
140 | Assignment Navigation 141 |
142 | 143 | 144 |



145 | 146 |
147 | Quick Access 148 |
149 |

150 | 151 |
152 | {questions.map((data,index) => { 153 | return <> 154 | 160 | 161 | })} 162 |
163 |
164 |
165 | 166 | 167 |
168 | props.setShowQuizPage(false)} fontSize="large"/> 169 |
170 | 171 |
176 |
177 | {questions.map((q,index) => { 178 | 179 | return
180 |
181 | {index+1}) {q.question} 182 |
183 | 184 |
185 | {q.options.map((optn,j) => { 186 | let str_class="" 187 | 188 | if(optn === q.marked_answer){ 189 | str_class = str_class + "quiz__grid__item quiz__option__selected " 190 | } 191 | else{ 192 | str_class = str_class + "quiz__grid__item " 193 | } 194 | 195 | if (optn === q.correct_answer && showResult) 196 | { 197 | str_class = str_class+ "quiz__option quiz__option__green " 198 | } 199 | else{ 200 | str_class = str_class + "quiz__option " 201 | } 202 | 203 | return
204 | 211 |
{optn}
212 |
213 | })} 214 |
215 |
216 | })} 217 |

218 | 219 |
220 | 225 |
226 | 227 |
228 | 229 | 230 | ) 231 | } 232 | 233 | export default Quiz 234 | -------------------------------------------------------------------------------- /src/const.js: -------------------------------------------------------------------------------- 1 | export const CLIENT_URL = "https://dc5d75fb6e73.ngrok.io" -------------------------------------------------------------------------------- /src/features/counter/Counter.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { useSelector, useDispatch } from 'react-redux'; 3 | import { 4 | decrement, 5 | increment, 6 | incrementByAmount, 7 | incrementAsync, 8 | selectCount, 9 | } from './counterSlice'; 10 | import styles from './Counter.module.css'; 11 | 12 | export function Counter() { 13 | const count = useSelector(selectCount); 14 | const dispatch = useDispatch(); 15 | const [incrementAmount, setIncrementAmount] = useState('2'); 16 | 17 | return ( 18 |
19 |
20 | 27 | {count} 28 | 35 |
36 |
37 | setIncrementAmount(e.target.value)} 42 | /> 43 | 51 | 57 |
58 |
59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /src/features/counter/Counter.module.css: -------------------------------------------------------------------------------- 1 | .row { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | 7 | .row:not(:last-child) { 8 | margin-bottom: 16px; 9 | } 10 | 11 | .value { 12 | font-size: 78px; 13 | padding-left: 16px; 14 | padding-right: 16px; 15 | margin-top: 2px; 16 | font-family: 'Courier New', Courier, monospace; 17 | } 18 | 19 | .button { 20 | appearance: none; 21 | background: none; 22 | font-size: 32px; 23 | padding-left: 12px; 24 | padding-right: 12px; 25 | outline: none; 26 | border: 2px solid transparent; 27 | color: rgb(112, 76, 182); 28 | padding-bottom: 4px; 29 | cursor: pointer; 30 | background-color: rgba(112, 76, 182, 0.1); 31 | border-radius: 2px; 32 | transition: all 0.15s; 33 | } 34 | 35 | .textbox { 36 | font-size: 32px; 37 | padding: 2px; 38 | width: 64px; 39 | text-align: center; 40 | margin-right: 8px; 41 | } 42 | 43 | .button:hover, .button:focus { 44 | border: 2px solid rgba(112, 76, 182, 0.4); 45 | } 46 | 47 | .button:active { 48 | background-color: rgba(112, 76, 182, 0.2); 49 | } 50 | 51 | .asyncButton { 52 | composes: button; 53 | position: relative; 54 | margin-left: 8px; 55 | } 56 | 57 | .asyncButton:after { 58 | content: ""; 59 | background-color: rgba(112, 76, 182, 0.15); 60 | display: block; 61 | position: absolute; 62 | width: 100%; 63 | height: 100%; 64 | left: 0; 65 | top: 0; 66 | opacity: 0; 67 | transition: width 1s linear, opacity 0.5s ease 1s; 68 | } 69 | 70 | .asyncButton:active:after { 71 | width: 0%; 72 | opacity: 1; 73 | transition: 0s 74 | } 75 | -------------------------------------------------------------------------------- /src/features/counter/counterSlice.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from '@reduxjs/toolkit'; 2 | 3 | export const counterSlice = createSlice({ 4 | name: 'counter', 5 | initialState: { 6 | value: 0, 7 | }, 8 | reducers: { 9 | increment: state => { 10 | // Redux Toolkit allows us to write "mutating" logic in reducers. It 11 | // doesn't actually mutate the state because it uses the Immer library, 12 | // which detects changes to a "draft state" and produces a brand new 13 | // immutable state based off those changes 14 | state.value += 1; 15 | }, 16 | decrement: state => { 17 | state.value -= 1; 18 | }, 19 | incrementByAmount: (state, action) => { 20 | state.value += action.payload; 21 | }, 22 | }, 23 | }); 24 | 25 | export const { increment, decrement, incrementByAmount } = counterSlice.actions; 26 | 27 | // The function below is called a thunk and allows us to perform async logic. It 28 | // can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This 29 | // will call the thunk with the `dispatch` function as the first argument. Async 30 | // code can then be executed and other actions can be dispatched 31 | export const incrementAsync = amount => dispatch => { 32 | setTimeout(() => { 33 | dispatch(incrementByAmount(amount)); 34 | }, 1000); 35 | }; 36 | 37 | // The function below is called a selector and allows us to select a value from 38 | // the state. Selectors can also be defined inline where they're used instead of 39 | // in the slice file. For example: `useSelector((state) => state.counter.value)` 40 | export const selectCount = state => state.counter.value; 41 | 42 | export default counterSlice.reducer; 43 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 store from './app/store'; 6 | import { Provider } from 'react-redux'; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | 12 | 13 | , 14 | document.getElementById('root') 15 | ); 16 | --------------------------------------------------------------------------------