[ React ] TimeTable 시간표 컴포넌트 구현

2024. 6. 24. 12:25· React
목차
  1. 아이디어
  2. 시간표 레이아웃
  3. 예약 정보 구현
  4. 모바일 화면 구분
728x90

마땅한 라이브러리가 없어 직접 만들어봤다.

 

 

아이디어

시간과 구분선은 같은 컴포넌트 내부에 작성하여 미리 시간표 레이아웃을 만들어 두고 그 외 예약 정보는 absolute로 적용한다.

 


 

시간표 레이아웃

<TimeList>
  {TIMELIST.map((time) => (
    <div>
      <span key={time}>{time}</span>
      <hr />
    </div>
  ))}
</TimeList>
export const TimeList = styled.div`
  ${flexBox("column", "start", "start")};
  color: ${({ theme }) => theme.colors.gray};
  gap: 4rem;
  width: 100%;
  height: 100%;

  div {
    ${flexBox()};
    width: 100%;
    height: 1rem;

    span {
      width: 4rem;
    }

    hr {
      flex: 1;
      height: 1px;
      border: none;
      background-color: ${({ theme }) => theme.colors.grayBg};
    }
  }
`;

 

시간표 레이아웃의 하단 부에 어느 정도의 여백을 두어 Nav 바와 간격을 가지는 것이 좋다고 생각했다.

그러나 스크롤이 있는 div에는 padding이나 margin이 적용되지 않는다.

 

→ 대신 마지막 div에 padding 적용하여 공백을 생성했다.

 

  div:nth-last-child(1) {
    padding-bottom: 2rem;
  }

또는

  div:last-child {
    padding-bottom: 2rem;
  }

※ 위 두가지 가상 선택자는 의미가 같음

 

 

 

 


 

예약 정보 구현

const ReserveItem = (item: ReserveInfo, room: number) => {
  // 시작 위치
  const top = TIMELIST.findIndex((time) => time === item.startTime);

  // 높이
  const [startHour, startMinute] = item.startTime.split(":").map(Number);
  const [endHour, endMinute] = item.endTime.split(":").map(Number);
  const diff = (endHour - startHour) * 2 + Number(startMinute !== endMinute);

  return (
    <TimeTableItem
      key={item.startTime}
      $room={room}
      $top={top}
      $space={diff}
      $color={GroupColor(item.userGroup)}
    >
      <span>
        {item.startTime} ~ {item.endTime}
      </span>
      <p>
        {item.userGroup} {item.userName} {item.userRank}
      </p>
    </TimeTableItem>
  );
};
  1. 시작 위치
    • TIMELIST 배열에서 startTime의 index를 찾아 위치(top)을 구해준다.
  2. 높이
    • endTime과 startTime의 차이를 이용해서 몇 칸을 차지할 지를 구해준다.
    • 한 칸은 30분을 의미하므로, 시간 단위와 분 단위를 나누어 계산했다.
      • 시간의 경우 → 차 * 2
      • 분의 경우 → 일치 여부
export const TimeTableItem = styled.div<{
  $top?: number;
  $space?: number;
  $room?: number;
  $color?: string;
}>`
  position: absolute;
  width: calc((100% - 8rem) / 3);
  height: ${({ $space }) => `calc(5rem * ${$space})`};
  left: ${({ $room }) => `calc(6rem + ((100% - 8rem) / 3) * ${$room})`};
  top: ${({ $top }) => `calc((1.5rem + 5rem * ${$top}))`};
  background-color: ${({ theme, $color }) => theme.teamColors[`${$color}Soft`]};

  border-radius: 4px;
  padding: 1rem 1.5rem;
  border-left: 3px solid ${({ theme, $color }) => theme.teamColors[`${$color}Hard`]};

  span {
    color: ${({ theme }) => theme.colors.gray};
    font-size: 0.8rem;
  }

  p {
    ${fontStyle("Button")};
    color: ${({ theme, $color }) => theme.teamColors[`${$color}Hard`]};
  }
`;
  1. width
    • hr의 길이를 3등분한 것이 각 한 칸의 크기가 된다.
    • 부모요소의 너비(100%)에서 양쪽 padding과 span 만큼의 크기를 뺀 너비에서 나누기 3을 해줬다.
  2. height
    • gap(4rem)과 hr이 가지는 너비(0.5rem + 0.5rem) → 5rem
    • $space 칸만큼 곱해줬다.
  3. left
    • 회의실 종류에 따라 width 만큼 옆으로 이동시켰다.
  4. top
    • 가장 최초의 공백(padding-top: 1rem + div 크기 절반: 0.5rem ⇒ 1.5rem)
    • 한 칸의 크기 5rem

 

 

 

 


 

모바일 화면 구분

모바일 화면의 경우 3가지 예약 정보가 모두 들어가기엔 좁다고 판단하여 탭 구분을 통해 나눠줬다.

이때 isSelected 변수와 display: none 속성을 활용했다.

<TimeTableItem
  key={item.startTime}
  $room={room}
  $top={top}
  $space={diff}
  $color={GroupColor(item.userGroup)}
  $isSelected={selectedRoom === room}
>

TimeTableItem에 $isSelected 속성 추가

// 모바일의 경우, 선택된 회의실만 보여줌
@media ${({ theme }) => theme.device.mobile} {
  width: calc(100% - 6rem);
  left: 5rem;
  display: ${({ $isSelected }) => ($isSelected ? "block" : "none")};
}

 

728x90

'React' 카테고리의 다른 글

[ React ] 검색 가능한 SelectBox 컴포넌트 구현  (0) 2024.07.04
[ React ] 기본 SelectBox 컴포넌트 구현  (1) 2024.07.03
[ React ] weekSelector 컴포넌트 구현  (0) 2024.06.21
[ React ] useRef로 영역 외 클릭 시 감지 기능 구현하기  (0) 2024.06.19
[ React ] DatePicker 컴포넌트 직접 만들기  (0) 2024.06.17
  1. 아이디어
  2. 시간표 레이아웃
  3. 예약 정보 구현
  4. 모바일 화면 구분
'React' 카테고리의 다른 글
  • [ React ] 검색 가능한 SelectBox 컴포넌트 구현
  • [ React ] 기본 SelectBox 컴포넌트 구현
  • [ React ] weekSelector 컴포넌트 구현
  • [ React ] useRef로 영역 외 클릭 시 감지 기능 구현하기
ZoD
ZoD
바쁘게 굴러가는 ZoD의 하루~
ZoD
como siempre
ZoD
  • 분류 전체보기 (173)
    • Daily (0)
    • Javascript (16)
      • 모던 자바스크립트 (46)
    • Typescript (8)
    • FrontEnd (7)
    • React (21)
      • tanstack query (1)
      • 라이브러리 (3)
    • Vue (33)
      • Nuxt (11)
      • Quasar (6)
    • CSS (12)
    • Storybook (8)
    • Figma (3)
    • CS 지식 (5)
    • Network (5)
    • 알고리즘 (2)
    • 사이드 프로젝트 (4)
      • ddangkong (4)
      • boncierge (0)
    • 개발, 근데 이제 헛소리를 곁들인 (1)
    • ETC (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

인기 글

최근 글

hELLO · Designed By 정상우.v4.2.2
ZoD
[ React ] TimeTable 시간표 컴포넌트 구현
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.