Skip to content

Commit

Permalink
[FE] 하루 일정 모달 구현 (#153)
Browse files Browse the repository at this point in the history
* feat: 하루 일정 모달 UI 구현

* feat: 하루 일정 조회 API 구현

* feat: 날짜와 하루 일정 모달 연결

* feat: 하루 일정 모달과 일정 조회 모달 연결

* refactor: 하루 일정 모달 이름 변경

* refactor: 리뷰반영

* refactor: 오타 수정

* refactor: 상태 이름 수정 및 rebase 충돌 해결

* refactor: day -> daily로 이름 변경
  • Loading branch information
hafnium1923 authored Jul 25, 2023
1 parent 0a909db commit 5a821ec
Show file tree
Hide file tree
Showing 11 changed files with 335 additions and 20 deletions.
9 changes: 6 additions & 3 deletions frontend/src/apis/schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ export const fetchSchedules = (
teamPlaceId: number,
year: number,
month: number,
day?: number,
) => {
const query = day
? `year=${year}&month=${month}&day=${day}`
: `year=${year}&month=${month}`;

return http.get<{
schedules: Schedule[];
}>(
`/api/team-place/${teamPlaceId}/calendar/schedules?year=${year}&month=${month}`,
);
}>(`/api/team-place/${teamPlaceId}/calendar/schedules?${query}`);
};

export const fetchScheduleById = (teamPlaceId: number, scheduleId: number) => {
Expand Down
44 changes: 38 additions & 6 deletions frontend/src/components/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import { useModal } from '~/hooks/useModal';
import { generateScheduleBars } from '~/utils/generateScheduleBars';
import { DAYS_OF_WEEK, MODAL_OPEN_TYPE } from '~/constants/calendar';
import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from '~/assets/svg';
import type { ModalOpenType } from '~/types/schedule';
import { arrayOf } from '~/utils/arrayOf';
import ScheduleMoreCell from '~/components/ScheduleMoreCell/ScheduleMoreCell';
import type { Position, ModalOpenType } from '~/types/schedule';
import DailyScheduleModal from '~/components/DailyScheduleModal/DailyScheduleModal';

const Calendar = () => {
const {
Expand All @@ -35,17 +36,32 @@ const Calendar = () => {
const [modalType, setModalType] = useState<ModalOpenType>(
MODAL_OPEN_TYPE.ADD,
);

if (schedules === undefined) {
return null;
}
const [dailyModalDate, setDailyModalDate] = useState<Date>(new Date());
const [dailyModalPosition, setDailyModalPosition] = useState<Position>({
row: 0,
column: 0,
});
const scheduleBars = generateScheduleBars(year, month, schedules);

const handleModalOpen = (modalOpenType: ModalOpenType) => {
setModalType(() => modalOpenType);
openModal();
};

const handleDailyScheduleModalOpen = (
day: Date,
row: number,
col: number,
) => {
setModalType(() => MODAL_OPEN_TYPE.DAILY);
setDailyModalDate(() => day);
setDailyModalPosition({
row,
column: col,
});
openModal();
};

return (
<>
<S.Container>
Expand Down Expand Up @@ -119,13 +135,21 @@ const Calendar = () => {
})}
</S.ScheduleBarContainer>
<S.DateView>
{week.map((day) => {
{week.map((day, colIndex) => {
return (
<DateCell
key={day.toISOString()}
rawDate={day}
currentMonth={month}
onClick={() => handleModalOpen(MODAL_OPEN_TYPE.ADD)}
onDayClick={(e) => {
e.stopPropagation();
handleDailyScheduleModalOpen(
day,
rowIndex,
colIndex,
);
}}
/>
);
})}
Expand Down Expand Up @@ -155,6 +179,14 @@ const Calendar = () => {
)}
/>
)}
{isModalOpen && modalType === MODAL_OPEN_TYPE.DAILY && (
<DailyScheduleModal
rawDate={dailyModalDate}
position={dailyModalPosition}
onScheduleModalOpen={handleScheduleModalOpen}
onSetModalType={() => setModalType(() => MODAL_OPEN_TYPE.VIEW)}
/>
)}
</>
);
};
Expand Down
19 changes: 18 additions & 1 deletion frontend/src/components/Calendar/DateCell/DateCell.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ interface WrapperProps {
}

export const Wrapper = styled.div<WrapperProps>`
display: flex;
flex-direction: column;
align-items: flex-end;
${({ size }) => {
if (size === 'sm')
return css`
Expand All @@ -18,7 +21,7 @@ export const Wrapper = styled.div<WrapperProps>`
if (size === 'md') return css``;
if (size === 'lg')
return css`
padding: 8px 8px 0 0;
padding: 2px 2px 0 0;
text-align: right;
`;
}};
Expand All @@ -31,3 +34,17 @@ export const Wrapper = styled.div<WrapperProps>`
cursor: pointer;
`;

export const TeamColorBadge = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 20px;
height: 20px;
border-radius: 50%;
&:hover {
background-color: ${({ theme }) => theme.color.GRAY300};
}
`;
22 changes: 13 additions & 9 deletions frontend/src/components/Calendar/DateCell/DateCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ import { parseDate } from '~/utils/parseDate';
import Text from '~/components/common/Text/Text';
import * as S from './DateCell.styled';
import type { DateCellSize } from '~/types/size';
import type { MouseEventHandler } from 'react';

interface DateCellProps {
rawDate: Date;
currentMonth: number;
onClick?: () => void;
onDayClick?: MouseEventHandler<HTMLDivElement>;
size?: DateCellSize;
}

const DateCell = (props: DateCellProps) => {
const { rawDate, currentMonth, size = 'lg', onClick } = props;
const { rawDate, currentMonth, size = 'lg', onClick, onDayClick } = props;
const { date, day } = parseDate(rawDate);

const isSunday = day === 0;
Expand All @@ -26,14 +28,16 @@ const DateCell = (props: DateCellProps) => {
size={size}
onClick={onClick}
>
<Text
css={css`
font-size: 12px;
opacity: ${isCurrentMonth ? 1 : 0.3};
`}
>
{date}
</Text>
<S.TeamColorBadge onClick={onDayClick}>
<Text
css={css`
font-size: 12px;
opacity: ${isCurrentMonth ? 1 : 0.3};
`}
>
{date}
</Text>
</S.TeamColorBadge>
</S.Wrapper>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { Meta, StoryObj } from '@storybook/react';
import DailyScheduleModal from '~/components/DailyScheduleModal/DailyScheduleModal';
import Button from '~/components/common/Button/Button';
import { useModal } from '~/hooks/useModal';
import type { SchedulePosition } from '~/types/schedule';

const meta = {
title: 'DailyScheduleModal',
component: DailyScheduleModal,
} satisfies Meta<typeof DailyScheduleModal>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
render: () => {
const { openModal } = useModal();

return (
<>
<Button onClick={openModal}>모달 열기</Button>
<DailyScheduleModal
onSetModalType={() => console.log('hi')}
rawDate={new Date()}
position={{ row: 0, column: 0 }}
onScheduleModalOpen={({ scheduleId, row, column, level }) =>
alert(`${scheduleId}, ${row}, ${column}, ${level}`)
}
/>
</>
);
},
args: {
onScheduleModalOpen: ({
scheduleId,
row,
column,
level,
}: SchedulePosition & {
scheduleId: number;
}) => {
alert(`${scheduleId}, ${row}, ${column}, ${level}`);
},
onSetModalType: () => alert('hi'),
position: { row: 0, column: 0 },
rawDate: new Date(),
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { css, styled } from 'styled-components';
import type { DailyScheduleModalProps } from '~/components/DailyScheduleModal/DailyScheduleModal';

export const Backdrop = styled.div`
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
`;

export const Container = styled.div`
display: flex;
position: absolute;
flex-direction: column;
z-index: ${({ theme }) => theme.zIndex.MODAL};
width: 300px;
height: 338px;
padding: 10px 20px 20px 20px;
border-radius: 10px;
background-color: ${({ theme }) => theme.color.WHITE};
box-shadow:
0 0 1px #1b1d1f33,
0 15px 25px #1b1d1f33,
0 5px 10px #1b1d1f1f;
`;

export const Header = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 38px;
padding-bottom: 4px;
margin-bottom: 24px;
border-bottom: ${({ theme }) => `1px solid ${theme.color.GRAY300}`};
`;

export const ScheduleWrapper = styled.div`
display: flex;
position: relative;
flex-wrap: wrap;
overflow: auto;
width: 100%;
max-height: 80%;
height: auto;
gap: 10px;
`;

export const ScheduleBox = styled.div<Pick<DailyScheduleModalProps, 'color'>>`
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 40px;
background-color: ${({ color }) => color};
border-radius: 4px;
filter: brightness(1.5);
cursor: pointer;
`;

export const closeButton = css`
width: 22px;
height: 38px;
padding: 8px 0;
`;

export const teamName = css`
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 200px;
`;
Loading

0 comments on commit 5a821ec

Please sign in to comment.