Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
students
travel
Commits
deade4a1
"server/git@compmath.korea.ac.kr:students/eue.git" did not exist on "1bc8719342d1ef6c0948f760f5860f933bf3e97d"
Commit
deade4a1
authored
Jul 20, 2022
by
Lee Soobeom
Browse files
editpost 기능
parent
4415469c
Changes
11
Hide whitespace changes
Inline
Side-by-side
frontend/src/App.tsx
View file @
deade4a1
...
@@ -7,6 +7,7 @@ import { Header, Body } from "./home";
...
@@ -7,6 +7,7 @@ import { Header, Body } from "./home";
import
{
Board
}
from
"
./board
"
;
import
{
Board
}
from
"
./board
"
;
import
Posting
from
"
./post/posting
"
;
import
Posting
from
"
./post/posting
"
;
import
{
Layout
}
from
"
./commons
"
;
import
{
Layout
}
from
"
./commons
"
;
import
{
EditPost
}
from
"
./post/editpost
"
;
export
const
App
=
()
=>
{
export
const
App
=
()
=>
{
return
(
return
(
...
@@ -26,7 +27,9 @@ export const App = () => {
...
@@ -26,7 +27,9 @@ export const App = () => {
}
}
/>
/>
<
Route
path
=
"board"
element
=
{
<
Board
/>
}
/>
<
Route
path
=
"board"
element
=
{
<
Board
/>
}
/>
<
Route
path
=
"post/:postId"
element
=
{
<
IntoPost
/>
}
/>
<
Route
path
=
"post/:postId/"
element
=
{
<
IntoPost
/>
}
>
<
Route
path
=
"edit"
element
=
{
<
EditPost
/>
}
/>
</
Route
>
<
Route
<
Route
path
=
"profile"
path
=
"profile"
element
=
{
element
=
{
...
...
frontend/src/apis/post.api.ts
View file @
deade4a1
...
@@ -4,7 +4,6 @@ import { PostType } from "../types";
...
@@ -4,7 +4,6 @@ import { PostType } from "../types";
export
const
posting
=
async
(
post
:
PostType
)
=>
{
export
const
posting
=
async
(
post
:
PostType
)
=>
{
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/posts/`
,
post
);
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/posts/`
,
post
);
return
data
;
return
data
;
};
};
...
@@ -24,3 +23,13 @@ export const getPostByPostId = async (_id: string) => {
...
@@ -24,3 +23,13 @@ export const getPostByPostId = async (_id: string) => {
const
{
data
}
=
await
axios
.
get
(
`
${
baseUrl
}
/posts/
${
_id
}
`
);
const
{
data
}
=
await
axios
.
get
(
`
${
baseUrl
}
/posts/
${
_id
}
`
);
return
data
;
return
data
;
};
};
export
const
deletePost
=
async
(
_id
:
string
)
=>
{
const
{
data
}
=
await
axios
.
delete
(
`
${
baseUrl
}
/posts/
${
_id
}
`
);
return
data
;
};
export
const
updating
=
async
(
post
:
PostType
)
=>
{
const
{
data
}
=
await
axios
.
put
(
`
${
baseUrl
}
/posts/
${
post
.
_id
}
`
,
post
);
return
data
;
};
frontend/src/post/editpost.tsx
0 → 100644
View file @
deade4a1
import
React
,
{
FormEvent
,
useState
}
from
"
react
"
;
import
{
useNavigate
,
useLocation
}
from
"
react-router-dom
"
;
import
isLength
from
"
validator/lib/isLength
"
;
import
equals
from
"
validator/lib/equals
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
import
{
PostType
}
from
"
../types
"
;
import
{
postApi
}
from
"
../apis
"
;
import
{
PostState
}
from
"
./intopost
"
;
export
function
EditPost
()
{
const
[
city
,
setCity
]
=
useState
<
string
>
(
"
질문종류
"
);
const
[
theme
,
setTheme
]
=
useState
<
string
>
(
"
질문종류
"
);
const
[
title
,
setTitle
]
=
useState
<
string
>
(
""
);
const
[
text
,
setText
]
=
useState
<
string
>
(
""
);
const
navigate
=
useNavigate
();
const
location
=
useLocation
()
as
PostState
;
const
post
=
location
.
state
;
const
[
user
,
setUser
]
=
useState
<
PostType
>
({
title
:
post
.
title
,
text
:
post
.
text
,
theme
:
post
.
theme
,
city
:
post
.
city
,
date
:
post
.
date
,
user
:
post
.
user
,
counts
:
0
,
_id
:
post
.
_id
,
});
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
error
,
setError
]
=
useState
(
""
);
const
[
disabled
,
setDisabled
]
=
useState
(
false
);
const
[
success
,
setSuccess
]
=
useState
(
false
);
async
function
handlePostSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
try
{
setError
(
""
);
console
.
log
(
"
user data
"
,
user
);
if
(
postingFormMatch
())
{
setLoading
(
true
);
const
res
=
await
postApi
.
updating
(
user
);
navigate
(
"
/board
"
,
{
replace
:
true
});
setSuccess
(
true
);
setError
(
""
);
}
}
catch
(
error
)
{
console
.
log
(
"
에러발생
"
);
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
function
postingFormMatch
()
{
if
(
!
isLength
(
user
.
title
??
""
,
{
min
:
1
}))
{
setError
(
"
제목을 입력해 주세요.
"
);
return
false
;
}
else
if
(
!
isLength
(
user
.
text
??
""
,
{
min
:
1
}))
{
setError
(
"
내용을 입력해 주세요.
"
);
return
false
;
}
else
if
(
equals
(
city
,
"
질문종류
"
))
{
setError
(
"
테마를 선택해 주세요.
"
);
return
false
;
}
else
if
(
equals
(
theme
,
"
질문종류
"
))
{
setError
(
"
도시를 선택해 주세요.
"
);
return
false
;
}
else
{
return
true
;
}
}
const
titleChange
=
(
event
:
React
.
ChangeEvent
<
HTMLTextAreaElement
>
)
=>
{
const
title
=
event
.
currentTarget
.
value
;
const
newUser
=
{
...
user
,
title
:
title
};
console
.
log
(
event
.
currentTarget
.
value
);
setTitle
(
event
.
currentTarget
.
value
);
setUser
(
newUser
);
};
const
textChange
=
(
event
:
React
.
ChangeEvent
<
HTMLTextAreaElement
>
)
=>
{
const
text
=
event
.
currentTarget
.
value
;
const
newUser
=
{
...
user
,
text
:
text
};
console
.
log
(
event
.
currentTarget
.
value
);
setText
(
event
.
currentTarget
.
value
);
setUser
(
newUser
);
};
const
cityChange
=
(
event
:
React
.
ChangeEvent
<
HTMLSelectElement
>
)
=>
{
const
city
=
event
.
currentTarget
.
value
;
const
newUser
=
{
...
user
,
city
:
city
};
console
.
log
(
event
.
currentTarget
.
value
);
setCity
(
event
.
currentTarget
.
value
);
setUser
(
newUser
);
};
const
themeChange
=
(
event
:
React
.
ChangeEvent
<
HTMLSelectElement
>
)
=>
{
const
theme
=
event
.
currentTarget
.
value
;
const
newUser
=
{
...
user
,
theme
:
theme
};
console
.
log
(
event
.
currentTarget
.
value
);
setTheme
(
event
.
currentTarget
.
value
);
setUser
(
newUser
);
};
return
(
<
div
className
=
"flex flex-col border-3"
>
<
form
onSubmit
=
{
handlePostSubmit
}
className
=
"w-full items-center"
>
<
div
className
=
"flex flex-row relative"
>
<
p
className
=
"basis-1/12 gap-x-8"
>
Id
</
p
>
<
p
className
=
"basis-8/12 invisible"
>
empty
</
p
>
<
select
name
=
"city"
id
=
"Questions"
className
=
"border border-3 border-black w-1/12"
onChange
=
{
cityChange
}
defaultValue
=
"질문종류"
>
<
option
value
=
"질문종류"
>
도시
</
option
>
<
option
value
=
"Seoul"
>
서울
</
option
>
<
option
value
=
"Busan"
>
부산
</
option
>
<
option
value
=
"Incheon"
>
인천
</
option
>
<
option
value
=
"Daegoo"
>
대구
</
option
>
<
option
value
=
"Kwangjoo"
>
광주
</
option
>
<
option
value
=
"Daejeon"
>
대전
</
option
>
<
option
value
=
"Woolsan"
>
울산
</
option
>
<
option
value
=
"Sejong"
>
세종
</
option
>
<
option
value
=
"Dokdo"
>
독도
</
option
>
<
option
value
=
"Jeju"
>
제주
</
option
>
</
select
>
<
select
name
=
"theme"
id
=
"Questions"
className
=
"border border-3 border-black w-1/12"
onChange
=
{
themeChange
}
defaultValue
=
"질문종류"
>
<
option
value
=
"질문종류"
>
테마
</
option
>
<
option
value
=
"cycling"
>
사이클링
</
option
>
<
option
value
=
"surfing"
>
서핑
</
option
>
<
option
value
=
"activity"
>
액티비티
</
option
>
<
option
value
=
"camping"
>
캠핑
</
option
>
<
option
value
=
"sking"
>
스키
</
option
>
<
option
value
=
"boat"
>
보트
</
option
>
<
option
value
=
"desert"
>
사막
</
option
>
<
option
value
=
"golf"
>
골프
</
option
>
<
option
value
=
"cave"
>
동굴
</
option
>
<
option
value
=
"history"
>
문화재
</
option
>
<
option
value
=
"zoo"
>
동물원
</
option
>
<
option
value
=
"cycling"
>
사이클링
</
option
>
</
select
>
<
button
type
=
"submit"
className
=
"border border-black basis-1/12 gap-x-8"
>
글쓰기
</
button
>
</
div
>
<
div
className
=
"flex border-4"
>
<
textarea
name
=
"title"
onChange
=
{
titleChange
}
placeholder
=
"title"
className
=
"w-full h-8"
></
textarea
>
</
div
>
<
div
className
=
"flex border-2"
>
<
textarea
onChange
=
{
textChange
}
name
=
"text"
placeholder
=
"text"
className
=
"w-full h-96"
></
textarea
>
</
div
>
</
form
>
</
div
>
);
}
frontend/src/post/intopost.tsx
View file @
deade4a1
import
React
from
"
react
"
;
import
React
,
{
MouseEvent
}
from
"
react
"
;
import
{
useLocation
}
from
"
react-router-dom
"
;
import
{
useLocation
,
useNavigate
,
Link
}
from
"
react-router-dom
"
;
import
{
postApi
}
from
"
../apis
"
;
import
{
PostType
}
from
"
../types
"
;
import
{
PostType
}
from
"
../types
"
;
interface
PostState
{
export
interface
PostState
{
state
:
PostType
;
state
:
PostType
;
}
}
export
function
IntoPost
()
{
export
function
IntoPost
()
{
const
location
=
useLocation
()
as
PostState
;
const
location
=
useLocation
()
as
PostState
;
const
post
=
location
.
state
;
const
post
=
location
.
state
;
const
navigate
=
useNavigate
();
// console.log(post);
// console.log(post);
const
handleDeleteClick
=
async
(
event
:
MouseEvent
<
HTMLButtonElement
>
)
=>
{
const
postId
=
event
.
currentTarget
.
id
;
const
res
=
await
postApi
.
deletePost
(
postId
);
navigate
(
"
/board
"
,
{
replace
:
true
});
console
.
log
(
"
delete post
"
,
res
);
};
return
(
return
(
<
div
>
<
div
>
<
div
>
<
div
>
<
div
className
=
"flex flex-row basis-8"
>
<
div
className
=
"border-2 border-current rounded"
>
<
button
id
=
{
post
.
_id
}
onClick
=
{
handleDeleteClick
}
>
delete
</
button
>
</
div
>
<
div
className
=
"border-2 border-current rounded"
>
<
Link
to
=
{
`/post/
${
post
.
_id
}
/edit`
}
state
=
{
post
}
>
<
button
>
update
</
button
>
</
Link
>
</
div
>
</
div
>
<
div
className
=
"flex flex-row"
>
<
div
className
=
"flex flex-row"
>
<
div
className
=
"flex basis-3/4"
>
제목:
{
post
.
title
}
</
div
>
<
div
className
=
"flex basis-3/4 border-2 border-black rounded"
>
<
div
className
=
"flex basis-1/4"
>
작성자: nickname
</
div
>
제목:
{
post
.
title
}
</
div
>
<
div
className
=
"flex basis-1/4 border-2 border-black rounded"
>
작성자: nickname
</
div
>
</
div
>
</
div
>
<
div
className
=
"flex flex-row"
>
<
div
className
=
"flex flex-row"
>
<
div
className
=
"flex basis-1/4"
>
도시:
{
post
.
city
}
</
div
>
<
div
className
=
"flex basis-1/4 border-2 border-black rounded"
>
<
div
className
=
"flex basis-1/4"
>
테마:
{
post
.
theme
}
</
div
>
도시:
{
post
.
city
}
<
div
className
=
"flex basis-1/4"
>
작성일:
{
post
.
date
}
</
div
>
</
div
>
<
div
className
=
"flex basis-1/4"
>
조회수:
{
post
.
counts
}
</
div
>
<
div
className
=
"flex basis-1/4 border-2 border-black rounded"
>
테마:
{
post
.
theme
}
</
div
>
<
div
className
=
"flex basis-1/4 border-2 border-black rounded"
>
작성일:
{
post
.
date
}
</
div
>
<
div
className
=
"flex basis-1/4 border-2 border-black rounded"
>
조회수:
{
post
.
counts
}
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
>
{
post
.
text
}
</
div
>
<
div
className
=
"border-2 border-black rounded h-96"
>
{
post
.
text
}
</
div
>
</
div
>
</
div
>
);
);
}
}
frontend/src/post/post.tsx
View file @
deade4a1
...
@@ -7,7 +7,7 @@ export type Props = {
...
@@ -7,7 +7,7 @@ export type Props = {
post
:
PostType
;
post
:
PostType
;
handleClick
:
MouseEventHandler
;
handleClick
:
MouseEventHandler
;
};
};
// Link opts = state : send obj , useLocation location.state
export
default
function
Post
({
handleClick
,
post
}:
Props
)
{
export
default
function
Post
({
handleClick
,
post
}:
Props
)
{
return
(
return
(
<
div
className
=
"flex flex-row h-16 divide-x-2 border-2 border-solid"
>
<
div
className
=
"flex flex-row h-16 divide-x-2 border-2 border-solid"
>
...
...
frontend/src/post/posting.tsx
View file @
deade4a1
...
@@ -30,14 +30,15 @@ export default function Posting() {
...
@@ -30,14 +30,15 @@ export default function Posting() {
const
[
success
,
setSuccess
]
=
useState
(
false
);
const
[
success
,
setSuccess
]
=
useState
(
false
);
async
function
handlePostSubmit
(
event
:
FormEvent
)
{
async
function
handlePostSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
// prevent onSubmit -> rerendering
event
.
preventDefault
();
try
{
try
{
setError
(
""
);
setError
(
""
);
console
.
log
(
"
user data
"
,
user
);
console
.
log
(
"
user data
"
,
user
);
if
(
postingFormMatch
())
{
if
(
postingFormMatch
())
{
setLoading
(
true
);
setLoading
(
true
);
const
res
=
await
postApi
.
posting
(
user
);
const
res
=
await
postApi
.
posting
(
user
);
//
console.log("서버연결됬나요", res);
console
.
log
(
"
서버연결됬나요
"
,
res
);
// console.log("user save");
// console.log("user save");
navigate
(
"
/board
"
,
{
replace
:
true
});
navigate
(
"
/board
"
,
{
replace
:
true
});
setSuccess
(
true
);
setSuccess
(
true
);
...
...
frontend/src/types/index.tsx
View file @
deade4a1
...
@@ -16,7 +16,7 @@ export interface PostType {
...
@@ -16,7 +16,7 @@ export interface PostType {
text
:
string
;
text
:
string
;
theme
:
string
;
theme
:
string
;
city
:
string
;
city
:
string
;
date
:
string
;
date
:
string
|
number
;
counts
:
number
;
counts
:
number
;
_id
:
string
;
_id
:
string
;
user
:
string
;
user
:
string
;
...
...
src/controllers/post.controller.ts
View file @
deade4a1
...
@@ -15,10 +15,9 @@ export const postCreate = asyncWrap(async (reqExp, res, next) => {
...
@@ -15,10 +15,9 @@ export const postCreate = asyncWrap(async (reqExp, res, next) => {
theme
:
string
;
theme
:
string
;
city
:
string
;
city
:
string
;
date
:
Date
;
date
:
Date
;
counts
:
number
;
};
};
console
.
log
(
"
body
"
,
req
.
body
);
// 1) title 빈 문자열인지 확인
// 1) title 빈 문자열인지 확인
if
(
!
isLength
(
title
??
""
,
{
min
:
1
}))
{
if
(
!
isLength
(
title
??
""
,
{
min
:
1
}))
{
return
res
.
status
(
422
).
send
(
"
제목을 한 글자 이상 입력해주세요
"
);
return
res
.
status
(
422
).
send
(
"
제목을 한 글자 이상 입력해주세요
"
);
...
@@ -46,10 +45,12 @@ export const postCreate = asyncWrap(async (reqExp, res, next) => {
...
@@ -46,10 +45,12 @@ export const postCreate = asyncWrap(async (reqExp, res, next) => {
text
,
text
,
theme
,
theme
,
city
,
city
,
date
,
date
:
Date
.
now
()
,
user
:
userId
,
user
:
userId
,
});
});
console
.
log
(
"
post
"
,
newPost
);
return
res
.
json
(
newPost
);
return
res
.
json
(
newPost
);
});
});
...
@@ -90,3 +91,44 @@ export const getOnePost = asyncWrap(async (req, res) => {
...
@@ -90,3 +91,44 @@ export const getOnePost = asyncWrap(async (req, res) => {
return
res
.
json
(
post
);
return
res
.
json
(
post
);
});
});
export
const
deleteOnePost
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
{
postId
}
=
req
.
params
;
console
.
log
(
postId
);
const
deleteCount
=
await
postDb
.
deletePost
(
postId
);
return
res
.
json
(
deleteCount
);
});
export
const
updatePost
=
asyncWrap
(
async
(
reqExp
,
res
)
=>
{
const
req
=
reqExp
as
TypedRequestAuth
<
{
userId
:
string
}
>
;
const
{
title
,
text
,
theme
,
city
,
date
}
=
req
.
body
as
{
title
:
string
;
text
:
string
;
theme
:
string
;
city
:
string
;
date
:
Date
;
counts
:
number
;
};
const
userId
=
req
.
auth
.
userId
;
const
{
postId
}
=
req
.
params
;
const
updatePost
=
await
postDb
.
updateOnePost
(
{
title
,
text
,
theme
,
city
,
date
:
Date
.
now
(),
counts
:
req
.
body
.
counts
,
user
:
userId
,
},
postId
);
console
.
log
(
"
게시글 수정 후
"
,
updatePost
);
return
res
.
json
(
updatePost
);
});
src/db/post.db.ts
View file @
deade4a1
...
@@ -24,7 +24,6 @@ export const addOneCount = async (_id: string, counts: number) => {
...
@@ -24,7 +24,6 @@ export const addOneCount = async (_id: string, counts: number) => {
{
counts
:
counts
},
{
counts
:
counts
},
{
new
:
true
}
{
new
:
true
}
);
);
// console.log(newCounts);
// console.log(newCounts);
return
newCounts
;
return
newCounts
;
...
@@ -34,3 +33,17 @@ export const getPost = async (_id: string) => {
...
@@ -34,3 +33,17 @@ export const getPost = async (_id: string) => {
const
post
=
await
Post
.
findOne
({
_id
:
_id
});
const
post
=
await
Post
.
findOne
({
_id
:
_id
});
return
post
;
return
post
;
};
};
export
const
deletePost
=
async
(
_id
:
string
)
=>
{
const
res
=
await
Post
.
deleteOne
({
_id
:
_id
});
return
res
;
};
export
const
updateOnePost
=
async
(
post
:
PostType
,
_id
:
string
)
=>
{
const
newPost
=
await
Post
.
findOneAndUpdate
(
{
_id
:
_id
},
{
post
},
{
new
:
true
}
);
return
newPost
;
};
src/models/post.model.ts
View file @
deade4a1
...
@@ -6,7 +6,7 @@ export interface PostType {
...
@@ -6,7 +6,7 @@ export interface PostType {
theme
:
string
;
theme
:
string
;
city
:
string
;
city
:
string
;
user
:
Types
.
ObjectId
|
string
;
user
:
Types
.
ObjectId
|
string
;
date
:
Date
;
date
:
Date
|
number
;
counts
?:
number
;
counts
?:
number
;
}
}
...
@@ -31,7 +31,7 @@ const PostSchema = new Schema<PostType>({
...
@@ -31,7 +31,7 @@ const PostSchema = new Schema<PostType>({
},
},
date
:
{
date
:
{
type
:
Date
,
type
:
Date
,
default
:
Date
.
now
,
default
:
Date
.
now
()
,
},
},
counts
:
{
counts
:
{
type
:
Number
,
type
:
Number
,
...
...
src/routes/post.route.ts
View file @
deade4a1
...
@@ -4,5 +4,16 @@ import { postCtrl, authCtrl } from "../controllers";
...
@@ -4,5 +4,16 @@ import { postCtrl, authCtrl } from "../controllers";
const
router
=
express
.
Router
();
const
router
=
express
.
Router
();
router
.
route
(
"
/
"
).
post
(
authCtrl
.
requireLogin
,
postCtrl
.
postCreate
);
router
.
route
(
"
/
"
).
post
(
authCtrl
.
requireLogin
,
postCtrl
.
postCreate
);
router
.
route
(
"
/
"
).
get
(
postCtrl
.
getAllPost
);
router
.
route
(
"
/:postId
"
)
.
post
(
authCtrl
.
requireLogin
,
postCtrl
.
addCounts
)
.
get
(
authCtrl
.
requireLogin
,
postCtrl
.
getOnePost
);
router
.
route
(
"
/:postId
"
).
delete
(
authCtrl
.
requireLogin
,
postCtrl
.
deleteOnePost
);
// authenticate
router
.
route
(
"
/:postId
"
).
put
(
authCtrl
.
requireLogin
,
postCtrl
.
updatePost
);
router
.
param
(
"
postId
"
,
postCtrl
.
userByPostId
);
export
default
router
;
export
default
router
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment