diff --git a/README.md b/README.md index 6044e1d4..9d1ae3f6 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,73 @@ -# Team6-AwesomeOrange +# ๐ŸŠ Team6-AwesomeOrange > ๋ฐฑ์—”๋“œ ๋ ˆํฌ๋Š” ์—ฌ๊ธฐ๋กœ! => [๋ฐฑ์—”๋“œ ๋ ˆํฌ](https://github.com/softeerbootcamp4th/Team6-AwesomeOrange-BE) -## Contributors +## ๐ŸŽ‰ Project Introduction +![thumbnails](https://github.com/user-attachments/assets/7fd7c6a4-198a-40eb-bd9a-2bff653199f3) + +**๐Ÿ•น๏ธ ๋ฐ๋ชจ** : https://softeer-awesome-orange.vercel.app/ + +**๐ŸŽฌ ์‹œ์—ฐ์˜์ƒ** : https://www.youtube.com/watch?v=OfGelpl1vD8 + +### ๐Ÿš— ์ธํ„ฐ๋ž™์…˜๊ณผ ํ•จ๊ป˜, The ์ƒˆ๋กœ์›Œ์ง„ IONIQ 5๋ฅผ ๋งŒ๋‚˜๋‹ค. +์ด ํ”„๋กœ์ ํŠธ๋Š” **The new IONIQ 5 ์ถœ์‹œ ๊ธฐ๋… ์ด๋ฒคํŠธ๋ฅผ ์ปจ์…‰์œผ๋กœ, ๋‹ค์–‘ํ•œ ์ธํ„ฐ๋ž™์…˜์„ ํ†ตํ•ด IONIQ 5์˜ ๊ธฐ๋Šฅ์„ ์นœ์ˆ™ํ•˜๊ณ  ๋ช…๋ฃŒํ•˜๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ์ด๋ฒคํŠธ ํŽ˜์ด์ง€**์ž…๋‹ˆ๋‹ค. +ํ”„๋กœ์ ํŠธ๋Š” IONIQ 5์˜ ๊ธฐ์ˆ ์  ๊ฒฝ์Ÿ๋ ฅ์„ ๊ฐ•์กฐํ•˜๋ฉด์„œ๋„, ๋”ฑ๋”ฑํ•œ ์ •๋ณด๋ฅผ ์นœ์ˆ™ํ•˜๊ฒŒ ์ œ๊ณตํ•˜๊ณ ์ž, IONIQ 5์˜ ๊ธฐ๋Šฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ธํ„ฐ๋ž™์…˜ ์ฝ˜ํ…์ธ ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ์š” ์„ฑ๋Šฅ์„ ์ง๊ฐ„์ ‘์ ์œผ๋กœ ์ฒดํ—˜ํ•˜๋„๋ก ๊ตฌ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ๋Š” ์ด๋ฒคํŠธ ๊ธฐ๊ฐ„ ๋™์•ˆ ์ง€์†์ ์ธ ํŠธ๋ž˜ํ”ฝ์„ ์œ ๋„ํ•˜๊ณ ์ž, ๋ˆ„๊ตฌ๋‚˜ ๋ถ€๋‹ด์—†์ด ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ๋Š” ์นด๋“œ ๋’ค์ง‘๊ธฐ ๋ฐฉ์‹์„ ์ฑ„์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ, ์ด๋ฒคํŠธ ํŽ˜์ด์ง€์ด๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์ด๋ฒคํŠธ ํŽ˜์ด์ง€๋กœ ์œ ์ž…ํ•˜๊ณ , ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋ฏ€๋กœ, **SSG๋ฅผ ๋„์ž…**ํ•˜์—ฌ ๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™”(SEO)๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰ ์—”์ง„์— ์ €ํฌ ์‚ฌ์ดํŠธ๊ฐ€ ์‰ฝ๊ฒŒ ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ–ˆ์œผ๋ฉฐ, ๋ชจ๋ฐ”์ผ ์‚ฌ์šฉ์ž๋ฅผ ๋ฐฐ๋ คํ•œ **๋ฐ˜์‘ํ˜• ์›น ๋ฐ ํ„ฐ์น˜ ์ธํ„ฐ๋ž™์…˜**, ์‹œ๊ฐ์žฅ์• ์ธ์„ ๋ฐฐ๋ คํ•œ **ํ‚ค๋ณด๋“œ ์ธํ„ฐ๋ž™์…˜ ์กฐ์ž‘ ๋ฐ `aria-live="assertive"`๋ฅผ ์ด์šฉํ•œ ์ ์ ˆํ•œ ์Œ์„ฑ ์ž๋ง‰ ํ”ผ๋“œ๋ฐฑ**์œผ๋กœ ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์˜ ์‚ฌ๋žŒ๋“ค์ด ์ด๋ฒคํŠธ์— ๋ถ€๋‹ด์—†์ด ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค. + +### โœจ Features +- ๐ŸŽฎ **IONIQ 5๋ฅผ ์ƒ์ง•ํ•˜๋Š” 5๊ฐœ์˜ ์ธํ„ฐ๋ž™์…˜ ์ œ๊ณต** + - ์ฃผํ–‰๊ฑฐ๋ฆฌ ์ธํ„ฐ๋ž™์…˜ - ์  ๋“œ๋ž˜๊ทธ๋ฅผ ํ†ตํ•œ ๊ฑฐ๋ฆฌ ์˜ˆ์ธก + - ๊ณ ์†์ถฉ์ „ ์ธํ„ฐ๋ž™์…˜ - ๋‹ค์ด์–ผ ๋“œ๋ž˜๊ทธ ํšŒ์ „์„ ํ†ตํ•œ ์ถฉ์ „ ์‹œ๊ฐ„ ์˜ˆ์ธก + - ์œ ๋‹ˆ๋ฒ„์„ค ์•„์ผ๋žœ๋“œ ์ธํ„ฐ๋ž™์…˜ - ์˜ค๋ธŒ์ ํŠธ 2๊ฐœ ๋“œ๋ž˜๊ทธ, ์˜ค๋ธŒ์ ํŠธ ์Šค๋‚ดํ•‘์„ ํ†ตํ•œ ๋ฌด์„ ์ถฉ์ „ ๊ธฐ๋Šฅ ํ™๋ณด + - V2L ์ธํ„ฐ๋ž™์…˜ - ๊ธธ์ž‡๊ธฐ ์—ฐ๊ฒฐ ํผ์ฆ + - ๋ฆฌ์…‹ํ•  ๋•Œ๋งˆ๋‹ค ๋žœ๋คํ•œ ํผ์ฆ ์ œ๊ณต + - ๋ณด์กฐ๊ธˆ ์ธํ„ฐ๋ž™์…˜ - ์นด์šดํŠธ์™€ ๋กœํ‹ฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ + - ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ ์ง€์› + - ์‹œ๊ฐ์žฅ์• ์ธ๋„ ์ด๋ฒคํŠธ์— ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ‚ค๋ณด๋“œ ์กฐ์ž‘ ์ง€์›, ์ธํ„ฐ๋ž™์…˜ ์‹œ ์ž๋ง‰ ์ œ๊ณต + - ์˜คํ”„๋ผ์ธ ํด๋ฐฑ ๋ชจ๋“œ ์ง€์› +- ๐Ÿƒ **์นด๋“œ ๋’ค์ง‘๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•œ ์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ** + - ๋‹ค์Œ ์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ ์‹ค์‹œ๊ฐ„ ์นด์šดํŠธ + - ๋Š๋ฆฐ ๋„คํŠธ์›Œํฌ ํ™˜๊ฒฝ์„ ์œ„ํ•ด ์ž์—ฐ์Šค๋Ÿฌ์šด ์นด๋“œ ๋กœ๋”ฉ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€ + - ์˜คํ”„๋ผ์ธ ํด๋ฐฑ ๋ชจ๋“œ ์ง€์› +- ๐ŸŽ  **์Šค์™€์ดํ•‘ ๊ฐ€๋Šฅํ•œ ๊ธฐ๋Œ€ํ‰ ์บ๋Ÿฌ์…€** + +## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Contributors | [@lybell-art](https://github.com/lybell-art) | [@darkdulgi](https://github.com/darkdulgi) | [@blaxsior](https://github.com/blaxsior) | [@win-luck](https://github.com/win-luck) | |:---------------------------------------------------------:|:-------------------------------------------------------:|:-------------------------------------------------------:|:-----------------------------------------------------------------:| -| | | | | +| | | | | | **Front-End** | **Front-End** | **Back-End** | **Back-End** | +## ๐Ÿค Collaborations +### ๐ŸŒฑ Ground Rule +> - ์„œ๋กœ ๊ฐ์ž๋ฅผ ์ดํ•ดํ•˜๊ณ  ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค ์šด์˜์„ ํ†ตํ•ด ๋งŒ์กฑ์Šค๋Ÿฌ์šด ๊ฒฐ๊ณผ๋ฌผ ๋งŒ๋“ค๊ธฐ +> - ์„œ๋กœ์˜ ์˜๊ฒฌ์„ ์กด์ค‘ํ•˜๋ฉฐ ํ™”๋ชฉํ•˜๊ณ  ๊ธฐ์–ต์— ๋‚จ์„ ๋งŒํ•œ ํŒ€ ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ํ•˜๊ธฐ +> - ๊ฐœ๋ฐœ ์ธก๋ฉด์—์„œ, "์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์‹œ์Šคํ…œ" ๊ตฌ์ถ•ํ•˜๊ธฐ +> - ๋ชจ๋ฅด๊ฑฐ๋‚˜ ๋ง‰ํžˆ๋Š” ๊ฒƒ์ด ์žˆ์œผ๋ฉด, ์ฆ‰์‹œ ์ƒ๋Œ€๋ฐฉ ๋ถ€๋ฅด๊ธฐ -## Ground Rule [Ground Rule](https://github.com/softeerbootcamp4th/Team6-AwesomeOrange-BE/wiki/%5BGround-Rule%5D) -## Convention +### ๐Ÿ“‡ Convention +> - ๋งค์ผ ์˜ค์ „ 10์‹œ์— ๋ฐ์ผ๋ฆฌ ์Šคํฌ๋Ÿผ์„ ์ง„ํ–‰ํ•˜๊ณ , ๋งค์ผ ์˜คํ›„ 6์‹œ 30๋ถ„์— ์ผ๊ฐ„ ํšŒ๊ณ ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค. +> - ๋ฐฑ๋กœ๊ทธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ, ๊ฐ์ž ์ˆ˜ํ–‰ํ•  ํƒœ์Šคํฌ๋ฅผ ๋ฐํ˜€ ๊ธฐ๋Šฅ์˜ ์ถฉ๋Œ์„ ๋ง‰๋Š”๋‹ค. +> - ํฌ๋ฆฌํ‹ฐ์ปฌํ•œ ๋ณ€๊ฒฝ์ด ์žˆ์„ ๊ฒฝ์šฐ, ํŒ€์›๊ณผ ์ถฉ๋ถ„ํžˆ ์˜๋…ผํ•˜๊ณ  ๊ฐ™์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. +> - ํ”ผ์ฒ˜ ๊ธฐ๋ฐ˜์œผ๋กœ ์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, `[feat] ํ”ผ์ฒ˜ ๋‚ด์šฉ`๊ณผ ๊ฐ™์ด ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋ฅผ ์ž‘์„ฑํ•œ๋‹ค. +> - ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ฝ”๋“œ ๋ฆฌ๋ทฐ๊ฐ€ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์œผ๋ฉด ๋จธ์ง€๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. + [Convention](https://github.com/softeerbootcamp4th/Team6-AwesomeOrange-BE/wiki/%08%5BTeam-Convention%5D) -## Plan & Design Link +## ๐ŸŽจ Plan & Design Link [Plan & Design Link(Figma)](https://www.figma.com/design/XieJv765qFmU9dFuQAG7tQ/%EC%96%B4%EC%8D%B8%EC%98%A4%EB%A0%8C%EC%A7%80_Hand-off_%EC%B5%9C%EC%A2%85(07%2F24)?node-id=33-1157) -## Schedule +## ๐Ÿ“… Schedule **Front-End** -| 1์ฃผ์ฐจ | ๊ณตํ†ต ์ปค์Šคํ…€ ํ›… ๋ฐ ์ธํ„ฐ๋ž™์…˜ ์ธํ„ฐํŽ˜์ด์Šค ์ถ”๊ฐ€, ๋ฉ”์ธ ํŽ˜์ด์ง€์˜ ์ธํŠธ๋กœ, ํ—ค๋”, ์ฐจ๋Ÿ‰ ๊ธฐ๋ณธ์ •๋ณด, QnA, ํ‘ธํ„ฐ ๊ตฌํ˜„ | -| --- | --- | -| 2์ฃผ์ฐจ | ์ธํ„ฐ๋ž™์…˜ ํŽ˜์ด์ง€, ์ธํ„ฐ๋ž™์…˜ ๋ชจ๋‹ฌ, ๊ฐ๊ฐ์˜ ์ธํ„ฐ๋ž™์…˜ ๊ตฌํ˜„ | -| 3์ฃผ์ฐจ | ๊ฐ๊ฐ์˜ ์ธํ„ฐ๋ž™์…˜ ๊ตฌํ˜„, ๊ธฐ๋Œ€ํ‰ ๊ตฌํ˜„ | -| 4์ฃผ์ฐจ | ์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ ๊ตฌํ˜„, ์‹œ๊ฐ„ ๋‚จ์„ ์‹œ ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€(๋กœ๊ทธ์ธ, ์ด๋ฒคํŠธ๋ชฉ๋ก) ๊ตฌํ˜„ | -| 5์ฃผ์ฐจ | ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€(์ด๋ฒคํŠธ ๋“ฑ๋ก์ˆ˜์ •, ์ด๋ฒคํŠธ ๊ด€๋ฆฌ, ๊ธฐ๋Œ€ํ‰ ๊ด€๋ฆฌ) ๊ตฌํ˜„ ๋ฐ ๋ฆฌํŒฉํ† ๋ง, ๋ฐœํ‘œ์ž๋ฃŒ ์ œ์ž‘ | +| ์ฃผ์ฐจ | [@lybell-art](https://github.com/lybell-art) | [@darkdulgi](https://github.com/darkdulgi) | +| --- | --- | --- | +| 1์ฃผ์ฐจ | ๊ณตํ†ต ์ปค์Šคํ…€ ํ›… ๋ฐ ์ธํ„ฐ๋ž™์…˜ ์ธํ„ฐํŽ˜์ด์Šค ์ถ”๊ฐ€, ์ฐจ๋Ÿ‰ ์ƒ์„ธ์ •๋ณด, QnA, ํ‘ธํ„ฐ, ๊ฐ๊ฐ์˜ ์ธํ„ฐ๋ž™์…˜ ๊ตฌํ˜„ | ์ธํŠธ๋กœ, ํ—ค๋”, ์ฐจ๋Ÿ‰ ๊ธฐ๋ณธ์ •๋ณด ํ‘ธํ„ฐ ๊ตฌํ˜„ | +| 2์ฃผ์ฐจ | ๊ธฐ๋Œ€ํ‰, ์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ ๊ตฌํ˜„ | ์ธํ„ฐ๋ž™์…˜ ์„น์…˜ ๋ฐ ๋ชจ๋‹ฌ ๊ตฌํ˜„ | +| 3์ฃผ์ฐจ | ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€ ์ด๋ฒคํŠธ ๊ด€๋ฆฌ ๊ตฌํ˜„ | ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€ ๊ธฐ๋Œ€ํ‰ ๊ด€๋ฆฌ ๊ตฌํ˜„ | +| 4์ฃผ์ฐจ | ์‹œ๊ฐ์žฅ์• ์ธ ์›น ์ ‘๊ทผ์„ฑ ๊ฐœ์„  ๋ฐ ์‚ฌ์šฉ์„ฑ ๊ฐœ์„  | ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€ ๊ธฐ๋Œ€ํ‰ ๊ด€๋ฆฌ, ์œ ์ € ๊ด€๋ฆฌ ๊ตฌํ˜„ | **Back-End** @@ -36,25 +77,100 @@ | 3์ฃผ์ฐจ | ์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ ์ตœ์ ํ™”, ์„œ๋น„์Šค ํ™•์žฅ์„ฑ ๊ฐœ์„ , ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑ | | 4์ฃผ์ฐจ | ๋ฒ„๊ทธ ์ˆ˜์ •, ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ๊ธฐ๋ฐ˜ ์„œ๋น„์Šค ์ตœ์ ํ™” | -## Backlog +## ๐Ÿชต Backlog ### Front-End ![image](https://github.com/user-attachments/assets/3fec291d-4aed-4f04-895b-7b2686aecc59) ### Back-End ![image](https://github.com/user-attachments/assets/d7444775-cbad-48a2-a278-fd73368a1b6e) -## ERD -image +## ๐Ÿค” Issue & TroubleShooting +- [ํ”„๋ก ํŠธ์—”๋“œ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…](https://github.com/softeerbootcamp4th/Team6-AwesomeOrange-FE/wiki) +- [๋ฐฑ์—”๋“œ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…](https://github.com/softeerbootcamp4th/Team6-AwesomeOrange-BE/wiki/%5BIssue-&-TroubleShooting%5D) -## Tech Stack +## โš™๏ธ Tech Stack & Architecture -### Front-End +### ๐Ÿ”ง Tech Stack + +#### Front-End -### Back-End +#### Back-End -## Issue & TroubleShooting -[Issue & TroubleShooting](https://github.com/softeerbootcamp4th/Team6-AwesomeOrange-BE/wiki/%5BIssue-&-TroubleShooting%5D) +### ๐Ÿ—‚๏ธ ํด๋” ๊ตฌ์กฐ +**ํ”ผ์ฒ˜ ๊ธฐ๋ฐ˜ ํด๋” ๊ตฌ์กฐ**๋ฅผ ์ฑ„์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ feature ํด๋” ๋‚ด์— ์ปดํฌ๋„ŒํŠธ, ํ›…, ์ƒ์ˆ˜ ๋“ฑ์ด ์ •์˜๋˜์–ด ์žˆ๋Š” ํ˜•ํƒœ๋กœ, ๋ถ„๋ฅ˜ ๊ธฐ๋ฐ˜ ํด๋” ๊ตฌ์กฐ์— ๋น„ํ•ด ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํŒŒ์ผ์„ ์ฐพ๊ธฐ ๋งค์šฐ ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ฑ„์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. +``` +. +โ”œโ”€โ”€ packages/ +โ”‚ โ”œโ”€โ”€ common/ : ๋ฉ”์ธ๊ณผ ์–ด๋“œ๋ฏผ ๊ณตํ†ต์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. +โ”‚ โ”‚ โ””โ”€โ”€ src +โ”‚ โ”œโ”€โ”€ mainPage/ : ๋ฉ”์ธ ํŽ˜์ด์ง€์˜ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์ž…๋‹ˆ๋‹ค. +โ”‚ โ”‚ โ”œโ”€โ”€ src/ +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ shared : 2๋ฒˆ ์ด์ƒ ์‚ฌ์šฉ๋˜๋Š” ๊ณตํ†ต feature์ž…๋‹ˆ๋‹ค. +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ features : 1๋ฒˆ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ์ฃผ์š” feature์ž…๋‹ˆ๋‹ค. +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ App.jsx +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ main-client.jsx +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ main-server.jsx +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ mock.js +โ”‚ โ”‚ โ”œโ”€โ”€ public : ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ์ •์  ์ž์›์ž…๋‹ˆ๋‹ค. +โ”‚ โ”‚ โ””โ”€โ”€ index.html +โ”‚ โ””โ”€โ”€ adminPage/ : ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€์˜ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์ž…๋‹ˆ๋‹ค. +โ”‚ โ”œโ”€โ”€ src/ +โ”‚ โ”‚ โ”œโ”€โ”€ shared +โ”‚ โ”‚ โ”œโ”€โ”€ features +โ”‚ โ”‚ โ”œโ”€โ”€ pages : ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€์˜ ๊ฐ ํŽ˜์ด์ง€๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. +โ”‚ โ”‚ โ”œโ”€โ”€ App.jsx +โ”‚ โ”‚ โ”œโ”€โ”€ main-client.jsx +โ”‚ โ”‚ โ”œโ”€โ”€ main-server.jsx +โ”‚ โ”‚ โ””โ”€โ”€ mock.js +โ”‚ โ”œโ”€โ”€ public +โ”‚ โ””โ”€โ”€ index.html +โ””โ”€โ”€ public +``` + +### ๐Ÿ—„๏ธ ERD +image -## Project Archeitecture +### ๐Ÿ—๏ธ ๋ฐฑ์—”๋“œ ์•„ํ‚คํ…์ฒ˜ +(์ค€๋น„์ค‘์ž…๋‹ˆ๋‹ค.) + +## ๐Ÿ“ฅ Installation + +1. ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ํด๋ก ํ•˜์„ธ์š”. +```bash +git clone https://github.com/softeerbootcamp4th/Team6-AwesomeOrange-FE.git +``` + +2. ์˜์กด์„ฑ ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•˜์„ธ์š”. +```bash +npm install +``` + +3. ํ”„๋กœ์ ํŠธ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”. + - ๋ฉ”์ธ ํ”„๋กœ์ ํŠธ + ```bash + npm run dev + ``` + - ์–ด๋“œ๋ฏผ ํ”„๋กœ์ ํŠธ + ```bash + npm run dev-admin + ``` + +4. ๋งŒ์•ฝ, ๋นŒ๋“œ๋œ ๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด, ๋‹ค์Œ์„ ์‹คํ–‰ํ•˜์„ธ์š”. + - ๋ฉ”์ธ ํ”„๋กœ์ ํŠธ + ```bash + npm run build && npm run preview + ``` + - ์–ด๋“œ๋ฏผ ํ”„๋กœ์ ํŠธ + ```bash + npm run build-admin && npm run preview-admin + ``` + +## ๐Ÿ“ธ Screenshots +![๊ฐ„๋‹จ ์†Œ๊ฐœ ์„น์…˜](https://github.com/user-attachments/assets/0026eae2-befc-4e4d-a765-b988d61d63d8) +![์ฃผํ–‰๊ฑฐ๋ฆฌ ์ธํ„ฐ๋ž™์…˜](https://github.com/user-attachments/assets/2bda17e1-a055-4b56-937c-5933d358496b) +![V2L ์ธํ„ฐ๋ž™์…˜](https://github.com/user-attachments/assets/c61aae83-817a-4d2c-9f79-e3d362fd99ec) +![์ •๋‹ต ๋ณด์—ฌ์ฃผ๊ธฐ](https://github.com/user-attachments/assets/18c01284-9a52-4ab6-825a-f5e7939f6070) +![๊ธฐ๋Œ€ํ‰ ์„น์…˜](https://github.com/user-attachments/assets/46c045f7-b87d-4d60-b785-01556e4088db) +![์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ](https://github.com/user-attachments/assets/b99a0f32-63aa-497d-8875-e53209254c89) diff --git a/package-lock.json b/package-lock.json index c21a31e9..24a726f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@awesome-orange", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@awesome-orange", - "version": "1.0.0", + "version": "1.0.1", "workspaces": [ "packages/common", "packages/mainPage", @@ -2479,6 +2479,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvas-confetti": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz", + "integrity": "sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4737,9 +4747,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -7237,16 +7247,17 @@ }, "packages/common": { "name": "@awesome-orange/common", - "version": "1.0.0", + "version": "1.0.1", "devDependencies": { "mime-types": "^2.1.35" } }, "packages/mainPage": { "name": "@awesome-orange/main", - "version": "1.0.0", + "version": "1.0.1", "dependencies": { "@awesome-orange/common": "*", + "canvas-confetti": "^1.9.3", "jwt-decode": "^4.0.0", "react-lottie-player": "^2.1.0", "swiper": "^11.1.9" diff --git a/package.json b/package.json index 7949e5d0..6515d191 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,14 @@ { "name": "@awesome-orange", "private": true, - "version": "1.0.0", + "version": "1.0.1", "type": "module", "scripts": { "format": "prettier --write 'packages/**/*.{js,jsx,ts,tsx,json,css}'", "lint": "eslint . --ext js,jsx --max-warnings 0", "lint-fix": "eslint . --ext js,jsx --fix", + "dev": "npm --prefix ./packages/mainPage run dev", + "dev-admin": "npm --prefix ./packages/adminPage run dev", "build": "npm --prefix ./packages/mainPage run build", "build-admin": "npm --prefix ./packages/adminPage run build", "preview": "npm --prefix ./packages/mainPage run preview", diff --git a/packages/adminPage/build.js b/packages/adminPage/build.js index ba07dbb8..e93b6175 100644 --- a/packages/adminPage/build.js +++ b/packages/adminPage/build.js @@ -7,8 +7,6 @@ import config from "./vite.config.js"; const __dirname = fileURLToPath(new URL(".", import.meta.url)); const toAbsolute = (p) => resolve(__dirname, p); -console.log("yeahhhhh!!!!"); - const buildUrl = [ "index", "events", @@ -46,6 +44,7 @@ async function processBuild() { await Promise.all([buildClient(), buildSSG()]); await Promise.all([ copyFolder("../../public/font", `./dist/font`), + copyFolder("../../public/favicon", `./dist/favicon`), copyFolder("../../public/icons", `./dist/shared/icons`), ]); await injectSSGToHtml(); diff --git a/packages/adminPage/index.html b/packages/adminPage/index.html index ec623a9c..294d636d 100644 --- a/packages/adminPage/index.html +++ b/packages/adminPage/index.html @@ -2,13 +2,16 @@ - + + + + Awesome Orange - Admin diff --git a/packages/adminPage/vite.config.js b/packages/adminPage/vite.config.js index 2440aa24..f6eb4648 100644 --- a/packages/adminPage/vite.config.js +++ b/packages/adminPage/vite.config.js @@ -19,6 +19,7 @@ export default defineConfig({ svgr(), sharedAssetRouter([ ["/font", "/public/font"], + ["/favicon", "/public/favicon"], ["/shared", "/public"], ["/mockServiceWorker.js", "/public/mockServiceWorker.js"], ]), diff --git a/packages/common/package.json b/packages/common/package.json index 0a84e396..abccae96 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,6 @@ { "name": "@awesome-orange/common", - "version": "1.0.0", + "version": "1.0.1", "type": "module", "devDependencies": { "mime-types": "^2.1.35" diff --git a/packages/common/src/components/PhoneInput.jsx b/packages/common/src/components/PhoneInput.jsx index a841697a..ea8fb0fd 100644 --- a/packages/common/src/components/PhoneInput.jsx +++ b/packages/common/src/components/PhoneInput.jsx @@ -1,11 +1,28 @@ +import { useRef } from "react"; import Input from "./Input.jsx"; import { addHyphen } from "../utils.js"; function PhoneInput({ text, setText, ...otherProps }) { + const isComposing = useRef(0); + return ( setText(addHyphen(value))} + setText={(value) => { + if (isComposing.current >= 1) { + isComposing.current = (isComposing.current + 1) % 3; + return; + } + setText(addHyphen(value)); + }} + onCompositionStart={() => { + isComposing.current = 1; + }} + onCompositionEnd={(e) => { + isComposing.current = 0; + setText(addHyphen(e.target.value)); + }} placeholder="-๋ฅผ ์ œ์™ธํ•œ ์ˆซ์ž๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”." {...otherProps} maxLength="13" diff --git a/packages/common/src/utils.js b/packages/common/src/utils.js index 3bbf0c54..e7c0b04a 100644 --- a/packages/common/src/utils.js +++ b/packages/common/src/utils.js @@ -147,7 +147,7 @@ export function getDayDifference(_date1, _date2) { } export function addHyphen(value) { - const plain = value.replace(/\D/g, ""); + const plain = value.trim().replace(/[^0-9]/g, ""); if (plain.length < 4) return plain; if (plain.length <= 7) return plain.replace(/^(\d{3})(\d{0,4})$/, "$1-$2"); diff --git a/packages/mainPage/build.js b/packages/mainPage/build.js index 70a16f62..8882207b 100644 --- a/packages/mainPage/build.js +++ b/packages/mainPage/build.js @@ -33,6 +33,7 @@ async function processBuild() { await Promise.all([buildClient(), buildSSG()]); await Promise.all([ copyFolder("../../public/font", `./dist/font`), + copyFolder("../../public/favicon", `./dist/favicon`), copyFolder("../../public/icons", `./dist/shared/icons`), ]); await injectSSGToHtml(); diff --git a/packages/mainPage/index.html b/packages/mainPage/index.html index 42d2a213..c6a5dca9 100644 --- a/packages/mainPage/index.html +++ b/packages/mainPage/index.html @@ -2,14 +2,22 @@ - + + + + + - Awesome Orange FE! + + + + + HI. Five. The new IONIQ 5 ์ด๋ฒคํŠธ ํŽ˜์ด์ง€
diff --git a/packages/mainPage/package.json b/packages/mainPage/package.json index 9fa1751b..00958fe5 100644 --- a/packages/mainPage/package.json +++ b/packages/mainPage/package.json @@ -1,6 +1,6 @@ { "name": "@awesome-orange/main", - "version": "1.0.0", + "version": "1.0.1", "type": "module", "main": "src/main-client.jsx", "scripts": { @@ -9,9 +9,10 @@ "preview": "vite preview" }, "dependencies": { + "@awesome-orange/common": "*", + "canvas-confetti": "^1.9.3", "jwt-decode": "^4.0.0", "react-lottie-player": "^2.1.0", - "swiper": "^11.1.9", - "@awesome-orange/common": "*" + "swiper": "^11.1.9" } } diff --git a/packages/mainPage/public/images/fcfsBackground.webp b/packages/mainPage/public/images/fcfsBackground.webp new file mode 100644 index 00000000..87af8a5d Binary files /dev/null and b/packages/mainPage/public/images/fcfsBackground.webp differ diff --git a/packages/mainPage/public/images/thumbnails.png b/packages/mainPage/public/images/thumbnails.png new file mode 100644 index 00000000..c813f2b7 Binary files /dev/null and b/packages/mainPage/public/images/thumbnails.png differ diff --git a/packages/mainPage/src/features/fcfs/cardGame/CardGame.jsx b/packages/mainPage/src/features/fcfs/cardGame/CardGame.jsx index 10dcf102..78ae43f8 100644 --- a/packages/mainPage/src/features/fcfs/cardGame/CardGame.jsx +++ b/packages/mainPage/src/features/fcfs/cardGame/CardGame.jsx @@ -27,6 +27,14 @@ const submitCardgameErrorHandle = { offline: "offline", }; +function popConfetti(confetti) { + confetti.default({ + particleCount: 100, + spread: 70, + origin: { y: 0.8 }, + }); +} + function CardGame({ offline }) { // states const eventStatus = useFcfsStore((store) => store.eventStatus); @@ -47,21 +55,29 @@ function CardGame({ offline }) { } function getCardAnswerOffline(index) { + const confetti = import("canvas-confetti"); return new Promise((resolve) => { - setTimeout(() => resolve(offlineAnswer === index), 1000); + setTimeout(() => { + const isAnswer = offlineAnswer === index; + if (isAnswer) confetti.then(popConfetti); + resolve(offlineAnswer === index); + }, 1000); }); } async function getCardAnswerOnline(index) { const fetchConfig = { method: "post", body: { answer: index } }; try { + const confetti = import("canvas-confetti"); const { answerResult, winner } = await fetchServer( `/api/v1/event/fcfs/${EVENT_FCFS_ID}`, fetchConfig, ).catch(handleError(submitCardgameErrorHandle)); if (answerResult) { - if (winner) openModal(); - else openModal(); + if (winner) { + confetti.then(popConfetti); + openModal(); + } else openModal(); } return answerResult; } catch (e) { @@ -103,22 +119,24 @@ function CardGame({ offline }) { } /> -
- {[1, 2, 3, 4].map((index, i) => ( - - setFlipState((state) => { - const newState = [...state]; - newState[i] = flipState; - return newState; - }) - } - key={`card ${index}`} - {...cardProps} - /> - ))} +
+
+ {[1, 2, 3, 4].map((index, i) => ( + + setFlipState((state) => { + const newState = [...state]; + newState[i] = flipState; + return newState; + }) + } + key={`card ${index}`} + {...cardProps} + /> + ))} +
diff --git a/packages/mainPage/src/features/fcfs/index.jsx b/packages/mainPage/src/features/fcfs/index.jsx index 7a578ba1..0a8acfa3 100644 --- a/packages/mainPage/src/features/fcfs/index.jsx +++ b/packages/mainPage/src/features/fcfs/index.jsx @@ -12,8 +12,15 @@ function FcfsSection() { return (
+

EVENT 2 diff --git a/packages/mainPage/src/features/interactions/index.jsx b/packages/mainPage/src/features/interactions/index.jsx index a1c1dadc..2c8be557 100644 --- a/packages/mainPage/src/features/interactions/index.jsx +++ b/packages/mainPage/src/features/interactions/index.jsx @@ -23,8 +23,9 @@ export default function InteractionPage() { return ( <>

- - +
+ +
- ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐ€๊ธฐ +
diff --git a/packages/mainPage/src/features/simpleInformation/index.jsx b/packages/mainPage/src/features/simpleInformation/index.jsx index 2bb3a51a..fb38cbb4 100644 --- a/packages/mainPage/src/features/simpleInformation/index.jsx +++ b/packages/mainPage/src/features/simpleInformation/index.jsx @@ -11,8 +11,8 @@ export default function SimpleInformation() { return (
-
-
+
+
๋‚ด๊ฐ€ ์„ ํƒํ•œ ๋‹จ ํ•˜๋‚˜์˜ ์ „๊ธฐ์ฐจ The new IONIQ 5 diff --git a/packages/mainPage/src/shared/auth/AuthModal.jsx b/packages/mainPage/src/shared/auth/AuthModal.jsx index 84cad166..b4d20537 100644 --- a/packages/mainPage/src/shared/auth/AuthModal.jsx +++ b/packages/mainPage/src/shared/auth/AuthModal.jsx @@ -5,9 +5,9 @@ import UserFindStage from "./UserFind"; import { ModalCloseContext } from "@common/modal/modal.jsx"; import { login } from "./store.js"; -const AUTH_INPUT_PAGE = Symbol("input"); -const AUTH_CODE_PAGE = Symbol("code"); -const AUTH_FIND_PAGE = Symbol("find"); +const AUTH_INPUT_PAGE = "input"; +const AUTH_CODE_PAGE = "code"; +const AUTH_FIND_PAGE = "find"; function AuthModal({ onComplete: onCompleteCallback }) { const close = useContext(ModalCloseContext); diff --git a/packages/mainPage/src/shared/drawEvent/store.js b/packages/mainPage/src/shared/drawEvent/store.js index 5c17c6d7..d51fb5ea 100644 --- a/packages/mainPage/src/shared/drawEvent/store.js +++ b/packages/mainPage/src/shared/drawEvent/store.js @@ -10,6 +10,7 @@ function getJoinDataEvent() { let newJoinedList = [false, false, false, false, false]; dates.forEach((date) => { const day = getDayDifference(EVENT_START_DATE, new Date(date)); + if (day >= 5 || day < 0) return; newJoinedList[day] = true; }); return newJoinedList; diff --git a/packages/mainPage/vite.config.js b/packages/mainPage/vite.config.js index b21fb821..f797e502 100644 --- a/packages/mainPage/vite.config.js +++ b/packages/mainPage/vite.config.js @@ -14,6 +14,7 @@ export default defineConfig({ svgr(), sharedAssetRouter([ ["/font", "/public/font"], + ["/favicon", "/public/favicon"], ["/shared", "/public"], ["/mockServiceWorker.js", "/public/mockServiceWorker.js"], ]), diff --git a/public/favicon/android-chrome-192x192.png b/public/favicon/android-chrome-192x192.png new file mode 100644 index 00000000..651ca722 Binary files /dev/null and b/public/favicon/android-chrome-192x192.png differ diff --git a/public/favicon/android-chrome-512x512.png b/public/favicon/android-chrome-512x512.png new file mode 100644 index 00000000..331a39eb Binary files /dev/null and b/public/favicon/android-chrome-512x512.png differ diff --git a/public/favicon/apple-touch-icon.png b/public/favicon/apple-touch-icon.png new file mode 100644 index 00000000..368984fd Binary files /dev/null and b/public/favicon/apple-touch-icon.png differ diff --git a/public/favicon/favicon-16x16.png b/public/favicon/favicon-16x16.png new file mode 100644 index 00000000..dea99eac Binary files /dev/null and b/public/favicon/favicon-16x16.png differ diff --git a/public/favicon/favicon-32x32.png b/public/favicon/favicon-32x32.png new file mode 100644 index 00000000..7fad71a5 Binary files /dev/null and b/public/favicon/favicon-32x32.png differ diff --git a/public/favicon/favicon.ico b/public/favicon/favicon.ico new file mode 100644 index 00000000..0249aa2c Binary files /dev/null and b/public/favicon/favicon.ico differ diff --git a/public/favicon/site.webmanifest b/public/favicon/site.webmanifest new file mode 100644 index 00000000..45dc8a20 --- /dev/null +++ b/public/favicon/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/public/vite.svg b/public/vite.svg deleted file mode 100644 index e7b8dfb1..00000000 --- a/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/vite-devRouter.js b/vite-devRouter.js deleted file mode 100644 index ab85f5f9..00000000 --- a/vite-devRouter.js +++ /dev/null @@ -1,33 +0,0 @@ -// from monument gallery -export default function devRouter(rawRouteList) { - // ๋ฌธ์ž์—ด๋กœ ๋œ route list๋ฅผ ์ •๊ทœํ‘œํ˜„์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์ •๊ทœํ‘œํ˜„์‹์ด ์•„๋‹Œ ๊ฒƒ๋“ค์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. - const routeList = rawRouteList - .map(([route, html]) => { - if (typeof route === "string") { - route = new RegExp(`^${route.replace(/\*/g, ".*").replace(/\?/g, ".")}/?$`); - } - return [route, html]; - }) - .filter(([route]) => route instanceof RegExp); - - // ์š”์ฒญํ•œ ํŒจ์Šค๊ฐ€ ์„ค์ •๋œ ๋ผ์šฐํŒ… ๊ฒฝ๋กœ์— ๋งž๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. - function foundRoute(path) { - for (let [route, html] of routeList) { - if (route.test(path)) return html; - } - return null; - } - - return { - name: "route-server", - configureServer(server) { - server.middlewares.use((req, res, next) => { - const htmlPath = foundRoute(req.originalUrl); - if (htmlPath === null) return next(); - req.url = htmlPath; - req.originalUrl = htmlPath; - next(); - }); - }, - }; -} \ No newline at end of file