Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
1,710 changes: 1,490 additions & 220 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
"axios": "^1.10.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"embla-carousel-react": "^8.6.0",
"lucide-react": "^0.525.0",
"next": "13.5.11",
"next": "^15.4.4",
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.59.0",
Expand Down
14 changes: 14 additions & 0 deletions public/images/image1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions public/images/image2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions public/images/image3.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions public/images/image4.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/Next.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/SearchButton.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/Star.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions src/components/common/winelist/WineCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react';

import Link from 'next/link';

import StarIcon from '@/assets/icons/Star.svg';
import { ImageCard } from '@/components/common/card/ImageCard';
import { cn } from '@/lib/utils';

interface WineCardProps {
id: number;
image: string;
name: string;
rating: number;
}

export default function WineCard({ id, image, name, rating }: WineCardProps) {
return (
<Link href={`/wines/${id}`} key={id} className='no-underline'>
<div
className={cn(
'flex h-[160px] bg-white p-2 border border-gray-200 ',
'rounded-[12px]',
'shadow-[0px_2px_20px_0px_rgba(0,0,0,0.04)]',
'md:w-[232px] md:h-[185px]',
)}
>
{/* ์™ผ์ชฝ: ์ด๋ฏธ์ง€ ์นด๋“œ */}
<div className='flex-shrink-0'>
<ImageCard
imageSrc={image}
className='p-0 border-none bg-transparent w-[80px] h-[112px]'
imageClassName='w-[38px] h-[136px] ml-[10px] rounded-md object-cover mt-[14px] md:w-[44px] md:h-[155px] md:mt-[20px] md:ml-[20px]'
/>
</div>

{/* ์˜ค๋ฅธ์ชฝ: ํ‰์  + ๋ณ„์  + ์ด๋ฆ„ */}
<div className='w-[80px] h-[97px] flex flex-col justify-start mt-[10px] ml-[5px] md:w-[100px] md:h-[125px] md:ml-[20px]'>
<div className='text-[28px] font-extrabold leading-100% text-gray-800 md:text-[36px] '>
{rating.toFixed(1)}
</div>
<div className='flex gap-[4px] w-[60px] h-[12px] -mt-[2px] md:w-[90px] md:h-[18px]'>
{Array.from({ length: 5 }).map((_, i) => (
<StarIcon
key={i}
className={cn(
rating >= i + 1 ? 'fill-purpleDark' : 'fill-gray-300',
'w-[12px] h-[12px] md:w-[18px] md:h-[18px]',
)}
/>
))}
</div>
<p className='text-[10px] leading-[140%] text-gray-500 mt-[10px] md:custom-text-xs-regular'>
{name}
</p>
</div>
</div>
</Link>
);
}
120 changes: 120 additions & 0 deletions src/components/common/winelist/WineFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import SearchButton from '@/assets/icons/SearchButton.svg';
import WineTypeFilter from '@/components/common/Filter/WineTypeFilter';
import Input from '@/components/common/Input';
import WineListCard from '@/components/common/winelist/WineListCard';
import { Button } from '@/components/ui/button';

export default function WineFilter() {
// const [isFilterOpen, setIsFilterOpen] = useState(false);

return (
<div className='w-full max-w-[1140px] mx-auto'>
{/* PC: ํ•„ํ„ฐ + ๊ฒ€์ƒ‰์ฐฝ + ๋“ฑ๋ก ๋ฒ„ํŠผ */}
<div className='hidden xl:flex max-w-[1140px] mx-auto mt-[30px] gap-[24px]'>
<div className='flex-shrink-0 w-[260px] h-auto flex flex-col gap-[50px] ml-[-28px]'>
<div className='pt-[70px] '>
<WineTypeFilter className='h-[450px]' />
</div>
<Button
variant='purpleDark'
size='md'
width={null}
className='ml-[30px] mb-[200px] w-[284px]'
>
์™€์ธ ๋“ฑ๋กํ•˜๊ธฐ
</Button>
</div>

<div className='flex-1 flex flex-col items-end gap-[18px] text-gray-500 [&_label]:top-[10px] md:[&_label]:top-[14px] xl:[&_label]:top-[14px]'>
<Input
id='wine-search'
type='text'
placeholder='์™€์ธ์„ ๊ฒ€์ƒ‰ํ•ด ๋ณด์„ธ์š”'
variant='search'
className='
xl:w-[800px] h-[48px] px-[20px] py-[14px] pl-[55px]
border border-gray-300 rounded-full
'
/>
{/* WineListCard PC์—์„œ๋งŒ ๋…ธ์ถœ */}
<div className='hidden xl:flex pt-[20px]'>
<WineListCard />
</div>
</div>
</div>

{/* Tablet: ํ•„ํ„ฐ ๋ฒ„ํŠผ + ๊ฒ€์ƒ‰์ฐฝ + ๋“ฑ๋ก ๋ฒ„ํŠผ */}
<div className='hidden md:flex xl:hidden flex-row items-center px-[20px] mt-[24px] md:mt-[50px] md:mb-[80px]'>
<Button
// onClick={() => setIsFilterOpen(true)}
variant='white'
size={null}
width={null}
className='flex items-center justify-center border border-gray-300 w-[48px] h-[48px] rounded-[8px] p-0'
>
<SearchButton className='w-[20px] h-[20px] text-gray-500' />
</Button>

<div className='flex-grow ml-[24px] text-gray-500 [&_label]:top-[14px]'>
<Input
id='wine-search'
type='text'
placeholder='์™€์ธ์„ ๊ฒ€์ƒ‰ํ•ด ๋ณด์„ธ์š”'
variant='search'
className='
md:w-full w-full
h-[48px] px-[20px] py-[14px] pl-[55px]
border border-gray-300 rounded-full
'
/>
</div>

<Button
variant='purpleDark'
size={null}
width={null}
className='w-[220px] h-[48px] rounded-[16px] flex-shrink-0 ml-[16px]'
>
์™€์ธ ๋“ฑ๋กํ•˜๊ธฐ
</Button>
</div>

{/* Mobile: ๊ฒ€์ƒ‰์ฐฝ + ํ•„ํ„ฐ ๋ฒ„ํŠผ */}
<div className='flex flex-col md:hidden gap-[8px] px-[16px] mt-[24px]'>
<div className='text-gray-500 [&_label]:top-[10px]'>
<Input
id='wine-search'
type='text'
placeholder='์™€์ธ์„ ๊ฒ€์ƒ‰ํ•ด ๋ณด์„ธ์š”'
variant='search'
className='w-full h-[38px] px-[15px] py-[14px] pl-[55px] border border-gray-300 rounded-full'
/>
</div>

<div className='w-fit mt-[15px] mb-[20px]'>
<Button
// onClick={() => setIsFilterOpen(true)}
variant='white'
size='sm'
width='xs'
className='flex items-center justify-center border border-gray-300 w-[38px] h-[38px] p-0'
>
<SearchButton className='w-[20px] h-[20px] text-gray-500' />
</Button>
</div>
</div>

{/* Mobile: ํ•˜๋‹จ ๊ณ ์ • ๋“ฑ๋ก ๋ฒ„ํŠผ */}
<div className='fixed bottom-[20px] left-0 right-0 z-10 px-[16px] md:hidden'>
<Button
variant='purpleDark'
size='sm'
width='full'
className='w-full h-[48px] rounded-[12px] text-sm'
>
์™€์ธ ๋“ฑ๋กํ•˜๊ธฐ
</Button>
</div>
</div>
);
}
190 changes: 190 additions & 0 deletions src/components/common/winelist/WineListCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import Link from 'next/link';

import NextIcon from '@/assets/icons/Next.svg';
import StarIcon from '@/assets/icons/Star.svg';
import { ImageCard } from '@/components/common/card/ImageCard';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';

const mockWines = [
{
id: 1,
name: 'Sentinel Carbernet Sauvignon 2016',
region: 'Western Cape, South Africa',
image: '/images/image1.svg',
price: 64900,
rating: 4.8,
review:
'Cherry, cocoa, vanilla and clove - beautiful red fruit driven Amarone. Low acidity and medium tannins. Nice long velvety finish.',
},
{
id: 2,
name: 'Palazzo della Torre 2017',
region: 'Western Cape, South Africa',
image: '/images/image3.svg',
price: 64900,
rating: 4.6,
review:
'Cherry, cocoa, vanilla and clove - beautiful red fruit driven Amarone. Low acidity and medium tannins. Nice long velvety finish.',
},
{
id: 3,
name: 'Sentinel Carbernet Sauvignon 2016',
region: 'Western Cape, South Africa',
image: '/images/image2.svg',
price: 59900,
rating: 4.6,
review:
'Cherry, cocoa, vanilla and clove - beautiful red fruit driven Amarone. Low acidity and medium tannins. Nice long velvety finish.',
},
{
id: 4,
name: 'Palazzo della Torre 2017',
region: 'Western Cape, South Africa',
image: '/images/image4.svg',
price: 74000,
rating: 3.1,
review:
'Cherry, cocoa, vanilla and clove - beautiful red fruit driven Amarone. Low acidity and medium tannins. Nice long velvety finish.',
},
];

export default function WineListCard() {
return (
Copy link
Collaborator

@626-ju 626-ju Jul 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ด๋Ÿฐ ์‹์œผ๋กœ ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์—ˆ๊ตฐ์š”?
๋ถ„๋ช… ๊ฐ ๋ทฐํฌํŠธ ๋ณ„๋กœ ๋‚˜๋ˆ ์„œ ๋ณด๊ธฐ์—” ํŽธํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ
์ด๋ ‡๊ฒŒ ํ•˜๋Š” ์‚ฌ๋ก€๋ฅผ ๊ฑฐ์˜ ๋ณธ ์ ์ด ์—†์–ด์„œ ์ €๋„ ์ฐพ์•„๋ณด๋‹ˆ

1.์Šคํฌ๋ฆฐ ๋ฆฌ๋”๊ธฐ๋‚˜ ํฌ๋กค๋Ÿฌ ๋ด‡์—๊ฒŒ ํ˜ผ๋ž€์„ ์ค„ ์ˆ˜ ์žˆ์Œ.
2. ์ˆ˜์ •์ด ํ•„์š”ํ•  ๋•Œ ์—ฌ๋Ÿฌ ๊ณณ์„ ํ•˜๋‚˜ํ•˜๋‚˜ ์ฐพ์•„์•ผ ํ•จ.
+์ˆ˜์ •์ด ํ•„์š”ํ•œ๋ฐ, ๋ˆ„๋ฝ์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ . +๋””๋ฒ„๊น…์˜ ์–ด๋ ค์›€

3.ํžˆ๋“ ์ด์—ฌ๋„ ๋”ํŠธ๋ฆฌ์—๋Š” ๊ทธ๋Œ€๋กœ ๋‚จ์•„์žˆ์œผ๋‹ˆ๊นŒ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค ๋‚ญ๋น„.

๋“ฑ์˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๊ตฌ์š”

๊ทธ๋ž˜๋„ ์˜ค๋Š˜ ๋ดค์„ ๋•Œ ui์ƒ์œผ๋กœ ํฌ๊ฒŒ ์ด์ƒํ•œ๊ฑด ์—†์—ˆ์œผ๋‹ˆ ์ง„ํ–‰์„ ํ•˜๊ตฌ,
์œ„์—์„œ ๋งํ•œ ์ ๋“ค์ด ์‹ ๊ฒฝ ์“ฐ์ด์‹ ๋‹ค๋ฉด ๋‹ค์Œ์— ์‹œ๊ฐ„ ๋‚จ์„ ๋•Œ ๊ฐœ์ธ์ ์œผ๋กœ ์ˆ˜์ •ํ•ด๋ณด์‹œ๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋„ค์š”!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๋ฉ”๋ชจํ•ด๋†“๊ฒ ์Šต๋‹ˆ๋‹ค!

<div className='flex flex-col gap-[24px] px-[16px] mt-[12px] min-w-[370px] md:px-[20px] md:mt-[24px] xl:px-0 max-w-[1140px] mx-auto xl:max-w-[800px]'>
{mockWines.map((wine) => (
<Link href={`/wines/${wine.id}`} key={wine.id} className='no-underline'>
{/* ์นด๋“œ ์ปจํ…Œ์ด๋„ˆ */}
<div className='w-full bg-white border border-gray-300 rounded-xl flex flex-col relative min-w-[320px]'>
<ImageCard
imageSrc={wine.image}
className='pt-[20px] pb-0 border-none md:pl-[30px]'
imageClassName={cn(
'block object-contain rounded-md',
'w-[60px] h-[208px] mt-[30px] min-w-[50px] min-h-[180px]',
'md:min-w-0 md:min-h-0',
'md:w-[70px] md:h-[210px] md:ml-[10px] md:mt-[30px]',
'xl:w-[60px] xl:h-[205px] xl:ml-[25px] xl:mt-[30x] xl:mr-[20px]',
)}
rightSlot={null}
>
<div className='flex flex-col w-full px-[16px] md:px-0'>
{/* name, region, price ๋ฒ„ํŠผ */}
<div
className='flex flex-col w-full ml-0 mt-[20px] gap-[8px]
md:w-[300px] md:ml-[36px] md:gap-[10px]'
>
<div
className='custom-text-xl-semibold text-gray-800 leading-[32px] h-auto
break-words max-w-[220px] mt-[5px] md:custom-text-3xl-semibold md:max-w-none'
>
{wine.name}
</div>
<div
className='custom-text-md-regular text-gray-500 leading-[24px] h-[24px]
md:text-[16px] md:leading-[26px] md:h-[26px] break-words'
>
{wine.region}
</div>
<Button
variant='purpleLight'
fontSize={null}
width={null}
size={null}
className='
text-[14px] text-purpleDark font-bold leading-[24px]
px-[10px] py-[2px] rounded-[10px] h-[30px]
w-full max-w-[86px] md:max-w-[114px]
md:text-[18px]
md:px-[2px] md:py-[2px]
md:rounded-[12px]
md:w-[114px] md:h-[42px] md:mt-[5px]'
>
โ‚ฉ {wine.price.toLocaleString()}
</Button>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ €๋Š” Badge ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉํ•˜๋Š” ๊ฑธ๋กœ ์•Œ๊ณ ์žˆ๋Š”๋ฐ ์•„๋‹๊นŒ์š”!?!? ์™œ ๋ฒ„ํŠผ์ธ์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค! ๋”ฐ๋กœ ๋กœ์ง์ด ์žˆ์„๊นŒ์š”?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.... ์™œ๊ทธ๋žฌ์„๊นŒ์š”. ์ด๊ฑฐ ๋‹ค์‹œ ํ™•์ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
๋ง์”€ํ•ด์ฃผ์‹ ๋Œ€๋กœ Badge ๋งž์Šต๋‹ˆ๋‹ค

</div>

{/* ๋ชจ๋ฐ”์ผ์šฉ rating */}
<div
className='flex flex-row items-start mt-[23px] w-full ml-0 gap-[6px]
md:hidden'
>
<div className='text-[28px] font-extrabold text-gray-800 w-auto h-auto'>
{wine.rating.toFixed(1)}
</div>
<div className='flex flex-col gap-[5px] ml-[15px] w-[100px] h-auto mt-[-6px]'>
<div className='flex gap-[4px] flex-nowrap'>
{Array.from({ length: 5 }).map((_, i) => (
<StarIcon
key={i}
className={cn(
wine.rating >= i + 1 ? 'fill-purpleDark' : 'fill-gray-300',
'w-3 h-3',
)}
/>
))}
</div>
<div className='custom-text-xs-regular text-gray-500 break-words'>
47๊ฐœ์˜ ํ›„๊ธฐ
</div>
</div>
</div>

{/* ๋ชจ๋ฐ”์ผ์šฉ NextIcon */}
<div className='flex-grow md:hidden flex justify-end items-center px-[16px] pr-[10px] mt-[-35px]'>
<button type='button' className='w-[36px] h-[36px] p-[4px] rounded'>
<NextIcon className='w-full h-full text-gray-300 hover:text-gray-500' />
</button>
</div>
</div>
</ImageCard>

{/* ํƒœ๋ธ”๋ฆฟ/PC์šฉ rating */}
<div className='hidden md:flex flex-col items-start absolute top-[40px] right-[-10px] z-10'>
<div className='text-[48px] font-extrabold text-gray-800 leading-[48px] md:mt-[9px]'>
{wine.rating.toFixed(1)}
</div>
<div className='flex flex-col gap-[5px] w-[160px] mt-[15px] items-start'>
<div className='flex gap-[4px] flex-nowrap'>
{Array.from({ length: 5 }).map((_, i) => (
<StarIcon
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋ชจ๋ฐ”์ผ๊ณผ PC์—์„œ ๋ณ„์  UI๋ฅผ ๋”ฐ๋กœ ๋ Œ๋”๋งํ•˜๊ณ  ๊ณ„์‹  ๊ฒƒ ๊ฐ™์•„์š”!

์Šคํƒ€์ผ๊ณผ ์œ„์น˜ ๋•Œ๋ฌธ์— ๋ ˆ์ด์•„์›ƒ์„ ๋‹ค๋ฅด๊ฒŒ ๊ตฌ์„ฑํ•˜์‹  ๊ฑฐ๋ผ๋ฉด ํ˜„์žฌ ๋ฐฉ์‹๋„ ๊ดœ์ฐฎ์ง€๋งŒ
๋ณ„์  ๋ Œ๋”๋ง ๋ถ€๋ถ„์€ ๋กœ์ง์ด ๋™์ผํ•˜๋ฏ€๋กœ ํ•จ์ˆ˜๋กœ ์ถ”์ถœํ•ด์„œ ์ค‘๋ณต์„ ์ค„์ด๋Š” ๋ฐฉ๋ฒ•๋„ ๊ณ ๋ คํ•ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค

์˜ˆ์‹œ๋กœ ์ œ์•ˆ๋“œ๋ฆฌ์ž๋ฉด:

  1. ์ž‘์„ฑํ•˜์‹  ์ฝ”๋“œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ชจ๋ฐ”์ผ/pc ๋ณ„๋กœ ๋ ˆ์ด์•„์›ƒ์€ ๋‚˜๋ˆ„๋˜, ์ค‘๋ณต ์ œ๊ฑฐ๋ฅผ ์œ„ํ•ด ๋ณ„ ๋ Œ๋”๋ง ํ•จ์ˆ˜๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค๊ธฐ

์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค

// ๋ณ„ ๋ Œ๋”๋ง ํ•จ์ˆ˜
function renderStars(rating: number, size: 'sm' | 'md') {
  const starSizeClass = size === 'sm' ? 'w-3 h-3' : 'w-[16px] h-[16px]';

  return (
    <div className='flex gap-[4px] flex-nowrap'>
      {Array.from({ length: 5 }).map((_, i) => (
        <StarIcon
          key={i}
          className={cn(
            rating >= i + 1 ? 'fill-purpleDark' : 'fill-gray-300',
            starSizeClass,
          )}
        />
      ))}
    </div>
  );
}

{/* ๋ชจ๋ฐ”์ผ์—์„œ๋Š” */}
{renderStars(wine.rating, 'sm')}

{/* PC์—์„œ๋Š” */}
{renderStars(wine.rating, 'md')}

์ด๋ ‡๊ฒŒ ๊ตฌ์„ฑํ•˜์‹œ๋ฉด ๋ณ„์  ๊ด€๋ จ ์ˆ˜์ •์ด ํ•„์š”ํ•  ๋•Œ๋„ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํ›จ์”ฌ ํŽธํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
ํ˜น์‹œ ๋ณ„๋„๋กœ ๋ถ„๊ธฐํ•˜์‹  ๋‹ค๋ฅธ ์ด์œ ๊ฐ€ ์žˆ์œผ์‹ค๊นŒ์š”??

์ฐธ๊ณ ๋กœ ์„ฑ์ฃผ๋‹˜๊ป˜์„œ ์ž‘์„ฑํ•˜์‹  wine.detail์—๋„ ๋ณ„์  ๊ด€๋ จ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์œผ๋‹ˆ ํ•œ๋ฒˆ ํ™•์ธํ•ด๋ณด์…”๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

key={i}
className={cn(
wine.rating >= i + 1 ? 'fill-purpleDark' : 'fill-gray-300',
'w-[16px] h-[16px]',
)}
/>
))}
</div>
<div className='custom-text-sm-regular text-gray-500 break-words w-[100px] text-left mt-[7px]'>
47๊ฐœ์˜ ํ›„๊ธฐ
</div>
</div>
</div>

{/* ํƒœ๋ธ”๋ฆฟ/PC์šฉ NextIcon */}
<button
type='button'
className='w-[40px] h-[40px] p-[4px] rounded flex-shrink-0 ml-0 hidden md:block absolute top-[185px] right-[50px] z-20'
>
<NextIcon className='w-full h-full text-gray-300 hover:text-gray-500' />
</button>

{/* ๊ตฌ๋ถ„์„  */}
<div className='w-full h-px bg-gray-300 mt-[-1px]' />

{/* ํ›„๊ธฐ ์˜์—ญ */}
<div className='px-[16px] py-[20px]'>
<div className='text-[14px] font-semibold text-gray-800 mb-[4px] break-words'>
์ตœ์‹  ํ›„๊ธฐ
</div>
<div className='text-[14px] text-gray-500 leading-[24px] break-words'>
{wine.review}
</div>
</div>
</div>
</Link>
))}
</div>
);
}
Loading
Loading