Toggle navigation
Toggle navigation
This project
Loading...
Sign in
2020-1-capstone-design1
/
Wico_Project1
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
조민지
2020-06-16 00:44:54 +0900
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
1fc93e20405f6bdc4692ac45c7e363f1e162d221
1fc93e20
1 parent
24ef0c9f
feat: 킥보드 및 사용자 검색 기능 구현
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
194 additions
and
89 deletions
frontend/src/components/Kickboard/KickboardHistoryTable.jsx
frontend/src/components/Kickboard/KickboardStatusCard.jsx
frontend/src/components/Kickboard/SearchButton.jsx
frontend/src/components/Sidebar/Sidebar.jsx
frontend/src/components/Tasks/Tasks.jsx
frontend/src/components/UserHistory/Fallback.jsx
frontend/src/components/UserHistory/SearchButton.jsx
frontend/src/components/UserHistory/UserDataCard.jsx
frontend/src/components/UserHistory/UserHistoryCard.jsx
frontend/src/views/Kickboard.jsx
frontend/src/views/UserHistory.jsx
frontend/src/components/Kickboard/KickboardHistoryTable.jsx
View file @
1fc93e2
...
...
@@ -12,27 +12,20 @@ const UserDataKey = {
rental_fee
:
'대여 금액'
,
};
class
KickboardHistoryTable
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
data
:
[]
};
}
function
timestampToString
(
stamp
)
{
if
(
!
stamp
)
return
''
;
const
date
=
stamp
.
split
(
'T'
)[
0
];
const
time
=
stamp
.
split
(
'T'
)[
1
].
split
(
'.'
)[
0
];
componentDidMount
()
{
fetch
(
`http://1.201.143.67:5901/kickboard/rent/
${
this
.
props
.
kbId
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
if
(
d
.
data
&&
d
.
data
.
length
)
this
.
setState
({
data
:
d
.
data
});
})
.
catch
(
err
=>
console
.
log
(
err
));
}
return
`
${
date
}
${
time
}
`
;
}
const
KickboardHistoryTable
=
(
props
)
=>
{
const
{
kbId
,
historyData
}
=
props
;
render
()
{
return
(
<
Card
title=
{
`
$
{this.props.
kbId}번 킥보드 사용자 히스토리`
}
title=
{
`
$
{
kbId}번 킥보드 사용자 히스토리`
}
ctTableFullWidth
ctTableResponsive
content=
{
...
...
@@ -45,22 +38,25 @@ class KickboardHistoryTable extends React.Component {
</
tr
>
</
thead
>
<
tbody
>
{
this
.
state
.
data
.
map
((
data
,
idx
)
=>
(
{
historyData
.
map
((
data
,
idx
)
=>
{
const
{
user_id
,
rent_datetime
,
return_datetime
,
rental_time
,
rental_distance
,
rental_fee
}
=
data
;
return
(
<
tr
key=
{
idx
}
>
<
td
>
{
data
.
user_id
}
</
td
>
<
td
>
{
data
.
rent_datetime
}
</
td
>
<
td
>
{
data
.
return_datetime
}
</
td
>
<
td
>
{
data
.
rental_time
}
</
td
>
<
td
>
{
data
.
rental_distance
}
</
td
>
<
td
>
{
data
.
rental_fee
}
</
td
>
<
td
>
{
user_id
}
</
td
>
<
td
>
{
timestampToString
(
rent_datetime
)
}
</
td
>
<
td
>
{
timestampToString
(
return_datetime
)
}
</
td
>
<
td
>
{
rental_time
}
분
</
td
>
<
td
>
{
rental_distance
}
km
</
td
>
<
td
>
{
rental_fee
}
원
</
td
>
</
tr
>
))
}
);
})
}
</
tbody
>
</
Table
>
}
/>
)
}
};
export
default
KickboardHistoryTable
;
...
...
frontend/src/components/Kickboard/KickboardStatusCard.jsx
View file @
1fc93e2
...
...
@@ -61,7 +61,7 @@ const kickboardDataKey = {
// "updated_datetime":"2020-06-12T10:00:28.715Z",
// "battery":72
function
makeT
imestampToString
(
stamp
)
{
function
t
imestampToString
(
stamp
)
{
if
(
!
stamp
)
return
''
;
const
date
=
stamp
.
split
(
'T'
)[
0
];
const
time
=
stamp
.
split
(
'T'
)[
1
].
split
(
'.'
)[
0
];
...
...
@@ -69,32 +69,16 @@ function makeTimestampToString(stamp) {
return
`
${
date
}
${
time
}
`
;
}
class
KickboardStatusCard
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
data
:
{}
};
}
componentDidMount
()
{
fetch
(
`http://1.201.143.67:5901/kickboard/
${
this
.
props
.
kbId
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
if
(
d
.
data
&&
d
.
data
.
length
)
this
.
setState
({
data
:
d
.
data
[
0
]});
})
.
catch
(
err
=>
console
.
log
(
err
));
}
render
()
{
const
getStats
=
`마지막 업데이트
${
moment
().
format
(
"YYYY/MM/DD hh:mm"
)}
`
;
const
KickboardStatusCard
=
(
props
)
=>
{
const
{
kbId
,
kbData
}
=
props
;
const
{
battery
,
coordinates
,
states
,
is_good_posture
,
total_driven_distance
,
total_driven_time
,
is_good_gps_signal
,
connected
,
updated_coordinates_datetime
,
connection_updated_datetime
,
model_name
,
updated_datetime
}
=
this
.
state
.
data
;
connection_updated_datetime
,
model_name
,
updated_datetime
}
=
kbData
;
const
getStats
=
`마지막 업데이트
${
moment
().
format
(
"YYYY/MM/DD hh:mm"
)}
`
;
return
(
<
Card
title=
{
`
$
{
this.props.
kbId}번 킥보드`
}
title=
{
`
$
{kbId}번 킥보드`
}
stats=
{
getStats
}
statsIcon=
"fa fa-history"
content=
{
...
...
@@ -117,16 +101,15 @@ class KickboardStatusCard extends React.Component {
<
KickboardData
>
{
kickboardDataKey
.
total_driven_time
}
:
{
total_driven_time
}
분
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
is_good_gps_signal
}
:
{
is_good_gps_signal
?
'양호'
:
'불량'
}
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
connected
}
:
{
connected
?
'연결됨'
:
'연결되지 않음'
}
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
updated_coordinates_datetime
}
:
{
makeT
imestampToString
(
updated_coordinates_datetime
)
}
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
connection_updated_datetime
}
:
{
makeT
imestampToString
(
connection_updated_datetime
)
}
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
updated_coordinates_datetime
}
:
{
t
imestampToString
(
updated_coordinates_datetime
)
}
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
connection_updated_datetime
}
:
{
t
imestampToString
(
connection_updated_datetime
)
}
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
model_name
}
:
{
model_name
}
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
updated_datetime
}
:
{
makeT
imestampToString
(
updated_datetime
)
}
</
KickboardData
>
<
KickboardData
>
{
kickboardDataKey
.
updated_datetime
}
:
{
t
imestampToString
(
updated_datetime
)
}
</
KickboardData
>
</
KickboardDataList
>
</
Row
>
}
/>
);
}
};
export
default
KickboardStatusCard
;
\ No newline at end of file
...
...
frontend/src/components/Kickboard/SearchButton.jsx
View file @
1fc93e2
import
React
from
"react"
;
import
React
,
{
useRef
}
from
"react"
;
import
styled
from
"styled-components"
;
const
SearchButtonWrapper
=
styled
.
div
`
...
...
@@ -30,11 +30,25 @@ const ApplyButton = styled.div`
const
SearchButton
=
()
=>
{
const
SearchButton
=
(
props
)
=>
{
const
{
setKbId
}
=
props
;
const
inputEl
=
useRef
(
null
);
const
searchKickboard
=
(
e
)
=>
{
const
searchText
=
e
.
target
.
value
;
fetch
(
`http://1.201.143.67:5901/kickboard/
${
searchText
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
if
(
d
.
success
&&
d
.
data
.
length
)
setKbId
();
else
window
.
alert
(
'해당 번호의 킥보드가 존재하지 않습니다!'
)
})
.
catch
(
err
=>
console
.
log
(
err
));
};
return
(
<
SearchButtonWrapper
>
<
SearchInput
type=
"text"
className=
"form-control"
placeholder=
{
"킥보드 번호로 검색하기"
}
/>
<
ApplyButton
><
span
>
검색
</
span
></
ApplyButton
>
<
SearchInput
ref=
{
inputEl
}
type=
"text"
className=
"form-control"
placeholder=
{
"킥보드 번호로 검색하기"
}
/>
<
ApplyButton
onClick=
{
(
e
)
=>
searchKickboard
(
e
)
}
><
span
>
검색
</
span
></
ApplyButton
>
</
SearchButtonWrapper
>
);
};
...
...
frontend/src/components/Sidebar/Sidebar.jsx
View file @
1fc93e2
...
...
@@ -27,17 +27,11 @@ class Sidebar extends Component {
backgroundColor
:
'rgb(217,94,45)'
};
console
.
log
(
this
.
props
.
color
);
return
(
<
div
id=
"sidebar"
className=
"sidebar"
>
{
this
.
props
.
hasImage
?
(
<
div
className=
"sidebar-background"
style=
{
sidebarBackground
}
/>
)
:
(
null
)
}
<
div
className=
"logo"
>
<
a
href=
"https://www.creative-tim.com?ref=lbd-sidebar"
...
...
frontend/src/components/Tasks/Tasks.jsx
View file @
1fc93e2
...
...
@@ -23,7 +23,6 @@ import Button from "components/CustomButton/CustomButton.jsx";
export
class
Tasks
extends
Component
{
handleCheckbox
=
event
=>
{
const
target
=
event
.
target
;
console
.
log
(
event
.
target
);
this
.
setState
({
[
target
.
name
]:
target
.
checked
});
...
...
frontend/src/components/UserHistory/Fallback.jsx
0 → 100644
View file @
1fc93e2
import
React
,
{
useRef
}
from
"react"
;
import
styled
from
"styled-components"
;
import
{
Col
,
Row
}
from
"react-bootstrap"
;
import
Card
from
"components/Card/Card.jsx"
;
const
Wrapper
=
styled
.
div
`
display: flex;
align-items: center;
justify-content: center;
color: #333333;
text-align: center;
`
;
const
EmptyImage
=
styled
.
img
`
max-width: 100%;
height: auto !important;
`
;
const
SearchButton
=
(
props
)
=>
{
return
(
<
Card
content=
{
<
Row
>
<
Col
md=
{
8
}
mdOffset=
{
2
}
>
<
EmptyImage
src=
"https://raw.githubusercontent.com/devSoyoung/whale-extension-keycrab/master/images/empty.png"
alt=
"empty"
/>
</
Col
>
<
Col
md=
{
12
}
>
<
Wrapper
>
{
Number
(
props
.
userId
)
<
0
?
<
div
>
검색 결과가 존재하지 않습니다.
</
div
>
:
<
div
>
전화번호, 이메일, 사용자ID를 통해
<
br
/>
사용자를 검색해보세요!
</
div
>
}
</
Wrapper
>
</
Col
>
</
Row
>
}
/>
);
};
export
default
SearchButton
;
frontend/src/components/UserHistory/SearchButton.jsx
View file @
1fc93e2
import
React
from
"react"
;
import
React
,
{
useRef
,
useState
}
from
"react"
;
import
styled
from
"styled-components"
;
const
SearchButtonWrapper
=
styled
.
div
`
...
...
@@ -8,7 +8,7 @@ const SearchButtonWrapper = styled.div`
`
;
const
SearchInput
=
styled
.
input
`
width:
60
%;
width:
55
%;
`
;
const
ApplyButton
=
styled
.
div
`
...
...
@@ -29,22 +29,58 @@ const ApplyButton = styled.div`
`
;
const
SelectBox
=
styled
.
select
`
width:
17
%;
width:
22
%;
color: #333333;
border-color: #E3E3E3;
border-radius: 4px;
`
;
const
searchTypeKR
=
{
phone_number
:
'전화번호'
,
email
:
'이메일'
,
user_id
:
'사용자ID'
};
const
SearchButton
=
(
props
)
=>
{
const
selectEl
=
useRef
(
null
);
const
inputEl
=
useRef
(
null
);
const
{
setUserId
}
=
props
;
const
[
searchType
,
setSearchType
]
=
useState
(
'phone_number'
);
const
searchUserData
=
(
e
)
=>
{
e
.
preventDefault
();
const
searchText
=
inputEl
.
current
.
value
;
if
(
searchType
===
'user_id'
)
{
fetch
(
`http://1.201.143.67:5901/user/
${
searchType
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
if
(
d
.
success
)
setUserId
(
searchType
);
else
setUserId
(
'-1'
);
// 검색결과 X
})
}
else
{
fetch
(
`http://1.201.143.67:5901/user/
${
searchType
}
/
${
searchText
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
if
(
d
.
success
)
setUserId
(
d
.
data
[
0
].
user_id
);
else
setUserId
(
'-1'
);
// 검색결과 X
})
}
};
const
onChangeSearchOption
=
(
e
)
=>
{
setSearchType
(
e
.
target
.
value
)
};
const
SearchButton
=
()
=>
{
return
(
<
SearchButtonWrapper
>
<
SelectBox
>
<
option
value=
"전화 번호"
>
전화 번호
</
option
>
<
option
value=
"이메일"
>
이메일
</
option
>
<
SelectBox
ref=
{
selectEl
}
onChange=
{
(
e
)
=>
onChangeSearchOption
(
e
)
}
>
<
option
value=
"phone_number"
>
전화번호
</
option
>
<
option
value=
"email"
>
이메일
</
option
>
<
option
value=
"user_id"
>
사용자ID
</
option
>
</
SelectBox
>
<
SearchInput
type=
"text"
className=
"form-control"
placeholder=
{
"킥보드 번호로 검색하기"
}
/>
<
ApplyButton
><
span
>
검색
</
span
></
ApplyButton
>
<
SearchInput
type=
"text"
ref=
{
inputEl
}
className=
"form-control"
placeholder=
{
`
$
{searchTypeKR[searchType]}로 검색하기`
}
/>
<
ApplyButton
onClick=
{
(
e
)
=>
searchUserData
(
e
)
}
><
span
>
검색
</
span
></
ApplyButton
>
</
SearchButtonWrapper
>
);
};
...
...
frontend/src/components/UserHistory/UserDataCard.jsx
View file @
1fc93e2
...
...
@@ -9,7 +9,7 @@ const UserData = styled.div`
font-size: 15px;
`
;
function
makeT
imestampToString
(
stamp
)
{
function
t
imestampToString
(
stamp
)
{
if
(
!
stamp
)
return
''
;
const
date
=
stamp
.
split
(
'T'
)[
0
];
const
time
=
stamp
.
split
(
'T'
)[
1
].
split
(
'.'
)[
0
];
...
...
@@ -56,10 +56,10 @@ const UserDataCard = (props) => {
</
Row
>
<
Row
>
<
Col
md=
{
6
}
sm=
{
6
}
xs=
{
12
}
>
<
UserData
>
가입 날짜 :
{
makeT
imestampToString
(
created_datetime
)
}
</
UserData
>
<
UserData
>
가입 날짜 :
{
t
imestampToString
(
created_datetime
)
}
</
UserData
>
</
Col
>
<
Col
md=
{
6
}
sm=
{
6
}
xs=
{
12
}
>
<
UserData
>
최근 로그인 날짜 :
{
makeT
imestampToString
(
recent_login_datetime
)
}
</
UserData
>
<
UserData
>
최근 로그인 날짜 :
{
t
imestampToString
(
recent_login_datetime
)
}
</
UserData
>
</
Col
>
</
Row
>
<
Row
>
...
...
frontend/src/components/UserHistory/UserHistoryCard.jsx
View file @
1fc93e2
...
...
@@ -7,6 +7,14 @@ import moment from "moment";
const
thArray
=
[
'킥보드 시리얼 번호'
,
'대여 시각'
,
'반납 시각'
,
'총 대여 시간'
,
'이동 거리'
,
'대여 금액'
];
function
timestampToString
(
stamp
)
{
if
(
!
stamp
)
return
''
;
const
date
=
stamp
.
split
(
'T'
)[
0
];
const
time
=
stamp
.
split
(
'T'
)[
1
].
split
(
'.'
)[
0
];
return
`
${
date
}
${
time
}
`
;
}
const
UserHistoryCard
=
(
props
)
=>
{
const
{
userId
,
rentData
}
=
props
;
const
getStats
=
`마지막 업데이트
${
moment
().
format
(
"YYYY/MM/DD hh:mm"
)}
`
;
...
...
@@ -14,7 +22,6 @@ const UserHistoryCard = (props) => {
return
(
<
Card
title=
{
`
$
{userId}번 사용자 킥보드 사용 히스토리`
}
ctTableFullWidth
ctTableResponsive
stats=
{
getStats
}
statsIcon=
"fa fa-history"
...
...
@@ -31,11 +38,11 @@ const UserHistoryCard = (props) => {
{
rentData
.
map
((
data
,
idx
)
=>
(
<
tr
key=
{
idx
}
>
<
td
>
{
data
.
serial_number
}
</
td
>
<
td
>
{
data
.
rent_datetime
}
</
td
>
<
td
>
{
data
.
return_datetime
}
</
td
>
<
td
>
{
data
.
rental_time
}
</
td
>
<
td
>
{
data
.
rental_distance
}
</
td
>
<
td
>
{
data
.
rental_fee
}
</
td
>
<
td
>
{
timestampToString
(
data
.
rent_datetime
)
}
</
td
>
<
td
>
{
timestampToString
(
data
.
return_datetime
)
}
</
td
>
<
td
>
{
data
.
rental_time
}
분
</
td
>
<
td
>
{
data
.
rental_distance
}
km
</
td
>
<
td
>
{
data
.
rental_fee
}
원
</
td
>
</
tr
>
))
}
</
tbody
>
...
...
frontend/src/views/Kickboard.jsx
View file @
1fc93e2
...
...
@@ -8,6 +8,23 @@ import SearchButton from '../components/Kickboard/SearchButton';
const
Kickboard
=
()
=>
{
const
[
kbId
,
setKbId
]
=
useState
(
'000165'
);
const
[
kbData
,
setKbData
]
=
useState
({});
const
[
historyData
,
setHistoryData
]
=
useState
([]);
useEffect
(()
=>
{
fetch
(
`http://1.201.143.67:5901/kickboard/
${
kbId
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
if
(
d
.
data
&&
d
.
data
.
length
)
setKbData
(
d
.
data
[
0
]);
fetch
(
`http://1.201.143.67:5901/kickboard/rent/
${
kbId
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
if
(
d
.
data
&&
d
.
data
.
length
)
setHistoryData
(
d
.
data
);
})
})
.
catch
(
err
=>
console
.
log
(
err
));
},[
kbId
]);
// 여기 API 요청
return
(
...
...
@@ -15,7 +32,7 @@ const Kickboard = () => {
<
Grid
fluid
>
<
Row
>
<
Col
md=
{
4
}
mdOffset=
{
8
}
sm=
{
3
}
smOffset=
{
9
}
style=
{
{
marginBottom
:
15
}
}
>
<
SearchButton
/>
<
SearchButton
setKbId=
{
setKbId
}
/>
</
Col
>
</
Row
>
<
Row
>
...
...
@@ -23,12 +40,12 @@ const Kickboard = () => {
<
GoogleMapCard
/>
</
Col
>
<
Col
md=
{
6
}
>
<
KickboardStatusCard
kbId=
{
kbId
}
/>
<
KickboardStatusCard
kbId=
{
kbId
}
kbData=
{
kbData
}
/>
</
Col
>
</
Row
>
<
Row
>
<
Col
md=
{
12
}
>
<
KickboardHistoryTable
kbId=
{
kbId
}
/>
<
KickboardHistoryTable
kbId=
{
kbId
}
historyData=
{
historyData
}
/>
</
Col
>
</
Row
>
</
Grid
>
...
...
frontend/src/views/UserHistory.jsx
View file @
1fc93e2
...
...
@@ -3,9 +3,10 @@ import { Grid, Row, Col, Table } from "react-bootstrap";
import
UserDataCard
from
'../components/UserHistory/UserDataCard'
;
import
UserHistoryCard
from
'../components/UserHistory/UserHistoryCard'
;
import
SearchButton
from
"../components/UserHistory/SearchButton"
;
import
Fallback
from
'../components/UserHistory/Fallback'
;
const
UserHistory
=
()
=>
{
const
[
userId
,
setUserId
]
=
useState
(
7575
);
const
[
userId
,
setUserId
]
=
useState
(
'0'
);
const
[
userData
,
setUserData
]
=
useState
({});
const
[
rentData
,
setRentData
]
=
useState
([]);
...
...
@@ -14,29 +15,33 @@ const UserHistory = () => {
},[]);
useEffect
(()
=>
{
if
(
Number
(
userId
)
<
0
)
return
;
fetch
(
`http://1.201.143.67:5901/user/
${
userId
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
console
.
log
(
'userData'
,
d
.
data
[
0
])
if
(
!
d
.
success
)
setUserId
(
'0'
);
// 유효하지 않은 userId인 경우
if
(
d
.
data
&&
d
.
data
.
length
)
setUserData
(
d
.
data
[
0
]);
fetch
(
`http://1.201.143.67:5901/user/rent/
${
userId
}
`
)
.
then
(
r
=>
r
.
json
())
.
then
(
d
=>
{
console
.
log
(
'rentData'
,
d
.
data
);
if
(
d
.
data
&&
d
.
data
.
length
)
setRentData
(
d
.
data
);
})
})
.
catch
(
err
=>
console
.
log
(
err
));
},[
userId
]);
.
catch
(
err
=>
console
.
log
(
err
));
},[
userId
]);
return
(
<
div
className=
"content"
>
<
Grid
fluid
>
<
Row
>
<
Col
md=
{
4
}
mdOffset=
{
8
}
sm=
{
5
}
smOffset=
{
7
}
style=
{
{
marginBottom
:
15
}
}
>
<
SearchButton
/>
<
SearchButton
setUserId=
{
setUserId
}
/>
</
Col
>
</
Row
>
{
Number
(
userId
)
>
0
?
(
<
Row
>
<
Col
md=
{
12
}
>
<
UserDataCard
userId=
{
userId
}
userData=
{
userData
}
/>
...
...
@@ -45,6 +50,15 @@ const UserHistory = () => {
<
UserHistoryCard
userId=
{
userId
}
rentData=
{
rentData
}
/>
</
Col
>
</
Row
>
)
:
(
<
Row
>
<
Col
md=
{
8
}
mdOffset=
{
2
}
>
<
Fallback
userId=
{
userId
}
/>
</
Col
>
</
Row
>
)
}
</
Grid
>
</
div
>
);
...
...
Please
register
or
login
to post a comment