Toggle navigation
Toggle navigation
This project
Loading...
Sign in
엄성진
/
Learn_In_Web
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
sungjin
2021-12-04 03:34:15 +0900
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
cd251f72d9474d4b50fa21944b742e7fd099f50a
cd251f72
1 parent
198eb525
Fix some issues for page, Change design to light page
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
154 additions
and
45 deletions
src/api/auth/auth.js
src/api/post/post.js
src/components/Header.js
src/components/HeaderItem.js
src/components/Nav.js
src/pages/_app.js
src/pages/login.js
src/pages/new.js
src/pages/post/[id].js
src/pages/signup.js
src/styles/globals.css
tailwind.config.js
src/api/auth/auth.js
View file @
cd251f7
...
...
@@ -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
;
...
...
src/api/post/post.js
View file @
cd251f7
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
,
...
...
@@ -56,4 +57,15 @@ 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
...
...
src/components/Header.js
View file @
cd251f7
...
...
@@ -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"
/>
...
...
src/components/HeaderItem.js
View file @
cd251f7
...
...
@@ -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
>
...
...
src/components/Nav.js
View file @
cd251f7
...
...
@@ -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
>
)
...
...
src/pages/_app.js
View file @
cd251f7
...
...
@@ -6,11 +6,13 @@ import Footer from '../components/Footer'
function
MyApp
({
Component
,
pageProps
})
{
return
(
<
div
>
<
div
className
=
"main"
>
<
Header
/>
<
Nav
/>
<
div
className
=
"min-h-screen"
>
<
div
className
=
"main bg-neutral pb-4 border-b-4 border-carbon"
>
<
Header
/>
<
Nav
/>
<
/div
>
<
Component
{...
pageProps
}
/
>
<
/div
>
<
Component
{...
pageProps
}
/
>
<
Footer
/>
<
/div
>
)
...
...
src/pages/login.js
View file @
cd251f7
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
>
<
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
>
<
/form
>
<
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
}
>
<
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
>
);
...
...
@@ -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
{
...
...
src/pages/new.js
View file @
cd251f7
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
.
valu
e
;
const
example
=
cod
e
;
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
>
...
...
src/pages/post/[id].js
View file @
cd251f7
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
...
...
src/pages/signup.js
View file @
cd251f7
...
...
@@ -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"
);
...
...
src/styles/globals.css
View file @
cd251f7
...
...
@@ -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
;
}
...
...
tailwind.config.js
View file @
cd251f7
...
...
@@ -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
:
{},
...
...
Please
register
or
login
to post a comment