diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-12-01 06:20:50 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-12-01 06:20:50 +0000 |
| commit | 13c8b4e48f62c1f437b1a2b10731d092fea2a83f (patch) | |
| tree | 8cc4cadd060e66d2eccc5ce3d1398a8d699e0164 /lib/basic-contract/agreement-comments/agreement-comment-list.tsx | |
| parent | 3c9a95332298450c7e0f75bfb08944439e1a3739 (diff) | |
(임수민) GTC 코멘트 수정
Diffstat (limited to 'lib/basic-contract/agreement-comments/agreement-comment-list.tsx')
| -rw-r--r-- | lib/basic-contract/agreement-comments/agreement-comment-list.tsx | 104 |
1 files changed, 86 insertions, 18 deletions
diff --git a/lib/basic-contract/agreement-comments/agreement-comment-list.tsx b/lib/basic-contract/agreement-comments/agreement-comment-list.tsx index bad5aee5..fc64eab3 100644 --- a/lib/basic-contract/agreement-comments/agreement-comment-list.tsx +++ b/lib/basic-contract/agreement-comments/agreement-comment-list.tsx @@ -30,6 +30,7 @@ import { getAgreementComments, addAgreementComment, deleteAgreementComment, + submitAgreementComment, uploadCommentAttachment, deleteCommentAttachment, completeNegotiation, @@ -65,6 +66,7 @@ export function AgreementCommentList({ const [isSaving, setIsSaving] = useState(false); const [pendingFiles, setPendingFiles] = useState<File[]>([]); // 첨부 대기 중인 파일들 const [isCompletingNegotiation, setIsCompletingNegotiation] = useState(false); + const [submittingComments, setSubmittingComments] = useState<Set<number>>(new Set()); // 제출 중인 코멘트 ID // 코멘트 로드 const loadComments = useCallback(async () => { @@ -205,6 +207,33 @@ export function AgreementCommentList({ } }, []); // loadComments 제거 + // 코멘트 제출 핸들러 + const handleSubmitComment = useCallback(async (commentId: number) => { + if (!confirm("이 코멘트를 제출하시겠습니까?\n제출 시 상대방에게 이메일이 발송됩니다.")) { + return; + } + + setSubmittingComments(prev => new Set(prev).add(commentId)); + try { + const result = await submitAgreementComment(commentId); + if (result.success) { + toast.success("코멘트가 제출되었으며 상대방에게 이메일이 발송되었습니다."); + await loadComments(); // 목록 새로고침 + } else { + toast.error(result.error || "코멘트 제출에 실패했습니다."); + } + } catch (error) { + console.error('코멘트 제출 실패:', error); + toast.error("코멘트 제출에 실패했습니다."); + } finally { + setSubmittingComments(prev => { + const next = new Set(prev); + next.delete(commentId); + return next; + }); + } + }, []); // loadComments 제거 + // 협의 완료 핸들러 const handleCompleteNegotiation = useCallback(async () => { if (!confirm("협의를 완료하시겠습니까?\n협의 완료 후에는 법무검토 요청이 가능합니다.")) { @@ -525,7 +554,7 @@ export function AgreementCommentList({ <div className="space-y-3"> {/* 헤더: 작성자 정보 */} <div className="flex items-start justify-between"> - <div className="flex items-center space-x-2"> + <div className="flex items-center space-x-2 flex-1"> <Badge variant="outline" className={cn( @@ -552,18 +581,50 @@ export function AgreementCommentList({ {comment.authorName} </span> )} + {comment.isSubmitted && ( + <Badge + variant="outline" + className="bg-green-100 text-green-700 border-green-300 text-xs" + > + <Send className="h-3 w-3 mr-1" /> + 제출됨 + </Badge> + )} </div> - {!readOnly && isCommentOwner && ( - <Button - variant="ghost" - size="sm" - onClick={() => handleDeleteComment(comment.id)} - className="h-7 w-7 p-0 text-red-500 hover:text-red-700 hover:bg-red-50" - > - <Trash2 className="h-4 w-4" /> - </Button> - )} + <div className="flex items-center space-x-1"> + {!readOnly && isCommentOwner && !comment.isSubmitted && ( + <Button + variant="outline" + size="sm" + onClick={() => handleSubmitComment(comment.id)} + disabled={submittingComments.has(comment.id)} + className="h-7 text-xs bg-blue-50 text-blue-700 border-blue-300 hover:bg-blue-100" + > + {submittingComments.has(comment.id) ? ( + <> + <Loader2 className="h-3 w-3 mr-1 animate-spin" /> + 제출 중... + </> + ) : ( + <> + <Send className="h-3 w-3 mr-1" /> + 제출 + </> + )} + </Button> + )} + {!readOnly && isCommentOwner && ( + <Button + variant="ghost" + size="sm" + onClick={() => handleDeleteComment(comment.id)} + className="h-7 w-7 p-0 text-red-500 hover:text-red-700 hover:bg-red-50" + > + <Trash2 className="h-4 w-4" /> + </Button> + )} + </div> </div> {/* 코멘트 내용 */} @@ -667,16 +728,23 @@ export function AgreementCommentList({ </div> )} - {/* 푸터: 작성일시 */} + {/* 푸터: 작성일시 및 제출일시 */} <div className="flex items-center justify-between text-xs text-gray-500 pt-2 border-t border-gray-200"> - <span> - 작성일: {formatDateTime(comment.createdAt, "KR")} - </span> - {comment.updatedAt && comment.updatedAt.getTime() !== comment.createdAt.getTime() && ( + <div className="flex items-center space-x-3"> <span> - 수정일: {formatDateTime(comment.updatedAt, "KR")} + 작성일: {formatDateTime(comment.createdAt, "KR")} </span> - )} + {comment.updatedAt && comment.updatedAt.getTime() !== comment.createdAt.getTime() && ( + <span> + 수정일: {formatDateTime(comment.updatedAt, "KR")} + </span> + )} + {comment.isSubmitted && comment.submittedAt && ( + <span className="text-green-600 font-medium"> + 제출일: {formatDateTime(comment.submittedAt, "KR")} + </span> + )} + </div> </div> </div> </CardContent> |
