Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ea926e2
style: 반응형 추가하여 자연스레 정렬되도록 추가
hyonun321 Jun 25, 2025
e2f4d99
style: 반응형 추가하여 h높이 지정
hyonun321 Jun 25, 2025
a51e5f7
Merge branch 'dev' of https://github.com/yeji424/me-plus into Style/메…
hyonun321 Jun 25, 2025
4da76a7
Merge pull request #104 from yeji424/Style/메인페이지-스타일-조정
hyonun321 Jun 25, 2025
e14ca97
Feat: 전체 높이 h-[100vh] 에서 [100dvh]로 변경
yeji424 Jun 26, 2025
5aa30f3
Feat: 바텀시트 플랜 리스트 토글오픈 시 자동 스크롤
yeji424 Jun 26, 2025
7e58ee0
Merge branch 'dev' of https://github.com/yeji424/me-plus into Feat/애니…
yeji424 Jun 26, 2025
c8058a1
Feat : 요금제자세히보기 모달추가
chemnida Jun 26, 2025
ef42ebb
Feat : 요금제자세히보기 모달추가
chemnida Jun 26, 2025
13794c4
Feat:요금제 정렬 필터 추가
leeemingyu Jun 26, 2025
2ac1517
Feat: 레이아웃 수정 과정
yeji424 Jun 26, 2025
ac3e623
Merge branch 'dev' of https://github.com/yeji424/me-plus into Feat/애니…
yeji424 Jun 26, 2025
00357a2
Merge pull request #106 from yeji424/Feat/요금제정렬필터추가
leeemingyu Jun 26, 2025
87d190f
Feat: 레이아웃 수정 과정 (진행중)
yeji424 Jun 26, 2025
d8cf2d0
Design: 페이지네이션 위치 수정
leeemingyu Jun 26, 2025
c675a5b
Merge pull request #108 from yeji424/Design/서비스가이드-UI-수정
leeemingyu Jun 26, 2025
d151343
chore: 불필요한 주석및 코드 삭제
hyonun321 Jun 26, 2025
8a1ad5d
Merge branch 'dev' of https://github.com/yeji424/me-plus into dev
hyonun321 Jun 26, 2025
49b00fe
Feat: 팻봇 페이지 전화연결 구현
yeji424 Jun 26, 2025
d0f281d
Feat : 메인돌아가기 버튼 클릭시 0.3초 후 이동
chemnida Jun 26, 2025
36d3e23
style: compare 페이지 내부요소에 드래그 되도록 수정
hyonun321 Jun 26, 2025
6bd7684
Merge pull request #110 from yeji424/Style/비교페이지-내부요소-스크롤-추가
hyonun321 Jun 26, 2025
be29c33
Feat : 모달 title 변경
chemnida Jun 26, 2025
4624e0a
Feat : 모달 title 변경
chemnida Jun 26, 2025
aec7ad8
Feat : 메인돌아가기 버튼 클릭시 0.3초 후 이동
chemnida Jun 26, 2025
ed6a3a5
Feat: 비교페이지 버튼 위치 수정
yeji424 Jun 26, 2025
904ea85
Feat: 팻봇 페이지 전화연결 구현
yeji424 Jun 26, 2025
d11cdd5
Design: 배경색 변경
leeemingyu Jun 26, 2025
06ddd80
Merge branch 'dev' into Design/서비스가이드-UI-수정
leeemingyu Jun 26, 2025
e593a30
Merge pull request #112 from yeji424/Design/서비스가이드-UI-수정
leeemingyu Jun 26, 2025
3b92e17
Merge branch 'dev' of https://github.com/yeji424/me-plus into Feat/애니…
yeji424 Jun 26, 2025
88f69dd
Fix: 메인, 테스트, 테스트 결과 페이지 스크롤 이슈 해결
yeji424 Jun 26, 2025
76eddb3
Fix: 비교 페이지 레이아웃 수정 후 버튼 안보임 이슈 해결
yeji424 Jun 26, 2025
a3844da
Merge branch 'dev' of https://github.com/yeji424/me-plus into Feat/애니…
yeji424 Jun 26, 2025
f098933
Merge branch 'dev' of https://github.com/yeji424/me-plus into Feat/애니…
yeji424 Jun 26, 2025
6e90751
Fix: Build 에러 수정
yeji424 Jun 26, 2025
95c5e63
Feat: 레이아웃 및 UX 문제 해결
yeji424 Jun 26, 2025
9222a0b
feat: 백엔드 응답 고도화
hyonun321 Jun 26, 2025
696a703
Merge pull request #114 from yeji424/Fix/백엔드-응답-올바르게
hyonun321 Jun 26, 2025
2bb2b28
fix: 토큰카운트 새채팅때 초기화 되고 누적되도록 수정
hyonun321 Jun 26, 2025
1970bf5
Merge pull request #115 from yeji424/Fix/토큰-role-에러-수정
hyonun321 Jun 26, 2025
0f99d28
Design: 푸터 삭제
leeemingyu Jun 26, 2025
d8c9b86
Design: 헤더가 모달 위로 올라오는 문제 해결
leeemingyu Jun 26, 2025
f3ebb9d
Merge pull request #117 from yeji424/Design-레이아웃-수정
leeemingyu Jun 26, 2025
f4382c9
feat: 100자 입력제한 추가
hyonun321 Jun 26, 2025
56b9b54
Merge pull request #118 from yeji424/Feat/input-100자-입력제한
hyonun321 Jun 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,22 @@ 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';
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 (
<>
<div className=" min-h-screen flex flex-col">
<main
className="flex-1"
style={{ minHeight: 'calc(100vh - 50px - 80px)' }}
>
<main style={{ minHeight: 'calc(100vh - 50px - 80px)' }}>
<Outlet />
</main>
<Footer />
</div>
</>
);
Expand All @@ -45,7 +39,6 @@ function App() {
<Route path="test-result" element={<TestResultPage />} />
<Route path="compare" element={<ComparePage />} />
<Route path="service-guide" element={<ServiceGuidePage />} />
<Route path="/chat-test" element={<ChatTestPage />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Route>
</Routes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ interface ComparisonActionButtonsProps {
rightButtonText?: string;
onLeftClick: () => void;
onRightClick: () => void;
className?: string;
}

const ComparisonActionButtons: React.FC<ComparisonActionButtonsProps> = ({
leftButtonText,
rightButtonText,
onLeftClick,
onRightClick,
className = '',
}) => {
return (
<div
className="flex flex-col justify-center items-center text-center gap-6 fixed bottom-[50px] max-w-[560px]"
className={`flex flex-col justify-center items-center text-center gap-6 ${className}`}
style={{ width: 'calc(100% - 40px)' }}
>
<div className="flex w-full">
Expand Down
66 changes: 64 additions & 2 deletions client/src/components/ComparePage/ComparisonResult.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
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';
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 {
Expand All @@ -16,11 +20,35 @@ const ComparisonResult: React.FC<ComparisonResultProps> = ({
selectedLeft,
selectedRight,
}) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [pendingLink, setPendingLink] = useState<string | null>(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
Expand Down Expand Up @@ -151,13 +179,47 @@ const ComparisonResult: React.FC<ComparisonResultProps> = ({
/>
</div>
</div>

<ComparisonActionButtons
leftButtonText={selectedLeft ? '자세히 보기' : ''}
rightButtonText={selectedRight ? '자세히 보기' : ''}
onLeftClick={() => 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'}
`}
/>

<Modal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
modalTitle="요금제 자세히 알아보기"
modalDesc={
<>
요금제 상세 페이지는 외부 사이트로 연결됩니다.
<br />
계속 진행하시겠습니까?
</>
}
>
<Button
fullWidth
variant="secondary"
size="medium"
onClick={() => setIsModalOpen(false)}
>
닫기
</Button>
<Button
fullWidth
size="medium"
onClick={() => {
if (pendingLink) window.open(pendingLink, '_blank');
setIsModalOpen(false);
}}
>
이동하기
</Button>
</Modal>
</>
);
};
Expand Down
11 changes: 11 additions & 0 deletions client/src/components/ComparePage/FilterSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<FilterSectionProps> = ({
dataList,
priceList,
dataAmountList,
activeDataIndex,
activePriceIndex,
activeDataAmountIndex,
onDataIndexChange,
onPriceIndexChange,
onDataAmountIndexChange,
}) => {
return (
<div className="fixed top-[45px] w-full pt-2 bg-background-40 z-5">
Expand All @@ -36,6 +42,11 @@ const FilterSection: React.FC<FilterSectionProps> = ({
activeIndex={activePriceIndex}
setActiveIndex={onPriceIndexChange}
/>
<Carousel
categoryList={dataAmountList}
activeIndex={activeDataAmountIndex}
setActiveIndex={onDataAmountIndexChange}
/>
</div>
</div>
);
Expand Down
17 changes: 16 additions & 1 deletion client/src/components/ComparePage/PlanListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
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;
Expand All @@ -18,8 +19,22 @@
onToggle,
onSelect,
}) => {
const itemRef = useRef<HTMLDivElement>(null);
const [wasOpen, setWasOpen] = useState(false);

useEffect(() => {
if (isOpen && !wasOpen && itemRef.current) {
setTimeout(() => {
itemRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
}, 0);
}
setWasOpen(isOpen);
}, [isOpen]);

Check warning on line 35 in client/src/components/ComparePage/PlanListItem.tsx

View workflow job for this annotation

GitHub Actions / Lint and Build Checks ✅

React Hook useEffect has a missing dependency: 'wasOpen'. Either include it or remove the dependency array
return (
<div>
<div ref={itemRef}>
<motion.div
whileHover={
!isOpen
Expand Down
8 changes: 6 additions & 2 deletions client/src/components/chatbot/BotBubbleFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ const BotBubbleFrame = ({
/>
) : null;
case 'showPlanLists':
return args?.plans ? (
return args?.plans && args.plans.length > 0 ? (
<div className="space-y-3">
{args.plans.map((plan, index) => (
<ToggleCard
Expand All @@ -179,7 +179,11 @@ const BotBubbleFrame = ({
/>
))}
</div>
) : null;
) : (
<>
<BotBubble messageChunks={['해당하는 요금제가 없습니다.']} />
</>
);
case 'showFirstCardList':
return <FirstCardList onButtonClick={onButtonClick} />;
default:
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/common/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Footer = () => {
return (
<footer className="w-full max-w-[600px] mx-auto px-5 py-1 flex justify-center items-center text-xs text-[rgba(87,50,161,0.8)] text-center">
<footer className="absolute bottom-0 w-full max-w-[600px] mx-auto px-5 py-1 flex justify-center items-center text-xs text-[rgba(87,50,161,0.8)] text-center">
<p>@meplus.com</p>
</footer>
);
Expand Down
16 changes: 8 additions & 8 deletions client/src/components/common/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ interface ModalProps {
isOpen: boolean;
onClose: () => void;
modalTitle: string;
modalDesc?: string;
modalDesc?: React.ReactNode;
children: React.ReactNode;
}

Expand All @@ -17,11 +17,11 @@ const Modal: React.FC<ModalProps> = ({
children,
}) => {
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'hidden';
}
// if (isOpen) {
// document.body.style.overflow = 'hidden';
// } else {
// document.body.style.overflow = 'hidden';
// }

const handleEsc = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
Expand All @@ -32,7 +32,7 @@ const Modal: React.FC<ModalProps> = ({
window.addEventListener('keydown', handleEsc);
return () => {
window.removeEventListener('keydown', handleEsc);
document.body.style.overflow = 'hidden';
// document.body.style.overflow = 'hidden';
};
}, [isOpen, onClose]);

Expand All @@ -41,7 +41,7 @@ const Modal: React.FC<ModalProps> = ({
{isOpen && (
<motion.div
key="backdrop"
className="fixed left-1/2 top-0 bottom-0 -translate-x-1/2 w-full max-w-[600px] bg-black/50 flex justify-center items-center z-50"
className="fixed left-1/2 top-0 bottom-0 -translate-x-1/2 w-full max-w-[600px] bg-black/50 flex justify-center items-center z-100"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
Expand Down
86 changes: 86 additions & 0 deletions client/src/components/common/ToastAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';

interface ToastAlertProps {
message: string;
onClose?: () => void;
}

function ToastAlert({ message, onClose }: ToastAlertProps) {
const [visible, setVisible] = useState(true);
const [isClosing, setIsClosing] = useState(false);

useEffect(() => {
const timer = setTimeout(() => {
setIsClosing(true);
}, 2500);

return () => clearTimeout(timer);
}, []);

const handleAnimationEnd = () => {
if (isClosing) {
setVisible(false);
if (onClose) onClose();
}
};

if (!visible) return null;

return createPortal(
<div
style={{
position: 'fixed',
top: '15px',
left: '50%',
transform: 'translateX(-50%)',
width: 'calc(100% - 20px)',
maxWidth: '560px',
padding: '16px 20px',
backgroundColor: 'rgba(255, 255, 255, 1)',
borderRadius: '12px',
boxShadow: '0 0 10px rgba(0, 0, 0, 0.08)',
fontSize: '14px',
lineHeight: '19px',
textAlign: 'center',
color: '#6B7280',
zIndex: 9999,
animation: isClosing
? 'slideUp 0.3s ease forwards'
: 'slideDown 0.3s ease forwards',
whiteSpace: 'pre-line',
}}
onAnimationEnd={handleAnimationEnd}
>
{message}
<style>
{`
@keyframes slideDown {
from {
opacity: 0.7;
transform: translate(-50%, -20px);
}
to {
opacity: 1;
transform: translate(-50%, 0);
}
}

@keyframes slideUp {
from {
opacity: 1;
transform: translate(-50%, 0);
}
to {
opacity: 0;
transform: translate(-50%, -20px);
}
}
`}
</style>
</div>,
document.body,
);
}

export default ToastAlert;
2 changes: 1 addition & 1 deletion client/src/components/types/Plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export interface Plan {
name: string;
description?: string;
isPopular: boolean;
dataGb?: number;
dataGb: number;
sharedDataGb?: number;
voiceMinutes?: number;
addonVoiceMinutes?: number;
Expand Down
Loading