summaryrefslogtreecommitdiff
path: root/lib/vendor-investigation/table/vendor-details-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vendor-investigation/table/vendor-details-dialog.tsx')
-rw-r--r--lib/vendor-investigation/table/vendor-details-dialog.tsx341
1 files changed, 341 insertions, 0 deletions
diff --git a/lib/vendor-investigation/table/vendor-details-dialog.tsx b/lib/vendor-investigation/table/vendor-details-dialog.tsx
new file mode 100644
index 00000000..27ed7826
--- /dev/null
+++ b/lib/vendor-investigation/table/vendor-details-dialog.tsx
@@ -0,0 +1,341 @@
+"use client"
+
+import * as React from "react"
+import { Building, Globe, Mail, MapPin, Phone, RefreshCw, Search } from "lucide-react"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+ DialogFooter,
+} from "@/components/ui/dialog"
+import { Button } from "@/components/ui/button"
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
+import { ScrollArea } from "@/components/ui/scroll-area"
+import { Skeleton } from "@/components/ui/skeleton"
+import { Badge } from "@/components/ui/badge"
+import { Separator } from "@/components/ui/separator"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { useToast } from "@/hooks/use-toast"
+
+// Import vendor service
+import { getVendorById, getVendorItemsByVendorId } from "@/lib/vendor-investigation/service"
+import { useRouter } from "next/navigation"
+
+interface VendorDetailsDialogProps {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ vendorId: number | null
+}
+
+export function VendorDetailsDialog({
+ open,
+ onOpenChange,
+ vendorId,
+}: VendorDetailsDialogProps) {
+ const { toast } = useToast()
+ const router = useRouter()
+ const [loading, setLoading] = React.useState(false)
+ const [vendorData, setVendorData] = React.useState<any>(null)
+ const [vendorItems, setVendorItems] = React.useState<any[]>([])
+ const [activeTab, setActiveTab] = React.useState("details")
+
+ // Fetch vendor details when the dialog opens
+ React.useEffect(() => {
+ if (open && vendorId) {
+ setLoading(true)
+
+ // Fetch vendor details
+ Promise.all([
+ getVendorById(vendorId),
+ getVendorItemsByVendorId(vendorId)
+ ])
+ .then(([vendorDetails, items]) => {
+ setVendorData(vendorDetails)
+ setVendorItems(items || [])
+ })
+ .catch((error) => {
+ console.error("Error fetching vendor data:", error)
+ toast({
+ title: "Error",
+ description: "Failed to load vendor details. Please try again.",
+ variant: "destructive",
+ })
+ })
+ .finally(() => {
+ setLoading(false)
+ })
+ } else {
+ // Reset state when the dialog closes
+ setVendorData(null)
+ setVendorItems([])
+ }
+ }, [open, vendorId, toast])
+
+ // Handle refresh button click
+ const handleRefresh = () => {
+ if (!vendorId) return
+
+ setLoading(true)
+ Promise.all([
+ getVendorById(vendorId),
+ getVendorItemsByVendorId(vendorId)
+ ])
+ .then(([vendorDetails, items]) => {
+ setVendorData(vendorDetails)
+ setVendorItems(items || [])
+ toast({
+ title: "Refreshed",
+ description: "Vendor information has been refreshed.",
+ })
+ })
+ .catch((error) => {
+ console.error("Error refreshing vendor data:", error)
+ toast({
+ title: "Error",
+ description: "Failed to refresh vendor details.",
+ variant: "destructive",
+ })
+ })
+ .finally(() => {
+ setLoading(false)
+ })
+ }
+
+ // Get vendor status badge variant
+ const getStatusVariant = (status: string) => {
+ switch (status?.toUpperCase()) {
+ case "ACTIVE":
+ return "default"
+ case "PENDING":
+ return "secondary"
+ case "SUSPENDED":
+ return "destructive"
+ case "APPROVED":
+ return "outline"
+ default:
+ return "secondary"
+ }
+ }
+
+ // Navigate to full vendor profile page
+ const navigateToVendorProfile = () => {
+ if (!vendorId) return
+
+ // Close dialog
+ onOpenChange(false)
+
+ // Navigate to vendor profile page with router
+ router.push(`/evcp/vendors/${vendorId}`)
+ }
+
+ return (
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent className="sm:max-w-[700px]">
+ <DialogHeader>
+ <div className="flex items-center justify-between">
+ <DialogTitle>협력업체 상세정보</DialogTitle>
+ <Button
+ variant="outline"
+ size="icon"
+ onClick={handleRefresh}
+ disabled={loading}
+ >
+ <RefreshCw className={`h-4 w-4 ${loading ? "animate-spin" : ""}`} />
+ <span className="sr-only">새로고침</span>
+ </Button>
+ </div>
+ <DialogDescription>
+ 협력업체 정보 상세보기
+ </DialogDescription>
+ </DialogHeader>
+
+ {loading ? (
+ <div className="space-y-4 py-4">
+ <div className="flex items-center space-x-4">
+ <Skeleton className="h-12 w-12 rounded-full" />
+ <div className="space-y-2">
+ <Skeleton className="h-4 w-[200px]" />
+ <Skeleton className="h-4 w-[150px]" />
+ </div>
+ </div>
+ <Skeleton className="h-[200px] w-full" />
+ </div>
+ ) : vendorData ? (
+ <div className="py-4">
+ {/* Vendor header with main info */}
+ <div className="flex items-start justify-between mb-6">
+ <div>
+ <h2 className="text-xl font-semibold">{vendorData.name}</h2>
+ <div className="flex items-center mt-1 space-x-2">
+ <span className="text-sm text-muted-foreground">업체코드: {vendorData.code}</span>
+ {vendorData.taxId && (
+ <>
+ <span className="text-muted-foreground">•</span>
+ <span className="text-sm text-muted-foreground">사업자등록번호: {vendorData.taxId}</span>
+ </>
+ )}
+ </div>
+ </div>
+ {vendorData.status && (
+ <Badge variant={getStatusVariant(vendorData.status)}>
+ {vendorData.status}
+ </Badge>
+ )}
+ </div>
+
+ <Tabs defaultValue="details" onValueChange={setActiveTab}>
+ <TabsList className="mb-4">
+ <TabsTrigger value="details">상세</TabsTrigger>
+ <TabsTrigger value="items">공급품목({vendorItems.length})</TabsTrigger>
+ </TabsList>
+
+ {/* Details Tab */}
+ <TabsContent value="details" className="space-y-4">
+ {/* Contact Information Card */}
+ <Card>
+ <CardHeader className="pb-2">
+ <CardTitle className="text-base">연락처 정보</CardTitle>
+ </CardHeader>
+ <CardContent className="space-y-2">
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+ {/* Email */}
+ <div className="flex items-center space-x-2">
+ <Mail className="h-4 w-4 text-muted-foreground" />
+ <span className="text-sm">{vendorData.email || "No email provided"}</span>
+ </div>
+
+ {/* Phone */}
+ <div className="flex items-center space-x-2">
+ <Phone className="h-4 w-4 text-muted-foreground" />
+ <span className="text-sm">{vendorData.phone || "No phone provided"}</span>
+ </div>
+
+ {/* Website */}
+ {vendorData.website && (
+ <div className="flex items-center space-x-2">
+ <Globe className="h-4 w-4 text-muted-foreground" />
+ <a
+ href={vendorData.website.startsWith('http') ? vendorData.website : `https://${vendorData.website}`}
+ target="_blank"
+ rel="noopener noreferrer"
+ className="text-sm text-blue-600 hover:underline"
+ >
+ {vendorData.website}
+ </a>
+ </div>
+ )}
+
+ {/* Address */}
+ {vendorData.address && (
+ <div className="flex items-center space-x-2">
+ <MapPin className="h-4 w-4 text-muted-foreground" />
+ <span className="text-sm">{vendorData.address}</span>
+ </div>
+ )}
+
+ {/* Country */}
+ {vendorData.country && (
+ <div className="flex items-center space-x-2">
+ <Building className="h-4 w-4 text-muted-foreground" />
+ <span className="text-sm">{vendorData.country}</span>
+ </div>
+ )}
+ </div>
+ </CardContent>
+ </Card>
+
+ {/* Additional Information */}
+ {vendorData.description && (
+ <Card>
+ <CardHeader className="pb-2">
+ <CardTitle className="text-base">협력업체 설명</CardTitle>
+ </CardHeader>
+ <CardContent>
+ <p className="text-sm">{vendorData.description}</p>
+ </CardContent>
+ </Card>
+ )}
+
+ {/* Registration Information */}
+ <Card>
+ <CardHeader className="pb-2">
+ <CardTitle className="text-base">등록 정보</CardTitle>
+ </CardHeader>
+ <CardContent>
+ <div className="grid grid-cols-2 gap-2">
+ <div>
+ <p className="text-xs text-muted-foreground">협력업체 생성일</p>
+ <p className="text-sm">
+ {vendorData.createdAt
+ ? new Date(vendorData.createdAt).toLocaleDateString()
+ : "Unknown"
+ }
+ </p>
+ </div>
+ <div>
+ <p className="text-xs text-muted-foreground">협력업체 정보 업데이트일</p>
+ <p className="text-sm">
+ {vendorData.updatedAt
+ ? new Date(vendorData.updatedAt).toLocaleDateString()
+ : "Unknown"
+ }
+ </p>
+ </div>
+ </div>
+ </CardContent>
+ </Card>
+ </TabsContent>
+
+ {/* Items Tab */}
+ <TabsContent value="items">
+ <ScrollArea className="h-[300px] pr-4">
+ {vendorItems.length > 0 ? (
+ <div className="space-y-4">
+ {vendorItems.map((item) => (
+ <Card key={item.id}>
+ <CardHeader className="pb-2">
+ <CardTitle className="text-base">{item.itemName}</CardTitle>
+ <CardDescription>Code: {item.itemCode}</CardDescription>
+ </CardHeader>
+ {item.description && (
+ <CardContent>
+ <p className="text-sm">{item.description}</p>
+ </CardContent>
+ )}
+ </Card>
+ ))}
+ </div>
+ ) : (
+ <div className="flex flex-col items-center justify-center h-full text-center p-8">
+ <Search className="h-8 w-8 text-muted-foreground mb-2" />
+ <h3 className="text-lg font-semibold">No items found</h3>
+ <p className="text-sm text-muted-foreground">해당 업체는 아직 공급품목이 등록되지 않았습니다.</p>
+ </div>
+ )}
+ </ScrollArea>
+ </TabsContent>
+
+ </Tabs>
+ </div>
+ ) : (
+ <div className="py-6 text-center">
+ <p className="text-muted-foreground">No vendor information available</p>
+ </div>
+ )}
+
+ <DialogFooter>
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
+ 닫기
+ </Button>
+ {vendorData && (
+ <Button onClick={navigateToVendorProfile}>
+ 전체 정보 보러가기
+ </Button>
+ )}
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ )
+} \ No newline at end of file