Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
471d6b9
✨ feat: PostLarge 파일 생성
Moon-ju-young Jun 21, 2025
c7d8599
🐛 fix: NoticeDetailItem type 오류 수정
Moon-ju-young Jun 21, 2025
d56302c
✨ feat: PostLarge에 Post 컴포넌트 내용 복사
Moon-ju-young Jun 21, 2025
734dc65
🐛 fix: 뱃지 스타일 통일
Moon-ju-young Jun 21, 2025
971acae
🐛 fix: icon 색 통일
Moon-ju-young Jun 21, 2025
0554c22
♻️ refactor: icon import 이름 변경
Moon-ju-young Jun 21, 2025
83cc6c8
🐛 fix: 비활성화 스타일 변경 및 isInactive 변수 삭제
Moon-ju-young Jun 21, 2025
6ae2cf9
🎨 style: 외부 틀 스타일 변경
Moon-ju-young Jun 21, 2025
fbba521
🎨 style: 가격 위치 변경
Moon-ju-young Jun 21, 2025
a522109
🔥 remove: 가게 이름(name) 삭제
Moon-ju-young Jun 21, 2025
c1db732
🎨 style: isHigherPay 뱃지 스타일 변경
Moon-ju-young Jun 21, 2025
2473c33
🎨 style: 가격-뱃지 부분 스타일 변경
Moon-ju-young Jun 21, 2025
7d85561
🎨 style: 시간/주소 부분 스타일 변경
Moon-ju-young Jun 21, 2025
f1cad48
🎨 style: 요소 배치 변경
Moon-ju-young Jun 21, 2025
4e2d8d0
🔥 remove: 불필요 span태그 삭제
Moon-ju-young Jun 21, 2025
5bb3639
✨ feat: 시급 문구 추가
Moon-ju-young Jun 21, 2025
5a9a52b
✨ feat: shopDescription 추가
Moon-ju-young Jun 21, 2025
11e4bdf
✨ feat: noticeDescription 추가
Moon-ju-young Jun 21, 2025
e36705e
🎨 style: noticeDescription 스타일 적용
Moon-ju-young Jun 21, 2025
4d63d3c
✨ feat: className, children prop 추가
Moon-ju-young Jun 21, 2025
8c99a36
🎨 style: 공고 설명 스타일 리팩토링
Moon-ju-young Jun 21, 2025
5fae175
🎨 style: border 고려하여 padding 조정
Moon-ju-young Jun 21, 2025
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: 1 addition & 1 deletion src/api/noticeApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface NoticeShopItem extends NoticeItem {

// application까지 포함된 상세형 Notice (상세 조회 시 사용)
export interface NoticeDetailItem extends NoticeShopItem {
currentUserApplication?: {
currentUserApplication: null | {
item: ApplicationItem;
};
}
Expand Down
139 changes: 139 additions & 0 deletions src/components/common/PostLarge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import type { ReactNode } from 'react';
import formatWorkTime from '@/utils/formatWorkTime';
import ic_clock from '@/assets/icons/clock-red.svg';
import ic_location from '@/assets/icons/location-red.svg';
import ic_arrow from '@/assets/icons/arrow-up-white.svg';
import PostImg from '@/assets/images/post-default.png';
import type { NoticeDetailItem } from '@/api/noticeApi';

// 상태 계산
function getStatus(
startsAt: string,
closed: boolean,
): 'ACTIVE' | 'CLOSED' | 'EXPIRED' {
const now = new Date();
const startDate = new Date(startsAt);

if (closed) return 'CLOSED'; // 인원 다 찼으면 마감
if (now >= startDate) return 'EXPIRED'; // 기간 종료되면 마감
return 'ACTIVE';
}

export default function PostLarge({
className = '',
data,
children,
}: {
className?: string;
data: NoticeDetailItem;
children?: ReactNode;
}) {
const {
hourlyPay,
workhour,
startsAt,
closed,
description: noticeDescription,
shop: {
item: {
address1,
imageUrl,
originalHourlyPay,
description: shopDescription,
},
},
} = data;

const status = getStatus(startsAt, closed);
const overlayText =
status === 'ACTIVE' ? '' : status === 'CLOSED' ? '마감 완료' : '지난 공고';

const dateTime = `${formatWorkTime({ startsAt, workhour })} (${workhour}시간)`;

const percent = Math.floor(
((hourlyPay - originalHourlyPay) / originalHourlyPay) * 100,
);
const isHigherPay = percent > 0; // 이전 시급보다 높을 때만 표시

const background = imageUrl ?? PostImg;

let badgeBgColor = '';
if (percent >= 50) {
badgeBgColor = 'bg-red-40';
} else if (percent >= 30) {
badgeBgColor = 'bg-red-30';
} else if (percent >= 1) {
badgeBgColor = 'bg-red-20 ';
}

return (
<div className={`text-body2/22 font-regular md:text-body1/26 ${className}`}>
<div className="flex min-h-356 flex-col items-stretch justify-between rounded-xl border border-gray-20 bg-white p-19 md:p-23 lg:flex-row">
<div className="relative h-178 md:h-360 lg:h-auto lg:w-539">
<div
className="h-full w-full rounded-xl bg-cover bg-center"
style={{ backgroundImage: `url(${background})` }}
/>
{status === 'ACTIVE' || (
<div className="absolute inset-0 flex items-center justify-center rounded-xl bg-[#000000]/70 text-h3 font-bold text-gray-30 md:text-h1">
{overlayText}
</div>
)}
</div>
<div className="mt-12 flex flex-col justify-between gap-24 text-black md:mt-16 md:gap-40 lg:w-346 lg:gap-0">
<div className="flex flex-col gap-8 md:gap-12">
<div>
<div className="mb-8 leading-17 font-bold text-primary md:leading-20">
시급
</div>
<div
className="flex items-center gap-4 md:gap-8"
title={`${hourlyPay.toLocaleString()}원${isHigherPay ? `: 기존 시급보다 ${percent}%` : ''}`}
>
<div className="text-h2/29 font-bold md:text-h1/34">
{hourlyPay.toLocaleString()}원
</div>
{isHigherPay && status === 'ACTIVE' && (
<div
className={`flex h-24 items-center justify-center gap-2 rounded-full px-8 py-4 text-caption/16 text-white md:h-36 md:p-12 md:text-body2 md:font-bold ${badgeBgColor}`}
>
<div className="max-w-122 truncate">
기존 시급보다 {percent}%
</div>
<img
src={ic_arrow}
alt="위 화살표"
className="size-16 md:size-20"
/>
</div>
)}
</div>
</div>
<div className="flex items-center gap-6 text-gray-50">
<img
src={ic_clock}
alt="시계 아이콘"
className="size-16 md:size-20"
/>
{dateTime}
</div>
<div className="flex items-center gap-6 text-gray-50">
<img
src={ic_location}
alt="위치 아이콘"
className="size-16 md:size-20"
/>
{address1}
</div>
{shopDescription}
</div>
{children}
</div>
</div>
<div className="mt-12 flex flex-col gap-8 rounded-xl bg-gray-10 p-20 md:mt-24 md:gap-12 md:p-32">
<div className="leading-17 font-bold md:leading-20">공고 설명</div>
{noticeDescription}
</div>
</div>
);
}