From ba8cd44a0ed2c613a5f2cee06bfc9bd0f61f21c7 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Fri, 7 Nov 2025 08:39:04 +0000
Subject: (최겸) 입찰/견적 수정사항
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../detail/general-contract-review-comments.tsx    | 194 +++++++++++++++++++++
 1 file changed, 194 insertions(+)
 create mode 100644 lib/general-contracts/detail/general-contract-review-comments.tsx

(limited to 'lib/general-contracts/detail/general-contract-review-comments.tsx')

diff --git a/lib/general-contracts/detail/general-contract-review-comments.tsx b/lib/general-contracts/detail/general-contract-review-comments.tsx
new file mode 100644
index 00000000..e80211f2
--- /dev/null
+++ b/lib/general-contracts/detail/general-contract-review-comments.tsx
@@ -0,0 +1,194 @@
+'use client'
+
+import React, { useState, useEffect } from 'react'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+import { Label } from '@/components/ui/label'
+import { Textarea } from '@/components/ui/textarea'
+import { Button } from '@/components/ui/button'
+import { MessageSquare, Send, Save } from 'lucide-react'
+import { toast } from 'sonner'
+import { useSession } from 'next-auth/react'
+import { 
+  getContractReviewComments,
+  confirmContractReview
+} from '../service'
+
+interface ContractReviewCommentsProps {
+  contractId: number
+  contractStatus: string
+}
+
+export function ContractReviewComments({ contractId, contractStatus }: ContractReviewCommentsProps) {
+  const session = useSession()
+  const userId = session.data?.user?.id ? Number(session.data.user.id) : null
+
+  const [vendorComment, setVendorComment] = useState<string>('')
+  const [shiComment, setShiComment] = useState<string>('')
+  const [isSaving, setIsSaving] = useState(false)
+  const [isEditingShiComment, setIsEditingShiComment] = useState(false)
+
+  // 계약 상태에 따른 표시 여부
+  const showVendorComment = ['Request to Review', 'Vendor Replied Review', 'SHI Confirmed Review'].includes(contractStatus)
+  const showShiComment = ['Vendor Replied Review', 'SHI Confirmed Review'].includes(contractStatus)
+  const canEditShiComment = contractStatus === 'Vendor Replied Review' && userId
+
+  useEffect(() => {
+    const loadComments = async () => {
+      try {
+        const result = await getContractReviewComments(contractId)
+        if (result.success) {
+          if (result.vendorComment) {
+            setVendorComment(result.vendorComment)
+          }
+          if (result.shiComment) {
+            setShiComment(result.shiComment)
+            setIsEditingShiComment(false) // 이미 저장된 의견이 있으면 편집 모드 해제
+          } else {
+            setIsEditingShiComment(canEditShiComment ? true : false) // 의견이 없고 편집 가능하면 편집 모드
+          }
+        }
+      } catch (error) {
+        console.error('의견 로드 오류:', error)
+      }
+    }
+
+    if (showVendorComment || showShiComment) {
+      loadComments()
+    }
+  }, [contractId, showVendorComment, showShiComment, canEditShiComment])
+
+  const handleConfirmReview = async () => {
+    if (!shiComment.trim()) {
+      toast.error('SHI 의견을 입력해주세요.')
+      return
+    }
+
+    if (!userId) {
+      toast.error('로그인이 필요합니다.')
+      return
+    }
+
+    setIsSaving(true)
+    try {
+      await confirmContractReview(contractId, shiComment, userId)
+      toast.success('검토가 확정되었습니다.')
+      // 페이지 새로고침
+      window.location.reload()
+    } catch (error) {
+      console.error('검토 확정 오류:', error)
+      const errorMessage = error instanceof Error ? error.message : '검토 확정에 실패했습니다.'
+      toast.error(errorMessage)
+    } finally {
+      setIsSaving(false)
+    }
+  }
+
+  return (
+    <Card>
+      <CardHeader>
+        <CardTitle className="flex items-center gap-2">
+          <MessageSquare className="h-5 w-5" />
+          계약 조건 검토 의견
+        </CardTitle>
+      </CardHeader>
+      <CardContent className="space-y-6">
+        {/* Vendor Comment */}
+        {showVendorComment && (
+          <div className="space-y-2">
+            <Label className="text-sm font-medium">Vendor Comment</Label>
+            <div className="min-h-[120px] p-4 bg-yellow-50 border-2 border-yellow-200 rounded-lg">
+              {vendorComment ? (
+                <p className="text-sm whitespace-pre-wrap">{vendorComment}</p>
+              ) : (
+                <p className="text-sm text-muted-foreground">협력업체 의견이 없습니다.</p>
+              )}
+            </div>
+          </div>
+        )}
+
+        {/* SHI Comment */}
+        {showShiComment && (
+          <div className="space-y-2">
+            <Label className="text-sm font-medium">SHI Comment</Label>
+            {isEditingShiComment ? (
+              <div className="space-y-2">
+                <Textarea
+                  value={shiComment}
+                  onChange={(e) => setShiComment(e.target.value)}
+                  placeholder="SHI 의견을 입력하세요"
+                  rows={6}
+                  className="resize-none"
+                  disabled={isSaving}
+                />
+                <div className="flex gap-2">
+                  <Button
+                    onClick={handleConfirmReview}
+                    disabled={isSaving || !shiComment.trim()}
+                    className="flex-1"
+                  >
+                    {isSaving ? (
+                      <>
+                        <Save className="h-4 w-4 mr-2 animate-spin" />
+                        확정 중...
+                      </>
+                    ) : (
+                      <>
+                        <Send className="h-4 w-4 mr-2" />
+                        의견 회신 및 검토 확정
+                      </>
+                    )}
+                  </Button>
+                  {shiComment && (
+                    <Button
+                      variant="outline"
+                      onClick={() => {
+                        setIsEditingShiComment(false)
+                        // 원래 값으로 복원하기 위해 다시 로드
+                        getContractReviewComments(contractId).then((result) => {
+                          if (result.success) {
+                            setShiComment(result.shiComment || '')
+                          }
+                        })
+                      }}
+                      disabled={isSaving}
+                    >
+                      취소
+                    </Button>
+                  )}
+                </div>
+              </div>
+            ) : (
+              <div className="space-y-2">
+                <div className="min-h-[120px] p-4 bg-gray-50 border rounded-lg">
+                  {shiComment ? (
+                    <p className="text-sm whitespace-pre-wrap">{shiComment}</p>
+                  ) : (
+                    <p className="text-sm text-muted-foreground">SHI 의견이 없습니다.</p>
+                  )}
+                </div>
+                {canEditShiComment && (
+                  <Button
+                    variant="outline"
+                    onClick={() => setIsEditingShiComment(true)}
+                    className="w-full"
+                  >
+                    <Save className="h-4 w-4 mr-2" />
+                    의견 수정
+                  </Button>
+                )}
+              </div>
+            )}
+          </div>
+        )}
+
+        {/* 상태가 아닌 경우 안내 메시지 */}
+        {!showVendorComment && !showShiComment && (
+          <div className="text-center py-8 text-muted-foreground">
+            <p>조건검토 요청 상태가 아닙니다.</p>
+          </div>
+        )}
+      </CardContent>
+    </Card>
+  )
+}
+
-- 
cgit v1.2.3

