Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
74b1992
역 관리 페이지 기능 목록 작성
junsubaek Dec 13, 2020
df574b9
html 초기 화면 셋팅
junsubaek Dec 13, 2020
7dce6cb
style: 표 스타일 작성
junsubaek Dec 13, 2020
21eb36a
feat: 역 관리 버튼 클릭 시 화면 연결 기능 추가
junsubaek Dec 13, 2020
4dca739
feat: 역 추가 버튼 클릭 시 역 추가 기능 추가
junsubaek Dec 13, 2020
2ad6de0
feat: 역 추가 시 화면에 그리는 기능 추가
junsubaek Dec 13, 2020
5878b4f
feat: 삭제 버튼 클릭 시 역 삭제 기능 추가
junsubaek Dec 13, 2020
8609377
Update README.md
junsubaek Dec 13, 2020
adb99aa
feat: 역 이름 유효성 검사하는 기능 추가
junsubaek Dec 13, 2020
fae92ef
feat: 노선 관리 버튼 클릭 시 화면 연결 기능 추가
junsubaek Dec 13, 2020
d86ca15
refactor: 이벤트 기능 파일 분리
junsubaek Dec 13, 2020
7b703c6
Update README.md
junsubaek Dec 13, 2020
6896db1
feat: 노선 이름을 입력 받는 기능 추가
junsubaek Dec 13, 2020
327aa9b
feat: 상행종점과 하행종점의 값을 입력받는 기능 추가
junsubaek Dec 13, 2020
fe65acd
feat: 노선 추가 버튼 클릭 시 노선이 추가 되는 기능 추가
junsubaek Dec 13, 2020
6efea54
feat: 노선 추가 버튼 클릭 시 화면에 그리는 기능 추가
junsubaek Dec 13, 2020
e611eb7
feat: 삭제 버튼 클릭 시 노선을 삭제하는 기능 추가
junsubaek Dec 13, 2020
1e453c5
feat: 중복된 노선 금지 기능 추가
junsubaek Dec 13, 2020
5e6e72a
feat: 지하철 역 로컬스토리지에 저장하는 기능 추가
junsubaek Dec 13, 2020
3faa8a5
refactor: 컴포넌트 분리
junsubaek Dec 13, 2020
8450b1f
refactor: 불필요한 코드 제거
junsubaek Dec 13, 2020
056450b
feat: 셀렉터에 로컬스토리지 정보 가져오기 기능 추가
junsubaek Dec 13, 2020
14fd273
refactor: 컴포넌트에 mount, render 추가
junsubaek Dec 13, 2020
8091eb2
Update README.md
junsubaek Dec 14, 2020
9fedab0
style: 테이블 스타일 수정
junsubaek Dec 14, 2020
7187f3d
feat: 구간 관리 버튼 클릭 시 화면 연결 기능 추가
junsubaek Dec 14, 2020
b06a081
feat: 노선 선택 버튼과 셀렉트 태그에 로컬스토리지 정보 부여
junsubaek Dec 14, 2020
a2ed620
feat: 노선 선택 버튼 클릭 시 구간 관리 화면 연결 기능 추가
junsubaek Dec 14, 2020
8cc6e62
feat: 노선 버튼 클릭 시 표에 로컬 스토리지 정보 불러오기 추가
junsubaek Dec 14, 2020
275238f
feat: 등록 버튼 클릭 시 구간 추가 기능 추가
junsubaek Dec 14, 2020
986f74e
feat: 제거 버튼 클릭 시 구간 삭제 기능 추가
junsubaek Dec 14, 2020
a06e61b
fix: 로컬스토리지에 정보를 넘기고 받아오는 기능 수정
junsubaek Dec 14, 2020
f420627
fix: 스토어의 라인 데이터 구조 변경
junsubaek Dec 14, 2020
2e443ba
Update README.md
junsubaek Dec 14, 2020
6df5e5c
feat: 지하철 노선도 출력 기능 추가
junsubaek Dec 14, 2020
42b8b32
feat: 2개 이하의 역 제거 금지 기능 추가
junsubaek Dec 14, 2020
d70eb89
refactor: mount함수 분리
junsubaek Dec 14, 2020
309aeec
refactor: 함수 리턴 값 수정
junsubaek Dec 14, 2020
b803079
refactor: 불필요한 코드 삭제
junsubaek Dec 14, 2020
13a5dde
refactor: 에러메시지 파일 분리
junsubaek Dec 14, 2020
9e40ce6
refactor: 함수 통일성 맞추기
junsubaek Dec 15, 2020
3e5d70a
refactor: 불필요한 코드 삭제
junsubaek Dec 15, 2020
23c5804
refactor: elementMap 파일 분리
junsubaek Dec 15, 2020
f0dd5da
refactor: reRenderPage 함수 파일 분리
junsubaek Dec 15, 2020
2c0406c
refactor: 코드 순서 변경
junsubaek Dec 15, 2020
7ca1c36
feat: 노선 이름 공백 불가 기능 추가
junsubaek Dec 15, 2020
ece0d18
refactor: 코드 순서 변경
junsubaek Dec 15, 2020
7ca1db5
Update README.md
junsubaek Dec 15, 2020
ba65448
Update README.md
junsubaek Dec 15, 2020
c1689ff
fix: 노선 출력 화면의 태그에 클래스를 map으로 수정
junsubaek Dec 15, 2020
35c8cff
Update README.md
junsubaek Dec 15, 2020
e2b903c
Update README.md
junsubaek 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
131 changes: 109 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,83 +1,169 @@
# 🚇 지하철 노선도 미션

## 🚦 디렉토리 구조
```
├── LICENSE
├── README.md
├── images
│ ├── line_manager.gif
│ ├── map_print_manager.gif
│ ├── section1.png
│ ├── section2.png
│ ├── section_manager.gif
│ └── station_manager.gif
├── index.html
└── src
├── config.js
├── core
│ └── Component.js
├── index.js
├── pages
│ ├── LineManager.js
│ ├── PrintSubwayLine.js
│ ├── SectionManager.js
│ └── StationManager.js
└── utils
├── errors.js
├── events.js
└── reRenderPage.js
```
- config: 전체 페이지에 필요한 태그를 따로 관리하기 위해 설정 파일로 분리
- core: 상태로 HTML을 렌더링하기 위해 사용되는 메서드들을 컴포넌트 클래스를 사용하여 정의
- pages: 각각의 화면들을 한 폴더에서 관리하기 위해 pages 폴더에 분리
- utils: 에러메시지, 이벤트, 페이지를 다시 그려주는 함수를 utils 폴더에 분리

<br/>

## 🚀 기능 요구사항

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

### 지하철 노선 관련 기능
- 지하철 노선을 등록하고 삭제할 수 있다.
- 중복된 지하철 노선 이름이 등록될 수 없다.
- 노선 등록 시 상행 종점역과 하행 종점역을 입력받는다.
- 지하철 노선의 목록을 조회할 수 있다.
#### 1) 역의 이름 유효성 검사

- 중복된 역의 이름을 등록할 수 없다.
- 역의 이름은 2글자 이상으로 한다.
- 역의 이름에 공백이 들어갈 수 없다.
- 역의 이름은 한글로만 작성 가능하다.
- 역의 이름이 올바르지 않을 시, `alert` 메시지를 출력한다.

#### 2) 지하철 역 목록 관리

- 역 관리 버튼 클릭 시, 역 관리 페이지를 출력한다.
- 역 추가 버튼 클릭 시, 역을 추가한다.
- 역 삭제 버튼 클릭 시, 역을 삭제한다.
- 역의 추가와 삭제 시, 역의 목록을 출력한다.
- 역 관리가 끝난 역의 목록을 로컬스토리지에 저장한다.

### 2. 노선 관리 페이지

#### 1) 노선의 이름 유효성 검사

- 중복된 노선의 이름을 등록할 수 없다.
- 노선의 이름에 공백이 들어갈 수 없다.
- 노선의 이름이 올바르지 않을 시, `alert` 메시지를 출력한다.

#### 2) 지하철 노선 목록 관리

- 노선 관리 버튼 클릭 시, 노선 관리 페이지를 출력한다.
- 노선 추가 버튼 클릭 시, 노선을 추가한다.
- 삭제 버튼 클릭 시, 노선을 삭제한다.
- 노선 추가와 삭제 시, 노선 목록을 출력하고 로컬스토리지에 노선 목록을 저장한다.

### 3. 구간 관리 페이지

#### 1) 노선 선택

- 로컬스토리지에서 노선을 받아와 노선 메뉴 버튼을 생성한다.
- 각 노선의 버튼을 클릭 시, 해당 노선의 정보를 출력한다.

#### 2) 지하철 구간 목록 관리

### 지하철 구간 추가 기능
- 지하철 노선에 구간을 추가하는 기능은 노선에 역을 추가하는 기능이라고도 할 수 있다.
- 역과 역사이를 구간이라 하고 이 구간들의 모음이 노선이다.
- 역과 역사이를 구간이라 하고 이 구간들의 모음이 노선이다.
- 하나의 역은 여러개의 노선에 추가될 수 있다.
- 역과 역 사이에 새로운 역이 추가 될 수 있다.
- 노선에서 갈래길은 생길 수 없다.
- 추가될 역의 이름과 순서를 입력 받는다.
- 등록 버튼 클릭 시, 노선에 역을 추가한다.
- 노선에서 제거 버튼 클릭 시, 노선에 역을 제거한다.
- 노선의 등록과 제거 시, 구간 목록을 출력하고 로컬스토리지에 노선 목록을 저장한다.
- 종점 제거 시 다음 역이 종점이 된다.
- 노선에 포함된 역이 2개 이하일 때, 역을 제거할 수 없다.
- 추가할 역의 순서를 입력하지 않으면 `alert` 메시지를 출력한다.

<img width="500" src="/images/section1.png">
### 4. 지하철 노선도 출력

### 지하철 구간 삭제 기능
- 노선에 등록된 역을 제거할 수 있다.
- 종점을 제거할 경우 다음 역이 종점이 된다.
- 노선에 포함된 역이 두개 이하일 때는 역을 제거할 수 없다.
- 로컬스토리지에 저장된 노선도를 화면에 출력한다.

<br/>

<img width="500" src="/images/section2.png">
## 🥊 미흡했던 점 & 고생했던 점

### 지하철 노선에 등록된 역 조회 기능
- 노선의 상행 종점부터 하행 종점까지 연결된 순서대로 역 목록을 조회할 수 있다.
- [data]: 현재 구조에서 어떻게 [data]속성을 사용해야 할지 파악을 하지 못했습니다.
- 새로운 구조로 코딩을 하다 보니 막히는 부분이 많았고, 그로 인해 시간에 쫓겨 더 많은 예외사항에 대한 고민이 부족했습니다.
- 상태가 변할 때 마다 전체 화면을 렌더링하는 구조로 코딩을 하여, 변화하지 않는 부분도 다시 그려야 했습니다.
- 각 페이지마다 하나의 클래스 안에 많은 메서드가 존재하여 읽기 불편하다고 생각이 들었습니다.
- eslint와 prettier의 셋팅을 에디터에서만 설정하고, 파일로 볼 수 있도록 하지 못한 점이 아쉽습니다.
- 더 효율적인 코드를 작성하지 못하고, 단순히 15라인을 넘지 않기 위해 억지로 분리한 듯한 부분이 있어 아쉽습니다.
- 어떠한 이유로 에러메시지가 화면에 뜬 건지 상황마다 더 명확하게 설명을 하지 못했습니다. 다른 분의 pr을 보고 try catch문을 사용하면 더 명확하게 설명을 할 수 있다는 것을 배울 수 있었습니다.
- map으로 화면을 그릴 때, 화면에 계속 의도치 않은 텍스트가 발생하여 원인을 찾는데 꽤 오래 걸렸습니다. 결과적으로 배열인데 `join` 을 사용하지 않아 발생한 문제였습니다.
- 템플릿 리터럴을 사용해 일일히 화면을 그리다 보니 태그들을 작성하는데 헷갈리는 부분이 많아 고생했습니다. 확장도구를 이용하여 더 편하게 할 수 있다는 것을 나중에 알게 되었습니다.
- 어떤 값을 상수로 관리해야 하는 지 판단하는 것이 어려웠습니다. 함수안에서만 사용하고 의미가 명확해 보이는 값들도 상수 처리 해야 하는 지 의문이 들었습니다.
- 상행종점과 하행종점의 값을 저장할 때 하나의 배열에 저장하지 않고 따로 저장했습니다. 그로 인해 구간에서 목록을 추가하고 삭제할 때, 데이터 변경하는 부분이 너무 어려웠습니다. 결국 다시 돌아가 두 값들을 하나의 배열로 관리하도록 수정하였고, 문제를 해결할 수 있었습니다.

<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 +187,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
21 changes: 20 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,29 @@
<head>
<meta charset="UTF-8" />
<title>지하철 노선도 관리</title>
<style>
table {
border-collapse: collapse;
}
td {
padding: 2px;
border: 3px double black;
}

thead {
font-weight: bold;
}
</style>
</head>
<body>
<div>
<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>
</div>
<div id="app">
<h1>🚇 지하철 노선도 관리 </h1>
</div>
<script type="module" src="src/index.js"></script>
</body>
Expand Down
23 changes: 23 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import LineManager from "./pages/lineManager.js";
import PrintSubwayLine from "./pages/PrintSubwayLine.js";
import SectionManager from "./pages/SectionManager.js";
import StationManager from "./pages/StationManager.js";

export const elementMap = [
{
page: StationManager,
button: document.getElementById("station-manager-button"),
},
{
page: LineManager,
button: document.getElementById("line-manager-button"),
},
{
page: SectionManager,
button: document.getElementById("section-manager-button"),
},
{
page: PrintSubwayLine,
button: document.getElementById("map-print-manager-button"),
},
];
32 changes: 32 additions & 0 deletions src/core/Component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { dispatchReRender } from "../utils/events.js";

export default class Component {
constructor() {
this.state = {};
this.store = {};
}

setState(state) {
this.state = state;
dispatchReRender();
}

setStore(store) {
this.store = store;
localStorage.setItem("store", JSON.stringify(store));
dispatchReRender();
}

create() {
const store = localStorage.getItem("store");
if (store) {
this.store = JSON.parse(store);
}
}

afterCreate() {}

mount() {}

render() {}
}
20 changes: 20 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { dispatchReRender, RE_RENDER_EVENT } from "./utils/events.js";
import { elementMap } from "./config.js";
import reRenderPage from "./utils/reRenderPage.js";

function init() {
const app = document.querySelector("#app");
let page;

elementMap.forEach((element) => {
const managerPage = new element.page();
element.button.addEventListener("click", () => {
page = managerPage;
dispatchReRender();
});
});

window.addEventListener(RE_RENDER_EVENT, () => reRenderPage(app, page));
}

init();
Loading