+`;
+const TABLE_HEADER_TEMPLATE = `
+
μμ |
+
μ΄λ¦ |
+
μ€μ |
+`;
+const SECTION_REGISTER_TEMPLATE = `
+
κ΅¬κ° λ±λ‘
+
+
+
+
+
+
+`;
diff --git a/src/ui/contents-ui/station-manager-ui.js b/src/ui/contents-ui/station-manager-ui.js
new file mode 100644
index 000000000..fb860d97c
--- /dev/null
+++ b/src/ui/contents-ui/station-manager-ui.js
@@ -0,0 +1,90 @@
+import { hasValidStationName } from "../../utility/input-check-utility.js";
+import { DELETE_CONFIRM_MESSAGE } from "../../utility/share-constant-utility.js";
+import { contentsUI } from "./contents-ui.js";
+
+export default class StationManagerUI extends contentsUI {
+ constructor(contentsID, subwayINFOManager) {
+ super(contentsID, subwayINFOManager);
+ this.setContentsHTML(INITIAL_TEMPLATE);
+ }
+ setContentsHTML(initialTemplate) {
+ super.setContentsHTML(initialTemplate);
+ this._addEventToNameInputButton();
+ this.updateStationsTable();
+ }
+ updateStationsTable() {
+ const stationsNames = this._stationINFOManager.getAllStationNames();
+ const tableContainer = document.getElementById(STATION_NAME_TABLE_ID);
+ let innerHTMLOfTable = TABLE_HEADER_TEMPLATE;
+ for (let name of stationsNames) {
+ innerHTMLOfTable += this._makeNewTableRowHTML(name);
+ }
+ tableContainer.innerHTML = innerHTMLOfTable;
+ this._addEventToAllTableDeleteButton();
+ }
+
+ _addEventToNameInputButton() {
+ this._addClickEventToButtonByID(
+ STATION_ADD_BUTTON_ID,
+ this._callbackOfNameInputButton
+ );
+ }
+ _addEventToAllTableDeleteButton() {
+ this._addClickEventToAllButtonByClassName(
+ STATION_DELETE_BUTTON_CLASS,
+ this._callbackOfTableDeleteButton
+ );
+ }
+ _callbackOfNameInputButton() {
+ const name = this._getInputTextByID(STATION_NAME_INPUT_ID);
+ if (!this._hasValidStationInput(name)) {
+ return;
+ }
+ this._stationINFOManager.addNewStation({
+ name: name,
+ });
+ this.updateStationsTable();
+ }
+ _callbackOfTableDeleteButton(event) {
+ if (!confirm(DELETE_CONFIRM_MESSAGE)) {
+ return;
+ }
+ const lines = this._lineINFOManager.getAllLines();
+ this._stationINFOManager.deleteStation(event.target.dataset.name, lines);
+ this.updateStationsTable();
+ }
+ _hasValidStationInput(name) {
+ const isValidStationName = hasValidStationName(name);
+ const isNotOverlapName = this._stationINFOManager.hasNotOverlapNameAmongStations(
+ name
+ );
+ return isValidStationName && isNotOverlapName;
+ }
+ _makeNewTableRowHTML(name) {
+ return `
+
+ | ${name} |
+
+
+ |
+
+ `;
+ }
+}
+const STATION_NAME_INPUT_ID = "station-name-input";
+const STATION_ADD_BUTTON_ID = "station-add-button";
+const STATION_NAME_TABLE_ID = "station-name-table";
+const STATION_DELETE_BUTTON_CLASS = "station-delete-button";
+
+const INITIAL_TEMPLATE = `
+
μ μ΄λ¦
+
+
+
π μ§νμ² μ λͺ©λ‘
+
+`;
+const TABLE_HEADER_TEMPLATE = `
+
μ μ΄λ¦ |
+
μ€μ |
+`;
diff --git a/src/ui/menubar-ui.js b/src/ui/menubar-ui.js
new file mode 100644
index 000000000..7cef557a1
--- /dev/null
+++ b/src/ui/menubar-ui.js
@@ -0,0 +1,51 @@
+export default class MenubarUI {
+ constructor({ htmlManager, menubarID }) {
+ this._htmlManager = htmlManager;
+ this._menubarID = menubarID;
+ this.setMenubar();
+ }
+ setMenubar() {
+ document.getElementById(this._menubarID).innerHTML = MENU_TEMPLATE;
+ this._addEventToStationButton();
+ this._addEventToLineButton();
+ this._addEventToSectionButton();
+ this._addEventToMapPrintButton();
+ }
+
+ _addEventToStationButton() {
+ const button = document.getElementById(STATION_ID);
+ button.addEventListener("click", () => {
+ this._htmlManager.setContentsUIOnStationUI();
+ });
+ }
+ _addEventToLineButton() {
+ const button = document.getElementById(LINE_ID);
+ button.addEventListener("click", () => {
+ this._htmlManager.setContentsUIOnSectionUI();
+ });
+ }
+ _addEventToSectionButton() {
+ const button = document.getElementById(SECTION_ID);
+ button.addEventListener("click", () => {
+ this._htmlManager.setContentsUIOnLineUI();
+ });
+ }
+ _addEventToMapPrintButton() {
+ const button = document.getElementById(MAP_PRINT_ID);
+ button.addEventListener("click", () => {
+ this._htmlManager.setContentsUIOnMapPrintUI();
+ });
+ }
+}
+
+const STATION_ID = "station-manager-button";
+const LINE_ID = "line-manager-button";
+const SECTION_ID = "section-manager-button";
+const MAP_PRINT_ID = "map-print-manager-button";
+
+const MENU_TEMPLATE = `
+
+
+
+
+`;
diff --git a/src/utility/input-check-utility.js b/src/utility/input-check-utility.js
new file mode 100644
index 000000000..9ac11b17a
--- /dev/null
+++ b/src/utility/input-check-utility.js
@@ -0,0 +1,104 @@
+import { SELECTEOR_NONE } from "./share-constant-utility.js";
+
+export function hasValidStationName(name) {
+ const isValidLength = hasSatisfiedMinLengthCondition({
+ operandLength: name.length,
+ minLength: MINIMUM_LENGTH_OF_STATION_NAME,
+ errorMessage: MINIMUM_LENGTH_STATION_NAME_ERROR_MESSAGE,
+ });
+ return isValidLength;
+}
+export function hasValidLine(name, startStationName, endStationName) {
+ const isValidLength = hasSatisfiedMinLengthCondition({
+ operandLength: name.length,
+ minLength: MINIMUM_LENGTH_OF_LINE_NAME,
+ errorMessage: MINIMUM_LENGTH_LINE_NAME_ERROR_MESSAGE,
+ });
+ const isNotEqualName = hasNotEqualName({
+ operand1: startStationName,
+ operand2: endStationName,
+ errorMessage: HAS_EQUAL_NAME_ERROR_MESSAGE,
+ });
+ return isValidLength && isNotEqualName;
+}
+export function hasValidOrder(order) {
+ const isTypeOfNumber = hasTypeOfNumber({
+ operand: order,
+ errorMessage: NOT_TYPE_OF_NUMBER_ERROR_MESSAGE,
+ });
+ const isSatisfyLengthCondition = hasSatisfiedMinLengthCondition({
+ operandLength: Number(order),
+ minLength: MINIMUM_VAILD_ORDER,
+ errorMessage: LESS_THAN_MINIMUM_ORDER_ERROR_MESSAGE,
+ });
+ return isTypeOfNumber && isSatisfyLengthCondition;
+}
+export function hasValidOption(inputOptions) {
+ let retBool = true;
+ for (let inputOption of inputOptions) {
+ if (inputOption === SELECTEOR_NONE) {
+ alert(NOT_SELECTED_OPTION_ERROR_MESSAGE);
+ retBool = false;
+ break;
+ }
+ }
+ return retBool;
+}
+export function hasSatisfiedMinLengthCondition({
+ operandLength,
+ minLength,
+ errorMessage,
+}) {
+ let boolToReturn = true;
+ if (operandLength < minLength) {
+ alert(errorMessage);
+ boolToReturn = false;
+ }
+ return boolToReturn;
+}
+export function hasSatisfiedMaxLengthCondition({
+ operandLength,
+ maxLength,
+ errorMessage,
+}) {
+ let boolToReturn = true;
+ if (operandLength > maxLength) {
+ alert(errorMessage);
+ boolToReturn = false;
+ }
+ return boolToReturn;
+}
+export function hasNotOverlapName(targetToFindOverlap, inputName) {
+ const overlapIndex = targetToFindOverlap.findIndex(
+ ({ name }) => name === inputName
+ );
+ return overlapIndex === -1;
+}
+
+function hasTypeOfNumber({ operand, errorMessage }) {
+ let retBool = true;
+ if (operand === "") {
+ alert(errorMessage);
+ retBool = false;
+ }
+ return retBool;
+}
+function hasNotEqualName({ operand1, operand2, errorMessage }) {
+ let isNotEqualName = true;
+ if (operand1 === operand2) {
+ alert(errorMessage);
+ isNotEqualName = false;
+ }
+ return isNotEqualName;
+}
+
+const MINIMUM_LENGTH_OF_STATION_NAME = 2;
+const MINIMUM_LENGTH_OF_LINE_NAME = 1;
+const MINIMUM_VAILD_ORDER = 0;
+
+const MINIMUM_LENGTH_STATION_NAME_ERROR_MESSAGE = `μ μ΄λ¦μ μ΅μ ${MINIMUM_LENGTH_OF_STATION_NAME} κΈμμ¬μΌ ν©λλ€.`;
+const MINIMUM_LENGTH_LINE_NAME_ERROR_MESSAGE = `λ
Έμ μ΄λ¦μ μ΅μ ${MINIMUM_LENGTH_OF_LINE_NAME} κΈμμ¬μΌ ν©λλ€.`;
+const NOT_TYPE_OF_NUMBER_ERROR_MESSAGE = "μ«μλ₯Ό μ
λ ₯ν΄μ£ΌμΈμ.";
+const LESS_THAN_MINIMUM_ORDER_ERROR_MESSAGE = `μμκ°μ μ΅μ ${MINIMUM_VAILD_ORDER} μ΄μμ΄μ΄μΌ ν©λλ€.`;
+const HAS_EQUAL_NAME_ERROR_MESSAGE = `μν μ’
μ κ³Ό νν μ’
μ μ΄ κ°μ μμ
λλ€.`;
+const NOT_SELECTED_OPTION_ERROR_MESSAGE = "콀보λ°μ€μ μ΅μ
μ μ νν΄μ£ΌμΈμ.";
diff --git a/src/utility/share-constant-utility.js b/src/utility/share-constant-utility.js
new file mode 100644
index 000000000..3e455f61f
--- /dev/null
+++ b/src/utility/share-constant-utility.js
@@ -0,0 +1,5 @@
+export const SELECTEOR_NONE = "none";
+export const SELECTOR_DEFAULT_TEMPLATE = `
+
+`;
+export const DELETE_CONFIRM_MESSAGE = "μ λ§λ‘ μμ νμκ² μ΅λκΉ?";
diff --git a/src/utility/storage-utility.js b/src/utility/storage-utility.js
new file mode 100644
index 000000000..7f8c8f9a7
--- /dev/null
+++ b/src/utility/storage-utility.js
@@ -0,0 +1,9 @@
+export function saveToLocalStorage(itemName, objectToSave) {
+ const jsonForm = JSON.stringify(objectToSave);
+ localStorage.setItem(itemName, jsonForm);
+}
+
+export function loadFromLocalStorage(itemName) {
+ let objectToLoad = JSON.parse(localStorage.getItem(itemName));
+ return objectToLoad;
+}