├── .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://www.djangoproject.com/)
4 |
5 | [](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 |
28 | Add/Edit Notes📕
29 | Based on your notes generate
30 |
31 | Quiz
32 |
33 | MCQs 📝
34 | True/False ✔️ ❎
35 | Fill in the blanks ❓
36 |
37 | Summary ✒️
38 | Flashcards 🔖
39 | Q/A from images 🚞
40 |
41 |
42 |
43 |
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 | You need to enable JavaScript to run this app.
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 |
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 | setMcq(!mcq)}
54 | className="cusmodal__button-container__button"
55 | style={{backgroundColor: "mediumturquoise"}}>Multiple Choice
56 | setFib(!fib)}
58 | className="cusmodal__button-container__button"
59 | style={{backgroundColor:"burlywood"}}>Fill In Blanks
60 | setTf(!tf)}
62 | className="cusmodal__button-container__button"
63 | style={{backgroundColor: "#f18888"}}>True/False
64 | {/* Multiple Choice */}
65 | {/* Multiple Choice */}
66 |
67 |
68 |
69 | Quiz Me
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 |
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 |
496 | Flashcards
497 |
498 | setOpenQuizForm(true)}>
502 | Quiz
503 |
504 | generateSummary()}
508 | >
509 | Summarize
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
525 |
529 | SAVE
530 |
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 |
155 |
156 | {index+1}
157 |
158 |
159 |
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 |
markAnswer(q,optn,j)}
206 | className={str_class}>
207 |
208 | {j+1}
209 |
210 |
211 |
{optn}
212 |
213 | })}
214 |
215 |
216 | })}
217 |
218 |
219 |
220 |
223 | Submit
224 |
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 | dispatch(increment())}
24 | >
25 | +
26 |
27 | {count}
28 | dispatch(decrement())}
32 | >
33 | -
34 |
35 |
36 |
37 | setIncrementAmount(e.target.value)}
42 | />
43 |
46 | dispatch(incrementByAmount(Number(incrementAmount) || 0))
47 | }
48 | >
49 | Add Amount
50 |
51 | dispatch(incrementAsync(Number(incrementAmount) || 0))}
54 | >
55 | Add Async
56 |
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 |
--------------------------------------------------------------------------------