diff --git a/client/src/App.tsx b/client/src/App.tsx index 76209b7..a24b381 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -5,7 +5,6 @@ import { Route, Routes, } from 'react-router-dom'; -import ChatTestPage from './pages/ChatTestPage'; import ChatbotPage from './pages/ChatbotPage'; import TestFirstPage from './pages/TestFirstPage'; import TestWaitingPage from './pages/TestWaitingPage'; @@ -13,20 +12,15 @@ import TestPage from './pages/TestPage'; import ComparePage from './pages/ComparePage'; import TestResultPage from './pages/TestResultPage'; import MainPage from './pages/MainPage'; -import Footer from './components/common/Footer'; import ServiceGuidePage from './pages/ServiceGuidePage'; const MainLayout = () => { return ( <>
-
+
-
); @@ -45,7 +39,6 @@ function App() { } /> } /> } /> - } /> } /> diff --git a/client/src/components/ComparePage/ComparisonActionButtons.tsx b/client/src/components/ComparePage/ComparisonActionButtons.tsx index fc82e96..133ad37 100644 --- a/client/src/components/ComparePage/ComparisonActionButtons.tsx +++ b/client/src/components/ComparePage/ComparisonActionButtons.tsx @@ -5,6 +5,7 @@ interface ComparisonActionButtonsProps { rightButtonText?: string; onLeftClick: () => void; onRightClick: () => void; + className?: string; } const ComparisonActionButtons: React.FC = ({ @@ -12,10 +13,11 @@ const ComparisonActionButtons: React.FC = ({ rightButtonText, onLeftClick, onRightClick, + className = '', }) => { return (
diff --git a/client/src/components/ComparePage/ComparisonResult.tsx b/client/src/components/ComparePage/ComparisonResult.tsx index 31d7ff8..72bb680 100644 --- a/client/src/components/ComparePage/ComparisonResult.tsx +++ b/client/src/components/ComparePage/ComparisonResult.tsx @@ -1,3 +1,4 @@ +import { useEffect, useState } from 'react'; import togetherIcon from '@/assets/image/card_family.png'; import premiumAddonsIcon from '@/assets/icon/special.png'; import mediaAddonsIcon from '@/assets/icon/media.png'; @@ -5,6 +6,9 @@ import BenefitText from '@/components/common/BenefitText'; import DataComparisonBar from '@/components/ComparePage/DataComparisonBar'; import BenefitComparisonRow from '@/components/ComparePage/BenefitComparisonRow'; import ComparisonActionButtons from '@/components/ComparePage/ComparisonActionButtons'; +import Modal from '../common/Modal'; +import Button from '../common/Button'; + import type { Plan } from '@/components/types/Plan'; interface ComparisonResultProps { @@ -16,11 +20,35 @@ const ComparisonResult: React.FC = ({ selectedLeft, selectedRight, }) => { + const [isModalOpen, setIsModalOpen] = useState(false); + const [pendingLink, setPendingLink] = useState(null); + const [showButtons, setShowButtons] = useState(false); + const handleDetailClick = (detailUrl?: string) => { if (detailUrl) { - window.open(detailUrl, '_blank'); + setPendingLink(detailUrl); // 링크만 저장 + setIsModalOpen(true); // 모달 먼저 띄우기 } }; + useEffect(() => { + const scrollContainer = document.querySelector('.scroll-target'); + if (!scrollContainer) return; + + const handleScroll = () => { + const scrollTop = scrollContainer.scrollTop; + const containerHeight = scrollContainer.clientHeight; + const scrollHeight = scrollContainer.scrollHeight; + + if (scrollTop + containerHeight >= scrollHeight - 100) { + setShowButtons(true); + } else { + setShowButtons(false); + } + }; + + scrollContainer.addEventListener('scroll', handleScroll); + return () => scrollContainer.removeEventListener('scroll', handleScroll); + }, []); // 데이터 값 계산 const leftDataValue = selectedLeft @@ -151,13 +179,47 @@ const ComparisonResult: React.FC = ({ />
- handleDetailClick(selectedLeft?.detailUrl)} onRightClick={() => handleDetailClick(selectedRight?.detailUrl)} + className={`fixed bottom-[50px] max-w-[560px] transition-all duration-500 + ${showButtons ? 'opacity-100 translate-y-0 pointer-events-auto' : 'opacity-0 translate-y-5 pointer-events-none'} + `} /> + + setIsModalOpen(false)} + modalTitle="요금제 자세히 알아보기" + modalDesc={ + <> + 요금제 상세 페이지는 외부 사이트로 연결됩니다. +
+ 계속 진행하시겠습니까? + + } + > + + +
); }; diff --git a/client/src/components/ComparePage/FilterSection.tsx b/client/src/components/ComparePage/FilterSection.tsx index 0945a92..03ebabc 100644 --- a/client/src/components/ComparePage/FilterSection.tsx +++ b/client/src/components/ComparePage/FilterSection.tsx @@ -3,19 +3,25 @@ import Carousel from '@/components/ComparePage/Carousel'; interface FilterSectionProps { dataList: string[]; priceList: string[]; + dataAmountList: string[]; activeDataIndex: number; activePriceIndex: number; + activeDataAmountIndex: number; onDataIndexChange: (index: number) => void; onPriceIndexChange: (index: number) => void; + onDataAmountIndexChange: (index: number) => void; } const FilterSection: React.FC = ({ dataList, priceList, + dataAmountList, activeDataIndex, activePriceIndex, + activeDataAmountIndex, onDataIndexChange, onPriceIndexChange, + onDataAmountIndexChange, }) => { return (
@@ -36,6 +42,11 @@ const FilterSection: React.FC = ({ activeIndex={activePriceIndex} setActiveIndex={onPriceIndexChange} /> +
); diff --git a/client/src/components/ComparePage/PlanListItem.tsx b/client/src/components/ComparePage/PlanListItem.tsx index 4f1367b..0d9845d 100644 --- a/client/src/components/ComparePage/PlanListItem.tsx +++ b/client/src/components/ComparePage/PlanListItem.tsx @@ -2,6 +2,7 @@ import { AnimatePresence, motion } from 'framer-motion'; import dropdownIcon from '@/assets/icon/dropdown_icon.svg'; import PlanDetailInfo from '@/components/ComparePage/PlanDetailInfo'; import type { Plan } from '@/components/types/Plan'; +import { useEffect, useRef, useState } from 'react'; interface PlanListItemProps { plan: Plan; @@ -18,8 +19,22 @@ const PlanListItem: React.FC = ({ onToggle, onSelect, }) => { + const itemRef = useRef(null); + const [wasOpen, setWasOpen] = useState(false); + + useEffect(() => { + if (isOpen && !wasOpen && itemRef.current) { + setTimeout(() => { + itemRef.current?.scrollIntoView({ + behavior: 'smooth', + block: 'center', + }); + }, 0); + } + setWasOpen(isOpen); + }, [isOpen]); return ( -
+
) : null; case 'showPlanLists': - return args?.plans ? ( + return args?.plans && args.plans.length > 0 ? (
{args.plans.map((plan, index) => ( ))}
- ) : null; + ) : ( + <> + + + ); case 'showFirstCardList': return ; default: diff --git a/client/src/components/common/Footer.tsx b/client/src/components/common/Footer.tsx index 8bd6131..821274b 100644 --- a/client/src/components/common/Footer.tsx +++ b/client/src/components/common/Footer.tsx @@ -1,6 +1,6 @@ const Footer = () => { return ( -