Skip to content

Commit 7328301

Browse files
committed
feat: PostListItem 컴포넌트 생성
1 parent d150e25 commit 7328301

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import clsx from "clsx";
2+
import { formatTimeRange, isPastDate } from "@/utils/datetime";
3+
import IconTime from "@/assets/icon/time.svg";
4+
import IconLocation from "@/assets/icon/location.svg";
5+
import IconArrow from "@/assets/icon/arrow-up.svg";
6+
import IconArrowBold from "@/assets/icon/arrow-up-bold.svg";
7+
8+
const getPayRateText = (
9+
hourlyPay: number,
10+
originalPay: number,
11+
): {
12+
rawRate: number;
13+
displayRate: number;
14+
rateText: string;
15+
} => {
16+
const rawRate = ((hourlyPay - originalPay) / originalPay) * 100;
17+
const displayRate = Math.min(Math.round(rawRate), 100);
18+
const rateText = `기존 시급보다 ${displayRate}%`;
19+
20+
return { rawRate, displayRate, rateText };
21+
};
22+
23+
interface PostListItemProps {
24+
hourlyPay: number;
25+
startsAt: string;
26+
workhour: number;
27+
closed: boolean;
28+
shop: {
29+
name: string;
30+
imageUrl: string;
31+
address1: string;
32+
originalHourlyPay: number;
33+
};
34+
}
35+
36+
export default function PostListItem({
37+
hourlyPay,
38+
startsAt,
39+
workhour,
40+
closed,
41+
shop,
42+
}: PostListItemProps) {
43+
const { name, address1, imageUrl, originalHourlyPay } = shop;
44+
45+
const timeRange = formatTimeRange(startsAt, workhour);
46+
const isPast = isPastDate(startsAt, workhour);
47+
const isDimmed = closed || isPast;
48+
const { displayRate, rateText } = getPayRateText(
49+
hourlyPay,
50+
originalHourlyPay,
51+
);
52+
53+
return (
54+
<article className="relative flex w-full flex-col rounded-xl border border-gray-20 bg-white p-3 shadow-md md:p-4">
55+
<div className="relative">
56+
<div
57+
className="w-full h-[84px] overflow-hidden rounded-xl bg-cover bg-center md:h-40"
58+
style={{ backgroundImage: `url(${imageUrl})` }}
59+
/>
60+
{isDimmed && (
61+
<h3 className="absolute inset-0 flex items-center justify-center rounded-md bg-black/70 text-sm text-white md:text-[28px]">
62+
{closed ? "마감 완료" : "지난 공고"}
63+
</h3>
64+
)}
65+
</div>
66+
67+
<div className={clsx(isDimmed && "opacity-20")}>
68+
<div className="mt-3 flex flex-col gap-2 md:mt-5">
69+
<h3 className="text-base md:text-xl">{name}</h3>
70+
<p className="flex items-start gap-[6px] text-xs font-normal leading-4 text-gray-50 md:items-center md:text-[14px] md:leading-[22px]">
71+
<img src={IconTime} className="h-4 w-4 md:h-5 md:w-5" />
72+
{timeRange}
73+
</p>
74+
<p className="flex items-start gap-[6px] text-xs font-normal leading-4 text-gray-50 md:items-center md:text-[14px] md:leading-[22px]">
75+
<img src={IconLocation} className="h-4 w-4 md:h-5 md:w-5" />
76+
{address1}
77+
</p>
78+
</div>
79+
80+
<div className="mt-4 flex flex-col items-start md:flex-row md:items-center md:justify-between">
81+
<h2 className="text-lg md:text-2xl">
82+
{hourlyPay.toLocaleString()}
83+
</h2>
84+
85+
{displayRate > 0 && (
86+
<span
87+
className={clsx(
88+
"mt-[5px] flex items-center gap-[2px] text-xs font-normal text-red-40 md:text-sm md:text-white md:px-3 md:py-2 md:rounded-[20px]",
89+
{
90+
"md:bg-red-40": displayRate >= 90,
91+
"md:bg-red-30": displayRate >= 70 && displayRate < 90,
92+
"md:bg-red-20": displayRate < 70,
93+
},
94+
)}
95+
>
96+
{rateText}
97+
<img src={IconArrow} className="hidden h-5 w-5 md:block" />
98+
<img src={IconArrowBold} className="h-4 w-4 md:hidden" />
99+
</span>
100+
)}
101+
</div>
102+
</div>
103+
</article>
104+
);
105+
}

0 commit comments

Comments
 (0)