diff --git a/README.md b/README.md
index e97a1d649..073597e5c 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,126 @@
# π μ§νμ² λ
Έμ λ λ―Έμ
+## π©π»βπ» κΈ°λ₯ λͺ©λ‘
+
+- 4κ° κ΄λ¦¬ νμ΄μ§ μ°κ²°μ μν λ²νΌ μμ±
+- 4κ° κ΄λ¦¬νμ΄μ§ μ»΄ν¬λνΈ μμ±
+- κ° λ²νΌμ μ΄λ²€νΈ 리μ€λ λ±λ‘νμ¬ μ»΄ν¬λνΈ μ°κ²°
+- μ κ΄λ¦¬ νμ΄μ§ UI ꡬν
+- μ κ΄λ¦¬ νμ΄μ§ κ° λ²νΌμ μ΄λ²€νΈ 리μ€λ μ°κ²°
+- local storageλ₯Ό μ΄μ©νμ¬ μ λ°μ΄ν° μ μ₯νκΈ°
+- λ
Έμ κ΄λ¦¬ νμ΄μ§ UI ꡬν
+- λ
Έμ κ΄λ¦¬ νμ΄μ§ κ° λ²νΌμ μ΄λ²€νΈ 리μ€λ μ°κ²°
+- local storageμ κ°μ²΄λ₯Ό μ΄μ©νμ¬ λ
Έμ λ°μ΄ν°μ μ λ°μ΄ν° ν¨κ» μ μ₯νκΈ°
+- μ κ΄λ¦¬ λ°μ΄ν°μ λ
Έμ κ΄λ¦¬ λ°μ΄ν° μ°λ
+- κ΅¬κ° κ΄λ¦¬ νμ΄μ§ UI ꡬν
+- κ΅¬κ° κ΄λ¦¬ νμ΄μ§ λ
Έμ μ ν λ²νΌμ μ΄λ²€νΈ 리μ€λ μ°κ²°νμ¬ ν΄λΉ λ
Έμ μ 보 λ λλ§
+- κ΅¬κ° λ±λ‘ ꡬν
+- κ΅¬κ° μ κ±° ꡬν
+- λ
Έμ λ μΆλ ₯ νμ΄μ§ UI ꡬν
+- μμΈ μν© κ²μ¦
+ - μ κ΄λ¦¬
+ - μ€λ³΅λ μ μ΄λ¦ μ
λ ₯ μ alert v
+ - 곡백 μ
λ ₯ μ alert v
+ - 2μ λ―Έλ§ μ
λ ₯ μ alert v
+ - λ
Έμ μ λ±λ‘λ μ μμ μ alert v
+ - λ
Έμ κ΄λ¦¬
+ - μ€λ³΅λ λ
Έμ μ΄λ¦ μ
λ ₯ μ alert v
+ - 곡백 μ
λ ₯ μ alert v
+ - μν μ’
μ μκ³Ό νν μ’
μ μμ΄ μ€λ³΅λλ λ
Έμ μ΄ μ΄λ―Έ μ‘΄μ¬νλ κ²½μ° alert v
+ - μν μ’
μ μκ³Ό νν μ’
μ μμ΄ λμΌν μμΈ κ²½μ° alert v
+ - κ΅¬κ° κ΄λ¦¬
+ - λ
Έμ μμ μ κ±° μ confirm ν μμ v
+ - λ
Έμ μ ν¬ν¨λ μμ΄ 2κ° μ΄νμΌ λ λ
Έμ μμ μ κ±° μ alert v
+ - κ΅¬κ° λ±λ‘ μ μΈλ±μ€κ° 0μ΄κ±°λ κ°μ₯ λ μΈλ±μ€μΈ κ²½μ° alert v
+ - μμμ μ«μκ° μλ κ° μ
λ ₯ λΆκ°νλλ‘ type=numberλ‘ μ€μ v
+ - μμμ μμ μ
λ ₯ μ alert v
+ - λ
Έμ μ μ΄λ―Έ μ‘΄μ¬νλ κ΅¬κ° μ΄λ¦ λ±λ‘ μ alert v
+ - μ€λ³΅λλ μ μ΄λ¦, λ
Έμ μ΄λ¦ κ²μ¦ ν¨μ ν΅ν© v
+- 리ν©ν λ§
+ - μλ°μ€ν¬λ¦½νΈ 컨벀μ
μ λ§μΆμ΄ validation depthμ€μ΄κΈ° λ° λ¦¬ν©ν λ§ v
+ - ν΄λ μ¬κ΅¬μ± v
+ - handlers 컨벀μ
μ λ§μΆμ΄ validation depthμ€μ΄κΈ° λ° λ¦¬ν©ν λ§ v
+ - html tag κ²ν v
+ - input value κ²ν , κ΅¬κ° type=number μμ ν μ«μλ§ μ
λ ₯ κ°λ₯νλλ‘ κ²μ¦ μΆκ° v
+ - returnκ°μ΄ μλ map λ©μλλ₯Ό forEachλ‘ μμ v
+ - μμν v
+ - css κ²ν v
+
+## β λ¬Έμ ꡬ쑰
+
+```plaintext
+βββ src
+β β
+β βββ components // μ¬μ©μλ¨μ 보μ¬μ§ νμ΄μ§λ₯Ό κ΄λ¦¬νλ κ³³
+β β β
+β β βββ pages
+β β β βββ linePages.js // λ
Έμ κ΄λ¦¬ νμ΄μ§
+β β β βββ mapPrintPages.js // λ
Έμ λ μΆλ ₯ νμ΄μ§
+β β β βββ sectionPages.js // κ΅¬κ° κ΄λ¦¬ νμ΄μ§
+β β β βββ stationPages.js // μ κ΄λ¦¬ νμ΄μ§
+β β β
+β β βββ app.js // κ° νμ΄μ§λ₯Ό λ λλ§ν λ λΌμ°ν
μ λ΄λΉνλ κ³³
+β β
+β βββ constatns
+β β β
+β β βββ tag.js // html tag μμλ₯Ό λͺ¨μλμ κ³³
+β β
+β βββ managers // κ° κ΄λ¦¬ νμ΄μ§λ₯Ό κ΄λ¦¬νλ κ³³
+β β β
+β β βββ handlers
+β β β βββ lineHanlderPages.js // λ
Έμ κ΄λ ¨ μ΄λ²€νΈ κ΄λ¦¬
+β β β βββ mapPrintHandlerPages.js // λ
Έμ λ μΆλ ₯ κ΄λ ¨ μ΄λ²€νΈ κ΄λ¦¬
+β β β βββ sectionHandlerPages.js // κ΅¬κ° κ΄λ ¨ μ΄λ²€νΈ κ΄λ¦¬
+β β β βββ stationHandlerPages.js // μ κ΄λ ¨ μ΄λ²€νΈ κ΄λ¦¬
+β β β
+β β βββ validation // μ ν¨μ±μ κ²μ¦νλ κ³³
+β β β βββ alert.js // μ ν¨μ± κ²μ¦μ μν alert messageλ₯Ό μμ±νλ κ³³
+β β β βββ validation.js // μ ν¨μ±μ κ²μ¦μ νκ³ νμν λ°μ΄ν°λ₯Ό λ°ννλ κ³³
+β β β
+β β βββ init.js // μ΄κΈ°νλ₯Ό λ΄λΉνλ κ³³
+β β β
+β β βββ render.js // λ λλ§μ λ΄λΉνλ κ³³
+β β
+β βββ objects
+β β β
+β β βββ objects.js // μμ±ν κ°μ²΄λ₯Ό λͺ¨μλ κ³³
+β β
+β βββ index.js // μμμ
+β β
+β βββ main.js // μ΄κΈ° μμ
λ€μ λ΄λΉνλ κ³³
+β
+βββ index.html
+```
+
+## π€¦π»ββοΈ κ³ λ―Όν μ§μ
+
+- λ²νΌμ κ° κ΄λ¦¬νμ΄μ§λ₯Ό μ°κ²°ν λ, 리μ‘νΈμμλ μ»΄ν¬λνΈλ₯Ό μ½κ² λ λλ§ν μ μμλλ° vanilla javascriptλ‘ μ°κ²°νλ €κ³ νλ μ΄λ €μ λ€.
+- μ¬μ©μ λμμ λ°λΌ μλ‘μ΄ μ리먼νΈλ₯Ό μΆκ°νκ±°λ μμ ν λ, λ¨μ μ리먼νΈλ₯Ό λ€μ renderνκ³ , μ΄λ²€νΈ 리μ€λλ₯Ό λ€μ μΆκ°νλ λ± μ
λ°μ΄νΈλ μνλ₯Ό ꡬννλ λΆλΆμ΄ κΉλ€λ‘μ κ³ , μ΄ λ°©λ²μ΄ κ³Όμ° ν¨μ¨μ μΈ λ°©λ²μ΄ λ§λμ§ μꡬμ¬μ΄ λ€μλ€.
+- station, line λ±μ μ΄λ¦μ΄ μ¬λ¬ ν¨μ, λ³μλͺ
μ ν¬ν¨λμ΄ μλ―Έ μ λ¬μ΄ λͺ
ννλ©΄μλ κ°λ
μ±μ΄ μ’μ ν¨μλͺ
, λ³μλͺ
μ μ§λ κ²μ΄ μ΄λ €μ λ€.
+- μμΈμν©μ μ΄λκΉμ§ 체ν¬ν΄μΌνλμ§ νλ¨νλ κ²μ΄ μ΄λ €μ λ€.
+
+---
+
## π κΈ°λ₯ μꡬμ¬ν
### μ§νμ² μ κ΄λ ¨ κΈ°λ₯
+
- μ§νμ² μμ λ±λ‘νκ³ μμ ν μ μλ€. (λ¨, λ
Έμ μ λ±λ‘λ μμ μμ ν μ μλ€)
- μ€λ³΅λ μ§νμ² μ μ΄λ¦μ΄ λ±λ‘λ μ μλ€.
- μ§νμ² μμ 2κΈμ μ΄μμ΄μ΄μΌ νλ€.
- μ§νμ² μμ λͺ©λ‘μ μ‘°νν μ μλ€.
### μ§νμ² λ
Έμ κ΄λ ¨ κΈ°λ₯
+
- μ§νμ² λ
Έμ μ λ±λ‘νκ³ μμ ν μ μλ€.
- μ€λ³΅λ μ§νμ² λ
Έμ μ΄λ¦μ΄ λ±λ‘λ μ μλ€.
- λ
Έμ λ±λ‘ μ μν μ’
μ μκ³Ό νν μ’
μ μμ μ
λ ₯λ°λλ€.
- μ§νμ² λ
Έμ μ λͺ©λ‘μ μ‘°νν μ μλ€.
### μ§νμ² κ΅¬κ° μΆκ° κΈ°λ₯
+
- μ§νμ² λ
Έμ μ ꡬκ°μ μΆκ°νλ κΈ°λ₯μ λ
Έμ μ μμ μΆκ°νλ κΈ°λ₯μ΄λΌκ³ λ ν μ μλ€.
- - μκ³Ό μμ¬μ΄λ₯Ό ꡬκ°μ΄λΌ νκ³ μ΄ κ΅¬κ°λ€μ λͺ¨μμ΄ λ
Έμ μ΄λ€.
+ - μκ³Ό μμ¬μ΄λ₯Ό ꡬκ°μ΄λΌ νκ³ μ΄ κ΅¬κ°λ€μ λͺ¨μμ΄ λ
Έμ μ΄λ€.
- νλμ μμ μ¬λ¬κ°μ λ
Έμ μ μΆκ°λ μ μλ€.
- μκ³Ό μ μ¬μ΄μ μλ‘μ΄ μμ΄ μΆκ° λ μ μλ€.
- λ
Έμ μμ κ°λκΈΈμ μκΈΈ μ μλ€.
@@ -24,6 +128,7 @@
### μ§νμ² κ΅¬κ° μμ κΈ°λ₯
+
- λ
Έμ μ λ±λ‘λ μμ μ κ±°ν μ μλ€.
- μ’
μ μ μ κ±°ν κ²½μ° λ€μ μμ΄ μ’
μ μ΄ λλ€.
- λ
Έμ μ ν¬ν¨λ μμ΄ λκ° μ΄νμΌ λλ μμ μ κ±°ν μ μλ€.
@@ -31,6 +136,7 @@
### μ§νμ² λ
Έμ μ λ±λ‘λ μ μ‘°ν κΈ°λ₯
+
- λ
Έμ μ μν μ’
μ λΆν° νν μ’
μ κΉμ§ μ°κ²°λ μμλλ‘ μ λͺ©λ‘μ μ‘°νν μ μλ€.
@@ -38,32 +144,38 @@
## π» νλ‘κ·Έλ¨ μ€ν κ²°κ³Ό
### μκ΄λ¦¬
+
### λ
Έμ κ΄λ¦¬
+
### ꡬκ°κ΄λ¦¬
+
### λ
Έμ λ μΆλ ₯
-
+
## β
νλ‘κ·Έλλ° μꡬμ¬ν
### λ©λ΄ λ²νΌ
+
- μ κ΄λ¦¬ button νκ·Έλ `#station-manager-button` idκ°μ κ°μ§λ€.
- λ
Έμ κ΄λ¦¬ button νκ·Έλ `#line-manager-button` idκ°μ κ°μ§λ€.
- κ΅¬κ° κ΄λ¦¬ button νκ·Έλ `#section-manager-button` idκ°μ κ°μ§λ€.
- μ§νμ² λ
Έμ λ μΆλ ₯ κ΄λ¦¬ button νκ·Έλ `#map-print-manager-button` idκ°μ κ°μ§λ€.
### μ§νμ² μ κ΄λ ¨ κΈ°λ₯
+
- μ§νμ² μμ μ
λ ₯νλ input νκ·Έλ `#station-name-input` idκ°μ κ°μ§λ€.
- μ§νμ² μμ μΆκ°νλ button νκ·Έλ `#station-add-button` idκ°μ κ°μ§λ€.
- μ§νμ² μμ μμ νλ button νκ·Έλ `.station-delete-button` classκ°μ κ°μ§λ€.
### μ§νμ² λ
Έμ κ΄λ ¨ κΈ°λ₯
+
- μ§νμ² λ
Έμ μ μ΄λ¦μ μ
λ ₯νλ input νκ·Έλ `#line-name-input` idκ°μ κ°μ§λ€.
- μ§νμ² λ
Έμ μ μν μ’
μ μ μ ννλ select νκ·Έλ `#line-start-station-selector` idκ°μ κ°μ§λ€.
- μ§νμ² λ
Έμ μ νν μ’
μ μ μ ννλ select νκ·Έλ `#line-end-station-selector` idκ°μ κ°μ§λ€.
@@ -71,6 +183,7 @@
- μ§νμ² λ
Έμ μ μμ νλ button νκ·Έλ `.line-delete-button` classκ°μ κ°μ§λ€.
### μ§νμ² κ΅¬κ° μΆκ° κΈ°λ₯
+
- μ§νμ² λ
Έμ μ μ ννλ button νκ·Έλ `.section-line-menu-button` classκ°μ κ°μ§λ€.
- μ§νμ² κ΅¬κ°μ μ€μ ν μ select νκ·Έλ `#section-station-selector` idκ°μ κ°μ§λ€.
- μ§νμ² κ΅¬κ°μ μμλ₯Ό μ
λ ₯νλ input νκ·Έλ `#section-order-input` idκ°μ κ°μ§λ€.
@@ -78,6 +191,7 @@
- μ§νμ² κ΅¬κ°μ μ κ±°νλ button νκ·Έλ `.section-delete-button` classκ°μ κ°μ§λ€.
### μ§νμ² λ
Έμ λ μΆλ ₯ κΈ°λ₯
+
- μ§νμ² λ
Έμ λ μΆλ ₯ λ²νΌμ λλ₯΄λ©΄ `
` νκ·Έλ₯Ό λ§λ€κ³ ν΄λΉ νκ·Έ λ΄λΆμ λ
Έμ λλ₯Ό μΆλ ₯νλ€.
### κΈ°μ‘΄ μꡬμ¬ν
@@ -101,7 +215,8 @@
- [https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals)
### μΆκ°λ μꡬμ¬ν
-- [data](https://developer.mozilla.org/ko/docs/Learn/HTML/Howto/%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%86%8D%EC%84%B1_%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0)μμ±μ νμ©νμ¬ html νκ·Έμ μ, λ
Έμ , ꡬκ°μ μ μΌν λ°μ΄ν° κ°λ€μ κ΄λ¦¬νλ€.
+
+- [data](https://developer.mozilla.org/ko/docs/Learn/HTML/Howto/%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%86%8D%EC%84%B1_%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0)μμ±μ νμ©νμ¬ html νκ·Έμ μ, λ
Έμ , ꡬκ°μ μ μΌν λ°μ΄ν° κ°λ€μ κ΄λ¦¬νλ€.
- [localStorage](https://developer.mozilla.org/ko/docs/Web/API/Window/localStorage)λ₯Ό μ΄μ©νμ¬, μλ‘κ³ μΉ¨νλλΌλ κ°μ₯ μ΅κ·Όμ μμ
ν μ 보λ€μ λΆλ¬μ¬ μ μλλ‘ νλ€.
diff --git a/index.html b/index.html
index fc99deac2..dd25c7316 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,7 @@
-
π μ§νμ² λ
Έμ λ κ΄λ¦¬
+ π μ§νμ² λ
Έμ λ κ΄λ¦¬
diff --git a/src/components/app.js b/src/components/app.js
new file mode 100644
index 000000000..bf3d1ae95
--- /dev/null
+++ b/src/components/app.js
@@ -0,0 +1,20 @@
+import stationManagerPage from "./pages/stationPage.js";
+import lineManagerPage from "./pages/linePage.js";
+import sectionManagerPage from "./pages/sectionPage.js";
+import mapPrintManagerPage from "./pages/mapPrintPage.js";
+
+export default function app(pageName, subwayDatas) {
+ let app = ``;
+
+ if (pageName === "station") {
+ app = stationManagerPage(subwayDatas);
+ } else if (pageName === "line") {
+ app = lineManagerPage(subwayDatas);
+ } else if (pageName === "section") {
+ app = sectionManagerPage(subwayDatas);
+ } else if (pageName === "map") {
+ app = mapPrintManagerPage(subwayDatas);
+ }
+
+ return app;
+}
diff --git a/src/components/pages/linePage.js b/src/components/pages/linePage.js
new file mode 100644
index 000000000..b9814c3ea
--- /dev/null
+++ b/src/components/pages/linePage.js
@@ -0,0 +1,54 @@
+import { LINE_NAME_INPUT, LINE_START_STATION_SELECTOR, LINE_END_STATION_SELECTOR, LINE_ADD_BUTTON, LINE_DELETE_BUTTON } from "../../constants/tag.js";
+
+function lineManagerPage(subwayDatas) {
+ let options = subwayDatas.subwayStations.map((station) => ``);
+ let table = ``;
+
+ subwayDatas.lines &&
+ subwayDatas.lines.forEach(
+ (line) =>
+ (table += `
+ | ${line.name} |
+ ${line.stops[0]} |
+ ${line.stops[line.stops.length - 1]} |
+ |
+
`)
+ );
+
+ let lineManager = `
+ λ
Έμ μ΄λ¦
+
+
+
+
+
+
+
+
+
+
+
+ πμ§νμ² λ
Έμ λͺ©λ‘
+
+
+
+ | λ
Έμ μ΄λ¦ |
+ μν μ’
μ μ |
+ νν μ’
μ μ |
+ μ€μ |
+
+
+
+ ${table}
+
+
+ `;
+
+ return lineManager;
+}
+
+export default lineManagerPage;
diff --git a/src/components/pages/mapPrintPage.js b/src/components/pages/mapPrintPage.js
new file mode 100644
index 000000000..a1991ea6c
--- /dev/null
+++ b/src/components/pages/mapPrintPage.js
@@ -0,0 +1,10 @@
+function mapPrintManagerPage(subwayDatas) {
+ const map = subwayDatas.lines.reduce((prev, line) => {
+ const insideOfUl = line.stops.reduce((prev, stop) => prev + `${stop}`, "");
+ return prev + `${line.name}${insideOfUl}
`;
+ }, "");
+
+ return `${map}
`;
+}
+
+export default mapPrintManagerPage;
diff --git a/src/components/pages/sectionPage.js b/src/components/pages/sectionPage.js
new file mode 100644
index 000000000..d05d93eb7
--- /dev/null
+++ b/src/components/pages/sectionPage.js
@@ -0,0 +1,69 @@
+import { SECTION_LINE_MENU_BUTTON, SECTION_STATION_SELECTOR, SECTION_ORDER_INPUT, SECTION_ADD_BUTTON, SECTION_DELETE_BUTTON } from "../../constants/tag.js";
+
+function sectionManagerPage(subwayDatas) {
+ let lines = ``;
+
+ subwayDatas.lines &&
+ subwayDatas.lines.forEach(
+ (line) =>
+ (lines += `
+ `)
+ );
+
+ let sectionManager = `
+ ꡬκ°μ μμ ν λ
Έμ μ μ νν΄μ£ΌμΈμ.
+
+ ${lines}
+
+ `;
+
+ if (subwayDatas.targetLine) {
+ let targetLine = subwayDatas.targetLine;
+ let options = subwayDatas.subwayStations.map((station) => ``);
+ let table = ``;
+
+ subwayDatas.lines.forEach((line) => {
+ if (line.name === targetLine) {
+ line.stops.forEach((stop, idx) => {
+ table += `
+
+ | ${idx} |
+ ${stop} |
+ |
+
`;
+ });
+ }
+ });
+
+ sectionManager += `
+
+
${targetLine} κ΄λ¦¬
+
κ΅¬κ° λ±λ‘
+
+
+
+
+
+
+
+
+ | μμ |
+ μ μ΄λ¦ |
+ μ€μ |
+
+
+
+ ${table}
+
+
+
`;
+ }
+
+ return sectionManager;
+}
+
+export default sectionManagerPage;
diff --git a/src/components/pages/stationPage.js b/src/components/pages/stationPage.js
new file mode 100644
index 000000000..73cd92317
--- /dev/null
+++ b/src/components/pages/stationPage.js
@@ -0,0 +1,38 @@
+import { STATION_NAME_INPUT, STATION_ADD_BUTTON, STATION_DELETE_BUTTON } from "../../constants/tag.js";
+
+function stationManagerPage(subwayDatas) {
+ let table = ``;
+
+ let stations = subwayDatas.subwayStations;
+ stations &&
+ stations.forEach((station) => {
+ table += `
+ | ${station.name} |
+
+
+ |
+
`;
+ });
+
+ let stationManager = `
+ μ μ΄λ¦
+
+
+ πμ§νμ² μ λͺ©λ‘
+
+
+
+
+ | μ μ΄λ¦ |
+ μ€μ |
+
+
+
+ ${table}
+
+
+ `;
+ return stationManager;
+}
+
+export default stationManagerPage;
diff --git a/src/constants/tag.js b/src/constants/tag.js
new file mode 100644
index 000000000..8cc7958c5
--- /dev/null
+++ b/src/constants/tag.js
@@ -0,0 +1,37 @@
+const STATION_MANAGER_BUTTON = "station-manager-button";
+const LINE_MANAGER_BUTTON = "line-manager-button";
+const SECTION_MANAGER_BUTTON = "section-manager-button";
+const MAP_PRINT_MANAGER_BUTTON = "map-print-manager-button";
+const STATION_NAME_INPUT = "station-name-input";
+const STATION_ADD_BUTTON = "station-add-button";
+const STATION_DELETE_BUTTON = "station-delete-button";
+const LINE_NAME_INPUT = "line-name-input";
+const LINE_START_STATION_SELECTOR = "line-start-station-selector";
+const LINE_END_STATION_SELECTOR = "line-end-station-selector";
+const LINE_ADD_BUTTON = "line-add-button";
+const LINE_DELETE_BUTTON = "line-delete-button";
+const SECTION_LINE_MENU_BUTTON = "section-line-menu-button";
+const SECTION_STATION_SELECTOR = "section-station-selector";
+const SECTION_ORDER_INPUT = "section-order-input";
+const SECTION_ADD_BUTTON = "section-add-button";
+const SECTION_DELETE_BUTTON = "section-delete-button";
+
+export {
+ STATION_MANAGER_BUTTON,
+ LINE_MANAGER_BUTTON,
+ SECTION_MANAGER_BUTTON,
+ MAP_PRINT_MANAGER_BUTTON,
+ STATION_NAME_INPUT,
+ STATION_ADD_BUTTON,
+ STATION_DELETE_BUTTON,
+ LINE_NAME_INPUT,
+ LINE_START_STATION_SELECTOR,
+ LINE_END_STATION_SELECTOR,
+ LINE_ADD_BUTTON,
+ LINE_DELETE_BUTTON,
+ SECTION_LINE_MENU_BUTTON,
+ SECTION_STATION_SELECTOR,
+ SECTION_ORDER_INPUT,
+ SECTION_ADD_BUTTON,
+ SECTION_DELETE_BUTTON,
+};
diff --git a/src/index.js b/src/index.js
index e69de29bb..88d36dfbc 100644
--- a/src/index.js
+++ b/src/index.js
@@ -0,0 +1,3 @@
+import main from "./main.js";
+
+main();
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 000000000..88fd7ef11
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,19 @@
+import { initHTML, addEventToMainBtns } from "./managers/init.js";
+import render from "./managers/render.js";
+import app from "./components/app.js";
+
+export default function main() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+
+ if (!subwayDatas) {
+ let subwayDatas = {
+ subwayStations: [],
+ lines: [],
+ };
+ localStorage.setItem("subwayDatas", JSON.stringify(subwayDatas));
+ }
+
+ initHTML();
+ render(app());
+ addEventToMainBtns();
+}
diff --git a/src/managers/handlers/lineHandlers.js b/src/managers/handlers/lineHandlers.js
new file mode 100644
index 000000000..187e90783
--- /dev/null
+++ b/src/managers/handlers/lineHandlers.js
@@ -0,0 +1,64 @@
+import render from "../render.js";
+import app from "../../components/app.js";
+import { Line } from "../../objects/objects.js";
+import { validateInput, validateStartAndEndStations } from "../validation/validation.js";
+import { LINE_NAME_INPUT, LINE_ADD_BUTTON, LINE_DELETE_BUTTON, LINE_START_STATION_SELECTOR, LINE_END_STATION_SELECTOR } from "../../constants/tag.js";
+
+function onLineHandler() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+
+ render(app("line", subwayDatas));
+ subwayDatas && updateEvent();
+}
+
+function updateEvent() {
+ document.getElementById(LINE_ADD_BUTTON).addEventListener("click", onAddLineHandler);
+
+ let deleteBtns = document.getElementsByClassName(LINE_DELETE_BUTTON);
+ for (let i = 0; i < deleteBtns.length; i++) {
+ deleteBtns[i].addEventListener("click", onDeleteLineHandler);
+ }
+}
+
+function onAddLineHandler() {
+ let lineName = validateInput(document.getElementById(LINE_NAME_INPUT).value, LINE_NAME_INPUT);
+
+ if (lineName !== "") {
+ let startAndEndStations = [document.getElementById(LINE_START_STATION_SELECTOR).value, document.getElementById(LINE_END_STATION_SELECTOR).value];
+ let validatedStartAndEndStations = validateStartAndEndStations(startAndEndStations);
+ validatedStartAndEndStations && addLine(lineName, validatedStartAndEndStations);
+ }
+}
+
+function addLine(lineName, validatedStartAndEndStations) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let line = new Line(lineName, validatedStartAndEndStations);
+ let endStops = [line.stops[0], line.stops[line.stops.length - 1]];
+ let startStopIdx = subwayDatas.subwayStations.findIndex((station) => station.name === endStops[0]);
+ let endStopIdx = subwayDatas.subwayStations.findIndex((station) => station.name === endStops[1]);
+
+ subwayDatas.subwayStations[startStopIdx].line.push(lineName);
+ subwayDatas.subwayStations[endStopIdx].line.push(lineName);
+ subwayDatas.lines.push(line);
+
+ localStorage.setItem("subwayDatas", JSON.stringify(subwayDatas));
+ render(app("line", subwayDatas));
+ subwayDatas && updateEvent();
+}
+
+function onDeleteLineHandler() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let deleteTarget = event.target.parentNode.parentNode.childNodes[1].outerText;
+ let deleteTargetIdx = subwayDatas.lines.findIndex((line) => line.name === deleteTarget);
+
+ subwayDatas.subwayStations.forEach((station) => {
+ station.line.splice(station.line.indexOf(deleteTarget), 1);
+ });
+ subwayDatas.lines.splice(deleteTargetIdx, 1);
+
+ localStorage.setItem("subwayDatas", JSON.stringify(subwayDatas));
+ render(app("line", subwayDatas));
+ updateEvent();
+}
+
+export { onLineHandler };
diff --git a/src/managers/handlers/mapPrintHandler.js b/src/managers/handlers/mapPrintHandler.js
new file mode 100644
index 000000000..ce9780678
--- /dev/null
+++ b/src/managers/handlers/mapPrintHandler.js
@@ -0,0 +1,10 @@
+import render from "../render.js";
+import app from "../../components/app.js";
+
+function onMapPrintHandler() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+
+ render(app("map", subwayDatas));
+}
+
+export { onMapPrintHandler };
diff --git a/src/managers/handlers/sectionHandler.js b/src/managers/handlers/sectionHandler.js
new file mode 100644
index 000000000..081b2d9dd
--- /dev/null
+++ b/src/managers/handlers/sectionHandler.js
@@ -0,0 +1,93 @@
+import render from "../render.js";
+import app from "../../components/app.js";
+import { validateSectionDelete, validateOrder, validateSection } from "../validation/validation.js";
+import { SECTION_LINE_MENU_BUTTON, SECTION_STATION_SELECTOR, SECTION_ORDER_INPUT, SECTION_ADD_BUTTON, SECTION_DELETE_BUTTON } from "../../constants/tag.js";
+
+function onSectionHandler() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+
+ subwayDatas.targetLine = ``;
+ renderAndUpdateEvent(subwayDatas);
+}
+
+function onLineSelectHandler() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let targetLine = event.target.innerText;
+
+ subwayDatas.targetLine = targetLine;
+ localStorage.setItem("subwayDatas", JSON.stringify(subwayDatas));
+ renderAndUpdateEvent(subwayDatas);
+}
+
+function onAddSectionHandler() {
+ let station = validateSection(document.getElementById(SECTION_STATION_SELECTOR).value);
+ let order = validateOrder(document.getElementById(SECTION_ORDER_INPUT).value);
+
+ if (station && order) {
+ addSection(station, order);
+ }
+}
+
+function addSection(station, order) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let targetLine = subwayDatas.targetLine;
+ let targetLineIdx = subwayDatas.lines.findIndex((line) => line.name === targetLine);
+
+ subwayDatas.lines[targetLineIdx].stops.splice(order, 0, station);
+ subwayDatas.subwayStations.forEach((addedStation, idx) => {
+ if (station === addedStation.name) {
+ subwayDatas.subwayStations[idx].line.push(subwayDatas.targetLine);
+ }
+ });
+
+ localStorage.setItem("subwayDatas", JSON.stringify(subwayDatas));
+ renderAndUpdateEvent(subwayDatas);
+}
+
+function onSectionDeleteHandler() {
+ let deleteTargetIdx = event.target.parentNode.parentNode.childNodes[1].outerText;
+ let deleteTarget = event.target.parentNode.parentNode.childNodes[3].outerText;
+ let deleteConfirmed = validateSectionDelete();
+
+ if (deleteConfirmed === true) {
+ sectionDelete(deleteTarget, deleteTargetIdx);
+ }
+}
+
+function sectionDelete(deleteTarget, deleteTargetIdx) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let targetLineIdx = subwayDatas.lines.findIndex((line) => line.name === subwayDatas.targetLine);
+
+ subwayDatas.lines[targetLineIdx].stops.splice(deleteTargetIdx, 1);
+ subwayDatas.subwayStations.forEach((station) => {
+ if (station.name === deleteTarget) {
+ station.line.splice(subwayDatas.subwayStations.indexOf(subwayDatas.targetLine), 1);
+ }
+ });
+
+ localStorage.setItem("subwayDatas", JSON.stringify(subwayDatas));
+ renderAndUpdateEvent(subwayDatas);
+}
+
+function renderAndUpdateEvent(subwayDatas) {
+ render(app("section", subwayDatas));
+ updateEventToBtns();
+}
+
+function updateEventToBtns() {
+ let sectionBtn = document.getElementById(SECTION_ADD_BUTTON);
+ sectionBtn && document.getElementById(SECTION_ADD_BUTTON).addEventListener("click", onAddSectionHandler);
+
+ let lineBtns = document.getElementsByClassName(SECTION_LINE_MENU_BUTTON);
+ for (let i = 0; i < lineBtns.length; i++) {
+ let eachBtn = lineBtns[i];
+ eachBtn.addEventListener("click", onLineSelectHandler);
+ }
+
+ let deleteBtns = document.getElementsByClassName(SECTION_DELETE_BUTTON);
+ for (let i = 0; i < deleteBtns.length; i++) {
+ deleteBtns[i].addEventListener("click", onSectionDeleteHandler);
+ }
+}
+
+export { onSectionHandler };
diff --git a/src/managers/handlers/stationHandlers.js b/src/managers/handlers/stationHandlers.js
new file mode 100644
index 000000000..44914fb06
--- /dev/null
+++ b/src/managers/handlers/stationHandlers.js
@@ -0,0 +1,50 @@
+import render from "../render.js";
+import app from "../../components/app.js";
+import { validateInput, validateStationDelete } from "../validation/validation.js";
+import { Station } from "../../objects/objects.js";
+import { STATION_NAME_INPUT, STATION_ADD_BUTTON, STATION_DELETE_BUTTON } from "../../constants/tag.js";
+
+function renderAndUpdateEvent(subwayDatas) {
+ render(app("station", subwayDatas));
+ updateEvent();
+}
+function onStationHandler() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+
+ renderAndUpdateEvent(subwayDatas);
+}
+
+function onAddStationHandler() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let stationName = validateInput(document.getElementById(STATION_NAME_INPUT).value, STATION_NAME_INPUT);
+
+ if (stationName !== "") {
+ let subwayStations = new Station(stationName);
+ subwayDatas.subwayStations.push(subwayStations);
+ localStorage.setItem("subwayDatas", JSON.stringify(subwayDatas));
+ renderAndUpdateEvent(subwayDatas);
+ }
+}
+
+function updateEvent() {
+ document.getElementById(STATION_ADD_BUTTON).addEventListener("click", onAddStationHandler);
+
+ let deleteBtns = document.getElementsByClassName(STATION_DELETE_BUTTON);
+ for (let i = 0; i < deleteBtns.length; i++) {
+ deleteBtns[i].addEventListener("click", onDeleteStationHandler);
+ }
+}
+
+function onDeleteStationHandler() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let deleteTarget = validateStationDelete(event.target.parentNode.parentNode.childNodes[1].outerText);
+
+ if (deleteTarget !== "") {
+ let deleteTargetIdx = subwayDatas.subwayStations.findIndex((station) => station.name === deleteTarget);
+ subwayDatas.subwayStations.splice(deleteTargetIdx, 1);
+ localStorage.setItem("subwayDatas", JSON.stringify(subwayDatas));
+ renderAndUpdateEvent(subwayDatas);
+ }
+}
+
+export { onStationHandler };
diff --git a/src/managers/init.js b/src/managers/init.js
new file mode 100644
index 000000000..04eb6b8a4
--- /dev/null
+++ b/src/managers/init.js
@@ -0,0 +1,30 @@
+import { onStationHandler } from "./handlers/stationHandlers.js";
+import { onLineHandler } from "./handlers/lineHandlers.js";
+import { onSectionHandler } from "./handlers/sectionHandler.js";
+import { onMapPrintHandler } from "./handlers/mapPrintHandler.js";
+import { STATION_MANAGER_BUTTON, LINE_MANAGER_BUTTON, SECTION_MANAGER_BUTTON, MAP_PRINT_MANAGER_BUTTON } from "../constants/tag.js";
+
+function initHTML() {
+ const buttonBox = document.createElement("div");
+
+ buttonBox.innerHTML = `
+
+
+
+ `;
+ document.body.append(buttonBox);
+
+ const mainBox = document.createElement("div");
+
+ mainBox.id = "main-box";
+ document.body.append(mainBox);
+}
+
+function addEventToMainBtns() {
+ document.getElementById(STATION_MANAGER_BUTTON).addEventListener("click", onStationHandler);
+ document.getElementById(LINE_MANAGER_BUTTON).addEventListener("click", onLineHandler);
+ document.getElementById(SECTION_MANAGER_BUTTON).addEventListener("click", onSectionHandler);
+ document.getElementById(MAP_PRINT_MANAGER_BUTTON).addEventListener("click", onMapPrintHandler);
+}
+
+export { initHTML, addEventToMainBtns };
diff --git a/src/managers/render.js b/src/managers/render.js
new file mode 100644
index 000000000..58136fdc4
--- /dev/null
+++ b/src/managers/render.js
@@ -0,0 +1,3 @@
+export default function render(app) {
+ document.getElementById("main-box").innerHTML = app;
+}
diff --git a/src/managers/validation/alert.js b/src/managers/validation/alert.js
new file mode 100644
index 000000000..00c6f5463
--- /dev/null
+++ b/src/managers/validation/alert.js
@@ -0,0 +1,139 @@
+function stationNameAlert(inputValue) {
+ return uniqueStationNameAlert(inputValue) || spaceAlert(inputValue) || underTwoCharacterAlert(inputValue);
+}
+
+function uniqueStationNameAlert(inputValue) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let alertMsg = "";
+
+ subwayDatas.subwayStations.map((station) => {
+ if (station.name === inputValue) {
+ alertMsg = "μ€λ³΅λ μ μ΄λ¦μ μ
λ ₯νμ
¨μ΅λλ€.";
+ }
+ });
+
+ return alertMsg;
+}
+
+function spaceAlert(inputValue) {
+ let alertMsg = "";
+
+ if (inputValue === "") {
+ alertMsg = "곡백μ μ
λ ₯νμ
¨μ΅λλ€.";
+ }
+
+ return alertMsg;
+}
+
+function underTwoCharacterAlert(inputValue) {
+ let alertMsg = "";
+
+ if (inputValue.length < 2) {
+ alertMsg = "2κΈμ μ΄μμΌλ‘ μ
λ ₯ν΄μ£ΌμΈμ.";
+ }
+
+ return alertMsg;
+}
+
+function stationDeleteAlert(deleteTarget) {
+ return inlineAlert(deleteTarget);
+}
+
+function inlineAlert(deleteTarget) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let alertMsg = "";
+
+ subwayDatas.subwayStations.forEach((station, idx) => {
+ if (station.name === deleteTarget && subwayDatas.subwayStations[idx].line.length >= 1) {
+ alertMsg = "λ
Έμ μ ν¬ν¨λ μμ μμ ν μ μμ΅λλ€.";
+ }
+ });
+
+ return alertMsg;
+}
+
+function lineNameAlert(inputValue) {
+ return ununiqueLineNameAlert(inputValue) || spaceAlert(inputValue);
+}
+
+function ununiqueLineNameAlert(inputValue) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let alertMsg = "";
+
+ subwayDatas.lines.forEach((line) => {
+ if (line.name === inputValue) {
+ alertMsg = "μ€λ³΅λ λ
Έμ μ΄λ¦μ μ
λ ₯νμ
¨μ΅λλ€.";
+ }
+ });
+
+ return alertMsg;
+}
+
+function startAndEndStationAlert(startAndEndStations) {
+ return unUniqueLineAlert(startAndEndStations) || sameStartAndEndStationAlert(startAndEndStations);
+}
+
+function unUniqueLineAlert(startAndEndStations) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let alertMsg = "";
+
+ subwayDatas.lines.forEach((line) => {
+ if (line.stops[0] === startAndEndStations[0] && line.stops[line.stops.length - 1] === startAndEndStations[1]) {
+ alertMsg = "μν, νν μ’
μ μμ΄ μ€λ³΅λλ λ
Έμ μ΄ μ΄λ―Έ μ‘΄μ¬ν©λλ€.";
+ }
+ });
+
+ return alertMsg;
+}
+
+function sameStartAndEndStationAlert(startAndEndStations) {
+ let alertMsg = "";
+
+ if (startAndEndStations[0] === startAndEndStations[1]) {
+ alertMsg = "μν μ’
μ κ³Ό νν μ’
μ μΌλ‘ λμΌν μμ μ ννμ
¨μ΅λλ€.";
+ }
+
+ return alertMsg;
+}
+
+function sectionDeleteAlert() {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let alertMsg = "";
+ let targetLineIdx = subwayDatas.lines.findIndex((line) => line.name === subwayDatas.targetLine);
+
+ if (subwayDatas.lines[targetLineIdx].stops.length <= 2) {
+ alertMsg = "λ
Έμ μ ν¬ν¨λ μμ΄ 2κ° μ΄νμΌ λμλ μμ ν μ μμ΅λλ€.";
+ }
+
+ return alertMsg;
+}
+
+function orderAlert(order) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let alertMsg = "";
+ let targetLineIdx = subwayDatas.lines.findIndex((line) => line.name === subwayDatas.targetLine);
+
+ if (isNaN(Number(order))) {
+ alertMsg = "μ«μλ§ μ
λ ₯ κ°λ₯ν©λλ€.";
+ } else if (0 > order) {
+ alertMsg = "μμλ§ μ
λ ₯ κ°λ₯ν©λλ€.";
+ } else if (order <= 0 || subwayDatas.lines[targetLineIdx].stops.length <= order) {
+ alertMsg = "μκ³Ό μ μ¬μ΄μλ§ κ΅¬κ° λ±λ‘μ΄ κ°λ₯ν©λλ€.";
+ }
+
+ return alertMsg;
+}
+
+function sectionAlert(stationName) {
+ let subwayDatas = JSON.parse(localStorage.getItem("subwayDatas"));
+ let alertMsg = "";
+ let targetLineIdx = subwayDatas.lines.findIndex((line) => line.name === subwayDatas.targetLine);
+
+ if (subwayDatas.lines[targetLineIdx].stops.indexOf(stationName) !== -1) {
+ alertMsg = "μ΄λ―Έ ꡬκ°μ λ±λ‘λ μμ
λλ€.";
+ }
+
+ return alertMsg;
+}
+
+export { stationNameAlert, stationDeleteAlert, lineNameAlert, startAndEndStationAlert, sectionDeleteAlert, orderAlert, sectionAlert };
diff --git a/src/managers/validation/validation.js b/src/managers/validation/validation.js
new file mode 100644
index 000000000..c277bd9bd
--- /dev/null
+++ b/src/managers/validation/validation.js
@@ -0,0 +1,78 @@
+import { stationNameAlert, stationDeleteAlert, lineNameAlert, startAndEndStationAlert, sectionDeleteAlert, orderAlert, sectionAlert } from "./alert.js";
+import { STATION_NAME_INPUT } from "../../constants/tag.js";
+
+function validateInput(input, inputTagID) {
+ let alertMsg = "";
+
+ inputTagID === STATION_NAME_INPUT ? (alertMsg = stationNameAlert(input)) : (alertMsg = lineNameAlert(input));
+
+ if (alertMsg) {
+ alert(alertMsg);
+ document.getElementById(inputTagID).focus();
+
+ return "";
+ }
+
+ return input;
+}
+
+function validateStationDelete(deleteTarget) {
+ let alertMsg = stationDeleteAlert(deleteTarget);
+
+ if (alertMsg !== "") {
+ alert(alertMsg);
+
+ return "";
+ }
+ return deleteTarget;
+}
+
+function validateSectionDelete() {
+ let alertMsg = sectionDeleteAlert();
+
+ if (alertMsg !== "") {
+ alert(alertMsg);
+
+ return "";
+ }
+
+ return confirm("μ λ§λ‘ λ
Έμ μμ μ κ±°νκ² μ΅λκΉ?");
+}
+
+function validateStartAndEndStations(startAndEndStations) {
+ let alertMsg = startAndEndStationAlert(startAndEndStations);
+
+ if (alertMsg !== "") {
+ alert(alertMsg);
+
+ return "";
+ }
+
+ return startAndEndStations;
+}
+
+function validateOrder(order) {
+ let alertMsg = orderAlert(order);
+
+ if (alertMsg !== "") {
+ alert(alertMsg);
+
+ return "";
+ }
+
+ return order;
+}
+
+function validateSection(stationName) {
+ let alertMsg = sectionAlert(stationName);
+
+ if (alertMsg !== "") {
+ alert(alertMsg);
+
+ return "";
+ }
+
+ return stationName;
+}
+
+export { validateInput, validateStationDelete, validateStartAndEndStations, validateSectionDelete, validateOrder, validateSection };
diff --git a/src/objects/objects.js b/src/objects/objects.js
new file mode 100644
index 000000000..4116878da
--- /dev/null
+++ b/src/objects/objects.js
@@ -0,0 +1,11 @@
+function Line(name, endStops) {
+ this.name = name;
+ this.stops = [endStops[0], endStops[1]];
+}
+
+function Station(name) {
+ this.name = name;
+ this.line = [];
+}
+
+export { Line, Station };