Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
students
travel
Commits
7285bfbd
Commit
7285bfbd
authored
Jul 25, 2022
by
Lee Soobeom
Browse files
files muliple uploads
parent
715ce2d9
Changes
12
Show whitespace changes
Inline
Side-by-side
frontend/src/App.tsx
View file @
7285bfbd
...
@@ -29,7 +29,6 @@ export const App = () => {
...
@@ -29,7 +29,6 @@ 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
path
=
"edit"
element
=
{
<
EditPost
/>
}
/>
{
/* </Route> */
}
<
Route
<
Route
path
=
"profile"
path
=
"profile"
element
=
{
element
=
{
...
@@ -39,7 +38,7 @@ export const App = () => {
...
@@ -39,7 +38,7 @@ export const App = () => {
}
}
/>
/>
<
Route
path
=
"admin"
element
=
{
<
Admin
/>
}
/>
<
Route
path
=
"admin"
element
=
{
<
Admin
/>
}
/>
<
Route
path
=
"rewrite"
element
=
{
<
ImgRewrite
/>
}
/>
<
Route
path
=
"rewrite"
element
=
{
<
ImgRewrite
/>
}
/>
</
Route
>
</
Route
>
</
Route
>
</
Route
>
</
Routes
>
</
Routes
>
...
...
frontend/src/apis/post.api.ts
View file @
7285bfbd
...
@@ -2,7 +2,7 @@ import axios from "axios";
...
@@ -2,7 +2,7 @@ import axios from "axios";
import
baseUrl
from
"
./baseUrl
"
;
import
baseUrl
from
"
./baseUrl
"
;
import
{
PostType
}
from
"
../types
"
;
import
{
PostType
}
from
"
../types
"
;
export
const
create
Img
AndPost
=
async
(
formdata
:
FormData
)
=>
{
export
const
create
File
AndPost
=
async
(
formdata
:
FormData
)
=>
{
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/posts/`
,
formdata
);
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/posts/`
,
formdata
);
return
data
;
return
data
;
};
};
...
@@ -10,31 +10,31 @@ export const createImgAndPost = async (formdata: FormData) => {
...
@@ -10,31 +10,31 @@ export const createImgAndPost = async (formdata: FormData) => {
export
const
getData
=
async
()
=>
{
export
const
getData
=
async
()
=>
{
const
{
data
}
=
await
axios
.
get
(
`
${
baseUrl
}
/posts/`
);
const
{
data
}
=
await
axios
.
get
(
`
${
baseUrl
}
/posts/`
);
return
data
;
return
data
;
};
};
//board
export
const
getFileByPostId
=
async
(
postId
:
string
)
=>
{
const
{
data
}
=
await
axios
.
get
(
`
${
baseUrl
}
/posts/files/
${
postId
}
`
);
return
data
;
};
//
export
const
getImgData
=
async
(
name
:
string
)
=>
{
export
const
getImgData
=
async
(
name
:
string
)
=>
{
const
{
data
}
=
await
axios
.
get
(
`/images/
${
name
}
`
);
const
{
data
}
=
await
axios
.
get
(
`/images/
${
name
}
`
);
return
data
;
return
data
;
};
};
export
const
addCounts
=
async
(
_i
d
:
string
,
counts
:
number
)
=>
{
export
const
addCounts
=
async
(
postI
d
:
string
,
counts
:
number
)
=>
{
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/posts/
${
_i
d
}
`
,
{
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/posts/
${
postI
d
}
`
,
{
counts
:
counts
+
1
,
counts
:
counts
+
1
,
});
});
return
data
;
return
data
;
};
};
export
const
getPostByPostId
=
async
(
_id
:
string
)
=>
{
export
const
deletePost
=
async
(
postId
:
string
)
=>
{
const
{
data
}
=
await
axios
.
get
(
`
${
baseUrl
}
/posts/
${
_id
}
`
);
const
{
data
}
=
await
axios
.
delete
(
`
${
baseUrl
}
/posts/
${
postId
}
`
);
return
data
;
};
export
const
deletePost
=
async
(
_id
:
string
)
=>
{
const
{
data
}
=
await
axios
.
delete
(
`
${
baseUrl
}
/posts/
${
_id
}
`
);
return
data
;
return
data
;
};
};
export
const
updat
ing
=
async
(
post
:
PostType
)
=>
{
export
const
updat
eImgAndPost
=
async
(
post
Id
:
string
,
formdata
:
FormData
)
=>
{
const
{
data
}
=
await
axios
.
put
(
`
${
baseUrl
}
/posts/
${
post
.
_i
d
}
`
,
post
);
const
{
data
}
=
await
axios
.
put
(
`
${
baseUrl
}
/posts/
${
post
I
d
}
`
,
formdata
);
return
data
;
return
data
;
};
};
frontend/src/board/board.tsx
View file @
7285bfbd
...
@@ -13,8 +13,8 @@ export default function BoardPage() {
...
@@ -13,8 +13,8 @@ export default function BoardPage() {
useEffect
(()
=>
{
useEffect
(()
=>
{
getDataList
();
getDataList
();
},
[
posts
]);
},
[]);
// posts
const
getDataList
=
async
()
=>
{
const
getDataList
=
async
()
=>
{
const
res
=
await
postApi
.
getData
();
const
res
=
await
postApi
.
getData
();
setPosts
(
res
);
setPosts
(
res
);
...
...
frontend/src/post/editpost.tsx
View file @
7285bfbd
import
React
,
{
FormEvent
,
useState
}
from
"
react
"
;
import
React
,
{
FormEvent
,
useState
,
useEffect
}
from
"
react
"
;
import
{
useNavigate
,
useLocation
}
from
"
react-router-dom
"
;
import
{
useNavigate
,
useLocation
}
from
"
react-router-dom
"
;
import
isLength
from
"
validator/lib/isLength
"
;
import
isLength
from
"
validator/lib/isLength
"
;
import
equals
from
"
validator/lib/equals
"
;
import
equals
from
"
validator/lib/equals
"
;
...
@@ -6,12 +6,16 @@ import { catchErrors } from "../helpers";
...
@@ -6,12 +6,16 @@ import { catchErrors } from "../helpers";
import
{
PostType
}
from
"
../types
"
;
import
{
PostType
}
from
"
../types
"
;
import
{
postApi
}
from
"
../apis
"
;
import
{
postApi
}
from
"
../apis
"
;
import
{
PostState
}
from
"
./intopost
"
;
import
{
PostState
}
from
"
./intopost
"
;
import
{
FileType
}
from
"
./intopost
"
;
export
function
EditPost
()
{
export
function
EditPost
()
{
const
[
city
,
setCity
]
=
useState
<
string
>
(
"
city
"
);
const
[
city
,
setCity
]
=
useState
<
string
>
(
"
city
"
);
const
[
theme
,
setTheme
]
=
useState
<
string
>
(
"
theme
"
);
const
[
theme
,
setTheme
]
=
useState
<
string
>
(
"
theme
"
);
const
[
title
,
setTitle
]
=
useState
<
string
>
(
""
);
const
[
title
,
setTitle
]
=
useState
<
string
>
(
""
);
const
[
text
,
setText
]
=
useState
<
string
>
(
""
);
const
[
text
,
setText
]
=
useState
<
string
>
(
""
);
const
[
file
,
setFile
]
=
useState
<
FileList
>
();
const
[
imgSrc
,
setImgSrc
]
=
useState
<
string
[]
>
();
const
[
filesList
,
setFilesList
]
=
useState
<
FileType
[]
>
();
const
navigate
=
useNavigate
();
const
navigate
=
useNavigate
();
const
location
=
useLocation
()
as
PostState
;
const
location
=
useLocation
()
as
PostState
;
...
@@ -24,7 +28,7 @@ export function EditPost() {
...
@@ -24,7 +28,7 @@ export function EditPost() {
city
:
post
.
city
,
city
:
post
.
city
,
date
:
post
.
date
,
date
:
post
.
date
,
user
:
post
.
user
,
user
:
post
.
user
,
counts
:
0
,
counts
:
post
.
counts
,
_id
:
post
.
_id
,
_id
:
post
.
_id
,
});
});
...
@@ -33,22 +37,52 @@ export function EditPost() {
...
@@ -33,22 +37,52 @@ export function EditPost() {
const
[
disabled
,
setDisabled
]
=
useState
(
false
);
const
[
disabled
,
setDisabled
]
=
useState
(
false
);
const
[
success
,
setSuccess
]
=
useState
(
false
);
const
[
success
,
setSuccess
]
=
useState
(
false
);
useEffect
(()
=>
{
getFilesList
(
post
.
_id
);
},
[]);
const
imgArr
=
new
Array
();
const
getFilesList
=
async
(
postId
:
string
)
=>
{
const
res
=
await
postApi
.
getFileByPostId
(
postId
);
//_id는 req.params에 항상 같이 보낸다
setFilesList
(
res
);
};
const
updateImg2Db
=
async
(
filelist
:
FileList
)
=>
{
const
formdata
=
new
FormData
();
formdata
.
append
(
"
title
"
,
user
.
title
);
formdata
.
append
(
"
text
"
,
user
.
text
);
formdata
.
append
(
"
theme
"
,
user
.
theme
);
formdata
.
append
(
"
city
"
,
user
.
city
);
if
(
filelist
===
undefined
||
filelist
===
null
)
{
const
res
=
await
postApi
.
updateImgAndPost
(
user
.
_id
,
formdata
);
}
else
{
for
(
var
i
=
0
;
i
<
filelist
.
length
;
i
++
)
{
formdata
.
append
(
"
picture
"
,
filelist
?.[
i
]);
}
const
res
=
await
postApi
.
updateImgAndPost
(
user
.
_id
,
formdata
);
}
};
async
function
reWriteSubmit
(
event
:
FormEvent
)
{
async
function
reWriteSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
event
.
preventDefault
();
try
{
try
{
if
(
confirm
(
"
게시물을 수정하시겠습니까?
"
)
==
true
)
{
setError
(
""
);
setError
(
""
);
// console.log("user data", user);
console
.
log
(
"
user data
"
,
user
);
if
(
postingFormMatch
(
user
)
===
true
)
{
if
(
postingFormMatch
(
user
)
===
true
)
{
setLoading
(
true
);
setLoading
(
true
);
const
res
=
await
postApi
.
updating
(
user
);
if
(
file
)
{
const
res
=
updateImg2Db
(
file
);
console
.
log
(
"
clear
"
,
res
);
// console.log(res);
}
navigate
(
"
/board
"
,
{
replace
:
true
});
navigate
(
"
/board
"
,
{
replace
:
true
});
setSuccess
(
true
);
setSuccess
(
true
);
setError
(
""
);
setError
(
""
);
}
}
}
else
{
return
false
;
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
log
(
"
에러발생
"
);
console
.
log
(
"
에러발생
"
);
catchErrors
(
error
,
setError
);
catchErrors
(
error
,
setError
);
...
@@ -57,17 +91,46 @@ export function EditPost() {
...
@@ -57,17 +91,46 @@ export function EditPost() {
}
}
}
}
const
handleInputPic
=
async
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
maxImg
=
10
;
const
{
files
}
=
event
.
target
;
if
(
!
(
files
===
null
))
{
setFile
(
files
);
}
if
(
!
(
files
?.
length
===
undefined
))
{
if
(
files
?.
length
<=
maxImg
)
{
for
(
var
i
=
0
;
i
<
files
.
length
;
i
++
)
{
const
reader
=
new
FileReader
();
reader
.
readAsDataURL
(
files
?.[
i
]);
reader
.
onload
=
(
e
)
=>
{
imgArr
.
push
(
e
.
target
?.
result
);
setImgSrc
(
imgArr
);
};
}
}
else
{
alert
(
`사진은 최대
${
maxImg
}
장까지 업로드 가능합니다!`
);
}
}
};
function
postingFormMatch
(
user
:
PostType
)
{
function
postingFormMatch
(
user
:
PostType
)
{
if
(
!
isLength
(
user
.
title
??
""
,
{
min
:
1
}))
{
if
(
!
isLength
(
user
.
title
??
""
,
{
min
:
1
}))
{
setError
(
"
제목을 입력해 주세요.
"
);
setError
(
"
제목을 입력해 주세요.
"
);
alert
(
"
제목을 입력해 주세요.
"
);
return
false
;
return
false
;
}
else
if
(
!
isLength
(
user
.
text
??
""
,
{
min
:
1
}))
{
}
else
if
(
!
isLength
(
user
.
text
??
""
,
{
min
:
1
}))
{
alert
(
"
내용을 입력해 주세요.
"
);
setError
(
"
내용을 입력해 주세요.
"
);
setError
(
"
내용을 입력해 주세요.
"
);
return
false
;
return
false
;
}
else
if
(
equals
(
city
,
"
city
"
))
{
}
else
if
(
equals
(
user
.
city
,
"
city
"
))
{
alert
(
"
도시를 선택해 주세요.
"
);
setError
(
"
도시를 선택해 주세요.
"
);
setError
(
"
도시를 선택해 주세요.
"
);
return
false
;
return
false
;
}
else
if
(
equals
(
theme
,
"
theme
"
))
{
}
else
if
(
equals
(
user
.
theme
,
"
theme
"
))
{
alert
(
"
테마를 선택해 주세요.
"
);
setError
(
"
테마를 선택해 주세요.
"
);
setError
(
"
테마를 선택해 주세요.
"
);
return
false
;
return
false
;
}
else
{
}
else
{
...
@@ -119,7 +182,7 @@ export function EditPost() {
...
@@ -119,7 +182,7 @@ export function EditPost() {
id
=
"files"
id
=
"files"
type
=
"file"
type
=
"file"
multiple
multiple
//
onChange={handleInputPic}
onChange
=
{
handleInputPic
}
className
=
"hidden"
className
=
"hidden"
/>
/>
<
label
htmlFor
=
"files"
className
=
"text-xs mt-1.5 ml-1 "
>
<
label
htmlFor
=
"files"
className
=
"text-xs mt-1.5 ml-1 "
>
...
@@ -132,14 +195,14 @@ export function EditPost() {
...
@@ -132,14 +195,14 @@ export function EditPost() {
name
=
"city"
name
=
"city"
className
=
"border-2 border-sky-400 rounded-full w-20 text-xs"
className
=
"border-2 border-sky-400 rounded-full w-20 text-xs"
onChange
=
{
cityChange
}
onChange
=
{
cityChange
}
defaultValue
=
"질문종류"
defaultValue
=
{
post
.
city
}
>
>
<
option
value
=
"
질문종류
"
>
도시
</
option
>
<
option
value
=
"
city
"
>
도시
</
option
>
<
option
value
=
"Seoul"
>
서울
</
option
>
<
option
value
=
"Seoul"
>
서울
</
option
>
<
option
value
=
"Busan"
>
부산
</
option
>
<
option
value
=
"Busan"
>
부산
</
option
>
<
option
value
=
"Incheon"
>
인천
</
option
>
<
option
value
=
"Incheon"
>
인천
</
option
>
<
option
value
=
"Daeg
oo
"
>
대구
</
option
>
<
option
value
=
"Daeg
u
"
>
대구
</
option
>
<
option
value
=
"
K
wangj
oo
"
>
광주
</
option
>
<
option
value
=
"
G
wangj
u
"
>
광주
</
option
>
<
option
value
=
"Daejeon"
>
대전
</
option
>
<
option
value
=
"Daejeon"
>
대전
</
option
>
<
option
value
=
"Woolsan"
>
울산
</
option
>
<
option
value
=
"Woolsan"
>
울산
</
option
>
<
option
value
=
"Sejong"
>
세종
</
option
>
<
option
value
=
"Sejong"
>
세종
</
option
>
...
@@ -153,9 +216,9 @@ export function EditPost() {
...
@@ -153,9 +216,9 @@ export function EditPost() {
name
=
"theme"
name
=
"theme"
className
=
"border-2 border-sky-400 rounded-full w-20 text-xs"
className
=
"border-2 border-sky-400 rounded-full w-20 text-xs"
onChange
=
{
themeChange
}
onChange
=
{
themeChange
}
defaultValue
=
"질문종류"
defaultValue
=
{
post
.
theme
}
>
>
<
option
value
=
"
질문종류
"
>
테마
</
option
>
<
option
value
=
"
theme
"
>
테마
</
option
>
<
option
value
=
"cycling"
>
사이클링
</
option
>
<
option
value
=
"cycling"
>
사이클링
</
option
>
<
option
value
=
"surfing"
>
서핑
</
option
>
<
option
value
=
"surfing"
>
서핑
</
option
>
<
option
value
=
"activity"
>
액티비티
</
option
>
<
option
value
=
"activity"
>
액티비티
</
option
>
...
@@ -174,9 +237,9 @@ export function EditPost() {
...
@@ -174,9 +237,9 @@ export function EditPost() {
<
div
className
=
"flex w-20"
>
<
div
className
=
"flex w-20"
>
<
button
<
button
type
=
"submit"
type
=
"submit"
className
=
"border-2 border-sky-400 rounded-full w-20 text-xs text-center transition
ease-in-out
delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300"
className
=
"border-2 border-sky-400 rounded-full w-20 text-xs text-center transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300"
>
>
글쓰기
수정
</
button
>
</
button
>
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -190,9 +253,14 @@ export function EditPost() {
...
@@ -190,9 +253,14 @@ export function EditPost() {
/>
/>
<
div
className
=
"flex flex-col mt-1 mb-1"
>
<
div
className
=
"flex flex-col mt-1 mb-1"
>
<
div
className
=
"flex gap-x-2 h-48 overflow-x-scroll"
>
<
div
className
=
"flex gap-x-2 h-48 overflow-x-scroll"
>
{
/* {imgSrc?.map((img, i) => (
{
filesList
?.
map
((
file
,
i
)
=>
(
<img key={i} src={img} width={200} height={200} />
<
img
))} */
}
key
=
{
i
}
src
=
{
"
http://localhost:3000/images/
"
+
file
.
newfilename
}
width
=
{
200
}
height
=
{
200
}
/>
))
}
</
div
>
</
div
>
</
div
>
</
div
>
<
textarea
<
textarea
...
...
frontend/src/post/intopost.tsx
View file @
7285bfbd
import
React
,
{
MouseEvent
}
from
"
react
"
;
import
React
,
{
MouseEvent
,
useEffect
,
useState
}
from
"
react
"
;
import
{
useLocation
,
useNavigate
,
Link
,
Outlet
}
from
"
react-router-dom
"
;
import
{
useLocation
,
useNavigate
,
Link
,
Outlet
}
from
"
react-router-dom
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
import
{
postApi
}
from
"
../apis
"
;
import
{
postApi
}
from
"
../apis
"
;
import
{
PostType
}
from
"
../types
"
;
import
{
PostType
}
from
"
../types
"
;
...
@@ -7,17 +8,54 @@ export interface PostState {
...
@@ -7,17 +8,54 @@ export interface PostState {
state
:
PostType
;
state
:
PostType
;
}
}
export
interface
FileType
{
id
:
string
;
post
:
string
;
originalfilename
:
string
;
newfilename
:
string
;
picturepath
:
string
;
}
export
interface
FilesList
{
filesList
:
FileType
[];
}
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
();
const
navigate
=
useNavigate
();
const
[
filesList
,
setFilesList
]
=
useState
<
FileType
[]
>
();
// console.log(post);
// console.log(post);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
error
,
setError
]
=
useState
(
""
);
const
[
addSuccess
,
setAddSuccess
]
=
useState
(
false
);
const
[
delSuccess
,
setDelSuccess
]
=
useState
(
false
);
useEffect
(()
=>
{
getFilesList
(
post
.
_id
);
console
.
log
(
"
newfilename
"
,
filesList
?.[
0
].
newfilename
);
},
[]);
const
getFilesList
=
async
(
postId
:
string
)
=>
{
const
res
=
await
postApi
.
getFileByPostId
(
postId
);
setFilesList
(
res
);
};
const
handleDeleteClick
=
async
(
event
:
MouseEvent
<
HTMLButtonElement
>
)
=>
{
const
handleDeleteClick
=
async
(
event
:
MouseEvent
<
HTMLButtonElement
>
)
=>
{
try
{
if
(
confirm
(
"
삭제하시겠습니까?
"
)
==
true
)
{
const
postId
=
event
.
currentTarget
.
id
;
const
postId
=
event
.
currentTarget
.
id
;
const
res
=
await
postApi
.
deletePost
(
postId
);
const
res
=
await
postApi
.
deletePost
(
postId
);
navigate
(
"
/board
"
,
{
replace
:
true
});
navigate
(
"
/board
"
,
{
replace
:
true
});
console
.
log
(
"
delete post
"
,
res
);
console
.
log
(
"
delete post
"
,
res
);
}
else
{
return
false
;
}
}
catch
(
error
)
{
console
.
log
(
"
에러발생
"
);
catchErrors
(
error
,
setError
);
}
};
};
return
(
return
(
...
@@ -29,44 +67,59 @@ export function IntoPost() {
...
@@ -29,44 +67,59 @@ export function IntoPost() {
<
button
<
button
id
=
{
post
.
_id
}
id
=
{
post
.
_id
}
onClick
=
{
handleDeleteClick
}
onClick
=
{
handleDeleteClick
}
className
=
"border-2 border-sky-
3
00 rounded-full h-8 w-8 text-xs text-center transition
ease-in-out
delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-red-300 duration-300"
className
=
"border-2 border-sky-
1
00 rounded-full h-8 w-8 text-xs text-center transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-red-300 duration-300"
>
>
삭제
삭제
</
button
>
</
button
>
</
div
>
</
div
>
<
div
className
=
"w-8"
>
<
div
className
=
"w-8"
>
<
Link
to
=
"/edit"
state
=
{
post
}
>
<
Link
to
=
"/edit"
state
=
{
post
}
>
<
button
className
=
"border-2 border-sky-
3
00 rounded-full h-8 w-8 text-xs transition
ease-in-out
delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300"
>
<
button
className
=
"border-2 border-sky-
1
00 rounded-full h-8 w-8 text-xs transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-sky-300 duration-300"
>
수정
수정
</
button
>
</
button
>
</
Link
>
</
Link
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className
=
"flex flex-row h-8 gap-x-1 place-content-between"
>
<
div
className
=
"flex flex-col h-16 md:h-8 md:flex-row"
>
<
div
className
=
"flex basis-3/6 border-2 border-sky-300 rounded"
>
<
div
className
=
"flex basis-1/2 place-content-between h-8"
>
제목:
{
post
.
title
}
<
div
className
=
"flex basis-1/2 border-2 border-sky-200 rounded h-8"
>
</
div
>
작성자:
{
post
.
user
.
slice
(
0
,
8
)
}
<
div
className
=
"flex basis-2/6 border-2 border-sky-300 rounded"
>
작성자:
{
post
.
user
}
</
div
>
</
div
>
<
div
className
=
"flex basis-
2/6
border-2 border-sky-
3
00 rounded"
>
<
div
className
=
"flex basis-
1/2
border-2 border-sky-
2
00 rounded
h-8
"
>
작성일:
{
post
.
date
}
작성일:
{
post
.
date
.
slice
(
0
,
10
)
}
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className
=
"flex
flex-row h-8 gap-x-1
place-content-
start
"
>
<
div
className
=
"flex
basis-1/2
place-content-
between h-8
"
>
<
div
className
=
"flex basis-1/
6
border-2 border-sky-300 rounded"
>
<
div
className
=
"flex basis-1/
3
border-2 border-sky-300 rounded"
>
도시:
{
post
.
city
}
도시:
{
post
.
city
}
</
div
>
</
div
>
<
div
className
=
"flex basis-1/
6
border-2 border-sky-300 rounded"
>
<
div
className
=
"flex basis-1/
3
border-2 border-sky-300 rounded"
>
테마:
{
post
.
theme
}
테마:
{
post
.
theme
}
</
div
>
</
div
>
<
div
className
=
"flex basis-1/
6
border-2 border-sky-300 rounded"
>
<
div
className
=
"flex basis-1/
3
border-2 border-sky-300 rounded"
>
조회수:
{
post
.
counts
}
조회수:
{
post
.
counts
}
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className
=
"border-2 border-sky-300 rounded h-48"
>
files
</
div
>
<
div
className
=
"flex flex-row h-8 gap-x-1 "
>
<
div
className
=
"border-2 border-sky-300 rounded h-96"
>
{
post
.
text
}
</
div
>
<
div
className
=
"flex w-full border-2 border-sky-200 rounded"
>
제목:
{
post
.
title
}
</
div
>
</
div
>
</
div
>
<
div
className
=
"flex-row border-2 border-sky-400 rounded h-48 gap-x-2 "
>
<
div
className
=
"flex gap-x-2 h-48 overflow-x-scroll"
>
{
filesList
?.
map
((
file
,
i
)
=>
(
<
img
key
=
{
i
}
src
=
{
"
http://localhost:3000/images/
"
+
file
.
newfilename
}
width
=
{
200
}
height
=
{
200
}
/>
))
}
</
div
>
</
div
>
<
div
className
=
"border-2 border-sky-500 rounded h-96"
>
{
post
.
text
}
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
);
);
...
...
frontend/src/post/post.tsx
View file @
7285bfbd
...
@@ -18,7 +18,7 @@ export default function Post({ handleClick, post }: Props) {
...
@@ -18,7 +18,7 @@ export default function Post({ handleClick, post }: Props) {
</
button
>
</
button
>
</
Link
>
</
Link
>
</
div
>
</
div
>
<
div
className
=
"basis-3/12"
>
{
post
.
date
}
</
div
>
<
div
className
=
"basis-3/12"
>
{
post
.
date
.
slice
(
0
,
10
)
}
</
div
>
<
div
className
=
"basis-2/12"
>
{
post
.
counts
}
</
div
>
<
div
className
=
"basis-2/12"
>
{
post
.
counts
}
</
div
>
</
div
>
</
div
>
);
);
...
...
frontend/src/post/posting.tsx
View file @
7285bfbd
...
@@ -5,7 +5,6 @@ import equals from "validator/lib/equals";
...
@@ -5,7 +5,6 @@ import equals from "validator/lib/equals";
import
{
catchErrors
}
from
"
../helpers
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
import
{
PostType
}
from
"
../types
"
;
import
{
PostType
}
from
"
../types
"
;
import
{
postApi
}
from
"
../apis
"
;
import
{
postApi
}
from
"
../apis
"
;
import
{
File
}
from
"
formidable
"
;
export
default
function
Posting
()
{
export
default
function
Posting
()
{
const
[
city
,
setCity
]
=
useState
<
string
>
(
"
city
"
);
const
[
city
,
setCity
]
=
useState
<
string
>
(
"
city
"
);
...
@@ -41,35 +40,40 @@ export default function Posting() {
...
@@ -41,35 +40,40 @@ export default function Posting() {
formdata
.
append
(
"
theme
"
,
user
.
theme
);
formdata
.
append
(
"
theme
"
,
user
.
theme
);
formdata
.
append
(
"
city
"
,
user
.
city
);
formdata
.
append
(
"
city
"
,
user
.
city
);
if
(
!
(
filelist
===
undefined
||
filelist
===
null
))
{
if
(
!
(
filelist
===
undefined
||
filelist
===
null
))
{
if
(
filelist
.
length
===
1
)
{
formdata
.
append
(
"
picture
"
,
filelist
?.[
0
]);
const
res
=
await
postApi
.
createFileAndPost
(
formdata
);
}
else
{
for
(
var
i
=
0
;
i
<
filelist
.
length
;
i
++
)
{
for
(
var
i
=
0
;
i
<
filelist
.
length
;
i
++
)
{
formdata
.
append
(
"
picture
"
,
filelist
?.[
i
]);
formdata
.
append
(
"
picture
"
,
filelist
?.[
i
]);
}
}
// formdata: post, imgs
const
res
=
await
postApi
.
createFileAndPost
(
formdata
);
const
res
=
await
postApi
.
createImgAndPost
(
formdata
);
}
}
}
// else {
// const res = await postApi.createImgAndPostTable(formdata);
// }
};
};
async
function
handlePostSubmit
(
event
:
FormEvent
)
{
async
function
handlePostSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
event
.
preventDefault
();
try
{
try
{
if
(
confirm
(
"
게시물을 작성하시겠습니까?
"
)
==
true
)
{
setError
(
""
);
setError
(
""
);
console
.
log
(
"
user data
"
,
user
);
// console.log("user data", user);
if
(
postingFormMatch
(
user
))
{
if
(
!
(
imgSrc
===
undefined
))
{
if
(
postingFormMatch
(
user
,
imgSrc
))
{
setLoading
(
true
);
setLoading
(
true
);
if
(
file
)
{
if
(
file
)
{
const
res
=
sendImg2Db
(
file
);
const
res
=
sendImg2Db
(
file
);
console
.
log
(
res
);
// console.log(res);
}
}
}
// const res = await postApi.posting(user);
// console.log("서버연결됬나요", res);
navigate
(
"
/board
"
,
{
replace
:
true
});
navigate
(
"
/board
"
,
{
replace
:
true
});
setSuccess
(
true
);
setSuccess
(
true
);
setError
(
""
);
setError
(
""
);
}
}
}
else
{
return
false
;
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
log
(
"
에러발생
"
);
console
.
log
(
"
에러발생
"
);
catchErrors
(
error
,
setError
);
catchErrors
(
error
,
setError
);
...
@@ -78,19 +82,27 @@ export default function Posting() {
...
@@ -78,19 +82,27 @@ export default function Posting() {
}
}
}
}
function
postingFormMatch
(
user
:
PostType
)
{
function
postingFormMatch
(
user
:
PostType
,
imgSrc
:
string
[]
)
{
if
(
!
isLength
(
user
.
title
??
""
,
{
min
:
1
}))
{
if
(
!
isLength
(
user
.
title
??
""
,
{
min
:
1
}))
{
alert
(
"
제목을 입력해 주세요.
"
);
setError
(
"
제목을 입력해 주세요.
"
);
setError
(
"
제목을 입력해 주세요.
"
);
return
false
;
return
false
;
}
else
if
(
!
isLength
(
user
.
text
??
""
,
{
min
:
1
}))
{
}
else
if
(
!
isLength
(
user
.
text
??
""
,
{
min
:
1
}))
{
alert
(
"
내용을 입력해 주세요.
"
);
setError
(
"
내용을 입력해 주세요.
"
);
setError
(
"
내용을 입력해 주세요.
"
);
return
false
;
return
false
;
}
else
if
(
equals
(
city
,
"
city
"
))
{
}
else
if
(
equals
(
city
,
"
city
"
))
{
alert
(
"
도시를 선택해 주세요.
"
);
setError
(
"
도시를 선택해 주세요.
"
);
setError
(
"
도시를 선택해 주세요.
"
);
return
false
;
return
false
;
}
else
if
(
equals
(
theme
,
"
theme
"
))
{
}
else
if
(
equals
(
theme
,
"
theme
"
))
{
alert
(
"
테마를 선택해 주세요.
"
);
setError
(
"
테마를 선택해 주세요.
"
);
setError
(
"
테마를 선택해 주세요.
"
);
return
false
;
return
false
;
}
else
if
(
imgSrc
===
undefined
||
imgSrc
===
null
)
{
alert
(
"
사진을 첨부해 주세요.
"
);
setError
(
"
사진을 첨부해 주세요.
"
);
return
false
;
}
else
{
}
else
{
return
true
;
return
true
;
}
}
...
@@ -160,7 +172,7 @@ export default function Posting() {
...
@@ -160,7 +172,7 @@ export default function Posting() {
className
=
"flex flex-col w-96 items-center"
className
=
"flex flex-col w-96 items-center"
>
>
<
div
className
=
"flex flex-row h-8 gap-x-1"
>
<
div
className
=
"flex flex-row h-8 gap-x-1"
>
<
div
className
=
"flex border-2 border-sky-400 rounded-full w-20 place-content-center transition
ease-in-out
delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-gray-300 duration-300"
>
<
div
className
=
"flex border-2 border-sky-400 rounded-full w-20 place-content-center transition delay-150 bg-white-400 hover:-translate-y-1 hover:scale-110 hover:bg-gray-300 duration-300"
>
<
input
<
input
id
=
"files"
id
=
"files"
type
=
"file"
type
=
"file"
...
@@ -184,8 +196,8 @@ export default function Posting() {
...
@@ -184,8 +196,8 @@ export default function Posting() {
<
option
value
=
"Seoul"
>
서울
</
option
>
<
option
value
=
"Seoul"
>
서울
</
option
>
<
option
value
=
"Busan"
>
부산
</
option
>
<
option
value
=
"Busan"
>
부산
</
option
>
<
option
value
=
"Incheon"
>
인천
</
option
>
<
option
value
=
"Incheon"
>
인천
</
option
>
<
option
value
=
"Daeg
oo
"
>
대구
</
option
>
<
option
value
=
"Daeg
u
"
>
대구
</
option
>
<
option
value
=
"
K
wangj
oo
"
>
광주
</
option
>
<
option
value
=
"
G
wangj
u
"
>
광주
</
option
>
<
option
value
=
"Daejeon"
>
대전
</
option
>
<
option
value
=
"Daejeon"
>
대전
</
option
>
<
option
value
=
"Woolsan"
>
울산
</
option
>
<
option
value
=
"Woolsan"
>
울산
</
option
>
<
option
value
=
"Sejong"
>
세종
</
option
>
<
option
value
=
"Sejong"
>
세종
</
option
>
...
...
src/controllers/post.controller.ts
View file @
7285bfbd
...
@@ -5,7 +5,7 @@ import { asyncWrap } from "../helpers";
...
@@ -5,7 +5,7 @@ import { asyncWrap } from "../helpers";
import
{
postDb
,
userDb
}
from
"
../db
"
;
import
{
postDb
,
userDb
}
from
"
../db
"
;
import
{
TypedRequest
}
from
"
../types
"
;
import
{
TypedRequest
}
from
"
../types
"
;
export
const
create
Img
AndPost
=
asyncWrap
(
async
(
reqExp
,
res
,
next
)
=>
{
export
const
create
File
AndPost
=
asyncWrap
(
async
(
reqExp
,
res
,
next
)
=>
{
const
req
=
reqExp
as
TypedRequestAuth
<
{
userId
:
string
}
>
;
const
req
=
reqExp
as
TypedRequestAuth
<
{
userId
:
string
}
>
;
const
{
userId
}
=
req
.
auth
;
const
{
userId
}
=
req
.
auth
;
...
@@ -16,31 +16,47 @@ export const createImgAndPost = asyncWrap(async (reqExp, res, next) => {
...
@@ -16,31 +16,47 @@ export const createImgAndPost = asyncWrap(async (reqExp, res, next) => {
multiples
:
true
,
multiples
:
true
,
});
});
form
.
parse
(
req
,
(
err
,
fields
,
files
)
=>
{
const
fileIdArr
=
new
Array
();
form
.
parse
(
req
,
async
(
err
,
fields
,
files
)
=>
{
if
(
!
Array
.
isArray
(
fields
.
title
))
{
const
title
=
fields
.
title
;
if
(
!
Array
.
isArray
(
fields
.
text
))
{
const
text
=
fields
.
text
;
if
(
!
Array
.
isArray
(
fields
.
theme
))
{
const
theme
=
fields
.
theme
;
if
(
!
Array
.
isArray
(
fields
.
city
))
{
const
city
=
fields
.
city
;
if
(
Array
.
isArray
(
files
.
picture
))
{
if
(
Array
.
isArray
(
files
.
picture
))
{
for
(
var
i
=
0
;
i
<
files
.
picture
.
length
;
i
++
)
{
for
(
var
i
=
0
;
i
<
files
.
picture
.
length
;
i
++
)
{
const
originalfilename
=
files
.
picture
?.[
i
].
originalFilename
;
const
originalfilename
=
files
.
picture
?.[
i
].
originalFilename
;
const
newfilename
=
files
.
picture
?.[
i
].
newFilename
;
const
newfilename
=
files
.
picture
?.[
i
].
newFilename
;
const
filepath
=
files
.
picture
?.[
i
].
filepath
;
const
filepath
=
files
.
picture
?.[
i
].
filepath
;
const
filesRes
=
postDb
.
createFilesRow
(
const
filesRes
=
await
postDb
.
createFilesRow
(
originalfilename
,
originalfilename
,
newfilename
,
newfilename
,
filepath
filepath
);
);
fileIdArr
.
push
(
filesRes
);
}
}
}
// create fileinfos row
}
else
if
(
!
Array
.
isArray
(
files
.
picture
))
{
const
originalfilename
=
files
.
picture
.
originalFilename
;
const
newfilename
=
files
.
picture
.
newFilename
;
const
filepath
=
files
.
picture
.
filepath
;
if
(
!
Array
.
isArray
(
fields
.
title
))
{
const
filesRes
=
await
postDb
.
createFilesRow
(
const
title
=
fields
.
title
;
originalfilename
,
if
(
!
Array
.
isArray
(
fields
.
text
))
{
newfilename
,
const
text
=
fields
.
text
;
filepath
if
(
!
Array
.
isArray
(
fields
.
theme
))
{
);
const
theme
=
fields
.
theme
;
if
(
!
Array
.
isArray
(
fields
.
city
))
{
fileIdArr
.
push
(
filesRes
);
const
city
=
fields
.
city
;
}
// file or one or more
const
postRes
=
postDb
.
createPostRow
({
const
postRes
=
await
postDb
.
createPostRow
({
title
,
title
,
text
,
text
,
theme
,
theme
,
...
@@ -48,7 +64,8 @@ export const createImgAndPost = asyncWrap(async (reqExp, res, next) => {
...
@@ -48,7 +64,8 @@ export const createImgAndPost = asyncWrap(async (reqExp, res, next) => {
date
:
Date
.
now
(),
date
:
Date
.
now
(),
counts
:
0
,
counts
:
0
,
user
:
userId
,
user
:
userId
,
});
// create posts
file
:
fileIdArr
,
});
}
}
}
}
}
}
...
@@ -58,18 +75,25 @@ export const createImgAndPost = asyncWrap(async (reqExp, res, next) => {
...
@@ -58,18 +75,25 @@ export const createImgAndPost = asyncWrap(async (reqExp, res, next) => {
export
const
getAllPost
=
asyncWrap
(
async
(
req
,
res
)
=>
{
export
const
getAllPost
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
posts
=
await
postDb
.
getPosts
();
const
posts
=
await
postDb
.
getPosts
();
console
.
log
(
posts
);
//
console.log(posts);
return
res
.
json
(
posts
);
return
res
.
json
(
posts
);
});
});
export
const
getFiles
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
{
postId
}
=
req
.
params
;
// console.log("나는 말하는 고구마.", postId);
const
files
=
await
postDb
.
getFilesByPostId
(
postId
);
return
res
.
json
(
files
);
});
export
const
addCounts
=
asyncWrap
(
async
(
req
,
res
)
=>
{
export
const
addCounts
=
asyncWrap
(
async
(
req
,
res
)
=>
{
// console.log(req.body);
const
{
postId
}
=
req
.
params
;
const
{
postId
}
=
req
.
params
;
const
{
counts
}
=
req
.
body
as
{
const
{
counts
}
=
req
.
body
as
{
counts
:
number
;
counts
:
number
;
};
};
console
.
log
(
postId
,
counts
);
//
console.log(postId, counts);
const
updateCounts
=
await
postDb
.
addOneCount
(
postId
,
counts
);
const
updateCounts
=
await
postDb
.
addOneCount
(
postId
,
counts
);
...
@@ -130,7 +154,7 @@ export const updatePost = asyncWrap(async (reqExp, res) => {
...
@@ -130,7 +154,7 @@ export const updatePost = asyncWrap(async (reqExp, res) => {
postId
postId
);
);
console
.
log
(
"
게시글 수정 후
"
,
updatePost
);
//
console.log("게시글 수정 후", updatePost);
return
res
.
json
(
updatePost
);
return
res
.
json
(
updatePost
);
});
});
src/db/post.db.ts
View file @
7285bfbd
import
{
Types
,
ObjectId
}
from
"
mongoose
"
;
import
{
Post
,
PostType
}
from
"
../models
"
;
import
{
Post
,
PostType
}
from
"
../models
"
;
import
{
FileInfo
,
IFileInfo
}
from
"
../models
"
;
import
{
FileInfo
,
IFileInfo
}
from
"
../models
"
;
...
@@ -10,8 +11,8 @@ export const createPostRow = async (post: PostType) => {
...
@@ -10,8 +11,8 @@ export const createPostRow = async (post: PostType) => {
user
:
post
.
user
,
user
:
post
.
user
,
date
:
post
.
date
,
date
:
post
.
date
,
counts
:
0
,
counts
:
0
,
file
:
post
.
file
,
});
});
console
.
log
(
"
check
"
,
newPostRow
);
return
newPostRow
;
return
newPostRow
;
};
};
...
@@ -25,22 +26,18 @@ export const createFilesRow = async (
...
@@ -25,22 +26,18 @@ export const createFilesRow = async (
newfilename
:
newfilename
,
newfilename
:
newfilename
,
picturepath
:
picturepath
,
picturepath
:
picturepath
,
});
});
return
newFileRow
;
// console.log("check", newFileRow);
return
newFileRow
.
_id
;
};
};
export
const
findFile
=
async
(
postId
:
string
)
=>
{
export
const
getPosts
=
async
()
=>
{
const
fileInfo
=
await
Post
.
findById
({
postId
}).
populate
(
"
file
"
);
const
posts
=
await
Post
.
find
({}).
sort
({
date
:
-
1
});
return
fileInfo
;
};
export
const
findFileByPostInfo
=
async
(
title
:
string
,
usreId
:
string
)
=>
{
const
posts
=
await
Post
.
find
({
title
:
title
,
userId
:
usreId
});
return
posts
;
return
posts
;
};
};
export
const
getPost
s
=
async
()
=>
{
export
const
get
FilesBy
Post
Id
=
async
(
postId
:
string
)
=>
{
const
post
s
=
await
Post
.
find
({}
);
const
file
s
=
await
Post
.
find
One
({
_id
:
postId
}).
populate
(
"
file
"
);
return
posts
;
return
files
?.
file
;
};
};
export
const
addOneCount
=
async
(
_id
:
string
,
counts
:
number
)
=>
{
export
const
addOneCount
=
async
(
_id
:
string
,
counts
:
number
)
=>
{
...
@@ -49,8 +46,6 @@ export const addOneCount = async (_id: string, counts: number) => {
...
@@ -49,8 +46,6 @@ export const addOneCount = async (_id: string, counts: number) => {
{
counts
:
counts
},
{
counts
:
counts
},
{
new
:
true
}
{
new
:
true
}
);
);
// console.log(newCounts);
return
newCounts
;
return
newCounts
;
};
};
...
...
src/models/fileinfo.model.ts
View file @
7285bfbd
import
{
model
,
Schema
}
from
"
mongoose
"
;
import
{
model
,
ObjectId
,
Schema
}
from
"
mongoose
"
;
export
interface
IFileInfo
{
export
interface
IFileInfo
{
originalfilename
?:
string
;
originalfilename
?:
string
;
...
...
src/models/post.model.ts
View file @
7285bfbd
...
@@ -8,7 +8,7 @@ export interface PostType {
...
@@ -8,7 +8,7 @@ export interface PostType {
date
:
Date
|
number
;
date
:
Date
|
number
;
counts
?:
number
;
counts
?:
number
;
user
:
Types
.
ObjectId
|
string
;
user
:
Types
.
ObjectId
|
string
;
file
?:
Types
.
ObjectId
|
string
;
file
?:
Array
<
Types
.
ObjectId
>
;
}
}
const
PostSchema
=
new
Schema
<
PostType
>
({
const
PostSchema
=
new
Schema
<
PostType
>
({
...
@@ -38,10 +38,12 @@ const PostSchema = new Schema<PostType>({
...
@@ -38,10 +38,12 @@ const PostSchema = new Schema<PostType>({
type
:
Number
,
type
:
Number
,
default
:
0
,
default
:
0
,
},
},
file
:
{
file
:
[
{
type
:
Schema
.
Types
.
ObjectId
,
type
:
Schema
.
Types
.
ObjectId
,
ref
:
"
FileInfo
"
,
ref
:
"
FileInfo
"
,
},
},
],
});
});
export
default
model
<
PostType
>
(
"
Post
"
,
PostSchema
);
export
default
model
<
PostType
>
(
"
Post
"
,
PostSchema
);
src/routes/post.route.ts
View file @
7285bfbd
...
@@ -3,14 +3,17 @@ import { postCtrl, authCtrl, fileInfoCtrl } from "../controllers";
...
@@ -3,14 +3,17 @@ import { postCtrl, authCtrl, fileInfoCtrl } from "../controllers";
const
router
=
express
.
Router
();
const
router
=
express
.
Router
();
router
.
route
(
"
/
"
).
post
(
authCtrl
.
requireLogin
,
postCtrl
.
create
Img
AndPost
);
router
.
route
(
"
/
"
).
post
(
authCtrl
.
requireLogin
,
postCtrl
.
create
File
AndPost
);
router
.
route
(
"
/
"
).
get
(
postCtrl
.
getAllPost
);
router
.
route
(
"
/
"
).
get
(
postCtrl
.
getAllPost
);
router
.
route
(
"
/files/:postId
"
).
get
(
authCtrl
.
requireLogin
,
postCtrl
.
getFiles
);
// router.param("postId", postCtrl.userByPostId);
router
router
.
route
(
"
/:postId
"
)
.
route
(
"
/:postId
"
)
.
post
(
authCtrl
.
requireLogin
,
postCtrl
.
addCounts
)
.
post
(
authCtrl
.
requireLogin
,
postCtrl
.
addCounts
)
.
get
(
authCtrl
.
requireLogin
,
postCtrl
.
getOnePost
)
.
get
(
authCtrl
.
requireLogin
,
postCtrl
.
getOnePost
)
.
delete
(
authCtrl
.
requireLogin
,
postCtrl
.
deleteOnePost
)
// authenticate
.
delete
(
authCtrl
.
requireLogin
,
postCtrl
.
deleteOnePost
)
//
+
authenticate
.
put
(
authCtrl
.
requireLogin
,
postCtrl
.
updatePost
);
.
put
(
authCtrl
.
requireLogin
,
postCtrl
.
updatePost
);
router
.
param
(
"
postId
"
,
postCtrl
.
userByPostId
);
router
.
param
(
"
postId
"
,
postCtrl
.
userByPostId
);
...
...
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