From 0bf706abe73971d6c588382f728836199fc9e766 Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Fri, 16 Aug 2024 11:23:32 +0900 Subject: [PATCH 01/16] =?UTF-8?q?feat:=20useScrollToTarget=20hook=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Scroll/index.tsx | 9 ++++++-- client/src/features/Main/Headline.tsx | 8 +++++-- client/src/features/Main/Lottery.tsx | 7 +++--- client/src/features/Main/Section.tsx | 30 +++++++++++++++----------- client/src/hooks/useScrollToTarget.ts | 11 ++++++++++ client/src/pages/Main/index.tsx | 7 ++++-- 6 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 client/src/hooks/useScrollToTarget.ts diff --git a/client/src/components/Scroll/index.tsx b/client/src/components/Scroll/index.tsx index 3b172b68..26cb4822 100644 --- a/client/src/components/Scroll/index.tsx +++ b/client/src/components/Scroll/index.tsx @@ -4,6 +4,7 @@ import { cva } from "class-variance-authority"; export interface ScrollProps { type: "light" | "dark"; children: ReactNode; + onClick?: () => void; } const scrollTextVariants = cva(`h-body-2-regular`, { @@ -15,9 +16,13 @@ const scrollTextVariants = cva(`h-body-2-regular`, { }, }); -export default function Scroll({ type, children }: ScrollProps) { +export default function Scroll({ type, children, onClick }: ScrollProps) { return ( -
+
{children}
아래 스크롤 아이콘 void; +} + +function Headline({ id, handleClickScroll }: HeadlineProps) { return (
- +

이벤트에 대해 궁금하다면

스크롤

해 보세요

diff --git a/client/src/features/Main/Lottery.tsx b/client/src/features/Main/Lottery.tsx index 46c1e077..a8d6a588 100644 --- a/client/src/features/Main/Lottery.tsx +++ b/client/src/features/Main/Lottery.tsx @@ -1,4 +1,4 @@ -import { memo } from "react"; +import { forwardRef, memo } from "react"; import { Link } from "react-router-dom"; import LotteryEvent from "@/components/LotteryEvent"; import { LOTTERY_EVENT_DATA } from "@/constants/Main/lotteryEventData.ts"; @@ -6,10 +6,11 @@ import { Section } from "@/features/Main/Section.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; import ArrowIcon from "/public/assets/icons/arrow.svg?react"; -function Lottery({ id }: SectionKeyProps) { +const Lottery = forwardRef(function Lottery({ id }, ref) { return (
); -} +}); const MemoizedLottery = memo(Lottery); export { MemoizedLottery as Lottery }; diff --git a/client/src/features/Main/Section.tsx b/client/src/features/Main/Section.tsx index 94b410e6..194e1c5e 100644 --- a/client/src/features/Main/Section.tsx +++ b/client/src/features/Main/Section.tsx @@ -1,4 +1,4 @@ -import { PropsWithChildren } from "react"; +import { PropsWithChildren, forwardRef } from "react"; import { motion } from "framer-motion"; import CTAButton from "@/components/CTAButton"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; @@ -14,20 +14,24 @@ interface SectionProps extends PropsWithChildren, SectionKeyProps { url?: string; } -export function Section({ - id, - backgroundColor, - title, - titleColor, - subtitle, - description, - descriptionColor, - children, - url, -}: SectionProps) { +export const Section = forwardRef(function Section( + { + id, + backgroundColor, + title, + titleColor, + subtitle, + description, + descriptionColor, + children, + url, + }, + ref +) { return (
); -} +}); diff --git a/client/src/hooks/useScrollToTarget.ts b/client/src/hooks/useScrollToTarget.ts new file mode 100644 index 00000000..46cbd199 --- /dev/null +++ b/client/src/hooks/useScrollToTarget.ts @@ -0,0 +1,11 @@ +import { useRef } from "react"; + +export default function useScrollToTarget() { + const targetRef = useRef(null); + + const handleScrollToTarget = () => { + targetRef.current?.scrollIntoView({ behavior: "smooth" }); + }; + + return { targetRef, handleScrollToTarget }; +} diff --git a/client/src/pages/Main/index.tsx b/client/src/pages/Main/index.tsx index 05e60f44..ed58bd12 100644 --- a/client/src/pages/Main/index.tsx +++ b/client/src/pages/Main/index.tsx @@ -3,6 +3,7 @@ import Notice from "@/components/Notice"; import { MAIN_SECTIONS } from "@/constants/PageSections/sections.ts"; import { Headline, LearnMore, Lottery, Rush } from "@/features/Main"; import useHeaderStyleObserver from "@/hooks/useHeaderStyleObserver.ts"; +import useScrollToTarget from "@/hooks/useScrollToTarget"; import useScrollTop from "@/hooks/useScrollTop.tsx"; export default function Main() { @@ -11,10 +12,12 @@ export default function Main() { darkSections: [MAIN_SECTIONS.LOTTERY, MAIN_SECTIONS.LEARN_MORE], }); + const { targetRef, handleScrollToTarget } = useScrollToTarget(); + return (
- - + + From 286770007ab3c1efc946aa4cb927002815673868 Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Fri, 16 Aug 2024 11:32:51 +0900 Subject: [PATCH 02/16] =?UTF-8?q?feat:=20=EC=B6=94=EC=B2=A8=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Lottery/Headline.tsx | 5 +++-- client/src/features/Lottery/Intro.tsx | 8 ++++---- client/src/pages/Lottery/index.tsx | 6 +++++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/client/src/features/Lottery/Headline.tsx b/client/src/features/Lottery/Headline.tsx index 2443b71e..0acd1958 100644 --- a/client/src/features/Lottery/Headline.tsx +++ b/client/src/features/Lottery/Headline.tsx @@ -7,9 +7,10 @@ import { SectionKeyProps } from "@/types/sections.ts"; interface HeadlineProps extends SectionKeyProps { handleClickShortCutButton: () => void; + handleClickScroll: () => void; } -function Headline({ id, handleClickShortCutButton }: HeadlineProps) { +function Headline({ id, handleClickShortCutButton, handleClickScroll }: HeadlineProps) { return (
- +

캐스퍼 일렉트릭 봇이 어디서 왔는지 궁금하다면

스크롤

해보세요

diff --git a/client/src/features/Lottery/Intro.tsx b/client/src/features/Lottery/Intro.tsx index 240a91b9..4a8e4bf3 100644 --- a/client/src/features/Lottery/Intro.tsx +++ b/client/src/features/Lottery/Intro.tsx @@ -1,11 +1,11 @@ -import { memo } from "react"; +import { forwardRef, memo } from "react"; import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; import { SectionKeyProps } from "@/types/sections.ts"; -function Intro({ id }: SectionKeyProps) { +const Intro = forwardRef(function Intro({ id }, ref) { return ( -
+
); -} +}); const MemoizedIntro = memo(Intro); export { MemoizedIntro as Intro }; diff --git a/client/src/pages/Lottery/index.tsx b/client/src/pages/Lottery/index.tsx index 88d0dc4b..78a6345e 100644 --- a/client/src/pages/Lottery/index.tsx +++ b/client/src/pages/Lottery/index.tsx @@ -22,6 +22,7 @@ import useHeaderStyleObserver from "@/hooks/useHeaderStyleObserver.ts"; import usePhoneNumberDispatchContext from "@/hooks/usePhoneNumberDispatchContext"; import usePhoneNumberStateContext from "@/hooks/usePhoneNumberStateContext"; import usePopup from "@/hooks/usePopup"; +import useScrollToTarget from "@/hooks/useScrollToTarget"; import useScrollTop from "@/hooks/useScrollTop"; import useToast from "@/hooks/useToast"; import { PostAuthResponse } from "@/types/authApi"; @@ -44,6 +45,8 @@ export default function Lottery() { }); const [_cookies, setCookie] = useCookies([COOKIE_KEY.ACCESS_TOKEN, COOKIE_KEY.INVITE_USER]); + const { targetRef, handleScrollToTarget } = useScrollToTarget(); + const { data: authToken, isSuccess: isSuccessGetAuthToken, @@ -104,8 +107,9 @@ export default function Lottery() { - + From 6c346e13e7a331ed2c460323150c73144db16b43 Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Fri, 16 Aug 2024 12:09:01 +0900 Subject: [PATCH 03/16] =?UTF-8?q?feat:=20=EC=84=A0=EC=B0=A9=EC=88=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20scroll=20=ED=81=B4=EB=A6=AD=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/BalanceGame.tsx | 8 ++++++-- client/src/features/Rush/Intro.tsx | 7 ++++--- client/src/pages/Rush/index.tsx | 11 +++++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame.tsx index 13d289b4..8a4e53d2 100644 --- a/client/src/features/Rush/BalanceGame.tsx +++ b/client/src/features/Rush/BalanceGame.tsx @@ -6,7 +6,11 @@ import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts" import { Background } from "@/features/Rush/Background.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; -function BalanceGame({ id }: SectionKeyProps) { +interface BalanceGameProps extends SectionKeyProps { + handleScrollToTarget: () => void; +} + +function BalanceGame({ id, handleScrollToTarget }: BalanceGameProps) { return (
- +

스크롤

하고 캐스퍼 일렉트릭의 놀라운 성능을 알아보세요

diff --git a/client/src/features/Rush/Intro.tsx b/client/src/features/Rush/Intro.tsx index 1b46a306..41e06263 100644 --- a/client/src/features/Rush/Intro.tsx +++ b/client/src/features/Rush/Intro.tsx @@ -1,12 +1,13 @@ -import { memo } from "react"; +import { forwardRef, memo } from "react"; import { motion } from "framer-motion"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import { SectionKeyProps } from "@/types/sections.ts"; -function Intro({ id }: SectionKeyProps) { +const Intro = forwardRef(function Intro({ id }, ref) { return (
@@ -29,7 +30,7 @@ function Intro({ id }: SectionKeyProps) {
); -} +}); const MemoizedIntro = memo(Intro); export { MemoizedIntro as Intro }; diff --git a/client/src/pages/Rush/index.tsx b/client/src/pages/Rush/index.tsx index eb72ec89..b046e69d 100644 --- a/client/src/pages/Rush/index.tsx +++ b/client/src/pages/Rush/index.tsx @@ -17,6 +17,7 @@ import { ReasonSecond, } from "@/features/Rush"; import useHeaderStyleObserver from "@/hooks/useHeaderStyleObserver.ts"; +import useScrollToTarget from "@/hooks/useScrollToTarget"; import useScrollTop from "@/hooks/useScrollTop.tsx"; export default function Rush() { @@ -24,10 +25,16 @@ export default function Rush() { const containerRef = useHeaderStyleObserver({ darkSections: [RUSH_SECTIONS.INTRO], }); + + const { targetRef, handleScrollToTarget } = useScrollToTarget(); + return (
- - + + From 0010c36b8babfa74fe021ed2d53e9403e3e89ffb Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Fri, 16 Aug 2024 14:08:30 +0900 Subject: [PATCH 04/16] =?UTF-8?q?chore:=20=EA=B3=B5=EC=9C=A0=20=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EB=B3=B5=EC=82=AC=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/CasperCustom/CasperCustomFinish.tsx | 2 +- client/src/pages/CasperShowCase/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/features/CasperCustom/CasperCustomFinish.tsx b/client/src/features/CasperCustom/CasperCustomFinish.tsx index ef7f62c0..85d8c6d3 100644 --- a/client/src/features/CasperCustom/CasperCustomFinish.tsx +++ b/client/src/features/CasperCustom/CasperCustomFinish.tsx @@ -50,7 +50,7 @@ export function CasperCustomFinish({ const { showToast, ToastComponent } = useToast( isErrorGetShareLink ? "공유 링크 생성에 실패했습니다! 캐스퍼 봇 생성 후 다시 시도해주세요." - : "링크가 복사되었어요!" + : "🔗 링크가 복사되었어요!" ); const dispatch = useCasperCustomDispatchContext(); diff --git a/client/src/pages/CasperShowCase/index.tsx b/client/src/pages/CasperShowCase/index.tsx index c005e155..e3816ff9 100644 --- a/client/src/pages/CasperShowCase/index.tsx +++ b/client/src/pages/CasperShowCase/index.tsx @@ -53,7 +53,7 @@ export default function CasperShowCase() { const { showToast, ToastComponent } = useToast( isErrorGetShareLink ? "공유 링크 생성에 실패했습니다! 캐스퍼 봇 생성 후 다시 시도해주세요." - : "링크가 복사되었어요!" + : "🔗 링크가 복사되었어요!" ); const casperList = useLoaderData() as GetCasperListResponse; From 15d8c6c9eba9c6fc0a95bb09c700e88aaa1042ab Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Fri, 16 Aug 2024 16:13:27 +0900 Subject: [PATCH 05/16] =?UTF-8?q?fix:=20=EA=B8=B0=EB=8C=80=ED=8F=89=20over?= =?UTF-8?q?flow=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/CasperCustom/CasperCardBackUI.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/features/CasperCustom/CasperCardBackUI.tsx b/client/src/features/CasperCustom/CasperCardBackUI.tsx index 2c3cb63c..dbd9a3c1 100644 --- a/client/src/features/CasperCustom/CasperCardBackUI.tsx +++ b/client/src/features/CasperCustom/CasperCardBackUI.tsx @@ -165,7 +165,12 @@ export function CasperCardBackUI({ style={{ width: CARD_WIDTH - 100 }} >

작성한 기대평

-

{expectations}

+

+ {expectations} +

)} From 964223eb4c88312aa241daeef058de428f954727 Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Fri, 16 Aug 2024 17:01:56 +0900 Subject: [PATCH 06/16] =?UTF-8?q?feat:=20=EC=BA=90=EC=8A=A4=ED=8D=BC=20?= =?UTF-8?q?=EB=B4=87=20=EA=B0=9C=EC=88=98=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?UI=20=EB=B6=84=EA=B8=B0=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/CasperShowCase/CasperCards.tsx | 13 ++++- .../CasperShowCase/TransitionCasperCards.tsx | 51 +++++++++++++------ client/src/pages/CasperShowCase/index.tsx | 34 +++++++++---- 3 files changed, 72 insertions(+), 26 deletions(-) diff --git a/client/src/features/CasperShowCase/CasperCards.tsx b/client/src/features/CasperShowCase/CasperCards.tsx index d1a1cdde..58d8707b 100644 --- a/client/src/features/CasperShowCase/CasperCards.tsx +++ b/client/src/features/CasperShowCase/CasperCards.tsx @@ -1,3 +1,4 @@ +import { useMemo } from "react"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; import { CasperCardType, TransitionCasperCards } from "./TransitionCasperCards"; @@ -8,8 +9,16 @@ interface CasperCardsProps { export function CasperCards({ cardList }: CasperCardsProps) { const cardLength = cardList.length; const cardLengthHalf = Math.floor(cardLength / 2); - const topCardList = cardList.slice(0, cardLengthHalf); - const bottomCardList = cardList.slice(cardLengthHalf, cardLength); + const visibleCardCount = useMemo(() => { + const width = window.innerWidth; + const cardWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH; + + return Math.ceil(width / cardWidth); + }, []); + const isMultipleLine = visibleCardCount * 2 <= cardLength; + + const topCardList = cardList.slice(0, isMultipleLine ? cardLengthHalf : cardLength); + const bottomCardList = isMultipleLine ? cardList.slice(cardLengthHalf, cardLength) : []; const itemWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH; const gap = 40; diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index 6373f931..a441b0c7 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { AnimatePresence, motion, useAnimation } from "framer-motion"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; import { CARD_TRANSITION } from "@/constants/CasperShowCase/showCase"; @@ -29,6 +29,14 @@ export function TransitionCasperCards({ gap, isEndCard, }: TransitionCasperCardsProps) { + const visibleCardCount = useMemo(() => { + const width = window.innerWidth; + const cardWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH; + + return Math.ceil(width / cardWidth); + }, []); + const isAnimated = visibleCardCount <= cardList.length; + const containerRef = useRef(null); const transitionControls = useAnimation(); @@ -54,6 +62,14 @@ export function TransitionCasperCards({ startAnimation(x); }, [transitionControls, totalWidth]); + const expandedCardList = useMemo(() => { + if (isAnimated) { + return [...cardList, ...cardList.slice(0, visibleCardCount)]; + } + + return cardList; + }, [cardList]); + const renderCardItem = (cardItem: CasperCardType, id: string) => { const [isFlipped, setIsFlipped] = useState(false); const { isInView, cardRef } = useLazyLoading(); @@ -92,20 +108,25 @@ export function TransitionCasperCards({ return ( - { - if (isEndCard(parseInt(String(latest.x)))) { - startAnimation(initialX); - } - }} - > - {cardList.map((card) => renderCardItem(card, `${card.id}`))} - {cardList.map((card) => renderCardItem(card, `${card.id}-clone`))} - + {isAnimated ? ( + { + if (isEndCard(parseInt(String(latest.x)))) { + startAnimation(initialX); + } + }} + > + {expandedCardList.map((card, idx) => renderCardItem(card, `${card.id}-${idx}`))} + + ) : ( +
    + {expandedCardList.map((card, idx) => renderCardItem(card, `${card.id}-${idx}`))} +
+ )}
); } diff --git a/client/src/pages/CasperShowCase/index.tsx b/client/src/pages/CasperShowCase/index.tsx index e3816ff9..0c98833a 100644 --- a/client/src/pages/CasperShowCase/index.tsx +++ b/client/src/pages/CasperShowCase/index.tsx @@ -79,16 +79,32 @@ export default function CasperShowCase() { id={CASPER_SHOWCASE_SECTIONS.SHOWCASE} className="flex flex-col justify-center items-center gap-800 w-full h-screen bg-n-neutral-950 overflow-hidden pt-1000" > - -

- 카드 위에 커서를 올리면 기대평을 볼 수 있어요 -

+ {cardListData.length === 0 ? ( + +

+ 나만의 캐스퍼 일렉트릭 봇을 만들어주세요! +

+ 캐스퍼 봇 아이콘 +
+ ) : ( + +

+ 카드 위에 커서를 올리면 기대평을 볼 수 있어요 +

- -
+ +
+ )} From 75507cfa8551a8c87f281278329b975189ad6569 Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Fri, 16 Aug 2024 18:05:47 +0900 Subject: [PATCH 07/16] =?UTF-8?q?fix:=20=EC=A0=84=ED=99=94=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20popup=20input=20=EC=98=88=EC=99=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/PopUp/index.tsx | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/client/src/components/PopUp/index.tsx b/client/src/components/PopUp/index.tsx index e3ed990b..4fbac935 100644 --- a/client/src/components/PopUp/index.tsx +++ b/client/src/components/PopUp/index.tsx @@ -1,4 +1,4 @@ -import { FormEvent, useCallback, useEffect, useState } from "react"; +import { FormEvent, useCallback, useEffect, useMemo, useState } from "react"; import { PHONE_NUMBER_FORMAT, formatPhoneNumber } from "@/utils/formatPhoneNumber"; import CTAButton from "../CTAButton"; import CheckBox from "../CheckBox"; @@ -43,9 +43,21 @@ export default function PopUp({ setIsMarketingInfoCheck(isChecked); }, []); + const errorMessage = useMemo(() => { + if (phoneNumber.length >= 11 && !phoneNumber.match(PHONE_NUMBER_FORMAT)) { + return "전화번호는 010으로 시작해야합니다!"; + } + if (!isMarketingInfoCheck || !isUserInfoCheck) { + return "필수 약관에 동의해주세요!"; + } + return ""; + }, [phoneNumber, isUserInfoCheck, isMarketingInfoCheck]); + const handleConfirm = (e: FormEvent) => { e.preventDefault(); - handlePhoneNumberConfirm(phoneNumber); + if (!errorMessage) { + handlePhoneNumberConfirm(phoneNumber); + } }; return ( @@ -84,7 +96,11 @@ export default function PopUp({ handleValueChange={handleTextFieldChange} /> -
+
+ +

{errorMessage}

+ +
From bdd05e401fbdf10d64bea81cc0a29097059742c1 Mon Sep 17 00:00:00 2001 From: juhyojeong Date: Sat, 17 Aug 2024 18:03:58 +0900 Subject: [PATCH 08/16] =?UTF-8?q?chore:=20transition=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/CasperShowCase/CasperCards.tsx | 7 +- .../TransitionCasperCardItem.tsx | 53 +++++++++ .../CasperShowCase/TransitionCasperCards.tsx | 103 ++++++++---------- client/src/types/casper.ts | 8 ++ 4 files changed, 113 insertions(+), 58 deletions(-) create mode 100644 client/src/features/CasperShowCase/TransitionCasperCardItem.tsx create mode 100644 client/src/types/casper.ts diff --git a/client/src/features/CasperShowCase/CasperCards.tsx b/client/src/features/CasperShowCase/CasperCards.tsx index 58d8707b..54226d79 100644 --- a/client/src/features/CasperShowCase/CasperCards.tsx +++ b/client/src/features/CasperShowCase/CasperCards.tsx @@ -1,13 +1,14 @@ import { useMemo } from "react"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; -import { CasperCardType, TransitionCasperCards } from "./TransitionCasperCards"; +import type { CasperCardType } from "@/types/casper"; +import { TransitionCasperCards } from "./TransitionCasperCards"; interface CasperCardsProps { cardList: CasperCardType[]; } export function CasperCards({ cardList }: CasperCardsProps) { - const cardLength = cardList.length; + const cardLength = 20; const cardLengthHalf = Math.floor(cardLength / 2); const visibleCardCount = useMemo(() => { const width = window.innerWidth; @@ -22,7 +23,7 @@ export function CasperCards({ cardList }: CasperCardsProps) { const itemWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH; const gap = 40; - const totalWidth = (itemWidth + gap) * topCardList.length; + const totalWidth = (itemWidth + gap) * visibleCardCount; const isEndTopCard = (latestX: number) => { return latestX <= -totalWidth; diff --git a/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx b/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx new file mode 100644 index 00000000..8d605bf2 --- /dev/null +++ b/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx @@ -0,0 +1,53 @@ +import { useState } from "react"; +import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; +import useLazyLoading from "@/hooks/useLazyLoading"; +import type { CasperCardType } from "@/types/casper"; +import { CasperFlipCard } from "../CasperCustom/CasperFlipCard"; + +interface TransitionCasperCardItemProps { + cardItem: CasperCardType; + id: string; + stopAnimation?: () => void; + startAnimation?: () => void; +} + +export function TransitionCasperCardItem({ + cardItem, + id, + stopAnimation, + startAnimation, +}: TransitionCasperCardItemProps) { + const [isFlipped, setIsFlipped] = useState(false); + const { isInView, cardRef } = useLazyLoading(); + + const handleMouseEnter = () => { + stopAnimation && stopAnimation(); + setIsFlipped(true); + }; + + const handleMouseLeave = () => { + startAnimation && startAnimation(); + setIsFlipped(false); + }; + + return ( +
  • + {isInView && ( + + )} +
  • + ); +} diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index a441b0c7..ba69cb2c 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -1,17 +1,10 @@ import { useEffect, useMemo, useRef, useState } from "react"; -import { AnimatePresence, motion, useAnimation } from "framer-motion"; +import { AnimatePresence, type ResolvedValues, motion, useAnimation } from "framer-motion"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; import { CARD_TRANSITION } from "@/constants/CasperShowCase/showCase"; -import useLazyLoading from "@/hooks/useLazyLoading"; -import { SelectedCasperIdxType } from "@/types/casperCustom"; -import { CasperFlipCard } from "../CasperCustom/CasperFlipCard"; +import { CasperCardType } from "@/types/casper"; +import { TransitionCasperCardItem } from "./TransitionCasperCardItem"; -export interface CasperCardType { - id: number; - casperName: string; - expectations: string; - selectedCasperIdx: SelectedCasperIdxType; -} interface TransitionCasperCardsProps { cardList: CasperCardType[]; initialX: number; @@ -36,11 +29,13 @@ export function TransitionCasperCards({ return Math.ceil(width / cardWidth); }, []); const isAnimated = visibleCardCount <= cardList.length; + const expandedCardList = useMemo(() => [...cardList, ...cardList], [cardList]); const containerRef = useRef(null); const transitionControls = useAnimation(); const [x, setX] = useState(initialX); + const [visibleCardListIdx, setVisibleCardListIdx] = useState(0); const startAnimation = (x: number) => { transitionControls.start({ @@ -58,52 +53,40 @@ export function TransitionCasperCards({ } }; - useEffect(() => { - startAnimation(x); - }, [transitionControls, totalWidth]); - - const expandedCardList = useMemo(() => { + const visibleCardList = useMemo(() => { if (isAnimated) { - return [...cardList, ...cardList.slice(0, visibleCardCount)]; + return [ + ...expandedCardList.slice( + visibleCardListIdx, + visibleCardListIdx + visibleCardCount + ), + ...expandedCardList.slice( + visibleCardListIdx + visibleCardCount, + visibleCardListIdx + visibleCardCount * 2 + ), + ]; } return cardList; - }, [cardList]); + }, [cardList, visibleCardCount, visibleCardListIdx]); - const renderCardItem = (cardItem: CasperCardType, id: string) => { - const [isFlipped, setIsFlipped] = useState(false); - const { isInView, cardRef } = useLazyLoading(); + useEffect(() => { + startAnimation(x); + }, [transitionControls, totalWidth]); - const handleMouseEnter = () => { - stopAnimation(); - setIsFlipped(true); - }; + const handleUpdateAnimation = (latest: ResolvedValues) => { + if (isEndCard(parseInt(String(latest.x)))) { + startAnimation(initialX); - const handleMouseLeave = () => { - startAnimation(x); - setIsFlipped(false); - }; + let nextIdx = visibleCardListIdx + visibleCardCount; - return ( -
  • - {isInView && ( - - )} -
  • - ); + // 만약 nextIdx가 cardList의 길이를 초과하면 0으로 초기화하거나 초과분을 조정합니다. + if (nextIdx + visibleCardCount >= cardList.length) { + nextIdx = (nextIdx + visibleCardCount) % cardList.length; + } + + setVisibleCardListIdx(nextIdx); + } }; return ( @@ -114,17 +97,27 @@ export function TransitionCasperCards({ className="flex" animate={transitionControls} style={{ gap: `${gap}px` }} - onUpdate={(latest) => { - if (isEndCard(parseInt(String(latest.x)))) { - startAnimation(initialX); - } - }} + onUpdate={handleUpdateAnimation} > - {expandedCardList.map((card, idx) => renderCardItem(card, `${card.id}-${idx}`))} + {visibleCardList.map((card, idx) => ( + startAnimation(x)} + /> + ))} ) : (
      - {expandedCardList.map((card, idx) => renderCardItem(card, `${card.id}-${idx}`))} + {visibleCardList.map((card, idx) => ( + + ))}
    )} diff --git a/client/src/types/casper.ts b/client/src/types/casper.ts new file mode 100644 index 00000000..7a358979 --- /dev/null +++ b/client/src/types/casper.ts @@ -0,0 +1,8 @@ +import { SelectedCasperIdxType } from "./casperCustom"; + +export interface CasperCardType { + id: number; + casperName: string; + expectations: string; + selectedCasperIdx: SelectedCasperIdxType; +} From 349ab4cd470446d7375868559c5629adba1eecd5 Mon Sep 17 00:00:00 2001 From: juhyojeong Date: Sun, 18 Aug 2024 17:00:24 +0900 Subject: [PATCH 09/16] =?UTF-8?q?chore:=20transition=20=EC=A1=B0=EA=B1=B4?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/CasperShowCase/CasperCards.tsx | 2 +- .../src/features/CasperShowCase/TransitionCasperCards.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/features/CasperShowCase/CasperCards.tsx b/client/src/features/CasperShowCase/CasperCards.tsx index 54226d79..cb44e426 100644 --- a/client/src/features/CasperShowCase/CasperCards.tsx +++ b/client/src/features/CasperShowCase/CasperCards.tsx @@ -8,7 +8,7 @@ interface CasperCardsProps { } export function CasperCards({ cardList }: CasperCardsProps) { - const cardLength = 20; + const cardLength = 10; const cardLengthHalf = Math.floor(cardLength / 2); const visibleCardCount = useMemo(() => { const width = window.innerWidth; diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index ba69cb2c..50f19ae6 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -81,10 +81,12 @@ export function TransitionCasperCards({ let nextIdx = visibleCardListIdx + visibleCardCount; // 만약 nextIdx가 cardList의 길이를 초과하면 0으로 초기화하거나 초과분을 조정합니다. - if (nextIdx + visibleCardCount >= cardList.length) { - nextIdx = (nextIdx + visibleCardCount) % cardList.length; + if (visibleCardListIdx >= cardList.length) { + nextIdx = visibleCardListIdx % cardList.length; } + console.log(nextIdx); + setVisibleCardListIdx(nextIdx); } }; From c88c631f63001f9a118a545403246fa56684a668 Mon Sep 17 00:00:00 2001 From: juhyojeong Date: Sun, 18 Aug 2024 19:46:49 +0900 Subject: [PATCH 10/16] =?UTF-8?q?feat:=20transition=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/constants/CasperShowCase/showCase.ts | 2 +- .../features/CasperCustom/CasperFlipCard.tsx | 2 +- .../features/CasperShowCase/CasperCards.tsx | 11 ++-- .../CasperShowCase/TransitionCasperCards.tsx | 57 +++++++++---------- 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/client/src/constants/CasperShowCase/showCase.ts b/client/src/constants/CasperShowCase/showCase.ts index 212e74cb..113ef598 100644 --- a/client/src/constants/CasperShowCase/showCase.ts +++ b/client/src/constants/CasperShowCase/showCase.ts @@ -2,7 +2,7 @@ export const CARD_TRANSITION = (itemLength: number) => ({ x: { repeat: Infinity, repeatType: "loop", - duration: itemLength * 2, + duration: itemLength, ease: "linear", }, }); diff --git a/client/src/features/CasperCustom/CasperFlipCard.tsx b/client/src/features/CasperCustom/CasperFlipCard.tsx index c3a7c52b..3f40dd73 100644 --- a/client/src/features/CasperCustom/CasperFlipCard.tsx +++ b/client/src/features/CasperCustom/CasperFlipCard.tsx @@ -1,7 +1,7 @@ import { memo } from "react"; import { motion } from "framer-motion"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; -import { CasperCardType } from "../CasperShowCase/TransitionCasperCards"; +import type { CasperCardType } from "@/types/casper"; import { CasperCardBackUI } from "./CasperCardBackUI"; import { CasperCardFrontUI } from "./CasperCardFrontUI"; diff --git a/client/src/features/CasperShowCase/CasperCards.tsx b/client/src/features/CasperShowCase/CasperCards.tsx index cb44e426..38fe15c2 100644 --- a/client/src/features/CasperShowCase/CasperCards.tsx +++ b/client/src/features/CasperShowCase/CasperCards.tsx @@ -8,7 +8,7 @@ interface CasperCardsProps { } export function CasperCards({ cardList }: CasperCardsProps) { - const cardLength = 10; + const cardLength = 20; const cardLengthHalf = Math.floor(cardLength / 2); const visibleCardCount = useMemo(() => { const width = window.innerWidth; @@ -38,17 +38,18 @@ export function CasperCards({ cardList }: CasperCardsProps) { cardList={topCardList} initialX={0} gap={gap} - diffX={-totalWidth} - totalWidth={totalWidth} + diffX={-totalWidth - 1} + visibleCardCount={visibleCardCount} isEndCard={isEndTopCard} />
    ); diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index 50f19ae6..b49884d2 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -1,6 +1,5 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { AnimatePresence, type ResolvedValues, motion, useAnimation } from "framer-motion"; -import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; import { CARD_TRANSITION } from "@/constants/CasperShowCase/showCase"; import { CasperCardType } from "@/types/casper"; import { TransitionCasperCardItem } from "./TransitionCasperCardItem"; @@ -9,27 +8,23 @@ interface TransitionCasperCardsProps { cardList: CasperCardType[]; initialX: number; diffX: number; - totalWidth: number; + visibleCardCount: number; gap: number; isEndCard: (latestX: number) => boolean; + isReverseCards?: boolean; } export function TransitionCasperCards({ cardList, initialX, diffX, - totalWidth, gap, + visibleCardCount, isEndCard, + isReverseCards = false, }: TransitionCasperCardsProps) { - const visibleCardCount = useMemo(() => { - const width = window.innerWidth; - const cardWidth = CASPER_CARD_SIZE[CASPER_SIZE_OPTION.SM].CARD_WIDTH; - - return Math.ceil(width / cardWidth); - }, []); const isAnimated = visibleCardCount <= cardList.length; - const expandedCardList = useMemo(() => [...cardList, ...cardList], [cardList]); + const expandedCardList = useMemo(() => [...cardList, ...cardList, ...cardList], [cardList]); const containerRef = useRef(null); const transitionControls = useAnimation(); @@ -54,40 +49,40 @@ export function TransitionCasperCards({ }; const visibleCardList = useMemo(() => { - if (isAnimated) { - return [ - ...expandedCardList.slice( - visibleCardListIdx, - visibleCardListIdx + visibleCardCount - ), - ...expandedCardList.slice( - visibleCardListIdx + visibleCardCount, - visibleCardListIdx + visibleCardCount * 2 - ), - ]; + const list = expandedCardList.slice( + visibleCardListIdx, + visibleCardListIdx + visibleCardCount * 2 + ); + + if (isAnimated && isReverseCards) { + return list.reverse(); } - return cardList; - }, [cardList, visibleCardCount, visibleCardListIdx]); + return isAnimated ? list : cardList; + }, [ + isReverseCards, + expandedCardList, + cardList, + isAnimated, + visibleCardCount, + visibleCardListIdx, + ]); useEffect(() => { startAnimation(x); - }, [transitionControls, totalWidth]); + }, []); const handleUpdateAnimation = (latest: ResolvedValues) => { if (isEndCard(parseInt(String(latest.x)))) { - startAnimation(initialX); - let nextIdx = visibleCardListIdx + visibleCardCount; - // 만약 nextIdx가 cardList의 길이를 초과하면 0으로 초기화하거나 초과분을 조정합니다. - if (visibleCardListIdx >= cardList.length) { - nextIdx = visibleCardListIdx % cardList.length; + // 만약 nextIdx가 cardList의 길이를 초과하면 배열의 처음부터 다시 index를 카운트하도록 함 + if (nextIdx >= cardList.length) { + nextIdx = nextIdx % cardList.length; } - console.log(nextIdx); - setVisibleCardListIdx(nextIdx); + startAnimation(initialX); } }; From 17d0435c56e4d6f4d92f3f9db7e8b65e7ce51322 Mon Sep 17 00:00:00 2001 From: juhyojeong Date: Sun, 18 Aug 2024 19:53:08 +0900 Subject: [PATCH 11/16] =?UTF-8?q?chore:=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomProcess/CasperCustomFinishing.tsx | 2 +- .../TransitionCasperCardItem.tsx | 2 +- .../CasperShowCase/TransitionCasperCards.tsx | 2 +- client/src/features/Rush/BalanceGame.tsx | 65 ------------------- client/src/pages/Rush/index.tsx | 2 +- 5 files changed, 4 insertions(+), 69 deletions(-) delete mode 100644 client/src/features/Rush/BalanceGame.tsx diff --git a/client/src/features/CasperCustom/CustomProcess/CasperCustomFinishing.tsx b/client/src/features/CasperCustom/CustomProcess/CasperCustomFinishing.tsx index 344fa134..74c53203 100644 --- a/client/src/features/CasperCustom/CustomProcess/CasperCustomFinishing.tsx +++ b/client/src/features/CasperCustom/CustomProcess/CasperCustomFinishing.tsx @@ -4,9 +4,9 @@ import { CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; import { DISSOLVE } from "@/constants/animation"; import { SCROLL_MOTION } from "@/constants/animation"; import { CasperFlipCard } from "@/features/CasperCustom/CasperCard/CasperFlipCard"; -import { CasperCardType } from "@/features/CasperShowCase/TransitionCasperCards"; import useCasperCustomStateContext from "@/hooks/useCasperCustomStateContext"; import useToast from "@/hooks/useToast"; +import type { CasperCardType } from "@/types/casper"; interface CasperCustomFinishingProps { navigateNextStep: () => void; diff --git a/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx b/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx index 8d605bf2..8fa9c4df 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; +import { CasperFlipCard } from "@/features/CasperCustom/CasperCard/CasperFlipCard"; import useLazyLoading from "@/hooks/useLazyLoading"; import type { CasperCardType } from "@/types/casper"; -import { CasperFlipCard } from "../CasperCustom/CasperFlipCard"; interface TransitionCasperCardItemProps { cardItem: CasperCardType; diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index b49884d2..2328df31 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { AnimatePresence, type ResolvedValues, motion, useAnimation } from "framer-motion"; import { CARD_TRANSITION } from "@/constants/CasperShowCase/showCase"; -import { CasperCardType } from "@/types/casper"; +import type { CasperCardType } from "@/types/casper"; import { TransitionCasperCardItem } from "./TransitionCasperCardItem"; interface TransitionCasperCardsProps { diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame.tsx deleted file mode 100644 index 8a4e53d2..00000000 --- a/client/src/features/Rush/BalanceGame.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { memo } from "react"; -import { motion } from "framer-motion"; -import CTAButton from "@/components/CTAButton"; -import Scroll from "@/components/Scroll"; -import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { Background } from "@/features/Rush/Background.tsx"; -import { SectionKeyProps } from "@/types/sections.ts"; - -interface BalanceGameProps extends SectionKeyProps { - handleScrollToTarget: () => void; -} - -function BalanceGame({ id, handleScrollToTarget }: BalanceGameProps) { - return ( -
    - - 이제 곧 하단에 밸런스 게임 주제가 공개돼요! - - -
    -

    - 밸런스 게임 주제 공개까지 남은 시간 -

    -
    - -

    Hours

    -

    04

    -
    -

    :

    - -

    Minutes

    -

    21

    -
    -

    :

    - -

    Seconds

    -

    32

    -
    -
    -
    -
    - -

    - 우리 편에 투표할 친구를 불러오세요! -

    - -
    - - -

    스크롤

    -

    하고 캐스퍼 일렉트릭의 놀라운 성능을 알아보세요

    -
    -
    -
    - ); -} - -const MemoizedBalanceGame = memo(BalanceGame); -export { MemoizedBalanceGame as BalanceGame }; diff --git a/client/src/pages/Rush/index.tsx b/client/src/pages/Rush/index.tsx index 87acb280..0f8e5c00 100644 --- a/client/src/pages/Rush/index.tsx +++ b/client/src/pages/Rush/index.tsx @@ -30,7 +30,7 @@ export default function Rush() { return (
    - + From 2f718ba7569c7f6dacbf1b08c029da49d6247833 Mon Sep 17 00:00:00 2001 From: juhyojeong Date: Sun, 18 Aug 2024 20:25:05 +0900 Subject: [PATCH 12/16] =?UTF-8?q?chore:=20=EA=B9=9C=EB=B9=A1=EC=9E=84=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/CasperShowCase/showCase.ts | 2 +- client/src/features/CasperShowCase/CasperCards.tsx | 6 +++--- .../CasperShowCase/TransitionCasperCardItem.tsx | 11 +---------- .../features/CasperShowCase/TransitionCasperCards.tsx | 6 ++++-- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/client/src/constants/CasperShowCase/showCase.ts b/client/src/constants/CasperShowCase/showCase.ts index 113ef598..212e74cb 100644 --- a/client/src/constants/CasperShowCase/showCase.ts +++ b/client/src/constants/CasperShowCase/showCase.ts @@ -2,7 +2,7 @@ export const CARD_TRANSITION = (itemLength: number) => ({ x: { repeat: Infinity, repeatType: "loop", - duration: itemLength, + duration: itemLength * 2, ease: "linear", }, }); diff --git a/client/src/features/CasperShowCase/CasperCards.tsx b/client/src/features/CasperShowCase/CasperCards.tsx index 38fe15c2..a960cc48 100644 --- a/client/src/features/CasperShowCase/CasperCards.tsx +++ b/client/src/features/CasperShowCase/CasperCards.tsx @@ -8,7 +8,7 @@ interface CasperCardsProps { } export function CasperCards({ cardList }: CasperCardsProps) { - const cardLength = 20; + const cardLength = cardList.length; const cardLengthHalf = Math.floor(cardLength / 2); const visibleCardCount = useMemo(() => { const width = window.innerWidth; @@ -38,7 +38,7 @@ export function CasperCards({ cardList }: CasperCardsProps) { cardList={topCardList} initialX={0} gap={gap} - diffX={-totalWidth - 1} + diffX={-totalWidth} visibleCardCount={visibleCardCount} isEndCard={isEndTopCard} /> @@ -46,7 +46,7 @@ export function CasperCards({ cardList }: CasperCardsProps) { cardList={bottomCardList} initialX={-totalWidth} gap={gap} - diffX={totalWidth + 1} + diffX={totalWidth} visibleCardCount={visibleCardCount} isEndCard={isEndBottomCard} isReverseCards diff --git a/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx b/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx index 8fa9c4df..13eaa09f 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCardItem.tsx @@ -1,7 +1,6 @@ import { useState } from "react"; import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper"; import { CasperFlipCard } from "@/features/CasperCustom/CasperCard/CasperFlipCard"; -import useLazyLoading from "@/hooks/useLazyLoading"; import type { CasperCardType } from "@/types/casper"; interface TransitionCasperCardItemProps { @@ -18,7 +17,6 @@ export function TransitionCasperCardItem({ startAnimation, }: TransitionCasperCardItemProps) { const [isFlipped, setIsFlipped] = useState(false); - const { isInView, cardRef } = useLazyLoading(); const handleMouseEnter = () => { stopAnimation && stopAnimation(); @@ -32,7 +30,6 @@ export function TransitionCasperCardItem({ return (
  • - {isInView && ( - - )} +
  • ); } diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index 2328df31..1ea68c16 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -34,8 +34,8 @@ export function TransitionCasperCards({ const startAnimation = (x: number) => { transitionControls.start({ - x: [x, x + diffX], - transition: CARD_TRANSITION(cardList.length), + x: [x, x + diffX * 2], + transition: CARD_TRANSITION(visibleCardCount * 2), }); }; @@ -81,6 +81,8 @@ export function TransitionCasperCards({ nextIdx = nextIdx % cardList.length; } + console.log(nextIdx); + setVisibleCardListIdx(nextIdx); startAnimation(initialX); } From 77110d87f18a655ae5449ef396a1f8b62b5b1898 Mon Sep 17 00:00:00 2001 From: juhyojeong Date: Sun, 18 Aug 2024 20:25:30 +0900 Subject: [PATCH 13/16] =?UTF-8?q?chore:=20=EC=BD=98=EC=86=94=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/CasperShowCase/TransitionCasperCards.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index 1ea68c16..adfedb65 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -81,8 +81,6 @@ export function TransitionCasperCards({ nextIdx = nextIdx % cardList.length; } - console.log(nextIdx); - setVisibleCardListIdx(nextIdx); startAnimation(initialX); } From 7b3cc4b15fc88256a5e00ceb5eb16d389be30a39 Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Mon, 19 Aug 2024 10:48:43 +0900 Subject: [PATCH 14/16] =?UTF-8?q?refactor:=20tailwind=20=EC=86=8D=EC=84=B1?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/CasperCustom/CasperCard/CasperCardBackUI.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/src/features/CasperCustom/CasperCard/CasperCardBackUI.tsx b/client/src/features/CasperCustom/CasperCard/CasperCardBackUI.tsx index dbd9a3c1..57226aa5 100644 --- a/client/src/features/CasperCustom/CasperCard/CasperCardBackUI.tsx +++ b/client/src/features/CasperCustom/CasperCard/CasperCardBackUI.tsx @@ -165,10 +165,7 @@ export function CasperCardBackUI({ style={{ width: CARD_WIDTH - 100 }} >

    작성한 기대평

    -

    +

    {expectations}

    From d779294a63cd835acb64bb8bb60c1b434310d0ad Mon Sep 17 00:00:00 2001 From: jhj2713 Date: Mon, 19 Aug 2024 10:50:27 +0900 Subject: [PATCH 15/16] =?UTF-8?q?refactor:=20=EC=A1=B0=EA=B1=B4=EB=B6=80?= =?UTF-8?q?=20tailwind=20=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Scroll/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/components/Scroll/index.tsx b/client/src/components/Scroll/index.tsx index 26cb4822..df0cdb71 100644 --- a/client/src/components/Scroll/index.tsx +++ b/client/src/components/Scroll/index.tsx @@ -19,9 +19,8 @@ const scrollTextVariants = cva(`h-body-2-regular`, { export default function Scroll({ type, children, onClick }: ScrollProps) { return (
    {children}
    Date: Mon, 19 Aug 2024 11:03:49 +0900 Subject: [PATCH 16/16] =?UTF-8?q?chore:=20useCallback=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CasperShowCase/TransitionCasperCards.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx index adfedb65..49673914 100644 --- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx +++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { AnimatePresence, type ResolvedValues, motion, useAnimation } from "framer-motion"; import { CARD_TRANSITION } from "@/constants/CasperShowCase/showCase"; import type { CasperCardType } from "@/types/casper"; @@ -32,21 +32,24 @@ export function TransitionCasperCards({ const [x, setX] = useState(initialX); const [visibleCardListIdx, setVisibleCardListIdx] = useState(0); - const startAnimation = (x: number) => { - transitionControls.start({ - x: [x, x + diffX * 2], - transition: CARD_TRANSITION(visibleCardCount * 2), - }); - }; + const startAnimation = useCallback( + (x: number) => { + transitionControls.start({ + x: [x, x + diffX * 2], + transition: CARD_TRANSITION(visibleCardCount * 2), + }); + }, + [visibleCardCount, transitionControls] + ); - const stopAnimation = () => { + const stopAnimation = useCallback(() => { transitionControls.stop(); if (containerRef.current) { const computedStyle = window.getComputedStyle(containerRef.current); const matrix = new DOMMatrix(computedStyle.transform); setX(matrix.m41); } - }; + }, [transitionControls, containerRef]); const visibleCardList = useMemo(() => { const list = expandedCardList.slice(