John-Jiang's picture
init commit
5301c48
raw
history blame
8.39 kB
'use client'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Textarea } from "@/components/ui/textarea"
import { ArrowLeft, Save, Star, ChevronLeft, ChevronRight } from "lucide-react"
import { useState } from "react"
import type { ToEvaluateDatasetRecord, TemplateResult } from './TemplateManager'
interface TemplateEvaluateStepProps {
evaluatedData: ToEvaluateDatasetRecord[]
setEvaluatedData: (data: ToEvaluateDatasetRecord[]) => void
templateResult: TemplateResult | null
onSaveExport: () => void
onBackToResults: () => void
}
export default function TemplateEvaluateStep({
evaluatedData,
setEvaluatedData,
templateResult,
onSaveExport,
onBackToResults
}: TemplateEvaluateStepProps) {
const [currentPage, setCurrentPage] = useState(1)
const recordsPerPage = 10
const totalRecords = evaluatedData.length
const totalPages = Math.ceil(totalRecords / recordsPerPage)
const startIndex = (currentPage - 1) * recordsPerPage
const endIndex = startIndex + recordsPerPage
const currentRecords = evaluatedData.slice(startIndex, endIndex)
const goToPage = (page: number) => {
setCurrentPage(Math.max(1, Math.min(page, totalPages)))
}
const handleScoreChange = (recordId: string, score: number) => {
setEvaluatedData(
evaluatedData.map(record =>
record.id === recordId ? { ...record, score } : record
)
)
}
const handleCommentChange = (recordId: string, comments: string) => {
setEvaluatedData(
evaluatedData.map(record =>
record.id === recordId ? { ...record, comments } : record
)
)
}
const StarRating = ({ recordId, currentRating }: { recordId: string, currentRating: number }) => {
const [hoveredRating, setHoveredRating] = useState(0)
return (
<div className="flex items-center gap-1">
{[1, 2, 3, 4, 5].map((star) => (
<Star
key={star}
className={`h-4 w-4 cursor-pointer transition-colors ${
star <= (hoveredRating || currentRating)
? 'fill-yellow-400 text-yellow-400'
: 'text-gray-300 hover:text-yellow-400'
}`}
onClick={() => handleScoreChange(recordId, star)}
onMouseEnter={() => setHoveredRating(star)}
onMouseLeave={() => setHoveredRating(0)}
/>
))}
</div>
)
}
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold">Evaluate Dataset</h2>
<p className="text-gray-600 mt-1">
Add quality scores and comments to each record
{totalRecords > recordsPerPage && (
<span> • Showing {startIndex + 1}-{Math.min(endIndex, totalRecords)} of {totalRecords} records</span>
)}
</p>
</div>
<Button
onClick={onSaveExport}
className="bg-pink-600 hover:bg-pink-700 text-white flex items-center gap-2"
>
<Save className="h-4 w-4" />
Save & Export
</Button>
</div>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Star className="h-5 w-5" />
Quality Evaluation
</CardTitle>
<CardDescription>
Rate each record's quality from 1 (poor) to 5 (excellent) and add comments
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-6 max-h-96 overflow-y-auto">
{currentRecords.map((record, index) => (
<div key={record.id} className="border rounded-lg p-4 space-y-4">
<div className="flex items-start justify-between gap-4">
<div className="flex-1">
<h4 className="font-medium mb-2">Record {startIndex + index + 1}</h4>
<div className="text-sm text-gray-600 space-y-1">
{Object.entries(record).filter(([key]) =>
// {.slice(0, 3)}
key !== 'id' && key !== 'score' && key !== 'rating' && key !== 'comments'
).map(([key, value]) => (
<div key={key}>
<span className="font-medium capitalize">{key.replace(/_/g, ' ')}:</span>{' '}
<span className="break-words">
{typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value)}
</span>
</div>
))}
</div>
</div>
</div>
{/* Scoring and Comments Section */}
<div className="border-t pt-4 space-y-3">
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<Label className="text-sm font-medium">Rating:</Label>
<StarRating
recordId={record.id}
currentRating={record.score || record.rating || 0}
/>
</div>
<div className="flex items-center gap-2">
<Label className="text-sm font-medium">Score:</Label>
<Select
value={(record.score || record.rating)?.toString() || ''}
onValueChange={(value) => handleScoreChange(record.id, parseInt(value))}
>
<SelectTrigger className="w-20">
<SelectValue placeholder="Rate" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">1</SelectItem>
<SelectItem value="2">2</SelectItem>
<SelectItem value="3">3</SelectItem>
<SelectItem value="4">4</SelectItem>
<SelectItem value="5">5</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="space-y-2">
<Label className="text-sm font-medium">Comments:</Label>
<Textarea
placeholder="Add your evaluation comments here..."
value={record.comments || ''}
onChange={(e) => handleCommentChange(record.id, e.target.value)}
className="min-h-[80px] resize-none text-sm"
/>
</div>
</div>
</div>
))}
</div>
{totalPages > 1 && (
<div className="flex items-center justify-between mt-4 pt-4 border-t">
<p className="text-sm text-gray-500">
Page {currentPage} of {totalPages}
</p>
<div className="flex items-center gap-2">
<Button
variant="outline"
size="sm"
onClick={() => goToPage(currentPage - 1)}
disabled={currentPage === 1}
>
<ChevronLeft className="h-4 w-4" />
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => goToPage(currentPage + 1)}
disabled={currentPage === totalPages}
>
Next
<ChevronRight className="h-4 w-4" />
</Button>
</div>
</div>
)}
</CardContent>
</Card>
<div className="flex justify-between">
<Button
variant="outline"
onClick={onBackToResults}
className="flex items-center gap-2"
>
<ArrowLeft className="h-4 w-4" />
Back to Results
</Button>
</div>
</div>
)
}