Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 인터랙션 모달 분기 처리 #83

Merged
merged 8 commits into from
Aug 9, 2024
6 changes: 3 additions & 3 deletions src/interactions/GiftDetail.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import Star from "./star.svg?react";
export default function GiftDetail({ contentList }) {
return (
<div className="flex flex-col font-bold">
<span className="text-body-l text-neutral-50 pb-10">경품 안내</span>
<span className="text-center sm:text-left text-body-l text-neutral-50 pb-10">경품 안내</span>

{contentList.map((content, index) => (
<div key={index} className="bg-neutral-900 p-6 mb-5 flex z-0 relative">
<img src={content.src} alt="경품" />

<div className="pl-8 flex flex-col">
<span className="text-body-l text-white">
<span className="text-body-m sm:text-body-l text-white">
{content.name}
<span className="text-blue-400 pl-2">{content.num}명</span>
</span>

<span className="pt-2 text-body-m text-neutral-400 whitespace-pre-wrap">
<span className="pt-2 text-body-s sm:text-body-m text-neutral-400 whitespace-pre-wrap">
{content.desc}
</span>
</div>
Expand Down
64 changes: 49 additions & 15 deletions src/interactions/InteractionAnswer.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
import userStore from "@/auth/store.js";
import scrollTo from "@/scroll/scrollTo";
import style from "./InteractionAnswer.module.css";
import { useState } from "react";
import { useEffect, useState } from "react";
import openModal from "@/modal/openModal.js";
import AuthModal from "@/auth/AuthModal.jsx";
// import fcfsStore from "@/fcfs/store";

export default function InteractionAnswer({
isAnswerUp,
setIsAnswerUp,
answer,
close,
isLogin,
}) {
const isLogin = userStore((state) => state.isLogin);
// const currentServerTime = fcfsStore((state) => state.currentServerTime);
const [isAniPlaying, setIsAniPlaying] = useState(false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

토스트 관련된 상태와 엘리먼트들은 전부 별개의 컴포넌트로 분리하는 게 좋습니다.

const [isEventToday, setIsEventToday] = useState(false);
const [isJoined, setIsJoined] = useState(false);
const authModal = (
<AuthModal
onComplete={() => {
/*
* 비로그인자가 정보등록을 성공시켰을 때 서버로 추첨이벤트 참여 api를 보내는 코드 미구현
*/
}}
/>
);

useEffect(() => {
/*
* 서버에서 해당 날짜의 사용자 응모 여부와, 시간을 받아온 후 이벤트 날짜와 비교하는 코드 미구현
*/

setIsEventToday(true);
setIsJoined(false);
}, []);

function onClickWrite() {
close();
Expand All @@ -21,8 +44,11 @@ export default function InteractionAnswer({
setIsAniPlaying(true);

/*
* 서버에서 받아온 단축 url을 클립보드에 복사하는 코드 미구현
* 서버에서 단축 url을 받아오는 코드 미구현
*/

const simpleURL = "https://youtu.be/KMU0tzLwhbE";
navigator.clipboard.writeText(simpleURL);
}

return (
Expand All @@ -38,33 +64,38 @@ export default function InteractionAnswer({

<button
onClick={() => setIsAnswerUp(false)}
className="absolute top-10 left-10 p-3 bg-neutral-800 rounded-full"
className="absolute top-5 xl:top-10 left-5 xl:left-10 p-1 xl:p-3 bg-neutral-800 rounded-full"
>
<img src="icons/left-arrow.svg" alt="뒤로가기" />
</button>

<div className="w-1/2 flex gap-8">
<span className="text-head-l text-blue-400 font-bold whitespace-pre">
<div className="w-2/3 xl:w-1/2 flex flex-col xl:flex-row gap-2 xl:gap-8">
<span className="text-head-s xl:text-head-l text-blue-400 font-bold whitespace-pre">
Comment on lines +72 to +73
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반응형 편-안

{answer.head}
</span>

<div className="flex flex-col gap-4">
<span className="text-title-s text-neutral-50">{answer.desc}</span>
<span className="text-body-l xl:text-title-s text-neutral-50">{answer.desc}</span>

<span className="text-body-s text-neutral-300">{answer.subdesc}</span>
<span className="text-detail-l xl:text-body-s text-neutral-300">{answer.subdesc}</span>
</div>
</div>

<div className="absolute bottom-10 flex flex-col items-center gap-10">
{isLogin ? (
<>
<span className="text-body-m text-green-400 font-bold">
오늘 응모가 완료되었습니다!
{isJoined
? "오늘 응모가 완료되었습니다!"
: "응모 기간이 지났습니다!"}
</span>

<div className="flex gap-4 items-end">
<div className="flex flex-col gap-2">
<div className="relative flex flex-col items-center animate-bounce">
<span className=" bg-green-400 text-nowrap text-body-m text-neutral-800 rounded-full px-8 py-2 font-bold">
<div
className={`${isEventToday ? "" : "hidden"} relative flex flex-col items-center animate-bounce`}
>
<span className=" bg-green-400 text-nowrap text-body-s xl:text-body-m text-neutral-800 rounded-full px-4 xl:px-8 py-1 xl:py-2 font-bold">
당첨확률 UP!
</span>

Expand All @@ -73,22 +104,25 @@ export default function InteractionAnswer({

<button
onClick={onClickWrite}
className="bg-white text-body-m text-black px-10 py-4"
className="bg-white text-body-m text-black px-5 xl:px-10 py-2 xl:py-4"
>
기대평 작성하기
</button>
</div>

<button
onClick={onClickShare}
className="border-2 border-neutral-300 text-body-m text-white px-10 py-[14px]"
className="border-2 border-neutral-300 text-body-m text-white px-5 xl:px-10 py-[7px] xl:py-[14px]"
>
공유하기
</button>
</div>
</>
) : (
<button className="text-body-m text-black bg-white px-10 py-4">
<button
onClick={() => openModal(authModal)}
className="text-body-m text-black bg-white px-10 py-4"
>
응모하기
</button>
)}
Expand Down
20 changes: 16 additions & 4 deletions src/interactions/InteractionModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Suspense from "@/common/Suspense.jsx";
import { ModalCloseContext } from "@/modal/modal.jsx";
import { lazy, useContext, useRef, useState } from "react";
import InteractionAnswer from "./InteractionAnswer";
import userStore from "@/auth/store.js";

const lazyInteractionList = [
lazy(() => import("./distanceDriven")),
Expand All @@ -17,15 +18,25 @@ export default function InteractionModal({ index, answer }) {
const [isActive, setIsActive] = useState(false);
const [isAnswerUp, setIsAnswerUp] = useState(false);
const interactionRef = useRef(null);
const isLogin = userStore((state) => state.isLogin);

if (!InteractionComponent) return <></>;

function joinEvent() {
setIsAnswerUp(true);
if (isLogin) {
/*
* 로그인 유저가 서버로 추첨이벤트 참여 api 전송하는 코드 미구현
*/
}
}

return (
<Suspense fallback={<div>Loading...</div>}>
<div className="w-5/6 h-5/6 relative backdrop-blur-[100px] border border-neutral-600 rounded overflow-hidden">
<button
onClick={close}
className="z-10 absolute top-10 right-10 bg-neutral-800 p-3 rounded-full"
className="z-10 absolute top-5 right-5 xl:top-10 xl:right-10 bg-neutral-800 p-1 xl:p-3 rounded-full"
>
<img src="icons/close-white.svg" alt="닫기" />
</button>
Expand All @@ -37,16 +48,16 @@ export default function InteractionModal({ index, answer }) {

<div className="absolute bottom-6 left-1/2 -translate-x-1/2 flex gap-4">
<button
onClick={() => setIsAnswerUp(true)}
onClick={joinEvent}
disabled={!isActive}
className={`${isActive ? "opacity-100" : "opacity-50"} bg-white px-10 py-4 text-black text-body-s`}
className={`${isActive ? "opacity-100" : "opacity-50"} bg-white px-4 py-2 xl:px-10 xl:py-4 text-black text-body-s`}
>
확인하기
</button>

<button
onClick={() => interactionRef.current.reset()}
className="border-2 border-neutral-100 p-2"
className="border-2 border-neutral-100 p-1 xl:p-2"
>
<img src="icons/refresh.svg" alt="다시하기" />
</button>
Expand All @@ -57,6 +68,7 @@ export default function InteractionModal({ index, answer }) {
setIsAnswerUp={setIsAnswerUp}
answer={answer}
close={close}
isLogin={isLogin}
/>
</div>
</Suspense>
Expand Down
16 changes: 8 additions & 8 deletions src/interactions/InteractionSlide.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default function InteractionSlide({
index,
isCurrent,
joined,
swiperRef,
slideTo,
answer,
}) {
const activeImgPath = `active${index + 1}.png`;
Expand Down Expand Up @@ -35,18 +35,18 @@ export default function InteractionSlide({

return (
<div
onClick={() => swiperRef.current.swiper.slideTo(index)}
className="w-full h-full flex flex-col items-center select-none"
onClick={() => slideTo(index)}
className="w-full h-full flex flex-col justify-center items-center select-none"
>
<span className="pt-[150px] text-body-l text-white font-bold">
<span className="sm:pt-10 text-body-m sm:text-body-l text-white font-bold">
{eventDate()}
</span>

<div className="pt-5 flex items-center">
<img src={numberImgPath} />

<span
className={`${isCurrent ? "opacity-100" : "opacity-50"} pl-3 text-head-s text-white font-bold`}
className={`${isCurrent ? "opacity-100" : "opacity-50"} pl-3 text-title-m sm:text-head-s text-white font-bold`}
>
{interactionDesc}
</span>
Expand All @@ -55,9 +55,9 @@ export default function InteractionSlide({
<button
onClick={onClickExperience}
disabled={!isCurrent || joined < 0}
className={`mt-8 py-4 px-10 bg-white ${joined < 0 ? "hidden" : isCurrent ? "opacity-100" : "opacity-50"}`}
className={`mt-8 py-1 sm:py-4 px-5 sm:px-10 bg-white ${joined < 0 ? "hidden" : isCurrent ? "opacity-100" : "opacity-50"}`}
>
<span className="text-body-s text-black font-bold">
<span className="text-detail-l sm:text-body-s text-black font-bold">
인터랙션 체험하기
</span>
</button>
Expand All @@ -76,7 +76,7 @@ export default function InteractionSlide({
<img
src={activeImgPath}
alt="activeImage"
className={`-z-10 absolute transition ease-in-out duration-200 ${isCurrent ? "opacity-100" : "opacity-0"}`}
className={`-z-10 absolute transition ease-in-out duration-200 ${isCurrent ? "opacity-100" : "opacity-30 sm:opacity-0"}`}
/>
</div>
);
Expand Down
16 changes: 8 additions & 8 deletions src/interactions/IntroductionDetail.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
export default function IntroductionDetail({ contentList }) {
return (
<div className="flex flex-col">
<span className="text-body-l pb-10 text-neutral-50 font-bold">
<span className="text-center sm:text-left text-body-l pb-10 text-neutral-50 font-bold">
상세 안내
</span>

<div className="flex gap-5">
<div className="flex gap-5 justify-center">
<div className="bg-neutral-900 p-6 flex flex-col font-bold">
<span className="text-body-m text-neutral-300">이벤트 기간</span>

<span className="pt-6 text-body-m text-blue-100">2024년</span>
<span className="pt-6 text-body-s sm:text-body-m text-blue-100">2024년</span>

<span className="text-body-l text-blue-400">
<span className="text-nowrap text-body-m sm:text-body-l text-blue-400">
09월09일(월)~13일(금)
</span>
</div>
Expand All @@ -21,12 +21,12 @@ export default function IntroductionDetail({ contentList }) {
당첨자 발표
</span>

<span className="pt-6 text-body-l text-white font-bold">
<span className="pt-6 text-body-m sm:text-body-l text-white font-bold">
2024년 9월 말
<span className="font-normal text-neutral-300">{` (예정)`}</span>
</span>

<span className="pt-2 text-body-s text-neutral-300">
<span className="pt-2 text-detail-l sm:text-body-s text-neutral-300">
* 추후 응모 시 입력한 연락처로 개별 안내
</span>
</div>
Expand All @@ -37,14 +37,14 @@ export default function IntroductionDetail({ contentList }) {

{contentList.map((contentSubList, index) => (
<div key={index} className="mt-[9px]">
<span className="bg-neutral-100 text-neutral-900 text-body-s px-2 py-0.5 rounded-[4px] mr-4">
<span className="bg-neutral-100 text-neutral-900 text-detail-l sm:text-body-s px-2 py-0.5 rounded-[4px] mr-4">
{index + 1}
</span>

{contentSubList.map((content, index) => (
<span
key={index}
className={`${index % 2 ? "text-neutral-400" : "text-white"} text-body-m`}
className={`${index % 2 ? "text-neutral-400" : "text-white"} text-body-s sm:text-body-m`}
>
{content}
</span>
Expand Down
4 changes: 2 additions & 2 deletions src/interactions/TapBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ export default function TapBar({ currentInteraction, joinedList, swiperRef }) {
EVENT 1
</span>

<span className="pt-9 text-head-m text-white font-bold">
<span className="pt-9 text-title-l sm:text-head-m text-white font-bold text-center">
The 새로워진 IONIQ 5, 인터랙션으로 만나다
</span>

<span className="pt-4 text-title-s text-neutral-300 whitespace-pre-wrap text-center">
<span className="pt-4 text-body-m sm:text-title-s text-neutral-300 whitespace-pre-wrap text-center">
{`The new IONIQ 5의 새로운 기능을 날마다 체험하고 이벤트에 응모하세요!\n추첨을 통해 IONIQ과 함께하는 제주 여행 패키지를 드립니다`}
</span>

Expand Down
8 changes: 4 additions & 4 deletions src/interactions/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function InteractionPage() {
return (
<section
ref={sectionRef}
className="bg-black py-60 flex flex-col items-center"
className="bg-black py-20 sm:py-60 flex flex-col items-center"
>
<TapBar
currentInteraction={currentInteraction}
Expand All @@ -35,20 +35,20 @@ export default function InteractionPage() {
ref={swiperRef}
>
{JSONData.interaction.map((interactionDesc, index) => (
<swiper-slide key={index} class="w-[566px] h-[456px]">
<swiper-slide key={index} class="w-5/6 sm:w-[566px] h-[456px]">
<InteractionSlide
interactionDesc={interactionDesc}
index={index}
isCurrent={currentInteraction === index}
joined={joinedList[index]}
swiperRef={swiperRef}
slideTo={(_index) => swiperRef.current.swiper.slideTo(_index)}
answer={JSONData.answer[index]}
/>
</swiper-slide>
))}
</swiper-container>

<div className="pt-32 flex flex-col xl:flex-row gap-[140px]">
<div className="pt-10 sm:pt-32 flex flex-col xl:flex-row gap-16 sm:gap-[140px]">
<IntroductionDetail contentList={JSONData.howto} />
<GiftDetail contentList={JSONData.gift} />
</div>
Expand Down
Loading