import React, { useState, useEffect } from 'react' import { Button } from './ui/8bit/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/8bit/card' import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from './ui/8bit/dialog' import { History, GitBranch, FileText, User, Clock, Package, ChevronDown, ChevronRight } from 'lucide-react' import type { VersionEntry, VariableChange } from '../types' interface VersionHistoryProps { projectPath?: string onRestoreVersion?: (versionId: string) => void playSound?: (type: 'success' | 'error' | 'powerup' | 'hit') => void } export default function VersionHistory({ projectPath, onRestoreVersion, playSound }: VersionHistoryProps) { const [versions, setVersions] = useState([]) const [isLoading, setIsLoading] = useState(false) const [selectedVersion, setSelectedVersion] = useState(null) const [expandedVersions, setExpandedVersions] = useState>(new Set()) useEffect(() => { loadVersionHistory() }, [projectPath]) const loadVersionHistory = async () => { setIsLoading(true) try { const res = await fetch(`/api/versions${projectPath ? `?projectPath=${encodeURIComponent(projectPath)}` : ''}`) if (res.ok) { const data = await res.json() setVersions(data.versions || []) } } catch (error) { console.error('Failed to load version history:', error) playSound?.('error') } setIsLoading(false) } const handleRestoreVersion = async (versionId: string) => { if (!confirm('Are you sure you want to restore this version? This will create a new draft with the restored state.')) { return } try { const res = await fetch('/api/versions/restore', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ versionId, projectPath }) }) if (res.ok) { onRestoreVersion?.(versionId) playSound?.('powerup') } else { playSound?.('error') } } catch (error) { console.error('Failed to restore version:', error) playSound?.('error') } } const toggleVersionExpanded = (versionId: string) => { const newExpanded = new Set(expandedVersions) if (newExpanded.has(versionId)) { newExpanded.delete(versionId) } else { newExpanded.add(versionId) } setExpandedVersions(newExpanded) } const formatChangeType = (type: 'create' | 'update' | 'delete' | 'none'): { text: string; color: string } => { switch (type) { case 'create': return { text: 'ADDED', color: 'text-green-400' } case 'update': return { text: 'MODIFIED', color: 'text-yellow-400' } case 'delete': return { text: 'DELETED', color: 'text-red-400' } case 'none': default: return { text: 'UNCHANGED', color: 'text-gray-400' } } } const getTimeDifference = (timestamp: string): string => { const now = new Date() const then = new Date(timestamp) const diffMs = now.getTime() - then.getTime() const diffMinutes = Math.floor(diffMs / (1000 * 60)) const diffHours = Math.floor(diffMinutes / 60) const diffDays = Math.floor(diffHours / 24) if (diffMinutes < 1) return 'Just now' if (diffMinutes < 60) return `${diffMinutes}m ago` if (diffHours < 24) return `${diffHours}h ago` return `${diffDays}d ago` } return ( VERSION HISTORY Track and manage environment variable changes over time {isLoading ? (
Loading version history...
) : versions.length === 0 ? (

No version history available

Publish some changes to start tracking versions

) : (
{versions.map((version) => { const isExpanded = expandedVersions.has(version.id) return (
{version.version} {version.published && ( PUBLISHED )}

{version.description}

{getTimeDifference(version.timestamp)}
{version.author && (
{version.author}
)}
{version.variableCount} variables {version.changes.length} changes
Version {selectedVersion?.version} Details {selectedVersion?.description}
Published: {new Date(selectedVersion?.timestamp || '').toLocaleString()}
Author: {selectedVersion?.author || 'Unknown'}
Variables: {selectedVersion?.variableCount}
Changes: {selectedVersion?.changes.length}
{selectedVersion && selectedVersion.changes.length > 0 && (

Changes:

{selectedVersion.changes.map((change, idx) => { const { text, color } = formatChangeType(change.type) return (
{change.name} {text}
{change.type !== 'create' && change.oldValue && (
Old: {change.sensitive ? '••••••••' : change.oldValue}
)} {change.type !== 'delete' && change.newValue && (
New: {change.sensitive ? '••••••••' : change.newValue}
)}
) })}
)}
{isExpanded && (
CHANGES IN THIS VERSION:
{version.changes.map((change, idx) => { const { text, color } = formatChangeType(change.type) return (
{change.name} {text}
) })}
)}
) })}
)}
) }