diff options
Diffstat (limited to 'lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx')
| -rw-r--r-- | lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx b/lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx index 8ce55d56..52758412 100644 --- a/lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx +++ b/lib/techsales-rfq/table/detail-table/rfq-detail-table.tsx @@ -22,6 +22,11 @@ import { TechSalesQuotationAttachmentsSheet, type QuotationAttachment } from ".. import type { QuotationInfo } from "./rfq-detail-column"
import { VendorContactSelectionDialog } from "./vendor-contact-selection-dialog"
import { QuotationContactsViewDialog } from "./quotation-contacts-view-dialog"
+import { ApprovalPreviewDialog } from "@/lib/approval/client"
+import { ApplicationReasonDialog } from "@/lib/rfq-last/vendor/application-reason-dialog"
+import { requestTechSalesRfqSendWithApproval } from "@/lib/techsales-rfq/approval-actions"
+import { mapTechSalesRfqSendToTemplateVariables } from "@/lib/techsales-rfq/approval-handlers"
+import { useSession } from "next-auth/react"
// 기본적인 RFQ 타입 정의
interface TechSalesRfq {
@@ -48,6 +53,8 @@ interface RfqDetailTablesProps { export function RfqDetailTables({ selectedRfq, maxHeight }: RfqDetailTablesProps) {
// console.log("selectedRfq", selectedRfq)
+ const session = useSession()
+
// 상태 관리
const [isLoading, setIsLoading] = useState(false)
const [details, setDetails] = useState<RfqDetailView[]>([])
@@ -89,6 +96,29 @@ export function RfqDetailTables({ selectedRfq, maxHeight }: RfqDetailTablesProps const [contactsDialogOpen, setContactsDialogOpen] = useState(false)
const [selectedQuotationForContacts, setSelectedQuotationForContacts] = useState<{ id: number; vendorName?: string } | null>(null)
+ // 결재 관련 상태 관리
+ const [showApplicationReasonDialog, setShowApplicationReasonDialog] = useState(false)
+ const [showApprovalPreview, setShowApprovalPreview] = useState(false)
+ const [approvalPreviewData, setApprovalPreviewData] = useState<{
+ vendors: Array<{
+ vendorId: number
+ vendorName: string
+ }>
+ drmAttachments: Array<{
+ fileName?: string | null
+ fileSize?: number | null
+ }>
+ drmAttachmentIds: number[]
+ selectedContacts?: Array<{
+ vendorId: number
+ contactId: number
+ contactEmail: string
+ contactName: string
+ }>
+ templateVariables?: Record<string, string>
+ applicationReason?: string
+ } | null>(null)
+
// selectedRfq ID 메모이제이션 (객체 참조 변경 방지)
const selectedRfqId = useMemo(() => selectedRfq?.id, [selectedRfq?.id])
@@ -239,6 +269,25 @@ export function RfqDetailTables({ selectedRfq, maxHeight }: RfqDetailTablesProps selectedContacts: selectedContacts
});
+ // DRM 파일이 있어서 결재가 필요한 경우
+ if (!result.success && result.requiresApproval) {
+ // 결재 데이터 저장
+ setApprovalPreviewData({
+ vendors: selectedRows.map(row => ({
+ vendorId: row.vendorId!,
+ vendorName: row.vendorName || "",
+ })),
+ drmAttachments: result.drmAttachments || [],
+ drmAttachmentIds: result.drmAttachmentIds || [],
+ selectedContacts: selectedContacts,
+ });
+
+ // 신청사유 입력 다이얼로그 표시
+ setShowApplicationReasonDialog(true);
+ setIsSendingRfq(false);
+ return;
+ }
+
if (result.success) {
toast.success(result.message || `${selectedContacts.length}명의 연락처에게 RFQ가 발송되었습니다.`);
} else {
@@ -412,6 +461,84 @@ export function RfqDetailTables({ selectedRfq, maxHeight }: RfqDetailTablesProps setContactsDialogOpen(true)
}, [])
+ // 신청사유 입력 완료 핸들러
+ const handleApplicationReasonConfirm = useCallback(async (reason: string) => {
+ if (!approvalPreviewData) {
+ toast.error("결재 데이터가 없습니다.");
+ return;
+ }
+
+ try {
+ // 템플릿 변수 생성 (신청사유 포함)
+ const templateVariables = await mapTechSalesRfqSendToTemplateVariables({
+ attachments: approvalPreviewData.drmAttachments,
+ vendorNames: approvalPreviewData.vendors.map(v => v.vendorName),
+ applicationReason: reason,
+ });
+
+ // 결재 미리보기 데이터 업데이트
+ setApprovalPreviewData({
+ ...approvalPreviewData,
+ templateVariables,
+ applicationReason: reason,
+ });
+
+ // 신청사유 다이얼로그 닫고 결재 미리보기 열기
+ setShowApplicationReasonDialog(false);
+ setShowApprovalPreview(true);
+ } catch (error) {
+ console.error("템플릿 변수 생성 실패:", error);
+ toast.error("결재 문서 생성에 실패했습니다.");
+ }
+ }, [approvalPreviewData]);
+
+ // 결재 미리보기 확인 핸들러
+ const handleApprovalConfirm = useCallback(async (approvalData: {
+ approvers: string[];
+ title: string;
+ description?: string;
+ }) => {
+ if (!approvalPreviewData || !selectedRfq || !session.data?.user) {
+ toast.error("결재 데이터가 없습니다.");
+ return;
+ }
+
+ if (!session.data.user.epId) {
+ toast.error("Knox EP ID가 필요합니다.");
+ return;
+ }
+
+ try {
+ const result = await requestTechSalesRfqSendWithApproval({
+ rfqId: selectedRfq.id,
+ rfqCode: selectedRfq.rfqCode || undefined,
+ vendorIds: approvalPreviewData.vendors.map(v => v.vendorId),
+ selectedContacts: approvalPreviewData.selectedContacts,
+ drmAttachmentIds: approvalPreviewData.drmAttachmentIds,
+ drmAttachments: approvalPreviewData.drmAttachments,
+ applicationReason: approvalPreviewData.applicationReason || '',
+ currentUser: {
+ id: Number(session.data.user.id),
+ epId: session.data.user.epId || null,
+ name: session.data.user.name || undefined,
+ email: session.data.user.email || undefined,
+ },
+ approvers: approvalData.approvers,
+ });
+
+ if (result.success) {
+ toast.success(result.message);
+ setShowApprovalPreview(false);
+ setApprovalPreviewData(null);
+ setSelectedRows([]);
+ await handleRefreshData();
+ }
+ } catch (error) {
+ console.error("결재 상신 실패:", error);
+ toast.error(error instanceof Error ? error.message : "결재 상신에 실패했습니다.");
+ }
+ }, [approvalPreviewData, selectedRfq, session, handleRefreshData]);
+
// 칼럼 정의 - unreadMessages 상태 전달 (메모이제이션)
const columns = useMemo(() =>
getRfqDetailColumns({
|
