feat: 꾸미기 아이템 목록 테이블 추가
Co-Authored-By: Claude Opus 5
@8e13fd84a08263160272530e003aade06f5ca194
+++ app/(protected)/(basic)/decoration-items/_components/decoration-item-table.tsx
... | ... | @@ -0,0 +1,106 @@ |
| 1 | +import { | |
| 2 | + Table, | |
| 3 | + TableBody, | |
| 4 | + TableCell, | |
| 5 | + TableHead, | |
| 6 | + TableHeaderCell, | |
| 7 | + TableRow, | |
| 8 | +} from '@/components/ui/table'; | |
| 9 | +import { | |
| 10 | + formatDecorationItemActiveLabel, | |
| 11 | + formatDecorationItemPoints, | |
| 12 | + formatDecorationItemUpdatedAt, | |
| 13 | + getDecorationItemThumbnailLabel, | |
| 14 | + type DecorationItem, | |
| 15 | +} from '@/lib/domain/decoration-item'; | |
| 16 | +import { DecorationItemRowActions } from './decoration-item-row-actions'; | |
| 17 | + | |
| 18 | +interface DecorationItemTableProps { | |
| 19 | + items: DecorationItem[]; | |
| 20 | + /** 1-based 현재 페이지. "번호" 열의 표시 순번 계산에 쓴다. */ | |
| 21 | + page: number; | |
| 22 | + pageSize: number; | |
| 23 | + /** 수정 팝업의 "(총 등록 N개)" 힌트로 그대로 흘려보낸다(현재 유형 전체 등록 건수). */ | |
| 24 | + typeTotalCount: number; | |
| 25 | +} | |
| 26 | + | |
| 27 | +const COLUMN_HEADERS = [ | |
| 28 | + '번호', | |
| 29 | + '아이템ID', | |
| 30 | + '썸네일', | |
| 31 | + '아이템명', | |
| 32 | + '카테고리', | |
| 33 | + '포인트', | |
| 34 | + '사용여부', | |
| 35 | + '정렬순서', | |
| 36 | + '수정일시', | |
| 37 | + '관리', | |
| 38 | +]; | |
| 39 | + | |
| 40 | +/** | |
| 41 | + * 꾸미기 아이템 목록 테이블(시안 ADM_ITM_101, 10컬럼). | |
| 42 | + * | |
| 43 | + * **"번호"는 admins와 달리 오름차순 표시 순번이다**(`offset + index + 1`) — 이 화면의 기본 | |
| 44 | + * 정렬이 정렬순서 오름차순이라(Repository가 보장) "가장 작은 정렬순서가 1번"이 직관적이다. | |
| 45 | + * admins가 전체 건수에서 거꾸로 세는 이유(생성일 최신순 정렬)가 여기에는 없다. | |
| 46 | + * | |
| 47 | + * **썸네일은 아직 실제 이미지가 없다** — 시안은 업로드 필드를 요구하지만 사용자가 "썸네일을 | |
| 48 | + * 따로 등록하지 않고 추후 백엔드가 자동생성해주는 형식"이라고 확정했고(등록/수정 폼에 업로드 | |
| 49 | + * 필드가 없는 이유, `decoration-item-form-fields.tsx` 참조), 그 백엔드 자체가 아직 없어 | |
| 50 | + * 지금은 생성해 줄 이미지도 없다. 열 자리는 유지하고 아이템ID의 중간 세그먼트(예: | |
| 51 | + * `ITEM-HAT-002` → `HAT`)를 뽑아 보여주는 텍스트 박스로 대신한다 — 백엔드가 실제 썸네일을 | |
| 52 | + * 내려주면 이 셀만 `<img>`로 바꾸면 된다. | |
| 53 | + * | |
| 54 | + * "관리" 열은 행별 수정/삭제 트리거(`DecorationItemRowActions`)에 위임한다 — 상호작용이 | |
| 55 | + * 필요한 것은 그 셀뿐이라 이 테이블 자체는 Server Component로 유지하고 최말단만 클라이언트 | |
| 56 | + * 경계로 뗀다. | |
| 57 | + */ | |
| 58 | +export function DecorationItemTable({ | |
| 59 | + items, | |
| 60 | + page, | |
| 61 | + pageSize, | |
| 62 | + typeTotalCount, | |
| 63 | +}: DecorationItemTableProps) { | |
| 64 | + const offset = (page - 1) * pageSize; | |
| 65 | + | |
| 66 | + return ( | |
| 67 | + <Table> | |
| 68 | + <TableHead> | |
| 69 | + <TableRow> | |
| 70 | + {COLUMN_HEADERS.map((header) => ( | |
| 71 | + <TableHeaderCell key={header}>{header}</TableHeaderCell> | |
| 72 | + ))} | |
| 73 | + </TableRow> | |
| 74 | + </TableHead> | |
| 75 | + <TableBody> | |
| 76 | + {items.map((item, index) => ( | |
| 77 | + <TableRow key={item.itemId}> | |
| 78 | + <TableCell>{offset + index + 1}</TableCell> | |
| 79 | + <TableCell>{item.itemId}</TableCell> | |
| 80 | + <TableCell> | |
| 81 | + <span | |
| 82 | + aria-hidden="true" | |
| 83 | + className="inline-flex size-9 items-center justify-center rounded-md bg-surface-muted text-label-sm text-foreground-muted" | |
| 84 | + > | |
| 85 | + {getDecorationItemThumbnailLabel(item.itemId)} | |
| 86 | + </span> | |
| 87 | + <span className="sr-only">썸네일 준비 중</span> | |
| 88 | + </TableCell> | |
| 89 | + <TableCell>{item.name}</TableCell> | |
| 90 | + <TableCell>{item.category}</TableCell> | |
| 91 | + <TableCell>{formatDecorationItemPoints(item.points)}</TableCell> | |
| 92 | + <TableCell>{formatDecorationItemActiveLabel(item.isActive)}</TableCell> | |
| 93 | + <TableCell>{item.sortOrder}</TableCell> | |
| 94 | + <TableCell>{formatDecorationItemUpdatedAt(item.updatedAt)}</TableCell> | |
| 95 | + <TableCell> | |
| 96 | + <DecorationItemRowActions | |
| 97 | + item={item} | |
| 98 | + typeTotalCount={typeTotalCount} | |
| 99 | + /> | |
| 100 | + </TableCell> | |
| 101 | + </TableRow> | |
| 102 | + ))} | |
| 103 | + </TableBody> | |
| 104 | + </Table> | |
| 105 | + ); | |
| 106 | +} |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?