diff options
Diffstat (limited to 'lib/bidding/failure')
| -rw-r--r-- | lib/bidding/failure/biddings-closure-dialog.tsx | 53 | ||||
| -rw-r--r-- | lib/bidding/failure/biddings-failure-table.tsx | 131 |
2 files changed, 100 insertions, 84 deletions
diff --git a/lib/bidding/failure/biddings-closure-dialog.tsx b/lib/bidding/failure/biddings-closure-dialog.tsx index f331167b..cea1f42a 100644 --- a/lib/bidding/failure/biddings-closure-dialog.tsx +++ b/lib/bidding/failure/biddings-closure-dialog.tsx @@ -4,7 +4,6 @@ import { useState } from "react" import { useSession } from "next-auth/react" import { toast } from "sonner" -import { requestBiddingClosureWithApproval } from "@/lib/bidding/approval-actions" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" @@ -21,58 +20,41 @@ interface BiddingsClosureDialogProps { biddingNumber: string; } | null; onSuccess?: () => void; + onApprovalPreview: (data: { description: string; files: File[]; biddingId: number }) => Promise<void>; } export function BiddingsClosureDialog({ open, onOpenChange, bidding, - onSuccess + onSuccess, + onApprovalPreview }: BiddingsClosureDialogProps) { const { data: session } = useSession() const [description, setDescription] = useState('') const [files, setFiles] = useState<File[]>([]) - const [isSubmitting, setIsSubmitting] = useState(false) - const handleSubmit = async (e: React.FormEvent) => { + const handleNextStep = async (e: React.FormEvent) => { e.preventDefault() - + if (!bidding || !description.trim()) { toast.error('폐찰 사유를 입력해주세요.') return } - - setIsSubmitting(true) try { - const result = await requestBiddingClosureWithApproval({ - biddingId: bidding.id, + // 결재자 선택 단계로 데이터 전달 + await onApprovalPreview({ description: description.trim(), - files, - currentUser: { - id: session?.user?.id ? Number(session.user.id) : 0, - epId: session?.user?.epId || null, - email: session?.user?.email || undefined, - }, + files: files, + biddingId: bidding.id, }) - if (result.status === 'pending_approval') { - toast.success('폐찰 결재가 상신되었습니다.') - onOpenChange(false) - // 폼 초기화 - setDescription('') - setFiles([]) - if (onSuccess) { - onSuccess() - } - } else { - toast.error('결재 상신에 실패했습니다.') - } + // 다이얼로그 닫기 + onOpenChange(false) } catch (error) { - console.error('폐찰 결재 상신 실패:', error) - toast.error(error instanceof Error ? error.message : '결재 상신 중 오류가 발생했습니다.') - } finally { - setIsSubmitting(false) + console.error('결재 미리보기 준비 실패:', error) + toast.error('결재 미리보기 준비 중 오류가 발생했습니다.') } } @@ -98,7 +80,7 @@ interface BiddingsClosureDialogProps { </DialogDescription> </DialogHeader> - <form onSubmit={handleSubmit} className="space-y-4"> + <form onSubmit={handleNextStep} className="space-y-4"> <div className="space-y-2"> <Label htmlFor="description">폐찰 사유 <span className="text-destructive">*</span></Label> <Textarea @@ -133,16 +115,15 @@ interface BiddingsClosureDialogProps { type="button" variant="outline" onClick={() => onOpenChange(false)} - disabled={isSubmitting} > 취소 </Button> <Button type="submit" - variant="destructive" - disabled={isSubmitting || !description.trim()} + variant="default" + disabled={!description.trim()} > - {isSubmitting ? '상신 중...' : '결재 상신'} + 다음 단계 </Button> </div> </form> diff --git a/lib/bidding/failure/biddings-failure-table.tsx b/lib/bidding/failure/biddings-failure-table.tsx index a0f98466..c4e3be06 100644 --- a/lib/bidding/failure/biddings-failure-table.tsx +++ b/lib/bidding/failure/biddings-failure-table.tsx @@ -25,7 +25,7 @@ import { FileX, RefreshCw, Undo2 } from "lucide-react" import { bidClosureAction, cancelDisposalAction } from "@/lib/bidding/actions"
import { increaseRoundOrRebid } from "@/lib/bidding/service"
import { ApprovalPreviewDialog } from "@/lib/approval/approval-preview-dialog"
-import { requestBiddingClosureWithApproval } from "@/lib/bidding/approval-actions"
+import { requestBiddingClosureWithApproval, prepareBiddingClosureApprovalData } from "@/lib/bidding/approval-actions"
import { useToast } from "@/hooks/use-toast"
type BiddingFailureItem = {
@@ -258,6 +258,86 @@ export function BiddingsFailureTable({ promises }: BiddingsFailureTableProps) { }
}, [session?.user?.id, toast, router])
+ // 폐찰 결재 준비 및 결재 다이얼로그 열기 핸들러
+ const handleClosureApprovalSend = async (data: { description: string; files: File[]; biddingId: number }) => {
+ try {
+ if (!session?.user?.id) {
+ toast({
+ title: '오류',
+ description: '사용자 정보가 없습니다.',
+ variant: 'destructive',
+ })
+ return
+ }
+
+ // 결재 데이터 준비 (템플릿 변수 등)
+ const approvalData = await prepareBiddingClosureApprovalData({
+ biddingId: data.biddingId,
+ description: data.description,
+ })
+
+ // 결재 준비 완료 - approvalPreviewData와 결재 데이터 저장 및 결재 다이얼로그 열기
+ setApprovalPreviewData({
+ templateName: '폐찰 품의 요청서',
+ variables: approvalData.variables,
+ title: `폐찰 - ${selectedBidding?.title || ''}`,
+ description: data.description,
+ files: data.files,
+ })
+ setIsApprovalPreviewDialogOpen(true)
+ } catch (error) {
+ console.error('결재 준비 중 오류 발생:', error)
+ toast({
+ title: '오류',
+ description: '결재 준비 중 오류가 발생했습니다.',
+ variant: 'destructive',
+ })
+ }
+ }
+
+ // 폐찰 결재 상신 핸들러 - 결재 완료 시 실제 폐찰 실행
+ const handleClosureApprovalSubmit = async (data: { approvers: string[]; title: string; attachments?: File[] }) => {
+ if (!session?.user?.id || !approvalPreviewData || !selectedBidding) return
+
+ try {
+ const result = await requestBiddingClosureWithApproval({
+ biddingId: selectedBidding.id,
+ description: approvalPreviewData.description,
+ files: approvalPreviewData.files,
+ currentUser: {
+ id: Number(session.user.id),
+ epId: session.user.epId || null,
+ email: session.user.email || undefined
+ },
+ approvers: data.approvers,
+ })
+
+ if (1) {
+ toast({
+ title: '성공',
+ description: `폐찰 결재가 상신되었습니다. (ID: ${result.approvalId})`,
+ })
+ setIsApprovalPreviewDialogOpen(false)
+ setApprovalPreviewData(null)
+ handleBiddingClosureDialogClose()
+ router.refresh()
+ } else {
+ toast({
+ title: '오류',
+ description: '폐찰 결재 상신 중 오류가 발생했습니다.',
+ variant: 'destructive',
+ })
+ }
+ } catch (error) {
+ console.error('폐찰 결재 상신 실패:', error)
+ toast({
+ title: '오류',
+ description: '폐찰 결재 상신 중 오류가 발생했습니다.',
+ variant: 'destructive',
+ })
+ }
+ }
+
const handleCancelDisposal = React.useCallback(async (bidding: BiddingFailureItem) => {
if (!session?.user?.id) {
toast({
@@ -438,10 +518,7 @@ export function BiddingsFailureTable({ promises }: BiddingsFailureTableProps) { router.refresh()
handleBiddingClosureDialogClose()
}}
- onApprovalPreview={(data) => {
- setApprovalPreviewData(data)
- setIsApprovalPreviewDialogOpen(true)
- }}
+ onApprovalPreview={handleClosureApprovalSend}
/>
)}
@@ -498,52 +575,10 @@ export function BiddingsFailureTable({ promises }: BiddingsFailureTableProps) { name: session.user.name || undefined,
email: session.user.email || undefined
}}
- onConfirm={handleClosureApprovalConfirm}
+ onConfirm={handleClosureApprovalSubmit}
/>
)}
</>
)
- // 폐찰 결재 상신 핸들러
- const handleClosureApprovalConfirm = async (data: { approvers: string[]; title: string; attachments?: File[] }) => {
- if (!session?.user?.id || !approvalPreviewData || !selectedBidding) return
-
- try {
- const result = await requestBiddingClosureWithApproval({
- biddingId: selectedBidding.id,
- description: approvalPreviewData.description,
- files: approvalPreviewData.files,
- currentUser: {
- id: Number(session.user.id),
- epId: session.user.epId || null,
- email: session.user.email || undefined
- },
- approvers: data.approvers,
- })
-
- if (result.status === 'pending_approval') {
- toast({
- title: '성공',
- description: `폐찰 결재가 상신되었습니다. (ID: ${result.approvalId})`,
- })
- setIsApprovalPreviewDialogOpen(false)
- setApprovalPreviewData(null)
- handleBiddingClosureDialogClose()
- router.refresh()
- } else {
- toast({
- title: '오류',
- description: '폐찰 결재 상신 중 오류가 발생했습니다.',
- variant: 'destructive',
- })
- }
- } catch (error) {
- console.error('폐찰 결재 상신 실패:', error)
- toast({
- title: '오류',
- description: '폐찰 결재 상신 중 오류가 발생했습니다.',
- variant: 'destructive',
- })
- }
- }
}
|
