Skip to content

Commit

Permalink
Merge pull request #43 from academic-relations/42-impl-calendar-compo…
Browse files Browse the repository at this point in the history
…nent
  • Loading branch information
ChaeyeonAhn authored Jan 3, 2025
2 parents a2f1e12 + 2ae3556 commit 54a1737
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 172 deletions.
131 changes: 105 additions & 26 deletions packages/web/src/common/components/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import {
addDays,
isSameMonth,
isSameDay,
getDay,
} from "date-fns";
import styled from "styled-components";
import MonthNavigator from "./_atomic/MonthNavigator";
import CalendarWeek, { CalendarSizeProps } from "./_atomic/CalendarWeek";
import { CalendarDateProps } from "./_atomic/CalendarDate";
import CalendarWeekdays from "./_atomic/CalendarWeekdays";
import Typography from "../Typography";

interface EventPeriod {
start: Date;
Expand All @@ -20,31 +21,80 @@ interface EventPeriod {

interface CalendarProps extends CalendarSizeProps {
existDates: Date[];
eventPeriods: EventPeriod[];
eventPeriods?: EventPeriod[];
selectedDates: Date[];
onDateClick?: (date: Date) => void;
width?: string;
height?: string;
title?: string;
small?: boolean;
}

const CalendarWrapper = styled.div<CalendarSizeProps>`
const CalendarWrapper = styled.div<{
width?: CalendarProps["width"];
height?: CalendarProps["height"];
}>`
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
width: 100%;
width: ${({ width }) => width || "100%"};
height: ${({ height }) => height || "100%"};
`;

const CalendarContentWrapper = styled.div<{
title?: CalendarProps["title"];
small?: CalendarProps["small"];
}>`
display: flex;
height: ${({ small }) => (small ? "calc(100% - 28px)" : "calc(100% - 40px)")};
height: ${({ title }) => title === "" && "100%"};
padding: ${({ small }) => (small ? "20px 18px" : "30px")};
flex-direction: column;
align-items: flex-end;
gap: 12px;
flex-shrink: 0;
border-radius: ${({ title }) => (title !== "" ? "0px 0px 4px 4px" : "4px")};
${({ title, theme }) =>
title === ""
? `border: 2px solid ${theme.colors.GRAY[100]}`
: `border-left: 2px solid ${theme.colors.GRAY[100]};
border-right: 2px solid ${theme.colors.GRAY[100]};
border-bottom: 2px solid ${theme.colors.GRAY[100]};`};
`;

const WeekWrapper = styled.div`
const WeekWrapper = styled.div<{
small?: CalendarProps["small"];
}>`
display: flex;
flex-direction: column;
gap: auto;
justify-content: space-between;
align-items: flex-start;
align-self: stretch;
flex: 1 0 0;
height: 100%;
`;

const TitleWrapper = styled.div<{
small?: CalendarProps["small"];
}>`
display: flex;
height: ${({ small }) => (small ? "28px" : "40px")};
border-radius: 4px 4px 0px 0px;
background: ${({ theme }) => theme.colors.GREEN[600]};
display: flex;
padding: ${({ small }) => (small ? "8px 12px" : "10px 20px")};
align-items: center;
gap: 8px;
width: 100%;
gap: 20px;
align-self: stretch;
`;

const Calendar: React.FC<CalendarProps> = ({
size = "md",
title = "",
width = undefined,
height = undefined,
small = false,
existDates,
eventPeriods,
eventPeriods = [],
selectedDates,
onDateClick = () => {},
}) => {
Expand All @@ -55,7 +105,7 @@ const Calendar: React.FC<CalendarProps> = ({
start: startOfMonth(currentDate),
end: endOfMonth(currentDate),
},
{ weekStartsOn: 0 },
{ weekStartsOn: 1 },
);

const handleDateClick = (date: Date) => {
Expand All @@ -70,10 +120,16 @@ const Calendar: React.FC<CalendarProps> = ({
const day = addDays(startDate, index);
const isCurrentMonth = isSameMonth(day, currentDate);
const exist = existDates.some(existDate => isSameDay(existDate, day));
const dayInWeek = getDay(day);
let type: CalendarDateProps["type"] = isCurrentMonth
? "Default"
: "Past/Future";

if (dayInWeek === 0) {
type = "Sunday";
} else if (dayInWeek === 6) {
type = "Saturday";
}
if (!isCurrentMonth) {
type = "Past/Future";
} else if (
Expand All @@ -82,7 +138,12 @@ const Calendar: React.FC<CalendarProps> = ({
type = "Selected";
} else {
eventPeriods.forEach(period => {
if (isSameDay(day, period.start)) {
if (
isSameDay(period.start, period.end) &&
isSameDay(day, period.start)
) {
type = "Selected";
} else if (isSameDay(day, period.start)) {
type = "Start";
} else if (isSameDay(day, period.end)) {
type = "End";
Expand All @@ -100,19 +161,37 @@ const Calendar: React.FC<CalendarProps> = ({
});

return (
<CalendarWrapper size={size}>
<MonthNavigator currentDate={currentDate} onChange={setCurrentDate} />
<CalendarWeekdays size={size} />
<WeekWrapper>
{weeks.map((weekStart: Date) => (
<CalendarWeek
week={getWeekData(weekStart)}
size={size}
key={weekStart.toISOString()}
onDateClick={handleDateClick}
/>
))}
</WeekWrapper>
<CalendarWrapper width={width} height={height}>
{title !== "" && (
<TitleWrapper small={small}>
{small ? (
<Typography color="WHITE" fs={16} fw="SEMIBOLD" lh={20}>
{title}
</Typography>
) : (
<Typography color="WHITE" fs={18} fw="SEMIBOLD" lh={20}>
{title}
</Typography>
)}
</TitleWrapper>
)}
<CalendarContentWrapper title={title} small={small}>
<MonthNavigator
currentDate={currentDate}
onChange={setCurrentDate}
small={small}
/>
<WeekWrapper small={small}>
{weeks.map((weekStart: Date) => (
<CalendarWeek
week={getWeekData(weekStart)}
small={small}
key={weekStart.toISOString()}
onDateClick={handleDateClick}
/>
))}
</WeekWrapper>
</CalendarContentWrapper>
</CalendarWrapper>
);
};
Expand Down
Loading

0 comments on commit 54a1737

Please sign in to comment.