summaryrefslogtreecommitdiff
path: root/lib/tech-vendor-possible-items/table
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tech-vendor-possible-items/table')
-rw-r--r--lib/tech-vendor-possible-items/table/add-possible-item-dialog.tsx822
-rw-r--r--lib/tech-vendor-possible-items/table/possible-items-data-table.tsx33
-rw-r--r--lib/tech-vendor-possible-items/table/possible-items-table-columns.tsx86
-rw-r--r--lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx247
4 files changed, 595 insertions, 593 deletions
diff --git a/lib/tech-vendor-possible-items/table/add-possible-item-dialog.tsx b/lib/tech-vendor-possible-items/table/add-possible-item-dialog.tsx
index cdce60af..85a551ea 100644
--- a/lib/tech-vendor-possible-items/table/add-possible-item-dialog.tsx
+++ b/lib/tech-vendor-possible-items/table/add-possible-item-dialog.tsx
@@ -1,450 +1,450 @@
-"use client";
+// "use client";
-import * as React from "react";
-import { Search, Plus, X } from "lucide-react";
+// import * as React from "react";
+// import { Search, Plus, X } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogHeader,
- DialogTitle,
- DialogTrigger,
-} from "@/components/ui/dialog";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Badge } from "@/components/ui/badge";
-import { useToast } from "@/hooks/use-toast";
-import {
- getAllTechVendors,
- createTechVendorPossibleItem,
- getItemsByVendorType
-} from "@/lib/tech-vendor-possible-items/service";
+// import { Button } from "@/components/ui/button";
+// import {
+// Dialog,
+// DialogContent,
+// DialogDescription,
+// DialogHeader,
+// DialogTitle,
+// DialogTrigger,
+// } from "@/components/ui/dialog";
+// import { Input } from "@/components/ui/input";
+// import { Label } from "@/components/ui/label";
+// import { Badge } from "@/components/ui/badge";
+// import { useToast } from "@/hooks/use-toast";
+// import {
+// getAllTechVendors,
+// createTechVendorPossibleItem,
+// getItemsByVendorType
+// } from "@/lib/tech-vendor-possible-items/service";
-interface TechVendor {
- id: number;
- vendorCode: string | null;
- vendorName: string;
- techVendorType: string;
-}
+// interface TechVendor {
+// id: number;
+// vendorCode: string | null;
+// vendorName: string;
+// techVendorType: string;
+// }
-interface ItemData {
- itemCode: string;
- itemList: string | null;
- workType: string | null;
- shipTypes?: string | null;
- subItemList?: string | null;
-}
+// interface ItemData {
+// itemCode: string;
+// itemList: string | null;
+// workType: string | null;
+// shipTypes?: string | null;
+// subItemList?: string | null;
+// }
-interface AddPossibleItemDialogProps {
- children?: React.ReactNode;
- onSuccess?: () => void;
-}
+// interface AddPossibleItemDialogProps {
+// children?: React.ReactNode;
+// onSuccess?: () => void;
+// }
-export function AddPossibleItemDialog({
- children,
- onSuccess
-}: AddPossibleItemDialogProps) {
- const { toast } = useToast();
- const [open, setOpen] = React.useState(false);
+// export function AddPossibleItemDialog({
+// children,
+// onSuccess
+// }: AddPossibleItemDialogProps) {
+// const { toast } = useToast();
+// const [open, setOpen] = React.useState(false);
- // 벤더 관련 상태
- const [vendors, setVendors] = React.useState<TechVendor[]>([]);
- const [filteredVendors, setFilteredVendors] = React.useState<TechVendor[]>([]);
- const [vendorSearch, setVendorSearch] = React.useState("");
- const [selectedVendor, setSelectedVendor] = React.useState<TechVendor | null>(null);
+// // 벤더 관련 상태
+// const [vendors, setVendors] = React.useState<TechVendor[]>([]);
+// const [filteredVendors, setFilteredVendors] = React.useState<TechVendor[]>([]);
+// const [vendorSearch, setVendorSearch] = React.useState("");
+// const [selectedVendor, setSelectedVendor] = React.useState<TechVendor | null>(null);
- // 아이템 관련 상태
- const [items, setItems] = React.useState<ItemData[]>([]);
- const [filteredItems, setFilteredItems] = React.useState<ItemData[]>([]);
- const [itemSearch, setItemSearch] = React.useState("");
- const [selectedItems, setSelectedItems] = React.useState<ItemData[]>([]);
+// // 아이템 관련 상태
+// const [items, setItems] = React.useState<ItemData[]>([]);
+// const [filteredItems, setFilteredItems] = React.useState<ItemData[]>([]);
+// const [itemSearch, setItemSearch] = React.useState("");
+// const [selectedItems, setSelectedItems] = React.useState<ItemData[]>([]);
- const [isLoading, setIsLoading] = React.useState(false);
+// const [isLoading, setIsLoading] = React.useState(false);
- // 벤더 목록 로드
- React.useEffect(() => {
- if (open) {
- loadVendors();
- }
- }, [open]);
+// // 벤더 목록 로드
+// React.useEffect(() => {
+// if (open) {
+// loadVendors();
+// }
+// }, [open]);
- // 벤더 검색 필터링
- React.useEffect(() => {
- if (!vendorSearch) {
- setFilteredVendors(vendors);
- } else {
- const filtered = vendors.filter(vendor =>
- vendor.vendorName.toLowerCase().includes(vendorSearch.toLowerCase()) ||
- vendor.vendorCode?.toLowerCase().includes(vendorSearch.toLowerCase())
- );
- setFilteredVendors(filtered);
- }
- }, [vendors, vendorSearch]);
+// // 벤더 검색 필터링
+// React.useEffect(() => {
+// if (!vendorSearch) {
+// setFilteredVendors(vendors);
+// } else {
+// const filtered = vendors.filter(vendor =>
+// vendor.vendorName.toLowerCase().includes(vendorSearch.toLowerCase()) ||
+// vendor.vendorCode?.toLowerCase().includes(vendorSearch.toLowerCase())
+// );
+// setFilteredVendors(filtered);
+// }
+// }, [vendors, vendorSearch]);
- // 아이템 검색 필터링
- React.useEffect(() => {
- if (!itemSearch) {
- setFilteredItems(items);
- } else {
- const filtered = items.filter(item =>
- item.itemCode.toLowerCase().includes(itemSearch.toLowerCase()) ||
- item.itemList?.toLowerCase().includes(itemSearch.toLowerCase()) ||
- item.workType?.toLowerCase().includes(itemSearch.toLowerCase())
- );
- setFilteredItems(filtered);
- }
- }, [items, itemSearch]);
+// // 아이템 검색 필터링
+// React.useEffect(() => {
+// if (!itemSearch) {
+// setFilteredItems(items);
+// } else {
+// const filtered = items.filter(item =>
+// item.itemCode.toLowerCase().includes(itemSearch.toLowerCase()) ||
+// item.itemList?.toLowerCase().includes(itemSearch.toLowerCase()) ||
+// item.workType?.toLowerCase().includes(itemSearch.toLowerCase())
+// );
+// setFilteredItems(filtered);
+// }
+// }, [items, itemSearch]);
- const loadVendors = async () => {
- try {
- setIsLoading(true);
- const vendorData = await getAllTechVendors();
- setVendors(vendorData);
- } catch (error) {
- console.error("Failed to load vendors:", error);
- toast({
- title: "오류",
- description: "벤더 목록을 불러오는데 실패했습니다.",
- variant: "destructive",
- });
- } finally {
- setIsLoading(false);
- }
- };
+// const loadVendors = async () => {
+// try {
+// setIsLoading(true);
+// const vendorData = await getAllTechVendors();
+// setVendors(vendorData);
+// } catch (error) {
+// console.error("Failed to load vendors:", error);
+// toast({
+// title: "오류",
+// description: "벤더 목록을 불러오는데 실패했습니다.",
+// variant: "destructive",
+// });
+// } finally {
+// setIsLoading(false);
+// }
+// };
- const loadItemsByVendorType = async (vendorTypes: string) => {
- try {
- setIsLoading(true);
- console.log("Loading items for vendor types:", vendorTypes);
- const itemData = await getItemsByVendorType(vendorTypes);
- console.log("Loaded items:", itemData.length, itemData);
- setItems(itemData);
- } catch (error) {
- console.error("Failed to load items:", error);
- toast({
- title: "오류",
- description: "아이템 목록을 불러오는데 실패했습니다.",
- variant: "destructive",
- });
- } finally {
- setIsLoading(false);
- }
- };
+// const loadItemsByVendorType = async (vendorTypes: string) => {
+// try {
+// setIsLoading(true);
+// console.log("Loading items for vendor types:", vendorTypes);
+// const itemData = await getItemsByVendorType(vendorTypes);
+// console.log("Loaded items:", itemData.length, itemData);
+// setItems(itemData);
+// } catch (error) {
+// console.error("Failed to load items:", error);
+// toast({
+// title: "오류",
+// description: "아이템 목록을 불러오는데 실패했습니다.",
+// variant: "destructive",
+// });
+// } finally {
+// setIsLoading(false);
+// }
+// };
- const handleVendorSelect = (vendor: TechVendor) => {
- setSelectedVendor(vendor);
- setSelectedItems([]); // 벤더 변경시 선택된 아이템 초기화
- loadItemsByVendorType(vendor.techVendorType);
- };
+// const handleVendorSelect = (vendor: TechVendor) => {
+// setSelectedVendor(vendor);
+// setSelectedItems([]); // 벤더 변경시 선택된 아이템 초기화
+// loadItemsByVendorType(vendor.techVendorType);
+// };
- const handleItemToggle = (item: ItemData) => {
- setSelectedItems(prev => {
- const isSelected = prev.some(i => i.itemCode === item.itemCode);
- if (isSelected) {
- return prev.filter(i => i.itemCode !== item.itemCode);
- } else {
- return [...prev, item];
- }
- });
- };
+// const handleItemToggle = (item: ItemData) => {
+// setSelectedItems(prev => {
+// const isSelected = prev.some(i => i.itemCode === item.itemCode);
+// if (isSelected) {
+// return prev.filter(i => i.itemCode !== item.itemCode);
+// } else {
+// return [...prev, item];
+// }
+// });
+// };
- const handleSubmit = async () => {
- if (!selectedVendor || selectedItems.length === 0) return;
+// const handleSubmit = async () => {
+// if (!selectedVendor || selectedItems.length === 0) return;
- try {
- setIsLoading(true);
- let successCount = 0;
- let errorCount = 0;
+// try {
+// setIsLoading(true);
+// let successCount = 0;
+// let errorCount = 0;
- for (const item of selectedItems) {
- const result = await createTechVendorPossibleItem({
- vendorId: selectedVendor.id,
- itemCode: item.itemCode,
- workType: item.workType,
- shipTypes: item.shipTypes,
- itemList: item.itemList,
- subItemList: item.subItemList,
- });
+// for (const item of selectedItems) {
+// const result = await createTechVendorPossibleItem({
+// vendorId: selectedVendor.id,
+// itemCode: item.itemCode,
+// workType: item.workType,
+// shipTypes: item.shipTypes,
+// itemList: item.itemList,
+// subItemList: item.subItemList,
+// });
- if (result.success) {
- successCount++;
- } else {
- errorCount++;
- }
- }
+// if (result.success) {
+// successCount++;
+// } else {
+// errorCount++;
+// }
+// }
- if (successCount > 0) {
- toast({
- title: "성공",
- description: `${successCount}개의 아이템이 추가되었습니다.${errorCount > 0 ? ` (${errorCount}개 실패)` : ""}`,
- });
+// if (successCount > 0) {
+// toast({
+// title: "성공",
+// description: `${successCount}개의 아이템이 추가되었습니다.${errorCount > 0 ? ` (${errorCount}개 실패)` : ""}`,
+// });
- handleClose();
- onSuccess?.();
- } else {
- toast({
- title: "오류",
- description: "아이템 추가에 실패했습니다.",
- variant: "destructive",
- });
- }
- } catch (error) {
- console.error("Failed to add items:", error);
- toast({
- title: "오류",
- description: "아이템 추가 중 오류가 발생했습니다.",
- variant: "destructive",
- });
- } finally {
- setIsLoading(false);
- }
- };
+// handleClose();
+// onSuccess?.();
+// } else {
+// toast({
+// title: "오류",
+// description: "아이템 추가에 실패했습니다.",
+// variant: "destructive",
+// });
+// }
+// } catch (error) {
+// console.error("Failed to add items:", error);
+// toast({
+// title: "오류",
+// description: "아이템 추가 중 오류가 발생했습니다.",
+// variant: "destructive",
+// });
+// } finally {
+// setIsLoading(false);
+// }
+// };
- const handleClose = () => {
- setOpen(false);
- setTimeout(() => {
- setSelectedVendor(null);
- setSelectedItems([]);
- setVendorSearch("");
- setItemSearch("");
- setVendors([]);
- setItems([]);
- setFilteredVendors([]);
- setFilteredItems([]);
- }, 200);
- };
+// const handleClose = () => {
+// setOpen(false);
+// setTimeout(() => {
+// setSelectedVendor(null);
+// setSelectedItems([]);
+// setVendorSearch("");
+// setItemSearch("");
+// setVendors([]);
+// setItems([]);
+// setFilteredVendors([]);
+// setFilteredItems([]);
+// }, 200);
+// };
- const parseVendorTypes = (vendorType: string): string[] => {
- if (!vendorType) return [];
+// const parseVendorTypes = (vendorType: string): string[] => {
+// if (!vendorType) return [];
- // JSON 배열 형태인지 확인
- if (vendorType.startsWith('[') && vendorType.endsWith(']')) {
- try {
- const parsed = JSON.parse(vendorType);
- return Array.isArray(parsed) ? parsed.filter(Boolean) : [vendorType];
- } catch {
- return [vendorType];
- }
- }
+// // JSON 배열 형태인지 확인
+// if (vendorType.startsWith('[') && vendorType.endsWith(']')) {
+// try {
+// const parsed = JSON.parse(vendorType);
+// return Array.isArray(parsed) ? parsed.filter(Boolean) : [vendorType];
+// } catch {
+// return [vendorType];
+// }
+// }
- // 콤마로 구분된 문자열인지 확인
- if (vendorType.includes(',')) {
- return vendorType.split(',').map(t => t.trim()).filter(Boolean);
- }
+// // 콤마로 구분된 문자열인지 확인
+// if (vendorType.includes(',')) {
+// return vendorType.split(',').map(t => t.trim()).filter(Boolean);
+// }
- // 단일 문자열
- return [vendorType.trim()].filter(Boolean);
- };
+// // 단일 문자열
+// return [vendorType.trim()].filter(Boolean);
+// };
- return (
- <Dialog open={open} onOpenChange={setOpen}>
- <DialogTrigger asChild>
- {children || (
- <Button size="sm">
- <Plus className="mr-2 h-4 w-4" />
- 추가
- </Button>
- )}
- </DialogTrigger>
- <DialogContent className="max-w-6xl max-h-[90vh] flex flex-col">
- <DialogHeader>
- <DialogTitle>
- 벤더별 아이템 추가
- </DialogTitle>
- <DialogDescription>
- 왼쪽에서 벤더를 선택하고, 오른쪽에서 아이템을 선택하세요.
- </DialogDescription>
- </DialogHeader>
+// return (
+// <Dialog open={open} onOpenChange={setOpen}>
+// <DialogTrigger asChild>
+// {children || (
+// <Button size="sm">
+// <Plus className="mr-2 h-4 w-4" />
+// 추가
+// </Button>
+// )}
+// </DialogTrigger>
+// <DialogContent className="max-w-6xl max-h-[90vh] flex flex-col">
+// <DialogHeader>
+// <DialogTitle>
+// 벤더별 아이템 추가
+// </DialogTitle>
+// <DialogDescription>
+// 왼쪽에서 벤더를 선택하고, 오른쪽에서 아이템을 선택하세요.
+// </DialogDescription>
+// </DialogHeader>
- <div className="flex-1 min-h-0">
- <div className="grid grid-cols-2 gap-4 h-[500px]">
- {/* 왼쪽: 벤더 선택/표시 */}
- <div className="space-y-4 h-full flex flex-col">
- {!selectedVendor ? (
- <>
- <div className="space-y-2">
- <Label htmlFor="vendor-search">벤더 검색</Label>
- <div className="relative">
- <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-4 w-4" /> <Input
- id="vendor-search"
- placeholder="벤더명 또는 벤더코드로 검색..."
- value={vendorSearch}
- onChange={(e) => setVendorSearch(e.target.value)}
- className="pl-10"
- />
- </div>
- </div>
+// <div className="flex-1 min-h-0">
+// <div className="grid grid-cols-2 gap-4 h-[500px]">
+// {/* 왼쪽: 벤더 선택/표시 */}
+// <div className="space-y-4 h-full flex flex-col">
+// {!selectedVendor ? (
+// <>
+// <div className="space-y-2">
+// <Label htmlFor="vendor-search">벤더 검색</Label>
+// <div className="relative">
+// <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-4 w-4" /> <Input
+// id="vendor-search"
+// placeholder="벤더명 또는 벤더코드로 검색..."
+// value={vendorSearch}
+// onChange={(e) => setVendorSearch(e.target.value)}
+// className="pl-10"
+// />
+// </div>
+// </div>
- <div className="max-h-96 overflow-y-auto border rounded-lg bg-gray-50 p-2">
- <div className="space-y-2">
- {isLoading ? (
- <div className="text-center py-4">로딩 중...</div>
- ) : filteredVendors.length === 0 ? (
- <div className="text-center py-4 text-muted-foreground">
- 검색 결과가 없습니다.
- </div>
- ) : (
- filteredVendors.map((vendor) => (
- <div
- key={vendor.id}
- className="p-3 bg-white border rounded-lg cursor-pointer transition-colors hover:bg-gray-50"
- onClick={() => handleVendorSelect(vendor)}
- >
- <div className="font-medium">{vendor.vendorName}</div>
- <div className="text-sm text-muted-foreground">
- {vendor.vendorCode}
- </div>
- <div className="flex flex-wrap gap-1 mt-2">
- {parseVendorTypes(vendor.techVendorType).map((type, index) => (
- <Badge key={`${vendor.id}-${type}-${index}`} variant="secondary" className="text-xs">
- {type}
- </Badge>
- ))}
- </div>
- </div>
- ))
- )}
- </div>
- </div>
- </>
- ) : (
- <div className="space-y-4">
- <div className="flex items-center justify-between">
- <Label>선택된 벤더</Label>
- <Button
- variant="outline"
- size="sm"
- onClick={() => {
- setSelectedVendor(null);
- setSelectedItems([]);
- setItems([]);
- setFilteredItems([]);
- }}
- >
- 변경
- </Button>
- </div>
- <div className="p-4 border rounded-md bg-muted/20">
- <div className="font-medium">{selectedVendor?.vendorName}</div>
- <div className="text-sm text-muted-foreground">
- {selectedVendor?.vendorCode}
- </div>
- <div className="flex flex-wrap gap-1 mt-2">
- {selectedVendor && parseVendorTypes(selectedVendor.techVendorType).map((type, index) => (
- <Badge key={`selected-${type}-${index}`} variant="outline" className="text-xs">
- {type}
- </Badge>
- ))}
- </div>
- </div>
- </div>
- )}
- </div>
+// <div className="max-h-96 overflow-y-auto border rounded-lg bg-gray-50 p-2">
+// <div className="space-y-2">
+// {isLoading ? (
+// <div className="text-center py-4">로딩 중...</div>
+// ) : filteredVendors.length === 0 ? (
+// <div className="text-center py-4 text-muted-foreground">
+// 검색 결과가 없습니다.
+// </div>
+// ) : (
+// filteredVendors.map((vendor) => (
+// <div
+// key={vendor.id}
+// className="p-3 bg-white border rounded-lg cursor-pointer transition-colors hover:bg-gray-50"
+// onClick={() => handleVendorSelect(vendor)}
+// >
+// <div className="font-medium">{vendor.vendorName}</div>
+// <div className="text-sm text-muted-foreground">
+// {vendor.vendorCode}
+// </div>
+// <div className="flex flex-wrap gap-1 mt-2">
+// {parseVendorTypes(vendor.techVendorType).map((type, index) => (
+// <Badge key={`${vendor.id}-${type}-${index}`} variant="secondary" className="text-xs">
+// {type}
+// </Badge>
+// ))}
+// </div>
+// </div>
+// ))
+// )}
+// </div>
+// </div>
+// </>
+// ) : (
+// <div className="space-y-4">
+// <div className="flex items-center justify-between">
+// <Label>선택된 벤더</Label>
+// <Button
+// variant="outline"
+// size="sm"
+// onClick={() => {
+// setSelectedVendor(null);
+// setSelectedItems([]);
+// setItems([]);
+// setFilteredItems([]);
+// }}
+// >
+// 변경
+// </Button>
+// </div>
+// <div className="p-4 border rounded-md bg-muted/20">
+// <div className="font-medium">{selectedVendor?.vendorName}</div>
+// <div className="text-sm text-muted-foreground">
+// {selectedVendor?.vendorCode}
+// </div>
+// <div className="flex flex-wrap gap-1 mt-2">
+// {selectedVendor && parseVendorTypes(selectedVendor.techVendorType).map((type, index) => (
+// <Badge key={`selected-${type}-${index}`} variant="outline" className="text-xs">
+// {type}
+// </Badge>
+// ))}
+// </div>
+// </div>
+// </div>
+// )}
+// </div>
- {/* 오른쪽: 아이템 선택 */}
- <div className="space-y-4 h-full flex flex-col">
- {selectedVendor ? (
- <>
+// {/* 오른쪽: 아이템 선택 */}
+// <div className="space-y-4 h-full flex flex-col">
+// {selectedVendor ? (
+// <>
- <Label htmlFor="item-search">아이템 검색</Label>
- <div className="relative">
- <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-4 w-4" /> <Input
- id="item-search"
- placeholder="아이템코드, 아이템리스트, 공종으로 검색..."
- value={itemSearch}
- onChange={(e) => setItemSearch(e.target.value)}
- className="pl-10"
- />
- </div>
+// <Label htmlFor="item-search">아이템 검색</Label>
+// <div className="relative">
+// <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-4 w-4" /> <Input
+// id="item-search"
+// placeholder="아이템코드, 아이템리스트, 공종으로 검색..."
+// value={itemSearch}
+// onChange={(e) => setItemSearch(e.target.value)}
+// className="pl-10"
+// />
+// </div>
- {selectedItems.length > 0 && (
- <div className="space-y-2">
- <Label>선택된 아이템 ({selectedItems.length}개)</Label>
- <div className="flex flex-wrap gap-1 p-2 border rounded-md bg-muted/50 max-h-20 overflow-y-auto">
- {selectedItems.map((item) => (
- <Badge key={`selected-${item.itemCode}`} variant="default" className="text-xs">
- {item.itemCode}
- <X
- className="ml-1 h-3 w-3 cursor-pointer"
- onClick={(e) => {
- e.stopPropagation();
- handleItemToggle(item);
- }}
- />
- </Badge>
- ))}
- </div>
- </div>
- )}
+// {selectedItems.length > 0 && (
+// <div className="space-y-2">
+// <Label>선택된 아이템 ({selectedItems.length}개)</Label>
+// <div className="flex flex-wrap gap-1 p-2 border rounded-md bg-muted/50 max-h-20 overflow-y-auto">
+// {selectedItems.map((item) => (
+// <Badge key={`selected-${item.itemCode}`} variant="default" className="text-xs">
+// {item.itemCode}
+// <X
+// className="ml-1 h-3 w-3 cursor-pointer"
+// onClick={(e) => {
+// e.stopPropagation();
+// handleItemToggle(item);
+// }}
+// />
+// </Badge>
+// ))}
+// </div>
+// </div>
+// )}
- <div className="max-h-80 overflow-y-auto border rounded-lg bg-gray-50 p-2">
- <div className="space-y-2">
- {isLoading ? (
- <div className="text-center py-4">아이템 로딩 중...</div>
- ) : filteredItems.length === 0 && items.length === 0 ? (
- <div className="text-center py-4 text-muted-foreground">
- 해당 벤더 타입에 대한 아이템이 없습니다.
- </div>
- ) : filteredItems.length === 0 ? (
- <div className="text-center py-4 text-muted-foreground">
- 검색 결과가 없습니다.
- </div>
- ) : (
- filteredItems.map((item) => {
- const isSelected = selectedItems.some(i => i.itemCode === item.itemCode);
- return (
- <div
- key={`item-${item.itemCode}`}
- className={`p-3 bg-white border rounded-lg cursor-pointer transition-colors ${
- isSelected
- ? "bg-primary/10 border-primary hover:bg-primary/20"
- : "hover:bg-gray-50"
- }`}
- onClick={() => handleItemToggle(item)}
- >
- <div className="font-medium">{item.itemCode}</div>
- <div className="text-sm text-muted-foreground">
- {item.itemList || "-"}
- </div>
- <div className="flex gap-2 mt-1 text-xs">
- <span>공종: {item.workType || "-"}</span>
- {item.shipTypes && <span>선종: {item.shipTypes}</span>}
- {item.subItemList && <span>서브아이템: {item.subItemList}</span>}
- </div>
- </div>
- );
- })
- )}
- </div>
- </div>
- </>
- ) : (
- <div className="flex-1 flex items-center justify-center text-muted-foreground">
- 왼쪽에서 벤더를 선택하세요.
- </div>
- )}
- </div>
- </div>
- </div>
+// <div className="max-h-80 overflow-y-auto border rounded-lg bg-gray-50 p-2">
+// <div className="space-y-2">
+// {isLoading ? (
+// <div className="text-center py-4">아이템 로딩 중...</div>
+// ) : filteredItems.length === 0 && items.length === 0 ? (
+// <div className="text-center py-4 text-muted-foreground">
+// 해당 벤더 타입에 대한 아이템이 없습니다.
+// </div>
+// ) : filteredItems.length === 0 ? (
+// <div className="text-center py-4 text-muted-foreground">
+// 검색 결과가 없습니다.
+// </div>
+// ) : (
+// filteredItems.map((item) => {
+// const isSelected = selectedItems.some(i => i.itemCode === item.itemCode);
+// return (
+// <div
+// key={`item-${item.itemCode}`}
+// className={`p-3 bg-white border rounded-lg cursor-pointer transition-colors ${
+// isSelected
+// ? "bg-primary/10 border-primary hover:bg-primary/20"
+// : "hover:bg-gray-50"
+// }`}
+// onClick={() => handleItemToggle(item)}
+// >
+// <div className="font-medium">{item.itemCode}</div>
+// <div className="text-sm text-muted-foreground">
+// {item.itemList || "-"}
+// </div>
+// <div className="flex gap-2 mt-1 text-xs">
+// <span>공종: {item.workType || "-"}</span>
+// {item.shipTypes && <span>선종: {item.shipTypes}</span>}
+// {item.subItemList && <span>서브아이템: {item.subItemList}</span>}
+// </div>
+// </div>
+// );
+// })
+// )}
+// </div>
+// </div>
+// </>
+// ) : (
+// <div className="flex-1 flex items-center justify-center text-muted-foreground">
+// 왼쪽에서 벤더를 선택하세요.
+// </div>
+// )}
+// </div>
+// </div>
+// </div>
- <div className="flex justify-end gap-2 pt-4 border-t">
- <Button variant="outline" onClick={handleClose}>
- 취소
- </Button>
- <Button
- onClick={handleSubmit}
- disabled={!selectedVendor || selectedItems.length === 0 || isLoading}
- >
- {isLoading ? "추가 중..." : `추가 (${selectedItems.length})`}
- </Button>
- </div>
- </DialogContent>
- </Dialog>
- );
-} \ No newline at end of file
+// <div className="flex justify-end gap-2 pt-4 border-t">
+// <Button variant="outline" onClick={handleClose}>
+// 취소
+// </Button>
+// <Button
+// onClick={handleSubmit}
+// disabled={!selectedVendor || selectedItems.length === 0 || isLoading}
+// >
+// {isLoading ? "추가 중..." : `추가 (${selectedItems.length})`}
+// </Button>
+// </div>
+// </DialogContent>
+// </Dialog>
+// );
+// } \ No newline at end of file
diff --git a/lib/tech-vendor-possible-items/table/possible-items-data-table.tsx b/lib/tech-vendor-possible-items/table/possible-items-data-table.tsx
index 28b9774f..42417059 100644
--- a/lib/tech-vendor-possible-items/table/possible-items-data-table.tsx
+++ b/lib/tech-vendor-possible-items/table/possible-items-data-table.tsx
@@ -9,21 +9,8 @@ import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-adv
import { getColumns } from "./possible-items-table-columns";
import { PossibleItemsTableToolbarActions } from "./possible-items-table-toolbar-actions";
-// 타입만 import
-type TechVendorPossibleItemsData = {
- id: number;
- vendorId: number;
- vendorCode: string | null;
- vendorName: string;
- techVendorType: string;
- itemCode: string;
- itemList: string | null;
- workType: string | null;
- shipTypes: string | null;
- subItemList: string | null;
- createdAt: Date;
- updatedAt: Date;
-};
+// 새로운 스키마에 맞는 타입 import
+import type { TechVendorPossibleItemsData } from "../service";
import type { DataTableAdvancedFilterField } from "@/types/table";
interface PossibleItemsDataTableProps {
@@ -51,6 +38,22 @@ export function PossibleItemsDataTable({ promises }: PossibleItemsDataTableProps
type: "text",
},
{
+ id: "vendorEmail",
+ label: "벤더이메일",
+ type: "text",
+ },
+ {
+ id: "vendorStatus",
+ label: "벤더상태",
+ type: "multi-select",
+ options: [
+ { label: "ACTIVE", value: "ACTIVE", count: 0 },
+ { label: "PENDING_INVITE", value: "PENDING_INVITE", count: 0 },
+ { label: "PENDING_REVIEW", value: "PENDING_REVIEW", count: 0 },
+ { label: "INACTIVE", value: "INACTIVE", count: 0 },
+ ],
+ },
+ {
id: "itemCode",
label: "아이템코드",
type: "text",
diff --git a/lib/tech-vendor-possible-items/table/possible-items-table-columns.tsx b/lib/tech-vendor-possible-items/table/possible-items-table-columns.tsx
index 7fdcc900..e9707a88 100644
--- a/lib/tech-vendor-possible-items/table/possible-items-table-columns.tsx
+++ b/lib/tech-vendor-possible-items/table/possible-items-table-columns.tsx
@@ -4,22 +4,8 @@ import { ColumnDef } from "@tanstack/react-table";
import { Checkbox } from "@/components/ui/checkbox";
import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header";
import Link from "next/link";
-// 타입만 import
-type TechVendorPossibleItemsData = {
- id: number;
- vendorId: number;
- vendorCode: string | null;
- vendorName: string;
- techVendorType: string;
- vendorStatus: string;
- itemCode: string;
- itemList: string | null;
- workType: string | null;
- shipTypes: string | null;
- subItemList: string | null;
- createdAt: Date;
- updatedAt: Date;
-};
+// 새로운 스키마에 맞는 타입 import
+import type { TechVendorPossibleItemsData } from "../service";
import { format } from "date-fns";
import { ko } from "date-fns/locale";
import { Badge } from "@/components/ui/badge";
@@ -153,6 +139,22 @@ export function getColumns(): ColumnDef<TechVendorPossibleItemsData>[] {
},
},
{
+ accessorKey: "vendorEmail",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="벤더이메일" />
+ ),
+ cell: ({ row }) => {
+ const vendorEmail = row.getValue("vendorEmail") as string | null;
+ return <div className="max-w-[200px] truncate">{vendorEmail || "-"}</div>;
+ },
+ filterFn: (row, id, value) => {
+ const vendorEmail = row.getValue(id) as string | null;
+ if (!value) return true;
+ if (!vendorEmail) return false;
+ return vendorEmail.toLowerCase().includes(value.toLowerCase());
+ },
+ },
+ {
accessorKey: "techVendorType",
header: ({ column }) => (
<DataTableColumnHeaderSimple column={column} title="벤더타입" />
@@ -216,29 +218,35 @@ export function getColumns(): ColumnDef<TechVendorPossibleItemsData>[] {
},
},
- {
- accessorKey: "vendorStatus",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="벤더상태" />
- ),
- cell: ({ row }) => {
- const vendorStatus = row.getValue("vendorStatus") as string;
- const getStatusColor = (status: string) => {
- switch (status) {
- case "ACTIVE": return "bg-green-100 text-green-800";
- case "PENDING_INVITE": return "bg-yellow-100 text-yellow-800";
- case "PENDING_REVIEW": return "bg-blue-100 text-blue-800";
- case "INACTIVE": return "bg-gray-100 text-gray-800";
- default: return "bg-gray-100 text-gray-800";
- }
- };
- return (
- <Badge className={getStatusColor(vendorStatus)}>
- {vendorStatus}
- </Badge>
- );
- },
- },
+ // {
+ // accessorKey: "vendorStatus",
+ // header: ({ column }) => (
+ // <DataTableColumnHeaderSimple column={column} title="벤더상태" />
+ // ),
+ // cell: ({ row }) => {
+ // const vendorStatus = row.getValue("vendorStatus") as string;
+ // const getStatusColor = (status: string) => {
+ // switch (status) {
+ // case "ACTIVE": return "bg-green-100 text-green-800";
+ // case "PENDING_INVITE": return "bg-yellow-100 text-yellow-800";
+ // case "PENDING_REVIEW": return "bg-blue-100 text-blue-800";
+ // case "INACTIVE": return "bg-gray-100 text-gray-800";
+ // default: return "bg-gray-100 text-gray-800";
+ // }
+ // };
+ // return (
+ // <Badge className={getStatusColor(vendorStatus)}>
+ // {vendorStatus}
+ // </Badge>
+ // );
+ // },
+ // filterFn: (row, id, value) => {
+ // const vendorStatus = row.getValue(id) as string;
+ // if (!value) return true;
+ // if (!vendorStatus) return false;
+ // return vendorStatus === value;
+ // },
+ // },
{
accessorKey: "createdAt",
header: ({ column }) => (
diff --git a/lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx b/lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx
index dc67221f..2914fb9c 100644
--- a/lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx
+++ b/lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx
@@ -2,152 +2,143 @@
import * as React from "react";
import { type Table } from "@tanstack/react-table";
-import { Download, Upload, FileSpreadsheet, Plus } from "lucide-react";
+// import { Plus } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { useToast } from "@/hooks/use-toast";
-import { AddPossibleItemDialog } from "./add-possible-item-dialog";
-import { DeletePossibleItemsDialog } from "./delete-possible-items-dialog";
-// Excel 함수들을 동적 import로만 사용하기 위해 타입만 import
-type TechVendorPossibleItemsData = {
- id: number;
- vendorId: number;
- vendorCode: string | null;
- vendorName: string;
- techVendorType: string;
- itemCode: string;
- itemList: string | null;
- workType: string | null;
- shipTypes: string | null;
- subItemList: string | null;
- createdAt: Date;
- updatedAt: Date;
-};
+// import { Button } from "@/components/ui/button";
+// import { Input } from "@/components/ui/input"; // 주석처리 (Excel 기능 사용 안함)
+// import { useToast } from "@/hooks/use-toast"; // 주석처리 (Excel 기능 사용 안함)
+// import { AddPossibleItemDialog } from "./add-possible-item-dialog";
+// import { DeletePossibleItemsDialog } from "./delete-possible-items-dialog";
+// 새로운 스키마에 맞는 타입 import
+import type { TechVendorPossibleItemsData } from "../service";
interface PossibleItemsTableToolbarActionsProps {
table: Table<TechVendorPossibleItemsData>;
}
export function PossibleItemsTableToolbarActions({
- table,
+ // table,
}: PossibleItemsTableToolbarActionsProps) {
- const { toast } = useToast();
+ // const { toast } = useToast(); // 주석처리 (Excel 기능 사용 안함)
- const selectedRows = table.getFilteredSelectedRowModel().rows;
- const hasSelection = selectedRows.length > 0;
- const selectedItems = selectedRows.map(row => row.original);
+ // const selectedRows = table.getFilteredSelectedRowModel().rows;
+ // const hasSelection = selectedRows.length > 0;
+ // const selectedItems = selectedRows.map(row => row.original);
- const handleSuccess = () => {
- table.toggleAllRowsSelected(false);
- // 페이지 새로고침이나 데이터 다시 로드 필요
- window.location.reload();
- };
+ // const handleSuccess = () => {
+ // table.toggleAllRowsSelected(false);
+ // // 페이지 새로고침이나 데이터 다시 로드 필요
+ // window.location.reload();
+ // };
- const handleExport = async () => {
- try {
- const { exportTechVendorPossibleItemsToExcel } = await import("./excel-export");
- const result = await exportTechVendorPossibleItemsToExcel(table.getFilteredRowModel().rows.map(row => row.original));
-
- if (result.success) {
- toast({
- title: "성공",
- description: "Excel 파일이 다운로드되었습니다.",
- });
- } else {
- toast({
- title: "오류",
- description: result.error || "내보내기 중 오류가 발생했습니다.",
- variant: "destructive",
- });
- }
- } catch (error) {
- console.error("Export error:", error);
- toast({
- title: "오류",
- description: "내보내기 중 오류가 발생했습니다.",
- variant: "destructive",
- });
- }
- };
+ // Excel Export 함수 주석처리 (새 스키마에서 사용하지 않음)
+ // const handleExport = async () => {
+ // try {
+ // const { exportTechVendorPossibleItemsToExcel } = await import("./excel-export");
+ // const result = await exportTechVendorPossibleItemsToExcel(table.getFilteredRowModel().rows.map(row => row.original));
+ //
+ // if (result.success) {
+ // toast({
+ // title: "성공",
+ // description: "Excel 파일이 다운로드되었습니다.",
+ // });
+ // } else {
+ // toast({
+ // title: "오류",
+ // description: result.error || "내보내기 중 오류가 발생했습니다.",
+ // variant: "destructive",
+ // });
+ // }
+ // } catch (error) {
+ // console.error("Export error:", error);
+ // toast({
+ // title: "오류",
+ // description: "내보내기 중 오류가 발생했습니다.",
+ // variant: "destructive",
+ // });
+ // }
+ // };
- const handleImport = async (event: React.ChangeEvent<HTMLInputElement>) => {
- const file = event.target.files?.[0];
- if (!file) return;
+ // Excel Import 함수 주석처리 (새 스키마에서 사용하지 않음)
+ // const handleImport = async (event: React.ChangeEvent<HTMLInputElement>) => {
+ // const file = event.target.files?.[0];
+ // if (!file) return;
- try {
- const { importTechVendorPossibleItemsFromExcel } = await import("./excel-import");
- const result = await importTechVendorPossibleItemsFromExcel(file);
-
- if (result.success) {
- toast({
- title: "성공",
- description: `${result.successCount}개의 아이템이 가져와졌습니다.`,
- });
- // 페이지 새로고침이나 데이터 다시 로드 필요
- window.location.reload();
- } else {
- toast({
- title: "가져오기 완료",
- description: `${result.successCount}개 성공, ${result.failedRows.length}개 실패`,
- variant: result.successCount > 0 ? "default" : "destructive",
- });
- }
- } catch (error) {
- console.error("Import error:", error);
- toast({
- title: "오류",
- description: "가져오기 중 오류가 발생했습니다.",
- variant: "destructive",
- });
- }
+ // try {
+ // const { importTechVendorPossibleItemsFromExcel } = await import("./excel-import");
+ // const result = await importTechVendorPossibleItemsFromExcel(file);
+ //
+ // if (result.success) {
+ // toast({
+ // title: "성공",
+ // description: `${result.successCount}개의 아이템이 가져와졌습니다.`,
+ // });
+ // // 페이지 새로고침이나 데이터 다시 로드 필요
+ // window.location.reload();
+ // } else {
+ // toast({
+ // title: "가져오기 완료",
+ // description: `${result.successCount}개 성공, ${result.failedRows.length}개 실패`,
+ // variant: result.successCount > 0 ? "default" : "destructive",
+ // });
+ // }
+ // } catch (error) {
+ // console.error("Import error:", error);
+ // toast({
+ // title: "오류",
+ // description: "가져오기 중 오류가 발생했습니다.",
+ // variant: "destructive",
+ // });
+ // }
- // Reset input
- event.target.value = "";
- };
+ // // Reset input
+ // event.target.value = "";
+ // };
- const handleDownloadTemplate = async () => {
- try {
- const { exportTechVendorPossibleItemsTemplate } = await import("./excel-template");
- const result = await exportTechVendorPossibleItemsTemplate();
- if (result.success) {
- toast({
- title: "성공",
- description: "템플릿 파일이 다운로드되었습니다.",
- });
- } else {
- toast({
- title: "오류",
- description: result.error || "템플릿 다운로드 중 오류가 발생했습니다.",
- variant: "destructive",
- });
- }
- } catch (error) {
- console.error("Template download error:", error);
- toast({
- title: "오류",
- description: "템플릿 다운로드 중 오류가 발생했습니다.",
- variant: "destructive",
- });
- }
- };
+ // Excel Template 함수 주석처리 (새 스키마에서 사용하지 않음)
+ // const handleDownloadTemplate = async () => {
+ // try {
+ // const { exportTechVendorPossibleItemsTemplate } = await import("./excel-template");
+ // const result = await exportTechVendorPossibleItemsTemplate();
+ // if (result.success) {
+ // toast({
+ // title: "성공",
+ // description: "템플릿 파일이 다운로드되었습니다.",
+ // });
+ // } else {
+ // toast({
+ // title: "오류",
+ // description: result.error || "템플릿 다운로드 중 오류가 발생했습니다.",
+ // variant: "destructive",
+ // });
+ // }
+ // } catch (error) {
+ // console.error("Template download error:", error);
+ // toast({
+ // title: "오류",
+ // description: "템플릿 다운로드 중 오류가 발생했습니다.",
+ // variant: "destructive",
+ // });
+ // }
+ // };
return (
<div className="flex items-center gap-2">
- {hasSelection && (
- <DeletePossibleItemsDialog
- selectedItems={selectedItems}
- onSuccess={handleSuccess}
- />
- )}
- <AddPossibleItemDialog onSuccess={handleSuccess}>
- <Button size="sm">
- <Plus className="mr-2 h-4 w-4" />
- 추가
- </Button>
- </AddPossibleItemDialog>
+ {/* {hasSelection && ( */}
+ {/* // <DeletePo ssibleItemsDialog
+ // selectedItems={selectedItems}
+ // onSuccess={handleSuccess}
+ // />
+ // )}
+ // <AddPossibleItemDialog onSuccess={handleSuccess}>
+ // <Button size="sm">
+ // <Plus className="mr-2 h-4 w-4" />
+ // 추가
+ // </Button>
+ // </AddPossibleItemDialog>
- <Button
+ {/* Excel 관련 버튼들 주석처리 (새 스키마에서 사용하지 않음) */}
+ {/* <Button
variant="outline"
size="sm"
onClick={() => document.getElementById("import-file")?.click()}
@@ -173,7 +164,7 @@ export function PossibleItemsTableToolbarActions({
<Button variant="outline" size="sm" onClick={handleDownloadTemplate}>
<FileSpreadsheet className="mr-2 h-4 w-4" />
Download Template
- </Button>
+ </Button> */}
</div>
);
} \ No newline at end of file