From 90f79a7a691943a496f67f01c1e493256070e4de Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 7 Jul 2025 01:44:45 +0000
Subject: (대표님) 변경사항 20250707 10시 43분 - unstaged 변경사항 추가
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/evaluation-submit/evaluation-page.tsx | 258 ++++++++++++++++++++++++++++++
 1 file changed, 258 insertions(+)
 create mode 100644 lib/evaluation-submit/evaluation-page.tsx

(limited to 'lib/evaluation-submit/evaluation-page.tsx')

diff --git a/lib/evaluation-submit/evaluation-page.tsx b/lib/evaluation-submit/evaluation-page.tsx
new file mode 100644
index 00000000..810ed03e
--- /dev/null
+++ b/lib/evaluation-submit/evaluation-page.tsx
@@ -0,0 +1,258 @@
+"use client"
+
+import * as React from "react"
+import { useParams, useRouter } from "next/navigation"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Button } from "@/components/ui/button"
+import { Skeleton } from "@/components/ui/skeleton"
+import { AlertCircle, ArrowLeft, RefreshCw } from "lucide-react"
+import { Alert, AlertDescription } from "@/components/ui/alert"
+
+import { getEvaluationFormData, EvaluationFormData } from "./service"
+import { EvaluationForm } from "./evaluation-form"
+
+/**
+ * 로딩 스켈레톤 컴포넌트
+ */
+function EvaluationFormSkeleton() {
+  return (
+    <div className="container mx-auto py-6 space-y-6">
+      {/* 헤더 스켈레톤 */}
+      <div className="flex items-center justify-between">
+        <div className="flex items-center gap-4">
+          <Skeleton className="h-10 w-10" />
+          <div className="space-y-2">
+            <Skeleton className="h-8 w-32" />
+            <Skeleton className="h-4 w-48" />
+          </div>
+        </div>
+        <Skeleton className="h-6 w-16" />
+      </div>
+
+      {/* 평가 정보 카드 스켈레톤 */}
+      <Card>
+        <CardHeader>
+          <Skeleton className="h-6 w-24" />
+        </CardHeader>
+        <CardContent>
+          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
+            {[...Array(4)].map((_, i) => (
+              <div key={i} className="space-y-2">
+                <Skeleton className="h-4 w-16" />
+                <Skeleton className="h-5 w-24" />
+                <Skeleton className="h-3 w-20" />
+              </div>
+            ))}
+          </div>
+        </CardContent>
+      </Card>
+
+      {/* 진행률 카드 스켈레톤 */}
+      <Card>
+        <CardContent className="pt-6">
+          <div className="flex items-center justify-between">
+            <div className="space-y-1">
+              <Skeleton className="h-4 w-16" />
+              <Skeleton className="h-6 w-24" />
+            </div>
+            <Skeleton className="h-2 w-32" />
+          </div>
+        </CardContent>
+      </Card>
+
+      {/* 질문 카드들 스켈레톤 */}
+      {[...Array(3)].map((_, i) => (
+        <Card key={i} className="mb-6">
+          <CardHeader className="pb-4">
+            <div className="flex items-start justify-between">
+              <div className="space-y-2">
+                <div className="flex items-center gap-2">
+                  <Skeleton className="h-5 w-16" />
+                  <Skeleton className="h-5 w-12" />
+                </div>
+                <Skeleton className="h-6 w-64" />
+                <Skeleton className="h-4 w-48" />
+              </div>
+            </div>
+          </CardHeader>
+          <CardContent className="space-y-4">
+            <div className="space-y-3">
+              <Skeleton className="h-4 w-32" />
+              {[...Array(3)].map((_, j) => (
+                <div key={j} className="flex items-center space-x-3 p-3 border rounded-lg">
+                  <Skeleton className="h-4 w-4 rounded-full" />
+                  <div className="flex-1 flex items-center justify-between">
+                    <Skeleton className="h-4 w-32" />
+                    <Skeleton className="h-5 w-12" />
+                  </div>
+                </div>
+              ))}
+            </div>
+            <div className="space-y-2">
+              <Skeleton className="h-4 w-24" />
+              <Skeleton className="h-20 w-full" />
+            </div>
+          </CardContent>
+        </Card>
+      ))}
+    </div>
+  )
+}
+
+/**
+ * 에러 상태 컴포넌트
+ */
+function EvaluationFormError({ 
+  error, 
+  onRetry 
+}: { 
+  error: string
+  onRetry: () => void 
+}) {
+  const router = useRouter()
+
+  return (
+    <div className="container mx-auto py-6 space-y-6">
+      <div className="flex items-center gap-4">
+        <Button 
+          variant="ghost" 
+          size="icon"
+          onClick={() => router.back()}
+        >
+          <ArrowLeft className="h-4 w-4" />
+        </Button>
+        <div>
+          <h1 className="text-2xl font-bold">평가 작성</h1>
+          <p className="text-muted-foreground">평가를 불러오는 중 오류가 발생했습니다</p>
+        </div>
+      </div>
+
+      <Alert variant="destructive">
+        <AlertCircle className="h-4 w-4" />
+        <AlertDescription>
+          {error}
+        </AlertDescription>
+      </Alert>
+
+      <Card>
+        <CardHeader>
+          <CardTitle>문제 해결</CardTitle>
+          <CardDescription>
+            다음 방법들을 시도해보세요:
+          </CardDescription>
+        </CardHeader>
+        <CardContent className="space-y-4">
+          <ul className="list-disc pl-6 space-y-2 text-sm">
+            <li>페이지를 새로고침해보세요</li>
+            <li>인터넷 연결 상태를 확인해보세요</li>
+            <li>잠시 후 다시 시도해보세요</li>
+            <li>문제가 지속되면 관리자에게 문의하세요</li>
+          </ul>
+          
+          <div className="flex items-center gap-2 pt-4">
+            <Button onClick={onRetry} className="flex items-center gap-2">
+              <RefreshCw className="h-4 w-4" />
+              다시 시도
+            </Button>
+            <Button variant="outline" onClick={() => router.back()}>
+              목록으로 돌아가기
+            </Button>
+          </div>
+        </CardContent>
+      </Card>
+    </div>
+  )
+}
+
+/**
+ * 평가 작성 페이지 메인 컴포넌트
+ */
+export function EvaluationPage() {
+  const params = useParams()
+  const router = useRouter()
+  const [formData, setFormData] = React.useState<EvaluationFormData | null>(null)
+  const [isLoading, setIsLoading] = React.useState(true)
+  const [error, setError] = React.useState<string | null>(null)
+
+  const reviewerEvaluationId = params.id ? parseInt(params.id as string) : null
+
+  // 평가 데이터 로드
+  const loadEvaluationData = React.useCallback(async () => {
+    if (!reviewerEvaluationId) {
+      setError("잘못된 평가 ID입니다.")
+      setIsLoading(false)
+      return
+    }
+
+    try {
+      setIsLoading(true)
+      setError(null)
+      
+      const data = await getEvaluationFormData(reviewerEvaluationId)
+      
+      if (!data) {
+        setError("평가 데이터를 찾을 수 없습니다.")
+        return
+      }
+      
+      setFormData(data)
+    } catch (err) {
+      console.error('Failed to load evaluation data:', err)
+      setError(
+        err instanceof Error 
+          ? err.message 
+          : "평가 데이터를 불러오는 중 오류가 발생했습니다."
+      )
+    } finally {
+      setIsLoading(false)
+    }
+  }, [reviewerEvaluationId])
+
+  // 초기 데이터 로드
+  React.useEffect(() => {
+    loadEvaluationData()
+  }, [loadEvaluationData])
+
+  // 평가 완료 후 처리
+  const handleSubmitSuccess = React.useCallback(() => {
+    router.push('/evaluations')
+  }, [router])
+
+  // 로딩 상태
+  if (isLoading) {
+    return <EvaluationFormSkeleton />
+  }
+
+  // 에러 상태
+  if (error) {
+    return (
+      <EvaluationFormError 
+        error={error} 
+        onRetry={loadEvaluationData}
+      />
+    )
+  }
+
+  // 데이터가 없는 경우
+  if (!formData) {
+    return (
+      <EvaluationFormError 
+        error="평가 데이터를 불러올 수 없습니다." 
+        onRetry={loadEvaluationData}
+      />
+    )
+  }
+
+  // 정상 상태 - 평가 폼 렌더링
+  return (
+    <EvaluationForm 
+      formData={formData}
+      onSubmit={handleSubmitSuccess}
+    />
+  )
+}
+
+// 페이지 컴포넌트용 기본 export
+export default function EvaluationPageWrapper() {
+  return <EvaluationPage />
+}
\ No newline at end of file
-- 
cgit v1.2.3

