[feat]: Item Master 데이터 관리 기능 구현 및 타입 에러 수정

- ItemMasterDataManagement 컴포넌트 구조화 (tabs, dialogs, components 분리)
- HierarchyTab 타입 에러 수정 (BOMItem section_id, updated_at 추가)
- API 클라이언트 구현 (item-master.ts, 13개 엔드포인트)
- ItemMasterContext 구현 (상태 관리 및 데이터 흐름)
- 백엔드 요구사항 문서 작성 (CORS 설정, API 스펙 등)
- SSR 호환성 수정 (navigator API typeof window 체크)
- 미사용 변수 ESLint 에러 해결
- Context 리팩토링 (AuthContext, RootProvider 추가)
- API 유틸리티 추가 (error-handler, logger, transformers)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2025-11-23 16:10:27 +09:00
parent 63f5df7d7d
commit df3db155dd
69 changed files with 31467 additions and 4796 deletions

View File

@@ -2,8 +2,7 @@
import { useAuthGuard } from '@/hooks/useAuthGuard';
import DashboardLayout from '@/layouts/DashboardLayout';
import { DataProvider } from '@/contexts/DataContext';
import { DeveloperModeProvider } from '@/contexts/DeveloperModeContext';
import { RootProvider } from '@/contexts/RootProvider';
/**
* Protected Layout
@@ -11,7 +10,7 @@ import { DeveloperModeProvider } from '@/contexts/DeveloperModeContext';
* Purpose:
* - Apply authentication guard to all protected pages
* - Apply common layout (sidebar, header) to all protected pages
* - Provide global context (DataProvider, DeveloperModeProvider)
* - Provide global context (RootProvider)
* - Prevent browser back button cache issues
* - Centralized protection for all routes under (protected)
*
@@ -32,10 +31,8 @@ export default function ProtectedLayout({
// 🎨 모든 하위 페이지에 공통 레이아웃 및 Context 적용
return (
<DataProvider>
<DeveloperModeProvider>
<DashboardLayout>{children}</DashboardLayout>
</DeveloperModeProvider>
</DataProvider>
<RootProvider>
<DashboardLayout>{children}</DashboardLayout>
</RootProvider>
);
}

View File

@@ -0,0 +1,60 @@
import { NextRequest } from 'next/server';
import { proxyToPhpBackend } from '@/lib/api/php-proxy';
/**
* 특정 페이지 조회 API
*
* 엔드포인트: GET /api/tenants/{tenantId}/item-master-config/pages/{pageId}
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ tenantId: string; pageId: string }> }
) {
const { tenantId, pageId } = await params;
return proxyToPhpBackend(
request,
`/api/v1/tenants/${tenantId}/item-master-config/pages/${pageId}`,
{ method: 'GET' }
);
}
/**
* 특정 페이지 업데이트 API
*
* 엔드포인트: PUT /api/tenants/{tenantId}/item-master-config/pages/{pageId}
*/
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ tenantId: string; pageId: string }> }
) {
const { tenantId, pageId } = await params;
const body = await request.json();
return proxyToPhpBackend(
request,
`/api/v1/tenants/${tenantId}/item-master-config/pages/${pageId}`,
{
method: 'PUT',
body: JSON.stringify(body),
}
);
}
/**
* 특정 페이지 삭제 API
*
* 엔드포인트: DELETE /api/tenants/{tenantId}/item-master-config/pages/{pageId}
*/
export async function DELETE(
request: NextRequest,
{ params }: { params: Promise<{ tenantId: string; pageId: string }> }
) {
const { tenantId, pageId } = await params;
return proxyToPhpBackend(
request,
`/api/v1/tenants/${tenantId}/item-master-config/pages/${pageId}`,
{ method: 'DELETE' }
);
}

View File

@@ -0,0 +1,74 @@
import { NextRequest } from 'next/server';
import { proxyToPhpBackend, appendQueryParams } from '@/lib/api/php-proxy';
/**
* 품목기준관리 전체 설정 조회 API
*
* 엔드포인트: GET /api/tenants/{tenantId}/item-master-config
*
* 역할:
* - PHP 백엔드로 단순 프록시
* - tenant.id 검증은 PHP에서 수행
* - PHP가 403 반환하면 그대로 전달
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ tenantId: string }> }
) {
const { tenantId } = await params;
const { searchParams } = new URL(request.url);
// PHP 엔드포인트 생성 (query params 포함)
const phpEndpoint = appendQueryParams(
`/api/v1/tenants/${tenantId}/item-master-config`,
searchParams
);
return proxyToPhpBackend(request, phpEndpoint, {
method: 'GET',
});
}
/**
* 품목기준관리 전체 설정 저장 API
*
* 엔드포인트: POST /api/tenants/{tenantId}/item-master-config
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ tenantId: string }> }
) {
const { tenantId } = await params;
const body = await request.json();
return proxyToPhpBackend(
request,
`/api/v1/tenants/${tenantId}/item-master-config`,
{
method: 'POST',
body: JSON.stringify(body),
}
);
}
/**
* 품목기준관리 전체 설정 업데이트 API
*
* 엔드포인트: PUT /api/tenants/{tenantId}/item-master-config
*/
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ tenantId: string }> }
) {
const { tenantId } = await params;
const body = await request.json();
return proxyToPhpBackend(
request,
`/api/v1/tenants/${tenantId}/item-master-config`,
{
method: 'PUT',
body: JSON.stringify(body),
}
);
}