From 40250c61031263606dd073ce7056a3e8e27f18d0 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Tue, 14 Oct 2025 14:25:28 +0900
Subject: (김준회) AVL 구매요구사항 수정 - AVL 상세 엑셀 익스포트 추가 - 레코드
이동 멀티선택 추가 - 최종확정처리 오류 수정 - 프로젝트 AVL에 H/T 구분 추가
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
lib/avl/table/avl-detail-table.tsx | 64 +++++++---
lib/avl/table/avl-registration-area.tsx | 25 +++-
lib/avl/table/columns-detail.tsx | 54 ++++++++-
lib/avl/table/project-avl-table-columns.tsx | 30 ++---
lib/avl/table/project-avl-table.tsx | 173 ++++++++++++++++-----------
lib/avl/table/standard-avl-table-columns.tsx | 30 ++---
lib/avl/table/standard-avl-table.tsx | 40 ++++---
lib/avl/table/vendor-pool-table-columns.tsx | 30 ++---
8 files changed, 264 insertions(+), 182 deletions(-)
(limited to 'lib/avl/table')
diff --git a/lib/avl/table/avl-detail-table.tsx b/lib/avl/table/avl-detail-table.tsx
index ca3ba7e7..407535db 100644
--- a/lib/avl/table/avl-detail-table.tsx
+++ b/lib/avl/table/avl-detail-table.tsx
@@ -10,6 +10,7 @@ import { toast } from "sonner"
import { columns } from "./columns-detail"
import type { AvlDetailItem } from "../types"
import { BackButton } from "@/components/ui/back-button"
+import { exportTableToExcel } from "@/lib/export_all"
interface AvlDetailTableProps {
data: AvlDetailItem[]
@@ -33,7 +34,42 @@ export function AvlDetailTable({
}: AvlDetailTableProps) {
- // 액션 핸들러
+ // 데이터 테이블 설정 (초기 meta는 없음)
+ const { table } = useDataTable({
+ data,
+ columns,
+ pageCount: pageCount ?? 1,
+ initialState: {
+ sorting: [{ id: "no", desc: false }],
+ pagination: {
+ pageIndex: 0,
+ pageSize: 10,
+ },
+ },
+ getRowId: (row) => String(row.id),
+ // meta는 useEffect에서 설정
+ // 정적 데이터이므로 무한 스크롤 설정하지 않음 (클라이언트 측 소팅 활성화)
+ infiniteScrollConfig: undefined,
+ })
+
+ // Excel export 핸들러
+ const handleExcelExport = React.useCallback(async () => {
+ try {
+ toast.info("엑셀 파일을 생성 중입니다...")
+ await exportTableToExcel(table, {
+ filename: `AVL_상세내역_${new Date().toISOString().split('T')[0]}`,
+ allPages: true,
+ excludeColumns: ["select", "actions"],
+ useGroupHeader: true,
+ })
+ toast.success("엑셀 파일이 다운로드되었습니다.")
+ } catch (error) {
+ console.error("Excel export error:", error)
+ toast.error("엑셀 파일 생성 중 오류가 발생했습니다.")
+ }
+ }, [table])
+
+ // 액션 핸들러 (table을 직접 사용하지 않는 액션들)
const handleAction = React.useCallback(async (action: string) => {
switch (action) {
case 'vendor-pool':
@@ -55,29 +91,15 @@ export function AvlDetailTable({
}
}, [])
-
// 테이블 메타 설정
const tableMeta = React.useMemo(() => ({
onAction: handleAction,
}), [handleAction])
- // 데이터 테이블 설정
- const { table } = useDataTable({
- data,
- columns,
- pageCount: pageCount ?? 1,
- initialState: {
- sorting: [{ id: "no", desc: false }],
- pagination: {
- pageIndex: 0,
- pageSize: 10,
- },
- },
- getRowId: (row) => String(row.id),
- meta: tableMeta,
- // 정적 데이터이므로 무한 스크롤 설정하지 않음 (클라이언트 측 소팅 활성화)
- infiniteScrollConfig: undefined,
- })
+ // table의 meta 설정
+ React.useEffect(() => {
+ table.options.meta = tableMeta
+ }, [table, tableMeta])
return (
@@ -101,6 +123,10 @@ export function AvlDetailTable({
{/* 상단 버튼 영역 */}
+ {/* Excel Export 버튼 */}
+
{/* 단순 이동 버튼 */}
@@ -636,8 +661,10 @@ export const ProjectAvlTable = forwardRef
• 프로젝트명: {projectInfo?.projectName || ""}
• 공사부문: {projectInfo?.constructionSector || ""}
• 선종: {projectInfo?.shipType || ""}
- • H/T 구분: {projectInfo?.htDivision || ""}
- • 벤더 정보: {data.length}개 (전체 레코드)
+ • H/T 구분: {searchHtDivision === 'H' ? 'Hull (H)' : searchHtDivision === 'T' ? 'Top (T)' : searchHtDivision}
+
+ • 확정될 벤더 정보: {totalVendorInfoCount}개
+
{/*
⚠️ 확정 후 내용 수정을 필요로 하는 경우 동일 건을 다시 최종확정해 revision 처리로 수정해야 합니다.
*/}
diff --git a/lib/avl/table/standard-avl-table-columns.tsx b/lib/avl/table/standard-avl-table-columns.tsx
index 903d2590..650220f5 100644
--- a/lib/avl/table/standard-avl-table-columns.tsx
+++ b/lib/avl/table/standard-avl-table-columns.tsx
@@ -16,29 +16,13 @@ export const standardAvlColumns: ColumnDef[] = [
aria-label="Select all"
/>
),
- cell: ({ row, table }) => {
- // 선종별 표준 AVL 테이블의 단일 선택 핸들러
- const handleRowSelection = (checked: boolean) => {
- if (checked) {
- // 다른 모든 행의 선택 해제
- table.getRowModel().rows.forEach(r => {
- if (r !== row && r.getIsSelected()) {
- r.toggleSelected(false)
- }
- })
- }
- // 현재 행 선택/해제
- row.toggleSelected(checked)
- }
-
- return (
-
- )
- },
+ cell: ({ row }) => (
+ row.toggleSelected(!!value)}
+ aria-label="Select row"
+ />
+ ),
enableSorting: false,
enableHiding: false,
size: 50,
diff --git a/lib/avl/table/standard-avl-table.tsx b/lib/avl/table/standard-avl-table.tsx
index 06fa6931..c638bd7f 100644
--- a/lib/avl/table/standard-avl-table.tsx
+++ b/lib/avl/table/standard-avl-table.tsx
@@ -27,7 +27,7 @@ import { Search } from "lucide-react"
import { toast } from "sonner"
import { standardAvlColumns } from "./standard-avl-table-columns"
import { AvlVendorAddAndModifyDialog } from "./avl-vendor-add-and-modify-dialog"
-import { createAvlVendorInfo, updateAvlVendorInfo, deleteAvlVendorInfo, finalizeStandardAvl } from "../service"
+import { createAvlVendorInfo, updateAvlVendorInfo, deleteAvlVendorInfo, finalizeStandardAvl, getStandardAvlVendorInfoCount } from "../service"
import { AvlVendorInfoInput } from "../types"
import { useSession } from "next-auth/react"
import { ShipTypeSelector, ShipTypeItem } from "@/components/common/ship-type"
@@ -341,6 +341,7 @@ export const StandardAvlTable = forwardRef(0)
// 최종 확정 핸들러 (표준 AVL)
const handleFinalizeStandardAvl = React.useCallback(async () => {
@@ -350,22 +351,31 @@ export const StandardAvlTable = forwardRef {
try {
- // 3. 현재 데이터의 모든 ID 수집 (전체 레코드 기준)
- const avlVendorInfoIds = data.map(item => item.id)
-
- // 4. 최종 확정 실행
+ // 최종 확정 실행 (서버에서 DB의 모든 레코드를 조회하여 확정)
const standardAvlInfo = {
constructionSector: searchConstructionSector,
shipType: selectedShipType?.CD || "",
@@ -375,17 +385,16 @@ export const StandardAvlTable = forwardRef {
@@ -626,10 +635,9 @@ export const StandardAvlTable = forwardRef• 선종: {selectedShipType?.CD || ""}
• AVL종류: {searchAvlKind}
• H/T 구분: {searchHtDivision}
- • 벤더 정보: {data.length}개 (전체 레코드)
- {/*
- ⚠️ 확정 후 내용 수정을 필요로 하는 경우 동일 건을 다시 최종확정해 revision 처리로 수정해야 합니다.
-
*/}
+
+ • 확정될 벤더 정보: {totalVendorInfoCount}개
+