├── Frontend ├── src │ ├── Redux │ │ ├── action.js │ │ ├── actionTypes.js │ │ ├── store.js │ │ └── reducer.js │ ├── App.css │ ├── assets │ │ ├── codev.png │ │ ├── codebg.png │ │ ├── logobg.png │ │ ├── Code Vertax (1).png │ │ ├── CodeVertexLogin.png │ │ ├── CodeVortexHome.png │ │ ├── CodeVertexSignup.png │ │ ├── CodeVertexForgotPass.png │ │ ├── CodeVortexInterview.png │ │ ├── CodeVortexScoresPage.png │ │ ├── CodeVortexFeedbackpage.png │ │ └── CodeVortexFeedbackGenerationPage.png │ ├── images │ │ └── code-vortex-logo.png │ ├── component │ │ ├── Question.jsx │ │ ├── animations.css │ │ ├── PrivateRoute.jsx │ │ ├── SpeechToText.css │ │ ├── AllRoutes.jsx │ │ ├── FeedbackCard.jsx │ │ ├── Navbar.jsx │ │ └── SpeechToText.jsx │ ├── setupTests.js │ ├── reportWebVitals.js │ ├── index.css │ ├── Pages │ │ ├── InterviewPage.jsx │ │ ├── scores.css │ │ ├── Score.jsx │ │ ├── FeedbackPage.jsx │ │ ├── ForgotPassword.jsx │ │ ├── Login.jsx │ │ ├── Signup.jsx │ │ ├── Home.jsx │ │ └── PerfomanceFeedback.jsx │ ├── index.js │ ├── App.jsx │ ├── Hooks │ │ └── useVerify.js │ ├── css │ │ ├── login.css │ │ ├── signup.css │ │ └── forgotpassword.css │ └── logo.svg ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── .env ├── .gitignore ├── tailwind.config.js ├── package.json └── README.md ├── Backend ├── .gitignore ├── Models │ ├── blacklist.model.js │ ├── user.model.js │ └── history.model.js ├── config │ └── db.js ├── README.md ├── Routes │ ├── History.Routes.js │ ├── Users.Routes.js │ └── Questions.Routes.js ├── package.json ├── middleware │ └── jwtAuth.middleware.js └── index.js ├── .gitignore └── README.md /Frontend/src/Redux/action.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Backend/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local Netlify folder 2 | .netlify 3 | -------------------------------------------------------------------------------- /Frontend/src/App.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } -------------------------------------------------------------------------------- /Frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/public/favicon.ico -------------------------------------------------------------------------------- /Frontend/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/public/logo192.png -------------------------------------------------------------------------------- /Frontend/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/public/logo512.png -------------------------------------------------------------------------------- /Frontend/src/assets/codev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/codev.png -------------------------------------------------------------------------------- /Frontend/src/assets/codebg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/codebg.png -------------------------------------------------------------------------------- /Frontend/src/assets/logobg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/logobg.png -------------------------------------------------------------------------------- /Frontend/src/assets/Code Vertax (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/Code Vertax (1).png -------------------------------------------------------------------------------- /Frontend/src/assets/CodeVertexLogin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/CodeVertexLogin.png -------------------------------------------------------------------------------- /Frontend/src/assets/CodeVortexHome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/CodeVortexHome.png -------------------------------------------------------------------------------- /Frontend/src/assets/CodeVertexSignup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/CodeVertexSignup.png -------------------------------------------------------------------------------- /Frontend/src/images/code-vortex-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/images/code-vortex-logo.png -------------------------------------------------------------------------------- /Frontend/src/assets/CodeVertexForgotPass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/CodeVertexForgotPass.png -------------------------------------------------------------------------------- /Frontend/src/assets/CodeVortexInterview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/CodeVortexInterview.png -------------------------------------------------------------------------------- /Frontend/src/assets/CodeVortexScoresPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/CodeVortexScoresPage.png -------------------------------------------------------------------------------- /Frontend/.env: -------------------------------------------------------------------------------- 1 | NODE_ENV = developemnt; 2 | REACT_APP_LOCAL_URL = http://localhost:5000 3 | REACT_APP_PROD_URL = https://tiny-pear-jaguar-veil.cyclic.app -------------------------------------------------------------------------------- /Frontend/src/assets/CodeVortexFeedbackpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/CodeVortexFeedbackpage.png -------------------------------------------------------------------------------- /Frontend/src/assets/CodeVortexFeedbackGenerationPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingDemon1/CodeVortex/HEAD/Frontend/src/assets/CodeVortexFeedbackGenerationPage.png -------------------------------------------------------------------------------- /Frontend/src/component/Question.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Question = ({ question }) => { 4 | console.log(question); 5 | return
{question}
; 6 | }; 7 | 8 | export default Question; 9 | -------------------------------------------------------------------------------- /Frontend/src/Redux/actionTypes.js: -------------------------------------------------------------------------------- 1 | export const USER_AUTH = "USER_AUTH"; 2 | export const QUESTIONS_UPDATE = "QUESTIONS_UPDATE"; 3 | export const UPDATE_ANSWER = "UPDATE_ANSWER"; 4 | export const INTERVIEW_FEEDBACK = "INTERVIEW_FEEDBACK"; 5 | export const USER_LOGOUT = "USER_LOGOUT"; -------------------------------------------------------------------------------- /Frontend/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Backend/Models/blacklist.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const blacklistSchema = mongoose.Schema({ 4 | token: String, 5 | }); 6 | 7 | const Blacklist = mongoose.model("blacklist", blacklistSchema); 8 | 9 | module.exports = { 10 | Blacklist, 11 | }; 12 | -------------------------------------------------------------------------------- /Backend/Models/user.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const userSchema = mongoose.Schema({ 3 | email: String, 4 | name: String, 5 | password: String, 6 | }); 7 | 8 | const UserModel = mongoose.model("user", userSchema); 9 | 10 | module.exports = { UserModel }; 11 | -------------------------------------------------------------------------------- /Frontend/src/Redux/store.js: -------------------------------------------------------------------------------- 1 | import { applyMiddleware, combineReducers, legacy_createStore } from "redux"; 2 | import { reducer } from "./reducer"; 3 | import thunk from "redux-thunk"; 4 | 5 | const rootReducer = combineReducers({ reducer }); 6 | 7 | export const store = legacy_createStore(rootReducer, applyMiddleware(thunk)); 8 | -------------------------------------------------------------------------------- /Backend/config/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | require("dotenv").config(); 3 | 4 | const connection = async () => { 5 | try { 6 | await mongoose.connect(process.env.mongoURL); 7 | console.log("Connected to DB"); 8 | } catch (error) { 9 | console.log(error); 10 | } 11 | }; 12 | 13 | module.exports = { connection }; 14 | -------------------------------------------------------------------------------- /Frontend/src/component/animations.css: -------------------------------------------------------------------------------- 1 | @keyframes pulse { 2 | 0%, 100% { 3 | opacity: 1; 4 | } 5 | 50% { 6 | opacity: .5; 7 | } 8 | } 9 | 10 | @keyframes marquee { 11 | 0% { transform: translateX(100%); } 12 | 100% { transform: translateX(-100%); } 13 | } 14 | 15 | .animate-marquee { 16 | animation: marquee 8s linear infinite reverse; 17 | } 18 | -------------------------------------------------------------------------------- /Backend/Models/history.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | //History Schema 4 | const historySchema = mongoose.Schema( 5 | { 6 | body: String, 7 | userID: String, 8 | date: String, 9 | }, 10 | { 11 | versionKey: false, 12 | } 13 | ); 14 | 15 | const HistoryModel = mongoose.model("history", historySchema); 16 | 17 | module.exports = { HistoryModel }; 18 | -------------------------------------------------------------------------------- /Frontend/.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 | -------------------------------------------------------------------------------- /Frontend/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 4 | theme: { 5 | extend: {}, 6 | screens: { 7 | sm: "640px", 8 | 9 | md: "768px", 10 | 11 | lg: "1024px", 12 | 13 | xl: "1280px", 14 | 15 | "2xl": "1536px", 16 | // => @media (min-width: 1536px) { ... } 17 | }, 18 | }, 19 | plugins: [], 20 | }; 21 | -------------------------------------------------------------------------------- /Frontend/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Frontend/src/component/PrivateRoute.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useSelector } from "react-redux"; 3 | import { Navigate, useLocation } from "react-router"; 4 | 5 | const PrivateRoute = ({ children }) => { 6 | const auth = useSelector((store) => store.reducer.auth); 7 | const location = useLocation(); 8 | 9 | if (auth) { 10 | return children; 11 | } 12 | 13 | return ; 14 | }; 15 | 16 | export default PrivateRoute; 17 | -------------------------------------------------------------------------------- /Frontend/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | margin: 0; 7 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 8 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 9 | sans-serif; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | code { 15 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 16 | monospace; 17 | } -------------------------------------------------------------------------------- /Backend/README.md: -------------------------------------------------------------------------------- 1 | - To run backend, Please follow these steps: 2 | 3 | 1. Installation of node modules: 4 | **npm i express dotenv openai** 5 | 6 | 2. Create .env file in /backend folder 7 | 8 | 3. Put your openai api key in .env i.e. : 9 | **OPENAI_API_KEY = yourapikeyhere** 10 | 11 | **For getting openai api key go to: https://platform.openai.com/ > login > Click on profile icon > Click on "View API Keys" > Click on create new secret key** 12 | 13 | 4. After all run command **npm start** to run the backend -------------------------------------------------------------------------------- /Frontend/src/Pages/InterviewPage.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import SpeechToText from "../component/SpeechToText"; 3 | import { useSelector } from "react-redux"; 4 | 5 | const InterviewPage = () => { 6 | const questions = useSelector((store) => store.reducer.question); 7 | const questionNumber = useSelector((store) => store.reducer.questionNumber); 8 | 9 | return ( 10 |
11 | 12 |
13 | ); 14 | }; 15 | 16 | export default InterviewPage; 17 | -------------------------------------------------------------------------------- /Frontend/src/component/SpeechToText.css: -------------------------------------------------------------------------------- 1 | .toggle { 2 | animation: toggleAnimation 1.5s linear infinite; 3 | border-radius: 50%; 4 | opacity: 1; 5 | } 6 | 7 | @keyframes toggleAnimation { 8 | 0% { 9 | background-color: rgba(255, 0, 0, 10%); 10 | } 11 | 12 | 25% { 13 | background-color: rgba(255, 0, 0, 25%); 14 | } 15 | 16 | 50% { 17 | background-color: rgba(255, 0, 0, 45%); 18 | } 19 | 20 | 75% { 21 | background-color: rgba(255, 0, 0, 30%); 22 | } 23 | 24 | 100% { 25 | background-color: rgba(255, 0, 0, 10%); 26 | } 27 | } -------------------------------------------------------------------------------- /Backend/Routes/History.Routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const HistoryRoute = express.Router(); 3 | const { HistoryModel } = require("../Models/history.model"); 4 | 5 | //Get User Specific history 6 | HistoryRoute.get("/:id", async (req, res) => { 7 | const id = req.params.id; 8 | // console.log("IM HERE VERIFY", id); 9 | try { 10 | const data = await HistoryModel.find({ userID: id }); 11 | console.log(data, "DATA"); 12 | res.status(200).send(data); 13 | } catch (err) { 14 | res.status(400).send({ msg: err.message }); 15 | } 16 | }); 17 | 18 | module.exports = { HistoryRoute }; 19 | -------------------------------------------------------------------------------- /Frontend/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 | -------------------------------------------------------------------------------- /Backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "bcrypt": "^5.1.0", 15 | "cors": "^2.8.5", 16 | "dotenv": "^16.3.1", 17 | "express": "^4.18.2", 18 | "jsonwebtoken": "^9.0.0", 19 | "mongoose": "^7.3.1", 20 | "nodemon": "^2.0.22", 21 | "openai": "^3.3.0", 22 | "socket.io": "^4.7.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Backend/middleware/jwtAuth.middleware.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | require("dotenv").config(); 3 | 4 | const verify = async (req, res, next) => { 5 | try { 6 | // console.log(req.header("Auth")); 7 | const tkn = req.header("Auth"); 8 | const decoded = jwt.verify(tkn, process.env.secretKey); 9 | if (decoded) { 10 | req.body.userId = decoded.userID; 11 | // console.log(decoded); 12 | next(); 13 | } else { 14 | res.status(400).send({ msg: "Something Went Wrong" }); 15 | } 16 | } catch (error) { 17 | res.status(400).send({ msg: error.message }); 18 | } 19 | }; 20 | 21 | module.exports = { verify }; 22 | -------------------------------------------------------------------------------- /Frontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import reportWebVitals from "./reportWebVitals"; 6 | import { BrowserRouter } from "react-router-dom"; 7 | import { ChakraProvider } from "@chakra-ui/react"; 8 | import { store } from "./Redux/store"; 9 | import { Provider } from "react-redux"; 10 | 11 | const root = ReactDOM.createRoot(document.getElementById("root")); 12 | root.render( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | 22 | // If you want to start measuring performance in your app, pass a function 23 | // to log results (for example: reportWebVitals(console.log)) 24 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 25 | reportWebVitals(); 26 | -------------------------------------------------------------------------------- /Frontend/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import "./App.css"; 3 | import AllRoutes from "./component/AllRoutes"; 4 | import Navbar from "./component/Navbar"; 5 | import useVerify from "./Hooks/useVerify"; 6 | import { useDispatch, useSelector } from "react-redux"; 7 | import { USER_AUTH } from "./Redux/actionTypes"; 8 | // import SpeechToText from "./component/SpeechToText"; 9 | 10 | function App() { 11 | const { verified, user, token } = useVerify(); 12 | // console.log(verified, user, token); 13 | 14 | const dispatch = useDispatch(); 15 | // const store = useSelector((store) => store.reducer); 16 | 17 | useEffect(() => { 18 | dispatch({ type: USER_AUTH, auth: verified, payload: user, token: token }); 19 | }, [verified]); 20 | 21 | return ( 22 |
23 | 24 | 25 | {/* */} 26 |
27 | ); 28 | } 29 | 30 | export default App; 31 | -------------------------------------------------------------------------------- /Backend/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const cors = require("cors"); 3 | require("dotenv").config(); 4 | const { UserRoute } = require("./Routes/Users.Routes"); 5 | const { QuestionRoute } = require("./Routes/Questions.Routes"); 6 | const { HistoryRoute } = require("./Routes/History.Routes"); 7 | const { connection } = require("./config/db"); 8 | 9 | const app = express(); 10 | app.use(cors()) 11 | app.use(express.json()); 12 | 13 | //Routes 14 | app.get("/", (req, res) => { 15 | res.status(200).send("Welcome to the backend of CodeVortex"); 16 | }); 17 | app.use("/user", UserRoute); 18 | app.use("/question", QuestionRoute); 19 | app.use("/history", HistoryRoute); 20 | 21 | 22 | //Server Running 23 | const port = process.env.PORT || 5000; 24 | 25 | app.listen(port, async () => { 26 | try { 27 | await connection(); 28 | console.log(`Listening at port - ${port}`); 29 | } catch (error) { 30 | console.error(error.message); 31 | } 32 | }); -------------------------------------------------------------------------------- /Frontend/src/Pages/scores.css: -------------------------------------------------------------------------------- 1 | .score-container { 2 | display: flex; 3 | justify-content: center; 4 | background-color: #f8f8f8; 5 | /* Change the background color to match your navbar color */ 6 | padding: 20px; 7 | } 8 | 9 | .feedback-list { 10 | width: 50%; 11 | } 12 | 13 | .card { 14 | background-color: #fff; 15 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); 16 | border-radius: 4px; 17 | padding: 16px; 18 | margin-bottom: 16px; 19 | transition: transform 0.3s ease; 20 | } 21 | 22 | .card:hover { 23 | transform: translateY(-4px); 24 | } 25 | 26 | .card-header { 27 | /* background-color: #007bff; /* Change the background color to match your navbar color */ 28 | color: black; 29 | 30 | border-radius: 4px 4px 0 0; 31 | padding: 8px; 32 | /* margin-bottom: 8px; */ 33 | } 34 | 35 | .score { 36 | font-size: 18px; 37 | font-weight: bold; 38 | /* margin-bottom: 8px; */ 39 | } 40 | 41 | .author { 42 | color: #eee; 43 | margin: 0; 44 | } 45 | 46 | .message { 47 | color: #444; 48 | margin: 0; 49 | } -------------------------------------------------------------------------------- /Frontend/src/Redux/reducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | INTERVIEW_FEEDBACK, 3 | QUESTIONS_UPDATE, 4 | UPDATE_ANSWER, 5 | USER_AUTH, 6 | USER_LOGOUT, 7 | } from "./actionTypes"; 8 | 9 | const initialState = { 10 | auth: false, 11 | token: "", 12 | question: {}, 13 | feedback: "", 14 | user: { name: "", _id: localStorage.getItem("id") || "", email: "" }, 15 | }; 16 | 17 | export const reducer = (state = initialState, action) => { 18 | switch (action.type) { 19 | case USER_AUTH: 20 | return { 21 | ...state, 22 | auth: action.auth, 23 | user: action.payload, 24 | token: action.token, 25 | }; 26 | 27 | case QUESTIONS_UPDATE: 28 | return { ...state, question: action.payload }; 29 | 30 | case INTERVIEW_FEEDBACK: 31 | return { ...state, feedback: action.payload }; 32 | 33 | case UPDATE_ANSWER: 34 | console.log("INREDUX", action.payload); 35 | return { 36 | ...state, 37 | question: action.payload, 38 | }; 39 | case USER_LOGOUT: 40 | return initialState; 41 | 42 | default: { 43 | return state; 44 | } 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /Frontend/src/Hooks/useVerify.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import axios from "axios"; 3 | 4 | const useVerify = () => { 5 | const [verified, setverified] = useState(true); 6 | const [user, setUser] = useState(""); 7 | const [token, setToken] = useState(""); 8 | 9 | const url = 10 | process.env.NODE_ENV == "development" 11 | ? process.env.REACT_APP_LOCAL_URL 12 | : process.env.REACT_APP_PROD_URL; 13 | 14 | useEffect(() => { 15 | console.log(`${url}/user/verify`); 16 | verifyToken(); 17 | }, []); 18 | 19 | function verifyToken() { 20 | axios 21 | .get(`${url}/user/verify`, { 22 | headers: { 23 | "Content-Type": "application/json", 24 | Auth: localStorage.getItem("token"), 25 | }, 26 | }) 27 | .then((res) => { 28 | console.log(res); 29 | if (res.data.msg == "Success") { 30 | setverified(true); 31 | setUser(res.data.user); 32 | setToken(res.data.token); 33 | } else { 34 | setverified(false); 35 | } 36 | }) 37 | .catch((err) => { 38 | console.log(err); 39 | setverified(false); 40 | }); 41 | } 42 | 43 | return { verified, user, token }; 44 | }; 45 | 46 | export default useVerify; 47 | -------------------------------------------------------------------------------- /Frontend/src/component/AllRoutes.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Routes, Route } from "react-router-dom"; 3 | import Home from "../Pages/Home"; 4 | import Login from "../Pages/Login"; 5 | import Signup from "../Pages/Signup"; 6 | import InterviewPage from "../Pages/InterviewPage"; 7 | import ForgotPassword from "../Pages/ForgotPassword"; 8 | import PrivateRoute from "./PrivateRoute"; 9 | import Score from "../Pages/Score"; 10 | import FeedbackPage from "../Pages/FeedbackPage"; 11 | 12 | function AllRoutes() { 13 | return ( 14 | 15 | 19 | 20 | 21 | } 22 | /> 23 | } /> 24 | } /> 25 | 29 | 30 | 31 | } 32 | /> 33 | 37 | 38 | 39 | } 40 | /> 41 | 45 | 46 | 47 | } 48 | /> 49 | } /> 50 | 51 | ); 52 | } 53 | 54 | export default AllRoutes; 55 | // 56 | -------------------------------------------------------------------------------- /Frontend/src/css/login.css: -------------------------------------------------------------------------------- 1 | #container { 2 | display: flex; 3 | justify-content: center; 4 | flex-direction: column; 5 | align-items: center; 6 | height: 100vh; 7 | } 8 | 9 | #login-card { 10 | border: 2px solid rgba(148, 154, 148, 0.099); 11 | width: 400px; 12 | text-align: center; 13 | border-radius: 20px; 14 | box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; 15 | } 16 | 17 | #login-card>div { 18 | margin: auto; 19 | width: 300px; 20 | padding: 10px; 21 | text-align: left; 22 | margin: 30px; 23 | } 24 | 25 | #login-card>div>form { 26 | width: 100%; 27 | } 28 | 29 | #login-card>div>form>input { 30 | width: 98%; 31 | padding: 10px; 32 | margin: 5px; 33 | border: 2px solid rgba(155, 155, 160, 0.085); 34 | border-radius: 5px; 35 | 36 | } 37 | 38 | #login-card>div>form>input:focus { 39 | border: none; 40 | background: #000000ad; 41 | color: white; 42 | } 43 | 44 | #login-card>div>form>button { 45 | width: 100%; 46 | padding: 10px; 47 | border-radius: 5px; 48 | border: none; 49 | margin-top: 20px; 50 | text-transform: uppercase; 51 | /* background: #000; */ 52 | color: white; 53 | /* background-color: linear-gradient(red, blue); */ 54 | } 55 | 56 | #login-card>div>form>button:hover { 57 | background-color: #000000bc; 58 | } 59 | 60 | form~a { 61 | text-align: end; 62 | color: rgba(0, 0, 0, 0.384); 63 | text-decoration: none; 64 | } 65 | 66 | #login-card+div { 67 | text-align: right; 68 | width: 90%; 69 | } -------------------------------------------------------------------------------- /Frontend/src/component/FeedbackCard.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useSelector } from "react-redux"; 3 | 4 | function FeedbackCard({ feedback }) { 5 | const user = useSelector((store) => store.reducer.user); 6 | 7 | const date = feedback.date.split(" ").splice(0, 5).join(" "); 8 | 9 | // console.log(date, "DATE"); 10 | return ( 11 |
12 | {/*
13 |

{date}

14 |
*/} 15 |
16 |

17 |

18 | {feedback.body?.split("\n")[2]?.replace(",", "")?.toUpperCase()}/10 19 |

20 |

{date}

21 |

22 | {/*

{user.name}

*/} 23 |
24 |
25 |

26 | Feedback :{" "} 27 | {feedback.body 28 | ?.split("\n")[3] 29 | ?.replace("feedback:", "") 30 | .replace(",", "") 31 | .replaceAll("'", "") 32 | .replace("extra:", "") 33 | .replace(",", "") 34 | .replaceAll("'", "") 35 | .replaceAll("[", "") 36 | .replaceAll("]", "") 37 | .replaceAll(".", "") 38 | .replace("feedback", "") 39 | .replace("error", "") 40 | .replace(":", "") 41 | .replace("extra", "")} 42 |

43 |
44 |
45 | ); 46 | } 47 | 48 | export default FeedbackCard; 49 | -------------------------------------------------------------------------------- /Frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@chakra-ui/react": "^2.7.1", 7 | "@emotion/react": "^11.11.1", 8 | "@emotion/styled": "^11.11.0", 9 | "@fortawesome/fontawesome-svg-core": "^6.4.0", 10 | "@fortawesome/free-solid-svg-icons": "^6.4.0", 11 | "@fortawesome/react-fontawesome": "^0.2.0", 12 | "@testing-library/jest-dom": "^5.16.5", 13 | "@testing-library/react": "^13.4.0", 14 | "@testing-library/user-event": "^13.5.0", 15 | "axios": "^1.4.0", 16 | "framer-motion": "^10.12.16", 17 | "react": "^18.2.0", 18 | "react-dom": "^18.2.0", 19 | "react-icons": "^4.10.1", 20 | "react-redux": "^8.1.1", 21 | "react-router-dom": "^6.13.0", 22 | "react-scripts": "5.0.1", 23 | "react-speech-recognition": "^3.10.0", 24 | "redux": "^4.2.1", 25 | "redux-thunk": "^2.4.2", 26 | "thunk": "^0.0.1", 27 | "web-vitals": "^2.1.4" 28 | }, 29 | "scripts": { 30 | "start": "react-scripts start", 31 | "build": "react-scripts build", 32 | "test": "react-scripts test", 33 | "eject": "react-scripts eject" 34 | }, 35 | "eslintConfig": { 36 | "extends": [ 37 | "react-app", 38 | "react-app/jest" 39 | ] 40 | }, 41 | "browserslist": { 42 | "production": [ 43 | ">0.2%", 44 | "not dead", 45 | "not op_mini all" 46 | ], 47 | "development": [ 48 | "last 1 chrome version", 49 | "last 1 firefox version", 50 | "last 1 safari version" 51 | ] 52 | }, 53 | "devDependencies": { 54 | "tailwindcss": "^3.3.2" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Frontend/src/css/signup.css: -------------------------------------------------------------------------------- 1 | #container { 2 | display: flex; 3 | justify-content: center; 4 | flex-direction: column; 5 | align-items: center; 6 | height: 100vh; 7 | } 8 | 9 | #signup-card { 10 | border: 2px solid rgba(148, 154, 148, 0.099); 11 | width: 400px; 12 | text-align: center; 13 | border-radius: 20px; 14 | } 15 | 16 | #signup-card>img { 17 | margin-top: 20px; 18 | border: 1px solid green; 19 | border-radius: 20px; 20 | 21 | } 22 | 23 | #signup-card>div { 24 | margin: auto; 25 | width: 300px; 26 | padding: 10px; 27 | text-align: left; 28 | margin-bottom: 30px; 29 | } 30 | 31 | #signup-card>div>form { 32 | width: 100%; 33 | } 34 | 35 | #signup-card>div>form>input { 36 | width: 90%; 37 | padding: 10px; 38 | margin: 5px; 39 | border: 2px solid rgba(155, 155, 160, 0.085); 40 | border-radius: 5px; 41 | 42 | 43 | } 44 | 45 | #signup-card>div>form>input::placeholder { 46 | font-size: 15px; 47 | } 48 | 49 | #signup-card>div>form>input:focus { 50 | border: none; 51 | background: #000000ad; 52 | color: white; 53 | } 54 | 55 | #signup-card>div>form>button { 56 | width: 100%; 57 | padding: 10px; 58 | border-radius: 5px; 59 | border: none; 60 | margin-top: 20px; 61 | text-transform: uppercase; 62 | /* background: #000; */ 63 | color: white; 64 | 65 | } 66 | 67 | #signup-card>div>form>button:hover { 68 | background-color: #000000bc; 69 | } 70 | 71 | form~a { 72 | text-align: end; 73 | color: rgba(0, 0, 0, 0.384); 74 | text-decoration: none; 75 | } 76 | 77 | #signup-card+div { 78 | text-align: right; 79 | width: 90%; 80 | } -------------------------------------------------------------------------------- /Frontend/src/Pages/Score.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import FeedbackCard from "../component/FeedbackCard"; 3 | import "./scores.css"; 4 | import axios from "axios"; 5 | import { useSelector } from "react-redux"; 6 | 7 | const Score = () => { 8 | const url = 9 | process.env.NODE_ENV == "development" 10 | ? process.env.REACT_APP_LOCAL_URL 11 | : process.env.REACT_APP_PROD_URL; 12 | 13 | // const feedbacks = [ 14 | // { 15 | // score: 8, 16 | // author: "John Doe", 17 | // message: "I had a wonderful time using your product. It's amazing!", 18 | // }, 19 | // { 20 | // score: 9, 21 | // author: "Jane Smith", 22 | // message: "Your team provided exceptional support. Thank you!", 23 | // }, 24 | // { 25 | // score: 3, 26 | // author: "John Doe", 27 | // message: 28 | // "I had a terrible experience with your product. It needs improvement.", 29 | // }, 30 | // ]; 31 | 32 | const [feedbacks, setFeedbacks] = useState([]); 33 | 34 | const user = useSelector((store) => store.reducer.user); 35 | console.log("USER", user); 36 | 37 | useEffect(() => { 38 | fetchUserFeedbackData(); 39 | }, []); 40 | 41 | function fetchUserFeedbackData() { 42 | axios 43 | .get(`${url}/history/${user._id || localStorage.getItem("id")}`) 44 | .then((res) => { 45 | console.log(res); 46 | setFeedbacks(res.data); 47 | }) 48 | .catch((err) => { 49 | console.log(err.message); 50 | }); 51 | } 52 | 53 | return ( 54 |
55 |
56 | {feedbacks.map((feedback, index) => ( 57 | 58 | ))} 59 |
60 |
61 | ); 62 | }; 63 | export default Score; 64 | -------------------------------------------------------------------------------- /Frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Code Vortex 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Frontend/src/css/forgotpassword.css: -------------------------------------------------------------------------------- 1 | .pin-input { 2 | border: 2px solid rgba(128, 117, 117, 0.17); 3 | width: 100%; 4 | margin-top: 10px; 5 | 6 | } 7 | 8 | .pin-input:focus { 9 | background-color: rgba(0, 0, 0, 0.584); 10 | } 11 | 12 | #container { 13 | display: flex; 14 | justify-content: center; 15 | flex-direction: column; 16 | align-items: center; 17 | } 18 | 19 | #forgot-card { 20 | background-color: white; 21 | border: 2px solid rgba(132, 131, 131, 0.171); 22 | width: 400px; 23 | text-align: center; 24 | border-radius: 20px; 25 | } 26 | 27 | #forgot-card>img { 28 | width: 150px; 29 | margin-bottom: -32px; 30 | border: 2px solid red; 31 | background-color: #000; 32 | } 33 | 34 | #forgot-card>div { 35 | margin: auto; 36 | width: 300px; 37 | padding: 10px; 38 | text-align: left; 39 | margin-bottom: 30px; 40 | } 41 | 42 | #forgot-card>div>form { 43 | width: 100%; 44 | } 45 | 46 | #forgot-card>div>form>input { 47 | width: 98%; 48 | padding: 10px; 49 | margin: 5px; 50 | border-color: rgba(155, 155, 160, 0.085); 51 | border-radius: 5px; 52 | border: 1px solid rgba(164, 164, 164, 0.236); 53 | 54 | } 55 | 56 | #forgot-card>div>form>input:focus { 57 | border: none; 58 | background: #000000ad; 59 | color: white; 60 | } 61 | 62 | #forgot-card>div>form>button { 63 | width: 100%; 64 | padding: 10px; 65 | border-radius: 5px; 66 | border: none; 67 | margin-top: 20px; 68 | text-transform: uppercase; 69 | /* background-color: #8c52ff; 70 | */ 71 | background-color: #000; 72 | 73 | color: white; 74 | 75 | } 76 | 77 | #forgot-card>div>form>button:hover { 78 | background-color: #000000bc; 79 | } 80 | 81 | form~a { 82 | text-align: end; 83 | color: rgba(0, 0, 0, 0.384); 84 | text-decoration: none; 85 | } 86 | 87 | #forgot-card+div { 88 | text-align: right; 89 | width: 90%; 90 | } -------------------------------------------------------------------------------- /Frontend/src/Pages/FeedbackPage.jsx: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import React, { useEffect, useState } from "react"; 3 | import { useDispatch, useSelector } from "react-redux"; 4 | import { Navigate } from "react-router-dom"; 5 | import { INTERVIEW_FEEDBACK } from "../Redux/actionTypes"; 6 | import { useToast } from "@chakra-ui/react"; 7 | import PerfomanceFeedback from "./PerfomanceFeedback"; 8 | 9 | const FeedbackPage = () => { 10 | const url = 11 | process.env.NODE_ENV == "development" 12 | ? process.env.REACT_APP_LOCAL_URL 13 | : process.env.REACT_APP_PROD_URL; 14 | 15 | const questions = useSelector((store) => store.reducer.question); 16 | // const feedback = useSelector((store) => store.reducer.feedback); 17 | const dispatch = useDispatch(); 18 | // console.log(feedback, "FEEDBACK"); 19 | const toast = useToast(); 20 | 21 | if (Object.keys(questions).length == 0) { 22 | return ; 23 | } else { 24 | sendInterviewQuestionsAndAnswers(); 25 | } 26 | 27 | function sendInterviewQuestionsAndAnswers() { 28 | axios 29 | .post( 30 | `${url}/question/rating`, 31 | { ...questions, id: localStorage.getItem("id") }, 32 | { 33 | headers: { 34 | "Content-Type": "application/json", 35 | // Auth: localStorage.getItem("token"), 36 | Authorization: localStorage.getItem("token"), 37 | }, 38 | } 39 | ) 40 | .then((res) => { 41 | console.log(res); 42 | if (res.data.success == true) { 43 | dispatch({ type: INTERVIEW_FEEDBACK, payload: res.data.data }); 44 | } 45 | toast({ 46 | title: `${res.data.msg ? res.data.msg : "Generating feedback"}`, 47 | status: "success", 48 | duration: 9000, 49 | isClosable: true, 50 | position: "top", 51 | }); 52 | }) 53 | .catch((err) => { 54 | console.log(err.message); 55 | toast({ 56 | title: `${err.message ? err.message : "Something went wrong!"}`, 57 | status: "error", 58 | duration: 9000, 59 | isClosable: true, 60 | position: "top", 61 | }); 62 | }); 63 | } 64 | 65 | return ( 66 |
67 | 68 |
69 | ); 70 | }; 71 | 72 | export default FeedbackPage; 73 | -------------------------------------------------------------------------------- /Frontend/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Frontend/src/component/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import image from "../assets/codev.png"; 3 | import "./animations.css"; 4 | import { Link } from "react-router-dom"; 5 | import { useDispatch, useSelector } from "react-redux"; 6 | import { USER_LOGOUT } from "../Redux/actionTypes"; 7 | import axios from "axios"; 8 | import { FaHome, FaUserAstronaut } from "react-icons/fa"; 9 | 10 | const Navbar = () => { 11 | const auth = useSelector((store) => store.reducer.auth); 12 | const dispatch = useDispatch(); 13 | 14 | const url = 15 | process.env.NODE_ENV == "development" 16 | ? process.env.REACT_APP_LOCAL_URL 17 | : process.env.REACT_APP_PROD_URL; 18 | 19 | const handleLogout = () => { 20 | axios 21 | .get(`${url}/user/logout`, { 22 | headers: { 23 | "Content-Type": "application/json", 24 | Authorization: `${localStorage.getItem("token")}`, 25 | }, 26 | }) 27 | .then((res) => { 28 | localStorage.setItem("token", ""); 29 | dispatch({ type: USER_LOGOUT }); 30 | }) 31 | .catch((err) => { 32 | console.log(err.message, "error while logout"); 33 | alert(err.message); 34 | }); 35 | }; 36 | return ( 37 | 78 | ); 79 | }; 80 | 81 | export default Navbar; 82 | -------------------------------------------------------------------------------- /Backend/Routes/Users.Routes.js: -------------------------------------------------------------------------------- 1 | const { Blacklist } = require("../Models/blacklist.model"); 2 | const { UserModel } = require("../Models/user.model"); 3 | const bcrypt = require("bcrypt"); 4 | const jwt = require("jsonwebtoken"); 5 | const { verify } = require("../middleware/jwtAuth.middleware"); 6 | const UserRoute = require("express").Router(); 7 | require("dotenv").config(); 8 | 9 | UserRoute.post("/register", async (req, res) => { 10 | try { 11 | const { name, email, password } = req.body; 12 | const isUserExist = await UserModel.findOne({ email }); 13 | // console.log(isUserExist); 14 | 15 | console.log(isUserExist); 16 | if (isUserExist) { 17 | return res.send({ 18 | msg: "user already exist in the database try with new email", 19 | }); 20 | } 21 | 22 | const hash = bcrypt.hashSync(password, 8); 23 | // console.log(hash); 24 | const user = new UserModel({ name, email, password: hash }); 25 | // console.log(user); 26 | await user.save(); 27 | 28 | res.send({ msg: "user has been registered successfully" }); 29 | } catch (error) { 30 | res.send({ msg: error.msg }); 31 | } 32 | }); 33 | UserRoute.post("/login", async (req, res) => { 34 | try { 35 | const { email, password } = req.body; 36 | const isUserExist = await UserModel.findOne({ email }); 37 | 38 | if (!isUserExist) { 39 | return res.status(401).send({ msg: "invalid username or password" }); 40 | } 41 | 42 | var result = bcrypt.compareSync(password, isUserExist.password); 43 | // console.log(result); 44 | if (!result) { 45 | return res.status(401).send({ msg: "invalid username or password" }); 46 | } 47 | 48 | const Accesstoken = jwt.sign( 49 | { userID: isUserExist._id }, 50 | process.env.secretKey 51 | ); 52 | console.log(Accesstoken); 53 | 54 | res.send({ msg: "login successfull", user: isUserExist, Accesstoken }); 55 | } catch (error) { 56 | res.send({ msg: error.msg }); 57 | } 58 | }); 59 | UserRoute.get("/logout", async (req, res) => { 60 | // we wil get the accesstoken and refreshtoken in req.headers with the respective name; 61 | try { 62 | const accesstoken = req.headers.authorization; 63 | 64 | const blackAccess = new Blacklist({ token: accesstoken }); 65 | await blackAccess.save(); 66 | 67 | res.send({ msg: "logout successfull....." }); 68 | } catch (error) { 69 | res.send({ msg: error.msg }); 70 | } 71 | }); 72 | 73 | // FOR FRONTEND 74 | /* This code defines a GET route for "/verify" on the UserRoute router. It uses the `verify` middleware 75 | function to authenticate the user's access token. If the token is valid, it sends a response with a 76 | success message. If the token is invalid or missing, it will throw an error and send a response with 77 | an error message. */ 78 | UserRoute.get("/verify", verify, async (req, res) => { 79 | const { userId } = req.body; 80 | const token = req.header("Auth"); 81 | try { 82 | const user = await UserModel.findOne({ _id: userId }); 83 | // console.log(userId, "USER"); 84 | res.send({ msg: "Success", user, token }); 85 | } catch (error) { 86 | res.send({ msg: error.msg }); 87 | } 88 | }); 89 | 90 | module.exports = { UserRoute }; 91 | -------------------------------------------------------------------------------- /Frontend/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /Frontend/src/Pages/ForgotPassword.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import "../css/forgotpassword.css"; 3 | import { PinInput, PinInputField, HStack } from '@chakra-ui/react'; 4 | import logo from "../images/code-vortex-logo.png"; 5 | import axios from 'axios'; 6 | const ForgotPassword = () => { 7 | const [btnText, setBtnText] = useState(false); 8 | const [pins, setPin] = useState("") 9 | const [email, setEmail] = useState(""); 10 | const [otp, setOtP] = useState(); 11 | const [showChangePassword, setShowChangePassword] = useState(false); 12 | const [password, setPassword] = useState("") 13 | 14 | const handleForm = (event) => { 15 | event.preventDefault(); 16 | 17 | if (!btnText) { 18 | 19 | //checking email is present or not in DB. if true then sending otp from BE allowing to show PIN 20 | // ----in.then..setBTNTEXT to true--- 21 | axios.post("localhost:5000/user/forget-password/email") 22 | .then((res) => { 23 | setOtP(res.data) 24 | setBtnText(true) 25 | }).catch((err) => alert(err.message)) 26 | // -- in catch 27 | // user not found 28 | } else { 29 | // check otp is correct or not 30 | // if correcrt then show and allow to change Password 31 | if (otp == pins) { 32 | setShowChangePassword(true) 33 | } else { 34 | alert("OTP doesn't matched") 35 | } 36 | //request for updating the password 37 | if (showChangePassword) { 38 | axios.patch("url") 39 | .then((res) => { 40 | alert("Password reset successfull !") 41 | }) 42 | .catch((err) => alert(err.message)) 43 | } 44 | 45 | } 46 | } 47 | return ( 48 |
49 | 50 |
51 |

Forgot Password

52 | {/* code-vertex */} 53 |
54 |
55 | 56 |
57 | setEmail(e.target.value)} type="email" name="email" disabled={btnText} /> 58 |
59 | { 60 | btnText && !showChangePassword ? ( 61 | setPin(e)} placeholder=''> 62 | 63 | 64 | 65 | 66 | 67 | ) : "" 68 | } 69 | 70 | { 71 | showChangePassword ? ( 72 | setPassword(e.target.value)} /> 73 | ) : "" 74 | } 75 | 76 |
77 | 78 |
79 |
80 | 81 |
82 | ) 83 | } 84 | 85 | export default ForgotPassword -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeVortex 2 | 3 | Code Vortex is an innovative self-interview prep platform harnessing the power of AI and natural language processing. It leverages OpenAI's advanced capabilities and prompt engineering techniques to replicate real interview scenarios. With personalized feedback and a comprehensive set of resources, Code Vortex empowers users to enhance their interview skills and excel in their job search. 4 | 5 | 6 | ## Deployed Links 7 | https://code-vertex.netlify.app **(Netlify)** \ 8 | https://tiny-pear-jaguar-veil.cyclic.app **(Cyclic)** 9 | 10 | 11 | ## Features 12 | 13 | - AI-Powered Interview Simulation 14 | - Personalized Feedback 15 | - Prompt Engineering Techniques 16 | - Performance Tracking and Analytics 17 | 18 | 19 | ## Tech Stack 20 | 21 | **Client:** React, Redux, TailwindCSS, Thunk, Chakra UI 22 | 23 | **Server:** Node, Express, MongoDB 24 | 25 | 26 | ## Screenshots 27 | 28 | ![CodeVertexSignup](https://github.com/CodingDemon1/CodeVortex/assets/68629598/e0217d76-477e-4213-aa9a-292548fbb996) 29 | ![CodeVertexLogin](https://github.com/CodingDemon1/CodeVortex/assets/68629598/2f569e53-698a-4007-a7d7-26129880cacc) 30 | ![CodeVertexForgotPass](https://github.com/CodingDemon1/CodeVortex/assets/68629598/28e9e2c1-f8f6-4fa9-89fb-5b4758a14717) 31 | ![CodeVortexHome](https://github.com/CodingDemon1/CodeVortex/assets/68629598/654458dc-2521-42f1-8386-28418a55536a) 32 | ![CodeVortexInterview](https://github.com/CodingDemon1/CodeVortex/assets/68629598/789e8dfb-9192-4192-8493-5cd1420f7523) 33 | ![CodeVortexFeedbackGenerationPage](https://github.com/CodingDemon1/CodeVortex/assets/68629598/d107e72a-6025-45d3-963f-48a4194bc8c2) 34 | ![CodeVortexFeedbackpage](https://github.com/CodingDemon1/CodeVortex/assets/68629598/cefe03a9-adb9-41ba-aede-0278479f96a3) 35 | ![CodeVortexScoresPage](https://github.com/CodingDemon1/CodeVortex/assets/68629598/e5be4b54-243d-470b-8cc1-c3875cc93ac3) 36 | 37 | 38 | 39 | 40 | ## Authors 41 | 42 | - [@abhimanyulp](https://github.com/abhimanyulp) 43 | - [@GRAviTY-GAGAN](https://github.com/GRAviTY-GAGAN) 44 | - [@vipullsingh](https://github.com/vipullsingh) 45 | - [@Sonu-Shettiyar](https://github.com/Sonu-Shettiyar) 46 | - [@CodingDemon1](https://github.com/CodingDemon1) 47 | - [@senapathisowjanya](https://github.com/senapathisowjanya) 48 | 49 | 50 | ## API Reference 51 | 52 | #### User Registration 53 | 54 | ```http 55 | POST /user/register 56 | ``` 57 | 58 | #### User Login 59 | 60 | ```http 61 | POST /user/login 62 | ``` 63 | 64 | #### User Logout 65 | 66 | ```http 67 | GET /user/logout 68 | ``` 69 | 70 | #### Verify User 71 | 72 | ```http 73 | GET /user/verify 74 | ``` 75 | 76 | | Header | Type | Description | 77 | | :-------- | :------- | :-------------------------------- | 78 | | `token` | `string` | **Required**. Token of the user | 79 | 80 | #### Get Questions 81 | 82 | ```http 83 | POST /question/query 84 | ``` 85 | 86 | | Body | Type | Description | 87 | | :-------- | :------- | :-------------------------------- | 88 | | `role, experience` | `object` | **Required**. | 89 | 90 | #### Get Feedback of Questions 91 | 92 | ```http 93 | POST /question/rating 94 | ``` 95 | 96 | | Body | Type | Description | 97 | | :-------- | :------- | :-------------------------------- | 98 | | `userid, question1, question2, answer1, answer3` | `object` | **Required**. | 99 | 100 | #### Get History of User 101 | 102 | ```http 103 | GET /history/${id} 104 | ``` 105 | 106 | | Parameter | Type | Description | 107 | | :-------- | :------- | :-------------------------------- | 108 | | `id` | `string` | **Required**. Id of user to fetch | 109 | 110 | 111 | -------------------------------------------------------------------------------- /Frontend/src/Pages/Login.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import "../css/login.css"; 3 | import axios from "axios"; 4 | import { Link, useLocation, useNavigate } from "react-router-dom"; 5 | import { useDispatch, useSelector } from "react-redux"; 6 | import { USER_AUTH } from "../Redux/actionTypes"; 7 | import { 8 | Center, 9 | Divider, 10 | Heading, 11 | Spinner, 12 | VStack, 13 | useToast, 14 | } from "@chakra-ui/react"; 15 | const Login = () => { 16 | const [email, setEmail] = useState(""); 17 | const [password, setPassword] = useState(""); 18 | 19 | const url = 20 | process.env.NODE_ENV == "development" 21 | ? process.env.REACT_APP_LOCAL_URL 22 | : process.env.REACT_APP_PROD_URL; 23 | 24 | const auth = useSelector((store) => store.reducer.auth); 25 | const navigate = useNavigate(); 26 | const location = useLocation(); 27 | const dispatch = useDispatch(); 28 | const toast = useToast(); 29 | 30 | useEffect(() => { 31 | if (auth) { 32 | location.state ? navigate(location.state) : navigate("/home"); 33 | } 34 | }, [auth]); 35 | 36 | const handleLogin = (e) => { 37 | e.preventDefault(); 38 | const payload = { email, password }; 39 | axios 40 | .post(`${url}/user/login`, payload) 41 | .then((res) => { 42 | console.log(res.data); 43 | localStorage.setItem("id", res.data.user._id); 44 | toast({ 45 | title: `${ 46 | res.data.user.name 47 | ? `${res.data.user.name} succesfully logged in` 48 | : res.data.msg 49 | }`, 50 | status: "success", 51 | duration: 9000, 52 | isClosable: true, 53 | position: "top", 54 | }); 55 | localStorage.setItem("token", res.data.Accesstoken); 56 | dispatch({ 57 | type: USER_AUTH, 58 | auth: true, 59 | payload: res.data.user, 60 | token: res.data.Accesstoken, 61 | }); 62 | navigate("/home"); 63 | }) 64 | .catch((err) => { 65 | console.log(err.message); 66 | toast({ 67 | title: `${err.message ? err.message : "Something went wrong!"}`, 68 | status: "error", 69 | duration: 9000, 70 | isClosable: true, 71 | position: "top", 72 | }); 73 | }); 74 | }; 75 | 76 | return ( 77 |
78 |
79 | {/*

Please Login

*/} 80 | {/* */} 81 |
82 |
83 | 84 |
85 | setEmail(e.target.value)} 89 | name="email" 90 | /> 91 |
92 | 93 |
94 | setPassword(e.target.value)} 98 | name="password" 99 | /> 100 |
101 | 107 |
108 | 109 |
Forgot password?
110 | 111 |
112 |
113 |
114 |

115 | {" "} 116 | Don't have account? SignUp 117 |

118 |
119 |
120 | ); 121 | }; 122 | 123 | export default Login; 124 | -------------------------------------------------------------------------------- /Frontend/src/Pages/Signup.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import "../css/signup.css"; 3 | import logo from "../images/code-vortex-logo.png"; 4 | import { Text, useToast } from "@chakra-ui/react"; 5 | import axios from "axios"; 6 | import { useNavigate } from "react-router-dom"; 7 | // import {useNavigate} fro/m 8 | const baseUrl = "localhost:5000"; 9 | const Signup = () => { 10 | const url = 11 | process.env.NODE_ENV == "development" 12 | ? process.env.REACT_APP_LOCAL_URL 13 | : process.env.REACT_APP_PROD_URL; 14 | 15 | const [email, setEmail] = useState(""); 16 | const [password, setPassword] = useState(""); 17 | const [name, setname] = useState(""); 18 | const [confirmPass, setConfirmPass] = useState(""); 19 | const navigate = useNavigate(); 20 | const toast = useToast(); 21 | const handleRegister = (e) => { 22 | e.preventDefault(); 23 | if (password === confirmPass) { 24 | const payload = { 25 | email, 26 | password, 27 | name, 28 | }; 29 | axios 30 | .post(`${url}/user/register`, payload) 31 | .then((res) => { 32 | if (res.data.msg === "user has been registered successfully") { 33 | toast({ 34 | title: res.data.msg, 35 | status: "success", 36 | duration: 9000, 37 | isClosable: true, 38 | position: "top", 39 | }); 40 | 41 | navigate("/"); 42 | } else { 43 | toast({ 44 | title: res.data.msg, 45 | status: "warning", 46 | duration: 9000, 47 | isClosable: true, 48 | position: "top", 49 | }); 50 | } 51 | }) 52 | .catch((err) => { 53 | console.log(err.message); 54 | toast({ 55 | title: `${err.message ? err.message : "Something went wrong!"}`, 56 | status: "error", 57 | duration: 9000, 58 | isClosable: true, 59 | position: "top", 60 | }); 61 | }); 62 | } else { 63 | toast({ 64 | title: "Oops! password is not matching ", 65 | status: "error", 66 | duration: 9000, 67 | isClosable: true, 68 | position: "top", 69 | }); 70 | } 71 | }; 72 | 73 | return ( 74 |
75 |
76 | {/* eroyu */} 77 | Register 78 |
79 |
80 | 81 |
82 | setname(e.target.value)} 86 | type="name" 87 | name="name" 88 | /> 89 |
90 | 91 |
92 | setEmail(e.target.value)} 96 | type="email" 97 | name="email" 98 | /> 99 |
100 | 101 |
102 | setPassword(e.target.value)} 107 | type="password" 108 | name="" 109 | id="" 110 | /> 111 |
112 | 113 |
114 | setConfirmPass(e.target.value)} 119 | type="password" 120 | name="confirm-password" 121 | /> 122 |
123 | 129 |
130 |
131 |
132 |
133 | ); 134 | }; 135 | 136 | export default Signup; 137 | -------------------------------------------------------------------------------- /Backend/Routes/Questions.Routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { Configuration, OpenAIApi } = require("openai"); 3 | require("dotenv").config(); 4 | const QuestionRoute = express.Router(); 5 | const { HistoryModel } = require("../Models/history.model"); 6 | const { verify } = require("../middleware/jwtAuth.middleware"); 7 | 8 | //OpenAI Config 9 | const configuration = new Configuration({ 10 | apiKey: process.env.OPENAI_API_KEY, 11 | }); 12 | 13 | const openai = new OpenAIApi(configuration); 14 | 15 | //Routes 16 | QuestionRoute.post("/query", async (req, res) => { 17 | const { role, experience } = req.body; 18 | 19 | // Set the prompt based on the received job role and experience 20 | const prompt = `Act as an Interviewer, For Job role ${role} developer and who's experience is ${experience} years, ask only two technical interview questions`; 21 | // 22 | try { 23 | const response = await openai.createCompletion({ 24 | model: "text-davinci-003", 25 | prompt, 26 | max_tokens: 300, 27 | temperature: 0.7, // Adjust the value to control the randomness of the generated text 28 | // stop: "\n", 29 | }); 30 | 31 | let data = response.data.choices[0].text; 32 | let stringWithoutNewlines = data.replace(/\n\n/g, ""); 33 | 34 | let qnArray = stringWithoutNewlines.split("\n"); 35 | console.log(qnArray); 36 | 37 | return res.status(200).json({ 38 | success: true, 39 | data: qnArray, 40 | }); 41 | } catch (error) { 42 | return res.status(400).json({ 43 | success: false, 44 | error: error.response 45 | ? error.response.data 46 | : "There was an issue on the server", 47 | }); 48 | } 49 | }); 50 | 51 | QuestionRoute.post("/rating", async (req, res) => { 52 | //Body should be in this format: 53 | // { 54 | // "userid":"put_userid_here", 55 | // "question1":"Put your question 1 here", 56 | // "question2":"Put your question 2 here", 57 | // "answer1":"Put your answer 1 here", 58 | // "answer2":"Put your answer 2 here" 59 | // } 60 | 61 | if (!req.body.question2) { 62 | return res.status(404).json({ msg: "Something went wrong!" }); 63 | } 64 | const obj = [ 65 | { 66 | question: req.body.question1.question, 67 | answer: req.body.question1.answer, 68 | }, 69 | { 70 | question: req.body.question2.question, 71 | answer: req.body.question2.answer, 72 | }, 73 | ]; 74 | 75 | let objStr = JSON.stringify(obj); 76 | // Extract Question 1 and Answer 1 from req.body 77 | // const question1 = req.body.question1.question; 78 | // const answer1 = req.body.question1.answer; 79 | 80 | // // Extract Question 2 and Answer 2 from req.body 81 | // const question2 = req.body.question2.question; 82 | // const answer2 = req.body.question2.answer; 83 | 84 | // Set the prompt based on the received job role and experience, including the extracted values 85 | // const prompt = `Rate Each Answers out of 10 given to these below questions and justification(1 line) why you rated this particular number. 86 | 87 | // Question 1: ${question1} 88 | // Answer 1: ${answer1} 89 | 90 | // Question 2: ${question2} 91 | // Answer 2: ${answer2}`; 92 | // // console.log(prompt); 93 | const prompt = `read the following array of objects and rate the answer out of 10 according to their questions. 94 | 95 | ${objStr} 96 | 97 | Level of the question is hard so the response should be also based on that level 98 | 99 | Provide the response on this format : [ 100 | score: {the score}, 101 | feedback : {the feedback}, 102 | extra : {extra information}, 103 | error : {error if any} 104 | ] 105 | 106 | `; 107 | 108 | try { 109 | const response = await openai.createCompletion({ 110 | model: "text-davinci-003", 111 | prompt, 112 | max_tokens: 1000, 113 | temperature: 1, // Adjust the value to control the randomness of the generated text 114 | // stop: "\n", 115 | }); 116 | 117 | let data = response.data.choices[0].text; 118 | 119 | console.log(data); 120 | 121 | //Saving data in History collection here 122 | console.log("USER ID", req.body); 123 | const history = new HistoryModel({ 124 | body: data, 125 | userID: req.body.id, 126 | date: Date(), 127 | }); 128 | await history.save(); 129 | 130 | return res.status(200).json({ 131 | success: true, 132 | data: data, 133 | }); 134 | } catch (error) { 135 | return res.status(400).json({ 136 | success: false, 137 | error: error.response 138 | ? error.response.data 139 | ? error.response.data.error.message 140 | : "There was an issue on the server" 141 | : "There was an issue on the server", 142 | }); 143 | } 144 | }); 145 | 146 | module.exports = { QuestionRoute }; 147 | -------------------------------------------------------------------------------- /Frontend/src/Pages/Home.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { useToast } from "@chakra-ui/react"; 3 | import { useNavigate } from "react-router"; 4 | import useVerify from "../Hooks/useVerify"; 5 | import axios from "axios"; 6 | import { Spinner } from "@chakra-ui/spinner"; 7 | import { useDispatch } from "react-redux"; 8 | import { QUESTIONS_UPDATE } from "../Redux/actionTypes"; 9 | 10 | function Home() { 11 | const url = 12 | process.env.NODE_ENV == "development" 13 | ? process.env.REACT_APP_LOCAL_URL 14 | : process.env.REACT_APP_PROD_URL; 15 | 16 | const topics = [ 17 | "React JS", 18 | "Node JS", 19 | "Spring", 20 | "Django", 21 | "JavaScript", 22 | "Java", 23 | "Python", 24 | ]; 25 | const toast = useToast(); 26 | const [loading, setLoading] = useState(false); 27 | const [role, setRole] = useState(""); 28 | const [experience, setExperience] = useState(""); 29 | const navigate = useNavigate(); 30 | const dispatch = useDispatch(); 31 | 32 | const verified = useVerify(); 33 | console.log(verified, "verified"); 34 | 35 | const handleRoleChange = (event) => { 36 | setRole(event.target.value); 37 | }; 38 | 39 | const handleExperienceChange = (event) => { 40 | setExperience(event.target.value); 41 | }; 42 | 43 | const handleSubmit = (e) => { 44 | setLoading(true); 45 | e.preventDefault(); 46 | if (role && experience) { 47 | let obj = { 48 | role, 49 | experience, 50 | }; 51 | console.log(obj); 52 | axios 53 | .post(`${url}/question/query`, obj) 54 | .then((res) => { 55 | console.log(res); 56 | if (res.data.success == true) { 57 | const questions = {}; 58 | res.data.data.forEach((question, i) => { 59 | // questions.push({ question, answer: "" }); 60 | questions[`question${i + 1}`] = { question, answer: "" }; 61 | }); 62 | dispatch({ type: QUESTIONS_UPDATE, payload: questions }); 63 | navigate("/interview"); 64 | } 65 | }) 66 | .catch((err) => { 67 | console.log(err); 68 | }) 69 | .finally(() => { 70 | setLoading(false); 71 | }); 72 | } else { 73 | toast({ 74 | title: "Please Fill the necessary details required.", 75 | // description: "We've created your account for you.", 76 | status: "error", 77 | duration: 9000, 78 | isClosable: true, 79 | position: "top", 80 | }); 81 | } 82 | }; 83 | 84 | return ( 85 |
86 |

87 | Welcome to CodeVertax..... 88 |

89 |
90 | 95 |
99 |
100 | 106 | 119 |
120 |
121 | 127 | 142 |
143 |
144 | 160 |
161 |
162 |
163 |
164 | ); 165 | } 166 | 167 | export default Home; 168 | -------------------------------------------------------------------------------- /Frontend/src/Pages/PerfomanceFeedback.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Button, 4 | Center, 5 | Container, 6 | Divider, 7 | Flex, 8 | Heading, 9 | Spinner, 10 | Text, 11 | VStack, 12 | } from "@chakra-ui/react"; 13 | import React, { useState } from "react"; 14 | import { useSelector } from "react-redux"; 15 | // import FontAwesomeIcon from "" 16 | import { AiOutlineFileDone } from "react-icons/ai"; 17 | import { PiNotePencil } from "react-icons/pi"; 18 | import { Link } from "react-router-dom"; 19 | const quotes = [ 20 | "Believe in yourself and your abilities.", 21 | "Confidence is the key to success in any interview.", 22 | "Preparation is the foundation of success.", 23 | "Putting the effort beforehand, will make you shine during the interview.", 24 | "Let your authenticity shine through.", 25 | "Stay positive and maintain a can-do attitude. ", 26 | "Remember Your enthusiasm and optimism will leave a lasting impression.", 27 | "Focus on your strengths, but also be willing to acknowledge areas for improvement.", 28 | " Show a growth mindset and a willingness to learn.", 29 | "Remember The interview is a conversation, not an interrogation.", 30 | "Tip: Engage with the interviewers show genuine interest.", 31 | "Keep pushing forward", 32 | "the right opportunity will come your way.", 33 | ]; 34 | const PerfomanceFeedback = () => { 35 | const name = useSelector((store) => store.reducer.user?.name); 36 | const feedback = useSelector((store) => store.reducer.feedback); 37 | const [loading, setLoading] = useState(true); 38 | 39 | useState(() => { 40 | setTimeout(() => { 41 | setLoading(false); 42 | }, 5000); 43 | }, []); 44 | if (loading) { 45 | return ( 46 |
47 | 48 | 49 | Please wait while we generate feedback for you... 50 | 51 | 52 |
53 | ); 54 | } 55 | return ( 56 | 57 |
58 | 59 | 60 | {quotes[Math.floor((Math.random() * 1000) / 100)]} 61 | 62 |
63 | 64 | 65 | YOUR {feedback?.split("\n")[2]?.replace(",", "")?.toUpperCase()}/10 66 | {/* {feedback} */} 67 | {console.log( 68 | feedback?.split("\n")[3]?.replace("feedback:", ""), 69 | "feedback" 70 | )} 71 | {console.log(feedback?.split("\n")[2], "score")} 72 | 73 | 80 | 81 | 82 | {" "} 83 | 84 | Feedback note's 85 | 86 | 87 |
88 | 89 | -These tips can expedite your hiring success.{" "} 90 | 91 |
92 | 93 | 94 | Advice : 95 | {feedback 96 | .split("\n")[3] 97 | ?.replace("feedback:", "") 98 | .replace(",", "") 99 | .replaceAll("'", "") 100 | .replace("extra:", "") 101 | .replace(",", "") 102 | .replaceAll("'", "") 103 | .replaceAll("[", "") 104 | .replaceAll("]", "") 105 | .replaceAll(".", "") 106 | .replace("feedback", "") 107 | .replace("error", "") 108 | .replace(":", "") 109 | .replace("extra", "")} 110 | . 111 | 112 | 113 | 114 | Extra Tip :{" "} 115 | {feedback 116 | ?.split("\n")[4] 117 | ?.replace("feedback:", "") 118 | .replace(",", "") 119 | .replaceAll("'", "") 120 | .replace("extra:", "") 121 | .replace(",", "") 122 | .replaceAll("'", "") 123 | .replaceAll("[", "") 124 | .replaceAll("]", "") 125 | .replaceAll(".", "") 126 | .replace("feedback", "") 127 | .replace("error", "") 128 | .replace(":", "") 129 | .replace("extra", "") 130 | .replace(`""`, "")} 131 | . 132 | 133 | 134 | {feedback 135 | ?.split("\n")[5] 136 | ?.replace("feedback:", "") 137 | .replace(",", "") 138 | .replaceAll("'", "") 139 | .replace("extra:", "") 140 | .replace(",", "") 141 | .replaceAll("'", "") 142 | .replaceAll("[", "") 143 | .replaceAll("]", "") 144 | .replaceAll(".", "") 145 | .replace("feedback", "") 146 | .replace("error", "") 147 | .replace(":", "") 148 | .replace("extra", "") 149 | .replace('""', "") 150 | .replace("error", "") === "null" 151 | ? "" 152 | : `${`${"Oversight" + " :"}`} ${feedback 153 | .split("\n")[5] 154 | ?.replace("feedback:", "") 155 | .replace(",", "") 156 | .replaceAll("'", "") 157 | .replace("extra:", "") 158 | .replace(",", "") 159 | .replaceAll("'", "") 160 | .replaceAll("[", "") 161 | .replaceAll("]", "") 162 | .replaceAll(".", "") 163 | .replace("feedback", "") 164 | .replace("error", "") 165 | .replace(":", "") 166 | .replace("extra", "") 167 | .replace('""', "") 168 | .replace("error", "")}`} 169 | 170 | 171 | 172 |
173 | 174 | 177 | 178 |
179 | ); 180 | }; 181 | 182 | export default PerfomanceFeedback; 183 | -------------------------------------------------------------------------------- /Frontend/src/component/SpeechToText.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef, useState } from "react"; 2 | import SpeechRecognition, { 3 | useSpeechRecognition, 4 | } from "react-speech-recognition"; 5 | import Question from "./Question"; 6 | import { BsRecord2Fill } from "react-icons/bs"; 7 | import "./SpeechToText.css"; 8 | import { useDispatch, useSelector } from "react-redux"; 9 | import { Navigate, useNavigate } from "react-router"; 10 | import { UPDATE_ANSWER } from "../Redux/actionTypes"; 11 | 12 | const SpeechToText = ({ questions, questionNumber }) => { 13 | const { transcript, listening, resetTranscript } = useSpeechRecognition(); 14 | const [intervieweeAnswer, setIntervieweeAnswer] = useState(""); 15 | const startBtn = document.querySelector(".startBtn"); 16 | const answerContainer = document.querySelector(".answerContainer"); 17 | const [timer1, setTimer1] = useState(5); 18 | const [answerTimer, setAnswerTimer] = useState(30); 19 | const showTimer1 = useRef(true); 20 | const showTimer2 = useRef(false); 21 | const [disableStopBtn, setDisableStopBtn] = useState(true); 22 | 23 | const studentQuestionAnswer = questions; 24 | console.log(studentQuestionAnswer); 25 | const [questionNumberTracker, setQuestionNumberTracker] = useState(1); 26 | 27 | // const questions = useSelector((store) => store.reducer.question); 28 | // const questionNumber = useSelector((store) => store.reducer.questionNumber); 29 | const dispatch = useDispatch(); 30 | const navigate = useNavigate(); 31 | console.log(showTimer1); 32 | console.log(showTimer2, startBtn); 33 | console.log(questions); 34 | // console.log(Object.keys(studentQuestionAnswer).length, "LENGTh"); 35 | // 36 | 37 | let alertTimerId; 38 | let answerTimerId; 39 | 40 | useEffect(() => { 41 | if (showTimer1.current == true) { 42 | alertTimerId = setInterval(() => { 43 | setTimer1((prev) => { 44 | if (prev <= 0) { 45 | startListening(); 46 | setTimer1(5); 47 | showTimer1.current = false; 48 | showTimer2.current = true; 49 | clearInterval(alertTimerId); 50 | return 5; 51 | } 52 | return prev - 1; 53 | }); 54 | }, 1000); 55 | } 56 | // 57 | 58 | if (showTimer2.current == true) { 59 | answerTimerId = setInterval(() => { 60 | setAnswerTimer((prev) => { 61 | if (prev == 0) { 62 | clearInterval(answerTimerId); 63 | stopListening(); 64 | // dispatch({ 65 | // type: UPDATE_ANSWER, 66 | // answer: answerContainer.textContent, 67 | // }); 68 | updateAnserFromStudent(); 69 | resetTranscript(); 70 | if ( 71 | questionNumberTracker < Object.keys(studentQuestionAnswer).length 72 | ) { 73 | showTimer1.current = true; 74 | showTimer2.current = false; 75 | setQuestionNumberTracker((prev) => prev + 1); 76 | return 30; 77 | } else { 78 | dispatch({ type: UPDATE_ANSWER, payload: studentQuestionAnswer }); 79 | navigate("/feedback"); 80 | } 81 | return 0; 82 | } // 83 | 84 | if (prev < 20) { 85 | setDisableStopBtn(false); 86 | } 87 | return prev - 1; 88 | }); 89 | }, 1000); 90 | } 91 | 92 | return () => { 93 | if (alertTimerId) { 94 | clearInterval(alertTimerId); 95 | } 96 | 97 | if (answerTimerId) { 98 | clearInterval(answerTimerId); 99 | } 100 | }; 101 | }, [showTimer2.current, showTimer1.current]); 102 | 103 | if (Object.keys(studentQuestionAnswer).length == 0) { 104 | return ; 105 | } 106 | 107 | let buttonDisabbled = listening; 108 | 109 | if (!SpeechRecognition.browserSupportsSpeechRecognition()) { 110 | return
Sorry, your browser doesn't support speech recognition.
; 111 | } 112 | 113 | const startListening = () => { 114 | SpeechRecognition.startListening({ continuous: true }); 115 | }; 116 | 117 | const stopListening = () => { 118 | setIntervieweeAnswer(transcript); 119 | SpeechRecognition.stopListening(); 120 | }; 121 | 122 | function handleReset() { 123 | resetTranscript(); 124 | console.log(intervieweeAnswer, "ANSWER"); 125 | } 126 | 127 | function updateAnserFromStudent() { 128 | studentQuestionAnswer[`question${questionNumberTracker}`].answer = 129 | answerContainer.textContent; 130 | answerContainer.textContent = ""; 131 | resetTranscript(); 132 | } 133 | 134 | return ( 135 |
136 |
137 | {showTimer1.current == true ? ( 138 |
Start answering the question in {timer1}
139 | ) : ( 140 |
Remaining time to answer {answerTimer}
141 | )} 142 |
143 |
144 |
145 | 148 |
149 |
150 |

{transcript}

151 |
152 |
153 |
154 |
159 | 160 |
{" "} 161 |
162 | 171 | 182 | 188 |
189 |
190 |
191 | ); 192 | }; 193 | 194 | export default SpeechToText; 195 | --------------------------------------------------------------------------------