Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { DeliveryCompany } from './product-delivery-company'
export { DeliveryTerms } from './product-delivery-terms'
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { DISCLOSURE_FIELDS, RADIO_OPTIONS } from './product-disclosure.constant'
export type { ProductInfoNoticeKey } from './product-disclosure.constant'
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ 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: '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' },
Comment on lines +8 to +17
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

storageGuide 제거 — 기존 저장 데이터/응답 호환성 점검

스키마가 DISCLOSURE_FIELDS 기반으로 동적 생성되어 신규 폼은 정상 동작하지만, 서버 응답이나 임시 저장(draft)에 productInfoNotice.storageGuide가 포함될 경우 zod에 의해 unknown 키로 떨어지거나(strict 시 실패) 사용자에게 노출되지 않습니다. 백엔드 스펙과 일치 여부, 그리고 기존 상품의 마이그레이션/표기 처리(예: 8/9번 라벨 재번호로 인한 사용자 혼선) 확인 부탁드립니다.

] as const

export const RADIO_OPTIONS = [
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Comment on lines +9 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

파일명 일관성 점검

같은 디렉터리 내에 create.type.ts, create-indivisual-form.type.ts(단수)와 create-form.types.ts(복수)가 혼재합니다. 배럴에서 export *로 합쳐지므로 동작엔 문제 없지만 컨벤션 통일을 권장합니다(.type.ts로 통일).

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export type ProductFormInput = {
productionTime: string
price: number | null
discountAmount: number | null
discountType: 'won' | 'percentage'
discountType: 'AMOUNT' | 'RATE'
}

export type DeliveryFormInput = {
Expand All @@ -16,8 +16,13 @@ export type DeliveryFormInput = {
deliveryMinFee: number | null
}

export type ThumbnailFormInput = {
mainImage: File | null
extraImages: File[]
}
Comment on lines +19 to +22
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

ThumbnailFormInput.mainImage 타입 점검

원인: File | null로 선언. 폼 초기값/리셋 시 undefined도 흔함.
영향: react-hook-form defaultValues에서 undefined를 쓰면 타입 불일치, 또는 매번 null로 초기화 강제.
대안: 사용 패턴 확인 후 mainImage?: File | null 또는 File | null 중 하나로 통일하고 폼 기본값과 일치시켜 주세요(요약본은 mainImage?: File로 기술됨 — 실제 코드와 차이가 있어 검증 필요).


export type ProductOptionFormInput = {
mainCategory: string
mainCategory: 'bread' | 'snack' | ''
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Optional: mainCategory에 빈 문자열 허용

빈 문자열을 union에 포함하면 “미선택” 상태가 도메인 값처럼 취급되어 zod refine 등에서 별도 가드가 필요해집니다. 'bread' | 'snack' | null(또는 옵셔널)로 표현하면 의도가 더 명확합니다. 현재 폼 RHF 사용 컨벤션과 충돌하지 않는지 확인 후 결정하세요.

subCategory: string
optionName: string
ingredientCategories: ('glutenFree' | 'vegan')[]
Expand Down
21 changes: 21 additions & 0 deletions apps/seller/src/entity/products/create/create-form/create.api.ts
Original file line number Diff line number Diff line change
@@ -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<ApiResponse<{ store: StoreInfo }>>(
'/api/v1/seller/stores',
)
return response.data.result.store
}
Comment thread
yeaseula marked this conversation as resolved.

// 상품 등록
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
}
16 changes: 16 additions & 0 deletions apps/seller/src/entity/products/create/create-form/create.query.ts
Original file line number Diff line number Diff line change
@@ -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,
}),
}
66 changes: 66 additions & 0 deletions apps/seller/src/entity/products/create/create-form/create.type.ts
Original file line number Diff line number Diff line change
@@ -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<string, string>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Record<string, string> 약화된 키 타입

원인: productInfoNoticeRequest 키가 임의 문자열.
영향: 폼 측 Record<ProductInfoNoticeKey, string>과 불일치, 오타·누락 키 컴파일 통과.
대안: Record<ProductInfoNoticeKey, string>로 좁혀 주세요.

-  productInfoNoticeRequest: Record<string, string>
+  productInfoNoticeRequest: Record<ProductInfoNoticeKey, string>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
productInfoNoticeRequest: Record<string, string>
productInfoNoticeRequest: Record<ProductInfoNoticeKey, string>

}

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
}
Comment on lines +19 to +49
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP "sodium|servingSize|nutritionInfo" --type=ts -C2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 6962


🏁 Script executed:

rg -n "ProductOptionFormInput|servingSize" --type=ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1332


🏁 Script executed:

cat -n apps/seller/src/entity/products/create/create-form/create-indivisual-form.type.ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1610


🏁 Script executed:

rg -n "servingSize|nutritionInfo.*{" --type=ts -A5 apps/seller/src/features/products/create

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 208


🏁 Script executed:

rg -n "nutritionInfo" --type=ts -B3 -A8 apps/seller/src/features/products/create

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

rg -n "ProductOptionRequest" --type=ts -B5 -A10

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 2793


🏁 Script executed:

rg -n "createProduct|products.*create" --type=ts -A10 apps/seller/src/entity/products/create/create-form/create.api.ts | head -50

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 344


🏁 Script executed:

rg -n "new FormData|nutritionInfo|servingSize" --type=ts -B5 -A5 apps/seller/src/features/products/create

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

rg -n "useCreateProductForm|handleSubmit" --type=ts -B3 -A15 | head -80

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 6233


🏁 Script executed:

cat -n apps/seller/src/features/products/create/create-form/use-create-product-form.hook.ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 2019


🏁 Script executed:

rg -n "onSubmit|createProduct\(" --type=ts -B3 -A10 apps/seller/src/features/products/create | head -100

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

find apps/seller/src/features/products/create -name "*.tsx" -o -name "*.ts" | head -20

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1812


🏁 Script executed:

rg -n "CreateFormContainer|createProduct" --type=tsx -B5 -A15 apps/seller/src/pages/products/create

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 116


🏁 Script executed:

rg -n "CreateFormContainer|createProduct" -B5 -A15 apps/seller/src/pages/products/create

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 4804


🏁 Script executed:

rg -n "export.*CreateFormContainer" -B3 -A20 apps/seller/src/features/products/create

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 2195


🏁 Script executed:

cat -n apps/seller/src/features/products/create/create-form/product-create.types.ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 945


🏁 Script executed:

rg -n "useMutation|useCreateProductMutation|createProduct" apps/seller/src/features/products/create -B3 -A10

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 2976


영양 정보 필드 불일치 수정 필요

폼 타입 ProductOptionFormInput에는 sodium이 있으나, API 요청 타입 ProductOptionRequest.nutritionInfo에는 없고, 반대로 폼에 없는 servingSize가 필수로 포함됨. 폼→요청 변환 시 나트륨 데이터 손실 및 servingSize 필수값 누락으로 백엔드 4xx 에러 발생 가능.

백엔드 스펙과 맞춰 양쪽 필드를 동기화하세요. (productionInfo 필드 정의 라인 40-49)


// API 응답 타입
export interface StoreInfo {
storeId: number
name: string
introduce: string
profile: string
phoneNumber: string
email: string
}

export interface ApiResponse<T> {
success: boolean
code: number
message: string
result: T
}
Comment on lines +61 to +66
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP "interface\s+ApiResponse<|type\s+ApiResponse<" --type=ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 277


🏁 Script executed:

#!/bin/bash
# Check the full content of both files to see the actual interface definitions
echo "=== Auth types.ts ===" 
sed -n '10,20p' apps/seller/src/entity/auth/types.ts

echo -e "\n=== Create type.ts ===" 
sed -n '58,70p' apps/seller/src/entity/products/create/create-form/create.type.ts

# Search for all ApiResponse definitions more broadly
echo -e "\n=== All ApiResponse definitions ===" 
rg "ApiResponse" --type=ts -B 1 -A 5

# Check if `@/shared` exists
echo -e "\n=== Shared directory structure ===" 
find . -path "./apps/*/src/shared" -type d 2>/dev/null

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 4364


ApiResponse<T> 인터페이스 중복 정의 및 불일치

원인: auth와 products 도메인에서 각각 정의됨. 더욱이 result 필드의 선택사항 여부가 다름 (auth: result?: T, products: result: T).
영향: 타입 일관성 저하, 향후 유지보수 비용 증가, API 응답 처리 로직 혼재.
대안: src/shared/types/api.ts 등으로 통합하되, 단일 인터페이스 정의 필요 (선택사항/필수 필드 통일).

16 changes: 16 additions & 0 deletions apps/seller/src/entity/products/create/create-form/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export type { CreateFormType } from './create-form.types'
export type {
ProductFormInput,
DeliveryFormInput,
ThumbnailFormInput,
ProductOptionFormInput,
ProductDisclosureFormInput,
} from './create-indivisual-form.type'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

파일명 오타: indivisualindividual

원인: create-indivisual-form.type.ts 파일명에 영문 철자 오타가 있고 배럴에서도 그대로 import 됩니다. 영향: PR에서 강조한 "도메인 직관성" 네이밍 컨벤션을 해치고 추후 grep/IDE 자동완성에서 혼란을 줍니다. 대안: 파일명을 create-individual-form.type.ts로 리네임하고 아래 import 경로도 함께 수정해 주세요.

♻️ 제안 diff (파일 리네임 후)
-} from './create-indivisual-form.type'
+} from './create-individual-form.type'

export { getMyStore, createProduct } from './create.api'
export { productQueries, productKeys } from './create.query'
export type {
CreateProductRequest,
ProductOptionRequest,
StoreInfo,
ApiResponse,
} from './create.type'
Comment on lines +1 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Optional 정리 (3건 이내)

  • 파일 접미사 일관성: create-form.types.ts(복수)와 create.type.ts / create-indivisual-form.type.ts(단수)가 혼재합니다. 한 가지(.types.ts 권장)로 통일하면 FSD 배럴 가독성이 좋아집니다.
  • export 그룹화 순서: 현재 type → api → query → type 순서로 타입 export가 분리되어 있습니다. types → api → query로 묶으면 의미적 그룹이 명확해집니다.
  • 와일드카드 재고: 같은 도메인의 타입을 한 모듈로 합쳐(./types) export type * from './types'로 단순화 가능합니다 (TS 5.0+ 지원, 현재 5.7.2 OK).

3 changes: 3 additions & 0 deletions apps/seller/src/entity/products/create/create-header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { CategoryOptions } from './category-options.constants'
export { EssentialOptions } from './essential-options.constants'
Comment on lines +1 to +2
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

상수 네이밍 컨벤션 불일치 — CategoryOptions/EssentialOptions

코드베이스 다른 상수(DISCLOSURE_FIELDS, RADIO_OPTIONS, NUTRITION_FIELDS, SHIPPING_DAYS)는 UPPER_SNAKE_CASE를 따르는데, 이 두 항목은 PascalCase라 타입과 혼동되기 쉽습니다. PR의 네이밍 일관성 검토 요청과도 맞물리니 통일을 권장드려요.

♻️ 제안
-export { CategoryOptions } from './category-options.constants'
-export { EssentialOptions } from './essential-options.constants'
+export { CATEGORY_OPTIONS } from './category-options.constants'
+export { ESSENTIAL_OPTIONS } from './essential-options.constants'
 export type { OptionTags } from './options-tag.type'

원본 파일에서도 식별자 변경 필요합니다.

export type { OptionTags } from './options-tag.type'
2 changes: 2 additions & 0 deletions apps/seller/src/entity/products/create/create-info/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { ProductDiscountType } from './product-discount-type.constants'
export { productionTimes } from './production-time.constants'
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export const ProductDiscountType = [
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

상수 명명 컨벤션 제안

원인: ProductDiscountType은 런타임 배열인데 PascalCase라 타입처럼 읽힙니다.
영향: 동일 도메인에 같은 이름의 타입(discountType 리터럴 유니온)이 등장할 때 혼동 유발.
대안: PRODUCT_DISCOUNT_TYPES 또는 productDiscountTypes로 변경, as const 부여로 value 타입 추론까지 확보.

♻️ 제안 변경
-export const ProductDiscountType = [
+export const PRODUCT_DISCOUNT_TYPES = [
   {
     label: '원',
     value: 'AMOUNT',
   },
   {
     label: '%',
     value: 'RATE',
   },
-]
+] as const
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const ProductDiscountType = [
export const PRODUCT_DISCOUNT_TYPES = [
{
label: '원',
value: 'AMOUNT',
},
{
label: '%',
value: 'RATE',
},
] as const

{
label: '원',
value: 'won',
value: 'AMOUNT',
},
{
label: '%',
value: 'percentage',
value: 'RATE',
},
]
Comment on lines 1 to 10
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP "'won'|'percentage'" --type=ts -C2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 4327


🏁 Script executed:

# 상수 파일 확인
cat -n apps/seller/src/entity/products/create/create-info/product-discount-type.constants.ts

# 다른 파일에서의 이전 리터럴 추가 검색
rg -nP "discountType\s*[=:]\s*['\"]won['\"]|discountType\s*[=:]\s*['\"]percentage['\"]" --type=ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 402


🏁 Script executed:

# 스키마 파일에서 enum 정의 확인
rg -nP "enum\(['\"](won|percentage|AMOUNT|RATE)" --type=ts -A2 -B2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

# 새로운 상수 값 사용 위치 확인
rg -nP "['\"]AMOUNT['\"]|['\"]RATE['\"]" --type=ts apps/seller/src/features

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

# 완전한 impact 범위 확인 - 모든 이전 리터럴 위치
rg -nP "(won|percentage)" --type=ts apps/seller/src/features/products/create | head -50

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1036


🏁 Script executed:

# 새 상수값이 실제로 사용되는 위치 확인
rg -nP "AMOUNT|RATE" --type=ts apps/seller/src | grep -v node_modules | grep -v "\.test\." | head -30

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 524


🏁 Script executed:

# ProductDiscountType 상수 사용 위치
rg -nP "ProductDiscountType" --type=ts -B2 -A2 apps/seller/src/features

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1427


할인 타입 변경으로 인한 다운스트림 코드 동기화 필수

원인: 상수값은 'won'/'percentage''AMOUNT'/'RATE'로 변경되었으나, features 레이어 7개 위치에서 여전히 이전 리터럴을 사용 중.
영향:

  • 스키마 검증 실패 (schema enum 불일치)
  • 기본값 'won'이 타입 정의 'AMOUNT' | 'RATE'와 충돌
  • 가격 계산/UI 조건 분기(=== 'won', === 'percentage') 모두 작동 안 함
  • 새 폼 제출 시 즉시 검증 실패

대안: 아래 파일들을 'AMOUNT'/'RATE'로 일괄 치환:

  • use-create-product-form.hook.ts:16 (기본값)
  • create-info.schema.ts:21, 39, 46, 56 (enum, refine 로직)
  • create-form-info-area.ui.tsx:136 (placeholder 조건)
  • use-product-info-form.hook.ts:25 (가격 계산 분기)

Original file line number Diff line number Diff line change
@@ -1,22 +1,7 @@
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' },
]
Comment on lines 1 to 7
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# productionTime 사용처 추적: 파싱/슬라이스/범위 가정 코드 점검
rg -nP --type=ts -C3 '\bproductionTime\b'
rg -nP --type=ts -C2 "productionTime.*(?:split|slice|substring|~)"

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 5694


🏁 Script executed:

# Check API implementation for productionTime payload handling
find apps/seller/src -name "*api*" -o -name "*create*" | grep -E "(api|service)" | head -20

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 287


🏁 Script executed:

# Search for where productionTime is sent to API or processed
rg -nP --type=ts "productionTime" --file-type=typescript -A5 -B2 | head -100

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 524


🏁 Script executed:

# Look for any transformation/formatting of productionTime before API call
rg -nP --type=ts "(submit|send|payload|request).*productionTime|productionTime.*(submit|send|payload|request)" -A3

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

# Check if there's any backend response parsing that expects range format
rg -nP --type=ts "productionTime.*range|range.*productionTime|split.*productionTime|productionTime.*split"

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

cat -n apps/seller/src/entity/products/create/create-form/create.api.ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 777


🏁 Script executed:

# Search for form submission and productionTime handling in create form
rg -nP --type=ts "createProduct|submit" apps/seller/src/features/products/create/ -A5 | head -80

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1763


🏁 Script executed:

# Look for any existing products display that might use productionTime
rg -nP --type=ts "productionTime" apps/seller/src -B2 -A2 | grep -E "(display|show|render|format)"

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 212


🏁 Script executed:

# Look for product detail/display pages that might load and use productionTime
rg -nP --type=ts "productionTime" apps/seller/src/features/ -B3 -A3 | grep -E "(detail|view|display|fetch|get|load)"

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

# Check if there's any product list or detail view that might show productionTime
find apps/seller/src/features -name "*detail*" -o -name "*view*" -o -name "*list*" | head -10

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 850


🏁 Script executed:

# Search in the entire apps/seller for any productionTime parsing or formatting
rg -nP --type=ts "productionTime" apps/seller/src -B1 -A1 | tail -50

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 3849


labelvalue 형식 불일치 — UI 일관성 문제

라벨은 범위('03:00~04:00')를 표시하지만 저장값은 시작 시각만('03:00') 보냅니다. 프론트엔드에서 파싱/슬라이싱하는 코드는 없으나, UI에서 사용자에게 혼동을 줄 수 있습니다. 라벨을 '03:00'으로 통일하거나, 백엔드 API 명세를 확인한 후 필요시 범위 정보도 함께 보존하는 것이 좋습니다.

Original file line number Diff line number Diff line change
@@ -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'
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export type ProductFileType = Record<string, boolean>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

ProductFileType 오타로 보임 → ProductFieldType

필드(productFields/setProductFields)에서 사용되는데 이름이 "File"이라 가독성을 해칩니다. 외부 노출 전(이번 PR 내) 정정해 두시는 게 좋습니다.

✏️ 제안
-export type ProductFileType = Record<string, boolean>
+export type ProductFieldType = Record<string, boolean>
...
-  productFields: ProductFileType
-  setProductFields: React.Dispatch<React.SetStateAction<ProductFileType>>
+  productFields: ProductFieldType
+  setProductFields: React.Dispatch<React.SetStateAction<ProductFieldType>>


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<React.SetStateAction<ProductFileType>>
setCurrentStep: React.Dispatch<React.SetStateAction<number>>
setHeaderHeight: React.Dispatch<React.SetStateAction<number>>
scrollToStep: (index: number) => void

isScrollingToStep: React.MutableRefObject<boolean>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 전역 React 네임스페이스 사용 가능 여부 및 동일 패턴 점검
rg -nP --type=ts -C2 'React\.MutableRefObject\b'
fd -t f 'tsconfig*.json' | xargs -I{} sh -c 'echo "==> {}"; cat "{}"' | rg -nC2 '"jsx"|"types"'

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 858


🏁 Script executed:

cat package.json | grep -A5 '"react"'

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

rg -n 'isScrollingToStep' --type=ts --type=tsx -B2 -A2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 116


🏁 Script executed:

rg -n 'useRef.*isScrollingToStep|isScrollingToStep.*useRef' --type=ts --type=tsx -B3 -A3

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 116


🏁 Script executed:

rg -n 'const.*useRef|useRef' apps/seller/src/entity/products/create/create-store/ --type=ts --type=tsx -B1 -A1

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 116


🏁 Script executed:

fd 'package.json' --type f

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 277


🏁 Script executed:

rg -n 'isScrollingToStep' --type ts -B2 -A2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 635


🏁 Script executed:

fd -t f '\.(ts|js)$' apps/seller/src/entity/products/create/create-store/ | head -20

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 229


🏁 Script executed:

cat apps/seller/package.json | grep -A10 -B2 '"react"'

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 491


🏁 Script executed:

cat apps/seller/src/entity/products/create/create-store/index.ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 193


🏁 Script executed:

rg -n 'CreateStoreHeaderContextValue|useRef' apps/seller/src/entity/products/create/create-store/ --type ts -B2 -A2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

rg -n 'CreateFormHeaderType|CreateStoreHeaderContextValue' apps/seller/src/ --type ts -B1 -A3

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 888


🏁 Script executed:

rg -n 'useContext.*CreateStoreHeader|CreateStoreHeader.*useContext' apps/seller/src/ --type ts -B2 -A2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

fd -t f 'create-store' apps/seller/src/ | xargs ls -la

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 216


🏁 Script executed:

rg -n 'CreateFormHeaderType' apps/seller/src/ --type ts -l

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 229


🏁 Script executed:

rg -n 'useRef.*boolean\|scrollingToStep\|isScrolling' apps/seller/src/ --type ts -B3 -A1

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

cat -n apps/seller/src/entity/products/create/create-store/create-store-header.type.ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1209


🏁 Script executed:

rg -n 'CreateContext\|useRef' apps/seller/src/entity/products/create/ --type ts -B2 -A3

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 70


🏁 Script executed:

fd -t f 'create' apps/seller/src/entity/products/ -name '*.ts' | head -20

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 319


🌐 Web query:

React 19 MutableRefObject deprecated removed

💡 Result:

In React 19, MutableRefObject is deprecated in favor of a unified RefObject type. All refs returned by useRef are now mutable by default (current: T, not readonly current: T | null), useRef requires an initial argument (useRef(null) or useRef(undefined) for convenience), and refs are no longer sometimes immutable. This simplifies typing and resolves previous confusion where refs initialized with null couldn't be mutated. It is not removed—it's deprecated, so still available during migration. Codemods like refobject-defaults and useRef-required-initial handle updates automatically. Official React 19 docs confirm: "MutableRef is now deprecated in favor of a single RefObject type which useRef will always return." All refs mutable by default.

Citations:


🏁 Script executed:

rg -rn 'CreateFormHeaderType' apps/seller/src/entity/products/create/ --type ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 255


🏁 Script executed:

find apps/seller/src/entity/products/create -type f -name '*.ts' | head -30

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1869


🏁 Script executed:

rg -n 'isScrollingToStep' apps/seller/src/ --type ts -B5 -A5

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1425


React 19에서 deprecated된 React.MutableRefObject 타입 제거

React 19부터 모든 ref가 mutable이 되어 MutableRefObject는 더 이상 사용되지 않습니다. React.RefObject<boolean>으로 변경하세요.

♻️ 제안
-  isScrollingToStep: React.MutableRefObject<boolean>
+  isScrollingToStep: React.RefObject<boolean>


nutritionDataList: NutritionData[]
setNutritionData: (index: number, data: NutritionData) => void
activeTags: ActiveTags

productPrice: number | null
setProductPrice: React.Dispatch<React.SetStateAction<number | null>>
Comment on lines +19 to +31
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

React.* 글로벌 네임스페이스 의존 — 명시적 import 권장

import type 없이 React.Dispatch/SetStateAction/MutableRefObject 등을 사용하면 tsconfigjsx 설정이나 글로벌 타입 노출에 의존하게 됩니다. 명시 import가 더 안전하고 IDE 친화적입니다.

♻️ 제안
+import type { Dispatch, SetStateAction, RefObject } from 'react'
+
 export type ProductFileType = Record<string, boolean>
 ...
-  setProductFields: React.Dispatch<React.SetStateAction<ProductFileType>>
-  setCurrentStep: React.Dispatch<React.SetStateAction<number>>
-  setHeaderHeight: React.Dispatch<React.SetStateAction<number>>
+  setProductFields: Dispatch<SetStateAction<ProductFileType>>
+  setCurrentStep: Dispatch<SetStateAction<number>>
+  setHeaderHeight: Dispatch<SetStateAction<number>>
   ...
-  isScrollingToStep: React.MutableRefObject<boolean>
+  isScrollingToStep: RefObject<boolean>
   ...
-  setProductPrice: React.Dispatch<React.SetStateAction<number | null>>
+  setProductPrice: Dispatch<SetStateAction<number | null>>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
setProductFields: React.Dispatch<React.SetStateAction<ProductFileType>>
setCurrentStep: React.Dispatch<React.SetStateAction<number>>
setHeaderHeight: React.Dispatch<React.SetStateAction<number>>
scrollToStep: (index: number) => void
isScrollingToStep: React.MutableRefObject<boolean>
nutritionDataList: NutritionData[]
setNutritionData: (index: number, data: NutritionData) => void
activeTags: ActiveTags
productPrice: number | null
setProductPrice: React.Dispatch<React.SetStateAction<number | null>>
import type { Dispatch, SetStateAction, MutableRefObject } from 'react'
export type ProductFileType = Record<string, boolean>
setProductFields: Dispatch<SetStateAction<ProductFileType>>
setCurrentStep: Dispatch<SetStateAction<number>>
setHeaderHeight: Dispatch<SetStateAction<number>>
scrollToStep: (index: number) => void
isScrollingToStep: MutableRefObject<boolean>
nutritionDataList: NutritionData[]
setNutritionData: (index: number, data: NutritionData) => void
activeTags: ActiveTags
productPrice: number | null
setProductPrice: Dispatch<SetStateAction<number | null>>

}
5 changes: 5 additions & 0 deletions apps/seller/src/entity/products/create/create-store/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type {
NutritionData,
ActiveTags,
CreateFormHeaderType,
} from './create-store-header.type'
Comment on lines +1 to +5
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

ProductFileType 재내보내기 누락

CreateFormHeaderType.productFields/setProductFields의 타입이라 소비자가 setter를 prop으로 전달하거나 컴포넌트 외부에서 동일 형태를 선언할 때 직접 참조가 필요합니다. PR의 "Public API 누락" 검토 항목과 직결되는 부분입니다.

♻️ 제안
 export type {
+  ProductFileType,
   NutritionData,
   ActiveTags,
   CreateFormHeaderType,
 } from './create-store-header.type'

9 changes: 8 additions & 1 deletion apps/seller/src/entity/products/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Comment on lines +9 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Optional: export * 광역 재내보내기

api/query/type을 모두 export *로 내보내면 동일 식별자 충돌 시 컴파일 에러로 발견이 늦습니다. 가능하면 index.ts에서 named re-export를 사용해 공개 표면을 명시하세요(이미 create-form/index.ts에는 잘 정리됨 → 상위 배럴도 동일 패턴 권장).


⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP "create-form/product-form\.type" --type=ts -C2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 815


🏁 Script executed:

find apps/seller/src/entity/products -type f -name "*.type.ts" | head -20

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 445


🏁 Script executed:

cat -n apps/seller/src/entity/products/index.ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1516


🏁 Script executed:

rg "ProductOptionFormInput" apps/seller/src --type=ts -l

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 473


🏁 Script executed:

rg "product-form\.type" apps/seller/src --type=ts

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 278


🏁 Script executed:

cat -n apps/seller/src/entity/products/create/create-form/create-indivisual-form.type.ts | head -30

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 1047


🏁 Script executed:

cat -n apps/seller/src/entity/products/create/create-form/create-form.types.ts | head -30

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 550


🏁 Script executed:

rg "ProductOptionFormInput" apps/seller/src/entity/products --type=ts -B2 -A2

Repository: eco-dessert-platform/dessert-front-dashboard

Length of output: 2108


product-form.type 경로 참조로 인한 빌드 실패 발생

use-product-options.form.hook.ts가 존재하지 않는 @/entity/products/create/create-form/product-form.type에서 ProductOptionFormInput을 임포트하고 있습니다. 해당 타입은 create-indivisual-form.type에 정의되어 있으므로, 다음 중 하나로 수정하세요:

  • @/entity/products/create/create-form/create-indivisual-form.type로 경로 변경
  • 또는 @/entity/products 배럴에서 직접 임포트


// Create - Header
export * from './create/create-header/category-options.constants'
Expand All @@ -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'
Loading