Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions src/assets/icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Active from "./active.svg?react";
import ArrowLeft from "./arrow-left.svg?react";
import ArrowRight from "./arrow-right.svg?react";
import ArrowUp from "./arrow-up.svg?react";
import ArrowUpBold from "./arrow-up-bold.svg?react";
import Camera from "./camera.svg?react";
import Check from "./check.svg?react";
import Close from "./close.svg?react";
Expand All @@ -16,6 +17,7 @@ import Time from "./time.svg?react";

export {
ArrowUp,
ArrowUpBold,
ArrowLeft,
ArrowRight,
Close,
Expand Down
29 changes: 6 additions & 23 deletions src/components/Post/Post.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,8 @@
import { cn } from "@/utils/cn";
import { Link } from "react-router-dom";
import { formatTimeRange, isPastDate } from "@/utils/datetime";
import IconTime from "@/assets/icon/time.svg?react";
import IconLocation from "@/assets/icon/location.svg?react";
import IconArrow from "@/assets/icon/arrow-up.svg?react";
import IconArrowBold from "@/assets/icon/arrow-up-bold.svg?react";

const getPayRateText = (
hourlyPay: number,
originalPay: number,
): {
rawRate: number;
displayRate: number;
rateText: string;
} => {
const rawRate = ((hourlyPay - originalPay) / originalPay) * 100;
const displayRate = Math.min(Math.round(rawRate), 100);
const rateText = `기존 시급보다 ${displayRate}%`;

return { rawRate, displayRate, rateText };
};
import { getPayRateText } from "@/utils/payRate";
import { Location, Time, ArrowUp, ArrowUpBold } from "@/assets/icon";

interface PostProps {
name: string;
Expand Down Expand Up @@ -76,11 +59,11 @@ export default function Post({
<div className="mt-3 flex flex-col gap-2 md:mt-5">
<h3 className="text-base md:text-xl">{name}</h3>
<p className="flex items-start gap-[6px] text-xs font-normal text-gray-50 md:text-[14px] md:leading-[22px]">
<IconTime className="h-4 w-4 md:h-5 md:w-5" />
<Time className="h-4 w-4 md:h-5 md:w-5" />
{timeRange}
</p>
<p className="flex items-start gap-[6px] text-xs font-normal text-gray-50 md:text-[14px] md:leading-[22px]">
<IconLocation className="h-4 w-4 md:h-5 md:w-5" />
<Location className="h-4 w-4 md:h-5 md:w-5" />
{address1}
</p>
</div>
Expand All @@ -102,8 +85,8 @@ export default function Post({
)}
>
{rateText}
<IconArrow className="hidden h-5 w-5 md:block" />
<IconArrowBold className="h-4 w-4 md:hidden" />
<ArrowUp className="hidden h-5 w-5 md:block" />
<ArrowUpBold className="h-4 w-4 md:hidden" />
</span>
)}
</div>
Expand Down
92 changes: 92 additions & 0 deletions src/components/Post/PostCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { cn } from "@/utils/cn";
import { formatTimeRange } from "@/utils/datetime";
import { getPayRateText } from "@/utils/payRate";
import { Location, Time, ArrowUp } from "@/assets/icon";

interface PostCardProps {
name: string;
imageUrl: string;
address1: string;
description: string;
originalHourlyPay?: number;
hourlyPay?: number;
startsAt?: string;
workhour?: number;
isShopInfo?: boolean;
backgroundColor?: string;
buttons?: React.ReactNode;
}

export default function PostCard({
name,
imageUrl,
address1,
description,
hourlyPay,
originalHourlyPay,
startsAt,
workhour,
isShopInfo = false,
backgroundColor = "#ffffff",
buttons = null,
}: PostCardProps) {
const { rateText } = getPayRateText(hourlyPay, originalHourlyPay);

const timeRange =
startsAt && workhour !== undefined
? formatTimeRange(startsAt, workhour)
: "";

return (
<article
className={cn(
"grid p-5 md:p-6 lg:grid-cols-[1fr_346px] lg:gap-[31px] rounded-2xl",
backgroundColor,
backgroundColor === "#ffffff" && "border border-gray-20 shadow-sm",
)}
>
<div className="w-full overflow-hidden rounded-xl">
<img
src={imageUrl}
alt={name}
className="w-full h-[180px] object-cover md:h-[360px] lg:h-[308px]"
/>
</div>
<div className="flex flex-col justify-between mt-3 h-[251px] md:mt-4 md:h-[252px] lg:h-[292px]">
<div className="space-y-2 md:space-y-3">
{!isShopInfo ? (
<>
<div className="flex flex-col gap-[2px]">
<p className="text-primary body2-bold md:body1-bold">시급</p>
<div className="flex items-center gap-2">
<h2 className="text-[20px] font-bold md:text-[28px]">
{hourlyPay?.toLocaleString()}원
</h2>
<span className="inline-flex items-center gap-[2px] rounded-[20px] bg-primary px-3 py-1 text-[12px] font-normal leading-[16px] text-white md:body2-bold">
{rateText}
<ArrowUp className="w-4 h-4 md:w-5 md:h-5" />
</span>
</div>
</div>
<div className="flex items-center gap-[6px] text-gray-50 body2-regular md:body1-regular">
<Time className="w-4 h-4 md:w-5 md:h-5" />
{timeRange}
</div>
</>
) : (
<p className="text-primary body2-bold md:body1-bold">식당</p>
)}
{isShopInfo && <h2 className="text-[28px] font-bold">{name}</h2>}
<div className="flex items-center gap-[6px] text-gray-50 body2-regular md:body1-regular">
<Location className="w-4 h-4 md:w-5 md:h-5" />
{address1}
</div>
<p className="text-black body2-regular md:body1-regular">
{description}
</p>
</div>
{buttons && <div className="flex gap-2 mt-3">{buttons}</div>}
</div>
</article>
);
}
4 changes: 4 additions & 0 deletions src/styles/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@
--color-green-10: #d4f7d4;
--color-green-20: #20a81e;

--color-violet: #5534da;

--color-primary: #ea3c12;

--color-kakao: #fee500;
}
28 changes: 28 additions & 0 deletions src/utils/payRate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* 시급 인상률 계산 유틸리티
* @param hourlyPay 현재 시급
* @param originalPay 기존 시급
* @returns { rawRate, displayRate, rateText }
*/
export const getPayRateText = (
hourlyPay?: number,
originalPay?: number,
): {
rawRate: number;
displayRate: number;
rateText: string;
} => {
if (hourlyPay === undefined || originalPay === undefined) {
return {
rawRate: 0,
displayRate: 0,
rateText: "",
};
}

const rawRate = ((hourlyPay - originalPay) / originalPay) * 100;
const displayRate = Math.min(Math.round(rawRate), 100);
const rateText = `기존 시급보다 ${displayRate}%`;

return { rawRate, displayRate, rateText };
};