'use client'; import React, { useMemo, useState } from 'react'; /** * Avatar G β€” Workspace (Home) * File: app/page.tsx * Requires: Tailwind CSS enabled (create-next-app with Tailwind) * Optional: add gradient background in globals.css (I’ll give after if needed) */ type ServiceKey = 'avatar' | 'voice' | 'image' | 'video' | 'music' | 'production'; type Service = { key: ServiceKey; title: string; subtitle: string; icon: string; // emoji placeholder (later swap to real icons) accent: 'cyan' | 'emerald' | 'violet' | 'orange' | 'blue' | 'pink'; }; type AssetType = 'avatar' | 'voice' | 'image' | 'video' | 'music' | 'project'; type HistoryItem = { id: string; createdAt: string; service: ServiceKey; title: string; promptSummary: string; status: 'ready' | 'processing' | 'error'; }; type LibraryItem = { id: string; type: AssetType; title: string; createdAt: string; sizeLabel?: string; }; type ChatMessage = { id: string; role: 'user' | 'assistant' | 'system'; text: string; createdAt: string; }; const SERVICES: Service[] = [ { key: 'avatar', title: 'Avatar Builder', subtitle: 'Identity β€’ Live Camera β€’ Style Engine', icon: 'πŸ‘€', accent: 'emerald' }, { key: 'voice', title: 'Voice Lab', subtitle: 'Accent β€’ Cloning β€’ Emotional Tone', icon: 'πŸŽ™οΈ', accent: 'cyan' }, { key: 'image', title: 'Image Architect', subtitle: '8K β€’ Brand Kit β€’ Lighting Control', icon: '🎨', accent: 'violet' }, { key: 'video', title: 'Video Cine-Lab', subtitle: 'Camera Path β€’ Motion β€’ VFX', icon: 'πŸ“½οΈ', accent: 'orange' }, { key: 'music', title: 'Music Studio', subtitle: 'BPM Sync β€’ Genre Morph β€’ Lyrics-to-Audio', icon: '🎡', accent: 'blue' }, { key: 'production', title: 'AI Production', subtitle: 'Timeline β€’ Lip-Sync β€’ One-Click Remix', icon: '🎬', accent: 'pink' } ]; function nowLabel() { const d = new Date(); return d.toLocaleString(undefined, { day: '2-digit', month: 'short', hour: '2-digit', minute: '2-digit' }); } function uid(prefix = 'id') { return `${prefix}_${Math.random().toString(16).slice(2)}_${Date.now()}`; } function accentClasses(accent: Service['accent']) { // No hard colors requested by user; using Tailwind primitives with subtle accents // Keep it premium & restrained. switch (accent) { case 'emerald': return 'from-emerald-400/20 to-emerald-200/5 ring-emerald-200/20'; case 'cyan': return 'from-cyan-400/20 to-cyan-200/5 ring-cyan-200/20'; case 'violet': return 'from-violet-400/20 to-violet-200/5 ring-violet-200/20'; case 'orange': return 'from-orange-400/20 to-orange-200/5 ring-orange-200/20'; case 'blue': return 'from-blue-400/20 to-blue-200/5 ring-blue-200/20'; case 'pink': return 'from-pink-400/20 to-pink-200/5 ring-pink-200/20'; default: return 'from-white/10 to-white/5 ring-white/10'; } } export default function Page() { // Global App State (V2 simple local state; later swap to Zustand/Redux) const [activeService, setActiveService] = useState(null); const [chatTab, setChatTab] = useState<'chat' | 'history' | 'library'>('chat'); const [status, setStatus] = useState<'idle' | 'processing' | 'error'>('idle'); const [credits, setCredits] = useState(1250); const [storageUsedGb, setStorageUsedGb] = useState(1.2); const storageTotalGb = 5; const [messages, setMessages] = useState(() => [ { id: uid('m'), role: 'system', text: 'Welcome to Avatar G Workspace. Select a service or ask the AI Helper to build a professional prompt.', createdAt: nowLabel() } ]); const [history, setHistory] = useState(() => [ { id: uid('h'), createdAt: nowLabel(), service: 'music', title: 'Music: Corporate ambient (Draft)', promptSummary: 'Genre: Corporate β€’ Mood: Calm β€’ BPM: Auto β€’ Instrument: Synth', status: 'ready' }, { id: uid('h'), createdAt: nowLabel(), service: 'avatar', title: 'Avatar: Business male (Draft)', promptSummary: 'Region: Tbilisi β€’ Style: Business β€’ Lighting: Soft Studio', status: 'ready' } ]); const [library, setLibrary] = useState(() => [ { id: uid('a'), type: 'image', title: 'Background: Modern Office', createdAt: nowLabel(), sizeLabel: '4.8MB' }, { id: uid('a'), type: 'voice', title: 'Voice: Tbilisi soft', createdAt: nowLabel(), sizeLabel: '2.1MB' }, { id: uid('a'), type: 'music', title: 'Track: Calm corporate loop', createdAt: nowLabel(), sizeLabel: '7.4MB' } ]); const filteredHistory = useMemo(() => history, [history]); const filteredLibrary = useMemo(() => library, [library]); function pushSystemLog(text: string) { setMessages((prev) => [ ...prev, { id: uid('m'), role: 'system', text, createdAt: nowLabel() } ]); } function sendMessage(text: string) { if (!text.trim()) return; setMessages((prev) => [ ...prev, { id: uid('m'), role: 'user', text: text.trim(), createdAt: nowLabel() } ]); // Simulated assistant response (replace with real API later) setStatus('processing'); setTimeout(() => { setMessages((prev) => [ ...prev, { id: uid('m'), role: 'assistant', text: "Got it. I can convert that into a professional prompt. Tell me: platform (Reels/TikTok/YouTube), tone (business/cinematic/fun), and language (KA/EN/RU).", createdAt: nowLabel() } ]); setStatus('idle'); }, 650); } function simulateGenerate(service: Service) { // This is UI-only: creates history + consumes credits + adds library item. setStatus('processing'); pushSystemLog(`[boot] ${service.title}: processing request...`); setCredits((c) => Math.max(0, c - 12)); setTimeout(() => { const newHistory: HistoryItem = { id: uid('h'), createdAt: nowLabel(), service: service.key, title: `${service.title}: New output`, promptSummary: 'Generated via Prompt Builder β€’ (demo)', status: 'ready' }; setHistory((prev) => [newHistory, ...prev]); const newAsset: LibraryItem = { id: uid('a'), type: service.key === 'avatar' ? 'avatar' : service.key === 'voice' ? 'voice' : service.key === 'image' ? 'image' : service.key === 'video' ? 'video' : service.key === 'music' ? 'music' : 'project', title: `${service.title} Output`, createdAt: nowLabel(), sizeLabel: 'β€”' }; setLibrary((prev) => [newAsset, ...prev]); setStorageUsedGb((gb) => Math.min(storageTotalGb, +(gb + 0.05).toFixed(2))); pushSystemLog(`[ok] ${service.title}: done. Saved to Library + History.`); setStatus('idle'); }, 900); } function attachFromHistory(item: HistoryItem) { pushSystemLog(`[attach] History β†’ Chat: "${item.title}"`); setChatTab('chat'); setMessages((prev) => [ ...prev, { id: uid('m'), role: 'system', text: `Attached from History: ${item.title} β€” ${item.promptSummary}`, createdAt: nowLabel() } ]); } function attachFromLibrary(item: LibraryItem) { pushSystemLog(`[attach] Library β†’ Chat: "${item.title}"`); setChatTab('chat'); setMessages((prev) => [ ...prev, { id: uid('m'), role: 'system', text: `Attached from Library: ${item.type.toUpperCase()} β€” ${item.title}`, createdAt: nowLabel() } ]); } return (
{/* Background */}
{/* Sidebar */} {/* Main Column */}
{/* Top Bar */}
Avatar G β€” AI Workspace
The Neural Station β€’ Glass UI β€’ Silver Borders β€’ Live Helper
{/* Workspace Grid */}
Workspace Grid
Pick a service. Each service has Prompt Builder + Library + Generate/View/Play/Download/Upload.
{SERVICES.map((s) => ( { setActiveService(s); pushSystemLog(`[ui] Open service: ${s.title}`); }} /> ))}
Smart Templates
sendMessage('Build a Business Promo prompt pack: avatar + voice + background + music.')} /> sendMessage('Create a Holiday Greeting template: warm tone, festive visuals, short 9:16.')} /> sendMessage('Generate a Breaking News style prompt: studio look, confident voice, captions.')} /> sendMessage('Auto-fill the best settings for a premium cinematic ad in Georgian.')} />
System Console
Live logs appear here and in Chat. This will later mirror backend job statuses.
{/* Persistent Chat Dock */}
{/* Service Overlay Modal */} {activeService && ( setActiveService(null)}>
{activeService.title}
{activeService.subtitle}
Prompt Builder
Demo UI