'use client'; import { useEffect, useState } from 'react'; import { ImagePlus, Maximize, Eraser, Film, Captions, Volume2, Type, Wand2, FileText, TrendingUp, Clock, CheckCircle, } from 'lucide-react'; import { useRouter } from 'next/navigation'; import { toast } from 'react-hot-toast'; import ModuleCard from '@/components/ModuleCard'; import { useStore } from '@/lib/store'; import { jobsApi, usersApi } from '@/lib/api'; const modules = [ { title: 'Image Generator', description: 'Create stunning images with AI using multiple providers', icon: ImagePlus, href: '/image/generate', }, { title: 'Image Upscaler', description: 'Enhance image resolution with Topaz Labs AI', icon: Maximize, href: '/image/upscale', }, { title: 'Background Remover', description: 'Remove backgrounds instantly with precision', icon: Eraser, href: '/image/remove-bg', }, { title: 'Video Generator', description: 'Generate videos with Runway and Google Veo', icon: Film, href: '/video/generate', }, { title: 'Video Upscaler', description: 'Upscale videos to higher resolutions', icon: Maximize, href: '/video/upscale', }, { title: 'Subtitle Generator', description: 'Auto-generate and translate subtitles', icon: Captions, href: '/video/subtitles', }, { title: 'Text to Speech', description: 'Convert text to natural speech with ElevenLabs', icon: Volume2, href: '/audio/text-to-speech', }, { title: 'Voice to Text', description: 'Transcribe audio with Whisper AI', icon: Type, href: '/audio/voice-to-text', }, { title: 'Prompt Studio', description: 'Enhance your prompts with AI assistance', icon: Wand2, href: '/text/prompt-studio', }, { title: 'Alt Text Generator', description: 'Generate accessible alt text for images', icon: FileText, href: '/text/alt-text', }, ]; export default function Dashboard() { const router = useRouter(); const { activeJobs } = useStore(); const [stats, setStats] = useState({ totalJobs: 0, completedToday: 0, processingTime: 0, }); const [recentJobs, setRecentJobs] = useState([]); const [dragTarget, setDragTarget] = useState<{ href: string, valid: boolean } | null>(null); useEffect(() => { const fetchData = async () => { try { const jobsResponse = await jobsApi.list({ limit: 5 }); setRecentJobs(jobsResponse.data.items || []); // Calculate stats from recent jobs const completed = jobsResponse.data.items?.filter( (j: any) => j.status === 'completed' ).length || 0; setStats({ totalJobs: jobsResponse.data.total || 0, completedToday: completed, processingTime: 2.4, }); } catch (err) { console.error('Failed to fetch dashboard data:', err); } }; fetchData(); }, []); const validateDrop = (href: string, mimeType: string) => { if (href.startsWith('/image/')) return mimeType.startsWith('image/'); if (href === '/video/upscale') return mimeType.startsWith('video/'); if (href === '/video/subtitles') return mimeType.startsWith('video/'); if (href === '/video/generate') return mimeType.startsWith('image/'); // Image to Video if (href === '/text/alt-text') return mimeType.startsWith('image/'); if (href === '/audio/voice-to-text') return mimeType.startsWith('audio/') || mimeType.startsWith('video/'); return false; }; const handleDragOver = (e: React.DragEvent, href: string) => { e.preventDefault(); if (e.dataTransfer.types.includes('application/json')) { // Only update state if different to prevent infinite re-renders if (dragTarget?.href !== href) { setDragTarget({ href, valid: true }); } } }; const handleDrop = (e: React.DragEvent, href: string) => { e.preventDefault(); setDragTarget(null); const raw = e.dataTransfer.getData('application/json'); if (!raw) return; try { const data = JSON.parse(raw); if (data.type === 'forge-asset') { if (validateDrop(href, data.mime_type || '')) { router.push(`${href}?assetId=${data.id}`); toast.success('File loaded into tool'); } else { toast.error('Invalid file type for this tool'); } } } catch (err) { console.error(err); } }; return (
{/* Stats Grid */}

Total Jobs

{stats.totalJobs}

Completed Today

{stats.completedToday}

Avg. Processing Time

{stats.processingTime}s

{/* Active Jobs */} {activeJobs.filter((j) => j.status === 'processing').length > 0 && (

Active Jobs

{activeJobs .filter((j) => j.status === 'processing') .map((job) => (
{job.module.replace('_', ' ')} {job.progress}%
))}
)} {/* Modules Grid */}

AI Tools

{modules.map((module) => (
handleDragOver(e, module.href)} onDragLeave={() => setDragTarget(null)} onDrop={(e) => handleDrop(e, module.href)} className={`transition-all rounded-xl h-full ${dragTarget?.href === module.href ? 'ring-2 ring-forge-yellow scale-105' : ''}`} >
))}
{/* Recent Jobs */} {recentJobs.length > 0 && (

Recent Activity

{recentJobs.map((job: any) => ( ))}
Module Status Provider Created
{job.module?.replace('_', ' ')} {job.status} {job.api_provider || '-'} {new Date(job.created_at).toLocaleString()}
)}
); }