Showing
16 changed files
with
369 additions
and
11 deletions
... | @@ -13,6 +13,7 @@ | ... | @@ -13,6 +13,7 @@ |
13 | "@testing-library/user-event": "^13.5.0", | 13 | "@testing-library/user-event": "^13.5.0", |
14 | "react": "^18.1.0", | 14 | "react": "^18.1.0", |
15 | "react-dom": "^18.1.0", | 15 | "react-dom": "^18.1.0", |
16 | + "react-router-dom": "^6.3.0", | ||
16 | "react-scripts": "5.0.1", | 17 | "react-scripts": "5.0.1", |
17 | "web-vitals": "^2.1.4" | 18 | "web-vitals": "^2.1.4" |
18 | } | 19 | } |
... | @@ -8061,6 +8062,14 @@ | ... | @@ -8061,6 +8062,14 @@ |
8061 | "he": "bin/he" | 8062 | "he": "bin/he" |
8062 | } | 8063 | } |
8063 | }, | 8064 | }, |
8065 | + "node_modules/history": { | ||
8066 | + "version": "5.3.0", | ||
8067 | + "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", | ||
8068 | + "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", | ||
8069 | + "dependencies": { | ||
8070 | + "@babel/runtime": "^7.7.6" | ||
8071 | + } | ||
8072 | + }, | ||
8064 | "node_modules/hoopy": { | 8073 | "node_modules/hoopy": { |
8065 | "version": "0.1.4", | 8074 | "version": "0.1.4", |
8066 | "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", | 8075 | "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", |
... | @@ -13462,6 +13471,30 @@ | ... | @@ -13462,6 +13471,30 @@ |
13462 | "node": ">=0.10.0" | 13471 | "node": ">=0.10.0" |
13463 | } | 13472 | } |
13464 | }, | 13473 | }, |
13474 | + "node_modules/react-router": { | ||
13475 | + "version": "6.3.0", | ||
13476 | + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", | ||
13477 | + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", | ||
13478 | + "dependencies": { | ||
13479 | + "history": "^5.2.0" | ||
13480 | + }, | ||
13481 | + "peerDependencies": { | ||
13482 | + "react": ">=16.8" | ||
13483 | + } | ||
13484 | + }, | ||
13485 | + "node_modules/react-router-dom": { | ||
13486 | + "version": "6.3.0", | ||
13487 | + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", | ||
13488 | + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", | ||
13489 | + "dependencies": { | ||
13490 | + "history": "^5.2.0", | ||
13491 | + "react-router": "6.3.0" | ||
13492 | + }, | ||
13493 | + "peerDependencies": { | ||
13494 | + "react": ">=16.8", | ||
13495 | + "react-dom": ">=16.8" | ||
13496 | + } | ||
13497 | + }, | ||
13465 | "node_modules/react-scripts": { | 13498 | "node_modules/react-scripts": { |
13466 | "version": "5.0.1", | 13499 | "version": "5.0.1", |
13467 | "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", | 13500 | "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", |
... | @@ -21987,6 +22020,14 @@ | ... | @@ -21987,6 +22020,14 @@ |
21987 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", | 22020 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", |
21988 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" | 22021 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" |
21989 | }, | 22022 | }, |
22023 | + "history": { | ||
22024 | + "version": "5.3.0", | ||
22025 | + "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", | ||
22026 | + "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", | ||
22027 | + "requires": { | ||
22028 | + "@babel/runtime": "^7.7.6" | ||
22029 | + } | ||
22030 | + }, | ||
21990 | "hoopy": { | 22031 | "hoopy": { |
21991 | "version": "0.1.4", | 22032 | "version": "0.1.4", |
21992 | "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", | 22033 | "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", |
... | @@ -25751,6 +25792,23 @@ | ... | @@ -25751,6 +25792,23 @@ |
25751 | "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", | 25792 | "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", |
25752 | "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" | 25793 | "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" |
25753 | }, | 25794 | }, |
25795 | + "react-router": { | ||
25796 | + "version": "6.3.0", | ||
25797 | + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", | ||
25798 | + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", | ||
25799 | + "requires": { | ||
25800 | + "history": "^5.2.0" | ||
25801 | + } | ||
25802 | + }, | ||
25803 | + "react-router-dom": { | ||
25804 | + "version": "6.3.0", | ||
25805 | + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", | ||
25806 | + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", | ||
25807 | + "requires": { | ||
25808 | + "history": "^5.2.0", | ||
25809 | + "react-router": "6.3.0" | ||
25810 | + } | ||
25811 | + }, | ||
25754 | "react-scripts": { | 25812 | "react-scripts": { |
25755 | "version": "5.0.1", | 25813 | "version": "5.0.1", |
25756 | "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", | 25814 | "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", | ... | ... |
... | @@ -8,6 +8,7 @@ | ... | @@ -8,6 +8,7 @@ |
8 | "@testing-library/user-event": "^13.5.0", | 8 | "@testing-library/user-event": "^13.5.0", |
9 | "react": "^18.1.0", | 9 | "react": "^18.1.0", |
10 | "react-dom": "^18.1.0", | 10 | "react-dom": "^18.1.0", |
11 | + "react-router-dom": "^6.3.0", | ||
11 | "react-scripts": "5.0.1", | 12 | "react-scripts": "5.0.1", |
12 | "web-vitals": "^2.1.4" | 13 | "web-vitals": "^2.1.4" |
13 | }, | 14 | }, | ... | ... |
... | @@ -29,15 +29,5 @@ | ... | @@ -29,15 +29,5 @@ |
29 | <body> | 29 | <body> |
30 | <noscript>You need to enable JavaScript to run this app.</noscript> | 30 | <noscript>You need to enable JavaScript to run this app.</noscript> |
31 | <div id="root"></div> | 31 | <div id="root"></div> |
32 | - <!-- | ||
33 | - This HTML file is a template. | ||
34 | - If you open it directly in the browser, you will see an empty page. | ||
35 | - | ||
36 | - You can add webfonts, meta tags, or analytics to this file. | ||
37 | - The build step will place the bundled scripts into the <body> tag. | ||
38 | - | ||
39 | - To begin the development, run `npm start` or `yarn start`. | ||
40 | - To create a production bundle, use `npm run build` or `yarn build`. | ||
41 | - --> | ||
42 | </body> | 32 | </body> |
43 | </html> | 33 | </html> | ... | ... |
1 | import "./styles/App.css"; | 1 | import "./styles/App.css"; |
2 | +import { BrowserRouter, Route, Routes } from "react-router-dom"; | ||
3 | + | ||
4 | +import Calendar from "./pages/Calendar"; | ||
5 | +import Home from "./pages/Home"; | ||
2 | 6 | ||
3 | function App() { | 7 | function App() { |
4 | - return <div className="App"></div>; | 8 | + return ( |
9 | + <BrowserRouter> | ||
10 | + <div className="App"> | ||
11 | + <Routes> | ||
12 | + <Route path="/calendar/*" element={<Calendar />} /> | ||
13 | + <Route exact path="/login" element={<></>} /> | ||
14 | + <Route exact path="/setting" element={<></>} /> | ||
15 | + <Route path="*" element={<Home />} /> | ||
16 | + </Routes> | ||
17 | + </div> | ||
18 | + </BrowserRouter> | ||
19 | + ); | ||
5 | } | 20 | } |
6 | 21 | ||
7 | export default App; | 22 | export default App; | ... | ... |
src/components/Grid.js
0 → 100644
1 | +import "../styles/Grid.css"; | ||
2 | +import GridHead from "./GridHead.js"; | ||
3 | +import GridRow from "./GridRow.js"; | ||
4 | + | ||
5 | +import React from "react"; | ||
6 | + | ||
7 | +const Grid = () => { | ||
8 | + const renderRows = () => { | ||
9 | + const rows = []; | ||
10 | + for (let i = 0; i < 5; i++) { | ||
11 | + rows.push(<GridRow key={i} />); | ||
12 | + } | ||
13 | + return rows; | ||
14 | + }; | ||
15 | + | ||
16 | + return ( | ||
17 | + <div className="Grid"> | ||
18 | + <GridHead /> | ||
19 | + {renderRows()} | ||
20 | + </div> | ||
21 | + ); | ||
22 | +}; | ||
23 | + | ||
24 | +export default Grid; |
src/components/GridHead.js
0 → 100644
1 | +const GridHead = () => { | ||
2 | + const days = ["일", "월", "화", "수", "목", "금", "토"]; | ||
3 | + const renderItems = () => { | ||
4 | + const items = []; | ||
5 | + for (let i = 0; i < 7; i++) { | ||
6 | + items.push( | ||
7 | + <div className="GridHeadItem" key={i}> | ||
8 | + {days[i]} | ||
9 | + </div> | ||
10 | + ); | ||
11 | + } | ||
12 | + return items; | ||
13 | + }; | ||
14 | + | ||
15 | + return <div className="GridHead">{renderItems()}</div>; | ||
16 | +}; | ||
17 | + | ||
18 | +export default GridHead; |
src/components/GridItem.js
0 → 100644
src/components/GridRow.js
0 → 100644
1 | +import GridItem from "./GridItem"; | ||
2 | + | ||
3 | +const GridRow = () => { | ||
4 | + const renderItems = () => { | ||
5 | + const items = []; | ||
6 | + for (let i = 0; i < 7; i++) { | ||
7 | + items.push(<GridItem key={i} />); | ||
8 | + } | ||
9 | + return items; | ||
10 | + }; | ||
11 | + | ||
12 | + return <div className="GridRow">{renderItems()}</div>; | ||
13 | +}; | ||
14 | + | ||
15 | +export default GridRow; |
src/components/Header.js
0 → 100644
1 | +import { useContext } from "react"; | ||
2 | +import { CalendarStateContext } from "../pages/Calendar"; | ||
3 | +import "../styles/Header.css"; | ||
4 | + | ||
5 | +const Header = () => { | ||
6 | + const [state, setState] = useContext(CalendarStateContext); | ||
7 | + | ||
8 | + const handleChangeState = (e) => { | ||
9 | + setState({ | ||
10 | + ...state, | ||
11 | + [e.target.name]: e.target.value, | ||
12 | + }); | ||
13 | + }; | ||
14 | + | ||
15 | + const gotoToday = () => { | ||
16 | + const scope = state.scope; | ||
17 | + const today = new Date(); | ||
18 | + const year = today.getFullYear(); | ||
19 | + const month = today.getMonth() + 1; | ||
20 | + const date = today.getDate(); | ||
21 | + setState({ scope, year, month, date }); | ||
22 | + }; | ||
23 | + | ||
24 | + const move = (e) => { | ||
25 | + const scope = state.scope; | ||
26 | + const current = new Date(state.year, state.month - 1, state.date); | ||
27 | + switch (scope) { | ||
28 | + case "month": | ||
29 | + current.setMonth(current.getMonth() + Number(e.target.value)); | ||
30 | + break; | ||
31 | + case "week": | ||
32 | + current.setDate(current.getDate() + Number(e.target.value) * 7); | ||
33 | + break; | ||
34 | + case "day": | ||
35 | + current.setDate(current.getDate() + Number(e.target.value)); | ||
36 | + break; | ||
37 | + default: | ||
38 | + } | ||
39 | + const year = current.getFullYear(); | ||
40 | + const month = current.getMonth() + 1; | ||
41 | + const date = current.getDate(); | ||
42 | + setState({ scope, year, month, date }); | ||
43 | + }; | ||
44 | + | ||
45 | + let headLabel; | ||
46 | + switch (state.scope) { | ||
47 | + case "month": | ||
48 | + case "week": | ||
49 | + headLabel = state.year + "년 " + state.month + "월"; | ||
50 | + break; | ||
51 | + case "day": | ||
52 | + headLabel = state.year + "년 " + state.month + "월 " + state.date + "일"; | ||
53 | + break; | ||
54 | + default: | ||
55 | + headLabel = "unexpected scope"; | ||
56 | + } | ||
57 | + | ||
58 | + return ( | ||
59 | + <header> | ||
60 | + <div className="hl"> | ||
61 | + <span className="hls">확장 캘린더</span> | ||
62 | + </div> | ||
63 | + <div className="hc"> | ||
64 | + <button className="hcb" onClick={gotoToday}> | ||
65 | + 오늘 | ||
66 | + </button> | ||
67 | + <div className="hcd"> | ||
68 | + <button onClick={move} value={-1}> | ||
69 | + {"ᐸ"} | ||
70 | + </button> | ||
71 | + <button onClick={move} value={+1}> | ||
72 | + {"ᐳ"} | ||
73 | + </button> | ||
74 | + </div> | ||
75 | + <span className="hcs">{headLabel}</span> | ||
76 | + </div> | ||
77 | + <div className="hr"> | ||
78 | + <div className="hrd"> | ||
79 | + <button | ||
80 | + disabled={state.scope === "day"} | ||
81 | + onClick={handleChangeState} | ||
82 | + name="scope" | ||
83 | + value="day" | ||
84 | + > | ||
85 | + 일 | ||
86 | + </button> | ||
87 | + <button | ||
88 | + disabled={state.scope === "week"} | ||
89 | + onClick={handleChangeState} | ||
90 | + name="scope" | ||
91 | + value="week" | ||
92 | + > | ||
93 | + 주 | ||
94 | + </button> | ||
95 | + <button | ||
96 | + disabled={state.scope === "month"} | ||
97 | + onClick={handleChangeState} | ||
98 | + name="scope" | ||
99 | + value="month" | ||
100 | + > | ||
101 | + 월 | ||
102 | + </button> | ||
103 | + </div> | ||
104 | + </div> | ||
105 | + </header> | ||
106 | + ); | ||
107 | +}; | ||
108 | + | ||
109 | +export default Header; |
src/libs/E_Campus.js
0 → 100644
File mode changed
src/pages/Calendar.js
0 → 100644
1 | +import React, { useState } from "react"; | ||
2 | +import { Route, Routes } from "react-router-dom"; | ||
3 | +import Grid from "../components/Grid"; | ||
4 | +import Header from "../components/Header"; | ||
5 | +import "../styles/Home.css"; | ||
6 | + | ||
7 | +export const CalendarStateContext = React.createContext(); | ||
8 | + | ||
9 | +const Calendar = () => { | ||
10 | + const today = new Date(); | ||
11 | + const year = today.getFullYear(); | ||
12 | + const month = today.getMonth() + 1; | ||
13 | + const date = today.getDate(); | ||
14 | + //const day = today.getDay(); | ||
15 | + | ||
16 | + //scope는 day, state는 date | ||
17 | + const [state, setState] = useState({ | ||
18 | + scope: "month", | ||
19 | + year: year, | ||
20 | + month: month, | ||
21 | + date: date, | ||
22 | + }); | ||
23 | + | ||
24 | + return ( | ||
25 | + <CalendarStateContext.Provider value={[state, setState]}> | ||
26 | + <div className="Calendar"> | ||
27 | + <Header /> | ||
28 | + <Routes> | ||
29 | + <Route path="/month/*" element={<Grid />} /> | ||
30 | + <Route path="/week/*" element={<></>} /> | ||
31 | + <Route path="/day/*" element={<></>} /> | ||
32 | + </Routes> | ||
33 | + </div> | ||
34 | + </CalendarStateContext.Provider> | ||
35 | + ); | ||
36 | +}; | ||
37 | + | ||
38 | +export default Calendar; |
src/pages/Home.js
0 → 100644
src/styles/Grid.css
0 → 100644
1 | +.GridItem, | ||
2 | +.GridHeadItem { | ||
3 | + border-style: solid; | ||
4 | + border-width: thin; | ||
5 | + height: 150px; | ||
6 | + flex-basis: 100px; | ||
7 | + flex-grow: 1; | ||
8 | +} | ||
9 | + | ||
10 | +.GridHeadItem { | ||
11 | + height: 30px; | ||
12 | + text-align: center; | ||
13 | + line-height: 30px; | ||
14 | + padding: 10px 5px 10px 5px; | ||
15 | +} | ||
16 | + | ||
17 | +.GridRow, | ||
18 | +.GridHead { | ||
19 | + display: flex; | ||
20 | +} | ||
21 | + | ||
22 | +.Grid { | ||
23 | + display: flex; | ||
24 | + flex-direction: column; | ||
25 | +} |
src/styles/Header.css
0 → 100644
1 | +header { | ||
2 | + background-color: rgba(255, 255, 255, 1); | ||
3 | + display: flex; | ||
4 | + padding: 8px; | ||
5 | + justify-content: space-between; | ||
6 | + align-items: center; | ||
7 | +} | ||
8 | + | ||
9 | +.hl { | ||
10 | + padding-right: 50px; | ||
11 | +} | ||
12 | + | ||
13 | +.hls { | ||
14 | + padding-left: 8px; | ||
15 | + font-size: x-large; | ||
16 | +} | ||
17 | + | ||
18 | +.hc { | ||
19 | + height: 48px; | ||
20 | + align-items: center; | ||
21 | + display: flex; | ||
22 | + justify-content: left; | ||
23 | + flex-grow: 1; | ||
24 | +} | ||
25 | + | ||
26 | +.hcb { | ||
27 | + height: 34px; | ||
28 | + margin: 10px; | ||
29 | +} | ||
30 | + | ||
31 | +.hcd { | ||
32 | + margin: 10px; | ||
33 | +} | ||
34 | + | ||
35 | +.hcd > button { | ||
36 | + font-size: large; | ||
37 | +} | ||
38 | + | ||
39 | +.hcs { | ||
40 | + font-size: x-large; | ||
41 | + margin: 10px; | ||
42 | +} | ||
43 | + | ||
44 | +.hrd > button { | ||
45 | + padding: 8px 14px 8px 14px; | ||
46 | + font-size: medium; | ||
47 | +} |
src/styles/Home.css
0 → 100644
File mode changed
-
Please register or login to post a comment