Skip to content

Commit

Permalink
feat: create Slot Component (#19)
Browse files Browse the repository at this point in the history
* feat: Slot 컴포넌트 관련 유틸 함수 구현
* refactor:  Task type을 공통 type으로 분리
* design: Slot 관련 css 속성 추가
* feat: TimeSlot 컴포넌트 구현
* feat: TimeSlot 컴포넌트 구현
* feat: Slot 컴포넌트 구현
* refactor: calculateTaskOffsetAndHeightPercent 함수 반환값 변경
  • Loading branch information
dmdgpdi authored Jul 31, 2024
1 parent cbd30aa commit bbc38a1
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/timetable/components/Slot.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.slot {
display: flex;
gap: 10px;
}

.timeSlotLayout {
position: relative;
flex: 0 1 10%; // flex-grow: 0, flex-shrink: 1, flex-basis: 10%
min-width: 50px;
max-width: 70px;
height: 100%;
}

.headerDate {
position: absolute;
top: -0.5em;
margin: 0;
padding: 0;
}

.taskSlotLayout {
box-sizing: border-box;
position: relative;
flex: 1 1 90%; // flex-grow: 1, flex-shrink: 1, flex-basis: 90%
min-width: 100px;
height: 100%;
}

.taskSlotBackground {
position: absolute;
width: 100%;
z-index: 0;
}

.taskSlotContent {
z-index: 20;
position: relative;
}

.title {
font-size: 1.25rem;
margin: 20px 0;
}

.description {
font-size: 1rem;
margin: 20px 0;
}
21 changes: 21 additions & 0 deletions src/timetable/components/Slot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import TimeSlot from '@/timetable/components/TimeSlot';
import TaskSlot from '@/timetable/components/TaskSlot';
import type { Task } from './Timetable.type';
import styled from './Slot.module.scss';

interface SlotProps {
headerDate: Date;
slotTime: number;
taskItem: Task | undefined;
}

function Slot({ headerDate, slotTime, taskItem }: SlotProps) {
return (
<div className={styled.slot}>
<TimeSlot headerDate={headerDate} />
<TaskSlot headerDate={headerDate} slotTime={slotTime} taskItem={taskItem} />
</div>
);
}

export default Slot;
49 changes: 49 additions & 0 deletions src/timetable/components/TaskSlot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { add } from 'date-fns';
import { calculateTaskOffsetAndHeightPercent } from '@/timetable/utils';
import styled from './Slot.module.scss';
import type { Task } from './Timetable.type';

interface TaskSlotProps {
headerDate: Date;
slotTime: number;
taskItem: Task | undefined;
}

function TaskSlot({ headerDate, slotTime, taskItem }: TaskSlotProps) {
if (!taskItem) {
return <div className={styled.taskSlotLayout} />;
}

const { startTime, endTime, slotColor, title, subTitle } = taskItem;

const slotStartTime = headerDate;
const slotEndTime = add(headerDate, { minutes: slotTime });

const { offsetPercent, heightPercent } = calculateTaskOffsetAndHeightPercent(
slotStartTime,
slotEndTime,
startTime,
endTime,
slotTime,
);

return (
<div className={styled.taskSlotLayout}>
<div
className={styled.taskSlotBackground}
style={{
top: `${offsetPercent}%`,
left: '0',
height: `${heightPercent}%`,
backgroundColor: `${slotColor}`,
}}
/>
<div className={styled.taskSlotContent}>
<p className={styled.title}>{title}</p>
<p className={styled.description}>{subTitle}</p>
</div>
</div>
);
}

export default TaskSlot;
17 changes: 17 additions & 0 deletions src/timetable/components/TimeSlot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getHourAndMinutesFormat } from '@/timetable/utils';
import styled from './Slot.module.scss';

interface TimeSlotProps {
headerDate: Date;
}

function TimeSlot({ headerDate }: TimeSlotProps) {
const currentTime = getHourAndMinutesFormat(headerDate);
return (
<div className={`${styled.timeSlotLayout} ${styled.title}`}>
<p className={styled.headerDate}>{currentTime}</p>
</div>
);
}

export default TimeSlot;
10 changes: 10 additions & 0 deletions src/timetable/components/Timetable.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
interface Task {
id: number;
title: string;
subTitle: string;
slotColor: string;
startTime: Date;
endTime: Date;
}

export type { Task };
43 changes: 43 additions & 0 deletions src/timetable/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const getHourAndMinutesFormat = (data: Date) => {
const hours = data.getHours();
const minutes = data.getMinutes();
const minutesFormat = minutes < 10 ? `0${minutes}` : minutes;
const currentTime = minutes === 0 ? hours : `${hours}:${minutesFormat}`;

return currentTime; // HH:MM
};

// 시간을 분단위로 바꿔버리고 더해주는 함수
const sumHoursAndMinutes = (date: Date) => date.getHours() * 60 + date.getMinutes();

const calculateTaskOffsetAndHeightPercent = (
slotStartTime: Date,
slotEndTime: Date,
taskStartTime: Date,
taskEndTime: Date,
slotTime: number,
) => {
const slotStartMinutes = sumHoursAndMinutes(slotStartTime);
const slotEndMinutes = sumHoursAndMinutes(slotEndTime);
const taskStartMinutes = sumHoursAndMinutes(taskStartTime);
const taskEndMinutes = sumHoursAndMinutes(taskEndTime);

let offsetPercent = 0;
let endPercent = 100;

if (slotStartMinutes < taskStartMinutes) {
// 슬롯의 시작시간보다 task의 시작 시간이 늦었다면(즉 slot 도중에 시작했다면)
offsetPercent = ((taskStartMinutes - slotStartMinutes) / slotTime) * 100;
}

if (taskEndMinutes < slotEndMinutes) {
// task의 끝나는 시간이 slot의 종료 시간보다 늦다면(즉 slot 도중에 끝난다면)
endPercent = ((taskEndMinutes - slotStartMinutes) / slotTime) * 100;
}

const heightPercent = endPercent - offsetPercent;

return { offsetPercent, heightPercent };
};

export { getHourAndMinutesFormat, sumHoursAndMinutes, calculateTaskOffsetAndHeightPercent };

0 comments on commit bbc38a1

Please sign in to comment.