Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4662ed5
style:핀하우스 home / 텍스트 Color 변경
Feb 10, 2026
e3f372f
Merge pull request #386 from PinHouse/style/#385
kyungchan3007 Feb 10, 2026
c0f6195
feat:바텀 시트 포지션 정리 / 해당 컴포넌트 공통 훅으로 분리
Feb 12, 2026
557fc38
Merge pull request #388 from PinHouse/feat/#387
kyungchan3007 Feb 12, 2026
3e90eff
feat 바텀 시트 포지션 정리 / 해당 컴포넌트 공통 훅으로 분리
Feb 13, 2026
b3160fc
Merge pull request #390 from PinHouse/feat/#389
kyungchan3007 Feb 13, 2026
bce1d8a
fix:바텀 시트 포지션 정리 / 글로벌 렌더링에 종속 되지 않고 시트가 뷰포트 기준으로 포지션이 잡힘
Feb 13, 2026
6e23336
Merge pull request #392 from PinHouse/fix/#391
kyungchan3007 Feb 13, 2026
958407f
fix:바텀 시트 포지션 정리 / 글로벌 렌더링에 종속 되지 않고 시트가 뷰포트 기준으로 포지션이 잡힘
Feb 13, 2026
2243e8f
Merge pull request #394 from PinHouse/fix/#393
kyungchan3007 Feb 13, 2026
aeb1a25
refactor: 앱 라우트·위젯 분리 및 접근성·에러 처리 보강
JW-Ahn0 Feb 13, 2026
00ed533
feat: 마이페이지 공통 헤더 추가
JW-Ahn0 Feb 13, 2026
703f64d
Merge branch 'develop' into feat/#273
JW-Ahn0 Feb 13, 2026
369365b
Merge pull request #395 from PinHouse/feat/#273
JW-Ahn0 Feb 13, 2026
68b3e9b
feat: info 버튼 바텀시트 연동 및 폰 프레임 내 시트/스크롤 처리
JW-Ahn0 Feb 13, 2026
2e56867
fix: 빌드 에러 해결
JW-Ahn0 Feb 13, 2026
62d216f
Merge pull request #396 from PinHouse/feat/#253
JW-Ahn0 Feb 13, 2026
ddf2a4b
feat: 진단 결과 생성 로딩 화면 UI 개발
JW-Ahn0 Feb 13, 2026
8255d4e
Merge pull request #397 from PinHouse/feat/#257
JW-Ahn0 Feb 13, 2026
c1f7d30
fix:공고리스트 시트 포지션 및 버튼 클릭시 라우터 이동 버그
Feb 13, 2026
c441b4e
Merge pull request #399 from PinHouse/fix/#398
kyungchan3007 Feb 13, 2026
5a6cee2
refactor:공고상세조회 / 필터 시트 역할,책임 분리 작업
Feb 13, 2026
ebd1813
Merge pull request #401 from PinHouse/refactor/#400
kyungchan3007 Feb 18, 2026
13ebdfd
feat: 자격진단 결과(입력 정보 확인) 화면 및 진단 종료 시 결과 페이지 이동
JW-Ahn0 Feb 19, 2026
7805a99
Merge pull request #402 from PinHouse/feat/#259
JW-Ahn0 Feb 19, 2026
8c14ce9
fix:공고 리스트 / 공고 카드 섹션 / 시트 조정
Feb 19, 2026
188270e
Merge pull request #404 from PinHouse/fix/#403
kyungchan3007 Feb 19, 2026
b08ee63
feat: 자격진단 API 연동 완료
JW-Ahn0 Feb 19, 2026
31fbd6c
Merge pull request #405 from PinHouse/feat/#256
JW-Ahn0 Feb 19, 2026
66c1a17
feat: 자격진단 핀 보고서 결과 화면(마이페이지,자격진단) 개발 완료
JW-Ahn0 Feb 19, 2026
16ab5e4
Merge pull request #406 from PinHouse/feat/#258
JW-Ahn0 Feb 19, 2026
15d7576
fix:
Feb 20, 2026
4ba2c8f
fix:핀하우스 Home / 자격진단 및 마이페이지
Feb 20, 2026
b923a99
Merge pull request #408 from PinHouse/fix/#407
kyungchan3007 Feb 20, 2026
b40bc8c
refactor:homeActionCardList 이전 커밋으로 롤백
Feb 20, 2026
0164908
Merge pull request #410 from PinHouse/refactor/#409
kyungchan3007 Feb 20, 2026
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
58 changes: 54 additions & 4 deletions app/eligibility/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,73 @@
"use client";

import { Suspense, useEffect } from "react";
import { Suspense, useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { EligibilitySection } from "@/src/widgets/eligibilitySection";
import { useEligibilityStore } from "@/src/features/eligibility/model/eligibilityStore";
import { useDiagnosisResultStore } from "@/src/features/eligibility/model/diagnosisResultStore";
import { getDiagnosisLatest } from "@/src/features/eligibility/api/diagnosisApi";
import type { DiagnosisLatestData } from "@/src/features/eligibility/api/diagnosisTypes";
import { Modal } from "@/src/shared/ui/modal/default/modal";
import { Spinner } from "@/src/shared/ui/spinner/default";

export default function EligibilityPage() {
const router = useRouter();
const reset = useEligibilityStore(state => state.reset);
const setDiagnosisResult = useDiagnosisResultStore(s => s.setResult);
const [isModalOpen, setIsModalOpen] = useState(false);

useEffect(() => {
// 자격진단 페이지 진입 시 store 초기화
reset();
}, [reset]);
let mounted = true;

const checkLatest = async () => {
try {
const response = await getDiagnosisLatest<DiagnosisLatestData>();
if (!mounted) return;
const data = response?.data as DiagnosisLatestData | undefined;
if (data != null && typeof data === "object" && "eligible" in data) {
setDiagnosisResult(
{
eligible: data.eligible,
decisionMessage: data.diagnosisResult,
recommended: data.recommended,
},
{ incomeLevel: data.myIncomeLevel }
);
setIsModalOpen(true);
} else {
reset();
}
} catch {
if (mounted) reset();
}
};

checkLatest();
return () => {
mounted = false;
};
}, [reset, setDiagnosisResult]);

const handleModalButtonClick = (index: number) => {
setIsModalOpen(false);
if (index === 0) {
setDiagnosisResult(null);
reset();
} else {
router.push("/eligibility/result/final");
}
};

return (
<main className="flex h-full flex-col">
<Suspense fallback={<Spinner title="로딩 중" description="페이지를 불러오는 중입니다." />}>
<EligibilitySection />
</Suspense>
<Modal
type="eligibilityPreviousDiagnosis"
open={isModalOpen}
onButtonClick={handleModalButtonClick}
/>
</main>
);
}
11 changes: 11 additions & 0 deletions app/eligibility/result/final/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";

import { EligibilityFinalResultSection } from "@/src/widgets/eligibilitySection";

export default function EligibilityFinalResultPage() {
return (
<main className="flex h-full flex-col">
<EligibilityFinalResultSection />
</main>
);
}
11 changes: 11 additions & 0 deletions app/eligibility/result/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";

import { EligibilityResultSection } from "@/src/widgets/eligibilitySection";

export default function EligibilityResultPage() {
return (
<main className="flex h-full flex-col">
<EligibilityResultSection />
</main>
);
}
6 changes: 1 addition & 5 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { HomeLandingRender } from "@/src/shared/ui/globalRender/globalRender";
import { FrameBottomNav } from "@/src/shared/ui/bottomNavigation/frameBottomNavigation";
import { ClientOnly } from "@/src/shared/ui/clientOnly/clientOnly";



export const metadata: Metadata = {
title: "pinhouse",
description: "pinhosue-fe",
Expand Down Expand Up @@ -43,9 +41,7 @@ export default function RootLayout({
</ClientOnly>
}
>
<ClientOnly>
<div>{children}</div>
</ClientOnly>
<ClientOnly>{children}</ClientOnly>
</HomeLandingRender>
</div>
</div>
Expand Down
80 changes: 2 additions & 78 deletions app/mypage/page.tsx
Original file line number Diff line number Diff line change
@@ -1,83 +1,7 @@
"use client";

import { SearchLine } from "@/src/assets/icons/home";
import FootPrintIcon from "@/src/assets/icons/mypage/footPrintIcon";
import MapPinIcon from "@/src/assets/icons/mypage/mapPinIcon";
import RecentIcon from "@/src/assets/icons/mypage/recentIcon";
import PinsetIcon from "@/src/assets/icons/mypage/pinsetIcon";
import { MypageSection, UserInfoCard, PinReportSection } from "@/src/features/mypage/ui";
import { useRouter } from "next/navigation";
import { useOAuthStore } from "@/src/features/login/model/authStore";

import { MypageSection } from "@/src/widgets/mypageSection";

export default function MypagePage() {
const { userName } = useOAuthStore();
const imageUrl = null;
const router = useRouter();
return (
<div className="flex flex-col min-h-screen gap-5 px-5 pb-6 bg-greyscale-grey-25">
{/* 사용자 정보 카드 */}
<UserInfoCard
imageUrl={imageUrl}
userName={userName}
userEmail="백엔드에서이메일정보전달필요@naver.com"
onSettingsClick={() => {
router.push("/mypage/settings");
}}
/>

{/* 핀 보고서 섹션 */}
<PinReportSection
onDiagnosisClick={() => {
router.push("/eligibility");
}}
/>

{/* 내 정보 섹션 */}
<MypageSection
title="내 정보"
items={[
{
icon: <FootPrintIcon />,
label: "관심 주변 환경 설정",
onClick: () => {
alert("관심 주변 환경 설정 미구현 상태");
// TODO: 네비게이션 구현
},
},
{
icon: <MapPinIcon />,
label: "핀포인트 설정",
onClick: () => {
router.push("/mypage/pinpoints");
},
},
]}
/>

{/* 내 활동 섹션 */}
<MypageSection
title="내 활동"
items={[
{
icon: <PinsetIcon />,
label: "저장 목록",
onClick: () => {
alert("저장 목록 이동 미구현 상태");
// TODO: 네비게이션 구현
},
},
{
icon: <RecentIcon />,
label: "최근 본 공고",
onClick: () => {
alert("최근 본 공고 이동 미구현 상태");
// TODO: 네비게이션 구현
},
},
]}
/>
</div>
);
return <MypageSection />;
}

51 changes: 4 additions & 47 deletions app/mypage/pinpoints/page.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,7 @@
"use client";

import { MapPin } from "@/src/assets/icons/onboarding";
import { useAddressStore } from "@/src/entities/address";
import { AddressSearch } from "@/src/features/addressSearch";
import { useAddPinpoint } from "@/src/features/mypage/hooks/useAddPinpoint";
import { Button } from "@/src/shared/lib/headlessUi";
import { useRouter } from "next/navigation";
import { PinpointsSection } from "@/src/widgets/mypageSection";

const MypagePinpointsPage = () => {
const title = "핀포인트 설정";
const description = "나만의 핀포인트를 찍고\n원하는 거리 안의 임재주택을 찾아보세요!";
const image = <MapPin />;
const { address, pinPoint } = useAddressStore();
const router = useRouter();
const { addPinpoint, isLoading, isError, error } = useAddPinpoint({
onSuccess: () => {
router.push("/mypage/settings"); // 주소 선택 후 이전 화면으로
// 또는 목록 새로고침 등
},
onError: err => {
// 토스트 등 에러 처리
},
});
return (
<div className="p-5">
<div className="mb-3 flex flex-[1] flex-col items-center justify-start text-center">
<div className="inline-flex sm:min-w-[200px] sm:max-w-[250px] md:min-w-[250px] md:max-w-[300px] lg:min-w-[280px] lg:max-w-[340px]">
{image}
</div>
{title && <h2 className="text-lg font-bold">{title}</h2>}
<p className="mt-1 whitespace-pre-line text-center text-sm text-gray-500">{description}</p>
<div className="mt-5 w-full">
<AddressSearch />
</div>
</div>
{address ? (
<Button
size={"md"}
variant={"solid"}
onClick={() => addPinpoint({ address, name: pinPoint || "핀 포인트", first: true })}
>
핀포인트 추가
</Button>
) : null}
</div>
);
};

export default MypagePinpointsPage;
export default function MypagePinpointsPage() {
return <PinpointsSection />;
}
23 changes: 2 additions & 21 deletions app/mypage/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,7 @@
"use client";

import { ProfileForm } from "@/src/features/mypage/ui/profileForm";
import { LeftButton } from "@/src/assets/icons/button/leftButton";
import { useRouter } from "next/navigation";
import { useOAuthStore } from "@/src/features/login/model/authStore";
import { ProfileSection } from "@/src/widgets/mypageSection";

export default function ProfilePage() {
const { userName } = useOAuthStore();

// TODO: 로그인 시 or 프로필 조회 API로 실제 사용자 이메일, Provider 정보 필요
const initialEmail = "로그인할때or프로필조회API로이메일_필요@naver.com"; // 예시
const initialProvider = "kakao" as const;
return (
<div className="flex min-h-screen flex-col bg-white">
{/* 프로필 폼 */}
<div className="px-5 py-6">
<ProfileForm
initialNickname={userName}
initialEmail={initialEmail}
initialProvider={initialProvider}
/>
</div>
</div>
);
return <ProfileSection />;
}
32 changes: 2 additions & 30 deletions app/mypage/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
"use client";

import Link from "next/link";
import { logout } from "@/src/features/login/utils/logout";
import { SettingsSection } from "@/src/widgets/mypageSection";

export default function MypageSettingsPage() {
return (
<div className="flex min-h-screen flex-col bg-white px-5">
<div className="flex flex-col">
<Link
href="/mypage/profile"
className="font-regular block w-full px-5 py-3 text-base leading-[140%] tracking-[-0.02em] text-greyscale-grey-900 hover:no-underline"
>
프로필 설정
</Link>
<div className="-mx-[20px] h-[9px] border-t border-greyscale-grey-50 bg-greyscale-grey-25"></div>

<button
type="button"
onClick={logout}
className="font-regular block w-full px-5 py-3 text-left text-base leading-[140%] tracking-[-0.02em] text-greyscale-grey-900"
>
로그아웃
</button>

<Link
href="/mypage/withdraw"
className="font-regular block w-full px-5 py-3 text-base leading-[140%] tracking-[-0.02em] text-greyscale-grey-900 hover:no-underline"
>
회원 탈퇴
</Link>
</div>
</div>
);
return <SettingsSection />;
}
22 changes: 2 additions & 20 deletions app/mypage/withdraw/page.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
"use client";

import { WithdrawForm } from "@/src/features/mypage/ui/withdrawForm";
import { WithdrawBanner } from "@/src/features/mypage/ui";
import { WithdrawSection } from "@/src/widgets/mypageSection";

export default function WithdrawPage() {
return (
<div className="flex min-h-screen flex-col bg-white">
{/* 상단 아이콘 및 문구 */}
<WithdrawBanner
className="py-6"
title="그동안 핀하우스를 이용해 주셔서 감사합니다."
description="탈퇴 사유를 알려주시면 서비스 개선에 참고하겠습니다."
/>

{/* 구분선 */}
<div className="mb-7 h-[9px] w-full border border-greyscale-grey-50 bg-greyscale-grey-25" />

{/* 탈퇴 폼 */}
<div className="px-5">
<WithdrawForm />
</div>
</div>
);
return <WithdrawSection />;
}
Loading