"use client";
import { useState, useEffect } from "react";
import { useSearchParams, useRouter } from "next/navigation";
import { ArrowLeft, Star, CheckCircle, AlertCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Textarea } from "@/components/ui/textarea";
import { fetchAppraisal, submitAppraisal } from "@/lib/supabase/appraisal-actions";
import PageSkeleton from "./PageSkeleton";
// ── Star Rating Component ──────────────────────────────────────
function StarRating({
value,
onChange,
readonly = false,
size = "md",
}: {
value: number;
onChange?: (v: number) => void;
readonly?: boolean;
size?: "sm" | "md" | "lg";
}) {
const [hover, setHover] = useState(0);
const sizeClass = size === "lg" ? "w-7 h-7" : size === "md" ? "w-5 h-5" : "w-4 h-4";
return (
{[1, 2, 3, 4, 5].map((s) => (
))}
);
}
// ── Question Renderer ──────────────────────────────────────────
function RatingQuestion({
question,
value,
onChange,
readonly,
}: {
question: string;
value: number;
onChange: (v: number) => void;
readonly: boolean;
}) {
return (
);
}
function TextQuestion({
question,
value,
onChange,
readonly,
}: {
question: string;
value: string;
onChange: (v: string) => void;
readonly: boolean;
}) {
return (
);
}
function YesNoQuestion({
question,
value,
onChange,
readonly,
}: {
question: string;
value: boolean | null;
onChange: (v: boolean) => void;
readonly: boolean;
}) {
return (
{question}
);
}
// ── Main Form Page ─────────────────────────────────────────────
export default function AppraisalFormPage() {
const searchParams = useSearchParams();
const router = useRouter();
const id = searchParams.get("id");
const [appraisal, setAppraisal] = useState(null);
const [loading, setLoading] = useState(true);
const [responses, setResponses] = useState>({});
const [overallRating, setOverallRating] = useState(0);
const [saving, setSaving] = useState(false);
const [error, setError] = useState("");
const [success, setSuccess] = useState(false);
useEffect(() => {
if (!id) {
router.push("/performance");
return;
}
let cancelled = false;
fetchAppraisal(id)
.then((a) => {
if (!cancelled) {
setAppraisal(a);
if (a?.responses) {
try {
setResponses(JSON.parse(a.responses));
} catch {
setResponses({});
}
}
if (a?.overall_rating) {
setOverallRating(a.overall_rating);
}
}
})
.catch(() => {})
.finally(() => {
if (!cancelled) setLoading(false);
});
return () => {
cancelled = true;
};
}, [id, router]);
const handleSubmit = async () => {
if (overallRating === 0) {
setError("Please provide an overall rating");
return;
}
setSaving(true);
setError("");
const result = await submitAppraisal(id!, responses, overallRating);
setSaving(false);
if (result.success) {
setSuccess(true);
// Refresh appraisal data
const refreshed = await fetchAppraisal(id!);
setAppraisal(refreshed);
} else {
setError(result.error || "Failed to submit appraisal");
}
};
const handleResponseChange = (questionId: string, value: any) => {
setResponses((prev) => ({ ...prev, [questionId]: value }));
};
if (loading) return ;
if (!appraisal) {
return (
Appraisal not found
);
}
const isSubmitted = appraisal.status === "submitted";
const employeeName = appraisal.employee
? `${appraisal.employee.first_name} ${appraisal.employee.last_name}`
: "Unknown";
const reviewerName = appraisal.reviewer
? `${appraisal.reviewer.first_name} ${appraisal.reviewer.last_name}`
: "Unknown";
const typeLabel =
appraisal.type === "self"
? "Self Assessment"
: appraisal.type === "manager"
? "Manager Assessment"
: appraisal.type || "Peer Assessment";
const questions = appraisal.cycle?.template?.questions
? typeof appraisal.cycle.template.questions === "string"
? JSON.parse(appraisal.cycle.template.questions)
: appraisal.cycle.template.questions
: [];
const cycleName = appraisal.cycle?.name || "";
if (success) {
return (
Appraisal Submitted
Appraisal submitted successfully
Your responses have been recorded for this appraisal cycle.
);
}
return (
{/* Header */}
{typeLabel}
{isSubmitted && (
Submitted
)}
{cycleName && `${cycleName} — `}
{employeeName}
Employee: {employeeName}
Reviewer: {reviewerName}
{/* Questions */}
{questions.length > 0 && (
Questions
{questions.map((q: { id: string; question: string; type: string }) => (
{q.type === "rating" && (
handleResponseChange(q.id, v)}
readonly={isSubmitted}
/>
)}
{q.type === "text" && (
handleResponseChange(q.id, v)}
readonly={isSubmitted}
/>
)}
{q.type === "yes_no" && (
handleResponseChange(q.id, v)}
readonly={isSubmitted}
/>
)}
))}
)}
{/* Overall Rating */}
Overall Rating
{overallRating > 0 && (
{overallRating === 1 && "Below expectations"}
{overallRating === 2 && "Needs improvement"}
{overallRating === 3 && "Meets expectations"}
{overallRating === 4 && "Exceeds expectations"}
{overallRating === 5 && "Outstanding"}
)}
{/* Error */}
{error && (
)}
{/* Submit */}
{!isSubmitted && (
)}
);
}