Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/components/Combination/CombinationDeviceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const CombinationDeviceCard = ({
<div className="flex flex-col gap-8">
<div className="flex items-center gap-8">
<p className="font-body-1-sm text-black">{combination.comboName}</p>
{combination.isPinned && <StarIcon className="w-22 h-22" />}
{combination.isPinned && <StarIcon className="w-22 h-22 -mt-2" />}
</div>
</div>
{/* Tags */}
Expand Down
62 changes: 50 additions & 12 deletions src/pages/devices/DeviceSearchPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState, useEffect, useRef } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useSearchParams, useNavigate } from 'react-router-dom';
import GNB from '@/components/Home/GNB';
import ProductCard from '@/components/ProductCard/ProductCard';
import PrimaryButton from '@/components/Button/PrimaryButton';
Expand All @@ -24,17 +24,28 @@ import {
SCROLL_CONSTANTS,
} from '@/constants/devices';
import { MOCK_PRODUCTS } from '@/constants/mockData';
import { type AuthStatus, type ModalView } from '@/types/devices';
import { ROUTES } from '@/constants/routes';
import { type ModalView } from '@/types/devices';
import { useGetCombos } from '@/apis/combo/getCombos';
import { useGetCombo } from '@/apis/combo/getComboId';
import { usePostComboDevice } from '@/apis/combo/postComboDevices';
import { useGetUserProfile } from '@/apis/mypage/getUserProfile';
import { hasAuthTokens, hasCompletedOnboarding } from '@/utils/auth/authStorage';

const DeviceSearchPage = () => {
const [searchParams, setSearchParams] = useSearchParams();
const selectedProductId = searchParams.get('productId');
const navigate = useNavigate();

// 로그인 상태 확인
const isLoggedIn = hasAuthTokens();

// 사용자 프로필 조회 (로그인 시에만 자동 실행)
const { data: userProfile, isLoading: isProfileLoading } = useGetUserProfile();

// 온보딩 완료 여부 확인 (로딩 중에는 false로 기본 처리)
const hasOnboarding = isProfileLoading ? false : hasCompletedOnboarding(userProfile);

// 추후 Zustand/Context에서 인증 상태 가져오기
const [authStatus] = useState<AuthStatus>('login'); // 테스트로 login으로 변경. 추후 logout으로 변경.
const [modalView, setModalView] = useState<ModalView>('device');

// API hooks
Expand Down Expand Up @@ -79,11 +90,6 @@ const DeviceSearchPage = () => {

/* 내 조합에 담기 */
const handleAddToCombination = () => {
if (authStatus === 'logout') {
// 로그인 페이지로 이동
return;
}

// 조합이 1개면 바로 저장
if (combos.length === 1 && selectedProductId) {
addDeviceToCombo(
Expand All @@ -110,6 +116,37 @@ const DeviceSearchPage = () => {
setModalView('combination');
};

/* 버튼 텍스트 및 핸들러 결정 */
const getAddToCombinationConfig = () => {
// Case 1: 로그아웃 상태
if (!isLoggedIn) {
return {
text: '로그인하고 내 조합에 담기',
handler: () => {
navigate(ROUTES.auth.login);
},
};
}

// Case 2: 로그인했지만 온보딩 미완료
if (!hasOnboarding) {
return {
text: '맞춤 설정하고 담기',
handler: () => {
navigate(ROUTES.auth.onboarding.lifestyle);
},
};
}

// Case 3: 로그인 + 온보딩 완료
return {
text: '내 조합에 담기',
handler: handleAddToCombination,
};
};

const addToCombinationConfig = getAddToCombinationConfig();

/* 조합 선택 - 기기 리스트 보기 */
const handleSelectCombination = (combinationId: number) => {
setSelectedCombinationId(combinationId);
Expand Down Expand Up @@ -400,8 +437,9 @@ const DeviceSearchPage = () => {

{/* Button */}
<PrimaryButton
text={authStatus === 'logout' ? '로그인하고 내 조합에 담기' : '내 조합에 담기'}
onClick={handleAddToCombination}
text={addToCombinationConfig.text}
onClick={addToCombinationConfig.handler}
disabled={isProfileLoading}
className="w-full bg-blue-500 hover:bg-blue-400 transition-colors"
/>
</div>
Expand Down Expand Up @@ -499,7 +537,7 @@ const DeviceSearchPage = () => {
{/* 조합명 + 대표조합 star */}
<div className="flex items-center gap-8">
<p className="font-body-1-sm text-black">{combo.comboName}</p>
{combo.isPinned && <StarIcon className="w-22 h-22" />}
{combo.isPinned && <StarIcon className="w-22 h-22 -mt-2" />}
</div>
</div>
{/* 기기 수 + 총 가격 */}
Expand Down
9 changes: 9 additions & 0 deletions src/utils/auth/authStorage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ACCESS_TOKEN, REFRESH_TOKEN} from '@/constants/tokenKey';
import type { UserProfileResult } from '@/types/mypage/user';

// localStorage를 조작하는 유틸리티 함수
// 나머지 파일에서는 localStorage를 직접 사용하지 않고 이 파일의 함수를 사용하도록 함
Expand Down Expand Up @@ -37,3 +38,11 @@ export const hasAuthTokens = (): boolean => {
const refreshToken = getRefreshToken();
return !!(accessToken && refreshToken);
};

// 온보딩 완료 여부 확인
// lifestyleList가 비어있지 않으면 온보딩 완료로 판단
export const hasCompletedOnboarding = (
userProfile: UserProfileResult | undefined
): boolean => {
return !!(userProfile?.lifestyleList && userProfile.lifestyleList.length > 0);
};