diff --git a/src/api/noticeApi.ts b/src/api/noticeApi.ts index fa2d0dfb..cacc72cb 100644 --- a/src/api/noticeApi.ts +++ b/src/api/noticeApi.ts @@ -1,6 +1,12 @@ +import api from './api'; +import { AxiosError } from 'axios'; import type { ApplicationItem } from './applicationApi'; import type { ShopInfo } from './shopApi'; +interface ErrorMessage { + message: string; +} + // Link (공통 링크 타입) export interface LinkInfo { rel: string; @@ -20,19 +26,36 @@ export interface NoticeItem { } // shop 포함된 확장형 Notice (리스트, 등록, 수정에 사용) -export interface NoticeWithShopItem extends NoticeItem { +export interface NoticeShopItem extends NoticeItem { shop: ShopInfo; } // application까지 포함된 상세형 Notice (상세 조회 시 사용) -export interface NoticeDetailItem extends NoticeWithShopItem { +export interface NoticeDetailItem extends NoticeShopItem { currentUserApplication?: { item: ApplicationItem; }; } -// GET /notices 공고 조회 -// Response +export interface NoticeInfo { + item: NoticeItem; + links: LinkInfo[]; +} + +// POST /shops/{shop_id}/notices 공고 등록 - Response +// PUT /shops/{shop_id}/notices/{notice_id} 특정 공고 수정 - Response +export interface NoticeShopInfo { + item: NoticeShopItem; + links: LinkInfo[]; +} + +// GET /shops/{shop_id}/notices/{notice_id} 가게의 특정 공고 조회 - Response +export interface NoticeDetailInfo { + item: NoticeDetailItem; + links: LinkInfo[]; +} + +// GET /notices 공고 조회 - Response export interface GetNoticesResponse { offset: number; limit: number; @@ -40,30 +63,22 @@ export interface GetNoticesResponse { hasNext: boolean; address: string[]; keyword?: string; - items: { - item: NoticeWithShopItem; - links: LinkInfo[]; - }[]; + items: NoticeShopInfo[]; links: LinkInfo[]; } -// GET /shops/{shop_id}/notices 가게별 공고 조회 -// Response +// GET /shops/{shop_id}/notices 가게별 공고 조회 - Response export interface GetShopNoticesResponse { offset: number; limit: number; count: number; hasNext: boolean; - items: { - item: NoticeItem; - links: LinkInfo[]; - }[]; + items: NoticeInfo[]; links: LinkInfo[]; } -// POST /shops/{shop_id}/notices 공고 등록 -// PUT /shops/{shop_id}/notices/{notice_id} 특정 공고 수정 -// Request Body +// POST /shops/{shop_id}/notices 공고 등록 - Request Body +// PUT /shops/{shop_id}/notices/{notice_id} 특정 공고 수정 - Request Body export interface NoticeUpsertRequest { hourlyPay: number; startsAt: string; @@ -71,15 +86,118 @@ export interface NoticeUpsertRequest { description: string; } -// Response -export interface NoticeUpsertResponse { - item: NoticeWithShopItem; - links: LinkInfo[]; -} +// GET /notices 공고 조회 +export const getNotices = async (query?: { + offset?: number; + limit?: number; + address?: string; + keyword?: string; + startsAtGte?: string; + hourlyPayGte?: number; + sort?: 'time' | 'pay' | 'hour' | 'shop'; +}): Promise => { + try { + const newQuery = new URLSearchParams({ + ...query, + offset: String(query?.offset ?? ''), + limit: String(query?.limit ?? ''), + hourlyPayGte: String(query?.hourlyPayGte ?? ''), + }); + const response = await api.get(`/notices?${newQuery}`); + return response.data; + } catch (error) { + const axiosError = error as AxiosError; // 에러 타입 명시 + if (axiosError.response) { + throw new Error(axiosError.response.data.message); + } else { + throw new Error('서버에 연결할 수 없습니다. 인터넷 연결을 확인해주세요.'); + } + } +}; + +// GET /shops/{shop_id}/notices 가게별 공고 조회 +export const getShopNotices = async ( + shopId: string, + query?: { offset?: number; limit?: number }, +): Promise => { + try { + const newQuery = new URLSearchParams({ + offset: String(query?.offset ?? ''), + limit: String(query?.limit ?? ''), + }); + const response = await api.get( + `/shops/${shopId}/notices?${newQuery}`, + ); + return response.data; + } catch (error) { + const axiosError = error as AxiosError; // 에러 타입 명시 + if (axiosError.response) { + throw new Error(axiosError.response.data.message); + } else { + throw new Error('서버에 연결할 수 없습니다. 인터넷 연결을 확인해주세요.'); + } + } +}; + +// POST /shops/{shop_id}/notices 공고 등록 +export const postShopNotice = async ( + shopId: string, + body: NoticeUpsertRequest, +): Promise => { + try { + const response = await api.post( + `/shops/${shopId}/notices`, + body, + ); + return response.data; + } catch (error) { + const axiosError = error as AxiosError; // 에러 타입 명시 + if (axiosError.response) { + throw new Error(axiosError.response.data.message); + } else { + throw new Error('서버에 연결할 수 없습니다. 인터넷 연결을 확인해주세요.'); + } + } +}; // GET /shops/{shop_id}/notices/{notice_id} 가게의 특정 공고 조회 -// Response -export interface GetNoticeDetailResponse { - item: NoticeDetailItem; - links: LinkInfo[]; -} +export const getShopNotice = async ( + shopId: string, + noticeId: string, +): Promise => { + try { + const response = await api.get( + `/shops/${shopId}/notices/${noticeId}`, + ); + return response.data; + } catch (error) { + const axiosError = error as AxiosError; // 에러 타입 명시 + if (axiosError.response) { + throw new Error(axiosError.response.data.message); + } else { + throw new Error('서버에 연결할 수 없습니다. 인터넷 연결을 확인해주세요.'); + } + } +}; + +// PUT /shops/{shop_id}/notices/{notice_id} 특정 공고 수정 +export const putShopNotice = async ( + shopId: string, + noticeId: string, + body: NoticeUpsertRequest, +): Promise => { + try { + const response = await api.put( + `/shops/${shopId}/notices/${noticeId}`, + body, + ); + return response.data; + } catch (error) { + const axiosError = error as AxiosError; // 에러 타입 명시 + if (axiosError.response) { + throw new Error(axiosError.response.data.message); + } else { + throw new Error('서버에 연결할 수 없습니다. 인터넷 연결을 확인해주세요.'); + } + } +}; diff --git a/src/components/common/Post.tsx b/src/components/common/Post.tsx index b2995d90..f58ede8e 100644 --- a/src/components/common/Post.tsx +++ b/src/components/common/Post.tsx @@ -9,7 +9,7 @@ import ArrowUpRed40 from '@/assets/icons/arrow-up-red40.svg'; import ArrowUpRed30 from '@/assets/icons/arrow-up-red30.svg'; import ArrowUpRed20 from '@/assets/icons/arrow-up-red20.svg'; import PostImg from '@/assets/images/post-default.png'; -import type { NoticeWithShopItem } from '@/api/noticeApi'; +import type { NoticeShopItem } from '@/api/noticeApi'; // 상태 계산 function getStatus( @@ -24,7 +24,7 @@ function getStatus( return 'ACTIVE'; } -export default function Post({ data }: { data: NoticeWithShopItem }) { +export default function Post({ data }: { data: NoticeShopItem }) { const { hourlyPay, workhour,