diff --git a/app/main/_components/ProfileCard.tsx b/app/main/_components/ProfileCard.tsx index 923c1da..4dd4973 100644 --- a/app/main/_components/ProfileCard.tsx +++ b/app/main/_components/ProfileCard.tsx @@ -200,16 +200,21 @@ const SocialIdDisplay = ({ profile }: { profile: ProfileData }) => { /* ── 메인 프로필 카드 컴포넌트 ── */ interface ProfileCardProps { profile: ProfileData; + isExpanded: boolean; + onToggleExpanded: () => void; } -const ProfileCard = ({ profile }: ProfileCardProps) => { - const [isExpanded, setIsExpanded] = React.useState(false); +const ProfileCard = ({ + profile, + isExpanded, + onToggleExpanded, +}: ProfileCardProps) => { const touchStartTime = useRef(0); const handleCardClick = () => { const touchDuration = Date.now() - touchStartTime.current; if (touchDuration < 200) { - setIsExpanded(!isExpanded); + onToggleExpanded(); } }; @@ -227,7 +232,7 @@ const ProfileCard = ({ profile }: ProfileCardProps) => { onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); - setIsExpanded(!isExpanded); + onToggleExpanded(); } }} className="flex w-full cursor-pointer flex-col items-center justify-start gap-3 p-4" diff --git a/app/main/_components/ProfileSlider.tsx b/app/main/_components/ProfileSlider.tsx index 19592d1..00b7acc 100644 --- a/app/main/_components/ProfileSlider.tsx +++ b/app/main/_components/ProfileSlider.tsx @@ -1,7 +1,7 @@ "use client"; import { ProfileData } from "@/lib/types/profile"; -import React, { useEffect, useRef, useState } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; import ProfileCard from "./ProfileCard"; /* ── 프로필 슬라이더 (스와이프 + 인디케이터) ── */ @@ -9,22 +9,34 @@ interface ProfileSliderProps { profiles: ProfileData[]; } +const PEEK_WIDTH = 16; // 다음 카드가 살짝 보이는 너비 (px) +const CARD_GAP = 8; // 카드 사이 간격 (px) + const ProfileSlider = ({ profiles }: ProfileSliderProps) => { const [activeIndex, setActiveIndex] = useState(0); + const [expandedCardId, setExpandedCardId] = useState(null); const scrollRef = useRef(null); + const toggleExpanded = useCallback((id: number) => { + setExpandedCardId((prev) => (prev === id ? null : id)); + }, []); + useEffect(() => { const el = scrollRef.current; if (!el) return; const handleScroll = () => { - const index = Math.round(el.scrollLeft / el.clientWidth); + const cardWidth = + profiles.length > 1 + ? el.clientWidth - PEEK_WIDTH + CARD_GAP + : el.clientWidth; + const index = Math.round(el.scrollLeft / cardWidth); setActiveIndex(index); }; el.addEventListener("scroll", handleScroll); return () => el.removeEventListener("scroll", handleScroll); - }, []); + }, [profiles.length]); if (!profiles || profiles.length === 0) return null; @@ -34,10 +46,23 @@ const ProfileSlider = ({ profiles }: ProfileSliderProps) => {
- {profiles.map((profile) => ( -
- + {profiles.map((profile, i) => ( +
1 ? PEEK_WIDTH + CARD_GAP : 0}px)`, + marginRight: + i === profiles.length - 1 ? `${PEEK_WIDTH}px` : undefined, + }} + > + toggleExpanded(profile.memberId)} + />
))}
diff --git a/app/main/_components/ScreenMainPage.tsx b/app/main/_components/ScreenMainPage.tsx index f5a21fb..eb531d7 100644 --- a/app/main/_components/ScreenMainPage.tsx +++ b/app/main/_components/ScreenMainPage.tsx @@ -50,7 +50,11 @@ const ScreenMainPage = () => { major: "정보통신전자공학부", mbti: "ENTP", contactFrequency: "NORMAL", - hobbies: [{ name: "🎸 인디음악", category: "음악" }], + hobbies: [ + { name: "🎸 인디음악", category: "음악" }, + { name: "📸 사진찍기", category: "문화" }, + ], + advantages: ["친절함", "경청하는 태도"], profileImageUrl: "/main/cat.png", socialAccountId: "winterizcoming_", }, @@ -61,7 +65,12 @@ const ScreenMainPage = () => { major: "컴퓨터정보공학부", mbti: "INFJ", contactFrequency: "FREQUENT", - hobbies: [{ name: "🎬 영화감상", category: "문화" }], + hobbies: [ + { name: "🎬 영화감상", category: "문화" }, + { name: "📖 독서", category: "문화" }, + { name: "🏊 수영", category: "스포츠" }, + ], + advantages: ["긍정적인 에너지", "솔직함", "유머러스함"], profileImageUrl: "/main/dog.png", socialType: "INSTAGRAM", socialAccountId: "comatching_king", @@ -73,7 +82,12 @@ const ScreenMainPage = () => { major: "경영학과", mbti: "ENFP", contactFrequency: "NORMAL", - hobbies: [{ name: "☕ 카페투어", category: "일상" }], + hobbies: [ + { name: "☕ 카페투어", category: "일상" }, + { name: "🍳 요리", category: "문화" }, + { name: "🍰 베이킹", category: "문화" }, + ], + advantages: ["공감 능력이 좋음"], profileImageUrl: "/main/cat.png", socialType: "KAKAO", socialAccountId: "kakao_kim", @@ -85,7 +99,11 @@ const ScreenMainPage = () => { major: "산업디자인학과", mbti: "ISFP", contactFrequency: "RARE", - hobbies: [{ name: "🎨 그림그리기", category: "예술" }], + hobbies: [ + { name: "🎨 그림그리기", category: "예술" }, + { name: "🧶 뜨개질", category: "예술" }, + ], + advantages: ["꼼꼼함", "배려심", "예술적 감각", "성실함"], profileImageUrl: "/main/cat.png", socialAccountId: "", }, @@ -96,7 +114,12 @@ const ScreenMainPage = () => { major: "천문학과", mbti: "INTP", contactFrequency: "NORMAL", - hobbies: [{ name: "🔭 별보기", category: "자연" }], + hobbies: [ + { name: "🔭 별보기", category: "자연" }, + { name: "🧩 퍼즐", category: "문화" }, + { name: "♟️ 보드게임", category: "놀이" }, + ], + advantages: ["지적인 대화", "차분함"], profileImageUrl: "/main/dog.png", socialType: "INSTAGRAM", socialAccountId: "nightsky_star", @@ -108,7 +131,11 @@ const ScreenMainPage = () => { major: "체육교육과", mbti: "ESTP", contactFrequency: "FREQUENT", - hobbies: [{ name: "⚽ 축구", category: "스포츠" }], + hobbies: [ + { name: "⚽ 축구", category: "스포츠" }, + { name: "🧗 클라이밍", category: "스포츠" }, + ], + advantages: ["건강한 정신", "추진력", "밝은 웃음"], profileImageUrl: "/main/cat.png", socialAccountId: "", }, @@ -119,7 +146,11 @@ const ScreenMainPage = () => { major: "국어국문학과", mbti: "ISTJ", contactFrequency: "RARE", - hobbies: [{ name: "📚 독서", category: "문화" }], + hobbies: [ + { name: "📚 독서", category: "문화" }, + { name: "✍️ 글쓰기", category: "문화" }, + ], + advantages: ["진중함", "학구열"], profileImageUrl: "/main/dog.png", socialType: "INSTAGRAM", socialAccountId: "bookworm_kr", diff --git a/app/profile-builder/_components/ScreenProfileBuilder.tsx b/app/profile-builder/_components/ScreenProfileBuilder.tsx index 8ab76ff..5d46d8c 100644 --- a/app/profile-builder/_components/ScreenProfileBuilder.tsx +++ b/app/profile-builder/_components/ScreenProfileBuilder.tsx @@ -62,9 +62,8 @@ const LEGACY_PROFILE_STORAGE_KEY = "profileBuilder"; export const ScreenProfileBuilder = () => { const router = useRouter(); - const { profile, updateProfile } = useProfile(); + const { profile, updateProfile, isReady } = useProfile(); - // Derive initial values from profile or localStorage synchronously const [currentStep, setCurrentStep] = useState(1); const [selectedBirthYear, setSelectedBirthYear] = useState(""); const [selectedUniversity, setSelectedUniversity] = useState(""); @@ -126,9 +125,20 @@ export const ScreenProfileBuilder = () => { }; useEffect(() => { - const initialValues = getInitialValues(); + if (!isReady) return; - Promise.resolve().then(() => { + const initialValues = getInitialValues(); + const allFilled = Boolean( + initialValues.birthYear && + initialValues.university && + initialValues.department && + initialValues.major && + initialValues.gender && + initialValues.mbti && + initialValues.frequency, + ); + + const timeoutId = setTimeout(() => { if (initialValues.birthYear) setSelectedBirthYear(initialValues.birthYear); if (initialValues.university) @@ -141,28 +151,19 @@ export const ScreenProfileBuilder = () => { setHasSelectedGender(true); } if (initialValues.mbti) { - const mbti = initialValues.mbti.toUpperCase(); - setSelectedMBTI(mbti); - if (isValidMBTI(mbti)) setHasSelectedMBTI(true); + setSelectedMBTI(initialValues.mbti); + setHasSelectedMBTI(true); } if (initialValues.frequency) { setSelectedFrequency(initialValues.frequency); setHasSelectedFrequency(true); } - const allFilled = Boolean( - initialValues.birthYear && - initialValues.university && - initialValues.department && - initialValues.major && - initialValues.gender && - isValidMBTI(initialValues.mbti) && - initialValues.frequency, - ); - if (allFilled) setCurrentStep(4); - }); - }, [profile]); + }, 0); + + return () => clearTimeout(timeoutId); + }, [isReady]); const yearOptions = getYearOptions(); const universityOptions = getUniversityOptions(universities); @@ -185,7 +186,6 @@ export const ScreenProfileBuilder = () => { const handleComplete = () => { const normalizedMBTI = selectedMBTI.toUpperCase(); - // Context 업데이트용 데이터 변환 const profileData: Partial = { birthDate: selectedBirthYear ? `${selectedBirthYear}-01-01` : undefined, university: selectedUniversity, @@ -196,10 +196,7 @@ export const ScreenProfileBuilder = () => { contactFrequency: contactFrequencyMap[selectedFrequency], }; - // Context 업데이트 updateProfile(profileData); - - // 다음 페이지로 이동 router.push("/hobby-select"); }; @@ -218,7 +215,6 @@ export const ScreenProfileBuilder = () => { setHasSelectedFrequency(true); }; - // 단계별 유효성 검사 const isStepValid = (() => { switch (currentStep) { case 1: @@ -241,7 +237,6 @@ export const ScreenProfileBuilder = () => { return (
- {/* 헤더 영역 */}

@@ -254,9 +249,7 @@ export const ScreenProfileBuilder = () => {

- {/* 폼 영역 */}
- {/* Step 4: Contact Frequency */} {currentStep >= 4 && ( { /> )} - {/* Step 3: MBTI */} {currentStep >= 3 && ( { /> )} - {/* Step 2: Gender */} {currentStep >= 2 && ( { /> )} - {/* Step 1: Basic */} { />
- {/* 하단 고정 버튼 */}
); }; + +export default ScreenProfileBuilder;