# 공통 컴포넌트 가이드 이 문서는 SAM MES 시스템의 통일된 레이아웃과 반응형 디자인을 위한 공통 컴포넌트 사용 가이드입니다. > 📌 **중요**: 페이지 타이틀 구조 통일에 대한 상세 가이드는 [TITLE_STRUCTURE_STANDARDIZATION.md](/TITLE_STRUCTURE_STANDARDIZATION.md)를 참고하세요. ## 📋 목차 1. [개요](#개요) 2. [공통 컴포넌트 목록](#공통-컴포넌트-목록) 3. [사용 예시](#사용-예시) 4. [디자인 원칙](#디자인-원칙) ## 개요 모든 페이지는 통일된 레이아웃과 디자인 스타일을 사용하여 일관된 사용자 경험을 제공합니다. - ✅ 완전한 반응형 디자인 (데스크톱/태블릿/모바일) - ✅ 데스크톱: 테이블 형식 - ✅ 모바일: 카드 형식 - ✅ 통일된 헤더, 검색, 통계 패턴 ## 공통 컴포넌트 목록 ### 1. PageLayout 페이지의 기본 레이아웃을 제공합니다. ```tsx import { PageLayout } from "./common/PageLayout"; function MyPage() { return ( {/* 페이지 내용 */} ); } ``` **Props:** - `maxWidth`: `"sm" | "md" | "lg" | "xl" | "2xl" | "full"` (기본값: "full") - `sm`: max-w-3xl - `md`: max-w-5xl - `lg`: max-w-6xl - `xl`: max-w-7xl - `2xl`: max-w-[1600px] - `full`: w-full (전체 너비, 기본값) - 자동으로 padding과 spacing 적용 (p-4 md:p-6, space-y-4 md:space-y-6) ### 2. PageHeader 페이지 헤더 (제목, 설명, 액션 버튼) ```tsx import { PageHeader } from "./common/PageHeader"; import { FileText, Plus } from "lucide-react"; 신규 작성 } /> ``` **Props:** - `title`: 페이지 제목 (필수) - `description`: 페이지 설명 (선택) - `icon`: Lucide 아이콘 컴포넌트 (선택) - `actions`: 액션 버튼들 (선택) ### 3. StatCards 통계 카드를 그리드로 표시 ```tsx import { StatCards } from "./common/StatCards"; import { FileText } from "lucide-react"; const stats = [ { label: "전체 견적", value: 150, icon: FileText, iconColor: "text-blue-600" }, { label: "금일 작성", value: 12, icon: FileText, iconColor: "text-green-600", trend: { value: "+15%", isPositive: true } } ]; ``` **Props:** - `stats`: 통계 데이터 배열 - `label`: 라벨 - `value`: 값 (숫자 또는 문자열) - `icon`: Lucide 아이콘 (선택) - `iconColor`: 아이콘 색상 클래스 (선택) - `trend`: 추세 정보 (선택) ### 4. SearchFilter 검색 및 필터 바 ```tsx import { SearchFilter } from "./common/SearchFilter"; 내보내기 } /> ``` **Props:** - `searchValue`: 검색어 (필수) - `onSearchChange`: 검색어 변경 핸들러 (필수) - `searchPlaceholder`: 검색 placeholder (선택) - `filterButton`: 필터 버튼 표시 여부 (기본값: true) - `onFilterClick`: 필터 클릭 핸들러 (선택) - `extraActions`: 추가 액션 버튼들 (선택) ### 5. EmptyState 빈 상태 표시 ```tsx import { EmptyState } from "./common/EmptyState"; import { FileText } from "lucide-react"; ``` **Props:** - `icon`: Lucide 아이콘 컴포넌트 (필수) - `title`: 제목 (필수) - `description`: 설명 (선택) - `action`: 액션 버튼 정보 (선택) - `label`: 버튼 텍스트 - `onClick`: 클릭 핸들러 ### 6. MobileCard 모바일용 카드 컴포넌트 ```tsx import { MobileCard } from "./common/MobileCard"; import { FileText, Eye, Edit, Trash2 } from "lucide-react"; } badge={{ label: "진행중", variant: "outline" }} fields={[ { label: "접수일", value: "2025-01-15" }, { label: "금액", value: "1,500,000원" }, { label: "상태", value: "완료", badge: true, badgeVariant: "secondary" } ]} actions={[ { label: "상세", icon: , variant: "outline", onClick: handleView }, { label: "수정", icon: , variant: "outline", onClick: handleEdit } ]} /> ``` **Props:** - `title`: 제목 (필수) - `subtitle`: 부제목 (선택) - `icon`: 아이콘 ReactNode (선택) - `badge`: 배지 정보 (선택) - `fields`: 필드 배열 (필수) - `actions`: 액션 버튼 배열 (선택) ## 사용 예시 ### List 페이지 전체 구조 ```tsx import { useState } from "react"; import { PageLayout } from "./common/PageLayout"; import { PageHeader } from "./common/PageHeader"; import { StatCards } from "./common/StatCards"; import { SearchFilter } from "./common/SearchFilter"; import { EmptyState } from "./common/EmptyState"; import { MobileCard } from "./common/MobileCard"; import { Card, CardContent } from "./ui/card"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./ui/table"; import { Button } from "./ui/button"; import { Badge } from "./ui/badge"; import { Plus, FileText, Eye, Edit, Trash2 } from "lucide-react"; export function MyListPage() { const [searchTerm, setSearchTerm] = useState(""); const [items, setItems] = useState([]); const stats = [ { label: "전체", value: items.length, icon: FileText, iconColor: "text-blue-600" }, { label: "금일", value: 12, icon: FileText, iconColor: "text-green-600" } ]; const filteredItems = items.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); return ( 신규 작성 } /> {filteredItems.length === 0 ? ( ) : ( <> {/* 데스크톱 테이블 */} 이름 상태 관리 {filteredItems.map(item => ( {item.name} {item.status} ))}
{/* 모바일 카드 */}
{filteredItems.map(item => ( , onClick: () => handleEdit(item) } ]} /> ))}
)}
); } ``` ### Write 페이지 전체 구조 ```tsx import { PageLayout } from "./common/PageLayout"; import { PageHeader } from "./common/PageHeader"; import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; import { Button } from "./ui/button"; import { Input } from "./ui/input"; import { Label } from "./ui/label"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collapsible"; import { ChevronDown, ChevronUp, Save, FileEdit } from "lucide-react"; export function MyWritePage({ onSave, onCancel }) { const [isBasicInfoOpen, setIsBasicInfoOpen] = useState(true); return ( } /> {/* 접이식 섹션 */} 기본 정보 {isBasicInfoOpen ? ( ) : ( )}
); } ``` ## 디자인 원칙 ### 반응형 브레이크포인트 - **모바일**: `< 768px` - 카드 뷰, 단일 컬럼 - **태블릿**: `768px - 1024px` - 2-3 컬럼 그리드 - **데스크톱**: `> 1024px` - 테이블 뷰, 4 컬럼 그리드 ### 간격 (Spacing) **필수 규칙:** - 모든 페이지는 `PageLayout`으로 감싸기 (자동으로 통일된 padding/spacing 적용) - 페이지 padding: `p-4 md:p-6` (PageLayout 자동 적용) - 섹션 간격: `space-y-4 md:space-y-6` (PageLayout 자동 적용) - 그리드 간격: `gap-4` - Card 내부 padding: `p-4 md:p-6` - Table이 포함된 Card: `CardContent`에 `p-0` 사용 (테이블이 꽉 차도록) ### 색상 패턴 통계 카드 아이콘 색상: - 파랑: `text-blue-600` - 전체/기본 - 초록: `text-green-600` - 성공/금일 - 주황: `text-orange-600` - 경고/이번주 - 보라: `text-purple-600` - 정보/평균 ### 타이포그래피 **페이지 타이틀 구조 (필수 규칙):** - ⛔ **절대 금지**: 직접 `

` 태그나 커스텀 제목 작성 - ✅ **필수 사용**: `PageHeader` 컴포넌트 사용 - PageHeader는 자동으로 올바른 타이포그래피 적용 (`text-xl md:text-2xl`) **잘못된 예시 (사용 금지):** ```tsx

주문 관리

차량관리

``` **올바른 예시 (필수):** ```tsx 등록} /> ``` **타이포그래피 규칙:** - 페이지 제목: `text-xl md:text-2xl` (PageHeader가 자동 적용) - 카드 제목: `text-base` - 본문: `text-sm` - 설명: `text-sm text-muted-foreground` ### 아이콘 크기 - 헤더 아이콘: `w-6 h-6` - 버튼 아이콘: `w-4 h-4` - 작은 아이콘: `w-3 h-3` - 통계 아이콘: `w-8 h-8 md:w-10 md:h-10` ## 체크리스트 새 페이지를 만들 때 다음을 확인하세요: ### 필수 사항 - [ ] `PageLayout`으로 감싸기 (maxWidth는 특별한 경우가 아니면 기본값 "full" 사용) - [ ] `PageHeader` 사용 (title, description, icon, actions) - **커스텀 h1 태그 절대 금지** - [ ] 페이지 타이틀은 반드시 `PageHeader` 컴포넌트 사용 - `text-3xl`, `text-2xl md:text-3xl` 직접 사용 금지 - [ ] 통계가 필요하면 `StatCards` 사용 - [ ] 검색이 필요하면 `SearchFilter` 사용 - [ ] 빈 상태에 `EmptyState` 사용 ### 반응형 디자인 - [ ] 데스크톱: `Card` + `Table` (테이블을 감싸는 Card만 표시) - [ ] 모바일: `MobileCard` (md:hidden) - [ ] 반응형 그리드: `grid-cols-1 md:grid-cols-2 lg:grid-cols-4` ### 레이아웃 규칙 - [ ] Table이 포함된 Card의 CardContent는 `p-0` 사용 - [ ] Dialog width: `max-w-[95vw] sm:max-w-lg md:max-w-2xl` 또는 `max-w-[95vw] sm:max-w-xl md:max-w-4xl` - [ ] Dialog에 `DialogDescription` 포함 - [ ] 모든 액션 버튼에 아이콘 추가 - [ ] Card 내부 padding: `p-4 md:p-6` (Table이 있는 경우 제외) ## 디자인 시스템 통일 작업 ### ✅ 완료된 페이지 (PageLayout + PageHeader 적용) - `/components/VehicleManagement.tsx` - 차량관리 - `/components/EquipmentManagement.tsx` - 설비관리 - `/components/ItemManagement.tsx` - 품목관리 - `/components/OrderManagement.tsx` - 주문관리 ⭐ **NEW** - `/components/QuoteManagement3List.tsx` - 견적관리 목록 - `/components/QuoteManagement3Write.tsx` - 견적관리 작성 ### ⚠️ 업데이트 필요 페이지 (커스텀 h1 사용 중) 다음 페이지들은 아직 커스텀 `

` 또는 `

`를 사용하고 있어 `PageHeader` 컴포넌트로 변경이 필요합니다: **품질관리:** - (대부분 완료) **전자결재:** - `/components/ApprovalManagement.tsx` - 전자결재 **회계관리:** - `/components/AccountingManagement.tsx` - 회계 관리 - `/components/ShippingManagement.tsx` - 출고관리 **인사관리:** - `/components/HRManagement.tsx` - 인사관리 **시스템관리:** - `/components/SystemManagement.tsx` - 시스템 관리 **자재관리:** - `/components/MaterialManagement.tsx` - 자재 관리 **대시보드:** - `/components/Dashboard.tsx` - CEO/생산관리자/작업자 대시보드 ### 업데이트 방법 기존 커스텀 헤더 코드: ```tsx

주문 관리

고객 주문 접수 및 진행 상황 관리

``` 변경 후 PageHeader 사용: ```tsx import { PageHeader } from "./common/PageHeader"; import { ShoppingCart } from "lucide-react"; 등록 } /> ``` ### 업데이트 체크리스트 각 페이지 업데이트 시 확인: 1. [ ] `PageLayout`으로 전체 페이지 감싸기 2. [ ] 커스텀 `

` 태그 제거 3. [ ] `PageHeader` 컴포넌트 import 및 사용 4. [ ] 적절한 lucide-react 아이콘 추가 5. [ ] actions prop에 버튼들 이동 6. [ ] description prop에 설명 추가 7. [ ] `text-3xl` 또는 `text-2xl md:text-3xl` 클래스 완전 제거 ## 참고 파일 완벽하게 구현된 예시: - `/components/VehicleManagement.tsx` - 차량관리 (PageLayout + PageHeader 완벽 구현) - `/components/EquipmentManagement.tsx` - 설비관리 (PageLayout + PageHeader 완벽 구현) - `/components/ItemManagement.tsx` - 품목관리 (PageLayout + PageHeader 완벽 구현) - `/components/QuoteManagement3List.tsx` - 견적관리 목록 - `/components/QuoteManagement3Write.tsx` - 견적관리 작성 - `/components/common/` - 모든 공통 컴포넌트