Skip to content

Latest commit

 

History

History
147 lines (116 loc) · 7.69 KB

hw.md

File metadata and controls

147 lines (116 loc) · 7.69 KB

React 과제 2

  • 제출 기한: 11월 5일 저녁 24:00
  • (10/13) 제출 방법 추가
  • (11/02) 과자 정보에 제조사가 포함된다는 내용 삭제 (포함되지 않음)
  • (11/02) 테스트 및 관련 스펙 추가, 제출 기한 연장
  • (11/04) 누락된 testid 추가

과제 목적

  • Context API를 통해 전역 상태를 효과적으로 관리한다
  • React Router를 통해 클라이언트 라우팅 앱을 만든다

제출 방법

  • 과제1을 작업했던 기존의 레포(wafflw-react-hw1)에서 과제에서 새로 브랜치를 파서 진행합니다.
  • 과제1의 채점이 끝나면 main에 머지하고, main에서 새로운 브랜치 hw2를 파서 과제2 작업 내용을 푸시하세요.
  • 과제2가 완료되면 PR을 열고 세미나장과 조교에게 리뷰 리퀘스트를 걸어주세요.
    • 리뷰 리퀘스트를 걸지 않으면 제출 확인이 어려워 채점이 늦어질 수 있습니다.

과제 스펙

리뷰 및 과자 데이터는 Context API를 통해 전역으로 관리한다. 예를 들면 다음과 같은 모듈을 정의할 수 있다:

// src/contexts/SnackContext.tsx

export type SnackInput = ...
export type Snack = ...
export type ReviewInput = ...
export type Review = ...
export type SnackContextData = {
  snacks: Snack[];
  getSnackById: (id: number) => Snack;
  getSnackByName: (name: string) => Snack | null;
  filterSnacksByName: (query: string) => Snack[];
  addSnack: (snack: SnackInput) => Snack;

  reviews: Review[];
  ...
};

export function SnackProvider ...
export function useSnackContext ...

이전 과제를 바탕으로 아래 기능을 추가/수정한다:

  • 초기 데이터(리뷰, 과자)는 비워둔다.
  • 헤더 메뉴 (모든 페이지)
    • "리뷰"를 클릭하면 /로 이동
    • "과자"를 클릭하면 /snacks로 이동
    • 리뷰 페이지, 과자 페이지에서는 해당 메뉴가 굵게 표시된다
  • 리뷰 쓰기 (/, 모달로 처리)
    • 리뷰 쓰기 창에서 과자 이름은 자동완성된다.
      • 과자 이름을 한 글자 입력할 때마다 리스트가 바뀐다.
        • 입력된 문자열 query와 과자 이름 name에 대해 다음 값이 true인 것만을 포함하면 충분하다: name.replace(' ', '').includes(query.replace(' ', ''))
        • (보너스) 한글 자동완성을 구현해도 좋다. 단, 종성이 없는 한글 및 공백으로만 이루어진 입력/이름(예: 쿠크/쿠크다스)에 대해서는 위의 간단한 방법으로 비교한 것과 같은 결과가 나와야 한다.
      • 리스트의 길이가 너무 길어지지 않도록 한다.
      • 리스트의 항목을 클릭하면 입력창의 내용이 해당 이름으로 바뀐다.
      • 입력창이 포커스를 잃으면 0.2초 후에 리스트가 사라진다.
        • 리스트의 항목을 클릭하기 전에 리스트가 사라지는 것을 막기 위해 약간의 딜레이를 준다.
      • 리뷰 생성 버튼을 누를 때 과자 이름이 잘못된 경우 이전 과제에서처럼 오류 메시지를 보여준다.
    • 이미지 url는 따로 입력하지 않는다.
  • 새 과자 페이지 (/snacks/new)
    • 과자 이름, 이미지 url를 입력한다.
    • 각 입력의 조건은 이전 과제와 비슷하다:
      • 과자 이름: 첫글자와 끝글자가 공백이 아닌 1~20자의 문자열.
      • 이미지 url: 반드시 1자 이상의 문자열로 작성해야 한다.
    • (보너스) 이전 과제에서와 같이 미리보기 이미지를 띄울 수 있다.
    • 과자 이름은 중복될 수 없다.
    • 올바르게 입력한 후 1초가 지나서 "추가" 버튼을 누르면 과자가 추가되고 해당 과자의 페이지(/snacks/:id)로 이동한다.
    • 잘못된 입력을 한 후 "추가" 버튼을 누르면, 리뷰 쓰기 모달에서와 각각의 오류에 대해 같이 오류 메시지를 보여준다.
    • "취소" 버튼을 누르면 이전 페이지로 돌아간다.
  • 리뷰 목록 페이지 (/)
    • 과자 이름이나 사진을 클릭하면 과자 페이지로 이동한다.
    • 우하단의 "+" 버튼을 누르면 메뉴가 나타난다.
      • "새 리뷰" 버튼을 누르면 메뉴는 사라지고 리뷰 쓰기 모달이 나타난다.
      • "새 과자" 버튼을 누르면 새 과자 페이지로 이동한다.
    • 화면의 다른 곳을 클릭하거나 "x"로 바뀐 버튼을 누르면 메뉴가 사라진다.
      • (힌트) useEffect 함수로 전역 클릭 이벤트를 등록한다.
  • 과자 목록 페이지 (/snacks)
    • 과자들의 이름과 이미지, 평균 평점이 나타난다.
    • 평균 평점은 이번 과제의 경우 구현할 필요 없다.
  • 과자 페이지 (/snacks/:id)
    • 과자의 이름과 이미지,평점이 나타난다.
    • 과자에 달린 리뷰가 생성된 역순으로 나타난다.
    • 리뷰 페이지에서와 같이 수정 및 삭제가 가능하다.
  • 테스트
    • 과제1과 같이 과제2도 테스트를 통과해야 한다.
    • 기존 playwright.yml 파일을 새 파일로 교체한다.
    • 필요한 data-testid는 아래를 참고한다.

UI는 아래 이미지를 참고한다:

testid

  • 공통
헤더 로고 이미지 헤더 제목 리뷰 목록 페이지 링크 과자 목록 페이지 링크
header waffle-logo header-title review snack
  • 새 과자 / 새 리뷰 버튼
녹색 '+' 버튼 (또는 적색 'x' 버튼) 새 과자 버튼 새 리뷰 버튼
open-menu new-snack new-review
  • 리뷰 쓰기 모달
리뷰 쓰기 모달 이름 입력창 이름 오류 메시지 별점 입력창 별점 오류 메시지
write-review-modal name-input name-input-message rating-input rating-input-message
내용 입력창 내용 오류 메시지 작성 버튼 취소 버튼 자동완성 목록
content-input content-input-message submit-review cancel-review snack-name-compl-list
  • 리뷰 목록 (리뷰 목록 페이지 및 과자 페이지)
리뷰 목록 리뷰 항목 리뷰 수정 버튼 리뷰 삭제 버튼 리뷰 수정 저장 버튼
review-list review edit-review delete-review edit-review-save
리뷰 수정 취소 버튼 리뷰 수정 입력창 과자 이름 과자 이미지 평점
edit-review-cancel edit-review-content-input snack-name snack-image rating
  • 리뷰 삭제 모달 (리뷰 목록 페이지 및 과자 페이지)
삭제 버튼 취소 버튼
delete-review-delete delete-review-cancel
  • 새 과자 페이지
이미지 주소 입력창 과자 이름 입력창 과자 이름 오류 메시지 추가 버튼 취소 버튼
image-input name-input snack-name-error add-button cancel-button
  • 과자 페이지 / 과자 목록 페이지
과자 항목 (과자 정보 상자) 과자 이미지 과자 이름 평점
snack-card snack-image snack-name rating