/** * Version history panel component * Provides UI for viewing and managing project versions */ import { Clock, GitBranch, History, MessageCircle, Plus, RotateCcw, Settings, User } from "lucide-react" import { useCallback, useEffect, useState } from "react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { ScrollArea } from "@/components/ui/scroll-area" import { Separator } from "@/components/ui/separator" import { useVersionControl } from "@/features/app-state/hooks/use-version-control" import { VersionInfo } from "../types" // Простая функция форматирования времени без date-fns const formatTimeAgo = (date: Date): string => { const now = new Date() const diffMs = now.getTime() - date.getTime() const diffMinutes = Math.floor(diffMs / (1000 * 60)) const diffHours = Math.floor(diffMs / (1000 * 60 * 60)) const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)) if (diffMinutes < 1) return "только что" if (diffMinutes < 60) return `${diffMinutes} мин. назад` if (diffHours < 24) return `${diffHours} ч. назад` if (diffDays < 30) return `${diffDays} дн. назад` return date.toLocaleDateString() } interface VersionHistoryPanelProps { className?: string } export function VersionHistoryPanel({ className }: VersionHistoryPanelProps) { const { currentVersionId, branchName, lastSnapshotTime, autoSaveEnabled, autoSaveIntervalSeconds, isLoading, error, createSnapshot, restoreVersion, getVersionHistory, enableAutoSave, setAutoSaveInterval, } = useVersionControl() const [versions, setVersions] = useState([]) const [loadingVersions, setLoadingVersions] = useState(false) const [snapshotMessage, setSnapshotMessage] = useState("") const [showAutoSaveSettings, setShowAutoSaveSettings] = useState(false) // Load version history const loadVersionHistory = useCallback(async () => { setLoadingVersions(true) try { const history = await getVersionHistory(20) // Last 20 versions if (history) { setVersions(history) } } finally { setLoadingVersions(false) } }, [getVersionHistory]) // Load history on mount and when current version changes useEffect(() => { void loadVersionHistory() }, [loadVersionHistory, currentVersionId]) // Handle create snapshot const handleCreateSnapshot = useCallback(async () => { const success = await createSnapshot(snapshotMessage || undefined) if (success) { setSnapshotMessage("") void loadVersionHistory() // Refresh list } }, [createSnapshot, snapshotMessage, loadVersionHistory]) // Handle restore version const handleRestoreVersion = useCallback( async (versionId: string) => { if (window.confirm(`Восстановить проект до версии ${versionId}? Все несохранённые изменения будут потеряны.`)) { const success = await restoreVersion(versionId) if (success) { void loadVersionHistory() // Refresh list } } }, [restoreVersion, loadVersionHistory], ) // Handle auto-save toggle const handleToggleAutoSave = useCallback(async () => { await enableAutoSave(!autoSaveEnabled) }, [enableAutoSave, autoSaveEnabled]) // Handle auto-save interval change const handleIntervalChange = useCallback( async (newInterval: number) => { await setAutoSaveInterval(newInterval) }, [setAutoSaveInterval], ) return ( История версий
Ветка: {branchName} {currentVersionId}
{/* Auto-save status */}
Автосохранение: {autoSaveEnabled ? "включено" : "отключено"} {autoSaveEnabled && ` (${autoSaveIntervalSeconds}с)`}
{/* Auto-save settings */} {showAutoSaveSettings && (
{autoSaveEnabled && (
{[30, 60, 120, 300].map((interval) => ( ))}
)}
)} {/* Create snapshot */}
setSnapshotMessage(e.target.value)} className="flex-1 px-3 py-2 text-sm border rounded-md" disabled={isLoading} />
{/* Version history */}

История версий

{error &&
{error}
} {loadingVersions ? (
Загрузка...
) : versions.length === 0 ? (
Нет сохранённых версий
) : (
{versions.map((version) => (
{version.id.slice(0, 8)} {version.id === currentVersionId && ( Текущая )}
{version.id !== currentVersionId && ( )}
{version.author} {formatTimeAgo(new Date(version.timestamp))}
{version.message && (
{version.message}
)}
))}
)}
{/* Last snapshot info */} {lastSnapshotTime && (
Последний снапшот: {formatTimeAgo(lastSnapshotTime)}
)}
) }