fix(WEB): 품목관리 규격 필드를 실제 스펙 텍스트로 표시하도록 수정
- Specification 타입: '인정'|'비인정' → string (실제 규격 텍스트) - 데이터 소스: options.specification → attributes.spec으로 변경 - 상세 페이지: 규격 필드를 Select → Input(텍스트)으로 변경 - 저장 시 attributes.spec으로 저장하도록 변경 - 규격 필터 옵션에서 인정/비인정 제거
This commit is contained in:
@@ -22,10 +22,9 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate';
|
||||
import { itemConfig } from './itemConfig';
|
||||
import { toast } from 'sonner';
|
||||
import type { ItemFormData, ItemType, Specification, OrderType, ItemStatus, OrderItem } from './types';
|
||||
import type { ItemFormData, ItemType, OrderType, ItemStatus, OrderItem } from './types';
|
||||
import {
|
||||
ITEM_TYPE_OPTIONS,
|
||||
SPECIFICATION_OPTIONS,
|
||||
ORDER_TYPE_OPTIONS,
|
||||
STATUS_OPTIONS,
|
||||
UNIT_OPTIONS,
|
||||
@@ -42,8 +41,7 @@ const initialFormData: ItemFormData = {
|
||||
itemNumber: '',
|
||||
itemType: '제품',
|
||||
categoryId: '',
|
||||
itemName: '',
|
||||
specification: '인정',
|
||||
itemName: '', specification: '',
|
||||
unit: 'SET',
|
||||
orderType: '경품발주',
|
||||
status: '사용',
|
||||
@@ -322,22 +320,13 @@ export default function ItemDetailClient({
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="specification">규격</Label>
|
||||
<Select
|
||||
<Input
|
||||
id="specification"
|
||||
value={formData.specification}
|
||||
onValueChange={(v) => handleFieldChange('specification', v as Specification)}
|
||||
onChange={(e) => handleFieldChange('specification', e.target.value)}
|
||||
placeholder="규격을 입력하세요 (예: 1∅220V)"
|
||||
disabled={isViewMode}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="규격 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{SPECIFICATION_OPTIONS.filter((o) => o.value !== 'all').map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { UniversalListPage, type UniversalListConfig, type TableColumn, type Fil
|
||||
import { MobileCard } from '@/components/organisms/MobileCard';
|
||||
import { toast } from 'sonner';
|
||||
import { DeleteConfirmDialog } from '@/components/ui/confirm-dialog';
|
||||
import type { Item, ItemStats, ItemType, Specification, OrderType, ItemStatus } from './types';
|
||||
import type { Item, ItemStats, ItemType, OrderType, ItemStatus } from './types';
|
||||
import {
|
||||
ITEM_TYPE_OPTIONS,
|
||||
SPECIFICATION_OPTIONS,
|
||||
@@ -59,7 +59,7 @@ export default function ItemManagementClient({
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const [itemTypeFilter, setItemTypeFilter] = useState<ItemType | 'all'>('all');
|
||||
const [categoryFilter, setCategoryFilter] = useState<string>('all');
|
||||
const [specificationFilter, setSpecificationFilter] = useState<Specification | 'all'>('all');
|
||||
const [specificationFilter, setSpecificationFilter] = useState<string>('all');
|
||||
const [orderTypeFilter, setOrderTypeFilter] = useState<OrderType | 'all'>('all');
|
||||
const [statusFilter, setStatusFilter] = useState<ItemStatus | 'all'>('all');
|
||||
const [sortBy, setSortBy] = useState<'latest' | 'oldest'>('latest');
|
||||
@@ -479,7 +479,7 @@ export default function ItemManagementClient({
|
||||
setCategoryFilter(value as string);
|
||||
break;
|
||||
case 'specification':
|
||||
setSpecificationFilter(value as Specification | 'all');
|
||||
setSpecificationFilter(value as string);
|
||||
break;
|
||||
case 'orderType':
|
||||
setOrderTypeFilter(value as OrderType | 'all');
|
||||
|
||||
@@ -37,12 +37,13 @@ function transformToBackendItemType(frontendType: ItemType): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Backend options → Frontend specification 변환
|
||||
* Backend attributes.spec → Frontend specification 변환
|
||||
* 실제 규격 텍스트 (예: "1∅220V", "면적 18.1m²")
|
||||
*/
|
||||
function transformSpecification(options: Record<string, unknown> | null | undefined): Specification {
|
||||
const spec = options?.specification;
|
||||
if (spec === '인정' || spec === '비인정') return spec;
|
||||
return '인정'; // 기본값
|
||||
function transformSpecification(attributes: Record<string, unknown> | null | undefined): Specification {
|
||||
const spec = attributes?.spec;
|
||||
if (typeof spec === 'string' && spec.trim()) return spec.trim();
|
||||
return '-';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,6 +96,7 @@ interface ApiItem {
|
||||
category?: { name?: string } | null;
|
||||
unit: string | null;
|
||||
options: Record<string, unknown> | null;
|
||||
attributes: Record<string, unknown> | null;
|
||||
is_active: boolean;
|
||||
description: string | null;
|
||||
created_at: string;
|
||||
@@ -110,7 +112,7 @@ function transformItem(apiItem: ApiItem): Item {
|
||||
categoryId: apiItem.category_id ? String(apiItem.category_id) : '',
|
||||
categoryName: apiItem.category?.name || '',
|
||||
unit: apiItem.unit || 'EA',
|
||||
specification: transformSpecification(apiItem.options),
|
||||
specification: transformSpecification(apiItem.attributes),
|
||||
orderType: transformOrderType(apiItem.options),
|
||||
status: transformStatus(apiItem.is_active, apiItem.options),
|
||||
createdAt: apiItem.created_at,
|
||||
@@ -141,8 +143,10 @@ function transformItemToApi(data: ItemFormData): Record<string, unknown> {
|
||||
unit: data.unit,
|
||||
is_active: data.status === '사용' || data.status === '승인',
|
||||
description: data.note || null,
|
||||
attributes: {
|
||||
spec: data.specification || null,
|
||||
},
|
||||
options: {
|
||||
specification: data.specification,
|
||||
orderType: data.orderType,
|
||||
status: data.status,
|
||||
orderItems: data.orderItems,
|
||||
|
||||
@@ -11,11 +11,9 @@ export const ITEM_TYPE_OPTIONS: { value: ItemType | 'all'; label: string }[] = [
|
||||
{ value: '공과', label: '공과' },
|
||||
];
|
||||
|
||||
// 규격 옵션
|
||||
export const SPECIFICATION_OPTIONS: { value: Specification | 'all'; label: string }[] = [
|
||||
// 규격 필터 옵션 (규격 있음/없음)
|
||||
export const SPECIFICATION_OPTIONS: { value: string; label: string }[] = [
|
||||
{ value: 'all', label: '전체' },
|
||||
{ value: '인정', label: '인정' },
|
||||
{ value: '비인정', label: '비인정' },
|
||||
];
|
||||
|
||||
// 구분(발주유형) 옵션
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// 물품유형
|
||||
export type ItemType = '제품' | '부품' | '소모품' | '공과';
|
||||
|
||||
// 규격
|
||||
export type Specification = '인정' | '비인정';
|
||||
// 규격 (실제 스펙 텍스트, 예: "1∅220V", "면적 18.1m²")
|
||||
export type Specification = string;
|
||||
|
||||
// 구분 (발주유형)
|
||||
export type OrderType = '경품발주' | '원자재발주' | '외주발주';
|
||||
|
||||
Reference in New Issue
Block a user