fix: 품목관리 수정 기능 버그 수정 및 Sales 페이지 추가

## 품목관리 수정 버그 수정
- FG(제품) 수정 시 품목명 반영 안되는 문제 해결
  - productName → name 필드 매핑 추가
  - FG 품목코드 = 품목명 동기화 로직 추가
- Materials(SM, RM, CS) 수정페이지 진입 오류 해결
- UNIQUE 제약조건 위반 오류 해결

## Sales 페이지
- 거래처관리 (client-management-sales-admin) 페이지 구현
- 견적관리 (quote-management) 페이지 구현
- 관련 컴포넌트 및 훅 추가

## 기타
- 회원가입 페이지 차단 처리
- 디버깅용 콘솔 로그 추가 (PUT 요청/응답 확인용)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2025-12-04 20:52:42 +09:00
parent 42f80e2b16
commit 751e65f59b
52 changed files with 8869 additions and 1088 deletions

View File

@@ -51,7 +51,7 @@ export interface PaginationConfig {
export interface StatCard {
label: string;
value: number;
value: string | number;
icon: LucideIcon;
iconColor: string;
}
@@ -108,7 +108,7 @@ export interface IntegratedListTemplateV2Props<T = any> {
allData?: T[]; // 모바일 인피니티 스크롤용 전체 필터된 데이터
mobileDisplayCount?: number; // 모바일에서 표시할 개수
onLoadMore?: () => void; // 더 불러오기 콜백
infinityScrollSentinelRef?: RefObject<HTMLDivElement>; // 인피니티 스크롤용 sentinel ref
infinityScrollSentinelRef?: RefObject<HTMLDivElement | null>; // 인피니티 스크롤용 sentinel ref
// 체크박스 선택
selectedItems: Set<string>;

View File

@@ -0,0 +1,96 @@
/**
* ResponsiveFormTemplate - 통합 등록 페이지 템플릿
*/
"use client";
import { ReactNode } from "react";
import { LucideIcon } from "lucide-react";
import { PageLayout } from "../organisms/PageLayout";
import { PageHeader } from "../organisms/PageHeader";
import { FormActions } from "../organisms/FormActions";
// Re-export form components for convenience
export { FormSection } from "../organisms/FormSection";
export type { FormSectionProps } from "../organisms/FormSection";
export { FormField } from "../molecules/FormField";
export type { FormFieldProps, FormFieldType, SelectOption } from "../molecules/FormField";
export { FormFieldGrid } from "../organisms/FormFieldGrid";
export type { FormFieldGridProps } from "../organisms/FormFieldGrid";
export { FormActions } from "../organisms/FormActions";
export type { FormActionsProps } from "../organisms/FormActions";
export interface ResponsiveFormTemplateProps {
title: string;
description?: string;
icon?: LucideIcon;
headerActions?: ReactNode;
isEditMode?: boolean;
children: ReactNode;
onSave?: () => void;
onCancel?: () => void;
saveLabel?: string;
cancelLabel?: string;
saveDisabled?: boolean;
saveLoading?: boolean;
showActions?: boolean;
customActions?: ReactNode;
className?: string;
maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
versionInfo?: ReactNode;
}
export function ResponsiveFormTemplate({
title,
description,
icon,
headerActions,
isEditMode,
children,
onSave,
onCancel,
saveLabel = "저장",
cancelLabel = "취소",
saveDisabled = false,
saveLoading = false,
showActions = true,
customActions,
className = "",
maxWidth = 'full',
versionInfo,
}: ResponsiveFormTemplateProps) {
return (
<PageLayout maxWidth={maxWidth} versionInfo={versionInfo}>
{/* 헤더 */}
<PageHeader
title={title}
description={description}
icon={icon}
rightActions={headerActions}
isEditMode={isEditMode}
/>
{/* 메인 컨텐츠 */}
<div className={`space-y-6 ${className}`}>
{children}
</div>
{/* 하단 액션 버튼 */}
{showActions && (
<div className="sticky bottom-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-t pt-4 pb-4 -mx-3 md:-mx-6 px-3 md:px-6 mt-6">
{customActions || (
<FormActions
onSave={onSave}
onCancel={onCancel}
saveLabel={saveLabel}
cancelLabel={cancelLabel}
saveDisabled={saveDisabled}
saveLoading={saveLoading}
/>
)}
</div>
)}
</PageLayout>
);
}