Spaces:
Sleeping
Sleeping
feat: Initialize a full-stack application with a FastAPI backend and React frontend for AI-powered marketing research concept generation.
481234c
| import React, { useState } from 'react'; | |
| import axios from 'axios'; | |
| import { motion, AnimatePresence } from 'framer-motion'; | |
| import { Zap, Layout, Terminal, Github, Compass } from 'lucide-react'; | |
| import ResearchForm from './components/ResearchForm'; | |
| import ResearchResult from './components/ResearchResult'; | |
| function App() { | |
| const [results, setResults] = useState(null); | |
| const [isLoading, setIsLoading] = useState(false); | |
| const [error, setError] = useState(null); | |
| const handleSearch = async (formData) => { | |
| setIsLoading(true); | |
| setError(null); | |
| try { | |
| const response = await axios.post('/api/research', formData); | |
| setResults(response.data); | |
| } catch (err) { | |
| console.error(err); | |
| setError('Failed to generate insights. Please check if the backend is running.'); | |
| } finally { | |
| setIsLoading(false); | |
| } | |
| }; | |
| return ( | |
| <div className="min-h-screen"> | |
| {/* Background Decor */} | |
| <div className="fixed inset-0 overflow-hidden pointer-events-none" style={{ zIndex: 0 }}> | |
| <div className="absolute top-[-10%] left-[-10%] w-[50%] h-[50%] bg-yellow-500/5 blur-[120px] rounded-full"></div> | |
| <div className="absolute bottom-[-10%] right-[-10%] w-[50%] h-[50%] bg-white/5 blur-[120px] rounded-full"></div> | |
| </div> | |
| {/* Header */} | |
| <header className="premium-header relative z-10"> | |
| <div className="container flex items-center justify-between h-full"> | |
| <div className="logo-container"> | |
| <div className="logo-box"> | |
| <Zap className="text-black" size={20} fill="currentColor" /> | |
| </div> | |
| <h1 className="logo-text"> | |
| AMALFA <span>CREATIVE</span> | |
| </h1> | |
| </div> | |
| <nav className="flex items-center"> | |
| <a href="#" className="nav-link">Workspace</a> | |
| <a href="#" className="nav-link">Docs</a> | |
| </nav> | |
| </div> | |
| </header> | |
| {/* Main Content */} | |
| <main className="container relative z-10 py-12"> | |
| <div className="app-grid"> | |
| {/* Left Column - Form */} | |
| <aside> | |
| <ResearchForm onSearch={handleSearch} isLoading={isLoading} /> | |
| {error && ( | |
| <motion.div | |
| initial={{ opacity: 0, y: 10 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| style={{ | |
| marginTop: '1.5rem', | |
| padding: '1rem', | |
| backgroundColor: 'rgba(239, 68, 68, 0.1)', | |
| border: '1px solid rgba(239, 68, 68, 0.2)', | |
| borderRadius: '12px', | |
| color: '#f87171', | |
| fontSize: '0.875rem' | |
| }} | |
| > | |
| {error} | |
| </motion.div> | |
| )} | |
| </aside> | |
| {/* Right Column - Results */} | |
| <section> | |
| <div className="flex items-center justify-between mb-8"> | |
| <h2 className="section-title"> | |
| <Compass size={24} className="text-yellow-500" /> | |
| Strategic Roadmap | |
| </h2> | |
| {results && ( | |
| <button | |
| onClick={() => setResults(null)} | |
| style={{ | |
| background: 'none', | |
| border: 'none', | |
| color: 'var(--text-muted)', | |
| fontSize: '0.75rem', | |
| cursor: 'pointer', | |
| textTransform: 'uppercase', | |
| letterSpacing: '1px' | |
| }} | |
| > | |
| Clear Analysis | |
| </button> | |
| )} | |
| </div> | |
| <ResearchResult results={results} /> | |
| </section> | |
| </div> | |
| </main> | |
| </div> | |
| ); | |
| } | |
| export default App; | |