Skip to content

Commit

Permalink
[2단계 - 음식점 목록] 우디(류정우) 미션 제출합니다. (#56)
Browse files Browse the repository at this point in the history
* docs: 프로젝트 실행 순서 작성

* refactor(App): 새로운 음식점 추가 모달을 열 때 해당 form의 내용을 초기화 하도록 수정

* refactor(App): filterd 오타 filtered로 수정

* refactor(App): 생성자에서 이벤트를 등록하는 메서드의 네이밍을 init에서 registerEvents로 변경

* refactor(App): 새로운 음식점을 추가할 때, 현재 선택된 카테고리와 새로운 음식점의 카테고리가 같은 경우에만 render하도록 변경

* refactor: as const 를 사용해 상수를 선언하고, 해당 상수로부터 타입을 정의하도록 변경

* refactor: Header의 렌더링, 담당하는 이벤트와 그에 대한 처리를 Header 컴포넌 트로 분리

* feat: filter category 타입과, filter categories 상수 추가

* refactor(RestaurantItem): 생성자안에서 음식점을 하나씩 렌더하는 클래스로 변경

* refactor(RestaurantList): 파일명을 RestaurantItems로 변경, 인스턴스로 생성될 때, 넘겨받은 음식점들로 각각의 음식점을 렌더하는 클래스로 변경

* refactor: 음식점 생성 Form과 그에 관련된 이벤트들을 컴포넌트로 분리

생성자들의 조합으로 앱을 구현할 수 있을거라 생각했지만 그러지 못했다. 전역에서 상태를 관리한다면 가능할 것 같다는 생각이 든다

* refactor: 컴포넌트내 이밴트가 발동했을 때 실행되는 메서드를 직접 가지지않고 App에서 넘겨받도록 변경

* feat: 상단 탭 네비게이션 html과 스타일 구현

* feat: 상단 네비게이션 탭 컴포넌트 생성, 클릭했을 때 스타일을 변경하는 기능 구현

* refactor: RestaurantItem에 cursor pointer 적용

* feat: 음식점에 liked 타입 추가, liked 프로퍼티가 true인 음식점을 반환하는 기능 구현

* feat: 음식점을 생성할 때, liked 프로퍼티를 기본값 false로 추가하도록 변경

* refactor: App에 상태를 두고 상태가 변환되면 변경된 상태에 따라 음식점 목록을 렌더링하도록 변경

* refactor: 카테고리, 정렬 옵션이 변하면 상태를 설정하고 렌더하는 setState를 실행하도록 변경

* refactor: Restaurant에 id 프로퍼티 추가

* feat: 채워져있는 별을 누르면 빈 별로, 빈 별을 누르면 채워져있는 표시하는 기능 구현

* refactor: 음식점 컴포넌트를 렌더 시, like 프로퍼티가 true라면 채워져있는 별을 표시하도록 변경

* feat: 자주가는 음식점 탭을 클릭했을 때, 필터 컨테이너를 숨기는 기능 구현

* feat: 음식점 컴포넌트의 별을 클릭했을 때, 해당 음
식점의 id를 사용해 전체 음식점이 담긴 배열을 업데이트하는 기능 구현

* refactor: hidden 클래스에 대해 visible이 아닌 display: none 적용

* fix: upper-tap 오타 upper-tab으로 수정

* feat: 음식점 컴포넌트를 클릭했을 때의 처리 구현

* refactor: 음식점 컴포넌트에 liked 프로퍼티 제거 후, restaurant 데이터로 기능 구현

* feat: 음식점 디테일 모달에 별 삽입

* feat: 음식점 id를 사용해 음식점을 제거하는 로직 구현

* feat: 음식점 디테일 모달에서 삭제 버튼으로 음식점을 삭제하는 기능 구현

* feat: 음식점이 삭제되면 해당 컴포넌트의 태그를 remove하는 기능 구현

* refactor: toggleModal 메서드의 네이밍을 toggleAddRestaurantModal로 변경

* refactor: 음식점의 id를 li태그의 class가 아닌 id로 할당

* refactor: 음식점 item 하나하나에서 click 이벤트를 조작하지 않고 items에서 이벤트 버블링을 하도록 변경

* refactor: header 태그를 정적으로 두고 내부의 html을 정적으로 삽입하도록 변경

* refactor: 컴포넌트 안의 메서드를 App파일에 구현

* refactor: imgFileName을 constants 폴더로 분리

* test: E2E 테스트 set up

* refactor(onClickNavTab): navElements를 가져올 때, 선택자가 아닌 클래스 선택자를 사용해서 가져오도록 변경

DOM 구조가 변경됐을 때, 해당 코드도 변경이 필요하기 변경이 적은 클래스 선택자를 사용

* refactor(store): 범용성을 높이기 위해, key와 item을 외부에서 주입받도록 변경

* refactor(App): filter-container의 활성화, 비활성화를 setState 메서드에서 수행하도록 변경

* refactor(App): setState가 실행되면 변경된 state 의 속성에 따라 로직을 수행하도록 변경

인자로 받은 obj를 key값 배열로 변환하여 첫번째 값을 이용해주기 보다, this.state.navTab === '자주 가는 음식점' 과 같이 신뢰할을 사용하도록 수정

* refactor(App): 즐겨찾기 버튼을 눌렀을 때, 채워진 별을 표시하거나 숨기는 기능을 메서드로 분리

* refactor(App): dom.closest를 사용할 때, 선택자가 아닌 클래스 선택자를 사용하도록 변경

* refactor(dom): 매개변수의 이름을 element에서 queryString으로 변경

* refactor(RestaurantFilterContainer): App의 하위 클래스에 직접적으로 setState를 수정할 권한을 줘서 이벤트 콜백 함수를 구현하지 않고, App으로부터 이벤트에 대한 콜백 함수를 넘겨받도록 변경
  • Loading branch information
jw-r committed Mar 15, 2023
1 parent 6f96d6b commit a60706b
Show file tree
Hide file tree
Showing 29 changed files with 4,971 additions and 7,888 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,36 @@
# javascript-lunch

우아한테크코스 레벨1 점심 뭐 먹지 미션

---

## 😀데모 페이지에서 바로 즐기기 :)

[🎯데모 페이지](https://evencoding.github.io/javascript-lunch/)

---

## 어플리케이션 실행 방법

### 1. 패키지 다운받기

```bash
npm i
```

위 명령어로 필요한 패키지를 다운로드해 주세요!

### 2. 프로젝트 실행

```bash
npm run start
```

위 명령어를 터미널에 입력해주세요!

### 3. 점심 메뉴를 등록해보세요!

```
추가한 음식점은 로컬스토리지에 저장됩니다!
새로고침 시 저장된 데이터를 읽어옵니다!
```
9 changes: 9 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from "cypress";

export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
9 changes: 9 additions & 0 deletions cypress/e2e/spec.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
describe('template spec', () => {
before(() => {
cy.visit('http://localhost:8080/');
});

it('', () => {
cy.get('.modal-open-button').click();
});
});
5 changes: 5 additions & 0 deletions cypress/fixtures/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
37 changes: 37 additions & 0 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
20 changes: 20 additions & 0 deletions cypress/support/e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
96 changes: 7 additions & 89 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,104 +8,22 @@

<body>
<!-- GNB -->
<header class="gnb">
<h1 class="gnb__title text-title">점심 뭐 먹지</h1>
<button type="button" class="modal-open-button gnb__button" aria-label="음식점 추가">
<img src="./add-button.png" alt="음식점 추가" />
</button>
</header>
<header class="gnb"></header>

<main>
<!-- 카테고리/정렬 필터 -->
<section class="restaurant-filter-container">
<select name="category" id="category-filter" class="restaurant-filter">
<option value="전체">전체</option>
<option value="한식">한식</option>
<option value="중식">중식</option>
<option value="일식">일식</option>
<option value="양식">양식</option>
<option value="아시안">아시안</option>
<option value="기타">기타</option>
</select>
<nav class="upper-tab"></nav>

<!-- 정렬 셀렉트 박스 -->
<select name="sorting" id="sorting-filter" class="restaurant-filter">
<option value="name">이름순</option>
<option value="distance">거리순</option>
</select>
</section>
<!-- 카테고리/정렬 필터 -->
<section class="restaurant-filter-container"></section>

<!-- 음식점 목록 -->
<section class="restaurant-list-container"></section>

<!-- 음식점 추가 모달 -->
<div class="modal">
<div class="modal-backdrop"></div>
<div class="modal-container">
<h2 class="modal-title text-title">새로운 음식점</h2>
<form class="add-restaurant-form">
<!-- 카테고리 -->
<div class="form-item form-item--required">
<label for="category text-caption">카테고리</label>
<select name="category" id="category" required>
<option value="">선택해 주세요</option>
<option value="한식">한식</option>
<option value="중식">중식</option>
<option value="일식">일식</option>
<option value="양식">양식</option>
<option value="아시안">아시안</option>
<option value="기타">기타</option>
</select>
</div>

<!-- 음식점 이름 -->
<div class="form-item form-item--required">
<label for="name text-caption">이름</label>
<input type="text" name="name" id="name" required />
</div>

<!-- 거리 -->
<div class="form-item form-item--required">
<label for="distance text-caption">거리(도보 이동 시간) </label>
<select name="distance" id="distance" required>
<option value="">선택해 주세요</option>
<option value="5">5분 내</option>
<option value="10">10분 내</option>
<option value="15">15분 내</option>
<option value="20">20분 내</option>
<option value="30">30분 내</option>
</select>
</div>

<!-- 설명 -->
<div class="form-item">
<label for="description text-caption">설명</label>
<textarea name="description" id="description" cols="30" rows="5"></textarea>
<span class="help-text text-caption">메뉴 등 추가 정보를 입력해 주세요.</span>
</div>

<!-- 링크 -->
<div class="form-item">
<label for="link text-caption">참고 링크</label>
<input type="text" name="link" id="link" />
<span class="help-text text-caption"
>매장 정보를 확인할 수 있는 링크를 입력해 주세요.</span
>
</div>
<div class="modal add-restaurant-modal"></div>

<!-- 취소/추가 버튼 -->
<div class="button-container">
<button
type="button"
class="modal-close-button button button--secondary text-caption"
>
취소하기
</button>
<button class="button button--primary text-caption">추가하기</button>
</div>
</form>
</div>
</div>
<!-- 음식점 디테일 모달 -->
<div class="modal restaurant-detail-modal"></div>
</main>
</body>
</html>
Loading

0 comments on commit a60706b

Please sign in to comment.