summaryrefslogtreecommitdiff
path: root/lib/avl/table
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-09-24 17:36:08 +0900
committerjoonhoekim <26rote@gmail.com>2025-09-24 17:36:08 +0900
commitbf2db28586569499e44b58999f2e0f33ed4cdeb5 (patch)
tree9ef9305829fdec30ec7a442f2ba0547a62dba7a9 /lib/avl/table
parent1bda7f20f113737f4af32495e7ff24f6022dc283 (diff)
(김준회) 구매 요청사항 반영 - vendor-pool 및 avl detail (이진용 프로)
Diffstat (limited to 'lib/avl/table')
-rw-r--r--lib/avl/table/avl-detail-table.tsx70
-rw-r--r--lib/avl/table/avl-registration-area.tsx10
-rw-r--r--lib/avl/table/avl-table-columns.tsx16
-rw-r--r--lib/avl/table/avl-table.tsx26
-rw-r--r--lib/avl/table/project-avl-table.tsx33
-rw-r--r--lib/avl/table/standard-avl-table.tsx11
-rw-r--r--lib/avl/table/vendor-pool-table.tsx3
7 files changed, 56 insertions, 113 deletions
diff --git a/lib/avl/table/avl-detail-table.tsx b/lib/avl/table/avl-detail-table.tsx
index 4408340a..22c503ff 100644
--- a/lib/avl/table/avl-detail-table.tsx
+++ b/lib/avl/table/avl-detail-table.tsx
@@ -6,12 +6,10 @@ import { useDataTable } from "@/hooks/use-data-table"
import { DataTable } from "@/components/data-table/data-table"
import { Button } from "@/components/ui/button"
import { toast } from "sonner"
-import { createAvlRfqItbAction, prepareAvlRfqItbInput } from "../avl-itb-rfq-service"
import { columns } from "./columns-detail"
import type { AvlDetailItem } from "../types"
import { BackButton } from "@/components/ui/back-button"
-import { useSession } from "next-auth/react"
interface AvlDetailTableProps {
data: AvlDetailItem[]
@@ -33,63 +31,11 @@ export function AvlDetailTable({
projectInfo,
businessType,
}: AvlDetailTableProps) {
- // 견적요청 처리 상태 관리
- const [isProcessingQuote, setIsProcessingQuote] = React.useState(false)
- const { data: session } = useSession()
-
- // 견적요청 처리 함수
- const handleQuoteRequest = React.useCallback(async () => {
- if (!businessType || !['조선', '해양'].includes(businessType)) {
- toast.error("공사구분이 올바르지 않습니다. 견적요청 처리 불가.")
- return
- }
- if (data.length === 0) {
- toast.error("견적요청할 AVL 데이터가 없습니다.")
- return
- }
-
- setIsProcessingQuote(true)
-
- try {
- // 현재 사용자 세션에서 ID 가져오기
- const currentUserId = session?.user?.id ? Number(session.user.id) : undefined
-
- // 견적요청 입력 데이터 준비 (전체 데이터를 사용)
- const quoteInput = await prepareAvlRfqItbInput(
- data, // 전체 데이터를 사용
- businessType as '조선' | '해양',
- {
- picUserId: currentUserId,
- rfqTitle: `${businessType} AVL 견적요청 - ${data[0]?.materialNameCustomerSide || 'AVL 아이템'}${data.length > 1 ? ` 외 ${data.length - 1}건` : ''}`
- }
- )
-
- // 견적요청 실행
- const result = await createAvlRfqItbAction(quoteInput)
-
- if (result.success) {
- toast.success(`${result.data?.type}가 성공적으로 생성되었습니다. (코드: ${result.data?.rfqCode})`)
- } else {
- toast.error(result.error || "견적요청 처리 중 오류가 발생했습니다.")
- }
-
- } catch (error) {
- console.error('견적요청 처리 오류:', error)
- toast.error("견적요청 처리 중 오류가 발생했습니다.")
- } finally {
- setIsProcessingQuote(false)
- }
- }, [businessType, data, session?.user?.id])
// 액션 핸들러
const handleAction = React.useCallback(async (action: string) => {
switch (action) {
-
- case 'quote-request':
- await handleQuoteRequest()
- break
-
case 'vendor-pool':
window.open('/evcp/vendor-pool', '_blank')
break
@@ -107,7 +53,7 @@ export function AvlDetailTable({
default:
toast.error(`알 수 없는 액션: ${action}`)
}
- }, [handleQuoteRequest])
+ }, [])
// 테이블 메타 설정
@@ -153,24 +99,10 @@ export function AvlDetailTable({
{/* 상단 버튼 영역 */}
<div className="flex items-center gap-2 ml-auto justify-end">
- {
- // 표준AVL로는 견적요청하지 않으며, 프로젝트 AVL로만 견적요청처리
- avlType === '프로젝트AVL' && businessType && ['조선', '해양'].includes(businessType) &&
- <Button
- variant="outline"
- size="sm"
- onClick={() => handleAction('quote-request')}
- disabled={data.length === 0 || isProcessingQuote}
- >
- {isProcessingQuote ? '처리중...' : `${businessType} 견적요청 (${businessType === '조선' ? 'RFQ' : 'ITB'})`}
- </Button>
- }
-
{/* 단순 이동 버튼 */}
<Button variant="outline" size="sm" onClick={() => handleAction('vendor-pool')}>
Vendor Pool
</Button>
-
</div>
{/* 데이터 테이블 */}
diff --git a/lib/avl/table/avl-registration-area.tsx b/lib/avl/table/avl-registration-area.tsx
index ba1c76d4..6c7eba9d 100644
--- a/lib/avl/table/avl-registration-area.tsx
+++ b/lib/avl/table/avl-registration-area.tsx
@@ -15,16 +15,6 @@ import { toast } from "sonner"
// 선택된 테이블 타입
type SelectedTable = 'project' | 'standard' | 'vendor' | null
-// TODO: 나머지 테이블들도 ref 지원 추가 시 인터페이스 추가 필요
-// interface StandardAvlTableRef {
-// getSelectedIds?: () => number[]
-// }
-//
-// interface VendorPoolTableRef {
-// getSelectedIds?: () => number[]
-// }
-
-
// 선택 상태 액션 타입
type SelectionAction =
| { type: 'SELECT_PROJECT'; count: number }
diff --git a/lib/avl/table/avl-table-columns.tsx b/lib/avl/table/avl-table-columns.tsx
index 6ec2c3db..06005d3d 100644
--- a/lib/avl/table/avl-table-columns.tsx
+++ b/lib/avl/table/avl-table-columns.tsx
@@ -45,9 +45,7 @@ export function getColumns({ selectedRows = [], onRowSelect }: GetColumnsProps):
enableSorting: false,
enableHiding: false,
enableResizing: false,
- size: 10,
- minSize: 10,
- maxSize: 10,
+ size: 50,
},
// No 컬럼
{
@@ -57,7 +55,7 @@ export function getColumns({ selectedRows = [], onRowSelect }: GetColumnsProps):
),
cell: ({ getValue }) => <div className="text-center">{getValue() as number}</div>,
enableResizing: true,
- size: 60,
+ size: 100,
},
// AVL 분류 컬럼
{
@@ -148,7 +146,7 @@ export function getColumns({ selectedRows = [], onRowSelect }: GetColumnsProps):
{
accessorKey: "htDivision",
header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="H/T 구분" />
+ <DataTableColumnHeaderSimple column={column} title="H/T" />
),
cell: ({ getValue }) => {
const value = getValue() as string
@@ -205,7 +203,7 @@ export function getColumns({ selectedRows = [], onRowSelect }: GetColumnsProps):
<DataTableColumnHeaderSimple column={column} title="자재그룹" />
),
enableResizing: true,
- size: 120,
+ size: 100,
},
// 협력업체 컬럼
{
@@ -214,7 +212,7 @@ export function getColumns({ selectedRows = [], onRowSelect }: GetColumnsProps):
<DataTableColumnHeaderSimple column={column} title="협력업체" />
),
enableResizing: true,
- size: 150,
+ size: 100,
},
// Tier 컬럼
{
@@ -280,7 +278,7 @@ export function getColumns({ selectedRows = [], onRowSelect }: GetColumnsProps):
return <div className="text-center text-sm">{date}</div>
},
enableResizing: true,
- size: 100,
+ size: 120,
},
// 최종변경자 컬럼
{
@@ -293,7 +291,7 @@ export function getColumns({ selectedRows = [], onRowSelect }: GetColumnsProps):
return <div className="text-center text-sm">{value}</div>
},
enableResizing: true,
- size: 100,
+ size: 120,
},
// 액션 컬럼
{
diff --git a/lib/avl/table/avl-table.tsx b/lib/avl/table/avl-table.tsx
index 61db658d..9b6ac90b 100644
--- a/lib/avl/table/avl-table.tsx
+++ b/lib/avl/table/avl-table.tsx
@@ -100,9 +100,9 @@ export function AvlTable({ data, pageCount, isLoading, onRegistrationModeChange,
const handleAction = React.useCallback(async (action: string, data?: Partial<AvlListItem>) => {
try {
switch (action) {
- case 'standard-registration':
- // 표준 AVL 등록
- const result = await handleAvlActionAction('standard-registration')
+ case 'avl-registration':
+ // AVL 등록 (통합된 기능)
+ const result = await handleAvlActionAction('avl-registration')
if (result.success) {
toast.success(result.message)
onRegistrationModeChange?.('standard') // 등록 모드 변경 콜백 호출
@@ -112,9 +112,10 @@ export function AvlTable({ data, pageCount, isLoading, onRegistrationModeChange,
break
case 'view-detail':
- // 상세 조회 (페이지 이동)
+ // 상세 조회 (페이지 이동) - 원래 방식으로 복원
if (data?.id && !String(data.id).startsWith('temp-')) {
- window.location.href = `/evcp/avl/${data.id}`
+ console.log('AVL 상세보기 이동:', data.id) // 디버깅용
+ window.location.href = `/ko/evcp/avl/${data.id}`
}
break
@@ -177,6 +178,9 @@ export function AvlTable({ data, pageCount, isLoading, onRegistrationModeChange,
columnSizing: {},
},
getRowId: (row) => String(row.id),
+ meta: {
+ onAction: handleAction,
+ },
})
return (
@@ -191,17 +195,9 @@ export function AvlTable({ data, pageCount, isLoading, onRegistrationModeChange,
<Button
variant="outline"
size="sm"
- onClick={() => handleAction('standard-registration')}
- >
- 표준AVL등록
- </Button>
-
- <Button
- variant="outline"
- size="sm"
- onClick={() => handleAction('project-registration')}
+ onClick={() => handleAction('avl-registration')}
>
- 프로젝트AVL등록
+ AVL 등록
</Button>
</div>
diff --git a/lib/avl/table/project-avl-table.tsx b/lib/avl/table/project-avl-table.tsx
index 9584c6f9..ad72b221 100644
--- a/lib/avl/table/project-avl-table.tsx
+++ b/lib/avl/table/project-avl-table.tsx
@@ -177,12 +177,40 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro
const projectData = await getProjectInfoByCode(projectCode.trim(), 'both')
if (projectData) {
+ // constructionSector 동적 결정
+ let constructionSector = "해양" // 기본값
+ if (projectData.source === 'projects') {
+ // projects 테이블의 경우: type='ship'이면 '조선', 그 외는 '해양'
+ constructionSector = projectData.type === 'ship' ? "조선" : "해양"
+ } else if (projectData.source === 'biddingProjects') {
+ // biddingProjects 테이블의 경우: sector가 'S'이면 '조선', 'M'이면 '해양'
+ constructionSector = projectData.sector === 'S' ? "조선" : "해양"
+ }
+
+ // htDivision 동적 결정
+ let htDivision = "" // 기본값
+ if (constructionSector === "조선") {
+ // constructionSector가 '조선'인 경우는 항상 H
+ htDivision = "H"
+ } else if (projectData.source === 'projects') {
+ // projects에서는 TYPE_MDG 컬럼이 Top이면 T, Hull이면 H
+ htDivision = projectData.typeMdg === 'Top' ? "T" : "H"
+ } else if (projectData.source === 'biddingProjects') {
+ if (projectData.sector === 'S') {
+ // biddingProjects에서 sector가 S이면 HtDivision은 항상 H
+ htDivision = "H"
+ } else if (projectData.sector === 'M') {
+ // biddingProjects에서 sector가 M인 경우: pjtType이 TOP이면 'T', HULL이면 'H'
+ htDivision = projectData.pjtType === 'TOP' ? "T" : "H"
+ }
+ }
+
// 프로젝트 정보 설정
setProjectInfo({
projectName: projectData.projectName || "",
- constructionSector: "조선", // 기본값으로 조선 설정 (필요시 로직 변경)
+ constructionSector: constructionSector,
shipType: projectData.shipType || projectData.projectMsrm || "",
- htDivision: projectData.projectHtDivision || ""
+ htDivision: htDivision
})
// 검색 상태 설정
@@ -307,6 +335,7 @@ export const ProjectAvlTable = forwardRef<ProjectAvlTableRef, ProjectAvlTablePro
getFilteredRowModel: getFilteredRowModel(),
manualPagination: true,
pageCount,
+ columnResizeMode: "onChange",
state: {
pagination,
},
diff --git a/lib/avl/table/standard-avl-table.tsx b/lib/avl/table/standard-avl-table.tsx
index bacb5812..06fa6931 100644
--- a/lib/avl/table/standard-avl-table.tsx
+++ b/lib/avl/table/standard-avl-table.tsx
@@ -123,6 +123,7 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable
getFilteredRowModel: getFilteredRowModel(),
manualPagination: true,
pageCount,
+ columnResizeMode: "onChange",
state: {
pagination,
},
@@ -150,11 +151,8 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable
},
})
- // 공사부문 변경 시 선종 초기화
const handleConstructionSectorChange = React.useCallback((value: string) => {
setSearchConstructionSector(value)
- // 공사부문이 변경되면 선종을 빈 값으로 초기화
- setSelectedShipType(undefined)
}, [])
// 검색 상태 변경 시 부모 컴포넌트에 전달
@@ -506,7 +504,7 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable
<div className="space-y-2">
<label className="text-sm font-medium">공사부문</label>
<Select value={searchConstructionSector} onValueChange={handleConstructionSectorChange}>
- <SelectTrigger>
+ <SelectTrigger className="bg-background">
<SelectValue />
</SelectTrigger>
<SelectContent>
@@ -526,7 +524,6 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable
selectedShipType={selectedShipType}
onShipTypeSelect={setSelectedShipType}
placeholder="선종을 선택하세요"
- disabled={!searchConstructionSector}
className="h-10"
/>
</div>
@@ -535,7 +532,7 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable
<div className="space-y-2">
<label className="text-sm font-medium">AVL종류</label>
<Select value={searchAvlKind} onValueChange={setSearchAvlKind}>
- <SelectTrigger>
+ <SelectTrigger className="bg-background">
<SelectValue />
</SelectTrigger>
<SelectContent>
@@ -552,7 +549,7 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable
<div className="space-y-2">
<label className="text-sm font-medium">H/T 구분</label>
<Select value={searchHtDivision} onValueChange={setSearchHtDivision}>
- <SelectTrigger>
+ <SelectTrigger className="bg-background">
<SelectValue />
</SelectTrigger>
<SelectContent>
diff --git a/lib/avl/table/vendor-pool-table.tsx b/lib/avl/table/vendor-pool-table.tsx
index 7ad9eb56..3ac67928 100644
--- a/lib/avl/table/vendor-pool-table.tsx
+++ b/lib/avl/table/vendor-pool-table.tsx
@@ -174,6 +174,7 @@ export const VendorPoolTable = forwardRef<VendorPoolTableRef, VendorPoolTablePro
getFilteredRowModel: getFilteredRowModel(),
manualPagination: !showAll, // 전체보기 시에는 수동 페이징 비활성화
pageCount: showAll ? 1 : pageCount, // 전체보기 시 1페이지, 일반 모드에서는 API에서 받은 pageCount 사용
+ columnResizeMode: "onChange",
state: {
pagination: showAll ? { pageIndex: 0, pageSize: data.length } : pagination,
},
@@ -262,7 +263,7 @@ export const VendorPoolTable = forwardRef<VendorPoolTableRef, VendorPoolTablePro
placeholder="설계공종, 업체명, 자재그룹 등으로 검색..."
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
- className="flex-1"
+ className="flex-1 bg-background"
onKeyPress={(e) => {
if (e.key === 'Enter') {
handleSearch()