Skip to content

Commit 09779e3

Browse files
authored
Merge pull request #397 from solid-connection/feat/univ-page
fix : 대학 페이지 스크롤 및 검색 로직 수정 및 멘토 페이지 무한 스피너 버그 해결
1 parent dd6188a commit 09779e3

7 files changed

Lines changed: 25 additions & 78 deletions

File tree

‎apps/web/src/app/(home)/_ui/UniversityList/index.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const UniversityList = ({ allRegionsUniversityList }: UniversityListProps) => {
4747
background: "white",
4848
}}
4949
/>
50-
<UniversityCards colleges={previewUniversities} showCapacity={false} enableVirtualization={false} />
50+
<UniversityCards colleges={previewUniversities} showCapacity={false} />
5151
</div>
5252
);
5353
};

‎apps/web/src/app/university/SearchBar.tsx‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import { zodResolver } from "@hookform/resolvers/zod";
4-
import { useRouter } from "next/navigation";
4+
import { usePathname, useRouter } from "next/navigation";
55
import { type SubmitHandler, useForm } from "react-hook-form";
66
import { z } from "zod";
77

@@ -27,6 +27,7 @@ interface SearchBarProps {
2727
// --- 폼 로직을 관리하는 부모 컴포넌트 ---
2828
const SearchForm = ({ initText }: SearchBarProps) => {
2929
const router = useRouter();
30+
const pathname = usePathname();
3031

3132
const {
3233
register,
@@ -48,12 +49,13 @@ const SearchForm = ({ initText }: SearchBarProps) => {
4849

4950
const queryString = queryParams.toString();
5051

51-
router.push(`/university?${queryString}`);
52+
// 현재 경로에서 쿼리 파라미터만 업데이트
53+
router.push(`${pathname}?${queryString}`);
5254
};
5355

5456
return (
55-
<form onSubmit={handleSubmit(onSubmit)} className="w-full">
56-
<div className="relative mb-2">
57+
<form onSubmit={handleSubmit(onSubmit)} className="sticky top-14 z-10 w-full bg-white pb-2">
58+
<div className="relative">
5759
<input
5860
type="text"
5961
placeholder={"대학명을 검색해보세요..."}

‎apps/web/src/app/university/list/[homeUniversityName]/SearchResultsContent.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const SearchResultsContentInner = ({ homeUniversityName }: SearchResultsContentI
8383
}, [searchParams]);
8484

8585
return (
86-
<div className="pt-4">
86+
<div>
8787
<SearchBar initText={searchText || undefined} />
8888

8989
{/* 지역 필터 */}

‎apps/web/src/app/university/list/[homeUniversityName]/page.tsx‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@ const UniversityListPage = async ({ params }: PageProps) => {
4949
return (
5050
<>
5151
<TopDetailNavigation title={`${universityName} 파견학교`} />
52-
<div className="mt-14 w-full px-5">
53-
<SearchResultsContent homeUniversityName={universityName} />
54-
</div>
52+
<SearchResultsContent homeUniversityName={universityName} />
5553
</>
5654
);
5755
};

‎apps/web/src/app/university/page.tsx‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,9 @@ const UniversityOnboardingPage = () => {
1919
return (
2020
<>
2121
<TopDetailNavigation title="대학교 선택" />
22-
<div className="mt-14 w-full px-5 py-6">
23-
<h1 className="mb-2 text-k-800 typo-bold-1">파견 대학교를 선택해주세요</h1>
24-
<p className="mb-6 text-k-500 typo-medium-4">
25-
소속 대학교를 선택하면 해당 대학교의 교환학생 파견 정보를 확인할 수 있습니다.
26-
</p>
27-
22+
<div className="mt-14 w-full px-5">
23+
<h1 className="mb-2 text-k-800 typo-bold-1">출신 학교 정보를 선택해주세요</h1>
24+
<p className="mb-6 text-k-500 typo-medium-4">해당 학교에서 제공되는 교환학생 파견 정보를 확인할 수 있습니다.</p>
2825
<div className="flex flex-col gap-2.5">
2926
{HOME_UNIVERSITIES.map((university) => (
3027
<Link key={university.slug} href={`/university/list/${university.slug}`} className="block">

‎apps/web/src/components/university/UniversityCards/index.tsx‎

Lines changed: 7 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
"use client";
22

3-
import { useVirtualizer } from "@tanstack/react-virtual";
4-
53
import clsx from "clsx";
6-
import { useRef } from "react";
74

85
import type { ListUniversity } from "@/types/university";
96
import UniversityCard from "../../ui/UniverSityCard";
@@ -13,69 +10,16 @@ type UniversityCardsProps = {
1310
style?: React.CSSProperties;
1411
className?: string;
1512
showCapacity?: boolean;
16-
enableVirtualization?: boolean;
1713
};
1814

19-
const ITEM_HEIGHT = 101;
20-
21-
const UniversityCards = ({
22-
colleges,
23-
style,
24-
className,
25-
showCapacity = true,
26-
enableVirtualization = true,
27-
}: UniversityCardsProps) => {
28-
// 훅은 항상 컴포넌트 상단에서 호출해야 함 (React Hooks 규칙)
29-
const parentRef = useRef<HTMLDivElement>(null);
30-
31-
const virtualizer = useVirtualizer({
32-
count: colleges.length,
33-
getScrollElement: () => parentRef.current,
34-
estimateSize: () => ITEM_HEIGHT,
35-
overscan: 5,
36-
});
37-
38-
// 가상화가 비활성화된 경우 일반 렌더링
39-
if (!enableVirtualization) {
40-
return (
41-
<div className={clsx("flex flex-col gap-2.5", className)} style={style}>
42-
{colleges.map((college) => (
43-
<div key={college.id} className="pb-2.5">
44-
<UniversityCard university={college} showCapacity={showCapacity} />
45-
</div>
46-
))}
47-
</div>
48-
);
49-
}
50-
51-
// 가상화 사용
15+
const UniversityCards = ({ colleges, style, className, showCapacity = true }: UniversityCardsProps) => {
5216
return (
53-
<div ref={parentRef} className={clsx("h-[calc(100vh-200px)] overflow-auto", className)} style={style}>
54-
<div
55-
style={{
56-
height: `${virtualizer.getTotalSize()}px`,
57-
width: "100%",
58-
position: "relative",
59-
}}
60-
>
61-
{virtualizer.getVirtualItems().map((virtualItem) => (
62-
<div
63-
key={colleges[virtualItem.index].id}
64-
style={{
65-
position: "absolute",
66-
top: 0,
67-
left: 0,
68-
width: "100%",
69-
height: `${virtualItem.size}px`,
70-
transform: `translateY(${virtualItem.start}px)`,
71-
}}
72-
>
73-
<div className="pb-2.5">
74-
<UniversityCard university={colleges[virtualItem.index]} showCapacity={showCapacity} />
75-
</div>
76-
</div>
77-
))}
78-
</div>
17+
<div className={clsx("flex flex-col gap-2.5", className)} style={style}>
18+
{colleges.map((college) => (
19+
<div key={college.id} className="pb-2.5">
20+
<UniversityCard university={college} showCapacity={showCapacity} />
21+
</div>
22+
))}
7923
</div>
8024
);
8125
};

‎apps/web/src/lib/zustand/useAuthStore.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ const useAuthStore = create<AuthState>()(
6363
accessToken: state.accessToken,
6464
isAuthenticated: state.isAuthenticated,
6565
}),
66+
onRehydrateStorage: () => (state) => {
67+
// hydration 완료 후 isInitialized를 true로 설정
68+
if (state) {
69+
state.isInitialized = true;
70+
}
71+
},
6672
},
6773
),
6874
);

0 commit comments

Comments
 (0)