From 1bd23f74456d6bd983fd17629bd1e5cfca3c5778 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Fri, 16 Jan 2026 04:01:14 +0000 Subject: [PATCH] Edited Spark --- src/App.tsx | 10 +- src/components/FeatureIdeaCloud.tsx | 644 ++++++++++++++++++++++++++++ src/components/NavigationMenu.tsx | 1 + src/types/project.ts | 1 + 4 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 src/components/FeatureIdeaCloud.tsx diff --git a/src/App.tsx b/src/App.tsx index 9a85749..ac81a06 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,7 +6,7 @@ import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Card } from '@/components/ui/card' import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable' -import { Code, Database, Tree, PaintBrush, Download, Sparkle, Flask, BookOpen, Play, Wrench, Gear, Cube, FileText, ChartBar, Keyboard, FlowArrow, Faders, DeviceMobile, Image, MagnifyingGlass } from '@phosphor-icons/react' +import { Code, Database, Tree, PaintBrush, Download, Sparkle, Flask, BookOpen, Play, Wrench, Gear, Cube, FileText, ChartBar, Keyboard, FlowArrow, Faders, DeviceMobile, Image, MagnifyingGlass, CloudArrowUp } from '@phosphor-icons/react' import { ProjectFile, PrismaModel, ComponentNode, ComponentTree, ThemeConfig, PlaywrightTest, StorybookStory, UnitTest, FlaskConfig, NextJsConfig, NpmSettings, Workflow, Lambda, FeatureToggles, Project } from '@/types/project' import { CodeEditor } from '@/components/CodeEditor' import { ModelDesigner } from '@/components/ModelDesigner' @@ -33,6 +33,7 @@ import { PWAUpdatePrompt } from '@/components/PWAUpdatePrompt' import { PWAStatusBar } from '@/components/PWAStatusBar' import { PWASettings } from '@/components/PWASettings' import { FaviconDesigner } from '@/components/FaviconDesigner' +import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud' import { GlobalSearch } from '@/components/GlobalSearch' import { NavigationMenu } from '@/components/NavigationMenu' import { PageHeader } from '@/components/PageHeader' @@ -104,6 +105,7 @@ const DEFAULT_FEATURE_TOGGLES: FeatureToggles = { documentation: true, sassStyles: true, faviconDesigner: true, + ideaCloud: true, } const DEFAULT_THEME: ThemeConfig = { @@ -784,6 +786,12 @@ Navigate to the backend directory and follow the setup instructions. )} + + {safeFeatureToggles.ideaCloud && ( + + + + )} diff --git a/src/components/FeatureIdeaCloud.tsx b/src/components/FeatureIdeaCloud.tsx new file mode 100644 index 0000000..d45b256 --- /dev/null +++ b/src/components/FeatureIdeaCloud.tsx @@ -0,0 +1,644 @@ +import { useState, useEffect, useRef } from 'react' +import { useKV } from '@github/spark/hooks' +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Card } from '@/components/ui/card' +import { Badge } from '@/components/ui/badge' +import { Textarea } from '@/components/ui/textarea' +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog' +import { ScrollArea } from '@/components/ui/scroll-area' +import { Plus, Trash, Cloud, Sparkle, ArrowsClockwise, Eye } from '@phosphor-icons/react' +import { motion, AnimatePresence } from 'framer-motion' +import { toast } from 'sonner' + +interface FeatureIdea { + id: string + title: string + description: string + category: string + priority: 'low' | 'medium' | 'high' + status: 'idea' | 'planned' | 'in-progress' | 'completed' + createdAt: number + x: number + y: number +} + +const SEED_IDEAS: FeatureIdea[] = [ + { + id: 'idea-1', + title: 'AI Code Assistant', + description: 'Integrate an AI assistant that can suggest code improvements and answer questions', + category: 'AI/ML', + priority: 'high', + status: 'completed', + createdAt: Date.now() - 10000000, + x: 10, + y: 15, + }, + { + id: 'idea-2', + title: 'Real-time Collaboration', + description: 'Allow multiple developers to work on the same project simultaneously', + category: 'Collaboration', + priority: 'high', + status: 'idea', + createdAt: Date.now() - 9000000, + x: 60, + y: 25, + }, + { + id: 'idea-3', + title: 'Component Marketplace', + description: 'A marketplace where users can share and download pre-built components', + category: 'Community', + priority: 'medium', + status: 'idea', + createdAt: Date.now() - 8000000, + x: 25, + y: 55, + }, + { + id: 'idea-4', + title: 'Visual Git Integration', + description: 'Git operations through a visual interface with branch visualization', + category: 'DevOps', + priority: 'high', + status: 'planned', + createdAt: Date.now() - 7000000, + x: 70, + y: 60, + }, + { + id: 'idea-5', + title: 'API Mock Server', + description: 'Built-in mock server for testing API integrations', + category: 'Testing', + priority: 'medium', + status: 'idea', + createdAt: Date.now() - 6000000, + x: 15, + y: 80, + }, + { + id: 'idea-6', + title: 'Performance Profiler', + description: 'Analyze and optimize application performance with visual metrics', + category: 'Performance', + priority: 'medium', + status: 'idea', + createdAt: Date.now() - 5000000, + x: 80, + y: 35, + }, + { + id: 'idea-7', + title: 'Theme Presets', + description: 'Pre-designed theme templates for quick project setup', + category: 'Design', + priority: 'low', + status: 'completed', + createdAt: Date.now() - 4000000, + x: 45, + y: 10, + }, + { + id: 'idea-8', + title: 'Database Schema Migrations', + description: 'Visual tool for creating and managing database migrations', + category: 'Database', + priority: 'high', + status: 'in-progress', + createdAt: Date.now() - 3000000, + x: 30, + y: 40, + }, + { + id: 'idea-9', + title: 'Mobile App Preview', + description: 'Live preview on actual mobile devices or simulators', + category: 'Mobile', + priority: 'medium', + status: 'planned', + createdAt: Date.now() - 2000000, + x: 55, + y: 75, + }, + { + id: 'idea-10', + title: 'Accessibility Checker', + description: 'Automated accessibility testing and suggestions', + category: 'Accessibility', + priority: 'high', + status: 'idea', + createdAt: Date.now() - 1000000, + x: 85, + y: 50, + }, + { + id: 'idea-11', + title: 'Code Templates', + description: 'Reusable code snippets and patterns library', + category: 'Productivity', + priority: 'medium', + status: 'completed', + createdAt: Date.now() - 900000, + x: 40, + y: 85, + }, + { + id: 'idea-12', + title: 'Webhook Testing', + description: 'Test and debug webhooks locally with request inspection', + category: 'DevOps', + priority: 'low', + status: 'idea', + createdAt: Date.now() - 800000, + x: 65, + y: 45, + }, +] + +const CATEGORIES = ['AI/ML', 'Collaboration', 'Community', 'DevOps', 'Testing', 'Performance', 'Design', 'Database', 'Mobile', 'Accessibility', 'Productivity', 'Security', 'Analytics', 'Other'] +const PRIORITIES = ['low', 'medium', 'high'] as const +const STATUSES = ['idea', 'planned', 'in-progress', 'completed'] as const + +const STATUS_COLORS = { + idea: 'bg-muted text-muted-foreground', + planned: 'bg-accent text-accent-foreground', + 'in-progress': 'bg-primary text-primary-foreground', + completed: 'bg-green-600 text-white', +} + +const PRIORITY_COLORS = { + low: 'border-blue-400 bg-blue-50 dark:bg-blue-950', + medium: 'border-amber-400 bg-amber-50 dark:bg-amber-950', + high: 'border-red-400 bg-red-50 dark:bg-red-950', +} + +export function FeatureIdeaCloud() { + const [ideas, setIdeas] = useKV('feature-ideas', SEED_IDEAS) + const [selectedIdea, setSelectedIdea] = useState(null) + const [editDialogOpen, setEditDialogOpen] = useState(false) + const [viewDialogOpen, setViewDialogOpen] = useState(false) + const [filterCategory, setFilterCategory] = useState('all') + const [filterStatus, setFilterStatus] = useState('all') + const [filterPriority, setFilterPriority] = useState('all') + const containerRef = useRef(null) + const [containerSize, setContainerSize] = useState({ width: 800, height: 600 }) + + const safeIdeas = ideas || SEED_IDEAS + + useEffect(() => { + if (!ideas || ideas.length === 0) { + setIdeas(SEED_IDEAS) + } + }, [ideas, setIdeas]) + + useEffect(() => { + const updateSize = () => { + if (containerRef.current) { + setContainerSize({ + width: containerRef.current.offsetWidth, + height: containerRef.current.offsetHeight, + }) + } + } + + updateSize() + window.addEventListener('resize', updateSize) + return () => window.removeEventListener('resize', updateSize) + }, []) + + const handleAddIdea = () => { + const newIdea: FeatureIdea = { + id: `idea-${Date.now()}`, + title: '', + description: '', + category: 'Other', + priority: 'medium', + status: 'idea', + createdAt: Date.now(), + x: Math.random() * 80, + y: Math.random() * 80, + } + setSelectedIdea(newIdea) + setEditDialogOpen(true) + } + + const handleEditIdea = (idea: FeatureIdea) => { + setSelectedIdea(idea) + setEditDialogOpen(true) + } + + const handleViewIdea = (idea: FeatureIdea) => { + setSelectedIdea(idea) + setViewDialogOpen(true) + } + + const handleSaveIdea = () => { + if (!selectedIdea || !selectedIdea.title.trim()) { + toast.error('Please enter a title') + return + } + + setIdeas((currentIdeas) => { + const existing = (currentIdeas || []).find(i => i.id === selectedIdea.id) + if (existing) { + return (currentIdeas || []).map(i => i.id === selectedIdea.id ? selectedIdea : i) + } else { + return [...(currentIdeas || []), selectedIdea] + } + }) + + setEditDialogOpen(false) + setSelectedIdea(null) + toast.success('Idea saved!') + } + + const handleDeleteIdea = (id: string) => { + setIdeas((currentIdeas) => (currentIdeas || []).filter(i => i.id !== id)) + setEditDialogOpen(false) + setViewDialogOpen(false) + setSelectedIdea(null) + toast.success('Idea deleted') + } + + const handleGenerateIdeas = async () => { + toast.info('Generating ideas with AI...') + + try { + const promptText = `Generate 3 innovative feature ideas for a low-code application builder. Each idea should be practical and valuable. Return as JSON with this structure: +{ + "ideas": [ + { + "title": "Feature Name", + "description": "Brief description", + "category": "${CATEGORIES.join('|')}", + "priority": "low|medium|high" + } + ] +}` + + const response = await window.spark.llm(promptText, 'gpt-4o-mini', true) + const result = JSON.parse(response) + + if (result.ideas && Array.isArray(result.ideas)) { + const newIdeas: FeatureIdea[] = result.ideas.map((idea: any, index: number) => ({ + id: `idea-ai-${Date.now()}-${index}`, + title: idea.title, + description: idea.description, + category: idea.category || 'Other', + priority: idea.priority || 'medium', + status: 'idea' as const, + createdAt: Date.now(), + x: 20 + (index * 20), + y: 20 + (index * 15), + })) + + setIdeas((currentIdeas) => [...(currentIdeas || []), ...newIdeas]) + toast.success(`Generated ${newIdeas.length} new ideas!`) + } + } catch (error) { + console.error('Failed to generate ideas:', error) + toast.error('Failed to generate ideas') + } + } + + const handleRandomizePositions = () => { + setIdeas((currentIdeas) => + (currentIdeas || []).map(idea => ({ + ...idea, + x: Math.random() * 80, + y: Math.random() * 80, + })) + ) + toast.success('Positions randomized!') + } + + const filteredIdeas = safeIdeas.filter(idea => { + if (filterCategory !== 'all' && idea.category !== filterCategory) return false + if (filterStatus !== 'all' && idea.status !== filterStatus) return false + if (filterPriority !== 'all' && idea.priority !== filterPriority) return false + return true + }) + + const categoryStats = safeIdeas.reduce((acc, idea) => { + acc[idea.category] = (acc[idea.category] || 0) + 1 + return acc + }, {} as Record) + + const statusStats = safeIdeas.reduce((acc, idea) => { + acc[idea.status] = (acc[idea.status] || 0) + 1 + return acc + }, {} as Record) + + return ( +
+
+
+
+

+ + Feature Idea Cloud +

+

+ Brainstorm and visualize your app features +

+
+
+ + + +
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+
+ +
+ + {filteredIdeas.map((idea) => ( + handleViewIdea(idea)} + > + +
+
+

{idea.title}

+
+

+ {idea.description} +

+
+ + {idea.category} + + + {idea.status} + +
+
+
+
+ ))} +
+ + {filteredIdeas.length === 0 && ( +
+
+ +

No ideas match your filters

+ +
+
+ )} +
+ + + + + + {selectedIdea?.title ? 'Edit Idea' : 'New Idea'} + + + Create or modify a feature idea for your app + + + + {selectedIdea && ( +
+
+ + setSelectedIdea({ ...selectedIdea, title: e.target.value })} + placeholder="Feature name..." + /> +
+ +
+ +