diff options
Diffstat (limited to 'lib/avl/table/standard-avl-table.tsx')
| -rw-r--r-- | lib/avl/table/standard-avl-table.tsx | 146 |
1 files changed, 73 insertions, 73 deletions
diff --git a/lib/avl/table/standard-avl-table.tsx b/lib/avl/table/standard-avl-table.tsx index cc39540b..bacb5812 100644 --- a/lib/avl/table/standard-avl-table.tsx +++ b/lib/avl/table/standard-avl-table.tsx @@ -15,6 +15,14 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select" +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" import { Search } from "lucide-react" import { toast } from "sonner" import { standardAvlColumns } from "./standard-avl-table-columns" @@ -22,13 +30,9 @@ import { AvlVendorAddAndModifyDialog } from "./avl-vendor-add-and-modify-dialog" import { createAvlVendorInfo, updateAvlVendorInfo, deleteAvlVendorInfo, finalizeStandardAvl } from "../service" import { AvlVendorInfoInput } from "../types" import { useSession } from "next-auth/react" +import { ShipTypeSelector, ShipTypeItem } from "@/components/common/ship-type" /** - * 조선인 경우, 선종: - * A-max, S-max, VLCC, LNGC, CONT - * 해양인 경우, 선종: - * FPSO, FLNG, FPU, Platform, WTIV, GOM - * * AVL종류: * Nearshore, Offshore, IOC, NOC */ @@ -39,31 +43,6 @@ const constructionSectorOptions = [ { value: "해양", label: "해양" }, ] -// 공사부문에 따른 선종 옵션들 -const getShipTypeOptions = (constructionSector: string) => { - if (constructionSector === "조선") { - return [ - { value: "A-max", label: "A-max" }, - { value: "S-max", label: "S-max" }, - { value: "VLCC", label: "VLCC" }, - { value: "LNGC", label: "LNGC" }, - { value: "CONT", label: "CONT" }, - ] - } else if (constructionSector === "해양") { - return [ - { value: "FPSO", label: "FPSO" }, - { value: "FLNG", label: "FLNG" }, - { value: "FPU", label: "FPU" }, - { value: "Platform", label: "Platform" }, - { value: "WTIV", label: "WTIV" }, - { value: "GOM", label: "GOM" }, - ] - } else { - // 공사부문이 선택되지 않은 경우 빈 배열 - return [] - } -} - const avlKindOptions = [ { value: "Nearshore", label: "Nearshore" }, { value: "Offshore", label: "Offshore" }, @@ -123,7 +102,9 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable // 검색 상태 const [searchConstructionSector, setSearchConstructionSector] = React.useState(initialConstructionSector || "") - const [searchShipType, setSearchShipType] = React.useState(initialShipType || "") + const [selectedShipType, setSelectedShipType] = React.useState<ShipTypeItem | undefined>( + initialShipType ? { CD: initialShipType, CDNM: initialShipType, displayText: initialShipType } : undefined + ) const [searchAvlKind, setSearchAvlKind] = React.useState(initialAvlKind || "") const [searchHtDivision, setSearchHtDivision] = React.useState(initialHtDivision || "") @@ -173,34 +154,29 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable const handleConstructionSectorChange = React.useCallback((value: string) => { setSearchConstructionSector(value) // 공사부문이 변경되면 선종을 빈 값으로 초기화 - setSearchShipType("") + setSelectedShipType(undefined) }, []) // 검색 상태 변경 시 부모 컴포넌트에 전달 React.useEffect(() => { onSearchConditionsChange?.({ constructionSector: searchConstructionSector, - shipType: searchShipType, + shipType: selectedShipType?.CD || "", avlKind: searchAvlKind, htDivision: searchHtDivision }) - }, [searchConstructionSector, searchShipType, searchAvlKind, searchHtDivision, onSearchConditionsChange]) + }, [searchConstructionSector, selectedShipType, searchAvlKind, searchHtDivision, onSearchConditionsChange]) - // 현재 공사부문에 따른 선종 옵션들 - const currentShipTypeOptions = React.useMemo(() => - getShipTypeOptions(searchConstructionSector), - [searchConstructionSector] - ) // 모든 검색 조건이 선택되었는지 확인 const isAllSearchConditionsSelected = React.useMemo(() => { return ( searchConstructionSector.trim() !== "" && - searchShipType.trim() !== "" && + selectedShipType?.CD?.trim() !== "" && searchAvlKind.trim() !== "" && searchHtDivision.trim() !== "" ) - }, [searchConstructionSector, searchShipType, searchAvlKind, searchHtDivision]) + }, [searchConstructionSector, selectedShipType, searchAvlKind, searchHtDivision]) // 데이터 로드 함수 const loadData = React.useCallback(async (searchParams: Partial<GetStandardAvlSchema> = {}) => { @@ -213,7 +189,7 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable sort: searchParams.sort ?? [{ id: "no", desc: false }], flags: searchParams.flags ?? [], constructionSector: searchConstructionSector, - shipType: searchShipType, + shipType: selectedShipType?.CD || "", avlKind: searchAvlKind, htDivision: searchHtDivision as "공통" | "H" | "T" | "", equipBulkDivision: searchParams.equipBulkDivision || "", @@ -249,7 +225,7 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable } finally { setLoading(false) } - }, [searchConstructionSector, searchShipType, searchAvlKind, searchHtDivision]) + }, [searchConstructionSector, selectedShipType, searchAvlKind, searchHtDivision]) // reloadTrigger가 변경될 때마다 데이터 리로드 React.useEffect(() => { @@ -262,7 +238,7 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable // 검색 초기화 핸들러 const handleResetSearch = React.useCallback(() => { setSearchConstructionSector("") - setSearchShipType("") + setSelectedShipType(undefined) setSearchAvlKind("") setSearchHtDivision("") // 초기화 시 빈 데이터로 설정 @@ -365,6 +341,9 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable } }, [table, loadData]) + // 최종 확정 다이얼로그 상태 + const [isConfirmDialogOpen, setIsConfirmDialogOpen] = React.useState(false) + // 최종 확정 핸들러 (표준 AVL) const handleFinalizeStandardAvl = React.useCallback(async () => { // 1. 필수 조건 검증 @@ -378,27 +357,20 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable return } - // 2. 사용자 확인 - const confirmed = window.confirm( - `현재 표준 AVL을 최종 확정하시겠습니까?\n\n` + - `- 공사부문: ${searchConstructionSector}\n` + - `- 선종: ${searchShipType}\n` + - `- AVL종류: ${searchAvlKind}\n` + - `- H/T 구분: ${searchHtDivision}\n` + - `- 벤더 정보: ${data.length}개\n\n` + - `확정 후에는 수정이 어려울 수 있습니다.` - ) - - if (!confirmed) return + // 2. 확인 다이얼로그 열기 + setIsConfirmDialogOpen(true) + }, [isAllSearchConditionsSelected, data.length]) + // 실제 최종 확정 실행 함수 + const executeFinalizeStandardAvl = React.useCallback(async () => { try { - // 3. 현재 데이터의 모든 ID 수집 + // 3. 현재 데이터의 모든 ID 수집 (전체 레코드 기준) const avlVendorInfoIds = data.map(item => item.id) // 4. 최종 확정 실행 const standardAvlInfo = { constructionSector: searchConstructionSector, - shipType: searchShipType, + shipType: selectedShipType?.CD || "", avlKind: searchAvlKind, htDivision: searchHtDivision } @@ -423,8 +395,10 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable } catch (error) { console.error("표준 AVL 최종 확정 실패:", error) toast.error("표준 AVL 최종 확정 중 오류가 발생했습니다.") + } finally { + setIsConfirmDialogOpen(false) } - }, [searchConstructionSector, searchShipType, searchAvlKind, searchHtDivision, isAllSearchConditionsSelected, data, table, loadData, sessionData?.user?.name]) + }, [searchConstructionSector, selectedShipType, searchAvlKind, searchHtDivision, data, table, loadData, sessionData?.user?.name]) // 초기 데이터 로드 (검색 조건이 모두 입력되었을 때만) React.useEffect(() => { @@ -437,7 +411,8 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable setData([]) setPageCount(0) } - }, [isAllSearchConditionsSelected, pagination.pageSize, searchConstructionSector, searchShipType, searchAvlKind, searchHtDivision]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isAllSearchConditionsSelected, pagination.pageSize, searchConstructionSector, selectedShipType, searchAvlKind, searchHtDivision]) @@ -547,18 +522,13 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable {/* 선종 */} <div className="space-y-2"> <label className="text-sm font-medium">선종</label> - <Select value={searchShipType} onValueChange={setSearchShipType}> - <SelectTrigger> - <SelectValue /> - </SelectTrigger> - <SelectContent> - {currentShipTypeOptions.map((option) => ( - <SelectItem key={option.value} value={option.value}> - {option.label} - </SelectItem> - ))} - </SelectContent> - </Select> + <ShipTypeSelector + selectedShipType={selectedShipType} + onShipTypeSelect={setSelectedShipType} + placeholder="선종을 선택하세요" + disabled={!searchConstructionSector} + className="h-10" + /> </div> {/* AVL종류 */} @@ -640,10 +610,40 @@ export const StandardAvlTable = forwardRef<StandardAvlTableRef, StandardAvlTable isTemplate={true} // 표준 AVL 모드 // 검색 조건에서 선택한 값들을 초기값으로 전달 initialConstructionSector={searchConstructionSector} - initialShipType={searchShipType} + initialShipType={selectedShipType?.CD || ""} initialAvlKind={searchAvlKind} initialHtDivision={searchHtDivision} /> + + {/* 최종 확정 확인 다이얼로그 */} + <Dialog open={isConfirmDialogOpen} onOpenChange={setIsConfirmDialogOpen}> + <DialogContent> + <DialogHeader> + <DialogTitle>표준 AVL 최종 확정</DialogTitle> + <DialogDescription> + 현재 표준 AVL을 최종 확정하시겠습니까? + </DialogDescription> + </DialogHeader> + <div className="space-y-2 text-sm"> + <div>• 공사부문: {searchConstructionSector}</div> + <div>• 선종: {selectedShipType?.CD || ""}</div> + <div>• AVL종류: {searchAvlKind}</div> + <div>• H/T 구분: {searchHtDivision}</div> + <div>• 벤더 정보: {data.length}개 (전체 레코드)</div> + {/* <div className="text-amber-600 font-medium mt-4"> + ⚠️ 확정 후 내용 수정을 필요로 하는 경우 동일 건을 다시 최종확정해 revision 처리로 수정해야 합니다. + </div> */} + </div> + <DialogFooter> + <Button variant="outline" onClick={() => setIsConfirmDialogOpen(false)}> + 취소 + </Button> + <Button onClick={executeFinalizeStandardAvl}> + 최종 확정 + </Button> + </DialogFooter> + </DialogContent> + </Dialog> </div> ) }) |
