diff --git a/README.md b/README.md
index e97a1d649..eb2df86ff 100644
--- a/README.md
+++ b/README.md
@@ -1,114 +1,129 @@
# π μ§νμ² λ
Έμ λ λ―Έμ
+## URL
+
+### https://yungo1846.github.io/javascript-subway-map-precourse/
+
+## λλ ν 리 ꡬ쑰
+
+```bash
+β index.html
+β LICENSE
+β README.md
+β
+ββimages
+β
+ββsrc
+ β index.js
+ β
+ ββcommon
+ β alertMessage.js
+ β checkInput.js
+ β clearInput.js
+ β constant.js
+ β
+ ββevent
+ β β menuEvent.js
+ β β
+ β ββcommon
+ β β checkStorageItem.js
+ β β
+ β ββline
+ β β addLineEvent.js
+ β β delLineEvent.js
+ β β
+ β ββsection
+ β β addSectionEvent.js
+ β β chooseLineEvent.js
+ β β delSectionEvent.js
+ β β
+ β ββstation
+ β addStationEvent.js
+ β delStationEvent.js
+ β
+ ββrender
+ render.js
+ renderLine.js
+ renderMapPrint.js
+ renderSection.js
+ renderStation.js
+```
+
+- common: μμ£Ό μ¬μ©λλ μμ, ν¨μ λ±μ λͺ¨μλμ λλ ν 리
+- event: eventHandleμ νμν λ‘μ§μ λͺ¨μλμ λλ ν 리
+- render: μ¬μ©μμκ² λ³΄μ΄λ νλ©΄μ ꡬμ±νλ λ‘μ§μ λͺ¨μλμ λλ ν 리
+
## π κΈ°λ₯ μꡬμ¬ν
### μ§νμ² μ κ΄λ ¨ κΈ°λ₯
-- μ§νμ² μμ λ±λ‘νκ³ μμ ν μ μλ€. (λ¨, λ
Έμ μ λ±λ‘λ μμ μμ ν μ μλ€)
-- μ€λ³΅λ μ§νμ² μ μ΄λ¦μ΄ λ±λ‘λ μ μλ€.
-- μ§νμ² μμ 2κΈμ μ΄μμ΄μ΄μΌ νλ€.
-- μ§νμ² μμ λͺ©λ‘μ μ‘°νν μ μλ€.
+
+- μ§νμ² μμ λ±λ‘νκ³ μμ ν μ μλ€. (λ¨, λ
Έμ μ λ±λ‘λ μμ μμ ν μ μλ€) (μλ£)
+- μ€λ³΅λ μ§νμ² μ μ΄λ¦μ΄ λ±λ‘λ μ μλ€. (μλ£)
+- μ§νμ² μμ 2κΈμ μ΄μμ΄μ΄μΌ νλ€. (μλ£)
+- μ§νμ² μμ λͺ©λ‘μ μ‘°νν μ μλ€. (μλ£)
### μ§νμ² λ
Έμ κ΄λ ¨ κΈ°λ₯
-- μ§νμ² λ
Έμ μ λ±λ‘νκ³ μμ ν μ μλ€.
-- μ€λ³΅λ μ§νμ² λ
Έμ μ΄λ¦μ΄ λ±λ‘λ μ μλ€.
-- λ
Έμ λ±λ‘ μ μν μ’
μ μκ³Ό νν μ’
μ μμ μ
λ ₯λ°λλ€.
-- μ§νμ² λ
Έμ μ λͺ©λ‘μ μ‘°νν μ μλ€.
+
+- μ§νμ² λ
Έμ μ λ±λ‘νκ³ μμ ν μ μλ€. (μλ£)
+- μ€λ³΅λ μ§νμ² λ
Έμ μ΄λ¦μ΄ λ±λ‘λ μ μλ€. (μλ£)
+- λ
Έμ μ΄λ¦μ 2κΈμ μ΄μμ΄μ΄μΌ νλ€. (μλ£)
+- λ
Έμ λ±λ‘ μ μν μ’
μ μκ³Ό νν μ’
μ μμ μ
λ ₯λ°λλ€. (μλ£)
+- μ§νμ² λ
Έμ μ λͺ©λ‘μ μ‘°νν μ μλ€. (μλ£)
+- λ
Έμ μμ κ°λκΈΈμ μκΈΈ μ μλ€. (μνμ νΉμ ννμ μ΄ λ€λ₯Έ λ
Έμ κ³Ό κ²ΉμΉλ κ²½μ°λ κ°λκΈΈλ‘ μΈμ ) (μλ£)
### μ§νμ² κ΅¬κ° μΆκ° κΈ°λ₯
-- μ§νμ² λ
Έμ μ ꡬκ°μ μΆκ°νλ κΈ°λ₯μ λ
Έμ μ μμ μΆκ°νλ κΈ°λ₯μ΄λΌκ³ λ ν μ μλ€.
- - μκ³Ό μμ¬μ΄λ₯Ό ꡬκ°μ΄λΌ νκ³ μ΄ κ΅¬κ°λ€μ λͺ¨μμ΄ λ
Έμ μ΄λ€.
-- νλμ μμ μ¬λ¬κ°μ λ
Έμ μ μΆκ°λ μ μλ€.
-- μκ³Ό μ μ¬μ΄μ μλ‘μ΄ μμ΄ μΆκ° λ μ μλ€.
-- λ
Έμ μμ κ°λκΈΈμ μκΈΈ μ μλ€.
+
+- μ§νμ² λ
Έμ μ ꡬκ°μ μΆκ°νλ κΈ°λ₯μ λ
Έμ μ μμ μΆκ°νλ κΈ°λ₯μ΄λΌκ³ λ ν μ μλ€. (μλ£)
+ - μκ³Ό μμ¬μ΄λ₯Ό ꡬκ°μ΄λΌ νκ³ μ΄ κ΅¬κ°λ€μ λͺ¨μμ΄ λ
Έμ μ΄λ€.
+- νλμ μμ μ¬λ¬κ°μ λ
Έμ μ μΆκ°λ μ μλ€. (μλ£)
+- μκ³Ό μ μ¬μ΄μ μλ‘μ΄ μμ΄ μΆκ° λ μ μλ€. (μλ£)
+- λ
Έμ μμ κ°λκΈΈμ μκΈΈ μ μλ€. (μνμ νΉμ ννμ μ΄ λ€λ₯Έ λ
Έμ κ³Ό κ²ΉμΉλ κ²½μ°λ κ°λκΈΈλ‘ μΈμ ) (μλ£)
+- κ΅¬κ° μμλ μ΄λ€ μ«μλ μ
λ ₯ λ°μ μ μλ€. (μλ£)
+ - 0λ³΄λ€ μμ μ«μλ₯Ό μ
λ ₯ λ°μ κ²½μ°, μνμ (0λ² μμ)μ μΆκ°νλ€.
+ - ν΄λΉ λ
Έμ ννμ μμ λ³΄λ€ ν° μ«μλ₯Ό μ
λ ₯ λ°μ κ²½μ°, ννμ μ μΆκ°νλ€.
### μ§νμ² κ΅¬κ° μμ κΈ°λ₯
-- λ
Έμ μ λ±λ‘λ μμ μ κ±°ν μ μλ€.
-- μ’
μ μ μ κ±°ν κ²½μ° λ€μ μμ΄ μ’
μ μ΄ λλ€.
-- λ
Έμ μ ν¬ν¨λ μμ΄ λκ° μ΄νμΌ λλ μμ μ κ±°ν μ μλ€.
+
+- λ
Έμ μ λ±λ‘λ μμ μ κ±°ν μ μλ€. (μλ£)
+- μ’
μ μ μ κ±°ν κ²½μ° λ€μ μμ΄ μ’
μ μ΄ λλ€. (μλ£)
+- λ
Έμ μ ν¬ν¨λ μμ΄ λκ° μ΄νμΌ λλ μμ μ κ±°ν μ μλ€. (μλ£)
### μ§νμ² λ
Έμ μ λ±λ‘λ μ μ‘°ν κΈ°λ₯
-- λ
Έμ μ μν μ’
μ λΆν° νν μ’
μ κΉμ§ μ°κ²°λ μμλλ‘ μ λͺ©λ‘μ μ‘°νν μ μλ€.
+
+- λ
Έμ μ μν μ’
μ λΆν° νν μ’
μ κΉμ§ μ°κ²°λ μμλλ‘ μ λͺ©λ‘μ μ‘°νν μ μλ€. (μλ£)
+
+## π€ κ³ λ―Όμ¬ν
+
+- μ¬μ©μ localStorageμ λ€λ₯Έ νλ‘κ·Έλ¨μμ μ¬μ©νκ³ μλ stationsμ linesκ° μλ κ²½μ°, μ΄λ»κ² μ²λ¦¬ν΄μΌνλκ°?
+
+ ν보1. localStorageμ stationsμ linesλ₯Ό μ΄κΈ°ν
+
+ => λ€λ₯Έ νλ‘κ·Έλ¨μμ λ¬Έμ κ° λ°μν μ μμ. λν μ΄κΈ°ν μ, λ§€λ² νμ΄μ§λ₯Ό μλ‘κ³ μΉ¨ ν λλ§λ€ μ΄κΈ°νκ° λ°μνκΈ° λλ¬Έμ localStorage μ¬μ©μ΄μ κ° μ¬λΌμ§.
+
+ ν보2. λ€λ₯Έ μ¬λλ€μ΄ μ λ μ¬μ©νμ§ μμ κ² κ°μ λ€μ΄λ°μ μ¬μ©νλ€.
+
+ => κ°μ₯ μ¬μ΄ λ°©λ²μ΄μ§λ§ μ½λμ κ°λ
μ±μ μν΄ μ¬κΈ°μλ μ¬μ©νμ§ μμλ€.
## π» νλ‘κ·Έλ¨ μ€ν κ²°κ³Ό
### μκ΄λ¦¬
+
### λ
Έμ κ΄λ¦¬
+
### ꡬκ°κ΄λ¦¬
+
### λ
Έμ λ μΆλ ₯
-
-
-
-## β
νλ‘κ·Έλλ° μꡬμ¬ν
-
-### λ©λ΄ λ²νΌ
-- μ κ΄λ¦¬ 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κ°μ κ°μ§λ€.
-- μ§νμ² λ
Έμ μ μΆκ°νλ button νκ·Έλ `#line-add-button` idκ°μ κ°μ§λ€.
-- μ§νμ² λ
Έμ μ μμ νλ button νκ·Έλ `.line-delete-button` classκ°μ κ°μ§λ€.
-
-### μ§νμ² κ΅¬κ° μΆκ° κΈ°λ₯
-- μ§νμ² λ
Έμ μ μ ννλ button νκ·Έλ `.section-line-menu-button` classκ°μ κ°μ§λ€.
-- μ§νμ² κ΅¬κ°μ μ€μ ν μ select νκ·Έλ `#section-station-selector` idκ°μ κ°μ§λ€.
-- μ§νμ² κ΅¬κ°μ μμλ₯Ό μ
λ ₯νλ input νκ·Έλ `#section-order-input` idκ°μ κ°μ§λ€.
-- μ§νμ² κ΅¬κ°μ λ±λ‘νλ button νκ·Έλ `#section-add-button` idκ°μ κ°μ§λ€.
-- μ§νμ² κ΅¬κ°μ μ κ±°νλ button νκ·Έλ `.section-delete-button` classκ°μ κ°μ§λ€.
-
-### μ§νμ² λ
Έμ λ μΆλ ₯ κΈ°λ₯
-- μ§νμ² λ
Έμ λ μΆλ ₯ λ²νΌμ λλ₯΄λ©΄ `
` νκ·Έλ₯Ό λ§λ€κ³ ν΄λΉ νκ·Έ λ΄λΆμ λ
Έμ λλ₯Ό μΆλ ₯νλ€.
-
-### κΈ°μ‘΄ μꡬμ¬ν
-
-- μ¬μ©μκ° μλͺ»λ μ
λ ₯ κ°μ μμ±ν κ²½μ° `alert`μ μ΄μ©ν΄ λ©μμ§λ₯Ό 보μ¬μ£Όκ³ , μ¬μ
λ ₯ν μ μκ² νλ€.
-- μΈλΆ λΌμ΄λΈλ¬λ¦¬(jQuery, Lodash λ±)λ₯Ό μ¬μ©νμ§ μκ³ , μμ Vanilla JSλ‘λ§ κ΅¬ννλ€.
-- **μλ°μ€ν¬λ¦½νΈ μ½λ 컨벀μ
μ μ§ν€λ©΄μ νλ‘κ·Έλλ°** νλ€
- - [https://google.github.io/styleguide/jsguide.html](https://google.github.io/styleguide/jsguide.html)
- - [https://ui.toast.com/fe-guide/ko_CODING-CONVENSION/](https://ui.toast.com/fe-guide/ko_CODING-CONVENTION)
-- **indent(μΈλ΄νΈ, λ€μ¬μ°κΈ°) depthλ₯Ό 3μ΄ λμ§ μλλ‘ κ΅¬ννλ€. 2κΉμ§λ§ νμ©**νλ€.
- - μλ₯Ό λ€μ΄ whileλ¬Έ μμ ifλ¬Έμ΄ μμΌλ©΄ λ€μ¬μ°κΈ°λ 2μ΄λ€.
- - ννΈ: indent(μΈλ΄νΈ, λ€μ¬μ°κΈ°) depthλ₯Ό μ€μ΄λ μ’μ λ°©λ²μ ν¨μ(λλ λ©μλ)λ₯Ό λΆλ¦¬νλ©΄ λλ€.
-- **ν¨μ(λλ λ©μλ)μ κΈΈμ΄κ° 15λΌμΈμ λμ΄κ°μ§ μλλ‘ κ΅¬ννλ€.**
- - ν¨μ(λλ λ©μλ)κ° ν κ°μ§ μΌλ§ μ νλλ‘ κ΅¬ννλ€.
-- λ³μ μ μΈμ `var` λ₯Ό μ¬μ©νμ§ μλλ€. `const` μ `let` μ μ¬μ©νλ€.
- - [const](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/const)
- - [let](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/let)
-- `import` λ¬Έμ μ΄μ©ν΄ μ€ν¬λ¦½νΈλ₯Ό λͺ¨λννκ³ λΆλ¬μ¬ μ μκ² λ§λ λ€.
- - [https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/import](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/import)
-- `template literal`μ μ΄μ©ν΄ λ°μ΄ν°μ html stringμ κ°λ
μ± μ’κ² νννλ€.
- - [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 νκ·Έμ μ, λ
Έμ , ꡬκ°μ μ μΌν λ°μ΄ν° κ°λ€μ κ΄λ¦¬νλ€.
-- [localStorage](https://developer.mozilla.org/ko/docs/Web/API/Window/localStorage)λ₯Ό μ΄μ©νμ¬, μλ‘κ³ μΉ¨νλλΌλ κ°μ₯ μ΅κ·Όμ μμ
ν μ 보λ€μ λΆλ¬μ¬ μ μλλ‘ νλ€.
-
-
-## π λ―Έμ
μ μ₯μ λ° μ§ν μꡬμ¬ν
-
-- λ―Έμ
μ [https://github.com/woowacourse/javascript-subway-map-precours](https://github.com/woowacourse/javascript-subway-map-precourse) μ μ₯μλ₯Ό fork/cloneν΄ μμνλ€.
-- **κΈ°λ₯μ ꡬννκΈ° μ μ javascript-subway-precourse/docs/README.md νμΌμ ꡬνν κΈ°λ₯ λͺ©λ‘**μ μ λ¦¬ν΄ μΆκ°νλ€.
-- **gitμ commit λ¨μλ μ λ¨κ³μμ README.md νμΌμ μ 리ν κΈ°λ₯ λͺ©λ‘ λ¨μλ‘ μΆκ°**νλ€.
-- [ν리μ½μ€ κ³Όμ μ μΆ](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) λ¬Έμ μ μ°¨λ₯Ό λ°λΌ λ―Έμ
μ μ μΆνλ€.
+
diff --git a/index.html b/index.html
index fc99deac2..7529e6f1c 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,49 @@
-
π μ§νμ² λ
Έμ λ κ΄λ¦¬
+ π μ§νμ² λ
Έμ λ κ΄λ¦¬
+
+
+
+
+
μ μ΄λ¦
+
+
+
π μ§νμ² μ λͺ©λ‘
+
+
+
+
λ
Έμ μ΄λ¦
+
+
+ μν μ’
μ
+
+
+
+ νν μ’
μ
+
+
+
+
π μ§νμ² λ
Έμ λͺ©λ‘
+
+
+
+
ꡬκ°μ μμ ν λ
Έμ μ μ νν΄μ£ΌμΈμ.
+
+
+
+
+
+
diff --git a/src/common/alertMessage.js b/src/common/alertMessage.js
new file mode 100644
index 000000000..403ba1ad4
--- /dev/null
+++ b/src/common/alertMessage.js
@@ -0,0 +1,14 @@
+import { constant } from "./constant.js";
+
+export const alertMessage = {
+ SHORT_LENGTH_ERROR: `μ΅μ ${constant.minLength} κΈμ μ΄μ μ
λ ₯ν΄μΌ ν©λλ€.`,
+ ORDERING_INPUT_NOTHING_ERROR: `μμλ₯Ό μ
λ ₯ν΄μ£ΌμΈμ`,
+ DELETE_CHECK_MESSAGE: "μ λ§λ‘ μμ νμκ² μ΅λκΉ?",
+ DELETE_STATION_ON_LINE_MESSAGE: "μ΄ μμ νμ¬ λ
Έμ μ λ±λ‘λμ΄ μμ΄ μμ κ° λΆκ°λ₯ν©λλ€.",
+ DELETE_STATIONS_ON_LINE_SHORTAGE_MESSAGE: `μ νν λ
Έμ μ μμ΄ ${constant.minStations}κ° μ΄νμΈ κ²½μ°μλ μμ ν μ μμ΅λλ€.`,
+ SAME_DESTINATION_ERROR: `μνκ³Ό ννμ΄ κ°μ΅λλ€. λ€μ μ
λ ₯ν΄μ£ΌμΈμ.`,
+ SAME_LINE_EXIST_ERROR: "μ΄λ―Έ κ°μ μ΄λ¦μ κ°μ§ λ
Έμ μ΄ μμ΅λλ€.",
+ SAME_STATION_EXIST_ERROR: "μ΄λ―Έ κ°μ μ΄λ¦μ κ°μ§ μμ΄ μμ΅λλ€.",
+ SAME_SECTION_EXIST_ERROR: "μ΄λ―Έ κ°μ ꡬκ°μ΄ λ±λ‘λμ΄ μμ΅λλ€.",
+ TRANSFER_STATION_MESSAGE: `μμ λ€λ₯Έ λ
Έμ μ λ±λ‘λμ΄ μμ΄ μΆκ°ν μ μμ΅λλ€.\n "4. μ§νμ² λ
Έμ λ μΆλ ₯"μ ν΄λ¦νμ¬ λ
Έμ μ νμΈν΄μ£ΌμΈμ.\nπ κ΅μ°¨μμ΄ μλλ‘ νκΈ° μν¨μ
λλ€. π`,
+};
diff --git a/src/common/checkInput.js b/src/common/checkInput.js
new file mode 100644
index 000000000..6a3873afe
--- /dev/null
+++ b/src/common/checkInput.js
@@ -0,0 +1,112 @@
+import { constant } from "./constant.js";
+
+export function isSatisfyLength(len) {
+ let result = true;
+ if (String(len).length < constant.minLength) {
+ result = false;
+ }
+
+ return result;
+}
+
+export function isSameDestination(start, end) {
+ let result = true;
+ if (start !== end) {
+ result = false;
+ }
+
+ return result;
+}
+
+export function isStationAlreadyExist(stations, name) {
+ let result = false;
+ for (let i = 0; i < localStorage.stations.length; i++) {
+ if (name === stations[i]) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+}
+
+export function isLineAlreadyExist(lines, name) {
+ let result = false;
+ for (let i = 0; i < lines.length; i++) {
+ if (name === lines[i].name) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+}
+
+export function isSectionAlreadyExist(sections, name) {
+ let result = false;
+ for (let i = 0; i < sections.length; i++) {
+ if (name === sections[i]) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+}
+
+function _isStationOnLine(sections, name) {
+ let result = false;
+ for (let i = 0; i < sections.length; i++) {
+ if (name === sections[i]) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+}
+
+export function isStationOnLine(lines, name) {
+ let result = false;
+ for (let i = 0; i < lines.length; i++) {
+ if (_isStationOnLine(lines[i].sections, name)) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+}
+
+export function isSatisfyMinNumOfStations(line) {
+ let result = false;
+ if (line.sections.length > constant.minStations) {
+ result = true;
+ }
+
+ return result;
+}
+
+export function _isTransferStation(sections, station) {
+ let result = false;
+ for (let i = 0; i < sections.length; i++) {
+ if (station === sections[i]) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+}
+
+export function isTransferStation(lines, station) {
+ let result = false;
+ for (let i = 0; i < lines.length; i++) {
+ if (_isTransferStation(lines[i].sections, station)) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+}
diff --git a/src/common/clearInput.js b/src/common/clearInput.js
new file mode 100644
index 000000000..f42c5f15e
--- /dev/null
+++ b/src/common/clearInput.js
@@ -0,0 +1,4 @@
+export function clearInput() {
+ const $input = document.querySelectorAll("input");
+ $input.forEach((input) => (input.value = ""));
+}
diff --git a/src/common/constant.js b/src/common/constant.js
new file mode 100644
index 000000000..3b75617b1
--- /dev/null
+++ b/src/common/constant.js
@@ -0,0 +1,4 @@
+export const constant = {
+ minLength: 2,
+ minStations: 2,
+};
diff --git a/src/event/common/checkStorageItem.js b/src/event/common/checkStorageItem.js
new file mode 100644
index 000000000..16b8caf40
--- /dev/null
+++ b/src/event/common/checkStorageItem.js
@@ -0,0 +1,25 @@
+export default function checkLocalStorageItem() {
+ if (localStorage.stations === undefined) {
+ localStorage.stations = JSON.stringify([
+ "μΈμ²",
+ "λμΈμ²",
+ "λμ",
+ "μμμ°",
+ "μ¬λΉ",
+ "μμ²",
+ "μ λλ¦Ό",
+ "λν",
+ "μ€κΈ",
+ "μ€μ΄λ",
+ "λΉκ³ κ°",
+ ]);
+ }
+
+ if (localStorage.lines === undefined) {
+ localStorage.lines = JSON.stringify([
+ { name: "1νΈμ ", sections: ["μΈμ²", "μμμ°"] },
+ { name: "2νΈμ ", sections: ["μμ²", "μ λλ¦Ό"] },
+ { name: "3νΈμ ", sections: ["λν", "μ€κΈ"] },
+ ]);
+ }
+}
diff --git a/src/event/line/addLineEvent.js b/src/event/line/addLineEvent.js
new file mode 100644
index 000000000..da24c65c8
--- /dev/null
+++ b/src/event/line/addLineEvent.js
@@ -0,0 +1,46 @@
+import renderLine from "../../render/renderLine.js";
+import {
+ isSatisfyLength,
+ isSameDestination,
+ isLineAlreadyExist,
+ isTransferStation,
+} from "../../common/checkInput.js";
+import { alertMessage } from "../../common/alertMessage.js";
+import { clearInput } from "../../common/clearInput.js";
+
+function addLine(line, start, end) {
+ let lines = JSON.parse(localStorage.lines);
+ let newLine = { name: String(line), sections: [start, end] };
+
+ lines.push(newLine);
+ localStorage.lines = JSON.stringify(lines);
+
+ renderLine();
+ clearInput();
+}
+
+function checkValidLine() {
+ const line = document.getElementById("line-name-input").value;
+ const start = document.getElementById("line-start-station-selector").value;
+ const end = document.getElementById("line-end-station-selector").value;
+ const lines = JSON.parse(localStorage.lines);
+
+ if (!isSatisfyLength(line)) {
+ return alert(alertMessage.SHORT_LENGTH_ERROR);
+ } else if (isSameDestination(start, end)) {
+ return alert(alertMessage.SAME_DESTINATION_ERROR);
+ } else if (isLineAlreadyExist(lines, line)) {
+ return alert(alertMessage.SAME_LINE_EXIST_ERROR);
+ } else if (isTransferStation(lines, start)) {
+ return alert(`${start}` + alertMessage.TRANSFER_STATION_MESSAGE);
+ } else if (isTransferStation(lines, end)) {
+ return alert(`${end}` + alertMessage.TRANSFER_STATION_MESSAGE);
+ }
+
+ addLine(line, start, end);
+}
+
+export default function addLineEvent() {
+ const $addLineBtn = document.getElementById("line-add-button");
+ $addLineBtn.addEventListener("click", checkValidLine);
+}
diff --git a/src/event/line/delLineEvent.js b/src/event/line/delLineEvent.js
new file mode 100644
index 000000000..95a786add
--- /dev/null
+++ b/src/event/line/delLineEvent.js
@@ -0,0 +1,35 @@
+import renderLine from "../../render/renderLine.js";
+import { alertMessage } from "../../common/alertMessage.js";
+
+function delLine(line) {
+ const lines = JSON.parse(localStorage.lines);
+ for (let i = 0; i < lines.length; i++) {
+ if (line === lines[i].name) {
+ lines.splice(i, 1);
+ }
+ }
+
+ localStorage.lines = JSON.stringify(lines);
+
+ renderLine();
+}
+
+function findDeleteTarget(event) {
+ const $target = event.target;
+ const $lineTable = document.getElementsByClassName("line-table-row");
+ const targetNumber = $target.closest("tr").dataset.number;
+ const line = $lineTable[targetNumber].querySelector("span").innerText;
+
+ delLine(line);
+}
+
+export default function delLineEvent() {
+ const $delLineBtn = document.querySelectorAll(".line-delete-button");
+ $delLineBtn.forEach((button) => {
+ button.addEventListener("click", (event) => {
+ if (confirm(alertMessage.DELETE_CHECK_MESSAGE)) {
+ findDeleteTarget(event);
+ }
+ });
+ });
+}
diff --git a/src/event/menuEvent.js b/src/event/menuEvent.js
new file mode 100644
index 000000000..1e5bbcc23
--- /dev/null
+++ b/src/event/menuEvent.js
@@ -0,0 +1,39 @@
+import render from "../render/render.js";
+import checkLocalStorageItem from "./common/checkStorageItem.js";
+import addStationEvent from "./station/addStationEvent.js";
+import addLineEvent from "./line/addLineEvent.js";
+import chooseLineEvent from "./section/chooseLineEvent.js";
+
+function setHiddenPages() {
+ const $page = document.querySelectorAll(".page");
+ $page.forEach((page) => (page.style.display = "none"));
+}
+
+function changeManagerContainer({ target }) {
+ setHiddenPages();
+
+ if (target.id === "station-manager-button") {
+ document.getElementById("station-page").style.display = "block";
+ addStationEvent();
+ render("station");
+ } else if (target.id === "line-manager-button") {
+ document.getElementById("line-page").style.display = "block";
+ addLineEvent();
+ render("line");
+ } else if (target.id === "section-manager-button") {
+ document.getElementById("section-page").style.display = "block";
+ render("section");
+ chooseLineEvent();
+ } else if (target.id === "map-print-manager-button") {
+ document.getElementById("map-print-page").style.display = "block";
+ render("mapPrint");
+ }
+}
+
+export default function menuEvent() {
+ const $menuButton = document.querySelector(".menu-button");
+
+ checkLocalStorageItem();
+
+ $menuButton.addEventListener("click", changeManagerContainer);
+}
diff --git a/src/event/section/addSectionEvent.js b/src/event/section/addSectionEvent.js
new file mode 100644
index 000000000..aa6082f6e
--- /dev/null
+++ b/src/event/section/addSectionEvent.js
@@ -0,0 +1,52 @@
+import { renderSection } from "../../render/renderSection.js";
+import { isSectionAlreadyExist, isTransferStation } from "../../common/checkInput.js";
+import { alertMessage } from "../../common/alertMessage.js";
+import { clearInput } from "../../common/clearInput.js";
+
+export function getIndexOfLine(lineName) {
+ const lines = JSON.parse(localStorage.lines);
+ let indexOfLine;
+
+ for (let i = 0; i < lines.length; i++) {
+ if (lineName === lines[i].name) {
+ indexOfLine = i;
+ break;
+ }
+ }
+
+ return indexOfLine;
+}
+
+function addSection(indexOfLine, selectedLine, selectedStaion, stationOrder) {
+ let lines = JSON.parse(localStorage.lines);
+ lines[indexOfLine].sections = [
+ ...lines[indexOfLine].sections.slice(0, stationOrder),
+ selectedStaion,
+ ...lines[indexOfLine].sections.slice(stationOrder),
+ ];
+ localStorage.lines = JSON.stringify(lines);
+
+ renderSection(selectedLine);
+ clearInput();
+}
+
+function checkValidSection(selectedLine) {
+ const selectedStation = document.getElementById("section-station-selector").value;
+ const stationOrder = document.getElementById("section-order-input").value;
+ const lines = JSON.parse(localStorage.lines);
+ const indexOfLine = getIndexOfLine(selectedLine);
+ if (isSectionAlreadyExist(lines[indexOfLine].sections, selectedStation)) {
+ return alert(alertMessage.SAME_SECTION_EXIST_ERROR);
+ } else if (stationOrder === "") {
+ return alert(alertMessage.ORDERING_INPUT_NOTHING_ERROR);
+ } else if (isTransferStation(lines, selectedStation)) {
+ return alert(`${selectedStation}` + alertMessage.TRANSFER_STATION_MESSAGE);
+ }
+
+ addSection(indexOfLine, selectedLine, selectedStation, stationOrder);
+}
+
+export default function addSectionEvent(selectedLine) {
+ const $addSectionBtn = document.getElementById("section-add-button");
+ $addSectionBtn.addEventListener("click", () => checkValidSection(selectedLine));
+}
diff --git a/src/event/section/chooseLineEvent.js b/src/event/section/chooseLineEvent.js
new file mode 100644
index 000000000..ddfcb5c74
--- /dev/null
+++ b/src/event/section/chooseLineEvent.js
@@ -0,0 +1,17 @@
+import { renderSection } from "../../render/renderSection.js";
+
+function onClickLine(event) {
+ const $target = event.target;
+ const targetName = $target.dataset.name;
+
+ renderSection(targetName);
+}
+
+export default function addSectionEvent() {
+ const $sectionLineMenuBtns = document.querySelectorAll(".section-line-menu-button");
+ $sectionLineMenuBtns.forEach((button) =>
+ button.addEventListener("click", (event) => {
+ onClickLine(event);
+ })
+ );
+}
diff --git a/src/event/section/delSectionEvent.js b/src/event/section/delSectionEvent.js
new file mode 100644
index 000000000..f7cd90c67
--- /dev/null
+++ b/src/event/section/delSectionEvent.js
@@ -0,0 +1,54 @@
+import { renderSection } from "../../render/renderSection.js";
+import { getIndexOfLine } from "./addSectionEvent.js";
+import { isSatisfyMinNumOfStations } from "../../common/checkInput.js";
+import { alertMessage } from "../../common/alertMessage.js";
+
+function getIndexOfSection(indexOfLine, section) {
+ const lines = JSON.parse(localStorage.lines);
+ let indexOfSection;
+
+ for (let i = 0; i < lines[indexOfLine].sections.length; i++) {
+ if (section === lines[indexOfLine].sections[i]) {
+ indexOfSection = i;
+ break;
+ }
+ }
+
+ return indexOfSection;
+}
+
+function delSection(selectedLine, section) {
+ const indexOfLine = getIndexOfLine(selectedLine);
+ const indexOfSection = getIndexOfSection(indexOfLine, section);
+ let lines = JSON.parse(localStorage.lines);
+
+ if (!isSatisfyMinNumOfStations(lines[indexOfLine])) {
+ return alert(alertMessage.DELETE_STATIONS_ON_LINE_SHORTAGE_MESSAGE);
+ }
+
+ lines[indexOfLine].sections.splice(indexOfSection, 1);
+ localStorage.lines = JSON.stringify(lines);
+
+ renderSection(selectedLine);
+}
+
+function findDeleteTarget(event, selectedLine) {
+ const $target = event.target;
+ const $sectionTable = document.getElementsByClassName("section-table-row");
+ const targetNumber = $target.closest("tr").dataset.number;
+ const section = $sectionTable[targetNumber].querySelector("span").innerText;
+
+ delSection(selectedLine, section);
+}
+
+export default function delSectionEvent(selectedLine) {
+ const $delSectionBtn = document.querySelectorAll(".section-delete-button");
+
+ $delSectionBtn.forEach((button) =>
+ button.addEventListener("click", (event) => {
+ if (confirm(alertMessage.DELETE_CHECK_MESSAGE)) {
+ findDeleteTarget(event, selectedLine);
+ }
+ })
+ );
+}
diff --git a/src/event/station/addStationEvent.js b/src/event/station/addStationEvent.js
new file mode 100644
index 000000000..283471b93
--- /dev/null
+++ b/src/event/station/addStationEvent.js
@@ -0,0 +1,29 @@
+import renderStation from "../../render/renderStation.js";
+import { isSatisfyLength, isStationAlreadyExist } from "../../common/checkInput.js";
+import { alertMessage } from "../../common/alertMessage.js";
+import { clearInput } from "../../common/clearInput.js";
+
+function addStation(stationInput) {
+ let stations = JSON.parse(localStorage.stations);
+ stations.push(String(stationInput));
+ localStorage.stations = JSON.stringify(stations);
+ renderStation();
+ clearInput();
+}
+
+function checkValidStation() {
+ const station = document.getElementById("station-name-input").value;
+ let stations = JSON.parse(localStorage.stations);
+
+ if (!isSatisfyLength(station)) {
+ return alert(alertMessage.SHORT_LENGTH_ERROR);
+ } else if (isStationAlreadyExist(stations, station)) {
+ return alert(alertMessage.SAME_STATION_EXIST_ERROR);
+ }
+ addStation(station);
+}
+
+export default function addStationEvent() {
+ const $addStationBtn = document.getElementById("station-add-button");
+ $addStationBtn.addEventListener("click", checkValidStation);
+}
diff --git a/src/event/station/delStationEvent.js b/src/event/station/delStationEvent.js
new file mode 100644
index 000000000..12dbfae55
--- /dev/null
+++ b/src/event/station/delStationEvent.js
@@ -0,0 +1,38 @@
+import renderStation from "../../render/renderStation.js";
+import { isStationOnLine } from "../../common/checkInput.js";
+import { alertMessage } from "../../common/alertMessage.js";
+
+function delStation(station) {
+ const lines = JSON.parse(localStorage.lines);
+ const stations = JSON.parse(localStorage.stations);
+
+ stations.splice(stations.indexOf(station), 1);
+
+ if (isStationOnLine(lines, station)) {
+ return alert(alertMessage.DELETE_STATION_ON_LINE_MESSAGE);
+ }
+
+ localStorage.stations = JSON.stringify(stations);
+
+ renderStation();
+}
+
+function findDeleteTarget(event) {
+ const $target = event.target;
+ const $stationTable = document.getElementsByClassName("station-table-row");
+ const targetNumber = $target.closest("tr").dataset.number;
+ const station = $stationTable[targetNumber].querySelector("span").innerText;
+
+ delStation(station);
+}
+
+export default function delStationEvent() {
+ const $delStationBtn = document.querySelectorAll(".station-delete-button");
+ $delStationBtn.forEach((button) =>
+ button.addEventListener("click", (event) => {
+ if (confirm(alertMessage.DELETE_CHECK_MESSAGE)) {
+ findDeleteTarget(event);
+ }
+ })
+ );
+}
diff --git a/src/index.js b/src/index.js
index e69de29bb..2b42f38e2 100644
--- a/src/index.js
+++ b/src/index.js
@@ -0,0 +1,7 @@
+import menuEvent from "./event/menuEvent.js";
+
+export default function SubwayMap() {
+ menuEvent();
+}
+
+new SubwayMap();
diff --git a/src/render/render.js b/src/render/render.js
new file mode 100644
index 000000000..739eebced
--- /dev/null
+++ b/src/render/render.js
@@ -0,0 +1,16 @@
+import renderStation from "./renderStation.js";
+import renderLine from "./renderLine.js";
+import renderMapPrint from "./renderMapPrint.js";
+import { renderLineButton } from "./renderSection.js";
+
+export default function render(name) {
+ if (name === "station") {
+ renderStation();
+ } else if (name === "line") {
+ renderLine();
+ } else if (name === "section") {
+ renderLineButton();
+ } else if (name === "mapPrint") {
+ renderMapPrint();
+ }
+}
diff --git a/src/render/renderLine.js b/src/render/renderLine.js
new file mode 100644
index 000000000..5f29d7247
--- /dev/null
+++ b/src/render/renderLine.js
@@ -0,0 +1,71 @@
+import delLineEvent from "../event/line/delLineEvent.js";
+
+function selectListTemplate() {
+ const stations = JSON.parse(localStorage.stations);
+ let newHTML = "";
+
+ stations.forEach((station) => (newHTML += ``));
+
+ return newHTML;
+}
+
+function initSelectContainer() {
+ const $selectContainers = document.querySelectorAll(".line-station-selector");
+ $selectContainers.forEach(
+ (selectContainer) => (selectContainer.innerHTML = selectListTemplate())
+ );
+}
+
+function lineTableTemplate() {
+ return `
+
+ | λ
Έμ μ΄λ¦ |
+ μν μ’
μ μ |
+ νν μ’
μ μ |
+ μ€μ |
+
+
`;
+}
+
+function initLineListContainer() {
+ const $lineTableContainer = document.getElementById("line-table-container");
+ $lineTableContainer.innerHTML = lineTableTemplate();
+}
+
+function lineListTemplate(line, lineNumber) {
+ return `
+ |
+ ${line.name}
+ |
+
+ ${line.sections[0]}
+ |
+
+ ${line.sections[line.sections.length - 1]}
+ |
+
+
+ |
+
`;
+}
+
+function initLineList(lines) {
+ const $lineTable = document.querySelector(".line-table");
+ let lineNumber = 0;
+
+ lines.forEach((line) =>
+ $lineTable.insertAdjacentHTML("beforeend", lineListTemplate(line, lineNumber++))
+ );
+
+ delLineEvent();
+}
+
+export default function renderStation() {
+ initSelectContainer();
+ initLineListContainer();
+
+ const lines = JSON.parse(localStorage.lines);
+ if (lines !== null) {
+ initLineList(lines);
+ }
+}
diff --git a/src/render/renderMapPrint.js b/src/render/renderMapPrint.js
new file mode 100644
index 000000000..fe525c5d6
--- /dev/null
+++ b/src/render/renderMapPrint.js
@@ -0,0 +1,22 @@
+function mapPrintTemplate() {
+ const lines = JSON.parse(localStorage.lines);
+ let newHTML = ``;
+
+ lines.forEach(
+ (line) =>
+ (newHTML += `
${line.name}
${line.sections
+ .map((section) => `- ${section}
`)
+ .join("")}
`)
+ );
+
+ return newHTML + "
";
+}
+
+function initMapPrint() {
+ const $mapPrintContainer = document.getElementById("map-print-container");
+ $mapPrintContainer.innerHTML = mapPrintTemplate();
+}
+
+export default function renderMapPrint() {
+ initMapPrint();
+}
diff --git a/src/render/renderSection.js b/src/render/renderSection.js
new file mode 100644
index 000000000..3348c193c
--- /dev/null
+++ b/src/render/renderSection.js
@@ -0,0 +1,106 @@
+import addSectionEvent from "../event/section/addSectionEvent.js";
+import delSectionEvent from "../event/section/delSectionEvent.js";
+
+function lineSelectButtonTemplate() {
+ const lines = JSON.parse(localStorage.lines);
+
+ return lines
+ .map(
+ (line) =>
+ ``
+ )
+ .join(" ");
+}
+
+function initLineSelectButtonCotainer() {
+ const $lineSelectButtonContainer = document.getElementById("line-select-button-container");
+ $lineSelectButtonContainer.innerHTML = lineSelectButtonTemplate();
+}
+
+export function renderLineButton() {
+ initLineSelectButtonCotainer();
+}
+
+function sectionInputTemplate(line) {
+ return `${line}
+ κ΅¬κ° λ±λ‘
+
+
+
+
+
`;
+}
+
+function initSectionInputContainer(selectedLine) {
+ const $sectionInputContainer = document.getElementById("section-input-container");
+ $sectionInputContainer.innerHTML = sectionInputTemplate(selectedLine);
+
+ addSectionEvent(selectedLine);
+}
+
+function sectionSelectorTemplate() {
+ const stations = JSON.parse(localStorage.stations);
+ let newHTML = "";
+
+ stations.forEach((station) => (newHTML += ``));
+
+ return newHTML;
+}
+
+function initSectionSelector() {
+ const $sectionStationSelector = document.getElementById("section-station-selector");
+ $sectionStationSelector.innerHTML = sectionSelectorTemplate();
+}
+
+function sectionTableTemplate() {
+ return `
+
+ | μμ |
+ μ΄λ¦ |
+ μ€μ |
+
+
`;
+}
+
+function initSectionTableContainer() {
+ const $sectionTableContainer = document.getElementById("section-table-container");
+ $sectionTableContainer.innerHTML = sectionTableTemplate();
+}
+
+function sectionListTemplate(section, sectionNumber) {
+ return `
+ |
+ ${sectionNumber}
+ |
+
+ ${section}
+ |
+
+
+ |
+
+ `;
+}
+
+function initSectionList(selectedLine) {
+ const lines = JSON.parse(localStorage.lines);
+ const $sectionTable = document.querySelector(".section-table");
+ let sectionNumber = 0;
+
+ for (let i = 0; i < lines.length; i++) {
+ if (selectedLine === lines[i].name) {
+ lines[i].sections.forEach((section) =>
+ $sectionTable.insertAdjacentHTML("beforeend", sectionListTemplate(section, sectionNumber++))
+ );
+ }
+ }
+
+ delSectionEvent(selectedLine);
+}
+
+export function renderSection(selectedLine) {
+ initSectionInputContainer(selectedLine);
+ initSectionSelector();
+ initSectionTableContainer();
+ initSectionList(selectedLine);
+}
diff --git a/src/render/renderStation.js b/src/render/renderStation.js
new file mode 100644
index 000000000..d1eca5190
--- /dev/null
+++ b/src/render/renderStation.js
@@ -0,0 +1,46 @@
+import delStationEvent from "../event/station/delStationEvent.js";
+
+function stationTableTemplate() {
+ return `
+
+ | μ μ΄λ¦ |
+ μ€μ |
+
+
`;
+}
+
+function initStationListContainer() {
+ const $stationTableContainer = document.getElementById("station-table-container");
+ $stationTableContainer.innerHTML = stationTableTemplate();
+}
+
+function stationListTemplate(station, stationNumber) {
+ return `
+ |
+ ${station}
+ |
+
+
+ |
+
`;
+}
+
+function initStationList(stations) {
+ const $stationTable = document.querySelector(".station-table");
+ let stationNumber = 0;
+
+ stations.forEach((station) =>
+ $stationTable.insertAdjacentHTML("beforeend", stationListTemplate(station, stationNumber++))
+ );
+
+ delStationEvent();
+}
+
+export default function renderStation() {
+ initStationListContainer();
+
+ const stations = JSON.parse(localStorage.stations);
+ if (stations !== null) {
+ initStationList(stations);
+ }
+}