# 📱 TabbedTableTemplate 사용 가이드

## 개요

`TabbedTableTemplate`은 탭과 테이블이 결합된 표준 템플릿입니다.
- **데스크톱**: 기본 `TabsList` + `Table` 컴포넌트
- **모바일/태블릿**: 커스텀 버튼 탭 + `MobileCard` 컴포넌트
- **자동 반응형 전환** (768px 기준)
- **페이지네이션 내장**

## 적용 대상 페이지

모든 "탭 + 테이블" 구조를 가진 페이지:
- ✅ 품목관리 (ItemManagement.tsx)
- ✅ 판매관리 (SalesManagement.tsx)
- ✅ 견적관리 (QuoteManagement.tsx)
- ✅ 거래처관리 (ClientManagement.tsx)
- ✅ BOM관리 (BOMManagement.tsx)
- 기타 탭+테이블 페이지

## 파일 위치

```
/components/templates/TabbedTableTemplate.tsx        # 템플릿 컴포넌트
/components/templates/TabbedTableTemplate.example.tsx # 사용 예시
```

## 기본 사용법

### 1. Import

```tsx
import { TabbedTableTemplate, TabConfig, TableColumn } from "./templates/TabbedTableTemplate";
import { MobileCard } from "./organisms/MobileCard";
import { TableRow, TableCell } from "./ui/table";
```

### 2. 데이터 타입 정의

```tsx
interface MyDataType {
  id: string;
  code: string;
  name: string;
  type: string;
  status: string;
}
```

### 3. 탭 구성

```tsx
const tabs: TabConfig[] = [
  { 
    value: 'all', 
    label: '전체', 
    count: data.length, 
    color: 'blue'  // blue, purple, orange, cyan, green, gray
  },
  { 
    value: 'active', 
    label: '활성', 
    count: activeData.length, 
    color: 'green' 
  },
  { 
    value: 'inactive', 
    label: '비활성', 
    count: inactiveData.length, 
    color: 'gray' 
  },
];
```

### 4. 테이블 컬럼 정의

```tsx
const columns: TableColumn[] = [
  { key: 'no', label: '번호', className: 'w-16' },
  { key: 'code', label: '코드', className: 'w-32' },
  { key: 'name', label: '이름' },
  { key: 'type', label: '유형', hidden: 'md' },  // md 미만에서 숨김
  { key: 'status', label: '상태', hidden: 'lg' }, // lg 미만에서 숨김
  { key: 'actions', label: '작업', className: 'text-right' },
];
```

### 5. 모바일 카드 렌더링

```tsx
const renderMobileCard = (item: MyDataType, index: number) => (
  <MobileCard
    key={item.id}
    title={item.code}
    subtitle={item.name}
    badge={{
      label: item.status === 'active' ? '활성' : '비활성',
      variant: item.status === 'active' ? 'default' : 'outline'
    }}
    fields={[
      { label: '유형', value: item.type },
      { label: '등록일', value: item.createdAt },
    ]}
    actions={[
      {
        label: '수정',
        onClick: () => handleEdit(item.id),
        icon: Edit,
        variant: 'outline'
      }
    ]}
  />
);
```

### 6. 테이블 행 렌더링

```tsx
const renderTableRow = (item: MyDataType, index: number, globalIndex: number) => (
  <TableRow key={item.id} className="hover:bg-muted/50">
    <TableCell>{globalIndex + 1}</TableCell>
    <TableCell>
      <code className="text-xs bg-gray-100 px-2 py-1 rounded">
        {item.code}
      </code>
    </TableCell>
    <TableCell className="font-medium">{item.name}</TableCell>
    <TableCell className="hidden md:table-cell">{item.type}</TableCell>
    <TableCell className="hidden lg:table-cell">
      <Badge variant={item.status === 'active' ? 'default' : 'outline'}>
        {item.status === 'active' ? '활성' : '비활성'}
      </Badge>
    </TableCell>
    <TableCell className="text-right">
      <Button
        variant="ghost"
        size="sm"
        onClick={() => handleEdit(item.id)}
      >
        <Edit className="h-4 w-4" />
      </Button>
    </TableCell>
  </TableRow>
);
```

### 7. 템플릿 사용

```tsx
<TabbedTableTemplate
  title="데이터 목록"
  tabs={tabs}
  defaultTab="all"
  data={filteredData}
  columns={columns}
  itemsPerPage={20}
  renderMobileCard={renderMobileCard}
  renderTableRow={renderTableRow}
  emptyMessage="데이터가 없습니다."
  showPagination={true}
  onTabChange={(tab) => console.log('탭 변경:', tab)}
/>
```

## Props 상세 설명

| Prop | 타입 | 필수 | 기본값 | 설명 |
|------|------|------|--------|------|
| `title` | `string` | ❌ | - | 카드 타이틀 |
| `tabs` | `TabConfig[]` | ✅ | - | 탭 구성 배열 |
| `defaultTab` | `string` | ✅ | - | 기본 선택 탭 값 |
| `data` | `T[]` | ✅ | - | 표시할 데이터 배열 |
| `columns` | `TableColumn[]` | ✅ | - | 테이블 컬럼 정의 |
| `itemsPerPage` | `number` | ❌ | `20` | 페이지당 항목 수 |
| `renderMobileCard` | `Function` | ✅ | - | 모바일 카드 렌더링 함수 |
| `renderTableRow` | `Function` | ✅ | - | 테이블 행 렌더링 함수 |
| `emptyMessage` | `string` | ❌ | `"데이터가 없습니다."` | 빈 상태 메시지 |
| `showPagination` | `boolean` | ❌ | `true` | 페이지네이션 표시 여부 |
| `onTabChange` | `Function` | ❌ | - | 탭 변경 이벤트 핸들러 |

## TabConfig 인터페이스

```tsx
interface TabConfig {
  value: string;      // 탭 고유 값
  label: string;      // 탭 라벨
  count: number;      // 항목 수 (모바일 탭에 표시)
  color?: 'blue' | 'purple' | 'orange' | 'cyan' | 'green' | 'gray';
}
```

## TableColumn 인터페이스

```tsx
interface TableColumn {
  key: string;        // 컬럼 키
  label: string;      // 컬럼 라벨
  className?: string; // 추가 CSS 클래스
  hidden?: 'md' | 'lg' | 'xl' | '2xl'; // 특정 브레이크포인트에서 숨김
}
```

## 반응형 동작

### 데스크톱 (≥768px)
- `TabsList` 컴포넌트로 탭 표시
- `Table` 컴포넌트로 데이터 표시
- 모든 컬럼 표시 (hidden 설정에 따라 일부 숨김 가능)

### 모바일/태블릿 (<768px)
- 커스텀 버튼 스타일 탭 (카운트 + 색상 표시)
- `MobileCard` 컴포넌트로 카드형 표시
- 스크롤 가능한 카드 목록

## 페이지네이션

자동으로 포함되며 다음 버튼 제공:
- **처음**: 첫 페이지로 이동
- **이전**: 이전 페이지로 이동
- **다음**: 다음 페이지로 이동
- **마지막**: 마지막 페이지로 이동
- **현재 페이지 표시**: `1 / 5` 형식

## 색상 테마

모바일 탭 버튼은 6가지 색상 지원:

| Color | 용도 |
|-------|------|
| `blue` | 전체, 기본 |
| `purple` | 제품, 중요 |
| `orange` | 부품, 경고 |
| `cyan` | 부자재, 정보 |
| `green` | 원자재, 성공 |
| `gray` | 소모품, 비활성 |

## 실제 적용 예시

### ItemManagement.tsx 적용

```tsx
<TabbedTableTemplate
  tabs={[
    { value: 'all', label: '전체', count: itemMasters.length, color: 'blue' },
    { value: 'FG', label: '제품', count: fgItems.length, color: 'purple' },
    { value: 'PT', label: '부품', count: ptItems.length, color: 'orange' },
    { value: 'SM', label: '부자재', count: smItems.length, color: 'cyan' },
    { value: 'RM', label: '원자재', count: rmItems.length, color: 'green' },
    { value: 'CS', label: '소모품', count: csItems.length, color: 'gray' },
  ]}
  defaultTab="all"
  data={filteredItems}
  columns={[
    { key: 'checkbox', label: '', className: 'w-[50px]' },
    { key: 'no', label: '번호', hidden: 'md' },
    { key: 'code', label: '품목코드', className: 'min-w-[100px]' },
    { key: 'type', label: '품목유형', className: 'min-w-[80px]' },
    { key: 'name', label: '품목명', className: 'min-w-[120px]' },
    { key: 'spec', label: '규격', hidden: 'md' },
    { key: 'unit', label: '단위', hidden: 'md' },
    { key: 'status', label: '품목 상태', hidden: 'lg' },
    { key: 'actions', label: '작업', className: 'text-right min-w-[100px]' },
  ]}
  renderMobileCard={(item, index) => (
    <MobileCard
      key={item.id}
      title={item.itemCode}
      subtitle={item.itemName}
      badge={{
        label: getItemTypeLabel(item.itemType),
        variant: 'outline'
      }}
      fields={[
        { label: '규격', value: item.specification || '-' },
        { label: '단위', value: item.unit || '-' },
      ]}
      actions={[
        { label: '상세', onClick: () => handleView(item), icon: Eye, variant: 'outline' },
        { label: '수정', onClick: () => handleEdit(item), icon: Edit, variant: 'outline' },
      ]}
    />
  )}
  renderTableRow={(item, index, globalIndex) => (
    <TableRow key={item.id} className="hover:bg-muted/50">
      <TableCell>
        <Checkbox
          checked={selectedItems.has(item.id)}
          onCheckedChange={() => toggleItemSelection(item.id)}
        />
      </TableCell>
      <TableCell className="hidden md:table-cell text-muted-foreground">
        {globalIndex + 1}
      </TableCell>
      <TableCell>
        <code className="text-xs bg-gray-100 px-2 py-1 rounded">
          {item.itemCode}
        </code>
      </TableCell>
      <TableCell>{getItemTypeBadge(item.itemType)}</TableCell>
      <TableCell className="font-medium">{item.itemName}</TableCell>
      <TableCell className="hidden md:table-cell text-sm text-muted-foreground">
        {item.specification || '-'}
      </TableCell>
      <TableCell className="hidden md:table-cell">
        <Badge variant="secondary">{item.unit || '-'}</Badge>
      </TableCell>
      <TableCell className="hidden lg:table-cell">
        {getStatusBadge(item.status)}
      </TableCell>
      <TableCell className="text-right">
        <TableActionButtons
          onView={() => handleView(item)}
          onEdit={() => handleEdit(item)}
          onDelete={() => handleDelete(item)}
        />
      </TableCell>
    </TableRow>
  )}
  itemsPerPage={20}
  showPagination={true}
  onTabChange={(tab) => setFilterType(tab)}
/>
```

## 주의사항

1. **Key prop 필수**: 모든 카드와 행에 고유한 `key` prop 제공
2. **반응형 클래스**: `hidden md:table-cell` 등으로 숨김 처리
3. **데이터 필터링**: 탭 변경 시 `data` prop에 필터된 데이터 전달
4. **페이지네이션 리셋**: 탭 변경 시 자동으로 첫 페이지로 이동

## 디자인 시스템 등록

이 템플릿은 **디자인시스템 관리** 페이지에 등록되어 있습니다:
- 경로: 관리자 > 디자인시스템
- 카테고리: Templates
- 사용 예시 및 Props 문서 확인 가능

## 문의

템플릿 사용 중 문제가 있거나 개선이 필요한 경우:
1. `/components/templates/TabbedTableTemplate.example.tsx` 참조
2. 디자인시스템 관리 페이지에서 상세 정보 확인
3. 기존 적용 사례 (ItemManagement.tsx, SalesManagement.tsx) 참조
