HackingFactory-v2 / client /src /pages /Dashboard.tsx
FECUOY's picture
Initial commit: HackingFactory v2 Enhanced with Self-Refining AI features
4c41b3d
import React, { useState } from "react";
import { trpc } from "@/lib/trpc";
import { useAuth } from "@/_core/hooks/useAuth";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Badge } from "@/components/ui/badge";
import { Zap, Code2, Cpu, TrendingUp, Plus, Play, Activity } from "lucide-react";
import { IterationChart } from "@/components/IterationChart";
import { CodeEditor } from "@/components/CodeEditor";
import { PayloadLibrary } from "@/components/PayloadLibrary";
import { NewProjectDialog } from "@/components/NewProjectDialog";
import ChatInterface from "./ChatInterface";
export default function Dashboard() {
const { user } = useAuth();
const projectsQuery = trpc.projects.list.useQuery();
const [selectedProject, setSelectedProject] = useState<number | null>(null);
const [refreshKey, setRefreshKey] = useState(0);
const iterationsQuery = trpc.projects.getIterations.useQuery(
{ projectId: selectedProject as number },
{ enabled: !!selectedProject }
);
const stats = [
{ label: "Active Projects", value: projectsQuery.data?.length || 0, icon: Code2, color: "from-green-400 to-emerald-500" },
{ label: "Completed", value: projectsQuery.data?.filter(p => p.status === "completed").length || 0, icon: TrendingUp, color: "from-cyan-400 to-blue-500" },
{ label: "Processing", value: projectsQuery.data?.filter(p => p.status === "in_progress").length || 0, icon: Cpu, color: "from-purple-400 to-pink-500" },
{ label: "Avg Score", value: "85", icon: Zap, color: "from-orange-400 to-red-500" },
];
const handleProjectCreated = () => {
projectsQuery.refetch();
setRefreshKey(prev => prev + 1);
};
return (
<div className="min-h-screen bg-black text-white">
{/* Header */}
<header className="border-b border-green-500/20 bg-black/50 backdrop-blur-sm sticky top-0 z-40">
<div className="container mx-auto px-4 py-4 flex justify-between items-center">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-gradient-to-br from-green-400 to-cyan-400 flex items-center justify-center">
<Zap className="text-black" size={20} />
</div>
<div>
<h1 className="text-xl font-bold bg-gradient-to-r from-green-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent">
Hacking Factory
</h1>
<p className="text-xs text-gray-400">AI Code Generation & Evaluation</p>
</div>
</div>
<div className="text-sm text-gray-400">
Welcome, <span className="text-green-400 font-semibold">{user?.name || "User"}</span>
</div>
</div>
</header>
{/* Main Content */}
<main className="container mx-auto px-4 py-8">
{/* Stats Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
{stats.map((stat, idx) => {
const Icon = stat.icon;
return (
<Card key={idx} className="bg-gray-900/50 border-green-500/20 hover:border-green-500/50 transition-colors">
<CardContent className="pt-6">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-400 text-sm">{stat.label}</p>
<p className="text-3xl font-bold text-white mt-2">{stat.value}</p>
</div>
<div className={`p-3 rounded-lg bg-gradient-to-br ${stat.color} opacity-20`}>
<Icon className="text-white" size={24} />
</div>
</div>
</CardContent>
</Card>
);
})}
</div>
{/* Projects Section */}
<Tabs defaultValue="projects" className="space-y-4">
<TabsList className="bg-gray-900/50 border border-green-500/20">
<TabsTrigger value="projects" className="data-[state=active]:bg-green-500/20 data-[state=active]:text-green-400">
Projects
</TabsTrigger>
<TabsTrigger value="chat" className="data-[state=active]:bg-cyan-500/20 data-[state=active]:text-cyan-400">
AI Chat
</TabsTrigger>
<TabsTrigger value="library" className="data-[state=active]:bg-purple-500/20 data-[state=active]:text-purple-400">
Code Library
</TabsTrigger>
</TabsList>
{/* Projects Tab */}
<TabsContent value="projects" className="space-y-4">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-bold text-white">Your Projects</h2>
<NewProjectDialog onProjectCreated={handleProjectCreated} />
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="space-y-4">
{projectsQuery.data?.map((project) => (
<Card
key={project.id}
className={`bg-gray-900/50 border-green-500/20 hover:border-green-500/50 transition-all cursor-pointer ${selectedProject === project.id ? 'border-green-500 ring-1 ring-green-500' : ''}`}
onClick={() => setSelectedProject(project.id)}
>
<CardHeader>
<div className="flex justify-between items-start">
<div>
<CardTitle className="text-green-400">{project.name}</CardTitle>
<CardDescription className="text-gray-400 mt-1">
Mode: <span className="text-cyan-400 font-mono">{project.mode}</span>
</CardDescription>
</div>
<Badge
className={`${
project.status === "completed"
? "bg-green-500/20 text-green-400"
: project.status === "in_progress"
? "bg-cyan-500/20 text-cyan-400"
: "bg-gray-500/20 text-gray-400"
}`}
>
{project.status}
</Badge>
</div>
</CardHeader>
<CardContent>
<div className="flex justify-between items-center">
<div className="text-sm text-gray-400">
Score: <span className="text-green-400 font-bold">{project.finalScore}/100</span>
</div>
<Button variant="ghost" size="sm" className="text-cyan-400 hover:text-cyan-300">
<Play size={16} className="mr-2" />
View
</Button>
</div>
</CardContent>
</Card>
))}
{!projectsQuery.data || projectsQuery.data.length === 0 && (
<Card className="bg-gray-900/50 border-gray-500/20">
<CardContent className="pt-6 text-center text-gray-500">
No projects yet. Create one to get started!
</CardContent>
</Card>
)}
</div>
{/* Detail Panel */}
<div className="space-y-4">
{selectedProject ? (
<Card className="bg-gray-900/50 border-cyan-500/20 h-full">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-cyan-400">
<Activity size={20} />
Iteration Progress
</CardTitle>
</CardHeader>
<CardContent>
{iterationsQuery.data && iterationsQuery.data.length > 0 ? (
<div className="space-y-6">
<IterationChart data={iterationsQuery.data} />
<div className="grid grid-cols-2 gap-4">
<div className="p-3 rounded-lg bg-black/50 border border-green-500/20">
<p className="text-xs text-gray-400">Best Score</p>
<p className="text-xl font-bold text-green-400">
{Math.max(...iterationsQuery.data.map(i => i.score || 0))}/100
</p>
</div>
<div className="p-3 rounded-lg bg-black/50 border border-cyan-500/20">
<p className="text-xs text-gray-400">Total Iterations</p>
<p className="text-xl font-bold text-cyan-400">
{iterationsQuery.data.length}
</p>
</div>
</div>
</div>
) : (
<div className="h-64 flex items-center justify-center text-gray-500 border border-dashed border-gray-700 rounded-lg">
No iterations recorded yet
</div>
)}
</CardContent>
</Card>
) : (
<div className="h-full flex items-center justify-center text-gray-500 border border-dashed border-gray-700 rounded-lg">
Select a project to view progress
</div>
)}
</div>
</div>
</TabsContent>
{/* Chat Tab */}
<TabsContent value="chat" className="space-y-4">
<Card className="bg-gray-900/50 border-cyan-500/20">
<CardHeader>
<CardTitle className="text-cyan-400">AI Chat Interface</CardTitle>
<CardDescription className="text-gray-400">
Generate and evaluate code with multiple AI models
</CardDescription>
</CardHeader>
<CardContent>
<ChatInterface />
</CardContent>
</Card>
</TabsContent>
{/* Library Tab */}
<TabsContent value="library" className="space-y-4">
<Card className="bg-gray-900/50 border-purple-500/20">
<CardHeader>
<CardTitle className="text-purple-400">Code Library</CardTitle>
<CardDescription className="text-gray-400">
Manage your reference code files and templates
</CardDescription>
</CardHeader>
<CardContent>
<PayloadLibrary
payloads={[
{ id: "p1", name: "Reverse Shell", score: 92, tags: ["shell", "network"] },
{ id: "p2", name: "Privilege Escalation", score: 88, tags: ["privilege", "windows"] },
{ id: "p3", name: "Data Exfiltration", score: 85, tags: ["data", "stealth"] },
]}
/>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</main>
</div>
);
}