Skip to content

Commit

Permalink
Merge pull request #830 from sparcs-kaist/dev
Browse files Browse the repository at this point in the history
Main branch update from Dev branch
  • Loading branch information
kmc7468 authored Sep 7, 2024
2 parents b409cc2 + f26e08e commit 9f05b8e
Show file tree
Hide file tree
Showing 49 changed files with 2,331 additions and 1,083 deletions.
4 changes: 3 additions & 1 deletion packages/web/src/components/Event/BodyRandomBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ type BodyRandomBoxProps = {
isBoxOpend: boolean;
onClickBox?: () => void;
itemImageUrl?: string;
nonClick?: boolean;
};

const BodyRandomBox = ({
isBoxOpend,
onClickBox,
itemImageUrl,
nonClick,
}: BodyRandomBoxProps) => {
const bodyRef = useRef<HTMLDivElement>(null);
const getBodyWidth = useCallback(() => bodyRef.current?.clientWidth || 0, []);
Expand Down Expand Up @@ -81,7 +83,7 @@ const BodyRandomBox = ({
height: `${boxSize}px`,
aspectRatio: 1,
margin: `0 auto`,
...theme.cursor(isBoxOpend),
...theme.cursor(isBoxOpend || nonClick),
transform: `scale(${
(boxSize / 500) * 0.8
}) translateX(-160px) translateY(-70px)`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import WhiteContainer from "@/components/WhiteContainer";
import theme from "@/tools/theme";

import { ReactComponent as CreditIcon } from "@/static/events/2023fallCredit.svg";
// ToDo : 2023fall 이미지
import { ReactComponent as Ticket1Icon } from "@/static/events/2023fallTicket1.svg";
// ToDo : 2023fall 이미지
import { ReactComponent as Ticket2Icon } from "@/static/events/2023fallTicket2.svg";
// ToDo : 2023fall 이미지

// import { ReactComponent as Ticket1Icon } from "@/static/events/2023fallTicket1.svg";
// import { ReactComponent as Ticket2Icon } from "@/static/events/2023fallTicket2.svg";

type CreditAmountStatusContainerProps = {
type?: "credit" | "ticket";
Expand All @@ -19,8 +17,7 @@ const CreditAmountStatusContainer = ({
type = "credit",
...whiteContainerProps
}: CreditAmountStatusContainerProps) => {
const { creditAmount, ticket1Amount, ticket2Amount } =
useValueRecoilState("event2023FallInfo") || {};
const { creditAmount } = useValueRecoilState("event2024FallInfo") || {};

return (
<WhiteContainer
Expand All @@ -34,15 +31,15 @@ const CreditAmountStatusContainer = ({
{...whiteContainerProps}
>
<div css={{ color: theme.white, ...theme.font16_bold, flexGrow: 1 }}>
{type === "credit" ? "내가 모은 송편" : "일반 / 고급 응모권"}
{type === "credit" ? "내가 모은 송편코인" : "일반 / 고급 응모권"}
</div>
{type === "credit" ? (
<>
<CreditIcon css={{ width: "27px", height: "16px" }} />
<div css={{ color: theme.white, ...theme.font16_bold }}>
{creditAmount || 0}
</div>
</>
<>
<CreditIcon css={{ width: "27px", height: "16px" }} />
<div css={{ color: theme.white, ...theme.font16_bold }}>
{creditAmount || 0}
</div>
</>
{/* {type === "credit" ? (
) : (
<>
<Ticket1Icon
Expand All @@ -69,7 +66,7 @@ const CreditAmountStatusContainer = ({
{ticket2Amount || 0}
</div>
</>
)}
)} */}
</WhiteContainer>
);
};
Expand Down
211 changes: 211 additions & 0 deletions packages/web/src/components/Event/DailyAttendanceCalendar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { memo } from "react";

import { useValueRecoilState } from "@/hooks/useFetchRecoilState";

import MiniCircle from "@/components/MiniCircle";

import moment, { getToday } from "@/tools/moment";
import theme from "@/tools/theme";

import { ReactComponent as MissionCompleteIcon } from "@/static/events/2023fallMissionComplete.svg";

const getCalendarDates = () => {
const startDate = moment("2024-09-06", "YYYY-MM-DD");
const endDate = moment("2024-09-24", "YYYY-MM-DD");
const endDateOfMonth = moment("2024-09-30", "YYYY-MM-DD");
const today = getToday();
// const today = moment("2024-09-10", "YYYY-MM-DD"); // FIXME: 배포 전에 수정
const date = startDate.clone();
date.subtract(date.day(), "day");
const event2024FallInfo = useValueRecoilState("event2024FallInfo");
const completedDates = event2024FallInfo?.completedQuests.reduce(
(acc, { questId, completedAt }) => {
if (questId === "dailyAttendance" && completedAt) {
acc.push(moment(completedAt).format("YYYY-MM-DD"));
}
return acc;
},
[] as string[]
);

const calendar = [];

for (let i = 0; i < 5; i++) {
const week = [];
for (let i = 0; i < 7; i++) {
let available = null;
let checked = false;
if (date.isSame(today)) {
available = "today";
} else if (date.isAfter(startDate) && date.isBefore(today)) {
available = "past";
} else if (date.isBefore(endDate) && date.isAfter(startDate, "day")) {
available = true;
}

if (completedDates?.includes(date.format("YYYY-MM-DD"))) {
checked = true;
}

week.push({
year: date.year(),
month: date.month() + 1,
date: date.date(),
available,
checked,
});
if (date.isSame(endDateOfMonth)) {
break;
}
date.add(1, "day");
}
calendar.push(week);
}
return calendar;
};
type DateProps = {
index: number;
year: number;
month: number;
date: number;
available: string | boolean | null;
checked: boolean;
};

const Date = ({ index, date, available, checked }: DateProps) => {
const style = {
width: "calc((100% - 36px) / 7)",
aspectRatio: "1 / 1",
height: "100%",
};
const styleBox: React.CSSProperties = {
...style,
borderRadius: "6px",
position: "relative",
display: "flex",
alignItems: "center",
justifyContent: "center",
background: available ? theme.white : theme.gray_background,
transitionDuration: theme.duration,
};
const styleDate = {
...theme.font12,
letterSpacing: undefined,
marginTop: "3px",
color:
available === "past" || !available
? theme.gray_line
: index === 0
? theme.red_text
: index === 6
? theme.blue_text
: theme.black,
};
const styleToday: React.CSSProperties = {
position: "absolute",
top: "calc(50% + 8px)",
left: "calc(50% - 2px)",
};
const styleCompleteIcon: React.CSSProperties = {
position: "absolute",
height: "34px",
width: "34px",
};

if (!date) return <div style={style} />;
return (
<div style={styleBox}>
<div style={styleDate}>{date}</div>
{available === "today" && (
<div style={styleToday}>
<MiniCircle type="date" />
</div>
)}
{checked && <MissionCompleteIcon style={styleCompleteIcon} />}
</div>
);
};
const MemoizedDate = memo(Date);

const DailyAttendanceCalendar = () => {
const dateInfo = getCalendarDates();

const styleMonth: React.CSSProperties = {
display: "flex",
flexDirection: "column",
rowGap: "6px",
marginBottom: "5px",
};
const styleDay: React.CSSProperties = {
display: "flex",
margin: "12px 0 8px",
columnGap: "6px",
};
const styleDayItem: React.CSSProperties = {
width: "calc((100% - 36px) / 7)",
fontSize: "10px",
height: "12px",
textAlign: "center",
};
const styleWeek = {
display: "flex",
columnGap: "6px",
};

const week: { color: string; text: string }[] = [
{ color: theme.red_text, text: "일" },
{ color: theme.black, text: "월" },
{ color: theme.black, text: "화" },
{ color: theme.black, text: "수" },
{ color: theme.black, text: "목" },
{ color: theme.black, text: "금" },
{ color: theme.blue_text, text: "토" },
];

return (
<div
className="datepicker"
style={{
transition: "max-height 0.3s ease-in-out",
margin: "-10px -15px",
padding: "10px 15px",
}}
>
<div style={styleDay}>
{week.map((item, index) => (
<div
key={index}
style={{
...styleDayItem,
color: item.color,
opacity: 0.632,
}}
>
{item.text}
</div>
))}
</div>
<div className="month" style={styleMonth}>
{dateInfo.map((item, index) => {
return (
<div key={index} style={styleWeek}>
{item.map((item, index) => (
<MemoizedDate
key={index}
index={index}
year={item.year}
month={item.month}
date={item.date}
available={item.available}
checked={item.checked}
/>
))}
</div>
);
})}
</div>
</div>
);
};

export default DailyAttendanceCalendar;
Loading

0 comments on commit 9f05b8e

Please sign in to comment.