diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-07 01:44:45 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-07 01:44:45 +0000 |
| commit | 90f79a7a691943a496f67f01c1e493256070e4de (patch) | |
| tree | 37275fde3ae08c2bca384fbbc8eb378de7e39230 /lib/evaluation-submit/evaluation-page.tsx | |
| parent | fbb3b7f05737f9571b04b0a8f4f15c0928de8545 (diff) | |
(대표님) 변경사항 20250707 10시 43분 - unstaged 변경사항 추가
Diffstat (limited to 'lib/evaluation-submit/evaluation-page.tsx')
| -rw-r--r-- | lib/evaluation-submit/evaluation-page.tsx | 258 |
1 files changed, 258 insertions, 0 deletions
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 |
