aethex-studio/src/components/PreviewModal.tsx
MrPiglr 8d6ebeba35 Generated by Spark: Create a cloud-based game development IDE called "AeThex Studio" using Next.js and Tailwind.
Layout:

Top navbar: AeThex logo (left), project name (center), user menu with avatar (right)
Left sidebar (250px): File tree navigator with folders/files, "New File" and "New Folder" buttons
Center: Code editor area (use Monaco Editor component if available, or textarea with syntax highlighting)
Right sidebar (300px, collapsible): AI Assistant chat panel with message history
Bottom panel (200px, collapsible): Console output and terminal
Features:

File tree supports create/rename/delete operations
Tabs for multiple open files
Syntax highlighting for Lua, JavaScript, TypeScript
Dark theme with purple/cyan accent colors (futuristic gaming aesthetic)
Split panes are resizable
Auto-save indicator in navbar
Use TypeScript and proper state management. Make it feel like VS Code but purpose-built for game development.

Create a unified game development workspace that shows the same game running on three platforms simultaneously:

Left panel: Roblox viewport (embed mockup)
Center panel: Web browser viewport with game canvas
Right panel: Mobile device mockup with game
Include:

Shared state indicator showing synced variables (player position, score, inventory)
Platform-specific code tabs that show Lua (Roblox), JavaScript (Web), and React Native (Mobile)
"Deploy to Platform" buttons for each
Sync status indicator (green = synced, yellow = syncing, red = conflict)
Console output panel at bottom showing platform-specific logs
Use a dark IDE-like theme. Make it feel like a professional developer tool.

Add a "New Project" modal to the AeThex Studio IDE:

Modal triggered by "New Project" button in navbar:

Step 1: Choose template (card grid layout)

Roblox Game Starter
Cross-Platform Multiplayer
Transmedia Story Project
Blank Project Each card shows icon, title, description, and "Popular" badge where applicable
Step 2: Project configuration form

Project name input
Platform checkboxes (Roblox, Web, Mobile)
Enable Nexus Engine toggle (with tooltip explaining state sync)
Enable Passport Auth toggle (with tooltip explaining unified identity)
Step 3: Review summary and "Create Project" button

After creation, populate file tree with template structure and open main file in editor.

Use a stepper UI component to show progress. Modern, clean design.

Build the AI Assistant chat panel for the right sidebar:

UI Components:

Header: "AeThex AI Assistant" with model selector dropdown (Claude Sonnet, GPT-4o)
Chat message history (scrollable, auto-scroll to bottom)
Messages alternate left (user) and right (AI) with avatars
Code blocks in messages with syntax highlighting and copy button
Input textarea at bottom with "Send" button
Token usage indicator (shows X / 500K tokens used this month)
Quick Actions (buttons above input):

"Explain selected code"
"Add comments"
"Convert to cross-platform"
"Generate tests"
Message Types:

User messages: blue background
AI messages: dark gray background with purple border
System messages: small, centered, gray text (e.g., "Code inserted into editor")
Features:

When AI generates code, show "Insert into editor" button
Track conversation context (include current file, project structure)
Show typing indicator when AI is responding
Make the UX smooth and polished.

Create a preview panel modal that opens when user clicks "Preview" in navbar:

Layout (fullscreen modal with dark backdrop):

Close button (top right)
Tab navigation: "Roblox" | "Web" | "Mobile" | "All Platforms"
"All Platforms" tab shows three columns:

Left: Roblox viewport (iframe placeholder with Roblox logo)
Center: Web browser viewport (iframe with game canvas)
Right: Mobile device mockup (iPhone frame with game view)
Shared State Indicator (floating panel at bottom):

Shows synced variables in real-time table: Variable | Roblox | Web | Mobile | Status playerX | 120 | 120 | 120 | ✓ Synced health | 100 | 98 | 100 | ⚠ Syncing
Color coded: Green (synced), Yellow (syncing), Red (conflict)
Controls:

"Refresh All" button
Individual "Deploy to [Platform]" buttons
Latency simulator slider (0-500ms)
Use glassmorphism UI style with blur effects. This should look futuristic and impressive.

Add user authentication and workspace management:

Login page:

AeThex logo and tagline
"Sign in with AeThex Passport" button (purple gradient)
"Sign in with Google" button
"Sign in with GitHub" button
Illustration of cross-platform game development
Dashboard (after login, before opening project):

Header: "My Workspaces" with "New Workspace" button
Grid of workspace cards showing:
Project name
Last modified timestamp
Platform badges (Roblox, Web, Mobile icons)
Thumbnail/preview image
Three-dot menu (Rename, Delete, Share)
Empty state if no workspaces: "Create your first game" CTA with template previews
Each workspace card is clickable and opens the IDE with that project loaded.

Use modern card design with hover effects. Show loading skeletons while fetching data.
2026-01-17 03:02:17 +00:00

207 lines
9.4 KiB
TypeScript

import { useState } from 'react';
import { Dialog, DialogContent } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Card } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { X, ArrowsClockwise } from '@phosphor-icons/react';
interface PreviewModalProps {
open: boolean;
onClose: () => void;
code: string;
}
interface SharedState {
variable: string;
roblox: string;
web: string;
mobile: string;
status: 'synced' | 'syncing' | 'conflict';
}
export function PreviewModal({ open, onClose, code }: PreviewModalProps) {
const [sharedState] = useState<SharedState[]>([
{ variable: 'playerX', roblox: '120', web: '120', mobile: '120', status: 'synced' },
{ variable: 'playerY', roblox: '50', web: '50', mobile: '50', status: 'synced' },
{ variable: 'health', roblox: '100', web: '98', mobile: '100', status: 'syncing' },
{ variable: 'score', roblox: '450', web: '450', mobile: '450', status: 'synced' },
]);
const getStatusColor = (status: SharedState['status']) => {
switch (status) {
case 'synced':
return 'text-green-500';
case 'syncing':
return 'text-yellow-500';
case 'conflict':
return 'text-red-500';
}
};
const getStatusIcon = (status: SharedState['status']) => {
switch (status) {
case 'synced':
return '✓';
case 'syncing':
return '⚠';
case 'conflict':
return '✗';
}
};
return (
<Dialog open={open} onOpenChange={onClose}>
<DialogContent className="max-w-[95vw] h-[90vh] p-0 gap-0">
<div className="flex flex-col h-full">
<div className="flex items-center justify-between p-4 border-b border-border">
<h2 className="text-xl font-bold">Preview - All Platforms</h2>
<div className="flex items-center gap-2">
<Button variant="outline" size="sm">
<ArrowsClockwise className="mr-2" />
Refresh All
</Button>
<Button variant="ghost" size="icon" onClick={onClose}>
<X />
</Button>
</div>
</div>
<Tabs defaultValue="all" className="flex-1 flex flex-col">
<TabsList className="mx-4 mt-4 w-fit">
<TabsTrigger value="all">All Platforms</TabsTrigger>
<TabsTrigger value="roblox">Roblox</TabsTrigger>
<TabsTrigger value="web">Web</TabsTrigger>
<TabsTrigger value="mobile">Mobile</TabsTrigger>
</TabsList>
<TabsContent value="all" className="flex-1 flex flex-col p-4 gap-4 m-0">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 flex-1">
<Card className="p-4 flex flex-col">
<div className="flex items-center justify-between mb-3">
<h3 className="font-semibold">Roblox</h3>
<Button size="sm" variant="outline">Deploy</Button>
</div>
<div className="flex-1 bg-muted/30 rounded flex items-center justify-center border-2 border-dashed border-border">
<div className="text-center p-8">
<div className="text-6xl mb-4">🎮</div>
<p className="text-sm text-muted-foreground">Roblox Viewport</p>
<p className="text-xs text-muted-foreground mt-1">Studio integration</p>
</div>
</div>
</Card>
<Card className="p-4 flex flex-col">
<div className="flex items-center justify-between mb-3">
<h3 className="font-semibold">Web Browser</h3>
<Button size="sm" variant="outline">Deploy</Button>
</div>
<div className="flex-1 bg-muted/30 rounded flex items-center justify-center border-2 border-dashed border-border">
<div className="text-center p-8">
<div className="text-6xl mb-4">🌐</div>
<p className="text-sm text-muted-foreground">Web Canvas</p>
<p className="text-xs text-muted-foreground mt-1">Browser preview</p>
</div>
</div>
</Card>
<Card className="p-4 flex flex-col">
<div className="flex items-center justify-between mb-3">
<h3 className="font-semibold">Mobile</h3>
<Button size="sm" variant="outline">Deploy</Button>
</div>
<div className="flex-1 bg-muted/30 rounded flex items-center justify-center border-2 border-dashed border-border">
<div className="w-[200px] h-full bg-background rounded-3xl border-4 border-foreground/20 p-2 flex flex-col">
<div className="w-1/3 h-6 bg-foreground/10 rounded-full mx-auto mb-2" />
<div className="flex-1 bg-muted/30 rounded-2xl flex items-center justify-center">
<div className="text-center">
<div className="text-4xl mb-2">📱</div>
<p className="text-xs text-muted-foreground">Mobile View</p>
</div>
</div>
<div className="h-6 w-1/2 bg-foreground/10 rounded-full mx-auto mt-2" />
</div>
</div>
</Card>
</div>
<Card className="p-4">
<div className="flex items-center justify-between mb-3">
<h3 className="font-semibold">Shared State Sync</h3>
<Badge variant="outline" className="text-green-500 border-green-500">
Live Sync Enabled
</Badge>
</div>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead className="border-b border-border">
<tr className="text-left">
<th className="pb-2 font-semibold">Variable</th>
<th className="pb-2 font-semibold">Roblox</th>
<th className="pb-2 font-semibold">Web</th>
<th className="pb-2 font-semibold">Mobile</th>
<th className="pb-2 font-semibold">Status</th>
</tr>
</thead>
<tbody>
{sharedState.map((state, idx) => (
<tr key={idx} className="border-b border-border/50">
<td className="py-2 font-mono text-accent">{state.variable}</td>
<td className="py-2 font-mono">{state.roblox}</td>
<td className="py-2 font-mono">{state.web}</td>
<td className="py-2 font-mono">{state.mobile}</td>
<td className="py-2">
<span className={getStatusColor(state.status)}>
{getStatusIcon(state.status)} {state.status}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</Card>
</TabsContent>
<TabsContent value="roblox" className="flex-1 p-4 m-0">
<Card className="h-full p-8 flex items-center justify-center">
<div className="text-center">
<div className="text-8xl mb-4">🎮</div>
<h3 className="text-2xl font-bold mb-2">Roblox Preview</h3>
<p className="text-muted-foreground mb-4">Full-screen Roblox viewport</p>
<Button>Deploy to Roblox</Button>
</div>
</Card>
</TabsContent>
<TabsContent value="web" className="flex-1 p-4 m-0">
<Card className="h-full p-8 flex items-center justify-center">
<div className="text-center">
<div className="text-8xl mb-4">🌐</div>
<h3 className="text-2xl font-bold mb-2">Web Preview</h3>
<p className="text-muted-foreground mb-4">Browser-based game preview</p>
<Button>Deploy to Web</Button>
</div>
</Card>
</TabsContent>
<TabsContent value="mobile" className="flex-1 p-4 m-0 flex items-center justify-center">
<div className="w-[300px] h-[600px] bg-background rounded-3xl border-8 border-foreground/20 p-4 flex flex-col shadow-2xl">
<div className="w-1/2 h-8 bg-foreground/10 rounded-full mx-auto mb-4" />
<Card className="flex-1 flex items-center justify-center">
<div className="text-center">
<div className="text-6xl mb-4">📱</div>
<h3 className="text-xl font-bold mb-2">Mobile Preview</h3>
<p className="text-sm text-muted-foreground mb-4">iOS/Android view</p>
<Button size="sm">Deploy to Mobile</Button>
</div>
</Card>
<div className="h-8 w-1/2 bg-foreground/10 rounded-full mx-auto mt-4" />
</div>
</TabsContent>
</Tabs>
</div>
</DialogContent>
</Dialog>
);
}