코드잇 스프린트 : 프론트엔드 4기 Part3 - Tenten(10팀)
프로젝트명 : Synergy(The Julge)
프로젝트 소개 : 급하게 일손이 필요한 자리에 더 많은 시급을 제공해서 아르바이트생을 구할 수 있는 서비스
개발 기간: 2024. 4. 15 ~ 5. 1
[팀장] 김예진 |
[팀원] 이유진 |
[팀원] 이재성 |
[팀원] 조한빈 |
[팀원] 하태훈 |
분류 | 기술 |
---|---|
프레임워크 | |
언어 | |
Styles | |
HTTP | |
코드 컨벤션 | |
협업 Tools | |
배포 | |
라이브러리 및 추가 Extension |
-
맞춤 공고
- 로그인하지 않은 상태거나 사장일 경우 보여주지 않음
- 알바로 로그인했을 때 내 프로필을 등록하지 않았을 경우, 선호 지역을 선택하지 않았을 경우 내 프로필로 이동해 등록할 수 있게 박스 표시
- 선호 지역이 있을 경우 해당하는 지역 공고 중 마감되지 않은 공고를 최대 8개를 보여주지만 8개가 채워지지 않았을 경우 인근 지역 데이터도 보여줌
- 인근 지역에도 공고가 없을 경우 공고가 없다는 문구 표시
- 한 번에 3개가 보이고 시간이 지나면 하나씩 넘어간다(테블릿, 모바일에서는 한번에 2개보여줌)
-
정렬 및 상세 필터
- 정렬
- 4가지로 정렬 가능
- 상세 필터
- 위치, 시작일, 금액에 값을 입력하면 그에 해당하는 데이터를 보여주고 선택한 필터 개수에 따라 버튼에 개수 표시
- 자유로운 주소 선택, 삭제. 선택한 주소는 표시해서 구분
- 사용자 경험을 고려해 시작일은 오늘로 설정 되어있고, 초기화해서 지난 공고를 볼 수도 있음
- 정렬
-
페이지네이션
- offset, limit 값을 받아와서 페이지 번호를 누를 때마다 데이터를 받아온다
- 사용자 입장을 고려해 화살표를 눌렀을 시 다음 섹션(최대 7개의 페이지를 보여줄 경우 1~7에서 화살표를 누르면 8로)으로 이동한다
- 페이지 이동시 공고의 상단으로 이동해 사용자가 보기 편하도록 설정
- 검색창에 값을 입력하고 엔터를 누르면 쿼리값을 이용해 검색어에 해당하는 공고를 보여주는 페이지
- 스피너
- 사용자 입장을 고려해 로딩되는 동안 나타나는 화면요소 구현
- 프로필 데이터, 알바의 신청내역 데이터를 GET Method를 통해 받아들임
- userId, token이 없거나, userType이 employee가 아닐 경우 메인페이지로 redirect
- 등록된 프로필이 없으면 '프로필을 등록하세요' 렌더링
- 프로필은 있으나 신청 내역이 없으면 '신청내역이 없어요' 렌더링
- 사장의 지원자 내역 데이터를 GET Method를 통해 받아들임
- 지원자가 있으면 table 렌더링, 없으면 '신청자가 없어요' 요소 렌더링
- AlarmSet, AlarmContainer Component
- 알람 데이터 GET, 알람 읽으면 읽음처리 PUT
- 알람 읽거나, 알람아이콘을 누르면 클라이언트 사이드에서 재렌더링
- 알람 데이터에서 알바 본인이 취소한 알람은 filter
- 읽지 않은 알람 유무에 따라 알람 아이콘 다르게 구현
- getFromTime함수 구현
- Label Component
- 위치라벨과 상태라벨을 공통 컴포넌트로 추상화
- NoList Component
-
ApplyTable Component
- 반응형 구현
- userType에 따른 데이터 다루기
- 사장이 승인하기/거절하기 버튼 누르면 모달 띄우기, 모달의 ‘예’ 누르면 status 바꾸기
- 클라이언트 사이드에서 바로 바뀌도록 구현
- 사장이 승인하기 버튼 누르면 pending중인 다른 지원들은 거절 라벨로 보이도록 구현
- 클라이언트 사이드에서 바로 바뀌도록 구현
- 페이지네이션 연결
-
MyProfile Component
- react-hook-form 라이브러리를 활용한 입력값 관리
- 입력값 리스트 : 이름, 연락처, 선호지역, 자기소개
- 필수 입력값을 설정하지 않고 제출 시 에러 메세지 노출
- 연락처의 경우 010-0000-0000 의 형식을 지키지 않을 시 에러 메세지 노출
- 선호지역의 경우 Dropdown 형식으로 UI 구성
- 자기소개의 경우 글자 수를 제한하여 초과할 시 텍스트 입력을 막음
- 내 프로필 등록 및 수정 페이지는 같은 페이지를 공유하며 url의 쿼리값으로 등록, 수정 여부를 판단
- 등록 페이지 (/myprofile/register), 수정 페이지(/myprofile/register/?action=edit)
- 수정 페이지로 판단 될 시 기존 유저의 정보를 fetch 하여 입력창의 기본값으로 설정
- 수정 페이지 진입 시 유저 정보가 fetch 되기 전까지 spinner를 구현하여 유저 편의성 고려
- 모든 입력값을 준수하고 제출 시 API 성공 여부에 따라 확인 모달창에 메세지 노출
- 내 프로필 등록이 되어 있는데 url로 등록 페이지 접근 시 ‘/’ 루트 페이지로 redirect 되도록 구현
- 입력값 리스트 : 가게이름, 분류, 주소, 상세주소, 가게이미지, 기본시급, 가게설명
- 필수 입력값을 설정하지 않고 제출 시 에러 메세지 노출
- 기본 시급의 경우 24년 기준 최저임금 이하로 입력 시 에러메세지 노출
- 가게 이미지
- S3 외부 클라우드 저장소를 이용하여 이용자가 첨부한 사진 파일을 이미지 url로 변환하여 사용
- 가게 이미지 Box를 클릭하면 display: none; 으로 설정되어있던 file type의 input의 Ref를 참조하여 click 이벤트가 발생하게 구현
- 자기소개의 경우 글자 수를 제한하여 초과할 시 텍스트 입력을 막음
- 가게 분류와 주소는 Dropdown 형식으로 UI 구성
- 내 가게 등록 및 수정 페이지는 같은 페이지를 공유하며 url의 쿼리값으로 등록, 수정 여부를 판단
- 등록 페이지(/myshop/register), 수정 페이지(myshop/register/?action=edit)
- 수정 페이지로 판단 될 시 기존 가게 정보를 fetch 하여 입력창의 기본값으로 설정
- 수정 페이지 진입 시 가게 정보가 fetch 되기 전까지 spinner를 구현하여 유저 편의성 고려
- 모든 입력값을 준수하고 제출 시 API 성공 여부에 따라 확인 모달창에 메세지 노출
- 내 가게가 등록되어 있는데 url로 등록 페이지 접근 시 ‘/’ 루트 페이지로 redirect 되도록 구현
- 입력값 리스트 : 시급, 시작일시, 업무시간, 공고 설명
- 필수 입력값을 설정하지 않고 제출 시 에러 메세지 노출
- 시급의 경우 가게 정보를 등록할 때의 기본 시급보다 낮은 금액은 설정하지 못하도록 구현
- 시작일시
- react-datePicker 라이브러리를 사용하여 시작일시 값을 선택할 수 있도록 구현
- react-hook-form과 연결하기 위해 제공되는 Controller 컴포넌트를 사용하여 react-datePicker 라이브러리와 연동하였음
- 날짜와 시간대를 선택할 수 있음
- 현재 시간보다 이전 시간을 선택할 경우 에러 메세지 노출
- 공고 설명의 경우 글자 수를 제한하여 초과할 시 텍스트 입력을 막음
- 내 가게 공고 등록 및 수정 페이지는 같은 페이지를 공유하며 url의 쿼리값으로 등록, 수정 여부를 판단
- 공고 등록 페이지(/myshop/register/notice), 공고 수정 페이지(/myshop/register/notice?noticeId=${noticeId})
- 수정 페이지로 판단 될 시 기존 공고 정보를 fetch 하여 입력창의 기본값으로 설정
- 수정 페이지 진입 시 공고 정보가 fetch 되기 전까지 spinne를 구현하여 유저 편의성 고려
- 모든 입력값을 준수하고 제출 시 API 성공 여부에 따라 확인 모달창에 메세지 노출
- 공고 수정 완료 시 작성된 공고 상세 페이지로 이동
- 공고 등록 시 내 가게 페이지로 이동하여 생성된 공고 리스트 노출
- Header Component
- 로고, 검색창 및 내 가게(내 프로필), 로그아웃, 로그인 및 회원가입 버튼으로 구성되어 있는 상단 고정 component
-
가게상세와 공고상세에 공통적으로 쓰일 Box 구현
- 버튼 갯수나 쓰임새의 경우의 수가 많아서 버튼을 children으로 배치
- 로그인을 통해 저장된 cookie를 바탕으로 하여, 유저 종류 및 가게의 마감 여부 등에 따라 버튼을 렌더링 하도록 조건식 작성
-
시급 인상율 뱃지 제작
- 카드에서 보여질 때와 페이지에서 보여질 때 디자인 구별
- 시급이나 인상율 텍스트가 길어져서 생략될 경우 (text-overflow) 호버 시 전제 텍스트 표시
-
등록한 공고는 무한스크롤 방식으로 로드
- Intersection Observer 사용, 클라이언트 컴포넌트화
-
내 가게 페이지
- '/myshop' layout 단계에서 유저타입 검사 후 사장이 아니면 루트 페이지로 리다이렉트
-
공고 상세보기 페이지(알바)
- 최근에 본 공고를 로컬스토리지에 JSON 객체로 저장
- 중복을 없애고, 최신순 정렬하기 위한 로직 구현
- Modal Component
- 경고, 로그아웃 등의 경고 및 알림을 나타내기 위한 컴포넌트
- 프로젝트 배포 및 배포 시 발생하는 오류 검토
- react-hook-form을 활용하여 로그인, 회원가입 페이지 제작
- setCookies 생성
- 로그인 시, u_id(userID), s_id(shopID), userType, token이 cookie에 자동으로 설정할 수 있도록 setCookies 생성
- 기본 쿠키(알바생, 사장님 공통) : u_id, userType, token 생성
- userType === employer : 내 가게 등록 여부에 따라 cookie에 s_id 추가
- 로그인 시, u_id(userID), s_id(shopID), userType, token이 cookie에 자동으로 설정할 수 있도록 setCookies 생성
- Input Component
- label 등 설정 가능
- label의 내용에 따라 input box에 ‘원’, ‘시간’ 단위 추가
- type === password : eyeIcon 추가, 비밀번호가 보이도록 설정 가능
- Button Component
- props에 색상, 크기, 내용, button type 설정 가능
- TypeSelector Component
- 회원가입에서 userType 설정
- 알바생 : employee, 사장님 : employer
- Toast Component
- 로그인, 회원가입에서 성공, 경고 여부 출력
- 기본 Toast 유지 시간 : 1.5초
- Footer Componet
- 반응형 동작 구현
- Header에서 로그아웃 시, 로그아웃 진행
- 로그아웃 버튼 클릭 시, modal 화면을 통하여 다시한번 로그아웃 여부 확인
- 로그인 시 Header 구성 요소 조건 추가
- userType, token 쿠키를 받아와서 token 존재 여부 및 userType에 따라 버튼 결정
- 검색 후 다른 페이지 접근 시 검색창의 내용 초기화
- usePathname() 사용
- 로그인할 때 쿠키에 저장되는 값(userType)으로 알바생, 사장님 구분
- 각 페이지에서 쿠키 값을 가져와 조건부 렌더링으로 구현
- 각 페이지에서는 쿠키 값 참조를 위해 SSR로 구현
- 데이터 변화 시 리렌더링을 위해 컴포넌트 분리 후 CSR로 설정
- 쿠키 값은 props로 넘겨받음
- 입력 필드에 register 함수를 적용했음에도 입력 값이 제대로 등록되지 않음
- onSubmit 이벤트를 처리하면서, 폼 제출 시 사용자 입력 데이터를 올바르게 처리하지 못함
- form 태그의 props에서 handleSubmit을 활용함으로 문제 해결
- input field에 React Hook Form과 연결하고, 폼 제출 시 입력 값을 검색할 수 있도록 적용