sungjin

Fix some issues for page, Change design to light page

......@@ -4,12 +4,16 @@ import { SERVER_BASE_URL } from '..';
// login request to the server with axios and next-auth
export const login = async (email, password) => {
const response = await axios.post(`${SERVER_BASE_URL}/auth/signin` , {
const response = await axios.post(`${SERVER_BASE_URL}/auth/signin`, {
email,
password,
}).catch(err => {
if (err.response.status === 400 || err.response.status === 401) {
throw alert('Invalid email or password');
}
});
if (response.status !== 200 && response.status !== 201) {
throw new Error('Login failed!');
if (response == undefined || (response.status !== 200 && response.status !== 201)) {
throw alert('Login failed!');
}
console.log(response.data.access_token)
useSession.accessToken = response.data.access_token;
......@@ -22,15 +26,20 @@ export const signup = async (name, email, password) => {
name,
email,
password,
}).catch(err => {
if (err.response.status === 400 || err.response.status === 401) {
throw alert('Signup failed, maybe email is already used');
}
});
if (response.status !== 200 && response.status !== 201) {
throw new Error('Signup failed!');
throw alert('Signup failed!');
}
useSession.accessToken = response.data.access_token;
return response.data;
}
export const logout = async () => {1
export const logout = async () => {
1
useSession.accessToken = null;
return true;
}
......@@ -60,6 +69,8 @@ export const validateToken = async () => {
console.log(useSession.accessToken);
const response = await axios.post(`${SERVER_BASE_URL}/auth/validate`, {
token: useSession.accessToken,
}).catch(err => {
throw false;
});
if (response.status !== 200 && response.status !== 201) {
return false;
......
import * as auth from '../auth'
import axios from 'axios';
import { SERVER_BASE_URL } from '..';
import { useSession } from 'next-auth/client';
export const newPost = async (
title,
......@@ -57,3 +58,14 @@ export const getPostsByDifficulty = async (difficulty) => {
console.log(response.data);
return response.data;
}
export const createComment = async (id, content) => {
const response = await axios.post(`${SERVER_BASE_URL}/post/comment/${id}`, {
token : useSession.accessToken,
content,
});
if (response.status !== 200 && response.status !== 201) {
throw new Error('Failed to create comment!');
}
return response.data;
}
\ No newline at end of file
......
......@@ -14,7 +14,7 @@ import Link from "next/link"
function Header() {
return (
<header className="flex flex-col sm:flex-row m-5 justify-between items-center">
<header className="flex flex-col sm:flex-row m-5 mt-0 pt-5 justify-between items-center">
<Link href="/" passHref>
<div className="flex cursor-pointer transform hover:scale-105">
<CubeIcon className="h-20" />
......
......@@ -3,7 +3,7 @@ import Link from "next/link"
function HeaderItem({ Icon, title, link }) {
return (
<Link href={link}>
<div className="flex flex-col items-center cursor-pointer group w-12 sm:w-20 hover:text-white">
<div className="flex flex-col items-center cursor-pointer group w-12 sm:w-20 hover:text-black">
<Icon className="h-8 mb-1 group-hover:animate-bounce" />
<p className="opacity-0 group-hover:opacity-100 tracking-widest">{title}</p>
</div>
......
......@@ -25,20 +25,20 @@ export default function Nav() {
<div className="flex px-10 sm:px-20 text-2xl whitespace-nowrap
space-x-10 sm:space-x-20">
<Button onClick={moverun} className="cursor-pointer transition
duration-100 transform hover:scale-125 hover:text-white
active:text-blue-500">테스트</Button>
duration-100 transform hover:scale-125 hover:text-black
active:text-white">테스트</Button>
<Button onClick={movelow} className="cursor-pointer transition
duration-100 transform hover:scale-125 hover:text-white
active:text-blue-500">난이도 </Button>
duration-100 transform hover:scale-125 hover:text-black
active:text-white">난이도 </Button>
<Button onClick={movemed} className="cursor-pointer transition
duration-100 transform hover:scale-125 hover:text-white
active:text-blue-500">난이도 </Button>
duration-100 transform hover:scale-125 hover:text-black
active:text-white">난이도 </Button>
<Button onClick={movehigh} className="cursor-pointer transition
duration-100 transform hover:scale-125 hover:text-white
active:text-blue-500">난이도 </Button>
duration-100 transform hover:scale-125 hover:text-black
active:text-white">난이도 </Button>
<Button onClick={movenew} className="cursor-pointer transition
duration-100 transform hover:scale-125 hover:text-white
active:text-blue-500">문제 만들기</Button>
duration-100 transform hover:scale-125 hover:text-black
active:text-white">문제 만들기</Button>
</div>
</nav>
)
......
......@@ -6,11 +6,13 @@ import Footer from '../components/Footer'
function MyApp({ Component, pageProps }) {
return (
<div>
<div className="main">
<div className="min-h-screen">
<div className="main bg-neutral pb-4 border-b-4 border-carbon">
<Header />
<Nav />
</div>
<Component {...pageProps} />
</div>
<Footer />
</div>
)
......
import { useRouter } from "next/router";
import { Button } from "semantic-ui-react";
import * as auth from "../api/auth";
export default function Login() {
const router = useRouter();
return (
<div>
<h1>Login</h1>
<div className="flex h-auto">
<div className="w-auto inline-block p-3 bg-black rounded-lg m-auto">
<h1 className="font-bold text-4xl text-center">로그인</h1>
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<input type="email" id="email" />
<label htmlFor="password">Password</label>
<input type="password" id="password" />
<button type="submit">Login</button>
<input type="email" id="email" placeholder="email" className="my-2 rounded-sm"/>
<br />
<input type="password" id="password" className="my-2 rounded-sm" placeholder="password" />
<br />
<button type="submit" className="mt-2 px-4 py-2 text-base font-semibold text-white transition duration-500 transform bg-blue-300 rounded-lg hover:shadow-lg focus:bg-blue-400 focus:outline-none focus:ring-2 focus:ring-blue-300 focus:ring-offset-2 focus:ring-offset-blue-300 motion-reduce:transform-none hover:scale-105 tramsform">Login</button>
</form>
</div>
</div>
);
async function handleSubmit(event) {
......@@ -23,7 +26,7 @@ export default function Login() {
const email = form.email.value;
const password = form.password.value;
const login = await auth.login(email, password);
if(!login) {
if (!login) {
alert("Login failed");
}
else {
......
import { Button } from "semantic-ui-react";
import { newPost } from "../api/post";
import React from "react";
import dynamic from "next/dynamic";
import "@uiw/react-textarea-code-editor/dist.css";
const CodeEditor = dynamic(
() => import("@uiw/react-textarea-code-editor").then((mod) => mod.default),
{ ssr: false }
);
export default function New() {
const [code, setCode] = React.useState("");
async function makePost(event) {
event.preventDefault();
const form = event.target;
const title = form.title.value;
const explain = form.explain.value;
const example = form.example.value;
const example = code;
const testinput = form.testinput.value.split("\n");
const testoutput = form.testoutput.value.split("\n");
const difficulty = form.level.value;
......@@ -27,8 +37,20 @@ export default function New() {
</select>
<label>문제 설명</label>
<textarea id="explain"></textarea><br />
<label>예시 코드</label>
<textarea id="example"></textarea><br />
<label>예시 코드 (C++언어로 작성해야 합니다.)</label>
<CodeEditor
value={code}
language="cpp"
placeholder="Please enter example code."
onChange={(evn) => setCode(evn.target.value)}
padding={15}
style={{
fontSize: 12,
backgroundColor: "#f5f5f5",
fontFamily:
"ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace"
}}
/>
<label>예시 입력(Enter 구분)</label>
<textarea id="testinput"></textarea>
<label>예시 출력(Enter 구분)</label>
......
import { useRouter } from "next/dist/client/router"
import { getPostbyId } from "../../api/post"
import { createComment, getPostbyId } from "../../api/post"
import "@uiw/react-textarea-code-editor/dist.css";
import dynamic from "next/dynamic";
import { useEffect, useState } from "react";
import { Button } from "semantic-ui-react";
import { run } from "../../api/runner";
import { useSession } from "next-auth/client";
import SyntaxHighlighter from 'react-syntax-highlighter';
const CodeEditor = dynamic(
() => import("@uiw/react-textarea-code-editor").then((mod) => mod.default),
......@@ -20,6 +22,7 @@ export default function Post() {
if (!router.isReady) return;
const { id } = router.query
getPostbyId(id).then(res => {
console.log(res);
setPost(res)
})
}, [router.isReady]);
......@@ -28,16 +31,45 @@ export default function Post() {
const [code, setCode] = useState("");
const [answer, setAnswer] = useState("asdf");
const [answer, setAnswer] = useState("Answer Test");
const [comment, setComment] = useState("");
const addComment = async () => {
const { id } = router.query
const response = await createComment(id, comment)
}
const displayComment = () => {
console.log(post.comments);
if (post.comments != undefined) {
return post.comments.map(comment => (
<div className="w-full">
<div className="w-full flex justify-between">
<div className="w-1/2">
<span className="text-gray-700">{comment.username}</span>
</div>
</div>
</div>)
)
}
return <div></div>
}
const runCode = async function () {
if (useSession.accessToken == null) {
alert("You need to login first!")
router.push("/login")
return;
}
var result = await run(code, value);
console.log(result);
setAnswer(`출력 : ${result}`);
}
return (
<div>
<div className="ml-10 mr-10">
<h3 className="text-3xl font-bold">{post.title}</h3>
<p>{post.testinput}</p>
<p>{post.testoutput}</p>
......@@ -49,7 +81,7 @@ export default function Post() {
<option value="go">golang</option>
<option value="py">python</option>
</select>
<span className="left-100 fixed text-2xl font-semibold">문제 설명</span>
<span className="absolute left-1/2 text-2xl font-semibold">문제 설명</span>
<br></br>
<div className="w-6/12 inline-block">
<CodeEditor
......@@ -64,15 +96,24 @@ export default function Post() {
fontFamily:
"ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace"
}}
className="w-8/12 h-96 rounded"
className="w-8/12 min-h-[24rem] rounded"
/>
</div>
<div className="w-6/12 inline-block align-top">{post.explain}</div>
<Button onClick={runCode} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Run</Button>
<div className="">{answer}</div>
<p>{post.example}</p>
<details>
<summary>예시 코드 보기</summary>
<SyntaxHighlighter language="cpp">
{post.example || "Loading Example..."}
</SyntaxHighlighter>
</details>
<div>
<textarea className="w-full h-24" placeholder="Write your comment..." value={comment} onChange={(e) => setComment(e.target.value)}></textarea>
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={addComment}>댓글 쓰기</button>
{displayComment()}
</div>
</div>
)
}
\ No newline at end of file
......
......@@ -8,10 +8,16 @@ export default function Signup() {
<form onSubmit={handleSubmit}>
<label htmlFor="name">Name</label>
<input type="text" id="name" />
<br />
<label htmlFor="email">Email</label>
<input type="email" id="email" />
<br />
<label htmlFor="password">Password</label>
<input type="password" id="password" />
<br />
<label htmlFor="password-confirm">Confirm Password</label>
<input type="password" id="password-confirm" />
<br />
<button type="submit">Signup</button>
</form>
</div>
......@@ -24,7 +30,12 @@ function handleSubmit(event) {
const name = form.name.value;
const email = form.email.value;
const password = form.password.value;
console.log(name, email, password);
const passwordConfirm = form.passwordConfirm.value;
console.log(name, email, password, passwordConfirm);
if (password !== passwordConfirm) {
alert("Passwords do not match");
return;
}
const signup = auth.signup(name, email, password);
if(!signup) {
alert("Signup failed");
......
......@@ -4,7 +4,7 @@
@layer base {
body {
@apply bg-[#06202A] text-gray-300
@apply bg-neutral text-black;
}
}
......@@ -32,7 +32,7 @@ span.left-100.fixed {
}
.footer {
position: absolute;
position: flex;
bottom: 0;
left: 0;
}
......
......@@ -3,7 +3,14 @@ module.exports = {
purge: ['./src/**/*.{js,ts,jsx,tsx}'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
extend: {
colors: {
carbon: '#A9A9A9',
watermelon: "#ff3b3f",
neutral: "#efefef",
sky: "#caebf2",
},
},
},
variants: {
extend: {},
......