+
{timeRange}
@@ -77,11 +96,11 @@ export default function PostCard({
식당
)}
{isShopInfo &&
{name}
}
-
+
{address1}
-
+
{description}
diff --git a/src/constants/router.ts b/src/constants/router.ts
index cadfff7..2446bc3 100644
--- a/src/constants/router.ts
+++ b/src/constants/router.ts
@@ -18,8 +18,8 @@ const ROUTES = {
REGISTER: "/notice/register",
EDIT: "/notice/edit",
NOTICE_ID: {
- EMPLOYER: `/notice/:noticeId/employer`,
- EMPLOYEE: `/notice/:noticeId/employee`,
+ EMPLOYER: `/notice/:shopId/:noticeId/employer`,
+ EMPLOYEE: `/notice/:shopId/:noticeId/employee`,
},
},
} as const;
diff --git a/src/pages/NoticeEmployeePage.tsx b/src/pages/NoticeEmployeePage.tsx
deleted file mode 100644
index cd723f4..0000000
--- a/src/pages/NoticeEmployeePage.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function NoticeEmployeePage() {
- return
NoticeEmployeePage
;
-}
diff --git a/src/pages/NoticeEmployeePage/NoticeEmployeePage.tsx b/src/pages/NoticeEmployeePage/NoticeEmployeePage.tsx
new file mode 100644
index 0000000..0231b57
--- /dev/null
+++ b/src/pages/NoticeEmployeePage/NoticeEmployeePage.tsx
@@ -0,0 +1,34 @@
+import { useLoaderData, useParams } from "react-router-dom";
+
+import NoticeDetailInfo from "./components/NoticeDetailInfo";
+
+import PostList from "@/components/Post/PostList";
+
+export default function NoticeEmployeePage() {
+ const { noticeInfo, recentNotices } = useLoaderData();
+ const { shopId, noticeId } = useParams() as {
+ shopId: string;
+ noticeId: string;
+ };
+
+ return (
+ <>
+
+
+
+ >
+ );
+}
diff --git a/src/pages/NoticeEmployeePage/components/NoticeDetailInfo.tsx b/src/pages/NoticeEmployeePage/components/NoticeDetailInfo.tsx
new file mode 100644
index 0000000..b45c0be
--- /dev/null
+++ b/src/pages/NoticeEmployeePage/components/NoticeDetailInfo.tsx
@@ -0,0 +1,131 @@
+import {
+ postApplication,
+ putApplication,
+} from "@/apis/services/applicationService";
+import Button from "@/components/Button";
+import PostCard from "@/components/Post/PostCard";
+import { useToast } from "@/hooks/useToast";
+import { useModalStore } from "@/store/useModalStore";
+import { NoticeItem } from "@/types/notice";
+import { cn } from "@/utils/cn";
+import { isPastDate } from "@/utils/datetime";
+
+interface NoticeDetailInfoProps {
+ noticeInfo: NoticeItem;
+ shopId: string;
+ noticeId: string;
+}
+
+function NoticeDetailInfo({
+ shopId,
+ noticeId,
+ noticeInfo,
+}: NoticeDetailInfoProps) {
+ const { openModal } = useModalStore();
+ const { showToast } = useToast();
+
+ const {
+ hourlyPay,
+ startsAt,
+ workhour,
+ closed,
+ description,
+ currentUserApplication,
+ } = noticeInfo;
+
+ const {
+ name,
+ imageUrl,
+ address1,
+ originalHourlyPay,
+ description: shopDescription,
+ } = noticeInfo.shop!.item;
+
+ const applicationId = currentUserApplication?.item.id;
+ const applicationStatus = currentUserApplication?.item.status;
+ const isPast = isPastDate(startsAt, workhour);
+ const isDisabledNotice = isPast || closed || applicationStatus === "canceled";
+
+ const applyNotice = async () => {
+ const result = await postApplication(shopId, noticeId);
+
+ if (result.status === 201) {
+ showToast("신청 완료!");
+ }
+ };
+
+ const cancelApplication = () => {
+ openModal({
+ type: "confirm",
+ confirmText: "취소하기",
+ cancelText: "아니오",
+ iconType: "warning",
+ message: "신청을 취소하시겠어요?",
+ onConfirm: async () => {
+ const result = await putApplication(
+ shopId,
+ noticeId,
+ applicationId ?? "",
+ "canceled",
+ );
+
+ if (result.status === 200) {
+ showToast("취소가 완료 되었습니다.");
+ }
+ },
+ });
+ };
+
+ return (
+ <>
+
+
+ 식당
+
+
{name}
+
+ {noticeInfo && (
+
+ {applicationStatus === "pending" && "취소하기"}
+ {applicationStatus === "accepted" && "승낙"}
+ {applicationStatus === "rejected" && "지원 거절"}
+ {applicationStatus === "canceled" &&
+ "이미 취소한 지원 공고 입니다."}
+ {!applicationStatus && isDisabledNotice && "신청 불가"}
+ {!applicationStatus && !closed && !isPast && "지원하기"}
+
+ }
+ />
+ )}
+
+
공고 설명
+
{description}
+
+ >
+ );
+}
+
+export default NoticeDetailInfo;
diff --git a/src/pages/NoticeEmployeePage/components/ShopInfoPostCardSkeleton.tsx b/src/pages/NoticeEmployeePage/components/ShopInfoPostCardSkeleton.tsx
new file mode 100644
index 0000000..b1d66ed
--- /dev/null
+++ b/src/pages/NoticeEmployeePage/components/ShopInfoPostCardSkeleton.tsx
@@ -0,0 +1,52 @@
+import { Location, Time } from "@/assets/icon";
+
+function ShopInfoPostCardSkeleton() {
+ return (
+
+
+
+
+ 식당
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default ShopInfoPostCardSkeleton;
diff --git a/src/pages/NoticeEmployeePage/loader/noticeEmployeeLoader.ts b/src/pages/NoticeEmployeePage/loader/noticeEmployeeLoader.ts
new file mode 100644
index 0000000..a25318f
--- /dev/null
+++ b/src/pages/NoticeEmployeePage/loader/noticeEmployeeLoader.ts
@@ -0,0 +1,53 @@
+import { LoaderFunction } from "react-router-dom";
+
+import { getNotice, getNotices } from "@/apis/services/noticeService";
+
+interface LoadNoticeParams {
+ shopId: string;
+ noticeId: string;
+}
+
+const loadNotice = async ({ shopId, noticeId }: LoadNoticeParams) => {
+ const noticeResult = await getNotice(shopId, noticeId);
+
+ if (noticeResult.status === 200) {
+ return noticeResult.data.item;
+ }
+};
+
+const loadRecentNotices = async () => {
+ const recentNoticesResult = await getNotices({ sort: "hour", limit: 6 });
+
+ if (recentNoticesResult.status === 200) {
+ const recentNotices = recentNoticesResult.data.items.map(({ item }) => ({
+ id: item.id,
+ name: item.shop?.item.name ?? "",
+ imageUrl: item.shop?.item.imageUrl ?? "",
+ address1: item.shop?.item.address1 ?? "",
+ originalHourlyPay: item.shop?.item.originalHourlyPay ?? 0,
+ link: `/notice/${item.shop?.item.id}/${item.id}/employee`,
+ hourlyPay: item.hourlyPay,
+ startsAt: item.startsAt,
+ workhour: item.workhour,
+ closed: item.closed,
+ }));
+
+ return recentNotices;
+ }
+};
+
+const noticeEmployeeLoader: LoaderFunction = async ({ params }) => {
+ const { shopId, noticeId } = params as {
+ shopId: string;
+ noticeId: string;
+ };
+
+ const [noticeInfo, recentNotices] = await Promise.all([
+ loadNotice({ shopId, noticeId }),
+ loadRecentNotices(),
+ ]);
+
+ return { noticeInfo, recentNotices };
+};
+
+export default noticeEmployeeLoader;