Skip to content

Commit 1ffbcda

Browse files
authored
Merge pull request #77 from Morak-Team/feature/fixSupport
[Fix] 지원 공고 페이지 주관기관 표기 및 코드 중복 해소
2 parents 5eae09b + bac7348 commit 1ffbcda

16 files changed

Lines changed: 157 additions & 191 deletions

File tree

src/hooks/useLikeToggle.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { useState, useEffect } from "react";
2+
import {
3+
getLikedCompanies,
4+
likeCompany,
5+
unlikeCompany,
6+
} from "@/apis/company/getLikedCompanies";
7+
import useAuthStore from "@/store/authStore";
8+
import useLikeStore from "@/store/useLikeStore";
9+
10+
export const useLikeToggle = (companyId) => {
11+
const { isLoggedIn } = useAuthStore();
12+
const [isLiked, setIsLiked] = useState(false);
13+
const [loading, setLoading] = useState(true);
14+
const [showLoginModal, setShowLoginModal] = useState(false);
15+
16+
const { likedMap, setLike } = useLikeStore();
17+
18+
// 로그인 및 좋아요 여부 확인
19+
useEffect(() => {
20+
const check = async () => {
21+
if (isLoggedIn && companyId) {
22+
const likedList = await getLikedCompanies();
23+
const liked = likedList.some(
24+
(c) => String(c.companyId) === String(companyId),
25+
);
26+
setIsLiked(liked);
27+
setLike(companyId, liked);
28+
}
29+
setLoading(false);
30+
};
31+
32+
if (companyId) check();
33+
}, [companyId]);
34+
35+
// 좋아요 토글 함수
36+
const toggleLike = async () => {
37+
if (!isLoggedIn) {
38+
setShowLoginModal(true);
39+
return;
40+
}
41+
42+
try {
43+
const currentLiked = likedMap[companyId] ?? false;
44+
45+
if (currentLiked) {
46+
await unlikeCompany(companyId);
47+
} else {
48+
await likeCompany(companyId);
49+
}
50+
const newLiked = !currentLiked;
51+
setIsLiked(newLiked);
52+
setLike(companyId, newLiked);
53+
} catch (e) {
54+
console.error("좋아요 토글 실패:", e);
55+
}
56+
};
57+
58+
return {
59+
isLiked,
60+
isLoggedIn,
61+
loading,
62+
toggleLike,
63+
showLoginModal,
64+
setShowLoginModal,
65+
};
66+
};

src/pages/map/components/review/ReviewContent.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const ReviewContent = ({ item, hasBorder = true }) => {
88
item.reviewCategories?.includes(tag.value)
99
);
1010

11-
const profileIconSrc = `/svgs/profile/${item.profileColor || "gray"}.svg`;
11+
const profileIconSrc = `/svgs/profile/${item?.profileColor || "gray"}.svg`;
1212

1313
return (
1414
<div

src/pages/myPageDetail/MyPageDetailPage.jsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useGetReviews, useGetCheers } from "@/apis/myPage/queries";
66
import ReviewItem from "@/pages/myPageDetail/components/ReviewItem";
77
import StoryItem from "@/pages/myPageDetail/components/StoryItem";
88
import noResult from "/svgs/myPage/noResult.svg";
9+
import Spinner from "@/components/common/Spinner";
910

1011
const MyPageDetailPage = () => {
1112
const navigate = useNavigate();
@@ -20,6 +21,14 @@ const MyPageDetailPage = () => {
2021
});
2122
// const { data: heartsData, isLoading: isLoadingHearts } = useGetHearts({ enabled: kind === "찜" });
2223

24+
if (isLoadingReviews || isLoadingCheers) {
25+
return (
26+
<div className="flex justify-center items-center container">
27+
<Spinner />
28+
</div>
29+
);
30+
}
31+
2332
return (
2433
<div className="flex flex-col pt-5 container overflow-y-auto scrollbar-hide">
2534
<div className="mt-10 px-5 mb-4" onClick={() => navigate(-1)}>
@@ -38,7 +47,7 @@ const MyPageDetailPage = () => {
3847

3948
{kind === "찜" && (
4049
<div className="flex justify-between items-center px-5">
41-
<div className="flex gap-2 items-center">
50+
<div className="flex gap-2 items-center my-2">
4251
<img src={heart} className="w-8 h-8" />
4352
<p className="h3">저장한 장소</p>
4453
</div>
@@ -48,7 +57,7 @@ const MyPageDetailPage = () => {
4857

4958
{kind === "응원" && (
5059
<div className="flex justify-between items-center px-5">
51-
<div className="flex gap-2 items-center">
60+
<div className="flex gap-2 items-center my-2">
5261
<img src={cheer} className="w-8 h-8" />
5362
<p className="h3">내가 응원한 이야기</p>
5463
</div>
@@ -59,37 +68,37 @@ const MyPageDetailPage = () => {
5968
<div className="flex flex-col gap-4 w-full bg-gray-2 p-5 min-h-screen">
6069
{kind === "리뷰" && (
6170
<>
62-
{reviewsData?.length > 0 ? (
71+
{!isLoadingReviews && reviewsData?.length > 0 ? (
6372
reviewsData.map((item, idx) => (
6473
<ReviewItem data={item} key={idx} />
6574
))
66-
) : (
75+
) : !isLoadingReviews && reviewsData?.length === 0 ? (
6776
<div className="flex flex-col justify-center items-center mt-36">
6877
<img src={noResult} />
6978
<p className="h4 text-gray-9 text-center py-8">
7079
아직 작성한 리뷰가
7180
<br /> 없어요
7281
</p>
7382
</div>
74-
)}
83+
) : null}
7584
</>
7685
)}
7786

7887
{kind === "응원" && (
7988
<>
80-
{cheersData?.length > 0 ? (
89+
{!isLoadingCheers && cheersData?.length > 0 ? (
8190
cheersData.map((item) => (
8291
<StoryItem item={item} key={item.storyId} />
8392
))
84-
) : (
93+
) : !isLoadingCheers && cheersData?.length === 0 ? (
8594
<div className="flex flex-col justify-center items-center mt-36">
8695
<img src={noResult} />
8796
<p className="h4 text-gray-9 text-center py-8">
8897
아직 응원한 이야기가
8998
<br /> 없어요
9099
</p>
91100
</div>
92-
)}
101+
) : null}
93102
</>
94103
)}
95104
</div>

src/pages/myPageDetail/components/ReviewItem.jsx

Lines changed: 7 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,93 +2,28 @@ import ReviewContent from "@/pages/map/components/review/ReviewContent";
22
import { useNavigate } from "react-router-dom";
33
import { useGetCompanyPreview } from "@/apis/company/queries";
44
import { businessTypeNameMap } from "@/constants/categoryMap";
5-
import { useState, useEffect } from "react";
6-
import {
7-
getLikedCompanies,
8-
likeCompany,
9-
unlikeCompany,
10-
} from "@/apis/company/getLikedCompanies";
11-
import useAuthStore from "@/store/authStore";
5+
126
import useLikeStore from "@/store/useLikeStore";
13-
import HaveToLoginModal from "@/components/common/HaveToLoginModal";
147
import useUserInfoStore from "@/store/userInfoStore";
15-
16-
const dummyReviewItem = {
17-
name: "김소영",
18-
profileColor: "pink",
19-
temperature: 74.6,
20-
reviewContent:
21-
"제품 품질도 후드러고 청건하게 잘 관리되어 있어요. 다시 방문하고 싶어요!",
22-
reviewCategories: ["GOOD_QUALITY", "CLEAN", "REVISIT"],
23-
};
8+
import { useLikeToggle } from "@/hooks/useLikeToggle";
249

2510
const ReviewItem = ({ data }) => {
2611
const navigate = useNavigate();
2712
const { data: companyData } = useGetCompanyPreview(data.companyId);
28-
const [showLoginModal, setShowLoginModal] = useState(false);
29-
const [isLiked, setIsLiked] = useState(false);
30-
const [isLoggedIn, setIsLoggedIn] = useState(false);
31-
const [loading, setLoading] = useState(true);
3213

3314
const { userInfo } = useUserInfoStore();
3415

35-
const { likedMap, setLike } = useLikeStore();
16+
const { likedMap } = useLikeStore();
3617
const isGloballyLiked = likedMap[data.companyId] ?? false;
3718

19+
const { isLoggedIn, toggleLike } = useLikeToggle(data.companyId);
20+
3821
const combinedReviews = {
3922
...data,
4023
name: userInfo.name,
4124
profileColor: userInfo.profileColor,
4225
};
4326

44-
useEffect(() => {
45-
const checkLoginAndLiked = async () => {
46-
const isAuthenticated = await useAuthStore.getState().checkAuth();
47-
setIsLoggedIn(isAuthenticated);
48-
49-
if (isAuthenticated && data?.companyId) {
50-
const likedList = await getLikedCompanies();
51-
const liked = likedList.some(
52-
(c) => String(c.companyId) === String(data.companyId)
53-
);
54-
setIsLiked(liked);
55-
setLike(data.companyId, liked);
56-
}
57-
setLoading(false);
58-
};
59-
60-
if (data?.companyId) checkLoginAndLiked();
61-
}, [data?.companyId]);
62-
63-
const handleLikeClick = async () => {
64-
const isAuthenticated = await useAuthStore.getState().checkAuth();
65-
setIsLoggedIn(isAuthenticated);
66-
67-
if (!isAuthenticated) {
68-
setShowLoginModal(true);
69-
return;
70-
}
71-
72-
try {
73-
setLoading(true);
74-
const currentLiked = likedMap[data.companyId] ?? false;
75-
76-
if (currentLiked) {
77-
await unlikeCompany(data.companyId);
78-
} else {
79-
await likeCompany(data.companyId);
80-
}
81-
82-
const newLiked = !currentLiked;
83-
setIsLiked(newLiked);
84-
setLike(data.companyId, newLiked);
85-
} catch (e) {
86-
console.error("좋아요 토글 실패:", e);
87-
} finally {
88-
setLoading(false);
89-
}
90-
};
91-
9227
return (
9328
<div
9429
className="flex flex-col rounded-md pt-6 px-5 bg-white"
@@ -107,14 +42,14 @@ const ReviewItem = ({ data }) => {
10742
<button
10843
onClick={(e) => {
10944
e.stopPropagation();
110-
handleLikeClick();
45+
toggleLike();
11146
}}
11247
>
11348
<img
11449
src={
11550
isLoggedIn && isGloballyLiked
11651
? "/svgs/storeReview/fullHeartIcon.svg"
117-
: "/svgs/Ic_Heart-Empty.svg"
52+
: "/svgs/common/Ic_Heart-Empty.svg"
11853
}
11954
alt="좋아요 버튼"
12055
className="w-6 h-6"

src/pages/review/components/PlaceInfo.jsx

Lines changed: 22 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,70 +3,25 @@ import {
33
companyTypeNameMap,
44
companyTypeIconMap,
55
} from "@constants/categoryMap";
6-
import { useState, useEffect } from "react";
76
import { usePaymentStore } from "@/store/paymentStore";
8-
import {
9-
getLikedCompanies,
10-
likeCompany,
11-
unlikeCompany,
12-
} from "@apis/company/getLikedCompanies";
137
import HaveToLoginModal from "@components/common/HaveToLoginModal";
148
import { openNaverMapRoute } from "@pages/map/utils/openNaverMapRoute";
159
import { useUserCoords } from "@pages/search/hooks/useUserCoords";
16-
import useAuthStore from "@/store/authStore";
10+
import Spinner from "@/components/common/Spinner";
11+
import { useLikeToggle } from "@/hooks/useLikeToggle";
1712

1813
const PlaceInfo = ({ placeInfo }) => {
1914
const userCoords = useUserCoords();
20-
21-
const [showLoginModal, setShowLoginModal] = useState(false);
22-
const [isLiked, setIsLiked] = useState(false);
23-
const [isLoggedIn, setIsLoggedIn] = useState(false);
24-
const [loading, setLoading] = useState(true);
25-
2615
const { companyId } = usePaymentStore();
2716

28-
// 로그인 여부 + 찜 여부 확인
29-
useEffect(() => {
30-
const checkLoginAndLiked = async () => {
31-
const isAuthenticated = await useAuthStore.getState().checkAuth();
32-
setIsLoggedIn(isAuthenticated);
33-
34-
if (isAuthenticated && companyId) {
35-
const likedList = await getLikedCompanies();
36-
const liked = likedList.some(
37-
(c) => String(c.companyId) === String(companyId)
38-
);
39-
setIsLiked(liked);
40-
}
41-
setLoading(false);
42-
};
43-
44-
if (companyId) checkLoginAndLiked();
45-
}, [companyId]);
46-
47-
const handleLikeClick = async () => {
48-
const isAuthenticated = await useAuthStore.getState().checkAuth();
49-
setIsLoggedIn(isAuthenticated);
50-
51-
if (!isAuthenticated) {
52-
setShowLoginModal(true);
53-
return;
54-
}
55-
56-
try {
57-
setLoading(true);
58-
if (isLiked) {
59-
await unlikeCompany(companyId);
60-
} else {
61-
await likeCompany(companyId);
62-
}
63-
setIsLiked((prev) => !prev);
64-
} catch (e) {
65-
console.error("좋아요 토글 실패:", e);
66-
} finally {
67-
setLoading(false);
68-
}
69-
};
17+
const {
18+
isLiked,
19+
isLoggedIn,
20+
loading,
21+
toggleLike,
22+
showLoginModal,
23+
setShowLoginModal,
24+
} = useLikeToggle(companyId);
7025

7126
const handleRouteClick = (e) => {
7227
e.preventDefault();
@@ -89,6 +44,13 @@ const PlaceInfo = ({ placeInfo }) => {
8944
}
9045
};
9146

47+
if (loading) {
48+
return (
49+
<div className="flex justify-center items-center container">
50+
<Spinner />
51+
</div>
52+
);
53+
}
9254
return (
9355
<div className="w-full px-5">
9456
<div className="flex justify-between items-start mt-4 w-full">
@@ -153,14 +115,17 @@ const PlaceInfo = ({ placeInfo }) => {
153115
</a>
154116

155117
<button
156-
onClick={handleLikeClick}
118+
onClick={(e) => {
119+
e.preventDefault();
120+
toggleLike();
121+
}}
157122
className="w-12 h-12 flex items-center justify-center rounded-md bg-[#FAFAF9] shrink-0"
158123
>
159124
<img
160125
src={
161126
isLoggedIn && isLiked
162127
? "/svgs/storeReview/fullHeartIcon.svg"
163-
: "/svgs/Ic_Heart-Empty.svg"
128+
: "/svgs/common/Ic_Heart-Empty.svg"
164129
}
165130
alt="좋아요 버튼"
166131
className="w-6 h-6"

0 commit comments

Comments
 (0)