From 2c88fe76d0e9c06df958b60efcdb02969ed69927 Mon Sep 17 00:00:00 2001 From: grighth12 Date: Tue, 21 Sep 2021 19:03:53 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=204=20the-message=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- index.html | 4 ++ src/App.js | 4 ++ src/components/MessageForm.js | 28 ++++++++++++ src/components/MessagePreveiw.js | 20 +++++++++ src/pages/HomePage.js | 4 ++ src/pages/MessagePage.js | 49 +++++++++++++++++++++ src/styles/app.css | 73 ++++++++++++++++++++++++++++++++ 8 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 src/components/MessageForm.js create mode 100644 src/components/MessagePreveiw.js create mode 100644 src/pages/MessagePage.js diff --git a/.gitignore b/.gitignore index 11b581e..4f2e0cf 100644 --- a/.gitignore +++ b/.gitignore @@ -138,4 +138,5 @@ dist # and uncomment the following lines # .pnp.* -# End of https://www.toptal.com/developers/gitignore/api/node,yarn \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/node,yarn +.vscode/settings.json diff --git a/index.html b/index.html index bcdc7c6..89d349f 100644 --- a/index.html +++ b/index.html @@ -10,5 +10,9 @@
+ diff --git a/src/App.js b/src/App.js index af630de..d25cb99 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,7 @@ import ColorsPage from './pages/ColorsPage.js' import HexColorsGradientPage from './pages/HexColorsGradientPage.js' import HomePage from './pages/HomePage.js' +import MessagePage from './pages/MessagePage.js' import RandomQuotePage from './pages/RandomQuotePage.js' import RouterUtils from './utils/router.js' @@ -10,6 +11,7 @@ export default function App({ $target }) { const colorsPage = new ColorsPage({ $target }) const hexColorsGradientPage = new HexColorsGradientPage({ $target }) const randomQuotePage = new RandomQuotePage({ $target }) + const messagePage = new MessagePage({ $target }) this.route = () => { const { pathname } = location @@ -23,6 +25,8 @@ export default function App({ $target }) { hexColorsGradientPage.render() } else if (pathname === '/random-quote') { randomQuotePage.render() + } else if (pathname == '/the-message') { + messagePage.render() } } diff --git a/src/components/MessageForm.js b/src/components/MessageForm.js new file mode 100644 index 0000000..bc01e48 --- /dev/null +++ b/src/components/MessageForm.js @@ -0,0 +1,28 @@ +export default function MessageForm({ $target, onSubmit }) { + const $form = document.createElement('form') + + $target.appendChild($form) + + this.render = () => { + $form.innerHTML = ` +
+ + +
+ + ` + } + + $form.addEventListener('submit', (e) => { + e.preventDefault() + + const $input = $form.querySelector('.MessageForm__input') + onSubmit($input.value) + + $input.value = '' + }) + + this.render() +} diff --git a/src/components/MessagePreveiw.js b/src/components/MessagePreveiw.js new file mode 100644 index 0000000..66e5a98 --- /dev/null +++ b/src/components/MessagePreveiw.js @@ -0,0 +1,20 @@ +export default function MessagePreview({ $target, initialState }) { + const $preview = document.createElement('div') + $preview.className = 'MessageForm__preview' + + $target.appendChild($preview) + + this.state = initialState + + this.setState = (nextState) => { + this.state = nextState + this.render() + } + + this.render = () => { + $preview.style.display = this.state ? 'block' : 'none' + $preview.textContent = this.state + } + + this.render() +} diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 11e63f4..0ed6afb 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -13,6 +13,10 @@ const projects = [ name: 'Random Quote Generator', path: '/random-quote', }, + { + name: 'The message', + path: '/the-message', + }, ] export default function HomePage({ $target }) { diff --git a/src/pages/MessagePage.js b/src/pages/MessagePage.js new file mode 100644 index 0000000..8232614 --- /dev/null +++ b/src/pages/MessagePage.js @@ -0,0 +1,49 @@ +import MessageForm from '../components/MessageForm.js' +import MessagePreview from '../components/MessagePreveiw.js' +import { appendIfPageNotExists } from '../utils/render.js' + +const TITLE_TEXT = 'Pass the message' +const INFO_TEXT = 'Enter a message' + +export default function MessagePage({ $target }) { + const $page = document.createElement('div') + $page.className = 'Message' + + this.state = { + message: '', + } + + this.setState = (nextState) => { + this.state = nextState + messagePreview.setState(this.state.message) + } + + const $container = document.createElement('div') + $container.className = 'MessageForm' + $container.innerHTML = ` +

${TITLE_TEXT}

+
+

${INFO_TEXT}

+ ` + + new MessageForm({ + $target: $container, + onSubmit: (message) => { + this.setState({ + ...this.state, + message, + }) + }, + }) + + const messagePreview = new MessagePreview({ + $target: $container, + initialState: this.state.message, + }) + + $page.appendChild($container) + + this.render = () => { + appendIfPageNotExists($target, $page) + } +} diff --git a/src/styles/app.css b/src/styles/app.css index 94fdd8b..a7f5a9f 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -176,3 +176,76 @@ border-color: #117a8b; box-shadow: 0 0 0 4px rgba(58, 176, 195, 0.5); } + +/* project 4 */ +.Message { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + background-image: linear-gradient(#c3e0fc, white); +} + +.MessageForm { + display: flex; + flex-direction: column; + width: 80%; + max-width: 480px; + padding: 25px; + background-color: #f5f5f5; + border-radius: 5px; + box-shadow: 0px 2px 5px gray; +} + +.MessageForm__title { + font-size: 18px; + font-weight: 600; + text-align: center; +} + +.MessageForm__divider { + background-color: #d3d3d3; + height: 1px; + margin: 18px 0px; +} + +.MessageForm__info { + font-size: 14px; +} + +.MessageForm__input-area { + width: 100%; + display: flex; + margin: 20px 0px; +} + +.MessageForm__icon-button, +.MessageForm__input, +.MessageForm__submit { + outline: 0; + border: 1px solid #d3d3d3; + padding: 8px; +} + +.MessageForm__icon-button { + border-radius: 5px 0 0 5px; +} + +.MessageForm__icon-button:hover { + background-color: #d3d3d3; +} + +.MessageForm__input { + flex-grow: 1; + border-radius: 0 5px 5px 0; +} + +.MessageForm__preview { + padding: 20px 0px; + text-align: center; +} + +.MessageForm__submit { + border-radius: 5px; +} From d5486ff9feafc3b3d33a6401e6fe3b5df826adaa Mon Sep 17 00:00:00 2001 From: grighth12 Date: Tue, 21 Sep 2021 19:58:52 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=205=20Counter=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GenerateButton -> Button으로 변경 --- src/App.js | 6 +- .../{GenerateButton.js => Button.js} | 6 +- src/components/CountNumber.js | 19 ++++++ src/pages/ColorsPage.js | 2 +- src/pages/CounterPage.js | 66 +++++++++++++++++++ src/pages/HexColorsGradientPage.js | 2 +- src/pages/HomePage.js | 4 ++ src/pages/RandomQuotePage.js | 2 +- src/styles/app.css | 63 ++++++++++++++++++ 9 files changed, 163 insertions(+), 7 deletions(-) rename src/components/{GenerateButton.js => Button.js} (76%) create mode 100644 src/components/CountNumber.js create mode 100644 src/pages/CounterPage.js diff --git a/src/App.js b/src/App.js index d25cb99..6abca55 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,5 @@ import ColorsPage from './pages/ColorsPage.js' +import CounterPage from './pages/CounterPage.js' import HexColorsGradientPage from './pages/HexColorsGradientPage.js' import HomePage from './pages/HomePage.js' import MessagePage from './pages/MessagePage.js' @@ -12,6 +13,7 @@ export default function App({ $target }) { const hexColorsGradientPage = new HexColorsGradientPage({ $target }) const randomQuotePage = new RandomQuotePage({ $target }) const messagePage = new MessagePage({ $target }) + const counterPage = new CounterPage({ $target }) this.route = () => { const { pathname } = location @@ -25,8 +27,10 @@ export default function App({ $target }) { hexColorsGradientPage.render() } else if (pathname === '/random-quote') { randomQuotePage.render() - } else if (pathname == '/the-message') { + } else if (pathname === '/the-message') { messagePage.render() + } else if (pathname === '/counter') { + counterPage.render() } } diff --git a/src/components/GenerateButton.js b/src/components/Button.js similarity index 76% rename from src/components/GenerateButton.js rename to src/components/Button.js index 87a94fb..f427965 100644 --- a/src/components/GenerateButton.js +++ b/src/components/Button.js @@ -1,8 +1,8 @@ -export default function GenerateButton({ +export default function Button({ $target, text = 'Click Me!', className, - onClickGenerate, + onClick, }) { const $button = document.createElement('button') $button.className = `GenerateButton ${className}` @@ -10,6 +10,6 @@ export default function GenerateButton({ $target.appendChild($button) $button.addEventListener('click', () => { - onClickGenerate() + onClick() }) } diff --git a/src/components/CountNumber.js b/src/components/CountNumber.js new file mode 100644 index 0000000..597be12 --- /dev/null +++ b/src/components/CountNumber.js @@ -0,0 +1,19 @@ +export default function CountNumber({ $target, initialState }) { + const $number = document.createElement('div') + $number.className = 'Counter__number' + + $target.appendChild($number) + + this.state = initialState + + this.setState = (nextState) => { + this.state = nextState + this.render() + } + + this.render = () => { + $number.textContent = this.state + } + + this.render() +} diff --git a/src/pages/ColorsPage.js b/src/pages/ColorsPage.js index 5a039c0..8fbcc5e 100644 --- a/src/pages/ColorsPage.js +++ b/src/pages/ColorsPage.js @@ -1,4 +1,4 @@ -import RandomColorButton from '../components/GenerateButton.js' +import RandomColorButton from '../components/Button.js' import { getRandomColor } from '../utils/colors.js' import { appendIfPageNotExists } from '../utils/render.js' diff --git a/src/pages/CounterPage.js b/src/pages/CounterPage.js new file mode 100644 index 0000000..d415df2 --- /dev/null +++ b/src/pages/CounterPage.js @@ -0,0 +1,66 @@ +import Button from '../components/Button.js' +import CountNumber from '../components/CountNumber.js' +import { appendIfPageNotExists } from '../utils/render.js' + +const TITLE_TEXT = 'COUNTER' + +export default function CounterPage({ $target }) { + const $page = document.createElement('div') + $page.className = 'Counter' + + this.state = { + number: 0, + } + + this.setState = (nextState) => { + this.state = nextState + countNumber.setState(this.state.number) + } + + const $container = document.createElement('div') + $container.className = 'CounterContainer' + $container.innerHTML = ` +

${TITLE_TEXT}

+ ` + + const countNumber = new CountNumber({ + $target: $container, + initialState: this.state.number, + }) + + const $buttons = document.createElement('div') + $buttons.className = 'Counter__buttons' + $container.appendChild($buttons) + + new Button({ + $target: $buttons, + text: 'Increase', + className: 'Counter__button', + onClick: () => { + const number = this.state.number + 1 + this.setState({ + ...this.state, + number, + }) + }, + }) + + new Button({ + $target: $buttons, + text: 'Decrease', + className: 'Counter__button', + onClick: () => { + const number = this.state.number - 1 + this.setState({ + ...this.state, + number, + }) + }, + }) + + $page.appendChild($container) + + this.render = () => { + appendIfPageNotExists($target, $page) + } +} diff --git a/src/pages/HexColorsGradientPage.js b/src/pages/HexColorsGradientPage.js index 72adacb..3486229 100644 --- a/src/pages/HexColorsGradientPage.js +++ b/src/pages/HexColorsGradientPage.js @@ -1,4 +1,4 @@ -import GenerateButton from '../components/GenerateButton.js' +import GenerateButton from '../components/Button.js' import { getRandomColor } from '../utils/colors.js' import { appendIfPageNotExists } from '../utils/render.js' diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 0ed6afb..9805a5d 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -17,6 +17,10 @@ const projects = [ name: 'The message', path: '/the-message', }, + { + name: 'Counter', + path: '/counter', + }, ] export default function HomePage({ $target }) { diff --git a/src/pages/RandomQuotePage.js b/src/pages/RandomQuotePage.js index a7e96b9..b21cbbc 100644 --- a/src/pages/RandomQuotePage.js +++ b/src/pages/RandomQuotePage.js @@ -1,4 +1,4 @@ -import GenerateButton from '../components/GenerateButton.js' +import GenerateButton from '../components/Button.js' import { fetchQuote } from '../service/quoteApi.js' import { appendIfPageNotExists } from '../utils/render.js' diff --git a/src/styles/app.css b/src/styles/app.css index a7f5a9f..9d6c85b 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -249,3 +249,66 @@ .MessageForm__submit { border-radius: 5px; } + +/* * project 5 */ +.Counter { + --page-bg-color: #fcfc62; + --btn-color: #feffea; + --btn-hover-color: #343a40; + --btn-box-shadow: rgba(52, 58, 64, 0.5) 0px 0px 0px 3.2px; +} + +.Counter { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + background-color: var(--page-bg-color); +} + +.CounterContainer { + width: 600px; + padding: 40px 0px; + background-color: var(--btn-color); + border: 4px solid; + border-radius: 5px; +} + +.Counter__title { + text-align: center; + font-size: 32px; +} + +.Counter__number { + font-size: 138px; + font-weight: 600; + text-align: center; + margin-top: 35px; +} + +.Counter__buttons { + display: flex; + justify-content: center; + margin-top: 28px; +} + +.Counter__button { + color: var(--btn-hover-color); + background-color: var(--btn-color); + margin-right: 6px; + padding: 6px 12px; +} + +.Counter__button:last-child { + margin-right: 0; +} + +.Counter__button:hover { + color: var(--btn-color); + background-color: var(--btn-hover-color); +} + +.Counter__button:focus { + box-shadow: var(--btn-box-shadow); +} From 9c0ee56b02f8e6220ba8f49c5d6fd286f690b828 Mon Sep 17 00:00:00 2001 From: grighth12 Date: Tue, 21 Sep 2021 23:33:24 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=206=20Image=20Carousel=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 4 ++ src/components/Button.js | 2 +- src/components/ImageCarousel.js | 53 +++++++++++++++++ src/components/Indicators.js | 26 +++++++++ src/pages/CarouselPage.js | 100 ++++++++++++++++++++++++++++++++ src/pages/HomePage.js | 4 ++ src/styles/app.css | 82 ++++++++++++++++++++++++++ 7 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 src/components/ImageCarousel.js create mode 100644 src/components/Indicators.js create mode 100644 src/pages/CarouselPage.js diff --git a/src/App.js b/src/App.js index 6abca55..f02a561 100644 --- a/src/App.js +++ b/src/App.js @@ -1,3 +1,4 @@ +import CarouselPage from './pages/CarouselPage.js' import ColorsPage from './pages/ColorsPage.js' import CounterPage from './pages/CounterPage.js' import HexColorsGradientPage from './pages/HexColorsGradientPage.js' @@ -14,6 +15,7 @@ export default function App({ $target }) { const randomQuotePage = new RandomQuotePage({ $target }) const messagePage = new MessagePage({ $target }) const counterPage = new CounterPage({ $target }) + const carouselPage = new CarouselPage({ $target }) this.route = () => { const { pathname } = location @@ -31,6 +33,8 @@ export default function App({ $target }) { messagePage.render() } else if (pathname === '/counter') { counterPage.render() + } else if (pathname === '/image-carousel') { + carouselPage.render() } } diff --git a/src/components/Button.js b/src/components/Button.js index f427965..b94db27 100644 --- a/src/components/Button.js +++ b/src/components/Button.js @@ -6,7 +6,7 @@ export default function Button({ }) { const $button = document.createElement('button') $button.className = `GenerateButton ${className}` - $button.textContent = text + $button.innerHTML = text $target.appendChild($button) $button.addEventListener('click', () => { diff --git a/src/components/ImageCarousel.js b/src/components/ImageCarousel.js new file mode 100644 index 0000000..173ef7c --- /dev/null +++ b/src/components/ImageCarousel.js @@ -0,0 +1,53 @@ +import Button from './Button.js' + +export default function ImageCarousel({ + $target, + initialState, + onClickNext, + onClickPrev, +}) { + const $imageCarousel = document.createElement('div') + $imageCarousel.className = 'ImageCarousel' + + this.state = initialState + + $target.appendChild($imageCarousel) + + const $image = document.createElement('img') + $image.className = 'ImageCarousel__image' + + const $buttons = document.createElement('div') + $buttons.className = 'ImageCarousel__buttons' + + new Button({ + $target: $buttons, + text: '', + className: 'ImageCarousel__button', + onClick: onClickPrev, + }) + + new Button({ + $target: $buttons, + text: '', + className: 'ImageCarousel__button', + onClick: onClickNext, + }) + + this.setState = (nextState) => { + this.state = nextState + this.render() + } + + this.render = () => { + $imageCarousel.innerHTML = '' + + const { src, name } = this.state.image + $image.src = src + $image.alt = name + + $imageCarousel.appendChild($image) + $imageCarousel.appendChild($buttons) + } + + this.render() +} diff --git a/src/components/Indicators.js b/src/components/Indicators.js new file mode 100644 index 0000000..a5af2f3 --- /dev/null +++ b/src/components/Indicators.js @@ -0,0 +1,26 @@ +export default function Indicators({ $target, initialState, length }) { + const $indicators = document.createElement('div') + $indicators.className = 'Carousel__indicators' + $target.appendChild($indicators) + + this.state = initialState + + this.setState = (nextState) => { + this.state = nextState + this.render() + } + + this.render = () => { + const indicatorDots = Array.from(new Array(length), (_) => _) + .map( + (_, index) => ``, + ) + .join('') + $indicators.innerHTML = indicatorDots + } + + this.render() +} diff --git a/src/pages/CarouselPage.js b/src/pages/CarouselPage.js new file mode 100644 index 0000000..73ca040 --- /dev/null +++ b/src/pages/CarouselPage.js @@ -0,0 +1,100 @@ +import { appendIfPageNotExists } from '../utils/render.js' +import ImageCarousel from '../components/ImageCarousel.js' +import Indicators from '../components/Indicators.js' + +const images = [ + { + name: 'Lam0', + src: 'https://iamcodefoxx.github.io/ImageCarousel/Lam0.jpg', + }, + { + name: 'Lam1', + src: 'https://iamcodefoxx.github.io/ImageCarousel/Lam1.jpg', + }, + { + name: 'Lam2', + src: 'https://iamcodefoxx.github.io/ImageCarousel/Lam2.jpg', + }, + { + name: 'Lam3', + src: 'https://iamcodefoxx.github.io/ImageCarousel/Lam3.jpg', + }, + { + name: 'Lam4', + src: 'https://iamcodefoxx.github.io/ImageCarousel/Lam4.jpg', + }, + { + name: 'Lam5', + src: 'https://iamcodefoxx.github.io/ImageCarousel/Lam5.jpg', + }, + { + name: 'Lam5', + src: 'https://iamcodefoxx.github.io/ImageCarousel/Lam6.jpg', + }, + { + name: 'Lam7', + src: 'https://iamcodefoxx.github.io/ImageCarousel/Lam7.jpg', + }, +] + +const IMAGES_LENGTH = images.length + +export default function CarouselPage({ $target }) { + const $page = document.createElement('div') + $page.className = 'CarouselPage' + + this.state = { + index: 0, + } + + const imageCarousel = new ImageCarousel({ + $target: $page, + initialState: { + index: this.state.index, + image: images[this.state.index], + }, + onClickNext: () => { + const index = (this.state.index + 1) % IMAGES_LENGTH + + this.setState({ + ...this.state, + index, + }) + }, + onClickPrev: () => { + const index = + this.state.index - 1 < 0 ? IMAGES_LENGTH - 1 : this.state.index - 1 + + this.setState({ + ...this.state, + index, + }) + }, + }) + + const indicators = new Indicators({ + $target: $page, + initialState: { + index: this.state.index, + }, + length: IMAGES_LENGTH, + }) + + this.setState = (nextState) => { + this.state = nextState + const { index } = this.state + + imageCarousel.setState({ + index, + image: images[index], + }) + + indicators.setState({ + index, + }) + } + + this.render = () => { + appendIfPageNotExists($target, $page) + } +} diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 9805a5d..b9077bd 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -21,6 +21,10 @@ const projects = [ name: 'Counter', path: '/counter', }, + { + name: 'Image Carousel', + path: '/image-carousel', + }, ] export default function HomePage({ $target }) { diff --git a/src/styles/app.css b/src/styles/app.css index 9d6c85b..21a78ee 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -312,3 +312,85 @@ .Counter__button:focus { box-shadow: var(--btn-box-shadow); } + +/* Project 6 */ +@keyframes fadeIn { + from { + opacity: 0%; + } + to { + opacity: 100%; + } +} + +@media (max-width: 768px) { + .ImageCarousel { + position: relative; + width: 98%; + } +} + +@media (min-width: 768px) { + .ImageCarousel { + position: relative; + width: 70%; + } +} + +.CarouselPage { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.ImageCarousel__image { + width: 100%; + animation: fadeIn 0.8s ease-in; +} + +.ImageCarousel__buttons { + position: absolute; + top: 50%; + width: 100%; + display: flex; + justify-content: space-between; + transform: translateY(-50%); +} + +.ImageCarousel__button { + color: white; + background: transparent; + border-radius: 0px; + border: 0; +} + +.ImageCarousel__button:hover { + background-color: black; + opacity: 0.5; +} + +.ImageCarousel__button i { + pointer-events: none; +} +.Carousel__indicators { + display: flex; + margin-top: 10px; +} +.Carousel__indicator-dot { + width: 10px; + height: 10px; + background-color: gray; + border-radius: 50%; + margin-right: 8px; +} + +.Carousel__indicator-dot:last-child { + margin-right: 0px; +} + +.Carousel__indicator-dot--selected { + background-color: black; +} From bad742b7c1c96d8a18c7ef146ab85b4de07ce867 Mon Sep 17 00:00:00 2001 From: grighth12 Date: Wed, 22 Sep 2021 01:11:07 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20Digital=20clock=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 4 +++ src/pages/DigitalClockPage.js | 51 +++++++++++++++++++++++++++++++++++ src/pages/HomePage.js | 4 +++ src/styles/app.css | 48 ++++++++++++++++++++++++++++++++- src/utils/date.js | 1 + 5 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/pages/DigitalClockPage.js create mode 100644 src/utils/date.js diff --git a/src/App.js b/src/App.js index f02a561..98c734c 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,7 @@ import CarouselPage from './pages/CarouselPage.js' import ColorsPage from './pages/ColorsPage.js' import CounterPage from './pages/CounterPage.js' +import DigitalClockPage from './pages/DigitalClockPage.js' import HexColorsGradientPage from './pages/HexColorsGradientPage.js' import HomePage from './pages/HomePage.js' import MessagePage from './pages/MessagePage.js' @@ -16,6 +17,7 @@ export default function App({ $target }) { const messagePage = new MessagePage({ $target }) const counterPage = new CounterPage({ $target }) const carouselPage = new CarouselPage({ $target }) + const digitalClockPage = new DigitalClockPage({ $target }) this.route = () => { const { pathname } = location @@ -35,6 +37,8 @@ export default function App({ $target }) { counterPage.render() } else if (pathname === '/image-carousel') { carouselPage.render() + } else if (pathname === '/digital-clock') { + digitalClockPage.render() } } diff --git a/src/pages/DigitalClockPage.js b/src/pages/DigitalClockPage.js new file mode 100644 index 0000000..865a460 --- /dev/null +++ b/src/pages/DigitalClockPage.js @@ -0,0 +1,51 @@ +import { appendIfPageNotExists } from '../utils/render.js' +import { padDateNumber } from '../utils/date.js' + +const weekdays = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'] + +export default function DigitalClockPage({ $target }) { + const $page = document.createElement('div') + $page.className = 'DigitalClock' + + this.state = { + interval: null, + } + + const $clock = document.createElement('div') + $clock.className = 'Clock' + + $page.appendChild($clock) + + this.render = () => { + appendIfPageNotExists($target, $page) + + this.state.interval = setInterval(() => { + const today = new Date() + const time = ` +
+ ${weekdays[today.getDay()]} +
+
+ ${padDateNumber(today.getHours() === 0 ? 12 : today.getHours())} +
+
:
+
+ ${padDateNumber(today.getHours())} +
+
:
+
+ ${padDateNumber(today.getSeconds())} +
+
+ ${today.getHours() >= 12 ? 'PM' : 'AM'} +
+ ` + + $clock.innerHTML = time + }, 1000) + } + + window.addEventListener('popstate', () => { + clearInterval(this.state.interval) + }) +} diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index b9077bd..a773667 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -25,6 +25,10 @@ const projects = [ name: 'Image Carousel', path: '/image-carousel', }, + { + name: 'Digital Clock', + path: '/digital-clock', + }, ] export default function HomePage({ $target }) { diff --git a/src/styles/app.css b/src/styles/app.css index 21a78ee..730bd16 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css2?family=Noto+Sans&family=Dancing+Script&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans&family=Dancing+Script&family=Poiret+One&display=swap'); @keyframes changeColor { 0% { @@ -394,3 +394,49 @@ .Carousel__indicator-dot--selected { background-color: black; } + +/* * project 7 */ +@media (max-width: 768px) { + .Clock__bar { + display: none; + } + + .Clock__number { + width: 100%; + } +} + +.DigitalClock { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + background-image: conic-gradient( + from 90deg at 25% -10%, + #ff4500, + #d3f340, + #7bee85, + #afeeee, + #7bee85 + ); +} + +.Clock { + display: flex; + justify-content: center; + flex-wrap: wrap; + width: 80%; + padding: 20px 0px; + background-color: rgba(0, 0, 0, 0.09); + color: white; + font-family: 'Poiret One'; + font-size: 5rem; + font-weight: 600; + text-align: center; +} + +.Clock * { + margin: 0 10px; + padding: 10px 0px; +} diff --git a/src/utils/date.js b/src/utils/date.js new file mode 100644 index 0000000..2e2b1d8 --- /dev/null +++ b/src/utils/date.js @@ -0,0 +1 @@ +export const padDateNumber = (number) => (number < 10 ? `0${number}` : number) From a3b6c6721a57ddf607503818153717c9d783f4d6 Mon Sep 17 00:00:00 2001 From: grighth12 Date: Wed, 22 Sep 2021 01:18:42 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20onClickGenerate=20->=20onClick?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20Button=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ColorsPage.js | 2 +- src/pages/HexColorsGradientPage.js | 2 +- src/pages/RandomQuotePage.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/ColorsPage.js b/src/pages/ColorsPage.js index 8fbcc5e..441b4d9 100644 --- a/src/pages/ColorsPage.js +++ b/src/pages/ColorsPage.js @@ -19,7 +19,7 @@ export default function ColorsPage({ $target }) { $target: $page, text: 'Click Me!', className: 'RandomColorButton', - onClickGenerate: () => { + onClick: () => { const color = getRandomColor() this.setState({ color }) diff --git a/src/pages/HexColorsGradientPage.js b/src/pages/HexColorsGradientPage.js index 3486229..027d315 100644 --- a/src/pages/HexColorsGradientPage.js +++ b/src/pages/HexColorsGradientPage.js @@ -36,7 +36,7 @@ export default function HexColorsGradientPage({ $target }) { $target: $page, text: 'Click Me!', className: 'RandomGradientButton', - onClickGenerate: () => { + onClick: () => { const leftColor = getRandomColor() const rightColor = getRandomColor() diff --git a/src/pages/RandomQuotePage.js b/src/pages/RandomQuotePage.js index b21cbbc..cba0073 100644 --- a/src/pages/RandomQuotePage.js +++ b/src/pages/RandomQuotePage.js @@ -14,7 +14,7 @@ export default function RandomQuotePage({ $target }) { $target: $page, text: 'Generate Quote', className: 'RandomQuote__button', - onClickGenerate: async () => { + onClick: async () => { if (this.state.isLoading) { return }