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
18cf7518
Commit
18cf7518
authored
Jul 08, 2022
by
Lee Soobeom
Browse files
Merge remote-tracking branch 'origin/sb4' into develop
parents
6ffbcae1
c950832d
Changes
11
Hide whitespace changes
Inline
Side-by-side
frontend/src/apis/index.ts
View file @
18cf7518
import
axios
from
"
axios
"
;
export
*
as
authApi
from
"
./auth.api
"
;
export
*
as
postApi
from
"
./post.api
"
;
frontend/src/apis/post.api.ts
0 → 100644
View file @
18cf7518
import
axios
from
"
axios
"
;
import
baseUrl
from
"
./baseUrl
"
;
import
{
PostingType
}
from
"
../types
"
;
export
const
posting
=
async
(
post
:
PostingType
)
=>
{
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/posts/`
,
post
);
return
data
;
};
frontend/src/board/board.tsx
View file @
18cf7518
...
...
@@ -14,6 +14,7 @@ interface Posts {
export
const
fakes
=
[
{
id
:
"
a
"
,
username
:
"
lsb
"
,
title
:
"
여행가고싶다...
"
,
date
:
"
2022-06-30
"
,
counts
:
0
,
...
...
@@ -22,6 +23,7 @@ export const fakes = [
},
{
id
:
"
b
"
,
username
:
"
lsb
"
,
title
:
"
바다!바다!바다!
"
,
date
:
"
2022-08-01
"
,
counts
:
0
,
...
...
@@ -30,6 +32,7 @@ export const fakes = [
},
{
id
:
"
c
"
,
username
:
"
lsb
"
,
title
:
"
Jeju-island
"
,
date
:
"
2022-9-10
"
,
counts
:
0
,
...
...
@@ -38,6 +41,7 @@ export const fakes = [
},
{
id
:
"
d
"
,
username
:
"
lsb
"
,
title
:
"
마! 부싼 가봤나!
"
,
date
:
"
2022-9-22
"
,
counts
:
0
,
...
...
@@ -46,26 +50,29 @@ export const fakes = [
},
{
id
:
"
e
"
,
username
:
"
lsb
"
,
title
:
"
Daegu
"
,
date
:
"
2022-10-1
"
,
counts
:
0
,
theme
:
"
s
urfing
"
,
city
:
"
seoul
"
,
theme
:
"
s
ki
"
,
city
:
"
Daegu
"
,
},
{
id
:
"
f
"
,
username
:
"
lsb
"
,
title
:
"
강원도 감자는 맛있다.
"
,
date
:
"
2022-12-12
"
,
counts
:
0
,
theme
:
"
surf
ing
"
,
city
:
"
seoul
"
,
theme
:
"
camp
ing
"
,
city
:
"
강원도
"
,
},
{
id
:
"
g
"
,
username
:
"
lsb
"
,
title
:
"
부산남자의 서울여행
"
,
date
:
"
2022-12-25
"
,
counts
:
0
,
theme
:
"
surfing
"
,
theme
:
"
activity
"
,
city
:
"
seoul
"
,
},
];
...
...
frontend/src/post/posting.tsx
View file @
18cf7518
import
React
,
{
useState
}
from
"
react
"
;
import
React
,
{
FormEvent
,
useState
}
from
"
react
"
;
import
isLength
from
"
validator/lib/isLength
"
;
import
equals
from
"
validator/lib/equals
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
import
{
PostingType
}
from
"
../types
"
;
import
{
postApi
}
from
"
../apis
"
;
function
Title
()
{
const
[
title
,
setTitle
]
=
useState
<
string
>
(
"
질문종류
"
);
export
default
function
Posting
()
{
const
[
city
,
setCity
]
=
useState
<
string
>
(
"
질문종류
"
);
const
[
theme
,
setTheme
]
=
useState
<
string
>
(
"
질문종류
"
);
const
[
title
,
setTitle
]
=
useState
<
string
>
(
""
);
const
[
text
,
setText
]
=
useState
<
string
>
(
""
);
function
TitleChange
(
e
:
{
target
:
{
value
:
React
.
SetStateAction
<
string
>
}
})
{
setTitle
(
e
.
target
.
value
);
}
}
const
[
user
,
setUser
]
=
useState
<
PostingType
>
({
title
:
""
,
text
:
""
,
theme
:
""
,
city
:
""
,
username
:
""
,
});
function
Body
()
{
const
[
body
,
setBody
]
=
useState
<
string
>
(
"
질문종류
"
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
error
,
setError
]
=
useState
(
""
);
const
[
disabled
,
setDisabled
]
=
useState
(
false
);
const
[
success
,
setSuccess
]
=
useState
(
false
);
function
BodyChange
(
e
:
{
target
:
{
value
:
React
.
SetStateAction
<
string
>
}
})
{
setBody
(
e
.
target
.
value
);
async
function
handlePostSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
// prevent onSubmit -> rerendering
try
{
setError
(
""
);
console
.
log
(
"
user data
"
,
user
);
if
(
postingFormMatch
())
{
setLoading
(
true
);
const
res
=
await
postApi
.
posting
(
user
);
console
.
log
(
"
서버연결됬나요
"
,
res
);
console
.
log
(
"
user save
"
);
setSuccess
(
true
);
setError
(
""
);
}
}
catch
(
error
)
{
console
.
log
(
"
에러발생
"
);
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
}
function
SelectCity
()
{
const
[
selectCity
,
setSelectCity
]
=
useState
<
string
>
(
"
질문종류
"
);
function
CityChange
(
e
:
{
target
:
{
value
:
React
.
SetStateAction
<
string
>
}
})
{
setSelectCity
(
e
.
target
.
value
);
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
;
}
}
return
(
<
select
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
>
);
}
function
SelectTheme
()
{
const
[
selectTheme
,
setSelectTheme
]
=
useState
<
string
>
(
"
질문종류
"
);
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
);
};
function
ThemeChange
(
e
:
{
target
:
{
value
:
React
.
SetStateAction
<
string
>
}
})
{
setSelectTheme
(
e
.
target
.
value
);
}
return
(
<
select
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
>
{
/* <option value="cycling">{selectTheme}</option> */
}
</
select
>
);
}
// 눌렀다는 데이터가 어딘가에 있어야 한다. Map 객체를 이용해서 기타등등
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
);
};
// function postup() {
// axios.post("localhost:3000/api/post/up", {
// id: "a",
// title: title,
// body: body,
// date: `${() => new Date()}`,
// theme: selectTheme,
// city: selectCity,
// });
// }
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
);
};
export
default
function
Posting
()
{
return
(
<
div
className
=
"flex flex-col border-3"
>
<
form
className
=
"w-full items-center"
>
<
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
>
<
SelectCity
/>
<
SelectTheme
/>
<
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"
...
...
@@ -107,13 +152,19 @@ export default function Posting() {
<
div
className
=
"flex border-4"
>
<
textarea
onChange
=
{
Title
}
name
=
"title"
onChange
=
{
titleChange
}
placeholder
=
"title"
className
=
"w-full h-8"
></
textarea
>
</
div
>
<
div
onChange
=
{
Body
}
className
=
"flex border-2"
>
<
textarea
placeholder
=
"body"
className
=
"w-full h-96"
></
textarea
>
<
div
className
=
"flex border-2"
>
<
textarea
onChange
=
{
textChange
}
name
=
"text"
placeholder
=
"text"
className
=
"w-full h-96"
></
textarea
>
</
div
>
</
form
>
</
div
>
...
...
frontend/src/types/index.tsx
View file @
18cf7518
export
interface
PostType
{
id
:
string
;
title
:
string
;
body
?:
string
;
date
:
string
;
export
interface
PostType
extends
PostingType
{
date
?:
string
;
counts
:
number
;
theme
?:
string
;
city
?:
string
;
id
?:
string
;
}
export
interface
PostingType
{
title
:
string
;
text
?:
string
;
theme
:
string
;
city
:
string
;
username
:
string
;
}
export
interface
SignupUser
{
...
...
src/controllers/post.controller.ts
View file @
18cf7518
import
{
NextFunction
,
Request
,
Response
}
from
"
express
"
;
import
isLength
from
"
validator/lib/isLength
"
;
import
equals
from
"
validator/lib/equals
"
;
import
{
asyncWrap
}
from
"
../helpers
"
;
import
jwt
,
{
JwtPayload
}
from
"
jsonwebtoken
"
;
import
{
jwtCofig
,
envConfig
,
cookieConfig
}
from
"
../config
"
;
import
{
postDb
}
from
"
../db
"
;
export
const
posting
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
{
title
,
body
,
date
,
theme
,
city
}
=
req
.
body
;
// 1) title 빈 문자열인지 확인
const
titleString
=
postDb
.
checkTitleNull
(
title
,
);
if
(
!
titleString
)
{
return
res
.
status
(
422
).
send
(
`
${
title
}
제목을 입력해 주세요`
);
}
// 2) body 빈 문자열인지 확인
const
bodyString
=
postDb
.
checkBodyNull
(
body
,
);
if
(
!
bodyString
)
{
return
res
.
status
(
422
).
send
(
`
${
body
}
여행 후기를 입력해 주세요`
);
}
const
{
title
,
text
,
date
,
theme
,
city
}
=
req
.
body
;
// 3) submit 이벤트 발생시 date값 입력
const
dateGet
=
postDb
.
getSubmitDate
(
date
,
);
console
.
log
(
"
body
"
,
req
.
body
);
// 1) title 빈 문자열인지 확인
if
(
!
isLength
(
title
??
""
,
{
min
:
1
}))
{
return
res
.
status
(
422
).
send
(
"
제목을 한 글자 이상 입력해주세요
"
);
}
// 4) theme dropdown default-value일 경우 에러
const
themeSelect
=
postDb
.
selectTheme
(
theme
,
);
if
(
!
themeSelect
)
{
return
res
.
status
(
422
).
send
(
`
${
theme
}
테마를 선택해 주세요`
)
}
// 2) body 빈 문자열인지 확인
if
(
!
isLength
(
text
??
""
,
{
min
:
1
}))
{
return
res
.
status
(
422
).
send
(
"
제목을 한 글자 이상 입력해주세요
"
);
}
// 5) cuty dropdown default-value일 경우 에러
const
citySelect
=
postDb
.
selectCity
(
city
,
);
if
(
!
citySelect
)
{
return
res
.
status
(
422
).
send
(
`
${
city
}
도시를 선택해 주세요`
)
}
// 6) 토큰 생성
const
token
=
jwt
.
sign
({
},
jwtCofig
.
secret
,
{
expiresIn
:
jwtCofig
.
expires
,
});
// 3) submit 이벤트 발생시 date값 입력
// 7) 쿠키에 토큰 저장
res
.
cookie
(
cookieConfig
.
name
,
token
,
{
maxAge
:
cookieConfig
.
maxAge
,
path
:
"
/
"
,
httpOnly
:
envConfig
.
mode
===
"
production
"
,
secure
:
envConfig
.
mode
===
"
production
"
,
});
// 4) theme dropdown default-value "테마"일 경우 에러
if
(
equals
(
theme
,
"
질문종류
"
))
{
return
res
.
status
(
422
).
send
(
"
테마를 입력해 주세요
"
);
}
// 8) 사용자 반환
res
.
json
({});
// 5) city dropdown default-value "도시"일 경우 에러
if
(
equals
(
city
,
"
질문종류
"
))
{
return
res
.
status
(
422
).
send
(
"
도시를 선택해 주세요
"
);
}
});
src/db/index.ts
View file @
18cf7518
export
*
as
userDb
from
"
./user.db
"
;
export
*
as
postDb
from
"
./post.db
"
;
//
export * as postDb from "./post.db";
src/db/post.db.ts
deleted
100644 → 0
View file @
6ffbcae1
import
{
PostType
,
Post
}
from
"
../models
"
;
export
const
createPost
=
async
(
post
:
PostType
)
=>
{
const
newPost
=
await
Post
.
create
(
post
);
return
newPost
;
};
export
const
checkTitleNull
=
async
(
title
:
string
,
)
=>
{
}
export
const
checkBodyNull
=
async
(
body
:
string
,
)
=>
{
}
export
const
getSubmitDate
=
async
(
date
:
string
,
)
=>
{
}
export
const
selectTheme
=
async
(
theme
:
string
,
)
=>
{
let
user
;
if
(
theme
!=
"
테마
"
)
{
}
}
export
const
selectCity
=
async
(
city
:
string
,
)
=>
{
let
user
;
if
(
city
!=
"
도시
"
)
{
}
}
src/models/post.model.ts
View file @
18cf7518
import
{
model
,
Schema
}
from
"
mongoose
"
;
export
interface
PostType
{
id
:
string
;
title
:
string
;
date
:
Date
;
body
:
string
;
counts
?:
number
;
theme
:
string
;
city
:
string
;
}
export
interface
PostType
extends
PostingType
{
date
?:
string
;
counts
:
number
;
id
?:
string
;
}
export
interface
PostingType
{
title
:
string
;
text
?:
string
;
theme
:
string
;
city
:
string
;
username
:
string
;
}
const
schema
=
new
Schema
<
PostType
>
({
id
:
{
type
:
String
},
title
:
{
type
:
String
},
date
:
{
type
:
Date
},
body
:
{
type
:
String
},
counts
:
{
type
:
Number
},
theme
:
{
type
:
String
},
city
:
{
type
:
String
},
id
:
{
type
:
String
},
title
:
{
type
:
String
},
date
:
{
type
:
Date
},
text
:
{
type
:
String
},
counts
:
{
type
:
Number
},
theme
:
{
type
:
String
},
city
:
{
type
:
String
},
username
:
{
type
:
String
},
});
export
default
model
<
PostType
>
(
"
Post
"
,
schema
);
src/routes/index.ts
View file @
18cf7518
...
...
@@ -7,7 +7,7 @@ const router = express.Router();
router
.
use
(
"
/users
"
,
userRouter
);
router
.
use
(
"
/auth
"
,
authRouter
);
router
.
use
(
"
/posts
"
,
postRouter
);
//router.route
router
.
use
(
"
/posts
"
,
postRouter
);
//posting함수 -> mongodb에 posts json형식으로 저장
export
default
router
;
src/routes/post.route.ts
View file @
18cf7518
...
...
@@ -3,6 +3,6 @@ import { postCtrl } from "../controllers";
const
router
=
express
.
Router
();
router
.
route
(
"
/
posting
"
).
post
(
postCtrl
.
posting
);
router
.
route
(
"
/
"
).
post
(
postCtrl
.
posting
);
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