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