diff options
Diffstat (limited to 'lib/vendors/table')
| -rw-r--r-- | lib/vendors/table/approve-vendor-dialog.tsx | 154 | ||||
| -rw-r--r-- | lib/vendors/table/vendors-table-toolbar-actions.tsx | 4 |
2 files changed, 127 insertions, 31 deletions
diff --git a/lib/vendors/table/approve-vendor-dialog.tsx b/lib/vendors/table/approve-vendor-dialog.tsx index 940710f5..980953aa 100644 --- a/lib/vendors/table/approve-vendor-dialog.tsx +++ b/lib/vendors/table/approve-vendor-dialog.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { type Row } from "@tanstack/react-table" -import { Loader, Check } from "lucide-react" +import { Loader, Check, X } from "lucide-react" import { toast } from "sonner" import { useMediaQuery } from "@/hooks/use-media-query" @@ -28,23 +28,24 @@ import { DrawerTrigger, } from "@/components/ui/drawer" import { Vendor } from "@/db/schema/vendors" -import { approveVendors } from "../service" +import { approveVendors, rejectVendors } from "../service" import { useSession } from "next-auth/react" -interface ApprovalVendorDialogProps +interface VendorDecisionDialogProps extends React.ComponentPropsWithoutRef<typeof Dialog> { vendors: Row<Vendor>["original"][] showTrigger?: boolean onSuccess?: () => void } -export function ApproveVendorsDialog({ +export function VendorDecisionDialog({ vendors, showTrigger = true, onSuccess, ...props -}: ApprovalVendorDialogProps) { +}: VendorDecisionDialogProps) { const [isApprovePending, startApproveTransition] = React.useTransition() + const [isRejectPending, startRejectTransition] = React.useTransition() const isDesktop = useMediaQuery("(min-width: 640px)") const { data: session } = useSession() @@ -58,10 +59,10 @@ export function ApproveVendorsDialog({ try { console.log("π [DEBUG] μΉμΈ μμ² μμ - vendors:", vendors.map(v => ({ id: v.id, vendorName: v.vendorName, email: v.email }))); console.log("π [DEBUG] μΈμ
μ 보:", { userId: session.user.id, userType: typeof session.user.id }); - + const { error } = await approveVendors({ ids: vendors.map((vendor) => vendor.id), - userId: Number(session.user.id) + userId: Number(session.user.id) }) if (error) { @@ -72,7 +73,40 @@ export function ApproveVendorsDialog({ console.log("β
[DEBUG] μΉμΈ μ²λ¦¬ μ±κ³΅"); props.onOpenChange?.(false) - toast.success("Vendors successfully approved for review") + toast.success("νλ ₯μ
체 λ±λ‘μ΄ μΉμΈλμμ΅λλ€.") + onSuccess?.() + } catch (error) { + console.error("π¨ [DEBUG] μμμΉ λͺ»ν μλ¬:", error); + toast.error("μμμΉ λͺ»ν μ€λ₯κ° λ°μνμ΅λλ€.") + } + }) + } + + function onReject() { + if (!session?.user?.id) { + toast.error("μ¬μ©μ μΈμ¦ μ 보λ₯Ό μ°Ύμ μ μμ΅λλ€.") + return + } + + startRejectTransition(async () => { + try { + console.log("π [DEBUG] κ±°μ μμ² μμ - vendors:", vendors.map(v => ({ id: v.id, vendorName: v.vendorName, email: v.email }))); + console.log("π [DEBUG] μΈμ
μ 보:", { userId: session.user.id, userType: typeof session.user.id }); + + const { error } = await rejectVendors({ + ids: vendors.map((vendor) => vendor.id), + userId: Number(session.user.id) + }) + + if (error) { + console.error("π¨ [DEBUG] κ±°μ μ²λ¦¬ μλ¬:", error); + toast.error(error) + return + } + + console.log("β
[DEBUG] κ±°μ μ²λ¦¬ μ±κ³΅"); + props.onOpenChange?.(false) + toast.success("νλ ₯μ
체 λ±λ‘μ΄ κ±°μ λμμ΅λλ€.") onSuccess?.() } catch (error) { console.error("π¨ [DEBUG] μμμΉ λͺ»ν μλ¬:", error); @@ -88,29 +122,58 @@ export function ApproveVendorsDialog({ <DialogTrigger asChild> <Button variant="outline" size="sm" className="gap-2"> <Check className="size-4" aria-hidden="true" /> - κ°μ
Approve ({vendors.length}) + κ°μ
κ²°μ ({vendors.length}) </Button> </DialogTrigger> ) : null} - <DialogContent> + <DialogContent className="max-w-2xl"> <DialogHeader> - <DialogTitle>Confirm Vendor Approval</DialogTitle> + <DialogTitle>νλ ₯μ
체 κ°μ
κ²°μ </DialogTitle> <DialogDescription> - Are you sure you want to approve{" "} - <span className="font-medium">{vendors.length}</span> - {vendors.length === 1 ? " vendor" : " vendors"}? - After approval, vendors will be notified and can login to submit PQ information. + μ νν <span className="font-medium">{vendors.length}</span>κ° νλ ₯μ
체μ λν κ°μ
κ²°μ μ ν΄μ£ΌμΈμ. </DialogDescription> </DialogHeader> + + {/* μ νν λ²€λ λͺ©λ‘ νμ */} + <div className="max-h-64 overflow-y-auto border rounded-md p-4"> + <h4 className="font-medium mb-2">μ νλ νλ ₯μ
체:</h4> + <div className="space-y-2"> + {vendors.map((vendor) => ( + <div key={vendor.id} className="flex items-center justify-between p-2 bg-gray-50 rounded"> + <div> + <div className="font-medium">{vendor.vendorName}</div> + <div className="text-sm text-gray-600">{vendor.email}</div> + </div> + <div className="text-sm text-gray-500">ID: {vendor.id}</div> + </div> + ))} + </div> + </div> + <DialogFooter className="gap-2 sm:space-x-0"> <DialogClose asChild> - <Button variant="outline">Cancel</Button> + <Button variant="outline">μ·¨μ</Button> </DialogClose> <Button + aria-label="Reject selected vendors" + variant="destructive" + onClick={onReject} + disabled={isRejectPending || isApprovePending} + > + {isRejectPending && ( + <Loader + className="mr-2 size-4 animate-spin" + aria-hidden="true" + /> + )} + <X className="mr-2 size-4" aria-hidden="true" /> + κ±°μ + </Button> + <Button aria-label="Approve selected vendors" variant="default" onClick={onApprove} - disabled={isApprovePending} + disabled={isApprovePending || isRejectPending} > {isApprovePending && ( <Loader @@ -118,7 +181,8 @@ export function ApproveVendorsDialog({ aria-hidden="true" /> )} - Approve + <Check className="mr-2 size-4" aria-hidden="true" /> + μΉμΈ </Button> </DialogFooter> </DialogContent> @@ -132,34 +196,66 @@ export function ApproveVendorsDialog({ <DrawerTrigger asChild> <Button variant="outline" size="sm" className="gap-2"> <Check className="size-4" aria-hidden="true" /> - Approve ({vendors.length}) + κ°μ
κ²°μ ({vendors.length}) </Button> </DrawerTrigger> ) : null} - <DrawerContent> + <DrawerContent className="max-h-[80vh]"> <DrawerHeader> - <DrawerTitle>Confirm Vendor Approval</DrawerTitle> + <DrawerTitle>νλ ₯μ
체 κ°μ
κ²°μ </DrawerTitle> <DrawerDescription> - Are you sure you want to approve{" "} - <span className="font-medium">{vendors.length}</span> - {vendors.length === 1 ? " vendor" : " vendors"}? - After approval, vendors will be notified and can login to submit PQ information. + μ νν <span className="font-medium">{vendors.length}</span>κ° νλ ₯μ
체μ λν κ°μ
κ²°μ μ ν΄μ£ΌμΈμ. </DrawerDescription> </DrawerHeader> + + {/* μ νν λ²€λ λͺ©λ‘ νμ */} + <div className="max-h-48 overflow-y-auto px-4"> + <h4 className="font-medium mb-2">μ νλ νλ ₯μ
체:</h4> + <div className="space-y-2"> + {vendors.map((vendor) => ( + <div key={vendor.id} className="flex items-center justify-between p-2 bg-gray-50 rounded"> + <div> + <div className="font-medium">{vendor.vendorName}</div> + <div className="text-sm text-gray-600">{vendor.email}</div> + </div> + <div className="text-sm text-gray-500">ID: {vendor.id}</div> + </div> + ))} + </div> + </div> + <DrawerFooter className="gap-2 sm:space-x-0"> <DrawerClose asChild> - <Button variant="outline">Cancel</Button> + <Button variant="outline">μ·¨μ</Button> </DrawerClose> <Button + aria-label="Reject selected vendors" + variant="destructive" + onClick={onReject} + disabled={isRejectPending || isApprovePending} + > + {isRejectPending && ( + <Loader + className="mr-2 size-4 animate-spin" + aria-hidden="true" + /> + )} + <X className="mr-2 size-4" aria-hidden="true" /> + κ±°μ + </Button> + <Button aria-label="Approve selected vendors" variant="default" onClick={onApprove} - disabled={isApprovePending} + disabled={isApprovePending || isRejectPending} > {isApprovePending && ( - <Loader className="mr-2 size-4 animate-spin" aria-hidden="true" /> + <Loader className="mr-2 size-4 animate-spin" + aria-hidden="true" + /> )} - Approve + <Check className="mr-2 size-4" aria-hidden="true" /> + μΉμΈ </Button> </DrawerFooter> </DrawerContent> diff --git a/lib/vendors/table/vendors-table-toolbar-actions.tsx b/lib/vendors/table/vendors-table-toolbar-actions.tsx index 3d77486d..def46168 100644 --- a/lib/vendors/table/vendors-table-toolbar-actions.tsx +++ b/lib/vendors/table/vendors-table-toolbar-actions.tsx @@ -15,7 +15,7 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { VendorWithType } from "@/db/schema/vendors" -import { ApproveVendorsDialog } from "./approve-vendor-dialog" +import { VendorDecisionDialog } from "./approve-vendor-dialog" import { RequestPQVendorsDialog } from "./request-vendor-pg-dialog" import { RequestPQDialog } from "./request-pq-dialog" import { RequestProjectPQDialog } from "./request-project-pq-dialog" @@ -147,7 +147,7 @@ export function VendorsTableToolbarActions({ table }: VendorsTableToolbarActions <div className="flex items-center gap-2"> {/* μΉμΈ λ€μ΄μΌλ‘κ·Έ: PENDING_REVIEW μνμΈ νλ ₯μ
μ²΄κ° μμ λλ§ νμ */} {pendingReviewVendors.length > 0 && ( - <ApproveVendorsDialog + <VendorDecisionDialog vendors={pendingReviewVendors} onSuccess={() => table.toggleAllRowsSelected(false)} /> |
