Skip to content

Commit ee9b9fc

Browse files
authored
Merge pull request #127 from YAPP-Github/fix/PRODUCT-231
2 parents 7655767 + deb6009 commit ee9b9fc

File tree

3 files changed

+128
-94
lines changed

3 files changed

+128
-94
lines changed

src/app/(home)/_components/RecentCheers/RecentCheers.css.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@ export const recentSupportCard = style({
99
height: "13.6rem",
1010
});
1111

12-
export const storeImage = style({
13-
width: "4rem",
14-
height: "4rem",
15-
borderRadius: radius.circle,
16-
objectFit: "cover",
17-
});
18-
1912
export const cheersContent = style({
2013
display: "-webkit-box",
2114
WebkitLineClamp: 2,
@@ -56,3 +49,25 @@ export const divider = style({
5649
width: "0.1rem",
5750
height: "1rem",
5851
});
52+
53+
export const showAllButton = style({
54+
border: `1px solid ${semantic.border.grayLight}`,
55+
});
56+
57+
export const storeImage = style({
58+
width: "4rem",
59+
height: "4rem",
60+
borderRadius: radius[100],
61+
});
62+
63+
export const storeImageFallback = style([
64+
storeImage,
65+
{
66+
display: "flex",
67+
alignItems: "center",
68+
justifyContent: "center",
69+
70+
backgroundColor: semantic.background.grayLight,
71+
border: `0.4px solid ${semantic.border.grayLight}`,
72+
},
73+
]);

src/app/(home)/_components/RecentCheers/RecentCheers.tsx

Lines changed: 103 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@
22

33
import { Suspense } from "@suspensive/react";
44
import { useSuspenseQuery } from "@tanstack/react-query";
5-
import { chunk, noop } from "es-toolkit";
5+
import { chunk } from "es-toolkit";
66
import Image from "next/image";
77
import Link from "next/link";
88
import { type HTMLAttributes, useState } from "react";
99
import { Separated } from "react-simplikit";
1010

11-
import ChevronLeft from "@/assets/chevron-left.svg";
12-
import ChevronRight from "@/assets/chevron-right.svg";
11+
import LogoWordMark from "@/assets/logo-wordmark.svg";
12+
import ResetIcon from "@/assets/reset-20.svg";
13+
import { Button } from "@/components/ui/Button";
1314
import { Skeleton } from "@/components/ui/Skeleton";
1415
import { HStack, VStack } from "@/components/ui/Stack";
1516
import { Text } from "@/components/ui/Text";
17+
import { TextButton } from "@/components/ui/TextButton";
18+
import { colors } from "@/styles";
1619

1720
import { cheerQueryOptions } from "../../_api/cheer";
1821
import * as styles from "./RecentCheers.css";
@@ -21,53 +24,68 @@ const BACKGROUND_COLORS = ["#FEF8DD", "#FDE5E3", "#E0F2FF"];
2124

2225
export const RecentCheers = () => {
2326
return (
24-
<VStack gap={16}>
25-
<Text as='h2' color='text.normal' typo='title2Sb'>
26-
가게에 전하는 따뜻한 응원
27-
</Text>
28-
29-
<Suspense clientOnly fallback={<RecentSupportCardContentSkeleton />}>
30-
<RecentSupportCardContent />
31-
</Suspense>
32-
</VStack>
27+
<Suspense clientOnly fallback={<RecentSupportCardContentSkeleton />}>
28+
<RecentSupportCardContent />
29+
</Suspense>
3330
);
3431
};
3532

3633
const RecentSupportCardContent = () => {
3734
const [currentIndex, setCurrentIndex] = useState(0);
3835

39-
const { data } = useSuspenseQuery(cheerQueryOptions(10));
36+
const { data } = useSuspenseQuery(cheerQueryOptions(15));
4037

4138
const chunkedList = chunk(data.cheers, 3);
4239

40+
const handleRefresh = () => {
41+
setCurrentIndex((currentIndex + 1) % chunkedList.length);
42+
};
43+
4344
return (
44-
<VStack gap={24}>
45-
<VStack>
46-
{chunkedList[currentIndex]?.map((cheer, index) => (
47-
<Link key={cheer.cheerId} href={`/stores/${cheer.storeId}`}>
48-
<RecentSupportCard
49-
style={{
50-
backgroundColor: BACKGROUND_COLORS[index % 3],
51-
transform: index === 1 ? "rotate(-4deg)" : "translate3d(0,0,0)",
52-
}}
53-
store={{
54-
name: cheer.storeName,
55-
imageUrl: cheer.imageUrl,
56-
location: `${cheer.storeDistrict} ${cheer.storeNeighborhood}`,
57-
category: cheer.storeCategory,
58-
}}
59-
content={cheer.cheerDescription}
60-
/>
61-
</Link>
62-
))}
45+
<VStack gap={16}>
46+
<HStack justify='between'>
47+
<Text as='h2' color='text.normal' typo='title2Sb'>
48+
가게에 전하는 따뜻한 응원
49+
</Text>
50+
<TextButton variant='assistive' size='small' onClick={handleRefresh}>
51+
<HStack gap={4} align='center'>
52+
새로고침
53+
<ResetIcon width={16} height={16} />
54+
</HStack>
55+
</TextButton>
56+
</HStack>
57+
<VStack gap={20}>
58+
<VStack>
59+
{chunkedList[currentIndex]?.map((cheer, index) => (
60+
<Link key={cheer.cheerId} href={`/stores/${cheer.storeId}`}>
61+
<RecentSupportCard
62+
style={{
63+
backgroundColor: BACKGROUND_COLORS[index % 3],
64+
transform:
65+
index === 1 ? "rotate(-4deg)" : "translate3d(0,0,0)",
66+
}}
67+
store={{
68+
name: cheer.storeName,
69+
imageUrl: cheer.imageUrl,
70+
location: `${cheer.storeDistrict} ${cheer.storeNeighborhood}`,
71+
category: cheer.storeCategory,
72+
}}
73+
content={cheer.cheerDescription}
74+
/>
75+
</Link>
76+
))}
77+
</VStack>
78+
<Link href='/stores'>
79+
<Button
80+
variant='custom'
81+
size='large'
82+
className={styles.showAllButton}
83+
fullWidth
84+
>
85+
가게 전체보기
86+
</Button>
87+
</Link>
6388
</VStack>
64-
65-
<RecentSupportButtons
66-
currentIndex={currentIndex}
67-
totalCount={chunkedList.length - 1}
68-
onPrevious={() => setCurrentIndex(currentIndex - 1)}
69-
onNext={() => setCurrentIndex(currentIndex + 1)}
70-
/>
7189
</VStack>
7290
);
7391
};
@@ -90,15 +108,26 @@ const RecentSupportCard = ({
90108
return (
91109
<VStack gap={8} className={styles.recentSupportCard} {...restProps}>
92110
<HStack gap={12}>
93-
<Image
94-
width={40}
95-
height={40}
96-
alt={`${store.name} 가게 이미지`}
97-
className={styles.storeImage}
98-
src={store.imageUrl}
99-
// TODO: 추후 제거
100-
unoptimized
101-
/>
111+
{store.imageUrl ? (
112+
<Image
113+
width={40}
114+
height={40}
115+
alt={`${store.name} 가게 이미지`}
116+
className={styles.storeImage}
117+
objectFit='cover'
118+
src={store.imageUrl}
119+
// TODO: 추후 제거
120+
unoptimized
121+
/>
122+
) : (
123+
<span className={styles.storeImageFallback}>
124+
<LogoWordMark
125+
width={30.16}
126+
height={16}
127+
color={colors.coolNeutral[96]}
128+
/>
129+
</span>
130+
)}
102131
<VStack gap={2}>
103132
<Text as='span' typo='body2Sb' color='text.normal'>
104133
{store.name}
@@ -127,47 +156,34 @@ const RecentSupportCard = ({
127156
);
128157
};
129158

130-
const RecentSupportButtons = ({
131-
currentIndex,
132-
totalCount,
133-
onPrevious,
134-
onNext,
135-
}: {
136-
currentIndex: number;
137-
totalCount: number;
138-
onPrevious: () => void;
139-
onNext: () => void;
140-
}) => {
141-
return (
142-
<HStack justify='between'>
143-
<button
144-
className={styles.recentCheersButton}
145-
disabled={currentIndex === 0}
146-
onClick={onPrevious}
147-
>
148-
<ChevronLeft width={24} height={24} />
149-
</button>
150-
<button
151-
className={styles.recentCheersButton}
152-
disabled={currentIndex === totalCount}
153-
onClick={onNext}
154-
>
155-
<ChevronRight width={24} height={24} />
156-
</button>
157-
</HStack>
158-
);
159-
};
160-
161159
const RecentSupportCardContentSkeleton = () => {
162160
return (
163-
<VStack gap={24}>
164-
<Skeleton width='100%' height={400} radius={26} />
165-
<RecentSupportButtons
166-
currentIndex={0}
167-
totalCount={0}
168-
onPrevious={noop}
169-
onNext={noop}
170-
/>
161+
<VStack gap={16}>
162+
<HStack justify='between'>
163+
<Text as='h2' color='text.normal' typo='title2Sb'>
164+
가게에 전하는 따뜻한 응원
165+
</Text>
166+
<TextButton variant='assistive' size='small' disabled>
167+
<HStack gap={4} align='center'>
168+
새로고침
169+
<ResetIcon width={16} height={16} />
170+
</HStack>
171+
</TextButton>
172+
</HStack>
173+
174+
<VStack gap={20}>
175+
<Skeleton width='100%' height={400} radius={26} />
176+
<Link href='/stores'>
177+
<Button
178+
variant='custom'
179+
size='large'
180+
className={styles.showAllButton}
181+
fullWidth
182+
>
183+
가게 전체보기
184+
</Button>
185+
</Link>
186+
</VStack>
171187
</VStack>
172188
);
173189
};

src/assets/reset-20.svg

Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)