diff --git a/client/.gitignore b/client/.gitignore index 3c3629e6..a547bf36 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/client/index.html b/client/index.html index 60ee5964..a53999a6 100644 --- a/client/index.html +++ b/client/index.html @@ -2,12 +2,8 @@ - - Vite + React - - - + Peetcode
diff --git a/client/package.json b/client/package.json index 1fc31444..9ac2f799 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,7 @@ { "name": "leet-code-frontend", "private": true, + "proxy": "http://localhost:3000", "version": "0.0.0", "type": "module", "scripts": { diff --git a/client/src/App.css b/client/src/App.css index 35ac68f3..e1d23939 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -1,38 +1,10 @@ -/* -font-family: 'Merriweather', serif; -font-family: 'Montserrat', sans-serif; -font-family: 'Prompt', sans-serif; -font-family: 'Sacramento', cursive; -*/ - -h1 , h2 , h3 , h4 , h5 , h6 { - font-family: 'Montserrat', sans-serif; - font-weight: 900; -} -p , a { - font-family: 'Prompt', sans-serif -} - -.flex-row { - display: flex; - justify-content: center; - align-items: center; - flex-direction: row; -} - -.flex-col { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; -} - -.logo { - width: 40px; - height: 40px; -} - -a , Link { - text-decoration: none; +*{ + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: Verdana, Geneva, Tahoma, sans-serif; } +body { + background-color: #eceff1; +} \ No newline at end of file diff --git a/client/src/App.jsx b/client/src/App.jsx index f376af09..aabce76e 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -1,32 +1,65 @@ -import { BrowserRouter , Routes , Route } from "react-router-dom"; - -import HomePage from "./Components/HomePage/HomePage" -import AllProblems from "./Components/AllProblems/AllProblems"; - -import Navbar from "./Constants/Navbar/Navbar" -import ProblemsPage from "./Components/ProblemsPage/ProblemsPage"; -import Signup from "./Components/Signup/Signup" -import Login from "./Components/Login/Login" -import "./App.css" +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import "./App.css"; +import Login from "./pages/Login/Login"; +import Signup from "./pages/Signup/Signup"; +import ProblemList from "./pages/ProblemList/ProblemList"; +import Problem from "./pages/Problem/Problem"; +import Navbar from "./pages/Navbar/Navbar"; +/* + * Temporary problems array schema + */ +const problems = [ + { + title: "201. Bitwise AND of Numbers Range", + difficulty: "Medium", + acceptance: "42%", + description: "Given two integers left and right that represent the range [left, right], return the bitwise AND of all numbers in this range, inclusive.", + example: "Input: left = 5, right = 7 Output: 4" + }, + { + title: "201. Bitwise AND of Numbers Range", + difficulty: "Medium", + acceptance: "412%", + description: "Given two integers left and right that represent the range [left, right], return the bitwise AND of all numbers in this range, inclusive.", + example: "Input: left = 5, right = 7 Output: 4" + }, + { + title: "202. Happy Number", + difficulty: "Easy", + acceptance: "54.9%", + description: "Write an algorithm to determine if a number n is happy. A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits. Repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy. Return true if n is a happy number, and false if not.", + example: "Input: n = 19 Output: true Explanation: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1" + }, + { + title: "203. Remove Linked List Elements", + difficulty: "Hard", + acceptance: "42%", + description: "Given the head of a linked list and an integer val, remove all the nodes of the linked list that has Node.val == val, and return the new head.", + example: "Input: head = [1,2,6,3,4,5,6], val = 6 Output: [1,2,3,4,5]" + }, +]; function App() { + /* Add routing here, routes look like - + /login - Login page + /signup - Signup page + /problemset/all/ - All problems (see problems array above) + /problems/:problem_slug - A single problem page + */ - return ( - - - - } /> - } /> - } /> - } /> - } /> - 404 Not Found} /> - - - //
- // Finish the assignment! Look at the comments in App.jsx as a starting point - //
- ) + return ( +
+ + + + } /> + } /> + } /> + } /> + + +
+ ); } -export default App +export default App; diff --git a/client/src/Components/AllProblems/AllProblems.css b/client/src/Components/AllProblems/AllProblems.css deleted file mode 100644 index 0bdfb9f4..00000000 --- a/client/src/Components/AllProblems/AllProblems.css +++ /dev/null @@ -1,37 +0,0 @@ -table { - margin-top: 2rem; - width: 95%; - border-collapse: collapse; -} - - -tr { - color: rgb(0, 0, 156); - border: 2px solid grey; -} - -th { - border: 2px solid black; - text-align: start; - padding: 0.5rem 0 0.5rem 0.3rem; - color: black; - font-family: 'Merriweather', serif; -} - -td { - font-family: 'Merriweather', serif; - padding: 1rem; -} - -.Easy { - color: green; - font-weight: 900; -} -.Medium { - color: rgb(255, 166, 0); - font-weight: 900; -} -.Hard { - color: red; - font-weight: 900; -} \ No newline at end of file diff --git a/client/src/Components/AllProblems/AllProblems.jsx b/client/src/Components/AllProblems/AllProblems.jsx deleted file mode 100644 index 1e16e6b2..00000000 --- a/client/src/Components/AllProblems/AllProblems.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import React, {useEffect, useState} from 'react' -import { Link } from 'react-router-dom' - -import "./AllProblems.css" -import { backendUrl } from "../../constants.js"; - -const AllProblemsPage = () => { - const [problems, setProblems] = useState([]); - - const init = async () => { - const response = await fetch(`${backendUrl}/problems`, { - method: "GET", - }); - - const json = await response.json(); - setProblems(json.problems); - } - - useEffect(() => { - init() - }, []); - - return ( -
- - - - - - - - - - {problems.map((prob,index) => ( - - - - - - - - ))} - - -
TitleDifficultyAcceptance
{prob.title}{prob.difficulty}{prob.acceptance}
-
- ) -} - -export default AllProblemsPage \ No newline at end of file diff --git a/client/src/Components/HomePage/HomePage.css b/client/src/Components/HomePage/HomePage.css deleted file mode 100644 index d6f166b2..00000000 --- a/client/src/Components/HomePage/HomePage.css +++ /dev/null @@ -1,17 +0,0 @@ -.blog-box { - border: 1px solid grey; - padding: 1rem; -} -.date { - font-weight: 100; - font-size: 0.7rem; - margin: 0; -} - -.title { - margin: 10px 0; -} - -.content { - margin: 5px 0; -} \ No newline at end of file diff --git a/client/src/Components/HomePage/HomePage.jsx b/client/src/Components/HomePage/HomePage.jsx deleted file mode 100644 index f11180c3..00000000 --- a/client/src/Components/HomePage/HomePage.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' -import "./HomePage.css" -import loremContent from './LoremPosts' - -const HomePage = () => { - return ( -
-

Blogs

- {loremContent.map((content,index) => ( -
-

{content.date}

-

{content.title}

-

{content.content}

-
- ))} - -
- ) -} - -export default HomePage \ No newline at end of file diff --git a/client/src/Components/HomePage/LoremPosts.js b/client/src/Components/HomePage/LoremPosts.js deleted file mode 100644 index 311fc974..00000000 --- a/client/src/Components/HomePage/LoremPosts.js +++ /dev/null @@ -1,39 +0,0 @@ -const loremContent = [ - { - title : "Why use C++", - date : "10 July 2023", - content : "C++ is very fast" - }, - { - title : "Why use C++", - date : "10 July 2023", - content : "C++ is very fast" - }, - { - title : "Why use C++ users hate Java", - date : "2 July 2023", - content : "Java is very verbose" - }, - { - title : "Why Java is better than C++", - date : "5 March 2023", - content : "No Pointers and cross platforms" - }, - { - title : "Why Ai will take your job", - date : "1 March 2023", - content : "Because Ai can do alot of automation, that required humans" - }, - { - title : "What jobs will Ai Create", - date : "28 Feb 2023", - content : "Ai and Ml engineering jobs" - }, - { - title : "Is Python the real chad or Javascript", - date : "15 Feb 2023", - content : "Its like asking is IronMan better than Thor or Captain America" - }, -] - -export default loremContent; \ No newline at end of file diff --git a/client/src/Components/Login/Login.css b/client/src/Components/Login/Login.css deleted file mode 100644 index b2418acb..00000000 --- a/client/src/Components/Login/Login.css +++ /dev/null @@ -1,3 +0,0 @@ -#login { - height: 100%; -} \ No newline at end of file diff --git a/client/src/Components/Login/Login.jsx b/client/src/Components/Login/Login.jsx deleted file mode 100644 index 6cc12bfe..00000000 --- a/client/src/Components/Login/Login.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react' - -import "./Login.css" -import {useState} from "react"; -import {backendUrl} from "../../constants.js"; - -const Login = () => { - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - - return ( -
-

Login

-
-
- - { - setEmail(e.target.value) - }} type="text" name='email' placeholder='Your Email' /> -
- -
- - setPassword(e.target.value)} type="text" name='password' placeholder='Your Password' /> -
- - -
-
- ) -} - -export default Login ; \ No newline at end of file diff --git a/client/src/Components/ProblemsPage/ProblemsPage.css b/client/src/Components/ProblemsPage/ProblemsPage.css deleted file mode 100644 index a6bc6969..00000000 --- a/client/src/Components/ProblemsPage/ProblemsPage.css +++ /dev/null @@ -1,43 +0,0 @@ -#problempage { - min-height: 91vh; - display: flex; - align-items: flex-start; -} - -.ques , .code { - width: 50%; - min-height: 65vh; - margin: 0; - display: flex; - flex-direction: column; - justify-content: flex-start; - padding: 2rem; -} - -.code-form { - height: 70vh; -} - -textarea , pre { - width: 100%; - height: 100%; - font-size: 1.3rem; - -moz-tab-size : 4; - -o-tab-size : 4; - tab-size : 4; -} - -button { - padding: 0.5rem 1rem; - margin-right: 1rem; - font-weight: 800; - border-radius: 0.5rem; - cursor: pointer; -} - -#test { - background-color: gray; -} -#submit { - background-color: rgb(68, 207, 68); -} \ No newline at end of file diff --git a/client/src/Components/ProblemsPage/ProblemsPage.jsx b/client/src/Components/ProblemsPage/ProblemsPage.jsx deleted file mode 100644 index 66cedf39..00000000 --- a/client/src/Components/ProblemsPage/ProblemsPage.jsx +++ /dev/null @@ -1,86 +0,0 @@ -import React, {useEffect, useState} from 'react' -import { useParams } from 'react-router-dom' - -import "./ProblemsPage.css" -import {backendUrl} from "../../constants.js"; - - -const ProblemsPage = () => { - const [CodeSeg, setCodeSeg] = useState("") ; - const { pid } = useParams() ; - const cleanId = pid.substring(1) ; - const [problem, setProblem] = useState(null); - const [submission, setSubmission] = useState(""); - - const init = async () => { - const response = await fetch(`${backendUrl}/problem/` + cleanId, { - method: "GET", - }); - - const json = await response.json(); - setProblem(json.problem); - } - - useEffect(() => { - init(); - }, []) - // console.log(cleanId) ; - - - const handleKey = (event) => { - if (event.key == "Tab"){ - event.preventDefault() ; - const { selectionStart , selectionEnd , value } = event.target ; - const val = value.substring(0,selectionStart) + "\t" + value.substring(selectionStart) ; - event.target.value = val; - event.target.selectionStart = event.target.selectionEnd = selectionStart+1; - } - setCodeSeg(event.value) ; - } - - return ( -
- - { - problem? ( -
-
-

{problem.title}

-
Description
-

{problem.description}

- Input : {problem.exampleIn} - Output : {problem.exampleOut} -
-
-

Code Here

-
- - -
-
-
- ) : - (
The searched Question Doesn't exist
) - } - -
- - ) -} - -export default ProblemsPage \ No newline at end of file diff --git a/client/src/Components/Signup/Signup.css b/client/src/Components/Signup/Signup.css deleted file mode 100644 index c54036d6..00000000 --- a/client/src/Components/Signup/Signup.css +++ /dev/null @@ -1,29 +0,0 @@ -#signup { - min-height: 100%; -} - -.subform { - margin: 1rem; - font-family: 'Prompt', sans-serif;; -} - -.signup-form { - height: 200px; - width: 70%; - max-width: 550px; - border: 1px solid grey; - position: relative; - overflow: hidden; - display: flex; - flex-direction: column; - justify-content: center; - border-radius: 0.5rem; - background: #fffdfd; - box-shadow: 0 8px 8px -4px lightblue; -} - -.subform > input { - position: absolute; - right: 100px; - padding: 0.3rem; -} \ No newline at end of file diff --git a/client/src/Components/Signup/Signup.jsx b/client/src/Components/Signup/Signup.jsx deleted file mode 100644 index 20ca0cfb..00000000 --- a/client/src/Components/Signup/Signup.jsx +++ /dev/null @@ -1,60 +0,0 @@ -import React, { useState } from "react"; - -import "./Signup.css"; -import { backendUrl } from "../../constants.js"; -const Signup = () => { - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - - return ( -
-

Signup

-
-
- - { - setEmail(e.target.value); - }} - type='text' - name='email' - placeholder='Your Email' - /> -
- -
- - setPassword(e.target.value)} - type='password' - name='password' - placeholder='Your Password' - /> -
- - -
-
- ); -}; - -export default Signup; - -// neetcode1@gmail.com diff --git a/client/src/Constants/Navbar/Navbar.css b/client/src/Constants/Navbar/Navbar.css deleted file mode 100644 index 978c4365..00000000 --- a/client/src/Constants/Navbar/Navbar.css +++ /dev/null @@ -1,7 +0,0 @@ -.logo-box { - margin-right: 2rem; -} - -.nav-options { - margin-right: 2rem; -} \ No newline at end of file diff --git a/client/src/Constants/Navbar/Navbar.jsx b/client/src/Constants/Navbar/Navbar.jsx deleted file mode 100644 index 28ecfd12..00000000 --- a/client/src/Constants/Navbar/Navbar.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react' -import { Link } from 'react-router-dom' - -import './Navbar.css' - -const Navbar = () => { - return ( - - ) -} - -export default Navbar diff --git a/client/src/constants.js b/client/src/constants.js deleted file mode 100644 index 2a84056f..00000000 --- a/client/src/constants.js +++ /dev/null @@ -1 +0,0 @@ -export const backendUrl = "https://api.peetcode.com"; diff --git a/client/src/index.css b/client/src/index.css index 609e8822..e69de29b 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -1,7 +0,0 @@ -html, body, #app, #app>div { - height: 100% -} - -#root { - height: 90vh; -} \ No newline at end of file diff --git a/client/src/main.jsx b/client/src/main.jsx index 5cc59919..190dccb3 100644 --- a/client/src/main.jsx +++ b/client/src/main.jsx @@ -1,10 +1,9 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App' -import './index.css' +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import "./index.css"; +// import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; -ReactDOM.createRoot(document.getElementById('root')).render( - +ReactDOM.createRoot(document.getElementById("root")).render( - , -) +); diff --git a/client/src/pages/Login/Login.jsx b/client/src/pages/Login/Login.jsx new file mode 100644 index 00000000..79aab33f --- /dev/null +++ b/client/src/pages/Login/Login.jsx @@ -0,0 +1,56 @@ +import React, { useState } from "react"; +import "./login.css"; + +function Login() { + const [email, setEmail] = useState(""); + const [pass, setPass] = useState(""); + + const handleLogin = async (e) => { + const response = await fetch("http://localhost:3000/login", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + email: email, + password: pass, + }), + }); + + const json = await response.json(); + + if (json.token != null) { + localStorage.setItem("token", json.token); + console.log(json.msg); + window.location.reload(); + } + console.log(json.msg) + }; + + return ( +
+

LeetCode

+
+ setEmail(e.target.value)} + type="email" + placeholder="Username or E-mail" + id="email" + name="email" + /> + setPass(e.target.value)} + type="password" + placeholder="Password" + id="password" + name="password" + /> + +
+
+ ); +} + +export default Login; diff --git a/client/src/pages/Login/login.css b/client/src/pages/Login/login.css new file mode 100644 index 00000000..959b2b72 --- /dev/null +++ b/client/src/pages/Login/login.css @@ -0,0 +1,63 @@ +/* .App { + text-align: center; + display: flex; + min-height: 100vh; + align-items: center; + justify-content: center; + color: white; + background-image: linear-gradient(79deg, #7439db, #C66FBC 48%, #F7944D); +} */ + +.auth-form-container, +.login-form { + display: flex; + flex-direction: column; +} + +.login-form { + align-items: center; + width: 100%; + margin: auto; +} + +.auth-form-container { + background-color: white; + padding: 20px 20px; + width: 25%; + margin: auto; + margin-top: 5em; + /* border: 1px solid black; */ + box-shadow: 1px 1px 9px -1px rgb(199 197 197 / 78%); + -webkit-box-shadow: 1px 1px 9px -1px rgb(199 197 197 / 78%); + -moz-box-shadow: 1px 1px 9px -1px rgb(199 197 197 / 78%); +} + +.auth-form-container h2 { + text-align: center; + margin: 25px; +} + +input, button { + border: 1px solid #a7a8a9; + margin: 0.5rem 0; + padding: 1rem; + border-radius: 2px; + width: 100%; +} + +button[type="submit"] { + border: none; + background-color: #3c4d56; + cursor: pointer; + color: white; + margin: 0.5rem 0; + padding: 1rem; + border-radius: 2px; + /* width: 110%; */ +} + +.link-btn { + background: none; + color: white; + text-decoration: underline; +} \ No newline at end of file diff --git a/client/src/pages/Navbar/Navbar.jsx b/client/src/pages/Navbar/Navbar.jsx new file mode 100644 index 00000000..899aecbe --- /dev/null +++ b/client/src/pages/Navbar/Navbar.jsx @@ -0,0 +1,71 @@ +import React from "react"; +import { useEffect, useState } from "react"; +import { Link } from "react-router-dom"; +import "./navbar.css"; + +const Navbar = () => { + const [login, setLogin] = useState(false); + const init = async () => { + const response = await fetch("http://localhost:3000/me", { + method: "GET", + headers: { + "authorization": localStorage.getItem('token'), + }, + }); + + const json = await response.json(); + const msg = json.msg; + + if (msg === "logged in") setLogin(true); + else console.log(msg); + }; + + useEffect(() => { + init(); + }, []); + return ( +
+
+

LeetCode

+
+
+ +
+
+ ); +}; + +const Logout = () => { + return ( + <> + { + localStorage.clear(); + init() + }}> +
  • Logout
  • + + + ); +}; + +const Logger = () => { + return ( + <> + +
  • login
  • + + +
  • signup
  • + + + ); +}; + +export default Navbar; diff --git a/client/src/pages/Navbar/navbar.css b/client/src/pages/Navbar/navbar.css new file mode 100644 index 00000000..ce8f8d78 --- /dev/null +++ b/client/src/pages/Navbar/navbar.css @@ -0,0 +1,45 @@ +/* .logo{ + padding:7px 10px 10px 10px; + background-color: black; + font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; +} */ +h4{ + font-size: 1.7em; + margin: 10px 0; +} + +h4 span{ + color: gray; +} + +li{ + padding: 10px; +} +ul{ + display: flex; + list-style-type: none; +} +.container{ + display: flex; + justify-content: space-between; + /* border: 1px solid black; */ + padding: .5rem 5rem; + /* margin: 10px; */ + width: 100%; + background-color: white; + align-items: center; +} + +.nav-items{ + display: flex; +} + +.nav-items .link{ + text-transform: uppercase; + color: black; + text-decoration: none; +} + +button{ + margin: 8px; +} \ No newline at end of file diff --git a/client/src/pages/Problem/Problem.jsx b/client/src/pages/Problem/Problem.jsx new file mode 100644 index 00000000..536a5232 --- /dev/null +++ b/client/src/pages/Problem/Problem.jsx @@ -0,0 +1,239 @@ +import React, { useState, useEffect } from "react"; +import { useParams } from "react-router-dom"; +import "./problem.css"; + +const langs = { + C: "C language boilerplate", + Java: "Java language boilerplate", + Python: "Python language boilerplate", + "C++": "C++ langauge Boilerplate", +}; + +const Problem = () => { + // parameter value + const params = useParams(); + const [submissions, setSubmissions] = useState([]); + const [toggler, toggle] = useState("problem"); + const [problem, setProblem] = useState(); + const [loggedIn, logger] = useState(false); + // const { problemId } = params; + + const getSubmissions = async () => { + const response = await fetch( + "http://localhost:3000/submissions/" + params.problem_slug, + { + method: "GET", + headers: { + authorization: localStorage.getItem("token"), + }, + } + ); + + const json = await response.json(); + console.log(json); + setSubmissions(json.submissions.statuses); + // console.log(); + }; + + const init = async () => { + const getProblem = await fetch( + "http://localhost:3000/problem/" + params.problem_slug, + { + method: "GET", + } + ); + // console.log(response.json()); + const getProblemjson = await getProblem.json(); + setProblem(getProblemjson.problem); + const getLogin = await fetch("http://localhost:3000/me", { + method: "GET", + headers: { + authorization: localStorage.getItem("token"), + }, + }); + // console.log(response.json()); + const getLoginjson = await getLogin.json(); + const msg = getLoginjson.msg; + // console.log(msg); + if (msg === "logged in") logger(true); + }; + + useEffect(() => { + init(); + }, []); + + useEffect(() => { + getSubmissions(); + }, []); + + if (!problem) { + return
    Problem not found
    ; + } + + const performToggle = () => { + document.getElementById("descriptionButton").classList.toggle("active"); + document.getElementById("submissionsButton").classList.toggle("active"); + + if (toggler === "problem") toggle("submissions"); + else if (toggler === "submissions") toggle("problem"); + }; + + const Submissions = (props) => { + return ( + <> + {props.loggedIn ? ( + + ) : ( + + )} + + ); + }; + + const NoLogin = () => { + return <>Please login to see your submissions; + }; + + const ShowSubmissions = (props) => { + // getSubmissions(); + return ( +
    + {submissions.length == 0 ? ( +

    No problems yet

    + ) : ( + submissions.map((status) => { + return ( +

    + {status} +

    + ); + }) + )} +
    + ); + }; + + const ProblemDescription = (props) => { + const { + problemId, + title, + difficulty, + acceptance, + description, + exampleIn, + exampleOut, + } = props.problem; + return ( + <> +
    +

    + {problemId}. {title} +

    + + {difficulty} + +

    {description}

    +
    + +
    +
    +

    Example:

    +

    + Input: + {exampleIn}
    Output: {exampleOut} +

    +
    +
    + + ); + }; + + function LanguageSelector() { + const [selectedLanguage, setSelectedLanguage] = useState("C"); + const [textInputValue, setCodebox] = useState(langs[selectedLanguage]); + + const setLanguage = (e) => { + setSelectedLanguage(e.target.value); + setCodebox(langs[e.target.value]); + }; + + const setBoilerplate = (e) => { + setCodebox(e.target.value); + }; + + const submitProblem = async () => { + const response = await fetch( + "http://localhost:3000/submission/" + params.problem_slug, + { + method: "POST", + headers: { + authorization: localStorage.getItem("token"), + "Content-Type": "application/json", + }, + body: JSON.stringify({ + submittedSolution: textInputValue, + }), + } + ); + getSubmissions(); + const json = await response.json(); + console.log(json); + }; + + return ( +
    +
    + +
    + + +
    + ); + } + + return ( +
    +
    +
    + + +
    + + {toggler === "problem" ? ( + + ) : ( + + )} +
    + +
    + +
    +
    + ); +}; + +export default Problem; diff --git a/client/src/pages/Problem/p2.jsx b/client/src/pages/Problem/p2.jsx new file mode 100644 index 00000000..653c3435 --- /dev/null +++ b/client/src/pages/Problem/p2.jsx @@ -0,0 +1,233 @@ +import React, { useState, useEffect } from "react"; +import { useParams } from "react-router-dom"; +import "./problem.css"; + +const langs = { + C: "C language boilerplate", + Java: "Java language boilerplate", + Python: "Python language boilerplate", + "C++": "C++ langauge Boilerplate", +}; + +const Problem = () => { + // parameter value + const params = useParams(); + const [submissions, setSubmissions] = useState([]); + const [toggler, toggle] = useState("problem"); + const [problem, setProblem] = useState(); + const [loggedIn, logger] = useState(false); + // const { problemId } = params; + + const getSubmissions = async () => { + const response = await fetch( + "http://localhost:3000/submissions/" + params.problem_slug, + { + method: "GET", + headers: { + "authorization": localStorage.getItem("token"), + }, + } + ); + + const json = await response.json(); + // console.log(json.submissions.statuses); + setSubmissions(json.submissions.statuses); + // console.log(); + }; + + const init = async () => { + const getProblem = await fetch( + "http://localhost:3000/problem/" + params.problem_slug, + { + method: "GET", + } + ); + // console.log(response.json()); + const getProblemjson = await getProblem.json(); + setProblem(getProblemjson.problem); + const getLogin = await fetch("http://localhost:3000/me", { + method: "GET", + headers: { + authorization: localStorage.getItem("token"), + }, + }); + // console.log(response.json()); + const getLoginjson = await getLogin.json(); + const msg = getLoginjson.msg; + // console.log(msg); + if (msg === "logged in") logger(true); + }; + + useEffect(() => { + init(); + }, []); + + useEffect(() => { + getSubmissions(); + }, [submissions]) + + if (!problem) { + return
    Problem not found
    ; + } + + const performToggle = () => { + document.getElementById("descriptionButton").classList.toggle("active"); + document.getElementById("submissionsButton").classList.toggle("active"); + + if (toggler === "problem") toggle("submissions"); + else if (toggler === "submissions") toggle("problem"); + }; + + const Submissions = (props) => { + return ( + <> + {props.loggedIn ? ( + + ) : ( + + )} + + ); + }; + + const NoLogin = () => { + return <>Please login to see your submissions; + }; + + const ShowSubmissions = (props) => { + // getSubmissions(); + return ( +
    + {submissions.length == 0? (

    No problems yet

    ):submissions.map((status) => { + return ( +

    {status}

    + ); + })} +
    + ); + }; + + return ( +
    +
    +
    + + +
    + + {toggler === "problem" ? ( + + ) : ( + + )} +
    + +
    + +
    +
    + ); +}; + +const ProblemDescription = (props) => { + const { + problemId, + title, + difficulty, + acceptance, + description, + exampleIn, + exampleOut, + } = props.problem; + return ( + <> +
    +

    + {problemId}. {title} +

    + + {difficulty} + +

    {description}

    +
    + +
    +
    +

    Example:

    +

    + Input: + {exampleIn}
    Output: {exampleOut} +

    +
    +
    + + ); +}; + +function LanguageSelector(props) { + const [selectedLanguage, setSelectedLanguage] = useState("C"); + const [textInputValue, setCodebox] = useState(langs[selectedLanguage]); + + const setLanguage = (e) => { + setSelectedLanguage(e.target.value); + setCodebox(langs[e.target.value]); + }; + + const setBoilerplate = (e) => { + setCodebox(e.target.value); + }; + + const submitProblem = async () => { + const response = await fetch( + "http://localhost:3000/submission/" + props.problemId, + { + method: "POST", + headers: { + authorization: localStorage.getItem("token"), + "Content-Type": "application/json", + }, + body: JSON.stringify({ + submittedSolution: textInputValue, + }), + } + ); + + const json = await response.json(); + console.log(json); + }; + + return ( +
    +
    + +
    + + +
    + ); +} + +export default Problem; diff --git a/client/src/pages/Problem/problem.css b/client/src/pages/Problem/problem.css new file mode 100644 index 00000000..8e6b9107 --- /dev/null +++ b/client/src/pages/Problem/problem.css @@ -0,0 +1,195 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +#singleProblemMain { + width: 100%; + margin: 3rem auto; + padding: 1rem 5rem; + display: flex; + /* height: 100vh; */ + /* flex-direction: column; */ + justify-content: space-between; + align-items: flex-start; + /* gap: 0; */ +} + +.difficulty{ + height: 25px; + display: flex; + align-items: center; + border-radius: 35px; + padding: 5px 10px; + width: -moz-fit-content; + width: fit-content; + font-weight: bold; +} + +.difficulty#Medium{ + background-color: rgb(255 192 30/.15); + color: rgb(255 192 30/1); +} +.difficulty#Easy{ + background-color: rgb(0 184 163/.15); + color: rgb(0 184 163/1); +} +.difficulty#Hard{ + background-color: rgb(255 55 95/.15); + color: rgb(255 55 95/1); +} + +.left { + /* font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; */ + flex-basis: 45%; + /* height: 60vh; */ + display: flex; + flex-direction: column; + justify-content: center; + /* align-items: center; */ + gap: 2rem; +} + +.example { + width: 100%; + display: flex; + flex-direction: column; +} + +#exampleInOut{ + font-size: large; + border-radius: .5rem; + padding: 1.5rem; + background-color: white; + font-family: monospace; +} + +#exampleInOut b{ + font-size: smaller; +} + +.info, +.ex1 { + display: flex; + flex-direction: column; + gap: .75rem; +} + +.info p{ + white-space: pre-wrap; +} + +.ex1 h4{ + margin: 0; +} + +.info>h5 { + margin-top: -.3rem; +} + +.right { + width: 50%; + flex-basis: 50%; + display: flex; + justify-content: center; + align-items: center; +} + +.buttons{ + display: flex; + border-bottom: 1px solid black; + padding: 0; + margin: 0; + justify-content: flex-start; +} + +.buttons button{ + margin: 0 0; + width: 20%; + background: none; + border: none; + cursor: pointer; + padding: 7px 5px; +} + +.buttons .active{ + border-bottom: 1px solid black; + /* border-collapse: collapse; */ + border-radius: 0; +} + +.status{ + background-color: aliceblue; + margin: 10px auto; + border-radius: 10px; + text-align: center; + width: 50%; + padding: 10px; +} + +#WA{ + color: rgb(255 55 95/1); + background-color: rgb(255 55 95/.15); +} +#AC{ + color: rgb(0 184 163/1); + background-color: rgb(0 184 163/.15); +} + +.inout_fields { + border-radius: .5rem; + width: 100%; + height: 60vh; + /* gap: 1.5rem; */ + background-color: white; +} + +.inout_fields textarea{ + font-family: monospace; +} + +.input_fields{ + padding: 5px; + border-bottom: 1px solid black; +} + +.input_fields select, .input_fields select:focus-visible{ + border: none; + outline: none; +} + +#box { + width: 100%; + height: 60vh; + padding: 10px; + line-height: 1; + border: none; + resize: none; +} + +#submit { + margin: 0; + margin-right: auto; + padding: .3rem; + width: 5rem; + height: 2rem; + border-radius: .2rem; + border: 1px dotted; + background-color: #2cbb5d; + color: white; + cursor: pointer; +} + +#submit:hover { + color: white; + background-color: #4cc575; + transition: .5s; +} + +label { + display: flex; + gap: .2rem; + align-items: center; + justify-content: center; +} \ No newline at end of file diff --git a/client/src/pages/ProblemList/ProblemList.jsx b/client/src/pages/ProblemList/ProblemList.jsx new file mode 100644 index 00000000..bd5b4da3 --- /dev/null +++ b/client/src/pages/ProblemList/ProblemList.jsx @@ -0,0 +1,67 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { useState, useEffect } from "react"; +import "./problemList.css"; + +const ProblemList = () => { + const [problems, setProblems] = useState([]); + + const init = async () => { + const response = await fetch('http://localhost:3000/problems', { + method: "GET", + }); + + const json = await response.json(); + setProblems(json.problems); + } + + useEffect(() => { + init() + }, []); + return ( +
    + + + + + + + + + + {problems.map((problem) => { + return ( + + ); + })} + +
    TitleAcceptanceDifficulty
    +
    + ); +}; + +function ProblemStatement(props) { + const problemId = props.problemId; + const title = props.title; + const acceptance = props.acceptance; + const difficulty = props.difficulty; + + return ( + + + + {problemId}. {title} + + + {acceptance} + {difficulty} + + ); +} + +export default ProblemList; diff --git a/client/src/pages/ProblemList/problemList.css b/client/src/pages/ProblemList/problemList.css new file mode 100644 index 00000000..9714832b --- /dev/null +++ b/client/src/pages/ProblemList/problemList.css @@ -0,0 +1,53 @@ +#problemList { + margin: 3rem; + padding: 3rem; +} + +#table { + font-family: Arial, Helvetica, sans-serif; + border-collapse: collapse; + width: 80%; + margin: auto; +} + +th, +#row>td { + padding: 15px; +} + +#row>td { + background: transparent; +} + +#row:nth-child(even) { + background-color: #fff; +} + +#Easy{ + color: rgb(0 184 163/1); +} +#Medium{ + color: rgb(255 192 30/1); +} +#Hard{ + color: rgb(255 55 95/1); +} + +th { + padding-top: 12px; + padding-bottom: 12px; + text-align: left; + /* background-color: #2fb7b7; */ + color: black; + border-bottom: 1px solid #fff; +} +#problemLink { + text-decoration: none; + color: black; + transition: color .2s; +} +#problemLink:hover { + text-decoration: none; + color: blue; + transition: color .2s; +} \ No newline at end of file diff --git a/client/src/pages/Signup/Signup.jsx b/client/src/pages/Signup/Signup.jsx new file mode 100644 index 00000000..ad6399de --- /dev/null +++ b/client/src/pages/Signup/Signup.jsx @@ -0,0 +1,58 @@ +import React, { useState } from "react"; +import "../Login/login.css"; + +function Signup() { + const [email, setEmail] = useState(""); + const [pass, setPass] = useState(""); + const [cpass, setCPass] = useState(""); + + const handleSubmit = async (e) => { + const response = await fetch('http://localhost:3000/signup', { + method: "POST", + body: JSON.stringify({ + email: email, + password: pass, + conf_pass: cpass, + }), + headers: {"Content-Type": "application/json"} + }); + + const json = await response.json(); + console.log(json); + }; + + return ( +
    +

    LeetCode

    +
    + setEmail(e.target.value)} + type="email" + placeholder="Username or E-mail" + id="email" + name="email" + /> + setPass(e.target.value)} + type="password" + placeholder="Password" + id="password" + name="password" + /> + setCPass(e.target.value)} + type="password" + placeholder="Retype Password" + id="password" + name="cpassword" + /> + +
    +
    + ); +} + +export default Signup; diff --git a/server/.gitignore b/server/.gitignore index a56a7ef4..b512c09d 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,2 +1 @@ -node_modules - +node_modules \ No newline at end of file diff --git a/server/index.js b/server/index.js index 9691a837..e5d54ead 100644 --- a/server/index.js +++ b/server/index.js @@ -1,106 +1,131 @@ -const express = require("express"); -const app = express(); -const port = 3000; -var jwt = require("jsonwebtoken"); +const express = require('express') +const jwt = require('jsonwebtoken') const { auth } = require("./middleware"); -let USER_ID_COUNTER = 1; -const USERS = []; -const JWT_SECRET = "secret"; -const bodyParser = require("body-parser"); -var jsonParser = bodyParser.json(); -var urlencodedParser = bodyParser.urlencoded({ extended: false }); +const app = express() +const port = 3000 const cors = require("cors"); app.use(cors()); -app.use(jsonParser); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); + +const JWT_SECRET = "secret"; + +const USERS = [ + { email: "john@email", password: "password1"}, + // more objects here... +]; + +const SUBMISSIONS = []; const PROBLEMS = [ { - problemId: "1", - title: "401. Bitwise AND of Numbers Range", - difficulty: "Medium", - acceptance: "42%", - description: - "Given two integers left and right that represent the range [left, right], return the bitwise AND of all numbers in this range, inclusive.", - exampleIn: "left = 5, right = 7", - exampleOut: "4", - }, - { - problemId: "2", - title: "205. Add two numbers", - difficulty: "Medium", + problemId: "205", + title: "Isomorphic Strings", + difficulty: "Easy", acceptance: "41%", description: - "Given two numbers, add them and return them in integer range. use MOD=1e9+7", - exampleIn: "a = 100 , b = 200", - exampleOut: "300", + `Given two strings s and t, determine if they are isomorphic. + +Two strings s and t are isomorphic if the characters in s can be replaced to get t. + +All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character, but a character may map to itself.`, + exampleIn: 's = "egg", t = "add"', + exampleOut: "true", }, { - problemId: "3", - title: "202. Happy Number", + problemId: "202", + title: "Happy Number", difficulty: "Easy", acceptance: "54.9%", - description: "Write an algorithm to determine if a number n is happy.", + description: `Write an algorithm to determine if a number n is happy. + +A happy number is a number defined by the following process: + +- Starting with any positive integer, replace the number by the sum of the squares of its digits. +- Repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. +- Those numbers for which this process ends in 1 are happy. + +Return true if n is a happy number, and false if not.`, exampleIn: "n = 19", exampleOut: "true", }, { - problemId: "4", - title: "203. Remove Linked List Elements", - difficulty: "Hard", + problemId: "203", + title: "Remove Linked List Elements", + difficulty: "Easy", acceptance: "42%", - description: "Given number k , removed kth element", - exampleIn: "list: 1->2->3 , k=2", - exampleOut: "1->3", + description: "Given the head of a linked list and an integer val, remove all the nodes of the linked list that has Node.val == val, and return the new head.", + exampleIn: "head = [1,2,6,3,4,5,6], val = 6", + exampleOut: "[1,2,3,4,5]", }, { - problemId: "5", - title: "201. Bitwise AND of Numbers Range", - difficulty: "Medium", + problemId: "546", + title: "Remove Boxes", + difficulty: "Hard", acceptance: "42%", description: - "Given two integers left and right that represent the range [left, right], return the bitwise AND of all numbers in this range, inclusive.", - exampleIn: "left = 5, right = 7", - exampleOut: "4", +`You are given several boxes with different colors represented by different positive numbers. + +You may experience several rounds to remove boxes until there is no box left. Each time you can choose some continuous boxes with the same color (i.e., composed of k boxes, k >= 1), remove them and get k * k points. + +Return the maximum points you can get.`, + exampleIn: "boxes = [1,3,2,2,2,3,4,3,1]", + exampleOut: "23", }, { - problemId: "6", - title: "205. Add two numbers", + problemId: "2487", + title: "Remove Nodes from a Linked List", difficulty: "Medium", acceptance: "41%", description: - "Given two numbers, add them and return them in integer range. use MOD=1e9+7", - exampleIn: "a = 100 , b = 200", - exampleOut: "300", +`You are given the head of a linked list. + +Remove every node which has a node with a strictly greater value anywhere to the right side of it. + +Return the head of the modified linked list.`, + exampleIn: "head = [5,2,13,3,8]", + exampleOut: "[13, 8]", }, { - problemId: "7", - title: "202. Happy Number", - difficulty: "Easy", + problemId: "1171", + title: "Remove Zero Sum Consequtive Nodes from Linked List", + difficulty: "Medium", acceptance: "54.9%", - description: "Write an algorithm to determine if a number n is happy.", - exampleIn: "n = 19", - exampleOut: "true", + description: +`Given the head of a linked list, we repeatedly delete consecutive sequences of nodes that sum to 0 until there are no such sequences. + +After doing so, return the head of the final linked list. You may return any such answer. + + +(Note that in the examples below, all sequences are serializations of ListNode objects.)`, + exampleIn: "head = [1,2,-3,3,1]", + exampleOut: "[3, 1]", }, { - problemId: "8", - title: "203. Remove Linked List Elements", + problemId: "301", + title: "Remove Invalid Paranthesis", difficulty: "Hard", acceptance: "42%", - description: "Given number k , removed kth element", - exampleIn: "list: 1->2->3 , k=2", - exampleOut: "1->3", + description: +`Given a string s that contains parentheses and letters, remove the minimum number of invalid parentheses to make the input string valid. + +Return a list of unique strings that are valid with the minimum number of removals. You may return the answer in any order.`, + exampleIn: 's = "()())()"', + exampleOut: '["(())()","()()()"]', }, ]; -const SUBMISSIONS = []; +app.get('/', (req, res) => { + res.send('Hello World!') +}) -app.get("/", (req, res) => { - res.json({ - msg: "hello world", - }); -}); +app.get('/me', auth, (req, res) => { + const user = USERS.find((x) => x.email === req.email); + res.json({ email: user.email, msg: "logged in" }); +}) -app.get("/problems", (req, res) => { +app.get('/problems', (req, res) => { const filteredProblems = PROBLEMS.map((x) => ({ problemId: x.problemId, difficulty: x.difficulty, @@ -108,109 +133,81 @@ app.get("/problems", (req, res) => { title: x.title, })); - res.json({ - problems: filteredProblems, - }); -}); + return res.json({ + problems: filteredProblems + }) +}) -app.get("/problem/:id", (req, res) => { +app.get('/problem/:id', (req, res) => { const id = req.params.id; - const problem = PROBLEMS.find((x) => x.problemId === id); + const problem = PROBLEMS.find(x => x.problemId === id) - if (!problem) { - return res.status(411).json({}); - } + if(problem) + return res.json({problem}); + return res.status(403).json({msg: "no such problem"}) +}) - res.json({ - problem, - }); -}); +app.get('/submissions/:problemId', auth, (req, res) => { + const submissions = SUBMISSIONS.find(x => x.problemId === req.params.problemId && x.email === req.email); -app.get("/me", auth, (req, res) => { - const user = USERS.find((x) => x.id === req.userId); - res.json({ email: user.email, id: user.id }); -}); + res.json({submissions}) +}) -app.get("/submissions/:problemId", auth, (req, res) => { - const problemId = req.params.problemId; - const submissions = SUBMISSIONS.filter( - (x) => x.problemId === problemId && x.userId === req.userId - ); - res.json({ - submissions, - }); -}); - -app.post("/submission", auth, (req, res) => { - const isCorrect = Math.random() < 0.5; - const problemId = req.body.problemId; - const submission = req.body.submission; - - if (isCorrect) { - SUBMISSIONS.push({ - submission, - problemId, - userId: req.userId, - status: "AC", - }); - return res.json({ - status: "AC", - }); - } else { - SUBMISSIONS.push({ - submission, - problemId, - userId: req.userId, - status: "WA", - }); - return res.json({ - status: "WA", - }); - } -}); +app.post('/submission/:problemId', auth, (req, res) => { + const isCorrect = Math.random() < 0.5 + const problemId = req.params.problemId + const email = req.email + + let submissions = SUBMISSIONS.find(x => x.problemId === problemId && x.email === email); -app.post("/signup", (req, res) => { - const email = req.body.email; - const password = req.body.password; - if (USERS.find((x) => x.email === email)) { - return res.status(403).json({ msg: "Email already exists" }); + if(!submissions){ + submissions = { + problemId, email, statuses: [] + } + + SUBMISSIONS.push(submissions) } + if(isCorrect) submissions.statuses.unshift('AC'); + else submissions.statuses.unshift('WA'); - USERS.push({ - email, - password, - id: USER_ID_COUNTER++, - }); + return res.json(submissions) +}) - return res.json({ - msg: "Success", - }); -}); +app.post('/signup/', (req, res) => { + const email = req.body.email; + const password = req.body.password; + const confirmPass = req.body.conf_pass; -app.post("/login", (req, res) => { - const email = req.body.email; - const password = req.body.password; - const user = USERS.find((x) => x.email === email); + if(USERS.find(user => user.email === email)) return res.json({msg: "user already exists"}); - if (!user) { - return res.status(403).json({ msg: "User not found" }); - } + if(password != confirmPass) return res.json({msg: "Password does not match!"}); - if (user.password !== password) { - return res.status(403).json({ msg: "Incorrect password" }); - } + USERS.push({email, password}); + + return res.json({ + msg: "user added" + }); +}) + +app.post('/login', (req, res) => { + const {email, password} = req.body; + + const user = USERS.find(x => x.email === email) + + if(!user) return res.status(403).json({msg: "email does not exist"}); + if(user && user.password != password) return res.status(403).json({msg: "invalid password"}); const token = jwt.sign( { - id: user.id, + email: user.email, }, JWT_SECRET ); - return res.json({ token }); -}); + return res.json({ token: token, msg: "logged in" }); +}) app.listen(port, () => { - console.log(`Example app listening on port ${port}`); -}); + console.log(`Example app listening on port ${port}`) +}) \ No newline at end of file diff --git a/server/middleware.js b/server/middleware.js index cb6c3b1b..631ecb30 100644 --- a/server/middleware.js +++ b/server/middleware.js @@ -5,12 +5,14 @@ var jwt = require('jsonwebtoken'); module.exports = { auth: (req, res, next) => { const authHeader = req.headers["authorization"]; - if (!authHeader) { - return res.status(403).json({msg: "Missing auth header"}); + // console.log("auth header is " + authHeader + " " + typeof(authHeader)); + if (!authHeader || authHeader === "null") { + return res.json({msg: "Missing auth header"}); } + // const decoded = null; const decoded = jwt.verify(authHeader, JWT_SECRET); - if (decoded && decoded.id) { - req.userId = decoded.id; + if (decoded && decoded.email) { + req.email = decoded.email; next() } else { return res.status(403).json({msg: "Incorrect token"}); diff --git a/server/package-lock.json b/server/package-lock.json index 55cd30c7..52231c4c 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -9,7 +9,6 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "body-parser": "^1.20.2", "cors": "^2.8.5", "express": "^4.18.2", "jsonwebtoken": "^9.0.0" @@ -33,12 +32,12 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.5", + "content-type": "~1.0.4", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -46,7 +45,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.2", + "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -224,43 +223,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -300,12 +262,13 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -323,6 +286,17 @@ "node": ">= 0.4.0" } }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -567,9 +541,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -605,9 +579,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -752,12 +726,12 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { "bytes": "3.1.2", - "content-type": "~1.0.5", + "content-type": "~1.0.4", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -765,7 +739,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.2", + "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" } @@ -903,38 +877,6 @@ "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" - }, - "dependencies": { - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - } } }, "finalhandler": { @@ -967,12 +909,13 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" } }, @@ -984,6 +927,11 @@ "function-bind": "^1.1.1" } }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -1163,9 +1111,9 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -1184,9 +1132,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "requires": { "lru-cache": "^6.0.0" } diff --git a/server/package.json b/server/package.json index 6c77591c..684b3d3b 100644 --- a/server/package.json +++ b/server/package.json @@ -4,12 +4,11 @@ "description": "", "main": "index.js", "scripts": { - "start": "node index.js" + "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { - "body-parser": "^1.20.2", "cors": "^2.8.5", "express": "^4.18.2", "jsonwebtoken": "^9.0.0"