Showing
11 changed files
with
272 additions
and
76 deletions
... | @@ -4920,6 +4920,12 @@ | ... | @@ -4920,6 +4920,12 @@ |
4920 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.413.tgz", | 4920 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.413.tgz", |
4921 | "integrity": "sha512-Jm1Rrd3siqYHO3jftZwDljL2LYQafj3Kki5r+udqE58d0i91SkjItVJ5RwlJn9yko8i7MOcoidVKjQlgSdd1hg==" | 4921 | "integrity": "sha512-Jm1Rrd3siqYHO3jftZwDljL2LYQafj3Kki5r+udqE58d0i91SkjItVJ5RwlJn9yko8i7MOcoidVKjQlgSdd1hg==" |
4922 | }, | 4922 | }, |
4923 | + "element-resize-event": { | ||
4924 | + "version": "2.0.9", | ||
4925 | + "resolved": "https://registry.npmjs.org/element-resize-event/-/element-resize-event-2.0.9.tgz", | ||
4926 | + "integrity": "sha1-L14VgaKW61J1IQwUG8VjQuIY+HY=", | ||
4927 | + "dev": true | ||
4928 | + }, | ||
4923 | "elliptic": { | 4929 | "elliptic": { |
4924 | "version": "6.5.2", | 4930 | "version": "6.5.2", |
4925 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", | 4931 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", |
... | @@ -9774,6 +9780,11 @@ | ... | @@ -9774,6 +9780,11 @@ |
9774 | "minimist": "^1.2.5" | 9780 | "minimist": "^1.2.5" |
9775 | } | 9781 | } |
9776 | }, | 9782 | }, |
9783 | + "moment": { | ||
9784 | + "version": "2.26.0", | ||
9785 | + "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", | ||
9786 | + "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==" | ||
9787 | + }, | ||
9777 | "move-concurrently": { | 9788 | "move-concurrently": { |
9778 | "version": "1.0.1", | 9789 | "version": "1.0.1", |
9779 | "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", | 9790 | "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", |
... | @@ -12017,6 +12028,15 @@ | ... | @@ -12017,6 +12028,15 @@ |
12017 | } | 12028 | } |
12018 | } | 12029 | } |
12019 | }, | 12030 | }, |
12031 | + "react-dimensions": { | ||
12032 | + "version": "1.3.1", | ||
12033 | + "resolved": "https://registry.npmjs.org/react-dimensions/-/react-dimensions-1.3.1.tgz", | ||
12034 | + "integrity": "sha512-go5vMuGUxaB5PiTSIk+ZfAxLbHwcIgIfLhkBZ2SIMQjaCgnpttxa30z5ijEzfDjeOCTGRpxvkzcmE4Vt4Ppvyw==", | ||
12035 | + "dev": true, | ||
12036 | + "requires": { | ||
12037 | + "element-resize-event": "^2.0.4" | ||
12038 | + } | ||
12039 | + }, | ||
12020 | "react-dom": { | 12040 | "react-dom": { |
12021 | "version": "16.8.6", | 12041 | "version": "16.8.6", |
12022 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz", | 12042 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz", |
... | @@ -12061,6 +12081,11 @@ | ... | @@ -12061,6 +12081,11 @@ |
12061 | "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", | 12081 | "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", |
12062 | "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" | 12082 | "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" |
12063 | }, | 12083 | }, |
12084 | + "react-moment": { | ||
12085 | + "version": "0.9.7", | ||
12086 | + "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.9.7.tgz", | ||
12087 | + "integrity": "sha512-ifzUrUGF6KRsUN2pRG5k56kO0mJBr8kRkWb0wNvtFIsBIxOuPxhUpL1YlXwpbQCbHq23hUu6A0VEk64HsFxk9g==" | ||
12088 | + }, | ||
12064 | "react-notification-system": { | 12089 | "react-notification-system": { |
12065 | "version": "0.2.17", | 12090 | "version": "0.2.17", |
12066 | "resolved": "https://registry.npmjs.org/react-notification-system/-/react-notification-system-0.2.17.tgz", | 12091 | "resolved": "https://registry.npmjs.org/react-notification-system/-/react-notification-system-0.2.17.tgz", | ... | ... |
... | @@ -5,12 +5,14 @@ | ... | @@ -5,12 +5,14 @@ |
5 | "dependencies": { | 5 | "dependencies": { |
6 | "bootstrap": "3.3.7", | 6 | "bootstrap": "3.3.7", |
7 | "chartist": "0.10.1", | 7 | "chartist": "0.10.1", |
8 | + "moment": "^2.26.0", | ||
8 | "node-sass": "4.12.0", | 9 | "node-sass": "4.12.0", |
9 | "react": "16.8.6", | 10 | "react": "16.8.6", |
10 | "react-bootstrap": "0.32.4", | 11 | "react-bootstrap": "0.32.4", |
11 | "react-chartist": "0.13.3", | 12 | "react-chartist": "0.13.3", |
12 | "react-dom": "16.8.6", | 13 | "react-dom": "16.8.6", |
13 | "react-google-maps": "9.4.5", | 14 | "react-google-maps": "9.4.5", |
15 | + "react-moment": "^0.9.7", | ||
14 | "react-notification-system": "0.2.17", | 16 | "react-notification-system": "0.2.17", |
15 | "react-router": "5.0.0", | 17 | "react-router": "5.0.0", |
16 | "react-router-dom": "5.0.0", | 18 | "react-router-dom": "5.0.0", |
... | @@ -21,6 +23,7 @@ | ... | @@ -21,6 +23,7 @@ |
21 | "@types/googlemaps": "3.30.19", | 23 | "@types/googlemaps": "3.30.19", |
22 | "@types/markerclustererplus": "2.1.33", | 24 | "@types/markerclustererplus": "2.1.33", |
23 | "@types/react": "16.8.13", | 25 | "@types/react": "16.8.13", |
26 | + "react-dimensions": "^1.3.1", | ||
24 | "typescript": "3.4.3" | 27 | "typescript": "3.4.3" |
25 | }, | 28 | }, |
26 | "scripts": { | 29 | "scripts": { | ... | ... |
1 | +import React, {useEffect} from "react"; | ||
2 | +import Dimensions from "react-dimensions"; | ||
3 | + | ||
4 | +let map, infoWindow; | ||
5 | + | ||
6 | +const GoogleMap = (props) => { | ||
7 | + useEffect(() => { | ||
8 | + console.log('mount'); | ||
9 | + const { google } = window; | ||
10 | + | ||
11 | + infoWindow = new window.google.maps.InfoWindow({}); | ||
12 | + | ||
13 | + map = new google.maps.Map(document.getElementById("map"), { | ||
14 | + zoom: 11, | ||
15 | + center: {lat: -34.397, lng: 150.644}, | ||
16 | + disableDefaultUI: true, | ||
17 | + zoomControl: true | ||
18 | + }); | ||
19 | + }, []); | ||
20 | + | ||
21 | + return ( | ||
22 | + <div id="map" style={{height:props.containerWidth, backgroundColor:'pink'}}> | ||
23 | + </div> | ||
24 | + ) | ||
25 | +}; | ||
26 | + | ||
27 | +export default Dimensions()(GoogleMap) // Enhanced component | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +import React from "react"; | ||
2 | +import { Card } from "components/Card/Card.jsx"; | ||
3 | +import Dimensions from 'react-dimensions' | ||
4 | +import moment from 'moment'; | ||
5 | +import GoogleMap from './GoogleMap'; | ||
6 | + | ||
7 | +const GoogleMapCard = (props) => { | ||
8 | + const getStats = `마지막 업데이트 ${moment().format("YYYY/MM/DD hh:mm")}`; | ||
9 | + | ||
10 | + return ( | ||
11 | + <Card | ||
12 | + id="chartActivity" | ||
13 | + title="서비스 현황" | ||
14 | + category="All products including Taxes" | ||
15 | + stats={getStats} | ||
16 | + statsIcon="fa fa-history" | ||
17 | + content={ | ||
18 | + <GoogleMap/> | ||
19 | + } | ||
20 | + /> | ||
21 | + ); | ||
22 | +}; | ||
23 | + | ||
24 | +export default GoogleMapCard // Enhanced component | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +import React from "react"; | ||
2 | +import {Table} from "react-bootstrap"; | ||
3 | +import { Card } from "components/Card/Card.jsx"; | ||
4 | + | ||
5 | +import { tdArray } from "variables/Variables.jsx"; | ||
6 | + | ||
7 | +const thArray = ['유저ID', '대여 시각', '반납 시각', '대여 시간', '이동 거리', '대여 금액']; | ||
8 | + | ||
9 | +const KickboardHistoryTable = () => { | ||
10 | + | ||
11 | + return ( | ||
12 | + <Card | ||
13 | + title="Striped Table with Hover" | ||
14 | + category="Here is a subtitle for this table" | ||
15 | + ctTableFullWidth | ||
16 | + ctTableResponsive | ||
17 | + content={ | ||
18 | + <Table striped hover> | ||
19 | + <thead> | ||
20 | + <tr> | ||
21 | + {thArray.map((prop, key) => { | ||
22 | + return <th key={key}>{prop}</th>; | ||
23 | + })} | ||
24 | + </tr> | ||
25 | + </thead> | ||
26 | + <tbody> | ||
27 | + {tdArray.map((prop, key) => { | ||
28 | + return ( | ||
29 | + <tr key={key}> | ||
30 | + {prop.map((prop, key) => { | ||
31 | + return <td key={key}>{prop}</td>; | ||
32 | + })} | ||
33 | + </tr> | ||
34 | + ); | ||
35 | + })} | ||
36 | + </tbody> | ||
37 | + </Table> | ||
38 | + } | ||
39 | + /> | ||
40 | + ) | ||
41 | +}; | ||
42 | + | ||
43 | +export default KickboardHistoryTable; | ||
44 | + |
1 | +import React from "react"; | ||
2 | +import { Card } from "components/Card/Card.jsx"; | ||
3 | +import {Col, Row} from "react-bootstrap"; | ||
4 | +import styled from "styled-components" | ||
5 | +import moment from "moment"; | ||
6 | + | ||
7 | +// border: 1px solid #E3E3E3; | ||
8 | +const KickboardButton = styled.div` | ||
9 | + background-color: #e7e7e7; | ||
10 | + border-radius: 4px; | ||
11 | + color: #565656; | ||
12 | + padding: 8px 12px; | ||
13 | + height: 40px; | ||
14 | + box-shadow: none; | ||
15 | + margin: 0 auto; | ||
16 | + text-align: center; | ||
17 | + margin-bottom: 10px; | ||
18 | + | ||
19 | + &:hover { | ||
20 | + background-color: #565656; | ||
21 | + color: white; | ||
22 | + cursor: pointer; | ||
23 | + } | ||
24 | +`; | ||
25 | + | ||
26 | +const KickboardDataList = styled.ul` | ||
27 | + font-size: 16px; | ||
28 | +`; | ||
29 | + | ||
30 | +const KickboardData = styled.li` | ||
31 | + padding: 3px 0; | ||
32 | +`; | ||
33 | + | ||
34 | +const kickboardDataKey = { | ||
35 | + a: '배터리', | ||
36 | + b: '킥보드 위치', | ||
37 | + c: '킥보드 상태', | ||
38 | + d: '킥보드 자세 여부', | ||
39 | + e: '총 누적 이동 거리', | ||
40 | + f: '총 누적 대여 시간', | ||
41 | + g: '신호 양호 여부', | ||
42 | + h: '현재 네트워크 연결 여부', | ||
43 | + i: '최근 gps 업데이트 시각', | ||
44 | + j: '최근 연결 업데이트 시각', | ||
45 | + k: '모델명', | ||
46 | + l: '최근 업데이트 시각', | ||
47 | +}; | ||
48 | + | ||
49 | +const KickboardStatusCard = () => { | ||
50 | + const getStats = `마지막 업데이트 ${moment().format("YYYY/MM/DD hh:mm")}`; | ||
51 | + | ||
52 | + return ( | ||
53 | + <Card | ||
54 | + title={'000000번 킥보드'} | ||
55 | + stats={getStats} | ||
56 | + statsIcon="fa fa-history" | ||
57 | + content={ | ||
58 | + <Row> | ||
59 | + <Col md={4} sm={4} xs={4}> | ||
60 | + <KickboardButton>경적 울리기</KickboardButton> | ||
61 | + </Col> | ||
62 | + <Col md={4} sm={4} xs={4}> | ||
63 | + <KickboardButton>반납하기</KickboardButton> | ||
64 | + </Col> | ||
65 | + <Col md={4} sm={4} xs={4}> | ||
66 | + <KickboardButton>운행 종료하기</KickboardButton> | ||
67 | + </Col> | ||
68 | + <KickboardDataList> | ||
69 | + { | ||
70 | + Object.keys(kickboardDataKey).map(key => { | ||
71 | + return <KickboardData>{kickboardDataKey[key]} : {key}</KickboardData> | ||
72 | + }) | ||
73 | + } | ||
74 | + </KickboardDataList> | ||
75 | + </Row> | ||
76 | + } | ||
77 | + > | ||
78 | + </Card> | ||
79 | + ); | ||
80 | +}; | ||
81 | + | ||
82 | +export default KickboardStatusCard; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +import React from "react"; | ||
2 | +import styled from "styled-components"; | ||
3 | + | ||
4 | +const SearchButtonWrapper = styled.div` | ||
5 | + display: flex; | ||
6 | + flex-direction: row; | ||
7 | + justify-content: space-between; | ||
8 | +`; | ||
9 | + | ||
10 | +const SearchInput = styled.input` | ||
11 | + width: 80%; | ||
12 | +`; | ||
13 | + | ||
14 | +const ApplyButton = styled.div` | ||
15 | + width: 17%; | ||
16 | + background-color: #e7e7e7; | ||
17 | + border-radius: 4px; | ||
18 | + color: #565656; | ||
19 | + text-align: center; | ||
20 | + | ||
21 | + display: flex; | ||
22 | + justify-content: center; | ||
23 | + align-items: center; | ||
24 | + | ||
25 | + &:hover { | ||
26 | + background-color: #565656; | ||
27 | + color: white; | ||
28 | + cursor: pointer; | ||
29 | +`; | ||
30 | + | ||
31 | + | ||
32 | + | ||
33 | +const SearchButton = () => { | ||
34 | + return ( | ||
35 | + <SearchButtonWrapper> | ||
36 | + <SearchInput type="text" className="form-control" placeholder={"킥보드 번호로 검색하기"}/> | ||
37 | + <ApplyButton><span>검색</span></ApplyButton> | ||
38 | + </SearchButtonWrapper> | ||
39 | + ); | ||
40 | +}; | ||
41 | + | ||
42 | +export default SearchButton; | ||
43 | + | ||
44 | + |
... | @@ -268,12 +268,12 @@ var style = { | ... | @@ -268,12 +268,12 @@ var style = { |
268 | // | 268 | // |
269 | const thArray = ["ID", "Name", "Salary", "Country", "City"]; | 269 | const thArray = ["ID", "Name", "Salary", "Country", "City"]; |
270 | const tdArray = [ | 270 | const tdArray = [ |
271 | - ["1", "Dakota Rice", "$36,738", "Niger", "Oud-Turnhout"], | 271 | + ["1", "Dakota Rice", "$36,738", "Niger", "Oud-Turnhout", '1'], |
272 | - ["2", "Minerva Hooper", "$23,789", "Curaçao", "Sinaai-Waas"], | 272 | + ["2", "Minerva Hooper", "$23,789", "Curaçao", "Sinaai-Waas", '1'], |
273 | - ["3", "Sage Rodriguez", "$56,142", "Netherlands", "Baileux"], | 273 | + ["3", "Sage Rodriguez", "$56,142", "Netherlands", "Baileux", '1'], |
274 | - ["4", "Philip Chaney", "$38,735", "Korea, South", "Overland Park"], | 274 | + ["4", "Philip Chaney", "$38,735", "Korea, South", "Overland Park", '1'], |
275 | - ["5", "Doris Greene", "$63,542", "Malawi", "Feldkirchen in Kärnten"], | 275 | + ["5", "Doris Greene", "$63,542", "Malawi", "Feldkirchen in Kärnten", '1'], |
276 | - ["6", "Mason Porter", "$78,615", "Chile", "Gloucester"] | 276 | + ["6", "Mason Porter", "$78,615", "Chile", "Gloucester", '1'] |
277 | ]; | 277 | ]; |
278 | 278 | ||
279 | // | 279 | // | ... | ... |
1 | import React from "react"; | 1 | import React from "react"; |
2 | -import ChartistGraph from "react-chartist"; | 2 | +import {Grid, Row, Col} from "react-bootstrap"; |
3 | -import {Grid, Row, Col, Table} from "react-bootstrap"; | 3 | + |
4 | -import { Card } from "components/Card/Card.jsx"; | 4 | +import GoogleMapCard from '../components/Kickboard/GoogleMapCard'; |
5 | -import { Tasks } from "components/Tasks/Tasks.jsx"; | 5 | +import KickboardStatusCard from '../components/Kickboard/KickboardStatusCard'; |
6 | -import { | 6 | +import KickboardHistoryTable from '../components/Kickboard/KickboardHistoryTable'; |
7 | - dataBar, | 7 | +import SearchButton from '../components/Kickboard/SearchButton'; |
8 | - optionsBar, | ||
9 | - responsiveBar, | ||
10 | -} from "variables/Variables.jsx"; | ||
11 | -import { thArray, tdArray } from "variables/Variables.jsx"; | ||
12 | 8 | ||
13 | const Kickboard = () => { | 9 | const Kickboard = () => { |
10 | + // 여기 API 요청 | ||
14 | return ( | 11 | return ( |
15 | <div className="content"> | 12 | <div className="content"> |
16 | <Grid fluid> | 13 | <Grid fluid> |
17 | <Row> | 14 | <Row> |
18 | - <Col md={3} mdOffset={9} sm={3} smOffset={9} style={{marginBottom:15}}> | 15 | + <Col md={4} mdOffset={8} sm={3} smOffset={9} style={{marginBottom:15}}> |
19 | - <input type="text" className="form-control" placeholder={"킥보드 번호로 검색하기"}/> | 16 | + <SearchButton/> |
20 | </Col> | 17 | </Col> |
21 | </Row> | 18 | </Row> |
22 | <Row> | 19 | <Row> |
23 | <Col md={6}> | 20 | <Col md={6}> |
24 | - <Card | 21 | + <GoogleMapCard/> |
25 | - id="chartActivity" | ||
26 | - title="2014 Sales" | ||
27 | - category="All products including Taxes" | ||
28 | - stats="마지막 업데이트 2020/04/20 17:23" | ||
29 | - statsIcon="fa fa-check" | ||
30 | - content={ | ||
31 | - <div className="ct-chart"> | ||
32 | - <ChartistGraph | ||
33 | - data={dataBar} | ||
34 | - type="Bar" | ||
35 | - options={optionsBar} | ||
36 | - responsiveOptions={responsiveBar} | ||
37 | - /> | ||
38 | - </div> | ||
39 | - } | ||
40 | - /> | ||
41 | </Col> | 22 | </Col> |
42 | <Col md={6}> | 23 | <Col md={6}> |
43 | - <Card | 24 | + <KickboardStatusCard/> |
44 | - title="Tasks" | ||
45 | - category="Backend development" | ||
46 | - stats="Updated 3 minutes ago" | ||
47 | - statsIcon="fa fa-history" | ||
48 | - content={ | ||
49 | - <div className="table-full-width"> | ||
50 | - <table className="table"> | ||
51 | - <Tasks /> | ||
52 | - </table> | ||
53 | - </div> | ||
54 | - } | ||
55 | - /> | ||
56 | </Col> | 25 | </Col> |
57 | </Row> | 26 | </Row> |
58 | <Row> | 27 | <Row> |
59 | <Col md={12}> | 28 | <Col md={12}> |
60 | - <Card | 29 | + <KickboardHistoryTable/> |
61 | - title="Striped Table with Hover" | ||
62 | - category="Here is a subtitle for this table" | ||
63 | - ctTableFullWidth | ||
64 | - ctTableResponsive | ||
65 | - content={ | ||
66 | - <Table striped> | ||
67 | - <thead> | ||
68 | - <tr> | ||
69 | - {thArray.map((prop, key) => { | ||
70 | - return <th key={key}>{prop}</th>; | ||
71 | - })} | ||
72 | - </tr> | ||
73 | - </thead> | ||
74 | - <tbody> | ||
75 | - {tdArray.map((prop, key) => { | ||
76 | - return ( | ||
77 | - <tr key={key}> | ||
78 | - {prop.map((prop, key) => { | ||
79 | - return <td key={key}>{prop}</td>; | ||
80 | - })} | ||
81 | - </tr> | ||
82 | - ); | ||
83 | - })} | ||
84 | - </tbody> | ||
85 | - </Table> | ||
86 | - } | ||
87 | - /> | ||
88 | </Col> | 30 | </Col> |
89 | </Row> | 31 | </Row> |
90 | </Grid> | 32 | </Grid> | ... | ... |
... | @@ -21,6 +21,11 @@ import { Grid, Row, Col, Alert } from "react-bootstrap"; | ... | @@ -21,6 +21,11 @@ import { Grid, Row, Col, Alert } from "react-bootstrap"; |
21 | import Button from "components/CustomButton/CustomButton.jsx"; | 21 | import Button from "components/CustomButton/CustomButton.jsx"; |
22 | 22 | ||
23 | class Notifications extends Component { | 23 | class Notifications extends Component { |
24 | + constructor(props) { | ||
25 | + super(props); | ||
26 | + console.log(this.props); | ||
27 | + } | ||
28 | + | ||
24 | render() { | 29 | render() { |
25 | return ( | 30 | return ( |
26 | <div className="content"> | 31 | <div className="content"> | ... | ... |
package-lock.json
0 → 100644
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment