Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3b23682
docs: code formatter 설정 및 기능 구현 목록 작성
rjwu95 Dec 10, 2020
7e5e398
feat: 메뉴 레이아웃 잡고 버튼 클릭 시 해당 내용 보여주기
rjwu95 Dec 11, 2020
39b8473
feat: 역 관리 내용 부분 레이아웃 잡기
rjwu95 Dec 12, 2020
f002ba5
feat: 역 추가 및 삭제하기
rjwu95 Dec 13, 2020
af0d1e8
feat: 노선 관리 레이아웃 잡기
rjwu95 Dec 13, 2020
7458da6
refactor: Header 클래스를 따로 분리
rjwu95 Dec 13, 2020
c322335
chore: station delete button에 class 값 부여
rjwu95 Dec 13, 2020
7b903b5
refactor: utils 안에서 storage 모듈을 분리
rjwu95 Dec 13, 2020
f77b316
feat: 노선 관리 눌렀을 때 역 리스트 select에 넣기
rjwu95 Dec 13, 2020
56966cb
chore: constant.js 를 constants 폴더로 따로 구분
rjwu95 Dec 14, 2020
306e01b
feat: 노선 추가 및 삭제
rjwu95 Dec 14, 2020
aa4a63f
feat: 구간 관리 레이아웃 잡기
rjwu95 Dec 14, 2020
e8b08f4
feat: 구간 선택 시 구간 수정 화면 출력
rjwu95 Dec 15, 2020
0aafdcb
feat: 구간 추가 및 삭제하기
rjwu95 Dec 15, 2020
3d91111
refactor: 상수 모듈 분리 및 이름 수정
rjwu95 Dec 15, 2020
1f1614a
fix: 상수 오타 수정
rjwu95 Dec 15, 2020
157aa80
feat: 지하철 노선도 출력
rjwu95 Dec 15, 2020
87e4de8
feat: data 속성을 이용하여 html에 고유한 값 부여
rjwu95 Dec 15, 2020
ae6e806
chore: renderMapContent 메소드를 utils로 옮김
rjwu95 Dec 15, 2020
5d9172a
feat: 노선 이름이 비어있는 경우 예외 처리하기
rjwu95 Dec 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
38 changes: 35 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,83 +1,114 @@
# 🚇 지하철 노선도 미션

## 기능 구현 목록

- [x] 기능 구현 목록 작성 및 code formatter 설정
- [x] 네비게이션 레이아웃 잡고 버튼 클릭 시 해당 내용 보여주기
- [x] 역 관리 레이아웃 잡기
- [x] 역 추가 및 삭제 하기(예외 상황 처리)
- [x] 노선 관리 레이아웃 잡기
- [x] header 모듈 분리하기
- [x] 상행 하행 종점에 역 리스트 넣기
- [x] 노선 추가 및 삭제 하기
- [x] 구간 관리 레이아웃 잡기
- [x] 구간 선택 하기
- [x] 구간 등록 및 제거 하기
- [x] 상수 정리하기
- [x] 지하철 노선도 출력 레이아웃 및 보여주기
- [x] data 속성 사용하여 유일한 값 부여하기
- [x] 노선 이름 비어있는 경우 예외처리

## 🚀 기능 요구사항

### 지하철 역 관련 기능

- 지하철 역을 등록하고 삭제할 수 있다. (단, 노선에 등록된 역은 삭제할 수 없다)
- 중복된 지하철 역 이름이 등록될 수 없다.
- 지하철 역은 2글자 이상이어야 한다.
- 지하철 역의 목록을 조회할 수 있다.

### 지하철 노선 관련 기능

- 지하철 노선을 등록하고 삭제할 수 있다.
- 중복된 지하철 노선 이름이 등록될 수 없다.
- 노선 등록 시 상행 종점역과 하행 종점역을 입력받는다.
- 지하철 노선의 목록을 조회할 수 있다.

### 지하철 구간 추가 기능

- 지하철 노선에 구간을 추가하는 기능은 노선에 역을 추가하는 기능이라고도 할 수 있다.
- 역과 역사이를 구간이라 하고 이 구간들의 모음이 노선이다.
- 역과 역사이를 구간이라 하고 이 구간들의 모음이 노선이다.
- 하나의 역은 여러개의 노선에 추가될 수 있다.
- 역과 역 사이에 새로운 역이 추가 될 수 있다.
- 노선에서 갈래길은 생길 수 없다.

<img width="500" src="/images/section1.png">

### 지하철 구간 삭제 기능

- 노선에 등록된 역을 제거할 수 있다.
- 종점을 제거할 경우 다음 역이 종점이 된다.
- 노선에 포함된 역이 두개 이하일 때는 역을 제거할 수 없다.

<img width="500" src="/images/section2.png">

### 지하철 노선에 등록된 역 조회 기능

- 노선의 상행 종점부터 하행 종점까지 연결된 순서대로 역 목록을 조회할 수 있다.

<br/>

## 💻 프로그램 실행 결과

### 역관리

<img width="100%" src="/images/station_manager.gif">

### 노선관리

<img width="100%" src="/images/line_manager.gif">

### 구간관리

<img width="100%" src="/images/section_manager.gif">

### 노선도 출력
<img width="100%" src="/images/map_print_manager.gif">

<img width="100%" src="/images/map_print_manager.gif">

## ✅ 프로그래밍 요구사항

### 메뉴 버튼

- 역 관리 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값을 가진다.

### 지하철 노선도 출력 기능

- 지하철 노선도 출력 버튼을 누르면 `<div class="map"></div>` 태그를 만들고 해당 태그 내부에 노선도를 출력한다.

### 기존 요구사항
Expand All @@ -101,7 +132,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)를 이용하여, 새로고침하더라도 가장 최근에 작업한 정보들을 불러올 수 있도록 한다.

<br/>
Expand Down
63 changes: 62 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,69 @@
</head>
<body>
<div id="app">
<h1>🚇 지하철 노선도 관리 </h1>
<header>
<h1>🚇 지하철 노선도 관리</h1>
<button id="station-manager-button">1.역 관리</button>
<button id="line-manager-button">2.노선 관리</button>
<button id="section-manager-button">3.구간 관리</button>
<button id="map-print-manager-button">4.지하철 노선도 출력</button>
</header>
<div id="content">
<div class="hide" id="station-manager-content">
<div>역 이름</div>
<input type="text" id="station-name-input" />
<button id="station-add-button">역 추가</button>
<h2>🚉 지하철 역 목록</h2>
<table id="station-table">
<tbody id="station-table-body"></tbody>
</table>
</div>
<div class="hide" id="line-manager-content">
<div>노선 이름</div>
<input
type="text"
placeholder="노선 이름을 입력해주세요"
id="line-name-input"
/>
<div id="end-point-container">
상행 종점
<select id="line-start-station-selector"></select>
<br />
하행 종점
<select id="line-end-station-selector"></select>
</div>
<button id="line-add-button">노선 추가</button>
<h2>🚉 지하철 노선 목록</h2>
<table>
<tbody id="line-table-body"></tbody>
</table>
</div>
<div class="hide" id="section-manager-content"></div>
</div>
</div>
<style>
.hide {
display: none;
}
#content {
margin-top: 20px;
}
table,
th,
td {
border: 1px solid black;
}
#line-name-input,
#end-point-container {
margin-bottom: 20px;
}
#section-table {
margin-top: 20px;
}
.section-line-menu-button {
margin-right: 8px;
}
</style>
<script type="module" src="src/index.js"></script>
</body>
</html>
65 changes: 65 additions & 0 deletions src/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
addClickEventFromId,
renderLineTable,
renderStationTable,
putOptionsFromId,
renderSectionSelector,
renderMapContent,
} from "./utils/dom.js";

const menuIds = [
"station-manager-button",
"line-manager-button",
"section-manager-button",
"map-print-manager-button",
];

export default class Header {
constructor() {
this.clickMenuEventListener();
}

clickMenuEventListener() {
menuIds.forEach((id) => {
addClickEventFromId(id, () => {
this.hideContentChildren();
this.renderContent(id);
});
});
}

hideContentChildren() {
const contentChildren = Array.from(
document.getElementById("content").children
);
contentChildren.forEach((el) => (el.style.display = "none"));
const mapContent = document.getElementsByClassName("map")[0];
if (mapContent !== undefined) {
mapContent.remove();
}
}

renderContent(id) {
const isMap = Boolean(id.match("map"));
if (isMap) {
renderMapContent();
return;
}
const isLine = Boolean(id.match("line"));
if (isLine) {
putOptionsFromId("line-start-station-selector");
putOptionsFromId("line-end-station-selector");
renderLineTable();
}
const isStation = Boolean(id.match("station"));
if (isStation) {
renderStationTable();
}
const isSection = Boolean(id.match("section"));
if (isSection) {
renderSectionSelector();
}
const content = document.getElementById(id.replace("button", "content"));
content.style.display = "block";
}
}
17 changes: 17 additions & 0 deletions src/Line.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getStateFromStorage, setStateToStorage } from "./utils/storage.js";
import * as storageKey from "./constants/storageKey.js";

export default class Line {
constructor(name, section) {
this.name = name;
this.section = section;
}

add() {
const lines = getStateFromStorage(storageKey.LINES);
setStateToStorage(storageKey.LINES, {
...lines,
[this.name]: this.section,
});
}
}
11 changes: 11 additions & 0 deletions src/constants/message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const MORE_THAN_2_STATION_NAME = "역 이름은 2자 이상이어야 합니다.";
export const ALREADY_EXIST_STATION_NAME = "이미 존재하는 역입니다.";
export const ALREADY_EXIST_LINE_NAME = "이미 존재하는 노선 이름입니다.";
export const CANT_SAME_START_AND_END =
"상행 종점과 하행 종점이 같을 수 없습니다.";
export const ALREAY_EXIST_SAME_END_POINTS =
"종점이 일치하는 노선이 이미 존재합니다.";
export const ALREADY_EXIST_STATION_IN_LINE = "역이 이미 노선에 존재합니다.";
export const LESS_THAN_2_LINE_SECTION =
"구간이 2개 이하일 때는 삭제할 수 없습니다.";
export const MUST_INPUT_LINE_NAME = "노선 이름을 입력해 주세요.";
38 changes: 38 additions & 0 deletions src/constants/skeleton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export const SECTION_CONTENT = `
<h2>구간을 수정할 노선을 선택해주세요.</h2>
<div id="section-selector-container"></div>
<div id="section-modify-container" class="hide">
<h3 id="section-manage-title"></h3>
<h4>구간 등록</h4>
<select id="section-station-selector"></select>
<input type="number" id="section-order-input" />
<button id="section-add-button">등록</button>
<table id="section-table">
<tbody id="section-table-body"></tbody>
</table>
</div>
`;

export const STATION_TABLE_BODY = `
<tr>
<th>역 이름</th>
<th>설정</th>
</tr>
`;

export const LINE_TABLE_BODY = `
<tr>
<th>노선 이름</th>
<th>상행 종점역</th>
<th>하행 종점역</th>
<th>설정</th>
</tr>
`;

export const SECTION_TABLE_BODY = `
<tr>
<th>순서</th>
<th>이름</th>
<th>설정</th>
</tr>
`;
2 changes: 2 additions & 0 deletions src/constants/storageKey.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const STATIONS = "STATIONS";
export const LINES = "LINES";
Loading