// File: frontend/components/admin/ai/VersionHistory.tsx
// Change Log:
// - 2026-06-14: Created VersionHistory component with type filtering and nice badges (conforming to task T017)
// - 2026-06-15: Added All Types view grouped by prompt type (T065)
// - 2026-06-15: Added pagination (20 versions/page) (T075)
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { CheckCircle2, Trash2, BookOpen, Clock, StickyNote, Folder, ChevronLeft, ChevronRight } from 'lucide-react';
import { PromptVersion } from '@/lib/types/ai-prompts';
import { cn } from '@/lib/utils';
interface VersionHistoryProps {
versions: PromptVersion[];
isLoading: boolean;
onLoadTemplate: (version: PromptVersion) => void;
onActivateVersion: (versionNumber: number) => void;
onDeleteVersion: (versionNumber: number) => void;
isActivating: boolean;
isDeleting: boolean;
showAllTypes?: boolean;
}
/**
* คอมโพเนนต์แสดงประวัติเวอร์ชันของพรอมต์ตามประเภทที่กรองไว้
* หรือแสดงทุกประเภทแบบจัดกลุ่ม (T065)
* แสดงรายการเวอร์ชันพร้อมปุ่มพรีโหลด เปิดใช้งาน และลบเวอร์ชันที่ไม่ต้องการ
*/
export default function VersionHistory({
versions,
isLoading,
onLoadTemplate,
onActivateVersion,
onDeleteVersion,
isActivating,
isDeleting,
showAllTypes = false,
}: VersionHistoryProps) {
const { t } = useTranslation('ai');
const [currentPage, setCurrentPage] = useState(1);
const PAGE_SIZE = 20; // T075: 20 versions per page
if (isLoading) {
return (
{t('prompt_management.version_history')}...
);
}
// Group versions by prompt type when showing all types
const groupedVersions = showAllTypes
? versions.reduce((acc, version) => {
const type = version.promptType;
if (!acc[type]) {
acc[type] = [];
}
acc[type].push(version);
return acc;
}, {} as Record)
: null;
const getPromptTypeLabel = (type: string): string => {
const labels: Record = {
ocr_extraction: 'สกัดข้อความ OCR (OCR Extraction)',
rag_query_prompt: 'ค้นหาข้อมูล RAG (RAG Query)',
rag_prep_prompt: 'เตรียมข้อมูล RAG (RAG Prep)',
classification_prompt: 'จำแนกประเภทเอกสาร (Classification)',
};
return labels[type] || type;
};
// Pagination logic (T075)
const totalPages = Math.ceil(versions.length / PAGE_SIZE);
const startIndex = (currentPage - 1) * PAGE_SIZE;
const endIndex = startIndex + PAGE_SIZE;
const paginatedVersions = versions.slice(startIndex, endIndex);
const handlePreviousPage = () => {
setCurrentPage((prev) => Math.max(1, prev - 1));
};
const handleNextPage = () => {
setCurrentPage((prev) => Math.min(totalPages, prev + 1));
};
return (
{showAllTypes ? `${t('prompt_management.version_history')} (${t('prompt_management.all_types')})` : t('prompt_management.version_history')}
{versions.length === 0 ? (
{t('prompt_management.no_versions')}
) : showAllTypes && groupedVersions ? (
// Grouped view by prompt type (with pagination applied to each group)
Object.entries(groupedVersions).map(([promptType, typeVersions]) => {
const paginatedGroupVersions = typeVersions.slice(startIndex, endIndex);
return (
{getPromptTypeLabel(promptType)}
{paginatedGroupVersions.map((version) => {
const isActive = version.isActive === true;
return (
v{version.versionNumber}
{isActive ? (
{t('prompt_management.is_active')}
) : (
ร่าง (Inactive)
)}
สร้าง: {new Date(version.createdAt).toLocaleString('th-TH')}
{!isActive && (
<>
>
)}
{version.manualNote && (
)}
);
})}
);
})
) : (
// Single type view with pagination (T075)
paginatedVersions.map((version) => {
const isActive = version.isActive === true;
return (
v{version.versionNumber}
{isActive ? (
{t('prompt_management.is_active')}
) : (
ร่าง (Inactive)
)}
สร้าง: {new Date(version.createdAt).toLocaleString('th-TH')}
{!isActive && (
<>
>
)}
{version.manualNote && (
)}
);
})
)}
{/* Pagination controls (T075) */}
{totalPages > 1 && (
หน้า {currentPage} จาก {totalPages} ({versions.length} เวอร์ชัน)
)}
);
}