feat(WEB): 권한 관리 시스템 구현 및 상세 페이지 권한 통합

- PermissionContext, usePermission 훅, PermissionGuard 컴포넌트 신규 추가
- AccessDenied 접근 거부 페이지 추가
- permissions lib (체커, 매퍼, 타입) 구현
- BadDebtDetail, BoardDetail, LaborDetail, PricingDetail 등 상세 페이지 권한 적용
- ProcessDetail, StepDetail, ItemDetail, PermissionDetail 권한 연동
- RootProvider에 PermissionProvider 통합
- protected layout 권한 체크 추가
- Claude 프로젝트 설정 파일 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-02-03 10:17:02 +09:00
parent f0987127eb
commit e111f7b362
22 changed files with 1267 additions and 994 deletions

View File

@@ -30,6 +30,7 @@ import { ArrowLeft, Edit, Package, FileImage, Download, FileText, Check, Calenda
import { downloadFileById } from '@/lib/utils/fileDownload';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { useMenuStore } from '@/store/menuStore';
import { usePermission } from '@/hooks/usePermission';
interface ItemDetailClientProps {
item: ItemMaster;
@@ -96,6 +97,7 @@ function getStorageUrl(path: string | undefined): string | null {
export default function ItemDetailClient({ item }: ItemDetailClientProps) {
const router = useRouter();
const sidebarCollapsed = useMenuStore((state) => state.sidebarCollapsed);
const { canUpdate } = usePermission();
return (
<div className="space-y-6 pb-24">
@@ -625,13 +627,15 @@ export default function ItemDetailClient({ item }: ItemDetailClientProps) {
<ArrowLeft className="w-4 h-4 mr-2" />
</Button>
<Button
type="button"
onClick={() => router.push(`/production/screen-production/${encodeURIComponent(item.itemCode)}?mode=edit&type=${item.itemType}&id=${item.id}`)}
>
<Edit className="w-4 h-4 mr-2" />
</Button>
{canUpdate && (
<Button
type="button"
onClick={() => router.push(`/production/screen-production/${encodeURIComponent(item.itemCode)}?mode=edit&type=${item.itemType}&id=${item.id}`)}
>
<Edit className="w-4 h-4 mr-2" />
</Button>
)}
</div>
</div>
);