From 7f84cc1b800b031c8fd90b98d1f3c7ea88735c06 Mon Sep 17 00:00:00 2001 From: hwmin414 Date: Tue, 3 Sep 2024 23:06:37 +0900 Subject: [PATCH 01/19] feat: 2024 fall store updated --- .../CreditAmountStatusContainer/index.tsx | 52 +- .../Event/EventItemContainer/index.tsx | 120 +++++ .../ModalPopup/ModalPurchaseSuccess.tsx | 79 +++ .../web/src/components/Skeleton/Routes.tsx | 2 +- .../src/pages/Event/Event2024FallHistory.tsx | 7 +- .../pages/Event/Event2024FallLeaderboard.tsx | 378 --------------- .../pages/Event/Event2024FallStore/Item.tsx | 453 ++++++++++++++++++ .../Event2024FallStore/ItemListSection.tsx | 103 +--- .../PublicNoticeContainer.tsx | 35 +- .../pages/Event/Event2024FallStore/index.tsx | 13 +- packages/web/src/pages/Event/index.tsx | 12 +- .../web/src/static/events/2024fallTicket.svg | 73 +++ .../static/events/2024fallTicketTilted.svg | 78 +++ 13 files changed, 831 insertions(+), 574 deletions(-) create mode 100644 packages/web/src/components/Event/EventItemContainer/index.tsx create mode 100644 packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx delete mode 100644 packages/web/src/pages/Event/Event2024FallLeaderboard.tsx create mode 100644 packages/web/src/pages/Event/Event2024FallStore/Item.tsx create mode 100644 packages/web/src/static/events/2024fallTicket.svg create mode 100644 packages/web/src/static/events/2024fallTicketTilted.svg diff --git a/packages/web/src/components/Event/CreditAmountStatusContainer/index.tsx b/packages/web/src/components/Event/CreditAmountStatusContainer/index.tsx index f79a31982..192228238 100644 --- a/packages/web/src/components/Event/CreditAmountStatusContainer/index.tsx +++ b/packages/web/src/components/Event/CreditAmountStatusContainer/index.tsx @@ -5,22 +5,16 @@ 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 이미지 type CreditAmountStatusContainerProps = { - type?: "credit" | "ticket"; + type?: "credit"; } & Parameters[0]; const CreditAmountStatusContainer = ({ type = "credit", ...whiteContainerProps }: CreditAmountStatusContainerProps) => { - const { creditAmount, ticket1Amount, ticket2Amount } = - useValueRecoilState("event2023FallInfo") || {}; + const { creditAmount } = useValueRecoilState("event2024FallInfo") || {}; return (
- {type === "credit" ? "내가 모은 송편" : "일반 / 고급 응모권"} + 내가 모은 송편
- {type === "credit" ? ( - <> - -
- {creditAmount || 0} -
- - ) : ( - <> - -
- {ticket1Amount || 0} -
-
- -
- {ticket2Amount || 0} -
- - )} + <> + +
+ {creditAmount || 0} +
+ ); }; diff --git a/packages/web/src/components/Event/EventItemContainer/index.tsx b/packages/web/src/components/Event/EventItemContainer/index.tsx new file mode 100644 index 000000000..7262b3c6f --- /dev/null +++ b/packages/web/src/components/Event/EventItemContainer/index.tsx @@ -0,0 +1,120 @@ +import { useState } from "react"; +import { useHistory } from "react-router-dom"; + +import type { EventItem } from "@/types/event2024fall"; + +import { + ModalEvent2024FallItem, + ModalEvent2024FallRandomBox, +} from "@/components/ModalPopup"; +import WhiteContainer from "@/components/WhiteContainer"; + +import theme from "@/tools/theme"; + +// ToDo : 2023fall 이미지 +import { ReactComponent as CreditIcon } from "@/static/events/2023fallCredit.svg"; + +type EventItemComponentProps = { + value: EventItem; + fetchItems?: () => void; + clickable?: boolean; +}; + +const EventItemContainer = ({ + value, + fetchItems, + clickable, +}: EventItemComponentProps) => { + const history = useHistory(); + const [isOpen, setIsOpen] = useState(false); + const [rewardItem, setRewardItem] = useState>(null); + const onClickHandler = () => { + if (value.itemType === 3) { + // setIsOpen(true); + } else { + // setIsOpen(true); + history.push(`/event/2024fall-store/item/${value._id}`); + } + }; + + return ( + +
+ {value.name} +
+
+ {value.name} +
+
+ +
+ {value.price} +
+
+ + {value.itemType === 3 && ( + setRewardItem(null)} + item={rewardItem || undefined} + /> + )} +
+ ); +}; + +export default EventItemContainer; diff --git a/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx b/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx new file mode 100644 index 000000000..abbb3ea3e --- /dev/null +++ b/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx @@ -0,0 +1,79 @@ +import Button from "@/components/Button"; +import DottedLine from "@/components/DottedLine"; +import Modal from "@/components/Modal"; + +import theme from "@/tools/theme"; + +import WbIncandescentIcon from "@mui/icons-material/WbIncandescent"; + +type ModalPurchaseSuccessProps = { + isOpen: boolean; + onChangeIsOpen?: (isOpen: boolean) => void; +}; + +const ModalPurchaseSuccess = ({ + isOpen, + onChangeIsOpen, +}: ModalPurchaseSuccessProps) => { + const styleTitle = { + ...theme.font18, + display: "flex", + alignItems: "center", + marginBottom: "12px", + }; + const styleLogo = { + fontSize: "21px", + margin: "0 4px 0 0px", + }; + const styleBody = { display: "grid", rowGap: "12px" }; + + return ( + +
+ + 응모권 구매에 성공했습니다. +
+ <> +
+ +
+ 정상적으로 구입되었습니다. +
+ +
+ +
+ ); +}; + +export default ModalPurchaseSuccess; diff --git a/packages/web/src/components/Skeleton/Routes.tsx b/packages/web/src/components/Skeleton/Routes.tsx index e77895bc6..11c200609 100644 --- a/packages/web/src/components/Skeleton/Routes.tsx +++ b/packages/web/src/components/Skeleton/Routes.tsx @@ -28,7 +28,7 @@ const routeProps = [ exact: true, }, { - path: "/event/:eventName", + path: ["/event/:eventName", "/event/:eventName/item/:itemId"], component: lazy(() => import("@/pages/Event")), exact: true, }, diff --git a/packages/web/src/pages/Event/Event2024FallHistory.tsx b/packages/web/src/pages/Event/Event2024FallHistory.tsx index d1f80f36a..6097e144a 100644 --- a/packages/web/src/pages/Event/Event2024FallHistory.tsx +++ b/packages/web/src/pages/Event/Event2024FallHistory.tsx @@ -133,17 +133,12 @@ const Event2024FallHistory = () => { diff --git a/packages/web/src/pages/Event/Event2024FallLeaderboard.tsx b/packages/web/src/pages/Event/Event2024FallLeaderboard.tsx deleted file mode 100644 index eada05d3a..000000000 --- a/packages/web/src/pages/Event/Event2024FallLeaderboard.tsx +++ /dev/null @@ -1,378 +0,0 @@ -import { useMemo } from "react"; - -import { useValueRecoilState } from "@/hooks/useFetchRecoilState"; -import useQuery from "@/hooks/useTaxiAPI"; - -import AdaptiveDiv from "@/components/AdaptiveDiv"; -import Empty from "@/components/Empty"; -import Footer from "@/components/Footer"; -import HeaderWithLeftNav from "@/components/Header/HeaderWithLeftNav"; -import Title from "@/components/Title"; -import ProfileImage from "@/components/User/ProfileImage"; -import WhiteContainer from "@/components/WhiteContainer"; - -import theme from "@/tools/theme"; - -// ToDo : 2023fall 이미지 -import { ReactComponent as LeaderBoardItems } from "@/static/events/2023fallLeaderBoardItems.svg"; -import { ReactComponent as Ticket1Icon } from "@/static/events/2023fallTicket1.svg"; -import { ReactComponent as Ticket2Icon } from "@/static/events/2023fallTicket2.svg"; - -const LeaderboardTopBar = () => ( -
- 순위 - 닉네임 - - - 추첨 확률 -
-); - -type LeaderboardElem = { - nickname: string; - profileImageUrl: string; - ticket1Amount: number; - ticket2Amount: number; - probability: number; - probabilityV2: number; -}; - -type LeaderboardItemProps = { - value: LeaderboardElem; - rank: number; - isMe?: boolean; -}; - -const LeaderboardItem = ({ - value, - rank, - isMe = false, -}: LeaderboardItemProps) => { - const styleContainer = (index: number) => { - switch (index) { - case 0: - return { - color: "#C6B200", - border: "0.5px solid #E4CD00", - background: "#FFEE5A", - boxShadow: "0px 1px 5px 0px #E4CD00", - ...theme.font20, - fontSize: "24px", - }; - case 1: - return { - color: "#96BCC6", - border: "0.5px solid #BBD4DA", - background: "#EEF6F8", - boxShadow: "0px 1px 5px 0px #BBD4DA", - ...theme.font20, - fontSize: "24px", - }; - case 2: - return { - color: "#CD6830", - border: "0.5px solid #DE8C5D", - background: "#FFC5A4", - boxShadow: "0px 1px 5px 0px #DE8C5D", - ...theme.font20, - fontSize: "24px", - }; - case -1: - return { - color: theme.purple_disabled, - background: theme.purple, - boxShadow: theme.shadow, - ...theme.font20, - }; - default: - return { - color: theme.purple_disabled, - background: theme.white, - boxShadow: theme.shadow, - ...theme.font20, - }; - } - }; - - const styleText = (index: number) => { - switch (index) { - case 0: - return "#6B6000"; - case 1: - return "#337182"; - case 2: - return "#9E3800"; - case -1: - return theme.white; - default: - return theme.purple; - } - }; - - const styleTicketText = { - ...theme.font16, - width: "30px", - flexShrink: 0, - textAlign: "center" as const, - }; - - return ( - - {rank + 1} -
- -
- {isMe && ( -
- 나 -
- )} -
- {value.nickname} -
- - {value.ticket1Amount || 0} - - {value.ticket2Amount || 0} -
- - {Math.trunc(value.probabilityV2 * 100) || 0} - - .{Math.floor(((value.probabilityV2 * 100) % 1) * 10)}% -
-
- ); -}; - -const Event2024FallLeaderboard = () => { - const { - leaderboard, - rank, - probability, - probabilityV2, - totalUserAmount, - totalTicket1Amount, - totalTicket2Amount, - } = useQuery.get("/events/2024fall/publicNotice/leaderboard")[1] || { - leaderboard: [], - rank: 0, - }; - const { ticket1Amount, ticket2Amount } = { - ticket1Amount: 0, - ticket2Amount: 0, - }; // TODO: FIXME - const { nickname, profileImgUrl } = useValueRecoilState("loginInfo") || {}; - const myLeaderboardInfo = useMemo>(() => { - if (!nickname || !profileImgUrl || !probability) return null; - return { - nickname, - profileImageUrl: profileImgUrl, - ticket1Amount: ticket1Amount || 0, - ticket2Amount: ticket2Amount || 0, - probability, - probabilityV2, - }; - }, [nickname, profileImgUrl, ticket1Amount, ticket2Amount, probability]); - - return ( - <> - - - - 안내 - - -
-
- 🌟 참여 방법 -
-
- 퀘스트 달성, 달토끼 상점을 통해 응모권을 얻을 수 있습니다. -
- 고급응모권은 일반응모권 당첨 확률의 5배입니다. -
- 여러 개의 응모권으로 중복 참여가 가능합니다. -
-
- 📌 경품 추첨 결과 발표일 : 10월 13일(금) -
-
- 추첨 결과는 인스타그램, Ara, Taxi 홈페이지를 통해 발표됩니다. -
-
- 🎁 경품 : 에어팟 3세대 (1명), 택시비 카카오페이 상품권 - 5000원 (14명) -
-
- -
-
- 🏆 리더보드 : 이벤트 기간 중, 실시간으로 변동되는 내 자신과 - 상위 참여자들의 추첨 확률이 공개됩니다. -
-
-
- - 리더보드 - - {leaderboard.length > 0 ? ( - <> - - {leaderboard.map((elem: LeaderboardElem, index: number) => ( - - ))} - {rank > 20 && myLeaderboardInfo && ( - - )} -
-
- • 리더보드의 추첨 확률은 정확한 확률이 아닌 내부 모델을 사용하여 - 계산한 근삿값입니다. -
-
- • 경품 추첨 전체 참여자 수 : {totalUserAmount || 0}명 -
-
- • 발급된 전체 일반 응모권 개수 : {totalTicket1Amount || 0}개 -
-
- • 발급된 전체 고급 응모권 개수 : {totalTicket2Amount || 0}개 -
-
- - ) : ( - 리더보드가 비어있습니다. - )} -
-
- - ); -}; // ToDo : 2023fall 문구 및 footer - -export default Event2024FallLeaderboard; diff --git a/packages/web/src/pages/Event/Event2024FallStore/Item.tsx b/packages/web/src/pages/Event/Event2024FallStore/Item.tsx new file mode 100644 index 000000000..4f1bae6b3 --- /dev/null +++ b/packages/web/src/pages/Event/Event2024FallStore/Item.tsx @@ -0,0 +1,453 @@ +import { useCallback, useMemo, useRef, useState } from "react"; + +import { + useFetchRecoilState, + useIsLogin, + useValueRecoilState, +} from "@/hooks/useFetchRecoilState"; +import useQuery from "@/hooks/useTaxiAPI"; +import { useAxios } from "@/hooks/useTaxiAPI"; + +import AdaptiveDiv from "@/components/AdaptiveDiv"; +import Button from "@/components/Button"; +import Empty from "@/components/Empty"; +import CreditAmountStatusContainer from "@/components/Event/CreditAmountStatusContainer"; +import EventItemContainer from "@/components/Event/EventItemContainer"; +import Footer from "@/components/Footer"; +import HeaderWithLeftNav from "@/components/Header/HeaderWithLeftNav"; +import ModalPurchaseSuccess from "@/components/ModalPopup/ModalPurchaseSuccess"; +import ProfileImage from "@/components/User/ProfileImage"; +import WhiteContainer from "@/components/WhiteContainer"; + +import alertAtom from "@/atoms/alert"; +import { useSetRecoilState } from "recoil"; + +import { eventMode } from "@/tools/loadenv"; +import theme from "@/tools/theme"; + +// ToDo : 2023fall 이미지 +import { ReactComponent as TicketIcon } from "@/static/events/2024fallTicket.svg"; +import { ReactComponent as TicketIconTilted } from "@/static/events/2024fallTicketTilted.svg"; +import ShoppingCartIcon from "@mui/icons-material/ShoppingCart"; + +const LeaderboardTopBar = () => ( +
+ 순위 + 닉네임 + + 추첨 확률 +
+); + +type LeaderboardElem = { + nickname: string; + profileImageUrl: string; + amount: number; + probability: number; +}; + +type LeaderboardItemProps = { + value: LeaderboardElem; + rank: number; + isMe?: boolean; +}; + +const LeaderboardItem = ({ + value, + rank, + isMe = false, +}: LeaderboardItemProps) => { + const styleContainer = (index: number) => { + switch (index) { + case 0: + return { + color: "#C6B200", + border: "0.5px solid #E4CD00", + background: "#FFEE5A", + boxShadow: "0px 1px 5px 0px #E4CD00", + ...theme.font20, + fontSize: "24px", + }; + case 1: + return { + color: "#96BCC6", + border: "0.5px solid #BBD4DA", + background: "#EEF6F8", + boxShadow: "0px 1px 5px 0px #BBD4DA", + ...theme.font20, + fontSize: "24px", + }; + case 2: + return { + color: "#CD6830", + border: "0.5px solid #DE8C5D", + background: "#FFC5A4", + boxShadow: "0px 1px 5px 0px #DE8C5D", + ...theme.font20, + fontSize: "24px", + }; + case -1: + return { + color: theme.purple_disabled, + background: theme.purple, + boxShadow: theme.shadow, + ...theme.font20, + }; + default: + return { + color: theme.purple_disabled, + background: theme.white, + boxShadow: theme.shadow, + ...theme.font20, + }; + } + }; + + const styleText = (index: number) => { + switch (index) { + case 0: + return "#6B6000"; + case 1: + return "#337182"; + case 2: + return "#9E3800"; + case -1: + return theme.white; + default: + return theme.purple; + } + }; + + const styleTicketText = { + ...theme.font16, + width: "30px", + flexShrink: 0, + textAlign: "center" as const, + }; + + return ( + + {rank + 1} +
+ +
+ {isMe && ( +
+ 나 +
+ )} +
+ {value.nickname} +
+ + {value.amount || 0} + +
+ + {Math.trunc(value.probability * 100) || 0} + + .{Math.floor(((value.probability * 100) % 1) * 10)}% +
+
+ ); +}; + +interface Event2024FallStoreItemProps { + itemId: string; +} + +const Event2024FallStoreItem = ({ itemId }: Event2024FallStoreItemProps) => { + const fetchEvent2024FallInfo = useFetchRecoilState("event2024FallInfo"); + const event2024FallInfo = useValueRecoilState("event2024FallInfo"); + const isLogin = useIsLogin(); + const isRequesting = useRef(false); + const [purchaseAmount, setPurchaseAmount] = useState(1); + const [isOpenPurchaseSuccess, setIsOpenPurchaseSuccess] = + useState(false); + const setAlert = useSetRecoilState(alertAtom); + const axios = useAxios(); + + const { leaderboard, totalAmount, totalUser, amount, probability, rank } = + useQuery.get(`/events/2024fall/items/leaderboard/${itemId}`, null, [ + event2024FallInfo, + ])[1] || { + leaderboard: [], + totalAmount: 0, + totalUser: 0, + amount: 0, + probability: 0, + }; + + const { item } = useQuery.get("/events/2024fall/items/" + itemId)[1] || { + item: null, + }; + const { nickname, profileImgUrl } = useValueRecoilState("loginInfo") || {}; + const myLeaderboardInfo = useMemo>(() => { + if (!nickname || !profileImgUrl || !probability) return null; + return { + nickname, + profileImageUrl: profileImgUrl, + amount: amount || 0, + probability, + }; + }, [nickname, profileImgUrl, probability]); + + const [isDisabled, buttonText] = useMemo( + () => + eventMode !== "2024fall" + ? [true, "이벤트 기간이 아닙니다"] + : !event2024FallInfo || !isLogin + ? [true, "로그인 후 구매가 가능합니다"] + : event2024FallInfo.creditAmount < item?.price + ? [true, "송편코인이 부족합니다"] + : [false, "응모권 구매하기"], + [eventMode, event2024FallInfo, item] + ); + + const onClickOk = useCallback(async () => { + if (isRequesting.current) return; + isRequesting.current = true; + await axios({ + url: `/events/2024fall/items/purchase/${item?._id}`, + method: "post", + data: { + amount: purchaseAmount, + }, + onSuccess: ({ reward }) => { + fetchEvent2024FallInfo(); + setPurchaseAmount(1); + setIsOpenPurchaseSuccess(true); + }, + onError: () => setAlert("구매를 실패하였습니다."), + }); + isRequesting.current = false; + }, [item?._id, fetchEvent2024FallInfo]); + + // fetchItems, + return ( + <> + + +
+ +
+
+ {item && ( + {}} + /> + )} + +
+ 경품 수량: {amount}개 +
+
+ 발급한 사용자 수 +
: {totalUser}명 +
+
+ 발급된 총 응모권 수 +
+ : + {" "} + X {totalAmount}개 +
+
+
+ + 구매 수량: + setPurchaseAmount(e.target.valueAsNumber)} + type="number" + style={{ + ...theme.font14, + width: "41px", + borderRadius: "6px", + padding: "6px 0", + background: theme.purple_light, + boxShadow: theme.shadow_purple_input_inset, + border: "none", + outline: "none", + textAlign: "center", + marginLeft: "5px", + }} + value={purchaseAmount} + /> +
+ +
+
+ {leaderboard.length > 0 ? ( + <> + + {leaderboard.map((elem: LeaderboardElem, index: number) => ( + + ))} + {rank > 20 && myLeaderboardInfo && ( + + )} + + ) : ( + 리더보드가 비어있습니다. + )} + +
+
+ + ); +}; // ToDo : 2023fall 문구 및 footer + +export default Event2024FallStoreItem; diff --git a/packages/web/src/pages/Event/Event2024FallStore/ItemListSection.tsx b/packages/web/src/pages/Event/Event2024FallStore/ItemListSection.tsx index 81e17ddf9..859e99765 100644 --- a/packages/web/src/pages/Event/Event2024FallStore/ItemListSection.tsx +++ b/packages/web/src/pages/Event/Event2024FallStore/ItemListSection.tsx @@ -1,107 +1,9 @@ -import { memo, useState } from "react"; +import { memo } from "react"; import type { EventItem } from "@/types/event2024fall"; import Empty from "@/components/Empty"; -import { - ModalEvent2024FallItem, - ModalEvent2024FallRandomBox, -} from "@/components/ModalPopup"; -import WhiteContainer from "@/components/WhiteContainer"; - -import theme from "@/tools/theme"; - -// ToDo : 2023fall 이미지 -import { ReactComponent as CreditIcon } from "@/static/events/2023fallCredit.svg"; - -type EventItemComponentProps = { - value: EventItem; - fetchItems?: () => void; -}; - -const EventItemContainer = ({ value, fetchItems }: EventItemComponentProps) => { - const [isOpen, setIsOpen] = useState(false); - const [rewardItem, setRewardItem] = useState>(null); - - return ( - setIsOpen(true)} - > -
- {value.name} -
-
- {value.name} -
-
- -
- {value.price} -
-
- - {value.itemType === 3 && ( - setRewardItem(null)} - item={rewardItem || undefined} - /> - )} -
- ); -}; +import EventItemContainer from "@/components/Event/EventItemContainer"; type ItemListSectionProps = { items: Array; @@ -122,6 +24,7 @@ const ItemListSection = ({ items, fetchItems }: ItemListSectionProps) => { key={item._id} value={item} fetchItems={fetchItems} + clickable /> ))}
diff --git a/packages/web/src/pages/Event/Event2024FallStore/PublicNoticeContainer.tsx b/packages/web/src/pages/Event/Event2024FallStore/PublicNoticeContainer.tsx index 17f6ba900..30951b9d7 100644 --- a/packages/web/src/pages/Event/Event2024FallStore/PublicNoticeContainer.tsx +++ b/packages/web/src/pages/Event/Event2024FallStore/PublicNoticeContainer.tsx @@ -1,44 +1,17 @@ import { css, keyframes } from "@emotion/react"; import { useMemo } from "react"; -import useQuery from "@/hooks/useTaxiAPI"; - import WhiteContainer from "@/components/WhiteContainer"; -import dayjs, { - dayDifference2str, - dayNowServer, - dayServerToClient, -} from "@/tools/day"; import theme from "@/tools/theme"; import CampaignRoundedIcon from "@mui/icons-material/CampaignRounded"; -type Transaction = { - text: string; - createAt: Date; -}; - const PublicNoticeContainer = () => { - const { transactions }: { transactions: Array } = useQuery.get( - "/events/2024fall/publicNotice/recentTransactions" - )[1] || { transactions: [] }; - const notices = useMemo(() => { - const publicNotices = transactions - .sort((a, b) => dayjs(b.createAt).diff(a.createAt)) - .map( - ({ text, createAt }) => - `[${dayDifference2str( - dayServerToClient(createAt), - dayNowServer() - )}] ${text}` - ); - return [ - "[공지] 아이템이 조기 소진될 경우 9월 30일(토), 10월 5일(목)에 추가 입고될 예정입니다.", - ...publicNotices, - "[공지] 이벤트가 종료되면 아이템을 구매할 수 없습니다. 종료 전에 송편을 모두 소진해주세요.", - ]; - }, [transactions]); + const notices = [ + "[공지] 아이템이 조기 소진될 경우 9월 30일(토), 10월 5일(목)에 추가 입고될 예정입니다.", + "[공지] 이벤트가 종료되면 아이템을 구매할 수 없습니다. 종료 전에 송편을 모두 소진해주세요.", + ]; const animationDuration = useMemo( () => notices.reduce((acc, text) => acc + text.length, 0) * 0.2, [notices] diff --git a/packages/web/src/pages/Event/Event2024FallStore/index.tsx b/packages/web/src/pages/Event/Event2024FallStore/index.tsx index 08bc733fd..22644c50d 100644 --- a/packages/web/src/pages/Event/Event2024FallStore/index.tsx +++ b/packages/web/src/pages/Event/Event2024FallStore/index.tsx @@ -39,17 +39,12 @@ const Event2024FallStore = () => { @@ -66,12 +61,8 @@ const Event2024FallStore = () => {
- - 응모권 - - - 아이템 + 경품 응모권 diff --git a/packages/web/src/pages/Event/index.tsx b/packages/web/src/pages/Event/index.tsx index 5b2a39eb0..8aef439f8 100644 --- a/packages/web/src/pages/Event/index.tsx +++ b/packages/web/src/pages/Event/index.tsx @@ -10,15 +10,21 @@ import Event2023Spring from "./Event2023Spring"; import Event2023SpringGuide from "./Event2023SpringGuide"; import Event2024Fall from "./Event2024Fall"; import Event2024FallHistory from "./Event2024FallHistory"; -import Event2024FallLeaderboard from "./Event2024FallLeaderboard"; import Event2024FallMissions from "./Event2024FallMissions"; import Event2024FallStore from "./Event2024FallStore"; +import Item from "./Event2024FallStore/Item"; import Event2024Spring from "./Event2024Spring"; import Event2024SpringLeaderboard from "./Event2024SpringLeaderboard"; import Event2024SpringMissions from "./Event2024SpringMissions"; const Event = () => { - const { eventName } = useParams() as { eventName: string }; + const { eventName, itemId } = useParams() as { + eventName: string; + itemId: string; + }; + if (eventName === "2024fall-store" && itemId) { + return ; + } switch (eventName) { case "2022beta": @@ -49,8 +55,6 @@ const Event = () => { return ; case "2024fall-history": return ; - case "2024fall-leaderboard": - return ; case "2024fall-missions": return ; default: diff --git a/packages/web/src/static/events/2024fallTicket.svg b/packages/web/src/static/events/2024fallTicket.svg new file mode 100644 index 000000000..b192644c7 --- /dev/null +++ b/packages/web/src/static/events/2024fallTicket.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/web/src/static/events/2024fallTicketTilted.svg b/packages/web/src/static/events/2024fallTicketTilted.svg new file mode 100644 index 000000000..2407b5ed9 --- /dev/null +++ b/packages/web/src/static/events/2024fallTicketTilted.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 97136018c62261165dde3c988a9703a683adc720 Mon Sep 17 00:00:00 2001 From: hwmin414 Date: Tue, 3 Sep 2024 23:29:53 +0900 Subject: [PATCH 02/19] =?UTF-8?q?fix:=20build=20error=20&=20feat:=20?= =?UTF-8?q?=EA=B2=BD=EA=B3=A0=20=EB=AC=B8=EA=B5=AC=20placeholder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CreditAmountStatusContainer/index.tsx | 53 +++++++++++++++---- .../pages/Event/Event2024FallStore/Item.tsx | 13 ++++- .../pages/Event/Event2024FallStore/index.tsx | 2 +- .../EventSection/EventSection2024Fall.tsx | 15 +----- 4 files changed, 58 insertions(+), 25 deletions(-) diff --git a/packages/web/src/components/Event/CreditAmountStatusContainer/index.tsx b/packages/web/src/components/Event/CreditAmountStatusContainer/index.tsx index 192228238..199f62c32 100644 --- a/packages/web/src/components/Event/CreditAmountStatusContainer/index.tsx +++ b/packages/web/src/components/Event/CreditAmountStatusContainer/index.tsx @@ -5,16 +5,23 @@ 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 이미지 type CreditAmountStatusContainerProps = { - type?: "credit"; + type?: "credit" | "ticket"; } & Parameters[0]; const CreditAmountStatusContainer = ({ type = "credit", ...whiteContainerProps }: CreditAmountStatusContainerProps) => { - const { creditAmount } = useValueRecoilState("event2024FallInfo") || {}; + const { creditAmount, ticket1Amount, ticket2Amount } = + useValueRecoilState("event2023FallInfo") || {}; return (
- 내가 모은 송편 + {type === "credit" ? "내가 모은 송편" : "일반 / 고급 응모권"}
- <> - -
- {creditAmount || 0} -
- + {type === "credit" ? ( + <> + +
+ {creditAmount || 0} +
+ + ) : ( + <> + +
+ {ticket1Amount || 0} +
+
+ +
+ {ticket2Amount || 0} +
+ + )} ); }; diff --git a/packages/web/src/pages/Event/Event2024FallStore/Item.tsx b/packages/web/src/pages/Event/Event2024FallStore/Item.tsx index 4f1bae6b3..264fc4c93 100644 --- a/packages/web/src/pages/Event/Event2024FallStore/Item.tsx +++ b/packages/web/src/pages/Event/Event2024FallStore/Item.tsx @@ -54,7 +54,7 @@ const LeaderboardTopBar = () => ( flexShrink: 0, }} /> - 추첨 확률 + 당첨 확률
); @@ -409,7 +409,7 @@ const Event2024FallStoreItem = ({ itemId }: Event2024FallStoreItemProps) => {
- setRewardItem(null)} item={rewardItem || undefined} /> - )} + )} */}
); }; diff --git a/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx b/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx index abbb3ea3e..0c35187d8 100644 --- a/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx +++ b/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx @@ -31,7 +31,7 @@ const ModalPurchaseSuccess = ({
@@ -55,8 +55,8 @@ const ModalPurchaseSuccess = ({ ); diff --git a/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx b/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx index 0c35187d8..5c756473d 100644 --- a/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx +++ b/packages/web/src/components/ModalPopup/ModalPurchaseSuccess.tsx @@ -56,7 +56,7 @@ const ModalPurchaseSuccess = ({ css={{ width: "100%", height: "35px", - ...theme.font16_bold, + ...theme.font14_bold, ...theme.cursor(), textAlign: "center", borderRadius: "6px", diff --git a/packages/web/src/pages/Event/Event2024FallStore/Item.tsx b/packages/web/src/pages/Event/Event2024FallStore/Item.tsx index ec327726d..b0c0b7d48 100644 --- a/packages/web/src/pages/Event/Event2024FallStore/Item.tsx +++ b/packages/web/src/pages/Event/Event2024FallStore/Item.tsx @@ -275,6 +275,8 @@ const Event2024FallStoreItem = ({ itemId }: Event2024FallStoreItemProps) => { ? [true, "이벤트 기간이 아닙니다"] : !event2024FallInfo || !isLogin ? [true, "로그인 후 구매가 가능합니다"] + : event2024FallInfo.isAgreeOnTermsOfEvent + ? [true, "이벤트 참여 동의가 필요합니다"] : event2024FallInfo.creditAmount < (item?.price * purchaseAmount || 0) ? [true, "송편코인이 부족합니다"] : [false, "응모권 구매하기"], @@ -290,7 +292,7 @@ const Event2024FallStoreItem = ({ itemId }: Event2024FallStoreItemProps) => { data: { amount: purchaseAmount, }, - onSuccess: ({ reward }) => { + onSuccess: () => { fetchEvent2024FallInfo(); setPurchaseAmount(1); setIsOpenPurchaseSuccess(true); @@ -338,8 +340,8 @@ const Event2024FallStoreItem = ({ itemId }: Event2024FallStoreItemProps) => { )} 1 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 Hu0mjfQ<`gC literal 0 HcmV?d00001 diff --git a/packages/web/src/static/events/2024fallJackpotSuccess.png b/packages/web/src/static/events/2024fallJackpotSuccess.png new file mode 100644 index 0000000000000000000000000000000000000000..8d125cf699766023ebb1b70583edb175fe9ae815 GIT binary patch literal 1404 zcmV-?1%vvDP)rS+L9e0rLeT79fqpXdJPK6p$RgAj207vtq#_ zmJkZ8lG!1_!bnI6p-~*iuYMNyR?-moHvx>6}%#+Vy16$I-s@KVR|iy#O#F=NbaDQcQ6 zT7*YQ8#9K$jGzy;i=K8ih16?8ql9Boz#qB*O()+IN8&E3)PCWveqO~4Fm+=7&y^A+ z6$$9|-u^g>fPc=~@@>_7swN*A(P3%Nx4wc5UtT?E4BK?GfV+fBNqJn^-~?|G81aIn(&Db-*`HmhLq~s z^%0TfYr35_U6aL9E@%2ZKPs=RJ>J5EmF^Lj7aAvZ8mU3QO}orHAE*5fQ~MEHHNQuo2-@Dh(me&dp1>$0BAU!XeEF zpP#pIk4$V55nhCFk3?(|5nhyV-$-my5nhyV57n_rMR<|IJ+$1j2-DQ}7hxSi2F@t%g&BM^@IFJ~-3jw)?DS;hE@)K9eU{cA=DLcG7sBgy%|4Y*io1>+C)#i(aTn%3ZmBB~w6}DxQy527 zZQ^Wm^#kv5DjKG(>A}Q-m$(ulY3VK)i*zMM^Jp0+5JDOEpSTiJ70)Z;Q~DI~KLC^B znTle4rC-#9&=0BXS1-zahyL~<&ik++$BBAf!Ysircu0_GR`iuKqDp(~;ai`a{Z6}f zH?5zx%cKI2sFD|kxeI<;ym7rCGRIu@9Y>JWkr*}3r6l9VXnmCssMd?Ed-uP*^fs&S zXn+4uF47(-D<#(Gf?_foJSY!){b}_i5wa?UE{z*U#Oh<`0={iFquqBOliJAk!8>)T)0000< KMNUMnLSTY!dV%-= literal 0 HcmV?d00001 diff --git a/packages/web/src/types/event2024fall.d.ts b/packages/web/src/types/event2024fall.d.ts index 5d1849932..d72ccac8e 100644 --- a/packages/web/src/types/event2024fall.d.ts +++ b/packages/web/src/types/event2024fall.d.ts @@ -31,6 +31,11 @@ export type EventItem = { itemType: number; }; +export type RandomBoxResult = { + isJackpot: boolean; + amount: number; +}; + export type Transaction = { type: "get" | "use"; amount: number; From e8e78f33c17f7b5dcf053e6d12b6f7bbeeceac0c Mon Sep 17 00:00:00 2001 From: hwmin414 Date: Thu, 5 Sep 2024 01:40:59 +0900 Subject: [PATCH 11/19] feat: update wording & change image --- .../Event/EventItemContainer/index.tsx | 8 +++++++- .../ModalPopup/ModalEvent2024FallItem.tsx | 12 +++--------- .../pages/Event/Event2024FallStore/Item.tsx | 6 +++--- .../src/static/events/2024fallJackpotFail.png | Bin 2337 -> 13681 bytes .../static/events/2024fallJackpotSuccess.png | Bin 1404 -> 6818 bytes 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/web/src/components/Event/EventItemContainer/index.tsx b/packages/web/src/components/Event/EventItemContainer/index.tsx index e3203f350..1fc6c9d52 100644 --- a/packages/web/src/components/Event/EventItemContainer/index.tsx +++ b/packages/web/src/components/Event/EventItemContainer/index.tsx @@ -3,6 +3,8 @@ import { useHistory } from "react-router-dom"; import type { EventItem, RandomBoxResult } from "@/types/event2024fall"; +import { useFetchRecoilState } from "@/hooks/useFetchRecoilState"; + import { ModalEvent2024FallItem, ModalEvent2024FallRandomBox, @@ -25,6 +27,7 @@ const EventItemContainer = ({ fetchItems, clickable, }: EventItemComponentProps) => { + const fetchEvent2024FallInfo = useFetchRecoilState("event2024FallInfo"); const history = useHistory(); const [isOpen, setIsOpen] = useState(false); const [randomBoxResult, setRandomBoxResult] = @@ -108,7 +111,10 @@ const EventItemContainer = ({ {value.itemType === 3 && ( setRandomBoxResult(null)} + onChangeIsOpen={() => { + setRandomBoxResult(null); + fetchEvent2024FallInfo(); + }} randomBoxResult={randomBoxResult || undefined} /> )} diff --git a/packages/web/src/components/ModalPopup/ModalEvent2024FallItem.tsx b/packages/web/src/components/ModalPopup/ModalEvent2024FallItem.tsx index 88ea72ebf..682fda4cd 100644 --- a/packages/web/src/components/ModalPopup/ModalEvent2024FallItem.tsx +++ b/packages/web/src/components/ModalPopup/ModalEvent2024FallItem.tsx @@ -46,7 +46,6 @@ const ModalEvent2024FallItem = ({ setShareItem, ...modalProps }: ModalEvent2024FallItemProps) => { - const fetchEvent2024FallInfo = useFetchRecoilState("event2024FallInfo"); const event2024FallInfo = useValueRecoilState("event2024FallInfo"); const isLogin = useIsLogin(); @@ -80,7 +79,6 @@ const ModalEvent2024FallItem = ({ method: "post", data: { amount: bettingAmount / 100 }, onSuccess: (result) => { - fetchEvent2024FallInfo(); fetchItems?.(); modalProps.onChangeIsOpen?.(false); if (itemInfo.itemType === 3) { @@ -92,13 +90,7 @@ const ModalEvent2024FallItem = ({ onError: () => setAlert("구매를 실패하였습니다."), }); isRequesting.current = false; - }, [ - itemInfo._id, - fetchItems, - modalProps.onChangeIsOpen, - fetchEvent2024FallInfo, - bettingAmount, - ]); + }, [itemInfo._id, fetchItems, modalProps.onChangeIsOpen, bettingAmount]); const [isDisabled, buttonText] = useMemo( () => @@ -106,6 +98,8 @@ const ModalEvent2024FallItem = ({ ? [true, "이벤트 기간이 아닙니다"] : !event2024FallInfo || !isLogin ? [true, "로그인 후 구매가 가능합니다"] + : event2024FallInfo.isAgreeOnTermsOfEvent === false + ? [true, "이벤트 참여 동의가 필요합니다"] : event2024FallInfo.creditAmount < bettingAmount ? [true, "송편코인이 부족합니다"] : [false, "구매하기"], diff --git a/packages/web/src/pages/Event/Event2024FallStore/Item.tsx b/packages/web/src/pages/Event/Event2024FallStore/Item.tsx index b0c0b7d48..3fe3c3e98 100644 --- a/packages/web/src/pages/Event/Event2024FallStore/Item.tsx +++ b/packages/web/src/pages/Event/Event2024FallStore/Item.tsx @@ -275,8 +275,8 @@ const Event2024FallStoreItem = ({ itemId }: Event2024FallStoreItemProps) => { ? [true, "이벤트 기간이 아닙니다"] : !event2024FallInfo || !isLogin ? [true, "로그인 후 구매가 가능합니다"] - : event2024FallInfo.isAgreeOnTermsOfEvent - ? [true, "이벤트 참여 동의가 필요합니다"] + : event2024FallInfo.isAgreeOnTermsOfEvent === false + ? [true, "참여약관 동의가 필요합니다"] : event2024FallInfo.creditAmount < (item?.price * purchaseAmount || 0) ? [true, "송편코인이 부족합니다"] : [false, "응모권 구매하기"], @@ -344,7 +344,7 @@ const Event2024FallStoreItem = ({ itemId }: Event2024FallStoreItemProps) => { flexBasis: "calc(50% - 8px)", boxSizing: "border-box", minWidth: "100px", - padding: "12px 12px 0px 12px", + padding: "12px 12px 5px 12px", display: "flex", flexDirection: "column", alignItems: "left", diff --git a/packages/web/src/static/events/2024fallJackpotFail.png b/packages/web/src/static/events/2024fallJackpotFail.png index cd6f4d97913a715e6366e4d7770f1336d06a20b9..b087b3f86819cf2fb1e2dcf1b7f1db4586eebc67 100644 GIT binary patch literal 13681 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 diff --git a/packages/web/src/static/events/2024fallJackpotSuccess.png b/packages/web/src/static/events/2024fallJackpotSuccess.png index 8d125cf699766023ebb1b70583edb175fe9ae815..9a90b65e58399404b7efd24d0b13b6101ba113d6 100644 GIT binary patch literal 6818 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 Qe*gdg07*qoM6N<$f>IwN*Z=?k delta 1371 zcmV-h1*H0-HT()8iBL{Q4GJ0x0000DNk~Le0000s0000e2nGNE0JWJ3HjyDTe+3aq zL_t(|0o7T{ZX-n$Jyq51N1PZlnpwaGBgBFgW|>tIiCM7A`~mX?BNiZy#AqC`h!l_< zz97RF46|avB9;&etdiLw!NN#L2%%9N$FF`C_g2ywC$Sy7{0c|1TwUF_ZlA8Idyd<{ z9N||gC4Xn9ggL;$JQ0Q!2*Irlf6N#Xb3&(5DMITaHA}iuDPYE!8!;6G>oM?B$MK6G z2sSZe%xx)Znk`y{M@btqhQN%V54MY*b~c67YeJ)hV^P2#x&Tcl-xEjTE~?ai;jVsO z#SAcYV*byS5+oG~==I+IIEsLO&f4;A)qAQYAf7pJz7wmT)i5PYm6-p_e>aby<6Umk zazm%xMiBT^3_~i0uT#Zw1lLU=lgYwKxlqy&tF^Lj7aAvZo8k%nMmalmDjyGmiGp2Gsx&V%;ACYSO!ifOho7yV4g7MZj{6iWm$3%}c;Wu2is zavc`1B4$Kbhjr4Te*)as{YHe(A(a|wtlk)hVjK!f^FF1A<%baw#V#x`cJZ(g;Z!OO zA^wDMD|tuJ9gFBML6VCT0*EC6Uk3cv%e^Npz#Xv&0!Ig-9q=q>K9eU{cAf9AT1ju*n~cFjJOPKvvZ94Fdv zCUF<$K5nTi5wy2-uTvODRBhsHbM*u7aVi?7t?9wUftR=vB5CO^7>jfzM)PPHCJ;gy z_n){DQx(rE;#2w*@jn2Q;+cwKeWhR2gwPME>{l0*=d+Xs_pPc-V2zr6G|tM6!k|4=T{9w;j%*64y_G8;T74}1M-^&}CpDuphM8%M4C9 From 6b1fb8af900b512e3caf2443cdf9492253a6f210 Mon Sep 17 00:00:00 2001 From: hwmin414 Date: Thu, 5 Sep 2024 01:44:56 +0900 Subject: [PATCH 12/19] fix: build error --- .../src/components/ModalPopup/ModalEvent2024FallItem.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/web/src/components/ModalPopup/ModalEvent2024FallItem.tsx b/packages/web/src/components/ModalPopup/ModalEvent2024FallItem.tsx index 682fda4cd..0ecaa0511 100644 --- a/packages/web/src/components/ModalPopup/ModalEvent2024FallItem.tsx +++ b/packages/web/src/components/ModalPopup/ModalEvent2024FallItem.tsx @@ -10,11 +10,7 @@ import { import type { EventItem, RandomBoxResult } from "@/types/event2024fall"; import { useDelayBoolean } from "@/hooks/useDelay"; -import { - useFetchRecoilState, - useIsLogin, - useValueRecoilState, -} from "@/hooks/useFetchRecoilState"; +import { useIsLogin, useValueRecoilState } from "@/hooks/useFetchRecoilState"; import { useAxios } from "@/hooks/useTaxiAPI"; import Button from "@/components/Button"; From ab5ab27125667789447ad36fa2212d6cec435ca4 Mon Sep 17 00:00:00 2001 From: static Date: Fri, 6 Sep 2024 10:55:43 +0900 Subject: [PATCH 13/19] Refactor: update texts --- .../src/pages/Event/Event2024FallHistory.tsx | 6 +- .../pages/Event/Event2024FallStore/Item.tsx | 8 ++- .../pages/Event/Event2024FallStore/index.tsx | 7 +- .../EventSection/EventSection2024Fall.tsx | 5 +- .../random/event2024FallStoreSpeeches.ts | 69 +++++++++---------- packages/web/src/tools/random/index.ts | 1 - 6 files changed, 51 insertions(+), 45 deletions(-) diff --git a/packages/web/src/pages/Event/Event2024FallHistory.tsx b/packages/web/src/pages/Event/Event2024FallHistory.tsx index 6097e144a..f9d63f4b5 100644 --- a/packages/web/src/pages/Event/Event2024FallHistory.tsx +++ b/packages/web/src/pages/Event/Event2024FallHistory.tsx @@ -133,7 +133,11 @@ const Event2024FallHistory = () => { { {