From a13f1c339d93d5ae914a594f1d7186edee62e4f5 Mon Sep 17 00:00:00 2001 From: yeaseula Date: Mon, 27 Apr 2026 15:43:05 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[seller]=20feat(173)=20:=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EB=93=B1=EB=A1=9D=20=EA=B4=80=EB=A0=A8=20entity=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=20=EA=B5=AC=ED=98=84=20(API,=20Type?= =?UTF-8?q?,=20Constants)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../products/create/create-delivery/index.ts | 2 + .../create/create-disclosure/index.ts | 2 + .../product-disclosure.constant.ts | 16 ++--- .../create/create-form/create-form.types.ts | 13 ++++ .../create-indivisual-form.type.ts | 45 +++++++++++++ .../products/create/create-form/create.api.ts | 21 ++++++ .../create/create-form/create.query.ts | 16 +++++ .../create/create-form/create.type.ts | 66 +++++++++++++++++++ .../products/create/create-form/index.ts | 10 +++ .../products/create/create-header/index.ts | 3 + .../products/create/create-info/index.ts | 2 + .../product-discount-type.constants.ts | 4 +- .../create-info/production-time.constants.ts | 47 +++++++------ .../products/create/create-options/index.ts | 7 ++ .../create-store/create-store-header.type.ts | 32 +++++++++ .../products/create/create-store/index.ts | 1 + 16 files changed, 257 insertions(+), 30 deletions(-) create mode 100644 apps/seller/src/entity/products/create/create-delivery/index.ts create mode 100644 apps/seller/src/entity/products/create/create-disclosure/index.ts create mode 100644 apps/seller/src/entity/products/create/create-form/create-form.types.ts create mode 100644 apps/seller/src/entity/products/create/create-form/create-indivisual-form.type.ts create mode 100644 apps/seller/src/entity/products/create/create-form/create.api.ts create mode 100644 apps/seller/src/entity/products/create/create-form/create.query.ts create mode 100644 apps/seller/src/entity/products/create/create-form/create.type.ts create mode 100644 apps/seller/src/entity/products/create/create-form/index.ts create mode 100644 apps/seller/src/entity/products/create/create-header/index.ts create mode 100644 apps/seller/src/entity/products/create/create-info/index.ts create mode 100644 apps/seller/src/entity/products/create/create-options/index.ts create mode 100644 apps/seller/src/entity/products/create/create-store/create-store-header.type.ts create mode 100644 apps/seller/src/entity/products/create/create-store/index.ts diff --git a/apps/seller/src/entity/products/create/create-delivery/index.ts b/apps/seller/src/entity/products/create/create-delivery/index.ts new file mode 100644 index 00000000..15986c05 --- /dev/null +++ b/apps/seller/src/entity/products/create/create-delivery/index.ts @@ -0,0 +1,2 @@ +export { DeliveryCompany } from './product-delivery-company' +export { DeliveryTerms } from './product-delivery-terms' diff --git a/apps/seller/src/entity/products/create/create-disclosure/index.ts b/apps/seller/src/entity/products/create/create-disclosure/index.ts new file mode 100644 index 00000000..d3731691 --- /dev/null +++ b/apps/seller/src/entity/products/create/create-disclosure/index.ts @@ -0,0 +1,2 @@ +export { DISCLOSURE_FIELDS, RADIO_OPTIONS } from './product-disclosure.constant' +export type { ProductInfoNoticeKey } from './product-disclosure.constant' diff --git a/apps/seller/src/entity/products/create/create-disclosure/product-disclosure.constant.ts b/apps/seller/src/entity/products/create/create-disclosure/product-disclosure.constant.ts index 70350c8e..91ede12d 100644 --- a/apps/seller/src/entity/products/create/create-disclosure/product-disclosure.constant.ts +++ b/apps/seller/src/entity/products/create/create-disclosure/product-disclosure.constant.ts @@ -5,17 +5,17 @@ export const DISCLOSURE_FIELDS = [ { label: '4. 소재지', key: 'originLocation' }, { label: '5. 제조년월일', key: 'manufactureDate' }, { label: '6. 소비기한 또는 품질 유지기한', key: 'expirationDate' }, - { label: '7. 보관방법', key: 'storageGuide' }, - { label: '8. 포장 단위 별 내용물 용량(중량) 수량', key: 'packagingContents' }, - { label: '9. 포장 단위별 수량', key: 'packagingQuantityUnit' }, + // { label: '7. 보관방법', key: 'storageGuide' }, + { label: '7. 포장 단위 별 내용물 용량(중량) 수량', key: 'packagingContents' }, + { label: '8. 포장 단위별 수량', key: 'packagingQuantityUnit' }, { - label: '10. 원재료명 (농수산물의 원산지 표시 등에 관한 법률)', + label: '9. 원재료명 (농수산물의 원산지 표시 등에 관한 법률)', key: 'rawMaterialName', }, - { label: '11. 영양성분', key: 'nutritionInfo' }, - { label: '12. 유전자 변형 식품에 해당하는 경우의 표시', key: 'transgenic' }, - { label: '13. 소비자 안전을 위한 주의사항', key: 'customerWarning' }, - { label: '14. 수입 식품의 경우', key: 'importFood' }, + { label: '10. 영양성분', key: 'nutritionInfo' }, + { label: '11. 유전자 변형 식품에 해당하는 경우의 표시', key: 'transgenic' }, + { label: '12. 소비자 안전을 위한 주의사항', key: 'customerWarning' }, + { label: '13. 수입 식품의 경우', key: 'importFood' }, ] as const export const RADIO_OPTIONS = [ diff --git a/apps/seller/src/entity/products/create/create-form/create-form.types.ts b/apps/seller/src/entity/products/create/create-form/create-form.types.ts new file mode 100644 index 00000000..2231a3c1 --- /dev/null +++ b/apps/seller/src/entity/products/create/create-form/create-form.types.ts @@ -0,0 +1,13 @@ +import { + DeliveryFormInput, + ProductDisclosureFormInput, + ProductFormInput, + ProductOptionFormInput, + ThumbnailFormInput, +} from './create-indivisual-form.type' + +export type CreateFormType = ProductFormInput & + DeliveryFormInput & { + options: ProductOptionFormInput[] // Feature의 스키마 대신 Entity의 순수 타입을 사용 + } & ProductDisclosureFormInput & + ThumbnailFormInput diff --git a/apps/seller/src/entity/products/create/create-form/create-indivisual-form.type.ts b/apps/seller/src/entity/products/create/create-form/create-indivisual-form.type.ts new file mode 100644 index 00000000..cd93376d --- /dev/null +++ b/apps/seller/src/entity/products/create/create-form/create-indivisual-form.type.ts @@ -0,0 +1,45 @@ +import { ProductInfoNoticeKey } from '../create-disclosure/product-disclosure.constant' + +export type ProductFormInput = { + productName: string + isFresh: boolean + productionTime: string + price: number | null + discountAmount: number | null + discountType: 'AMOUNT' | 'RATE' +} + +export type DeliveryFormInput = { + deliveryTerms: string + deliveryCompany: string + deliveryFee: number | null + deliveryMinFee: number | null +} + +export type ThumbnailFormInput = { + mainImage: File | null + extraImages: File[] +} + +export type ProductOptionFormInput = { + mainCategory: 'bread' | 'snack' | '' + subCategory: string + optionName: string + ingredientCategories: ('glutenFree' | 'vegan')[] + additionalPrice: number | null + stockQuantity: number | null + shippingDays: ('mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun')[] + hasNutrition: boolean + totalWeight: number | null + calories: number | null + carbohydrate: number | null + sugar: number | null + protein: number | null + fat: number | null + sodium: number | null +} + +export type ProductDisclosureFormInput = { + productInfoNotice: Record + productInfoNoticeMode: Record +} diff --git a/apps/seller/src/entity/products/create/create-form/create.api.ts b/apps/seller/src/entity/products/create/create-form/create.api.ts new file mode 100644 index 00000000..04077400 --- /dev/null +++ b/apps/seller/src/entity/products/create/create-form/create.api.ts @@ -0,0 +1,21 @@ +import { client } from '@/shared/utils/axios' + +import { ApiResponse, StoreInfo } from './create.type' + +// storeId 조회 +export const getMyStore = async () => { + const response = await client.get>( + '/api/v1/seller/stores', + ) + return response.data.result.store +} + +// 상품 등록 +export const createProduct = async (formData: FormData) => { + const response = await client.post('/api/v1/seller/boards', formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }) + return response.data +} diff --git a/apps/seller/src/entity/products/create/create-form/create.query.ts b/apps/seller/src/entity/products/create/create-form/create.query.ts new file mode 100644 index 00000000..4e86afcf --- /dev/null +++ b/apps/seller/src/entity/products/create/create-form/create.query.ts @@ -0,0 +1,16 @@ +import { queryOptions } from '@tanstack/react-query' + +import { getMyStore } from './create.api' + +export const productKeys = { + all: ['products'] as const, + myStore: () => [...productKeys.all, 'myStore'] as const, +} + +export const productQueries = { + myStore: () => + queryOptions({ + queryKey: productKeys.myStore(), + queryFn: getMyStore, + }), +} diff --git a/apps/seller/src/entity/products/create/create-form/create.type.ts b/apps/seller/src/entity/products/create/create-form/create.type.ts new file mode 100644 index 00000000..882f0f84 --- /dev/null +++ b/apps/seller/src/entity/products/create/create-form/create.type.ts @@ -0,0 +1,66 @@ +// API 요청 타입 +export interface CreateProductRequest { + storeId: number + title: string + isFresh: boolean + productionStartAt: string + price: number + discountType: 'AMOUNT' | 'RATE' + discountValue: number + deliveryCondition: string + deliveryCompany: string + deliveryFee: number + freeShippingConditions: number + content: string + products: ProductOptionRequest[] + productInfoNoticeRequest: Record +} + +export interface ProductOptionRequest { + title: string + category: string + plusPriceWithBoardPrice: number + stock: number + dietaryTags: { + glutenFreeTag: boolean + highProteinTag: boolean + sugarFreeTag: boolean + veganTag: boolean + ketogenicTag: boolean + } + availability: { + monday: boolean + tuesday: boolean + wednesday: boolean + thursday: boolean + friday: boolean + saturday: boolean + sunday: boolean + } + nutritionInfo: { + totalWeight: number + servingSize: number + carbohydrates: number + sugars: number + protein: number + fat: number + calories: number + } | null +} + +// API 응답 타입 +export interface StoreInfo { + storeId: number + name: string + introduce: string + profile: string + phoneNumber: string + email: string +} + +export interface ApiResponse { + success: boolean + code: number + message: string + result: T +} diff --git a/apps/seller/src/entity/products/create/create-form/index.ts b/apps/seller/src/entity/products/create/create-form/index.ts new file mode 100644 index 00000000..a9220c34 --- /dev/null +++ b/apps/seller/src/entity/products/create/create-form/index.ts @@ -0,0 +1,10 @@ +export * from './create-form.types' +export * from './create-indivisual-form.type' +export { getMyStore, createProduct } from './create.api' +export { productQueries, productKeys } from './create.query' +export type { + CreateProductRequest, + ProductOptionRequest, + StoreInfo, + ApiResponse, +} from './create.type' diff --git a/apps/seller/src/entity/products/create/create-header/index.ts b/apps/seller/src/entity/products/create/create-header/index.ts new file mode 100644 index 00000000..af7a350e --- /dev/null +++ b/apps/seller/src/entity/products/create/create-header/index.ts @@ -0,0 +1,3 @@ +export { CategoryOptions } from './category-options.constants' +export { EssentialOptions } from './essential-options.constants' +export type { OptionTags } from './options-tag.type' diff --git a/apps/seller/src/entity/products/create/create-info/index.ts b/apps/seller/src/entity/products/create/create-info/index.ts new file mode 100644 index 00000000..49ba22de --- /dev/null +++ b/apps/seller/src/entity/products/create/create-info/index.ts @@ -0,0 +1,2 @@ +export { ProductDiscountType } from './product-discount-type.constants' +export { productionTimes } from './production-time.constants' diff --git a/apps/seller/src/entity/products/create/create-info/product-discount-type.constants.ts b/apps/seller/src/entity/products/create/create-info/product-discount-type.constants.ts index 641e95ea..114de0a0 100644 --- a/apps/seller/src/entity/products/create/create-info/product-discount-type.constants.ts +++ b/apps/seller/src/entity/products/create/create-info/product-discount-type.constants.ts @@ -1,10 +1,10 @@ export const ProductDiscountType = [ { label: '원', - value: 'won', + value: 'AMOUNT', }, { label: '%', - value: 'percentage', + value: 'RATE', }, ] diff --git a/apps/seller/src/entity/products/create/create-info/production-time.constants.ts b/apps/seller/src/entity/products/create/create-info/production-time.constants.ts index 578e37c8..64b0fed5 100644 --- a/apps/seller/src/entity/products/create/create-info/production-time.constants.ts +++ b/apps/seller/src/entity/products/create/create-info/production-time.constants.ts @@ -1,22 +1,29 @@ +// export const productionTimes = [ +// { +// label: '03:00~04:00', +// value: '03:00~04:00', +// }, +// { +// label: '04:00~05:00', +// value: '04:00~05:00', +// }, +// { +// label: '05:00~06:00', +// value: '05:00~06:00', +// }, +// { +// label: '06:00~07:00', +// value: '06:00~07:00', +// }, +// { +// label: '07:00~08:00', +// value: '07:00~08:00', +// }, +// ] export const productionTimes = [ - { - label: '03:00~04:00', - value: '03:00~04:00', - }, - { - label: '04:00~05:00', - value: '04:00~05:00', - }, - { - label: '05:00~06:00', - value: '05:00~06:00', - }, - { - label: '06:00~07:00', - value: '06:00~07:00', - }, - { - label: '07:00~08:00', - value: '07:00~08:00', - }, + { label: '03:00~04:00', value: '03:00' }, + { label: '04:00~05:00', value: '04:00' }, + { label: '05:00~06:00', value: '05:00' }, + { label: '06:00~07:00', value: '06:00' }, + { label: '07:00~08:00', value: '07:00' }, ] diff --git a/apps/seller/src/entity/products/create/create-options/index.ts b/apps/seller/src/entity/products/create/create-options/index.ts new file mode 100644 index 00000000..ce4e42e0 --- /dev/null +++ b/apps/seller/src/entity/products/create/create-options/index.ts @@ -0,0 +1,7 @@ +export { NUTRITION_FIELDS } from './product-nutritions.constant' +export type { NutritionFieldKey } from './product-nutritions.constant' +export { + MAIN_CATEGORY_OPTIONS, + SUB_CATEGORY_MAP, +} from './product-options.constant' +export { SHIPPING_DAYS } from './product-shipping-days.constant' diff --git a/apps/seller/src/entity/products/create/create-store/create-store-header.type.ts b/apps/seller/src/entity/products/create/create-store/create-store-header.type.ts new file mode 100644 index 00000000..8be8d920 --- /dev/null +++ b/apps/seller/src/entity/products/create/create-store/create-store-header.type.ts @@ -0,0 +1,32 @@ +export type ProductFileType = Record + +export interface NutritionData { + sugar: number | null + protein: number | null + fat: number | null + ingredientCategories: string[] +} + +export interface ActiveTags { + [key: string]: boolean +} + +export interface CreateFormHeaderType { + productFields: ProductFileType + currentStep: number + headerHeight: number + + setProductFields: React.Dispatch> + setCurrentStep: React.Dispatch> + setHeaderHeight: React.Dispatch> + scrollToStep: (index: number) => void + + isScrollingToStep: React.MutableRefObject + + nutritionDataList: NutritionData[] + setNutritionData: (index: number, data: NutritionData) => void + activeTags: ActiveTags + + productPrice: number | null + setProductPrice: React.Dispatch> +} diff --git a/apps/seller/src/entity/products/create/create-store/index.ts b/apps/seller/src/entity/products/create/create-store/index.ts new file mode 100644 index 00000000..e4f95c2e --- /dev/null +++ b/apps/seller/src/entity/products/create/create-store/index.ts @@ -0,0 +1 @@ +export * from './create-store-header.type' From 538b145b4c5284eacbf6236f47d580c4072cded5 Mon Sep 17 00:00:00 2001 From: yeaseula Date: Mon, 27 Apr 2026 15:48:05 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[seller]=20feat(173)=20:=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../create/create-disclosure/product-disclosure.constant.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/seller/src/entity/products/create/create-disclosure/product-disclosure.constant.ts b/apps/seller/src/entity/products/create/create-disclosure/product-disclosure.constant.ts index 91ede12d..fdcd07a9 100644 --- a/apps/seller/src/entity/products/create/create-disclosure/product-disclosure.constant.ts +++ b/apps/seller/src/entity/products/create/create-disclosure/product-disclosure.constant.ts @@ -5,7 +5,6 @@ export const DISCLOSURE_FIELDS = [ { label: '4. 소재지', key: 'originLocation' }, { label: '5. 제조년월일', key: 'manufactureDate' }, { label: '6. 소비기한 또는 품질 유지기한', key: 'expirationDate' }, - // { label: '7. 보관방법', key: 'storageGuide' }, { label: '7. 포장 단위 별 내용물 용량(중량) 수량', key: 'packagingContents' }, { label: '8. 포장 단위별 수량', key: 'packagingQuantityUnit' }, { From d9cf40cfe7dfa4a7cdf1c5d0a18862fd4434dce7 Mon Sep 17 00:00:00 2001 From: yeaseula Date: Mon, 27 Apr 2026 16:03:47 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[seller]=20refactor(173):=20Public=20API=20?= =?UTF-8?q?=EB=88=84=EB=9D=BD=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../products/create/create-form/index.ts | 10 ++++- .../create/create-form/product-form.type.ts | 40 ------------------- .../products/create/create-store/index.ts | 6 ++- apps/seller/src/entity/products/index.ts | 9 ++++- 4 files changed, 21 insertions(+), 44 deletions(-) delete mode 100644 apps/seller/src/entity/products/create/create-form/product-form.type.ts diff --git a/apps/seller/src/entity/products/create/create-form/index.ts b/apps/seller/src/entity/products/create/create-form/index.ts index a9220c34..72a70819 100644 --- a/apps/seller/src/entity/products/create/create-form/index.ts +++ b/apps/seller/src/entity/products/create/create-form/index.ts @@ -1,5 +1,11 @@ -export * from './create-form.types' -export * from './create-indivisual-form.type' +export type { CreateFormType } from './create-form.types' +export type { + ProductFormInput, + DeliveryFormInput, + ThumbnailFormInput, + ProductOptionFormInput, + ProductDisclosureFormInput, +} from './create-indivisual-form.type' export { getMyStore, createProduct } from './create.api' export { productQueries, productKeys } from './create.query' export type { diff --git a/apps/seller/src/entity/products/create/create-form/product-form.type.ts b/apps/seller/src/entity/products/create/create-form/product-form.type.ts deleted file mode 100644 index a7e102bb..00000000 --- a/apps/seller/src/entity/products/create/create-form/product-form.type.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { ProductInfoNoticeKey } from '../create-disclosure/product-disclosure.constant' - -export type ProductFormInput = { - productName: string - isFresh: boolean - productionTime: string - price: number | null - discountAmount: number | null - discountType: 'won' | 'percentage' -} - -export type DeliveryFormInput = { - deliveryTerms: string - deliveryCompany: string - deliveryFee: number | null - deliveryMinFee: number | null -} - -export type ProductOptionFormInput = { - mainCategory: string - subCategory: string - optionName: string - ingredientCategories: ('glutenFree' | 'vegan')[] - additionalPrice: number | null - stockQuantity: number | null - shippingDays: ('mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun')[] - hasNutrition: boolean - totalWeight: number | null - calories: number | null - carbohydrate: number | null - sugar: number | null - protein: number | null - fat: number | null - sodium: number | null -} - -export type ProductDisclosureFormInput = { - productInfoNotice: Record - productInfoNoticeMode: Record -} diff --git a/apps/seller/src/entity/products/create/create-store/index.ts b/apps/seller/src/entity/products/create/create-store/index.ts index e4f95c2e..0749e913 100644 --- a/apps/seller/src/entity/products/create/create-store/index.ts +++ b/apps/seller/src/entity/products/create/create-store/index.ts @@ -1 +1,5 @@ -export * from './create-store-header.type' +export type { + NutritionData, + ActiveTags, + CreateFormHeaderType, +} from './create-store-header.type' diff --git a/apps/seller/src/entity/products/index.ts b/apps/seller/src/entity/products/index.ts index 6644c541..802396df 100644 --- a/apps/seller/src/entity/products/index.ts +++ b/apps/seller/src/entity/products/index.ts @@ -6,7 +6,11 @@ export * from './create/create-delivery/product-delivery-terms' export * from './create/create-disclosure/product-disclosure.constant' // Create - Form Types -export * from './create/create-form/product-form.type' +export * from './create/create-form/create-form.types' +export * from './create/create-form/create-indivisual-form.type' +export * from './create/create-form/create.api' +export * from './create/create-form/create.query' +export * from './create/create-form/create.type' // Create - Header export * from './create/create-header/category-options.constants' @@ -21,3 +25,6 @@ export * from './create/create-info/production-time.constants' export * from './create/create-options/product-nutritions.constant' export * from './create/create-options/product-options.constant' export * from './create/create-options/product-shipping-days.constant' + +// Create - store +export * from './create/create-store/create-store-header.type' From 81a7521cb4cceef4ba2ada8d49d6818a8b146f55 Mon Sep 17 00:00:00 2001 From: yeaseula Date: Mon, 27 Apr 2026 16:04:32 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[seller]=20refactor(173):=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../create-info/production-time.constants.ts | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/apps/seller/src/entity/products/create/create-info/production-time.constants.ts b/apps/seller/src/entity/products/create/create-info/production-time.constants.ts index 64b0fed5..f8fa2766 100644 --- a/apps/seller/src/entity/products/create/create-info/production-time.constants.ts +++ b/apps/seller/src/entity/products/create/create-info/production-time.constants.ts @@ -1,25 +1,3 @@ -// export const productionTimes = [ -// { -// label: '03:00~04:00', -// value: '03:00~04:00', -// }, -// { -// label: '04:00~05:00', -// value: '04:00~05:00', -// }, -// { -// label: '05:00~06:00', -// value: '05:00~06:00', -// }, -// { -// label: '06:00~07:00', -// value: '06:00~07:00', -// }, -// { -// label: '07:00~08:00', -// value: '07:00~08:00', -// }, -// ] export const productionTimes = [ { label: '03:00~04:00', value: '03:00' }, { label: '04:00~05:00', value: '04:00' },