summaryrefslogtreecommitdiff
path: root/lib/tbe/table/invite-vendors-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tbe/table/invite-vendors-dialog.tsx')
-rw-r--r--lib/tbe/table/invite-vendors-dialog.tsx209
1 files changed, 0 insertions, 209 deletions
diff --git a/lib/tbe/table/invite-vendors-dialog.tsx b/lib/tbe/table/invite-vendors-dialog.tsx
deleted file mode 100644
index 59535278..00000000
--- a/lib/tbe/table/invite-vendors-dialog.tsx
+++ /dev/null
@@ -1,209 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { type Row } from "@tanstack/react-table"
-import { Loader, Send } from "lucide-react"
-import { toast } from "sonner"
-
-import { useMediaQuery } from "@/hooks/use-media-query"
-import { Button } from "@/components/ui/button"
-import {
- Dialog,
- DialogClose,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle,
- DialogTrigger,
-} from "@/components/ui/dialog"
-import {
- Drawer,
- DrawerClose,
- DrawerContent,
- DrawerDescription,
- DrawerFooter,
- DrawerHeader,
- DrawerTitle,
- DrawerTrigger,
-} from "@/components/ui/drawer"
-
-import { Input } from "@/components/ui/input"
-
-import { VendorWithTbeFields } from "@/config/vendorTbeColumnsConfig"
-import { inviteTbeVendorsAction } from "@/lib/rfqs/service"
-
-interface InviteVendorsDialogProps
- extends React.ComponentPropsWithoutRef<typeof Dialog> {
- vendors: Row<VendorWithTbeFields>["original"][]
- rfqId: number
- showTrigger?: boolean
- onSuccess?: () => void
- hasMultipleRfqIds?: boolean
-}
-
-export function InviteVendorsDialog({
- vendors,
- rfqId,
- showTrigger = true,
- onSuccess,
- hasMultipleRfqIds,
- ...props
-}: InviteVendorsDialogProps) {
- const [isInvitePending, startInviteTransition] = React.useTransition()
-
-
- // multiple 파일을 받을 state
- const [files, setFiles] = React.useState<FileList | null>(null)
-
- // 미디어쿼리 (desktop 여부)
- const isDesktop = useMediaQuery("(min-width: 640px)")
-
- function onInvite() {
- startInviteTransition(async () => {
- // 파일이 선택되지 않았다면 에러
- if (!files || files.length === 0) {
- toast.error("Please attach TBE files before inviting.")
- return
- }
-
- // FormData 생성
- const formData = new FormData()
- formData.append("rfqId", String(rfqId))
- vendors.forEach((vendor) => {
- formData.append("vendorIds[]", String(vendor.id))
- })
-
- // multiple 파일
- for (let i = 0; i < files.length; i++) {
- formData.append("tbeFiles", files[i]) // key는 동일하게 "tbeFiles"
- }
-
- // 서버 액션 호출
- const { error } = await inviteTbeVendorsAction(formData)
-
- if (error) {
- toast.error(error)
- return
- }
-
- // 성공
- props.onOpenChange?.(false)
- toast.success("Vendors invited with TBE!")
- onSuccess?.()
- })
- }
-
- // 파일 선택 UI
- const fileInput = (
- <div className="mb-4">
- <label className="mb-2 block font-medium">TBE Sheets</label>
- <Input
- type="file"
- multiple
- onChange={(e) => {
- setFiles(e.target.files)
- }}
- />
- </div>
- )
- if (hasMultipleRfqIds) {
- toast.error("동일한 RFQ에 대해 선택해주세요");
- return;
- }
- // Desktop Dialog
- if (isDesktop) {
- return (
-
- <Dialog {...props}>
- {showTrigger ? (
- <DialogTrigger asChild>
- <Button variant="outline" size="sm">
- <Send className="mr-2 size-4" aria-hidden="true" />
- Invite ({vendors.length})
- </Button>
- </DialogTrigger>
- ) : null}
- <DialogContent>
- <DialogHeader>
- <DialogTitle>Are you absolutely sure?</DialogTitle>
- <DialogDescription>
- This action cannot be undone. This will permanently invite{" "}
- <span className="font-medium">{vendors.length}</span>
- {vendors.length === 1 ? " vendor" : " vendors"}. 파일 첨부가 필수이므로 파일을 첨부해야지 버튼이 활성화됩니다.
- </DialogDescription>
- </DialogHeader>
-
- {/* 파일 첨부 */}
- {fileInput}
-
- <DialogFooter className="gap-2 sm:space-x-0">
- <DialogClose asChild>
- <Button variant="outline">Cancel</Button>
- </DialogClose>
- <Button
- aria-label="Invite selected rows"
- variant="destructive"
- onClick={onInvite}
- // 파일이 없거나 초대 진행중이면 비활성화
- disabled={isInvitePending || !files || files.length === 0}
- >
- {isInvitePending && (
- <Loader
- className="mr-2 size-4 animate-spin"
- aria-hidden="true"
- />
- )}
- Invite
- </Button>
- </DialogFooter>
- </DialogContent>
- </Dialog>
- )
- }
-
- // Mobile Drawer
- return (
- <Drawer {...props}>
- {showTrigger ? (
- <DrawerTrigger asChild>
- <Button variant="outline" size="sm">
- <Send className="mr-2 size-4" aria-hidden="true" />
- Invite ({vendors.length})
- </Button>
- </DrawerTrigger>
- ) : null}
- <DrawerContent>
- <DrawerHeader>
- <DrawerTitle>Are you absolutely sure?</DrawerTitle>
- <DrawerDescription>
- This action cannot be undone. This will permanently invite{" "}
- <span className="font-medium">{vendors.length}</span>
- {vendors.length === 1 ? " vendor" : " vendors"}.
- </DrawerDescription>
- </DrawerHeader>
-
- {/* 파일 첨부 */}
- {fileInput}
-
- <DrawerFooter className="gap-2 sm:space-x-0">
- <DrawerClose asChild>
- <Button variant="outline">Cancel</Button>
- </DrawerClose>
- <Button
- aria-label="Invite selected rows"
- variant="destructive"
- onClick={onInvite}
- // 파일이 없거나 초대 진행중이면 비활성화
- disabled={isInvitePending || !files || files.length === 0}
- >
- {isInvitePending && (
- <Loader className="mr-2 size-4 animate-spin" aria-hidden="true" />
- )}
- Invite
- </Button>
- </DrawerFooter>
- </DrawerContent>
- </Drawer>
- )
-} \ No newline at end of file