katej927 / health-admin-app

[Team Project]

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

⛳ Health Admin Web

스크린샷 2022-06-02 오후 6 43 34

스크린샷 2022-06-02 오후 6 43 29


🗂 프로젝트 소개

  • 개발 기간 22.05.28 - 22.05.30
  • 팀원 강도희, 김민효, 박솔찬, 신가은, 이다슬, 이우성, 정규재, 정선미, 홍선영
  • 프로젝트 개요
    본 프로젝트는 모아데이타 선발 과제로 회원의 헬스 데이터를 볼 수 있는 관리자 웹페이지입니다.

💡 실행 방법

  1. repository clone

    git clone <https://github.com/wanted-pre-onboarding-FE-01/moa-health-admin.git>
    
  2. 해당 프로젝트 폴더로 이동

    cd moa-health-admin
    
  3. 필요 package들 설치

    yarn intall
    
  4. 프로젝트 실행

    yarn start
    
  5. 로그인 아이디, 비밀번호

    "name": "wooseong",
    "password": "1"
    

📁 폴더 구조

펼치기

📦src
┣ 📂assets
┃ ┗ 📂svgs
┃ ┃ ┣ 📜calendar.svg
┃ ┃ ┣ 📜circle_check.svg
┃ ┃ ┣ 📜circle_exclamation.svg
┃ ┃ ┣ 📜circle_info.svg
┃ ┃ ┣ 📜hide_password.svg
┃ ┃ ┣ 📜house_user_solid.svg
┃ ┃ ┣ 📜icon-arrow-down.svg
┃ ┃ ┣ 📜icon-arrow-left.svg
┃ ┃ ┣ 📜icon-arrow-right.svg
┃ ┃ ┣ 📜index.ts
┃ ┃ ┣ 📜logout.svg
┃ ┃ ┣ 📜show_password.svg
┃ ┃ ┣ 📜triangle_exclamation.svg
┃ ┃ ┣ 📜user_image.svg
┃ ┃ ┗ 📜user_solid.svg
┣ 📂components
┃ ┣ 📂datePicker
┃ ┃ ┣ 📂_shared
┃ ┃ ┃ ┣ 📂month
┃ ┃ ┃ ┃ ┣ 📜index.tsx
┃ ┃ ┃ ┃ ┗ 📜month.module.scss
┃ ┃ ┃ ┣ 📜constants.ts
┃ ┃ ┃ ┣ 📜index.ts
┃ ┃ ┃ ┣ 📜types.d.ts
┃ ┃ ┃ ┗ 📜utils.ts
┃ ┃ ┣ 📜datePicker.module.scss
┃ ┃ ┗ 📜index.tsx
┃ ┣ 📂popup
┃ ┃ ┣ 📜index.tsx
┃ ┃ ┗ 📜popup.module.scss
┃ ┣ 📂sideBar
┃ ┃ ┣ 📜index.tsx
┃ ┃ ┗ 📜sideBar.module.scss
┃ ┣ 📂whiteSection
┃ ┃ ┣ 📜index.tsx
┃ ┃ ┗ 📜whiteSection.module.scss
┃ ┗ 📜index.ts
┣ 📂constant
┃ ┗ 📜key.ts
┣ 📂data
┃ ┣ 📂heartrate_data
┃ ┃ ┣ 📜heartrate_136_0226_유령회원1번.json
┃ ┃ ┣ 📜heartrate_136_0308_유령회원1번.json
┃ ┃ ┣ 📜heartrate_136_0419_유령회원1번.json
┃ ┃ ┣ 📜heartrate_328_0416_유령회원2번.json
┃ ┃ ┣ 📜heartrate_328_0419_유령회원2번.json
┃ ┃ ┣ 📜heartrate_328_0420_유령회원2번.json
┃ ┃ ┣ 📜heartrate_380_0417_유령회원3번.json
┃ ┃ ┣ 📜heartrate_380_0418_유령회원3번.json
┃ ┃ ┣ 📜heartrate_380_0419_유령회원3번.json
┃ ┃ ┗ 📜heartrate_data_total.json
┃ ┣ 📂step_data
┃ ┃ ┣ 📜member_data.json
┃ ┃ ┣ 📜step_136_0226_유령회원1번.json
┃ ┃ ┣ 📜step_136_0308_유령회원1번.json
┃ ┃ ┣ 📜step_136_0419_유령회원1번.json
┃ ┃ ┣ 📜step_328_0416_유령회원2번.json
┃ ┃ ┣ 📜step_328_0419_유령회원2번.json
┃ ┃ ┣ 📜step_328_0420_유령회원2번.json
┃ ┃ ┣ 📜step_380_0417_유령회원3번.json
┃ ┃ ┣ 📜step_380_0418_유령회원3번.json
┃ ┃ ┣ 📜step_380_0419_유령회원3번.json
┃ ┃ ┗ 📜step_data.json
┃ ┣ 📜admin_data.json
┃ ┗ 📜member_data.json
┣ 📂hooks
┃ ┣ 📜useLogin.ts
┃ ┗ 📜useLogout.ts
┣ 📂routes
┃ ┣ 📂dashboard
┃ ┃ ┣ 📜dashboard.module.scss
┃ ┃ ┗ 📜index.tsx
┃ ┣ 📂detailMember
┃ ┃ ┣ 📂heartRateDataGraph
┃ ┃ ┃ ┣ 📜GRAPH_STYLE.ts
┃ ┃ ┃ ┣ 📜heartRateDataGraph.module.scss
┃ ┃ ┃ ┗ 📜index.tsx
┃ ┃ ┣ 📂stepDataGraph
┃ ┃ ┃ ┣ 📜GRAPH_STYLE.ts
┃ ┃ ┃ ┣ 📜formatGraphData.ts
┃ ┃ ┃ ┣ 📜index.tsx
┃ ┃ ┃ ┣ 📜stepDataGraph.module.scss
┃ ┃ ┃ ┗ 📜type.d.ts
┃ ┃ ┣ 📜detailMember.module.scss
┃ ┃ ┗ 📜index.tsx
┃ ┣ 📂layout
┃ ┃ ┣ 📜index.tsx
┃ ┃ ┗ 📜layout.module.scss
┃ ┣ 📂login
┃ ┃ ┣ 📜Checkbox.tsx
┃ ┃ ┣ 📜StoreID.tsx
┃ ┃ ┣ 📜index.tsx
┃ ┃ ┗ 📜login.module.scss
┃ ┣ 📂manageMember
┃ ┃ ┣ 📂_shared
┃ ┃ ┃ ┣ 📂searchMember
┃ ┃ ┃ ┃ ┣ 📜index.tsx
┃ ┃ ┃ ┃ ┗ 📜searchMember.module.scss
┃ ┃ ┃ ┗ 📂showMember
┃ ┃ ┃ ┃ ┣ 📜index.tsx
┃ ┃ ┃ ┃ ┗ 📜showMember.module.scss
┃ ┃ ┣ 📜index.tsx
┃ ┃ ┗ 📜manageMember.module.scss
┃ ┗ 📜index.tsx
┣ 📂states
┃ ┣ 📜index.ts
┃ ┣ 📜inquiryPeriod.ts
┃ ┣ 📜login.ts
┃ ┣ 📜searchMemberList.ts
┃ ┗ 📜selectMember.ts
┣ 📂styles
┃ ┣ 📂base
┃ ┃ ┣ 📜_fonts.scss
┃ ┃ ┣ 📜_more.scss
┃ ┃ ┗ 📜_reset.scss
┃ ┣ 📂constants
┃ ┃ ┣ 📜_colors.scss
┃ ┃ ┗ 📜_sizes.scss
┃ ┣ 📂mixins
┃ ┃ ┣ 📜_flexbox.scss
┃ ┃ ┗ 📜_visual.scss
┃ ┣ 📜index.js
┃ ┗ 📜index.scss
┣ 📂types
┃ ┣ 📜admin.d.ts
┃ ┗ 📜heartRate.d.ts
┣ 📂utils
┃ ┣ 📜getActiveBtn.ts
┃ ┣ 📜getDatesFromStartToLast.ts
┃ ┗ 📜login.ts
┣ 📜declaration.d.ts
┗ 📜index.tsx


🔨 기술 스택


라이브러리 내용 버전
classnames styles 관련 2.3.1
dayjs 날짜 관련 1.11.2
framer-motion 애니메이션 관련 6.3.3
react-use 리액트 편의 17.3.2
react-use-cookie 아이디 저장하기 1.4.0
store localStorage 편의 2.0.12
victory 차트 라이브러리 36.4.0


🏞 기능 설명

로그인

로그인 유틸

펼치기 로그인 로그아웃을 간단하게 훅스를 사용하는 방식으로 사용할 수 있도록 훅을 작성하여 사용
  • 로그인 훅스 (useLogin)
    • 기본적으로 로그인을 수행하는 util을 작성
    • 로그인 훅스에서 로그인 util을 사용하여 결과에 따라 로그인 상태를 변경하는 로직을 수행
    • 아이디, 비밀번호, 실패 핸들러 총 3개의 인자를 전달받아 로그인 유틸의 수행 결과에 따라 진행됨

  • 로그아웃 훅스 (useLogout)
    • 간단하게 로그아웃 훅을 통해 이벤트가 발생하면 한 번에 로그아웃 처리를 진행
    • 로그인 정보를 로컬스토리지에서 저장하기 때문에 로컬 스토리에서 데이터를 제거
    • 이후, 로그인 상태를 변경하여 페에지가 로그인 페이지로 전환됨
      • 상태가 비로그인 상태이기 때문

로그인 UI

펼치기 로그인 UI 및 관련된 기능을 구현
  • validation

    • 아이디 및 비밀 번호를 미입력시 focus out 및 로그인 버튼을 누를 때 미입력된 요소에 경고 메세지를 요소 하단에 표시한다.
    • 미입력된 요소가 있다면 버튼의 스타일이 활성화되지 않으며 버튼을 누르더라도 요소 하단에 경고 메세지만 표시하고 로그인 요청을 보내지 않는다.
  • 아이디 저장하기

    • 아이디 저장하기를 체크하면 로그인 로직을 통해 로그인이 성공했을 때 쿠키에 해당 아이디를 저장하고 다른 아이디로 새로 로그인할 경우 쿠키 값을 갱신한다.
    • 아이디 저장하기를 해제한다면 저장되어 있는 쿠키를 만료시킨다.

회원 관리

블라블라 작성하기


회원 관리 테이블

펼치기
  • 검색 조건에 따른 검색 결과를 Table 태그를 사용해 출력
const originMembers = useRecoilValue(searchMemberList);
const members = originMembers as IMember[];

...중략...

<p>전체  {members.length}명의 회원이 검색되었습니다.</p>
<div className={styles.tableWrapper}>
  <table>
    <thead>
      <tr>
        {header.map((headerName, index) => {
          const key = `${headerName}-${index}`;
          return <th key={key}>{headerName}</th>;
        })}
      </tr>
    </thead>
    <tbody>
      {members.map((member, index) => {
        const key = `${member}-${index}`;
        return (
          <tr key={key}>
            <td>{member.id}</td>
            <td>{member.crt_ymdt}</td>
            <td>{member.username}</td>
            <td>
              <Link to='/detailMember'>
                <button type='button' onClick={() => setSelectMember(member)}>
                  상세보기
                </button>
              </Link>
            </td>
          </tr>
        );
      })}
    </tbody>
  </table>
</div>
  • 특정 회원의 상세보기 버튼을 클릭하면 해당 회원의 정보를 Recoil에 담은 후 해당 회원의 상세 정보 페이지로 이동
export interface IMember {
  id: number;
  username: string;
  crt_ymdt: string;
}

export const selectMemberState = atom<IMember>({
  key: '#selectMemberState',
  default: {
    id: 0,
    username: '',
    crt_ymdt: '',
  },
});
const [, setSelectMember] = useRecoilState(selectMemberState);

회원 상세 정보

펼치기 - 회원 정보 테이블 - '회원 관리'페이지에서 관리자가 선택한 회원 정보 출력
  • 심박수 그래프
    • date picker로 선택된 날짜(startData,endDate) 값을 받아 해당되는 날짜의 심박수를 그래프로 표시
    • 선택한 기간이 하루일 때, 10분 단위로 심박수 표시
    • 선택한 기간이 2일 이상일 때, 일 단위로 심박수 표시

조회 기간 컴포넌트

펼치기
2022-05-31.2.36.53.mov

👉 자세히 보기

  • No Library

    • 직접 만든 date-range-picker
    • 이유: 최대한 기획된 디자인과 기능에 맞추기 위하여
  • 3개의 퀵버튼(오늘, 1주일, 전체) 구현

  • 페이지별 재사용

    • 회원 관리 페이지, 그래프 2개(심박 수, 걸음 수)
    • 개별적인 날짜 조회 가능 (컴포넌트별 state 모두 분리)
  • UI와 기능의 파일 분리

  • 정확한 날짜 표출

    • 표출되는 날짜에는 해당 날짜의 연/월/일 정보 보유 (단순 숫자 노출 x)

    • 코드 (한 달의 주차 별 날짜 배열 산출 방법)

      export const converteDate = (assignedDay: Dayjs) => {
        const firstWeek = assignedDay.startOf('month').week();
      
        const dates: Dayjs[] = Array.from(
          { length: assignedDay.daysInMonth() + assignedDay.startOf('month').day() },
          (v, index) => assignedDay.startOf('year').week(firstWeek).startOf('week').add(index, 'day')
        );
      
        const init: Dayjs[][] = [];
      
        let rowIdx = -1;
        return dates.reduce((acc, cur, i) => {
          if (!(i % 7)) {
            acc.push([cur]);
            rowIdx += 1;
          } else {
            acc[rowIdx].push(cur);
          }
          return acc;
        }, init);
      };

About

[Team Project]


Languages

Language:TypeScript 68.9%Language:SCSS 29.8%Language:HTML 1.1%Language:JavaScript 0.1%