feat: enhance ideation routes with event handling and new suggestion feature

- Updated the ideation routes to include an EventEmitter for better event management.
- Added a new endpoint to handle adding suggestions to the board, ensuring consistent category mapping.
- Modified existing routes to emit events for idea creation, update, and deletion, improving frontend notifications.
- Refactored the convert and create idea handlers to utilize the new event system.
- Removed static guided prompts data in favor of dynamic fetching from the backend API.
This commit is contained in:
webdevcody
2026-01-04 00:38:01 -05:00
parent 5c95d6d58e
commit ac92725a6c
20 changed files with 442 additions and 538 deletions

View File

@@ -13,9 +13,10 @@ import {
Gauge,
Accessibility,
BarChart3,
Loader2,
} from 'lucide-react';
import { Card, CardContent } from '@/components/ui/card';
import { PROMPT_CATEGORIES } from '../data/guided-prompts';
import { useGuidedPrompts } from '@/hooks/use-guided-prompts';
import type { IdeaCategory } from '@automaker/types';
interface PromptCategoryGridProps {
@@ -36,6 +37,8 @@ const iconMap: Record<string, typeof Zap> = {
};
export function PromptCategoryGrid({ onSelect, onBack }: PromptCategoryGridProps) {
const { categories, isLoading, error } = useGuidedPrompts();
return (
<div className="flex-1 flex flex-col p-6 overflow-auto">
<div className="max-w-4xl w-full mx-auto space-y-4">
@@ -48,30 +51,43 @@ export function PromptCategoryGrid({ onSelect, onBack }: PromptCategoryGridProps
<span>Back</span>
</button>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{PROMPT_CATEGORIES.map((category) => {
const Icon = iconMap[category.icon] || Zap;
return (
<Card
key={category.id}
className="cursor-pointer transition-all hover:border-primary hover:shadow-md"
onClick={() => onSelect(category.id)}
>
<CardContent className="p-6">
<div className="flex flex-col items-center text-center gap-3">
<div className="p-4 rounded-full bg-primary/10">
<Icon className="w-8 h-8 text-primary" />
{isLoading && (
<div className="flex items-center justify-center py-12">
<Loader2 className="w-6 h-6 animate-spin text-muted-foreground" />
<span className="ml-2 text-muted-foreground">Loading categories...</span>
</div>
)}
{error && (
<div className="text-center py-12 text-destructive">
<p>Failed to load categories: {error}</p>
</div>
)}
{!isLoading && !error && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{categories.map((category) => {
const Icon = iconMap[category.icon] || Zap;
return (
<Card
key={category.id}
className="cursor-pointer transition-all hover:border-primary hover:shadow-md"
onClick={() => onSelect(category.id)}
>
<CardContent className="p-6">
<div className="flex flex-col items-center text-center gap-3">
<div className="p-4 rounded-full bg-primary/10">
<Icon className="w-8 h-8 text-primary" />
</div>
<div>
<h3 className="font-semibold text-lg">{category.name}</h3>
<p className="text-muted-foreground text-sm mt-1">{category.description}</p>
</div>
</div>
<div>
<h3 className="font-semibold text-lg">{category.name}</h3>
<p className="text-muted-foreground text-sm mt-1">{category.description}</p>
</div>
</div>
</CardContent>
</Card>
);
})}
</div>
</CardContent>
</Card>
);
})}
</div>
)}
</div>
</div>
);

View File

@@ -5,7 +5,7 @@
import { useState } from 'react';
import { ArrowLeft, Lightbulb, Loader2, CheckCircle2 } from 'lucide-react';
import { Card, CardContent } from '@/components/ui/card';
import { getPromptsByCategory } from '../data/guided-prompts';
import { useGuidedPrompts } from '@/hooks/use-guided-prompts';
import { useIdeationStore } from '@/store/ideation-store';
import { useAppStore } from '@/store/app-store';
import { getElectronAPI } from '@/lib/electron';
@@ -24,6 +24,11 @@ export function PromptList({ category, onBack }: PromptListProps) {
const [loadingPromptId, setLoadingPromptId] = useState<string | null>(null);
const [startedPrompts, setStartedPrompts] = useState<Set<string>>(new Set());
const navigate = useNavigate();
const {
getPromptsByCategory,
isLoading: isLoadingPrompts,
error: promptsError,
} = useGuidedPrompts();
const prompts = getPromptsByCategory(category);
@@ -101,60 +106,73 @@ export function PromptList({ category, onBack }: PromptListProps) {
</button>
<div className="space-y-3">
{prompts.map((prompt) => {
const isLoading = loadingPromptId === prompt.id;
const isGenerating = generatingPromptIds.has(prompt.id);
const isStarted = startedPrompts.has(prompt.id);
const isDisabled = loadingPromptId !== null || isGenerating;
{isLoadingPrompts && (
<div className="flex items-center justify-center py-8">
<Loader2 className="w-6 h-6 animate-spin text-muted-foreground" />
<span className="ml-2 text-muted-foreground">Loading prompts...</span>
</div>
)}
{promptsError && (
<div className="text-center py-8 text-destructive">
<p>Failed to load prompts: {promptsError}</p>
</div>
)}
{!isLoadingPrompts &&
!promptsError &&
prompts.map((prompt) => {
const isLoading = loadingPromptId === prompt.id;
const isGenerating = generatingPromptIds.has(prompt.id);
const isStarted = startedPrompts.has(prompt.id);
const isDisabled = loadingPromptId !== null || isGenerating;
return (
<Card
key={prompt.id}
className={`transition-all ${
isDisabled
? 'opacity-60 cursor-not-allowed'
: 'cursor-pointer hover:border-primary hover:shadow-md'
} ${isLoading || isGenerating ? 'border-blue-500 ring-1 ring-blue-500' : ''} ${
isStarted && !isGenerating ? 'border-green-500/50' : ''
}`}
onClick={() => !isDisabled && handleSelectPrompt(prompt)}
>
<CardContent className="p-5">
<div className="flex items-start gap-4">
<div
className={`p-2 rounded-lg mt-0.5 ${
isLoading || isGenerating
? 'bg-blue-500/10'
: isStarted
? 'bg-green-500/10'
: 'bg-primary/10'
}`}
>
{isLoading || isGenerating ? (
<Loader2 className="w-4 h-4 text-blue-500 animate-spin" />
) : isStarted ? (
<CheckCircle2 className="w-4 h-4 text-green-500" />
) : (
<Lightbulb className="w-4 h-4 text-primary" />
)}
return (
<Card
key={prompt.id}
className={`transition-all ${
isDisabled
? 'opacity-60 cursor-not-allowed'
: 'cursor-pointer hover:border-primary hover:shadow-md'
} ${isLoading || isGenerating ? 'border-blue-500 ring-1 ring-blue-500' : ''} ${
isStarted && !isGenerating ? 'border-green-500/50' : ''
}`}
onClick={() => !isDisabled && handleSelectPrompt(prompt)}
>
<CardContent className="p-5">
<div className="flex items-start gap-4">
<div
className={`p-2 rounded-lg mt-0.5 ${
isLoading || isGenerating
? 'bg-blue-500/10'
: isStarted
? 'bg-green-500/10'
: 'bg-primary/10'
}`}
>
{isLoading || isGenerating ? (
<Loader2 className="w-4 h-4 text-blue-500 animate-spin" />
) : isStarted ? (
<CheckCircle2 className="w-4 h-4 text-green-500" />
) : (
<Lightbulb className="w-4 h-4 text-primary" />
)}
</div>
<div className="flex-1 min-w-0">
<h3 className="font-semibold">{prompt.title}</h3>
<p className="text-muted-foreground text-sm mt-1">{prompt.description}</p>
{(isLoading || isGenerating) && (
<p className="text-blue-500 text-sm mt-2">Generating in dashboard...</p>
)}
{isStarted && !isGenerating && (
<p className="text-green-500 text-sm mt-2">
Already generated - check dashboard
</p>
)}
</div>
</div>
<div className="flex-1 min-w-0">
<h3 className="font-semibold">{prompt.title}</h3>
<p className="text-muted-foreground text-sm mt-1">{prompt.description}</p>
{(isLoading || isGenerating) && (
<p className="text-blue-500 text-sm mt-2">Generating in dashboard...</p>
)}
{isStarted && !isGenerating && (
<p className="text-green-500 text-sm mt-2">
Already generated - check dashboard
</p>
)}
</div>
</div>
</CardContent>
</Card>
);
})}
</CardContent>
</Card>
);
})}
</div>
</div>
</div>

View File

@@ -1,391 +0,0 @@
/**
* Guided prompts for ideation sessions
* Static data that provides pre-made prompts for different categories
*/
import type { IdeaCategory, IdeationPrompt, PromptCategory } from '@automaker/types';
export const PROMPT_CATEGORIES: PromptCategory[] = [
{
id: 'feature',
name: 'Features',
icon: 'Zap',
description: 'New capabilities and functionality',
},
{
id: 'ux-ui',
name: 'UX/UI',
icon: 'Palette',
description: 'Design and user experience improvements',
},
{
id: 'dx',
name: 'Developer Experience',
icon: 'Code',
description: 'Developer tooling and workflows',
},
{
id: 'growth',
name: 'Growth',
icon: 'TrendingUp',
description: 'User engagement and retention',
},
{
id: 'technical',
name: 'Technical',
icon: 'Cpu',
description: 'Architecture and infrastructure',
},
{
id: 'security',
name: 'Security',
icon: 'Shield',
description: 'Security and privacy improvements',
},
{
id: 'performance',
name: 'Performance',
icon: 'Gauge',
description: 'Speed and optimization',
},
{
id: 'accessibility',
name: 'Accessibility',
icon: 'Accessibility',
description: 'Inclusive design for all users',
},
{
id: 'analytics',
name: 'Analytics',
icon: 'BarChart3',
description: 'Data insights and tracking',
},
];
export const GUIDED_PROMPTS: IdeationPrompt[] = [
// Feature prompts
{
id: 'feature-missing',
category: 'feature',
title: 'Missing Features',
description: 'Discover features users might expect',
prompt:
"Analyze this codebase and identify features that users of similar applications typically expect but are missing here. Consider the app's domain, target users, and common patterns in similar products.",
},
{
id: 'feature-automation',
category: 'feature',
title: 'Automation Opportunities',
description: 'Find manual processes that could be automated',
prompt:
'Review this codebase and identify manual processes or repetitive tasks that could be automated. Look for patterns where users might be doing things repeatedly that software could handle.',
},
{
id: 'feature-integrations',
category: 'feature',
title: 'Integration Ideas',
description: 'Identify valuable third-party integrations',
prompt:
"Based on this codebase, what third-party services or APIs would provide value if integrated? Consider the app's domain and what complementary services users might need.",
},
{
id: 'feature-workflow',
category: 'feature',
title: 'Workflow Improvements',
description: 'Streamline user workflows',
prompt:
'Analyze the user workflows in this application. What steps could be combined, eliminated, or automated? Where are users likely spending too much time on repetitive tasks?',
},
// UX/UI prompts
{
id: 'ux-friction',
category: 'ux-ui',
title: 'Friction Points',
description: 'Identify where users might get stuck',
prompt:
'Analyze the user flows in this codebase and identify potential friction points. Where might users get confused, stuck, or frustrated? Look at form submissions, navigation, error states, and complex interactions.',
},
{
id: 'ux-empty-states',
category: 'ux-ui',
title: 'Empty States',
description: 'Improve empty state experiences',
prompt:
"Review the components in this codebase and identify empty states that could be improved. How can we guide users when there's no content? Consider onboarding, helpful prompts, and sample data.",
},
{
id: 'ux-accessibility',
category: 'ux-ui',
title: 'Accessibility Improvements',
description: 'Enhance accessibility and inclusivity',
prompt:
'Analyze this codebase for accessibility improvements. Consider keyboard navigation, screen reader support, color contrast, focus states, and ARIA labels. What specific improvements would make this more accessible?',
},
{
id: 'ux-mobile',
category: 'ux-ui',
title: 'Mobile Experience',
description: 'Optimize for mobile users',
prompt:
'Review this codebase from a mobile-first perspective. What improvements would enhance the mobile user experience? Consider touch targets, responsive layouts, and mobile-specific interactions.',
},
{
id: 'ux-feedback',
category: 'ux-ui',
title: 'User Feedback',
description: 'Improve feedback and status indicators',
prompt:
'Analyze how this application communicates with users. Where are loading states, success messages, or error handling missing or unclear? What feedback would help users understand what is happening?',
},
// DX prompts
{
id: 'dx-documentation',
category: 'dx',
title: 'Documentation Gaps',
description: 'Identify missing documentation',
prompt:
'Review this codebase and identify areas lacking documentation. What would help new developers understand the architecture, APIs, and conventions? Consider inline comments, READMEs, and API docs.',
},
{
id: 'dx-testing',
category: 'dx',
title: 'Testing Improvements',
description: 'Enhance test coverage and quality',
prompt:
'Analyze the testing patterns in this codebase. What areas need better test coverage? What types of tests are missing? Consider unit tests, integration tests, and end-to-end tests.',
},
{
id: 'dx-tooling',
category: 'dx',
title: 'Developer Tooling',
description: 'Improve development workflows',
prompt:
'Review the development setup and tooling in this codebase. What improvements would speed up development? Consider build times, hot reload, debugging tools, and developer scripts.',
},
{
id: 'dx-error-handling',
category: 'dx',
title: 'Error Handling',
description: 'Improve error messages and debugging',
prompt:
'Analyze error handling in this codebase. Where are error messages unclear or missing? What would help developers debug issues faster? Consider logging, error boundaries, and stack traces.',
},
// Growth prompts
{
id: 'growth-onboarding',
category: 'growth',
title: 'Onboarding Flow',
description: 'Improve new user experience',
prompt:
"Analyze this application's onboarding experience. How can we help new users understand the value and get started quickly? Consider tutorials, progressive disclosure, and quick wins.",
},
{
id: 'growth-engagement',
category: 'growth',
title: 'User Engagement',
description: 'Increase user retention and activity',
prompt:
'Review this application and suggest features that would increase user engagement and retention. What would bring users back daily? Consider notifications, streaks, social features, and personalization.',
},
{
id: 'growth-sharing',
category: 'growth',
title: 'Shareability',
description: 'Make the app more shareable',
prompt:
'How can this application be made more shareable? What features would encourage users to invite others or share their work? Consider collaboration, public profiles, and export features.',
},
{
id: 'growth-monetization',
category: 'growth',
title: 'Monetization Ideas',
description: 'Identify potential revenue streams',
prompt:
'Based on this codebase, what features or tiers could support monetization? Consider premium features, usage limits, team features, and integrations that users would pay for.',
},
// Technical prompts
{
id: 'tech-performance',
category: 'technical',
title: 'Performance Optimization',
description: 'Identify performance bottlenecks',
prompt:
'Analyze this codebase for performance optimization opportunities. Where are the likely bottlenecks? Consider database queries, API calls, bundle size, rendering, and caching strategies.',
},
{
id: 'tech-architecture',
category: 'technical',
title: 'Architecture Review',
description: 'Evaluate and improve architecture',
prompt:
'Review the architecture of this codebase. What improvements would make it more maintainable, scalable, or testable? Consider separation of concerns, dependency management, and patterns.',
},
{
id: 'tech-debt',
category: 'technical',
title: 'Technical Debt',
description: 'Identify areas needing refactoring',
prompt:
'Identify technical debt in this codebase. What areas are becoming hard to maintain or understand? What refactoring would have the highest impact? Consider duplicated code, complexity, and outdated patterns.',
},
{
id: 'tech-security',
category: 'technical',
title: 'Security Review',
description: 'Identify security improvements',
prompt:
'Review this codebase for security improvements. What best practices are missing? Consider authentication, authorization, input validation, and data protection. Note: This is for improvement suggestions, not a security audit.',
},
// Security prompts
{
id: 'security-auth',
category: 'security',
title: 'Authentication Security',
description: 'Review authentication mechanisms',
prompt:
'Analyze the authentication system in this codebase. What security improvements would strengthen user authentication? Consider password policies, session management, MFA, and token handling.',
},
{
id: 'security-data',
category: 'security',
title: 'Data Protection',
description: 'Protect sensitive user data',
prompt:
'Review how this application handles sensitive data. What improvements would better protect user privacy? Consider encryption, data minimization, secure storage, and data retention policies.',
},
{
id: 'security-input',
category: 'security',
title: 'Input Validation',
description: 'Prevent injection attacks',
prompt:
'Analyze input handling in this codebase. Where could input validation be strengthened? Consider SQL injection, XSS, command injection, and file upload vulnerabilities.',
},
{
id: 'security-api',
category: 'security',
title: 'API Security',
description: 'Secure API endpoints',
prompt:
'Review the API security in this codebase. What improvements would make the API more secure? Consider rate limiting, authorization, CORS, and request validation.',
},
// Performance prompts
{
id: 'perf-frontend',
category: 'performance',
title: 'Frontend Performance',
description: 'Optimize UI rendering and loading',
prompt:
'Analyze the frontend performance of this application. What optimizations would improve load times and responsiveness? Consider bundle splitting, lazy loading, memoization, and render optimization.',
},
{
id: 'perf-backend',
category: 'performance',
title: 'Backend Performance',
description: 'Optimize server-side operations',
prompt:
'Review backend performance in this codebase. What optimizations would improve response times? Consider database queries, caching strategies, async operations, and resource pooling.',
},
{
id: 'perf-database',
category: 'performance',
title: 'Database Optimization',
description: 'Improve query performance',
prompt:
'Analyze database interactions in this codebase. What optimizations would improve data access performance? Consider indexing, query optimization, denormalization, and connection pooling.',
},
{
id: 'perf-caching',
category: 'performance',
title: 'Caching Strategies',
description: 'Implement effective caching',
prompt:
'Review caching opportunities in this application. Where would caching provide the most benefit? Consider API responses, computed values, static assets, and session data.',
},
// Accessibility prompts
{
id: 'a11y-keyboard',
category: 'accessibility',
title: 'Keyboard Navigation',
description: 'Enable full keyboard access',
prompt:
'Analyze keyboard accessibility in this codebase. What improvements would enable users to navigate entirely with keyboard? Consider focus management, tab order, and keyboard shortcuts.',
},
{
id: 'a11y-screen-reader',
category: 'accessibility',
title: 'Screen Reader Support',
description: 'Improve screen reader experience',
prompt:
'Review screen reader compatibility in this application. What improvements would help users with visual impairments? Consider ARIA labels, semantic HTML, live regions, and alt text.',
},
{
id: 'a11y-visual',
category: 'accessibility',
title: 'Visual Accessibility',
description: 'Improve visual design for all users',
prompt:
'Analyze visual accessibility in this codebase. What improvements would help users with visual impairments? Consider color contrast, text sizing, focus indicators, and reduced motion.',
},
{
id: 'a11y-forms',
category: 'accessibility',
title: 'Accessible Forms',
description: 'Make forms usable for everyone',
prompt:
'Review form accessibility in this application. What improvements would make forms more accessible? Consider labels, error messages, required field indicators, and input assistance.',
},
// Analytics prompts
{
id: 'analytics-tracking',
category: 'analytics',
title: 'User Tracking',
description: 'Track key user behaviors',
prompt:
'Analyze this application for analytics opportunities. What user behaviors should be tracked to understand engagement? Consider page views, feature usage, conversion funnels, and session duration.',
},
{
id: 'analytics-metrics',
category: 'analytics',
title: 'Key Metrics',
description: 'Define success metrics',
prompt:
'Based on this codebase, what key metrics should be tracked? Consider user acquisition, retention, engagement, and feature adoption. What dashboards would be most valuable?',
},
{
id: 'analytics-errors',
category: 'analytics',
title: 'Error Monitoring',
description: 'Track and analyze errors',
prompt:
'Review error handling in this codebase for monitoring opportunities. What error tracking would help identify and fix issues faster? Consider error aggregation, alerting, and stack traces.',
},
{
id: 'analytics-performance',
category: 'analytics',
title: 'Performance Monitoring',
description: 'Track application performance',
prompt:
'Analyze this application for performance monitoring opportunities. What metrics would help identify bottlenecks? Consider load times, API response times, and resource usage.',
},
];
export function getPromptsByCategory(category: IdeaCategory): IdeationPrompt[] {
return GUIDED_PROMPTS.filter((p) => p.category === category);
}
export function getPromptById(id: string): IdeationPrompt | undefined {
return GUIDED_PROMPTS.find((p) => p.id === id);
}
export function getCategoryById(id: IdeaCategory): PromptCategory | undefined {
return PROMPT_CATEGORIES.find((c) => c.id === id);
}

View File

@@ -9,27 +9,12 @@ import { useAppStore } from '@/store/app-store';
import { PromptCategoryGrid } from './components/prompt-category-grid';
import { PromptList } from './components/prompt-list';
import { IdeationDashboard } from './components/ideation-dashboard';
import { getCategoryById } from './data/guided-prompts';
import { useGuidedPrompts } from '@/hooks/use-guided-prompts';
import { Button } from '@/components/ui/button';
import { ArrowLeft, ChevronRight, Lightbulb } from 'lucide-react';
import type { IdeaCategory } from '@automaker/types';
import type { IdeationMode } from '@/store/ideation-store';
// Get subtitle text based on current mode
function getSubtitle(currentMode: IdeationMode, selectedCategory: IdeaCategory | null): string {
if (currentMode === 'dashboard') {
return 'Review and accept generated ideas';
}
if (currentMode === 'prompts') {
if (selectedCategory) {
const categoryInfo = getCategoryById(selectedCategory);
return `Select a prompt from ${categoryInfo?.name || 'category'}`;
}
return 'Select a category to generate ideas';
}
return '';
}
// Breadcrumb component - compact inline breadcrumbs
function IdeationBreadcrumbs({
currentMode,
@@ -40,6 +25,7 @@ function IdeationBreadcrumbs({
selectedCategory: IdeaCategory | null;
onNavigate: (mode: IdeationMode, category?: IdeaCategory | null) => void;
}) {
const { getCategoryById } = useGuidedPrompts();
const categoryInfo = selectedCategory ? getCategoryById(selectedCategory) : null;
// On dashboard, no breadcrumbs needed (it's the root)
@@ -88,9 +74,26 @@ function IdeationHeader({
onGenerateIdeas: () => void;
onBack: () => void;
}) {
const subtitle = getSubtitle(currentMode, selectedCategory);
const { getCategoryById } = useGuidedPrompts();
const showBackButton = currentMode === 'prompts';
// Get subtitle text based on current mode
const getSubtitle = (): string => {
if (currentMode === 'dashboard') {
return 'Review and accept generated ideas';
}
if (currentMode === 'prompts') {
if (selectedCategory) {
const categoryInfo = getCategoryById(selectedCategory);
return `Select a prompt from ${categoryInfo?.name || 'category'}`;
}
return 'Select a category to generate ideas';
}
return '';
};
const subtitle = getSubtitle();
return (
<div className="flex items-center justify-between p-4 border-b border-border bg-glass backdrop-blur-md">
<div className="flex items-center gap-3">