From 8ce3e36e867645c729a3e4b772e9b7ca122d9ebf Mon Sep 17 00:00:00 2001 From: Harun CAN Date: Mon, 23 Mar 2026 02:44:37 +0300 Subject: [PATCH] main --- src/components/skriptai/ProjectDetail.tsx | 16 +- src/components/skriptai/tabs/VersionsTab.tsx | 386 +++++++++++++++++++ src/components/skriptai/tabs/index.ts | 1 + src/lib/api/skriptai/index.ts | 16 + src/lib/api/skriptai/scripts/service.ts | 15 + src/lib/api/skriptai/scripts/use-hooks.ts | 35 ++ src/lib/api/skriptai/versions/service.ts | 78 ++++ src/lib/api/skriptai/versions/use-hooks.ts | 136 +++++++ src/types/skriptai.ts | 43 +++ 9 files changed, 725 insertions(+), 1 deletion(-) create mode 100644 src/components/skriptai/tabs/VersionsTab.tsx create mode 100644 src/lib/api/skriptai/versions/service.ts create mode 100644 src/lib/api/skriptai/versions/use-hooks.ts diff --git a/src/components/skriptai/ProjectDetail.tsx b/src/components/skriptai/ProjectDetail.tsx index 46adf65..6f975f2 100644 --- a/src/components/skriptai/ProjectDetail.tsx +++ b/src/components/skriptai/ProjectDetail.tsx @@ -26,6 +26,7 @@ import { LuBrain, LuChartBar, LuDownload, + LuHistory, } from 'react-icons/lu'; import { useGetProject, @@ -38,7 +39,7 @@ import { // Tab Components import ResearchTab from './tabs/ResearchTab'; -import { BriefTab, CharactersTab, ScriptTab, AnalysisTab } from './tabs'; +import { BriefTab, CharactersTab, ScriptTab, AnalysisTab, VersionsTab } from './tabs'; interface ProjectDetailProps { @@ -192,6 +193,15 @@ export default function ProjectDetail({ projectId }: ProjectDetailProps) { {t('analysis')} + + + Versiyonlar + {project.currentVersionNumber > 0 && ( + + {project.currentVersionNumber} + + )} + @@ -234,6 +244,10 @@ export default function ProjectDetail({ projectId }: ProjectDetailProps) { isAnalyzing={neuroAnalysis.isPending || youtubeAudit.isPending} /> + + + + diff --git a/src/components/skriptai/tabs/VersionsTab.tsx b/src/components/skriptai/tabs/VersionsTab.tsx new file mode 100644 index 0000000..d6b8ab0 --- /dev/null +++ b/src/components/skriptai/tabs/VersionsTab.tsx @@ -0,0 +1,386 @@ +'use client'; + +import { useState } from 'react'; +import { useTranslations } from 'next-intl'; +import { + Box, + Button, + Card, + Flex, + Heading, + HStack, + IconButton, + Text, + VStack, + Badge, + Input, + Textarea, +} from '@chakra-ui/react'; +import { + LuHistory, + LuSave, + LuUndo2, + LuTrash2, + LuGitCompare, + LuCheck, + LuClock, + LuBot, + LuUser, + LuChevronDown, + LuChevronUp, +} from 'react-icons/lu'; +import { + useVersions, + useCreateSnapshot, + useRestoreVersion, + useDeleteVersion, +} from '@/lib/api/skriptai'; +import { toaster } from '@/components/ui/feedback/toaster'; +import type { ScriptProject, ScriptVersionSummary } from '@/types/skriptai'; + +interface VersionsTabProps { + project: ScriptProject; +} + +export default function VersionsTab({ project }: VersionsTabProps) { + const t = useTranslations('skriptai'); + const { data: versions, isLoading } = useVersions(project.id); + const createSnapshot = useCreateSnapshot(project.id); + const restoreVersion = useRestoreVersion(project.id); + const deleteVersion = useDeleteVersion(project.id); + + const [showSaveForm, setShowSaveForm] = useState(false); + const [saveLabel, setSaveLabel] = useState(''); + const [saveNote, setSaveNote] = useState(''); + const [expandedVersionId, setExpandedVersionId] = useState(null); + + const handleSave = async () => { + await createSnapshot.mutateAsync({ + label: saveLabel || undefined, + changeNote: saveNote || undefined, + }); + setSaveLabel(''); + setSaveNote(''); + setShowSaveForm(false); + toaster.create({ + title: 'Versiyon kaydedildi', + type: 'success', + }); + }; + + const handleRestore = async (versionId: string, versionNumber: number) => { + if (!confirm(`v${versionNumber} versiyonuna geri dönmek istediğinize emin misiniz? Mevcut durum otomatik olarak kaydedilecektir.`)) { + return; + } + await restoreVersion.mutateAsync(versionId); + toaster.create({ + title: `v${versionNumber} versiyonuna geri dönüldü`, + type: 'success', + }); + }; + + const handleDelete = async (versionId: string, versionNumber: number) => { + if (!confirm(`v${versionNumber} versiyonunu silmek istediğinize emin misiniz?`)) { + return; + } + await deleteVersion.mutateAsync(versionId); + toaster.create({ + title: `v${versionNumber} silindi`, + type: 'info', + }); + }; + + const getGeneratedByIcon = (generatedBy: string) => { + switch (generatedBy) { + case 'AI': + return ; + case 'USER': + return ; + default: + return ; + } + }; + + const getGeneratedByColor = (generatedBy: string) => { + switch (generatedBy) { + case 'AI': + return 'purple'; + case 'USER': + return 'blue'; + default: + return 'gray'; + } + }; + + const getGeneratedByLabel = (generatedBy: string) => { + switch (generatedBy) { + case 'AI': + return 'AI Üretimi'; + case 'USER': + return 'Manuel Kayıt'; + default: + return 'Otomatik Kayıt'; + } + }; + + const formatDate = (dateStr: string) => { + const d = new Date(dateStr); + return d.toLocaleString('tr-TR', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + }); + }; + + return ( + + {/* Header */} + + + + Versiyon Geçmişi + + {versions?.length || 0} versiyon + + + Şu an: v{project.currentVersionNumber} + + + + + + + {/* Save Form */} + {showSaveForm && ( + + + + 💾 Yeni Versiyon Kaydet + + setSaveLabel(e.target.value)} + size='sm' + /> +