diff options
Diffstat (limited to 'lib/vendors/table')
| -rw-r--r-- | lib/vendors/table/approve-vendor-dialog.tsx | 31 | ||||
| -rw-r--r-- | lib/vendors/table/request-pq-dialog.tsx | 115 | ||||
| -rw-r--r-- | lib/vendors/table/vendors-table-toolbar-actions.tsx | 2 |
3 files changed, 123 insertions, 25 deletions
diff --git a/lib/vendors/table/approve-vendor-dialog.tsx b/lib/vendors/table/approve-vendor-dialog.tsx index 9c175dc5..940710f5 100644 --- a/lib/vendors/table/approve-vendor-dialog.tsx +++ b/lib/vendors/table/approve-vendor-dialog.tsx @@ -55,20 +55,29 @@ export function ApproveVendorsDialog({ } startApproveTransition(async () => { - const { error } = await approveVendors({ - ids: vendors.map((vendor) => vendor.id), - userId: Number(session.user.id) + 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) + }) - }) + if (error) { + console.error("π¨ [DEBUG] μΉμΈ μ²λ¦¬ μλ¬:", error); + toast.error(error) + return + } - if (error) { - toast.error(error) - return + console.log("β
[DEBUG] μΉμΈ μ²λ¦¬ μ±κ³΅"); + props.onOpenChange?.(false) + toast.success("Vendors successfully approved for review") + onSuccess?.() + } catch (error) { + console.error("π¨ [DEBUG] μμμΉ λͺ»ν μλ¬:", error); + toast.error("μμμΉ λͺ»ν μ€λ₯κ° λ°μνμ΅λλ€.") } - - props.onOpenChange?.(false) - toast.success("Vendors successfully approved for review") - onSuccess?.() }) } diff --git a/lib/vendors/table/request-pq-dialog.tsx b/lib/vendors/table/request-pq-dialog.tsx index 20388f71..14a1cd01 100644 --- a/lib/vendors/table/request-pq-dialog.tsx +++ b/lib/vendors/table/request-pq-dialog.tsx @@ -37,6 +37,7 @@ import { Checkbox } from "@/components/ui/checkbox" import { Label } from "@/components/ui/label"
import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge"
+import { Progress } from "@/components/ui/progress"
import { Vendor } from "@/db/schema/vendors"
import { requestBasicContractInfo, requestPQVendors } from "../service"
import { getProjectsWithPQList } from "@/lib/pq/service"
@@ -98,6 +99,11 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro // λΉλ°μ μ§ κ³μ½μ 첨λΆνμΌ κ΄λ ¨ μν
const [ndaAttachments, setNdaAttachments] = React.useState<File[]>([])
const [isUploadingNdaFiles, setIsUploadingNdaFiles] = React.useState(false)
+
+ // νλ‘κ·Έλ μ€ κ΄λ ¨ μν
+ const [progressValue, setProgressValue] = React.useState(0)
+ const [currentStep, setCurrentStep] = React.useState("")
+ const [showProgress, setShowProgress] = React.useState(false)
// μμ΄ν
κ²μ νν°λ§
React.useEffect(() => {
@@ -180,6 +186,9 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro setShowItemDropdown(false)
setNdaAttachments([])
setIsUploadingNdaFiles(false)
+ setProgressValue(0)
+ setCurrentStep("")
+ setShowProgress(false)
}
}, [props.open])
@@ -235,9 +244,22 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro if (!dueDate) return toast.error("λ§κ°μΌμ μ ννμΈμ.")
if (!session?.user?.id) return toast.error("μΈμ¦ μ€ν¨")
+ // νλ‘κ·Έλ μ€ λ°λ₯Ό μ¦μ νμ
+ setShowProgress(true)
+ setProgressValue(0)
+ setCurrentStep("μμ μ€...")
+
startApproveTransition(async () => {
try {
+
+ // μ 체 λ¨κ³ μ κ³μ°
+ const totalSteps = 1 +
+ (selectedTemplateIds.length > 0 ? 1 : 0) +
+ (isNdaTemplateSelected() && ndaAttachments.length > 0 ? 1 : 0)
+ let completedSteps = 0
+
// 1λ¨κ³: PQ μμ±
+ setCurrentStep("PQ μμ± μ€...")
console.log("π PQ μμ± μμ")
const { error: pqError } = await requestPQVendors({
ids: vendors.map((v) => v.id),
@@ -252,9 +274,13 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro })
if (pqError) {
+ setShowProgress(false)
toast.error(`PQ μμ± μ€ν¨: ${pqError}`)
return
}
+
+ completedSteps++
+ setProgressValue((completedSteps / totalSteps) * 100)
console.log("β
PQ μμ± μλ£")
toast.success("PQκ° μ±κ³΅μ μΌλ‘ μμ²λμμ΅λλ€")
@@ -264,12 +290,17 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro selectedTemplateIds.includes(t.id)
)
+ setCurrentStep(`κΈ°λ³Έκ³μ½μ μμ± μ€... (${templates.length}κ° ν
νλ¦Ώ)`)
console.log("π κΈ°λ³Έκ³μ½μ λ°±κ·ΈλΌμ΄λ μ²λ¦¬ μμ", templates.length, "κ° ν
νλ¦Ώ")
await processBasicContractsInBackground(templates, vendors)
+
+ completedSteps++
+ setProgressValue((completedSteps / totalSteps) * 100)
}
// 3λ¨κ³: λΉλ°μ μ§ κ³μ½μ 첨λΆνμΌμ΄ μλ κ²½μ° μ μ₯
if (isNdaTemplateSelected() && ndaAttachments.length > 0) {
+ setCurrentStep(`λΉλ°μ μ§ κ³μ½μ 첨λΆνμΌ μ μ₯ μ€... (${ndaAttachments.length}κ° νμΌ)`)
console.log("π λΉλ°μ μ§ κ³μ½μ 첨λΆνμΌ μ²λ¦¬ μμ", ndaAttachments.length, "κ° νμΌ")
const ndaResult = await saveNdaAttachments({
@@ -283,14 +314,24 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro } else {
toast.error(`첨λΆνμΌ μ²λ¦¬ μ€ μΌλΆ μ€λ₯κ° λ°μνμ΅λλ€: ${ndaResult.error}`)
}
+
+ completedSteps++
+ setProgressValue((completedSteps / totalSteps) * 100)
}
- // μλ£ ν λ€μ΄μΌλ‘κ·Έ λ«κΈ°
- props.onOpenChange?.(false)
- onSuccess?.()
+ setCurrentStep("μλ£!")
+ setProgressValue(100)
+
+ // μ μ μλ£ μνλ₯Ό 보μ¬μ€ ν λ€μ΄μΌλ‘κ·Έ λ«κΈ°
+ setTimeout(() => {
+ setShowProgress(false)
+ props.onOpenChange?.(false)
+ onSuccess?.()
+ }, 1000)
} catch (error) {
console.error('PQ μμ± μ€λ₯:', error)
+ setShowProgress(false)
toast.error(`μ²λ¦¬ μ€ μ€λ₯κ° λ°μνμ΅λλ€: ${error instanceof Error ? error.message : 'μ μ μλ μ€λ₯'}`)
}
})
@@ -328,6 +369,13 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro const template = templates[templateIndex]
processedCount++
+ // μ§νλ₯ μ
λ°μ΄νΈ (2λ¨κ³ λ²μ λ΄μμ)
+ const baseProgress = 33.33 // 1λ¨κ³ μλ£ ν
+ const contractProgress = (processedCount / totalContracts) * 33.33 // 2λ¨κ³λ 33.33% μ°¨μ§
+ const newProgress = baseProgress + contractProgress
+ setProgressValue(newProgress)
+ setCurrentStep(`κΈ°λ³Έκ³μ½μ μμ± μ€... (${processedCount}/${totalContracts})`)
+
console.log(`π μ²λ¦¬ μ€: ${vendor.vendorName} - ${template.templateName} (${processedCount}/${totalContracts})`)
// κ°λ³ λ²€λμ λν κΈ°λ³Έκ³μ½ μμ±
@@ -720,11 +768,31 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro <div className="flex-1 overflow-y-auto">
{dialogContent}
</div>
- <DialogFooter>
- <DialogClose asChild><Button variant="outline">μ·¨μ</Button></DialogClose>
- <Button onClick={onApprove} disabled={isApprovePending || !type || (type === "PROJECT" && !selectedProjectId)}>
- {isApprovePending && <Loader className="mr-2 size-4 animate-spin" />}μμ²νκΈ°
- </Button>
+ <DialogFooter className="flex-col gap-4">
+ {/* νλ‘κ·Έλ μ€ λ° */}
+ {(showProgress || isApprovePending) && (
+ <div className="w-full space-y-2">
+ <div className="flex items-center justify-between text-sm">
+ <span className="text-muted-foreground">{currentStep || "μ²λ¦¬ μ€..."}</span>
+ <span className="font-medium">{Math.round(progressValue)}%</span>
+ </div>
+ <Progress value={progressValue} className="w-full" />
+ </div>
+ )}
+
+ {/* λ²νΌλ€ */}
+ <div className="flex justify-end gap-2">
+ <DialogClose asChild>
+ <Button variant="outline" disabled={isApprovePending}>μ·¨μ</Button>
+ </DialogClose>
+ <Button
+ onClick={onApprove}
+ disabled={isApprovePending || !type || (type === "PROJECT" && !selectedProjectId)}
+ >
+ {isApprovePending && <Loader className="mr-2 size-4 animate-spin" />}
+ μμ²νκΈ°
+ </Button>
+ </div>
</DialogFooter>
</DialogContent>
@@ -753,11 +821,32 @@ export function RequestPQDialog({ vendors, showTrigger = true, onSuccess, ...pro <div className="flex-1 overflow-y-auto px-4">
{dialogContent}
</div>
- <DrawerFooter>
- <DrawerClose asChild><Button variant="outline">μ·¨μ</Button></DrawerClose>
- <Button onClick={onApprove} disabled={isApprovePending || !type || (type === "PROJECT" && !selectedProjectId)}>
- {isApprovePending && <Loader className="mr-2 size-4 animate-spin" />}μμ²νκΈ°
- </Button>
+ <DrawerFooter className="gap-4">
+ {/* νλ‘κ·Έλ μ€ λ° */}
+ {(showProgress || isApprovePending) && (
+ <div className="w-full space-y-2">
+ <div className="flex items-center justify-between text-sm">
+ <span className="text-muted-foreground">{currentStep || "μ²λ¦¬ μ€..."}</span>
+ <span className="font-medium">{Math.round(progressValue)}%</span>
+ </div>
+ <Progress value={progressValue} className="w-full" />
+ </div>
+ )}
+
+ {/* λ²νΌλ€ */}
+ <div className="flex gap-2">
+ <DrawerClose asChild>
+ <Button variant="outline" disabled={isApprovePending} className="flex-1">μ·¨μ</Button>
+ </DrawerClose>
+ <Button
+ onClick={onApprove}
+ disabled={isApprovePending || !type || (type === "PROJECT" && !selectedProjectId)}
+ className="flex-1"
+ >
+ {isApprovePending && <Loader className="mr-2 size-4 animate-spin" />}
+ μμ²νκΈ°
+ </Button>
+ </div>
</DrawerFooter>
</DrawerContent>
diff --git a/lib/vendors/table/vendors-table-toolbar-actions.tsx b/lib/vendors/table/vendors-table-toolbar-actions.tsx index 6d5f7425..3d77486d 100644 --- a/lib/vendors/table/vendors-table-toolbar-actions.tsx +++ b/lib/vendors/table/vendors-table-toolbar-actions.tsx @@ -83,7 +83,7 @@ export function VendorsTableToolbarActions({ table }: VendorsTableToolbarActions .rows .map(row => row.original) .filter(vendor => - ["PENDING_REVIEW", "IN_REVIEW", "IN_PQ", "PQ_APPROVED", "APPROVED", "READY_TO_SEND", "ACTIVE"].includes(vendor.status) + ["IN_REVIEW", "IN_PQ", "PQ_APPROVED", "APPROVED", "READY_TO_SEND", "ACTIVE"].includes(vendor.status) ); }, [table.getFilteredSelectedRowModel().rows]); |
