From 84363475b032060615fcf9f5a6d34251dc0c6c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Wed, 4 Feb 2026 23:06:59 +0900 Subject: [PATCH] =?UTF-8?q?feat(WEB):=20DateRangeSelector=20=ED=94=84?= =?UTF-8?q?=EB=A6=AC=EC=85=8B=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=B0=8F=20RuleModal=20=ED=92=88=EB=AA=A9=EC=9C=A0=ED=98=95=20?= =?UTF-8?q?=EB=8F=99=EC=A0=81=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DateRangeSelector: 프리셋 순서를 오늘→어제→당월→전월→전전월→당해년도로 변경 - RuleModal: 품목유형 옵션을 하드코딩에서 common_codes API 동적 조회로 변경 - RuleModal: 추가 모드 기본값을 개별 품목(individual)으로 변경 --- .../molecules/DateRangeSelector.tsx | 2 +- .../process-management/RuleModal.tsx | 36 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/components/molecules/DateRangeSelector.tsx b/src/components/molecules/DateRangeSelector.tsx index 7a4de51d..8e819a64 100644 --- a/src/components/molecules/DateRangeSelector.tsx +++ b/src/components/molecules/DateRangeSelector.tsx @@ -26,7 +26,7 @@ const PRESET_LABELS: Record = { /** * 기본 프리셋 순서 */ -const DEFAULT_PRESETS: DatePreset[] = ['thisYear', 'twoMonthsAgo', 'lastMonth', 'thisMonth', 'yesterday', 'today']; +const DEFAULT_PRESETS: DatePreset[] = ['today', 'yesterday', 'thisMonth', 'lastMonth', 'twoMonthsAgo', 'thisYear' ]; interface DateRangeSelectorProps { /** 시작 날짜 (yyyy-MM-dd 형식) */ diff --git a/src/components/process-management/RuleModal.tsx b/src/components/process-management/RuleModal.tsx index a04bb96e..55e91e3a 100644 --- a/src/components/process-management/RuleModal.tsx +++ b/src/components/process-management/RuleModal.tsx @@ -1,7 +1,7 @@ 'use client'; import { useState, useEffect, useCallback } from 'react'; -import { getItemList, type ItemOption } from './actions'; +import { getItemList, getItemTypeOptions, type ItemOption } from './actions'; import { Dialog, DialogContent, @@ -40,14 +40,8 @@ import type { } from '@/types/process'; import { RULE_TYPE_OPTIONS, MATCHING_TYPE_OPTIONS } from '@/types/process'; -// 품목 유형 옵션 -const ITEM_TYPE_OPTIONS = [ - { value: 'all', label: '전체' }, - { value: '제품', label: '제품' }, - { value: '반제품', label: '반제품' }, - { value: '원자재', label: '원자재' }, - { value: '부자재', label: '부자재' }, -]; +// 품목 유형 기본 옵션 (전체) +const DEFAULT_ITEM_TYPE_OPTION = { value: 'all', label: '전체' }; interface RuleModalProps { open: boolean; @@ -81,6 +75,9 @@ export function RuleModal({ open, onOpenChange, onAdd, editRule }: RuleModalProp const [itemList, setItemList] = useState([]); const [isItemsLoading, setIsItemsLoading] = useState(false); + // 품목 유형 옵션 (common_codes에서 동적 조회) + const [itemTypeOptions, setItemTypeOptions] = useState>([DEFAULT_ITEM_TYPE_OPTION]); + // 품목 목록 로드 (debounced) const loadItems = useCallback(async (q?: string, itemType?: string) => { setIsItemsLoading(true); @@ -131,11 +128,18 @@ export function RuleModal({ open, onOpenChange, onAdd, editRule }: RuleModalProp loadItems(searchKeyword, selectedItemType); }, [selectedItemType]); - // 모달 열릴 때 품목 목록 초기화 (초기 로드 안함) + // 모달 열릴 때 품목 목록 초기화 + 품목유형 옵션 로드 useEffect(() => { - if (open && registrationType === 'individual') { - setItemList([]); - setSearchKeyword(''); + if (open) { + // 품목유형 옵션 로드 (common_codes에서 동적 조회) + getItemTypeOptions().then((options) => { + setItemTypeOptions([DEFAULT_ITEM_TYPE_OPTION, ...options]); + }); + + if (registrationType === 'individual') { + setItemList([]); + setSearchKeyword(''); + } } }, [open, registrationType]); @@ -186,8 +190,8 @@ export function RuleModal({ open, onOpenChange, onAdd, editRule }: RuleModalProp setSelectedItemIds(new Set()); } } else { - // 추가 모드: 초기화 - setRegistrationType('pattern'); + // 추가 모드: 초기화 (개별 품목을 디폴트로) + setRegistrationType('individual'); setDescription(''); setRuleType('품목코드'); setMatchingType('startsWith'); @@ -399,7 +403,7 @@ export function RuleModal({ open, onOpenChange, onAdd, editRule }: RuleModalProp - {ITEM_TYPE_OPTIONS.map((opt) => ( + {itemTypeOptions.map((opt) => ( {opt.label}