veza/apps/web/src/components/views/FileDetailsView.tsx

187 lines
9.4 KiB
TypeScript
Raw Normal View History

import React from 'react';
import { Card } from '../ui/card';
import { Button } from '../ui/button';
import { Badge } from '../ui/badge';
import { FileNode } from '../../types';
import {
ArrowLeft, Download, Share2, Trash2, Edit3,
Music, FileText, Play, Activity,
Layers, HardDrive, Info
} from 'lucide-react';
import { useToast } from '../../context/ToastContext';
// Extended Mock Data for Demo
const MOCK_ACTIVITY = [
{ id: 'a1', user: 'Cyber_Producer', action: 'uploaded', timestamp: '2 days ago' },
{ id: 'a2', user: 'Sarah Connor', action: 'viewed', timestamp: '1 day ago' },
{ id: 'a3', user: 'System', action: 'processed', timestamp: '2 days ago' },
];
const MOCK_VERSIONS = [
{ id: 'v1', version: 'v1.0', uploadedBy: 'Cyber_Producer', timestamp: '2 days ago', size: '24.5 MB', url: '#' },
{ id: 'v2', version: 'v1.1', uploadedBy: 'Cyber_Producer', timestamp: '5 hours ago', size: '24.6 MB', url: '#', current: true },
];
interface FileDetailsViewProps {
fileId: string;
onBack: () => void;
}
export const FileDetailsView: React.FC<FileDetailsViewProps> = ({ fileId, onBack }) => {
const { addToast } = useToast();
// Mock fetching logic based on ID
const file: FileNode = {
id: fileId,
name: 'Neon_Nights_Final_Master.wav',
type: 'audio',
size: '48.2 MB',
modified: '2 hours ago',
status: 'ready',
metadata: {
bpm: 128,
key: 'F# Minor',
genre: 'Synthwave',
duration: '3:45'
}
};
const isAudio = file.type === 'audio';
const isImage = file.type === 'image';
return (
<div className="animate-fadeIn space-y-6 pb-20">
{/* Header */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<Button variant="ghost" size="icon" onClick={onBack} aria-label="Retour"><ArrowLeft className="w-5 h-5" /></Button>
<div>
<h2 className="text-2xl font-bold text-white flex items-center gap-3">
{file.name}
<Badge label={file.type} variant="terminal" />
</h2>
<p className="text-gray-400 text-sm font-mono flex items-center gap-4 mt-1">
<span>{file.size}</span>
<span></span>
<span>Modified {file.modified}</span>
</p>
</div>
</div>
<div className="flex gap-2">
<Button variant="ghost" icon={<Share2 className="w-4 h-4" />} onClick={() => addToast("Link copied")}>Share</Button>
<Button variant="primary" icon={<Download className="w-4 h-4" />} onClick={() => addToast("Downloading...")}>Download</Button>
<Button variant="ghost" className="text-kodo-red hover:bg-kodo-red/10" icon={<Trash2 className="w-4 h-4" />}>Delete</Button>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Left: Preview Area */}
<div className="lg:col-span-2 space-y-6">
<Card variant="default" className="min-h-[400px] flex items-center justify-center bg-black relative overflow-hidden group">
{isAudio && (
<div className="text-center w-full max-w-md">
<div className="w-32 h-32 bg-gradient-to-br from-kodo-cyan to-blue-600 rounded-full mx-auto mb-8 flex items-center justify-center shadow-[0_0_50px_rgba(102,252,241,0.3)] animate-pulse">
<Music className="w-12 h-12 text-black" />
</div>
<div className="h-16 flex items-center justify-center gap-1 mb-8">
{Array.from({length: 40}).map((_,i) => (
<div key={i} className="w-1.5 bg-kodo-cyan rounded-full" style={{height: `${Math.random() * 100}%`}}></div>
))}
</div>
<Button variant="primary" size="lg" className="rounded-full px-8" icon={<Play className="w-5 h-5 fill-current" />}>
PLAY PREVIEW
</Button>
</div>
)}
{isImage && (
<img src="https://picsum.photos/id/200/800/600" className="w-full h-full object-contain" />
)}
{!isAudio && !isImage && (
<div className="text-center text-gray-500">
<FileText className="w-24 h-24 mx-auto mb-4 opacity-50" />
<p>No preview available for this file type.</p>
</div>
)}
</Card>
{/* Metadata Grid */}
<Card variant="default">
<div className="flex justify-between items-center mb-6">
<h3 className="font-bold text-white flex items-center gap-2"><Info className="w-4 h-4 text-kodo-cyan" /> Metadata</h3>
<Button variant="ghost" size="sm" icon={<Edit3 className="w-3 h-3" />}>Edit</Button>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{Object.entries(file.metadata || {}).map(([key, val]) => (
<div key={key} className="bg-kodo-ink p-3 rounded border border-kodo-steel/50">
<div className="text-xs text-gray-500 uppercase font-bold mb-1">{key}</div>
<div className="text-white font-medium">{String(val)}</div>
</div>
))}
</div>
</Card>
</div>
{/* Right: Sidebar */}
<div className="space-y-6">
{/* Activity Feed */}
<Card variant="gaming">
<h3 className="font-bold text-white mb-4 flex items-center gap-2 text-sm uppercase tracking-wider">
<Activity className="w-4 h-4 text-kodo-gold" /> Activity Log
</h3>
<div className="space-y-4 relative">
<div className="absolute left-3 top-2 bottom-2 w-px bg-kodo-steel"></div>
{MOCK_ACTIVITY.map((act) => (
<div key={act.id} className="flex gap-3 relative">
<div className="w-6 h-6 rounded-full bg-kodo-graphite border border-kodo-steel flex items-center justify-center shrink-0 z-10">
<div className="w-2 h-2 rounded-full bg-kodo-gold"></div>
</div>
<div>
<p className="text-sm text-gray-300">
<span className="font-bold text-white">{act.user}</span> {act.action} this file.
</p>
<p className="text-xs text-gray-500">{act.timestamp}</p>
</div>
</div>
))}
</div>
</Card>
{/* Versions */}
<Card variant="default">
<h3 className="font-bold text-white mb-4 flex items-center gap-2 text-sm uppercase tracking-wider">
<Layers className="w-4 h-4 text-kodo-magenta" /> Version History
</h3>
<div className="space-y-2">
{MOCK_VERSIONS.map((ver) => (
<div key={ver.id} className={`flex items-center justify-between p-3 rounded border ${ver.current ? 'bg-kodo-magenta/10 border-kodo-magenta/30' : 'bg-kodo-ink border-kodo-steel hover:bg-white/5'}`}>
<div>
<div className="flex items-center gap-2">
<span className="font-bold text-white text-sm">{ver.version}</span>
{ver.current && <span className="text-[10px] bg-kodo-magenta text-white px-1.5 rounded">LATEST</span>}
</div>
<div className="text-xs text-gray-500">{ver.timestamp} {ver.uploadedBy}</div>
</div>
<Button variant="ghost" size="icon" className="h-8 w-8" aria-label="Télécharger"><Download className="w-3 h-3" /></Button>
</div>
))}
</div>
</Card>
{/* Storage Info */}
<div className="bg-kodo-ink p-4 rounded-xl border border-kodo-steel flex items-center gap-4">
<div className="w-10 h-10 bg-kodo-slate rounded-lg flex items-center justify-center text-gray-400">
<HardDrive className="w-5 h-5" />
</div>
<div>
<div className="text-xs text-gray-500 uppercase">Storage Location</div>
<div className="text-sm font-bold text-white">s3://veza-cloud/projects/alpha</div>
</div>
</div>
</div>
</div>
</div>
);
};