diff --git a/job_posting_generator/templates/job_posting_generator/detail.html b/job_posting_generator/templates/job_posting_generator/detail.html index bea1fe8..155cb0a 100644 --- a/job_posting_generator/templates/job_posting_generator/detail.html +++ b/job_posting_generator/templates/job_posting_generator/detail.html @@ -295,16 +295,127 @@ } - // Display job posting results with markdown formatting + // Display job posting results with professional formatting function displayResults(result) { - AgentUtils.displayResults({ - result: result, - resultsId: 'jobResults', - contentId: 'jobContent', - defaultMessage: 'Job posting generated successfully!', - successMessage: '✅ Job posting created and payment processed!', - errorMessage: '❌ Failed to generate job posting - no charge applied' - }); + const resultsContainer = document.getElementById('jobResults'); + const contentElement = document.getElementById('jobContent'); + + if (!resultsContainer || !contentElement) { + console.error('Job results elements not found'); + return; + } + + // Update wallet balance if provided + if (result.wallet_balance !== undefined) { + updateWalletBalance(result.wallet_balance); + } + + // Handle errors + if (result.error) { + AgentUtils.showToast(`❌ ${result.error}`, 'error'); + return; + } + + // Handle failed status + if (result.status === 'failed') { + AgentUtils.showToast('❌ Failed to generate job posting - no charge applied', 'error'); + return; + } + + // Extract job posting content with priority order + let content = ''; + + if (result.job_posting_content && typeof result.job_posting_content === 'string') { + content = result.job_posting_content; + } else if (result.content && typeof result.content === 'string') { + content = result.content; + } else if (result.formatted_report && typeof result.formatted_report === 'string') { + content = result.formatted_report; + } else if (result.output_text && typeof result.output_text === 'string') { + content = result.output_text; + } else { + content = 'Job posting generated successfully!'; + } + + // Format job posting content with professional styling + const formattedContent = formatJobPostingContent(content); + + // Update content + contentElement.innerHTML = formattedContent; + + // Show results + resultsContainer.style.display = 'block'; + resultsContainer.scrollIntoView({ behavior: 'smooth' }); + + // Show success message + const successMessage = result.success ? '✅ Job posting created and payment processed!' : '✅ Job posting generated!'; + AgentUtils.showToast(successMessage, 'success'); + } + + // Professional job posting formatter + function formatJobPostingContent(content) { + if (!content || typeof content !== 'string') { + return '

No job posting content available.

'; + } + + let html = content; + + // Enhanced header formatting for job titles and company names + html = html.replace(/^# (.*$)/gm, '

$1

'); + html = html.replace(/^## (.*$)/gm, '

$1

'); + html = html.replace(/^### (.*$)/gm, '

$1

'); + + // Professional bold text formatting + html = html.replace(/\*\*(.*?)\*\*/g, '$1'); + + // Professional bullet point formatting + const lines = html.split('\n'); + let inList = false; + let processedLines = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + + if (line.startsWith('- ') || line.startsWith('• ')) { + if (!inList) { + processedLines.push(''); + inList = false; + } + processedLines.push(line); + } + } + + if (inList) { + processedLines.push(''); + } + + html = processedLines.join('\n'); + + // Convert line breaks to professional paragraphs + const paragraphs = html.split(/\n\s*\n/); + html = paragraphs + .filter(p => p.trim() !== '') + .map(p => { + const trimmed = p.trim(); + // Don't wrap headers or lists in paragraphs + if (trimmed.startsWith('') || trimmed.includes('${trimmed}

`; + }) + .join(''); + + // Add professional spacing and structure + html = `
${html}
`; + + return html; } // Track if results have been displayed to prevent duplicates diff --git a/social_ads_generator/templates/social_ads_generator/detail.html b/social_ads_generator/templates/social_ads_generator/detail.html index b7182e0..2da3cf9 100644 --- a/social_ads_generator/templates/social_ads_generator/detail.html +++ b/social_ads_generator/templates/social_ads_generator/detail.html @@ -199,16 +199,127 @@ AgentUtils.showToast('Form reset! Ready for another ad campaign.', 'success'); } - // Display social ads results with markdown parsing + // Display social ads results with engaging ad copy formatting function displayResults(result) { - AgentUtils.displayResults({ - result: result, - resultsId: 'adResults', - contentId: 'adContent', - defaultMessage: 'Social ads generated successfully!', - successMessage: '✅ Social ads created and payment processed!', - errorMessage: '❌ Failed to generate ads - no charge applied' - }); + const resultsContainer = document.getElementById('adResults'); + const contentElement = document.getElementById('adContent'); + + if (!resultsContainer || !contentElement) { + console.error('Ad results elements not found'); + return; + } + + // Update wallet balance if provided + if (result.wallet_balance !== undefined) { + updateWalletBalance(result.wallet_balance); + } + + // Handle errors + if (result.error) { + AgentUtils.showToast(`❌ ${result.error}`, 'error'); + return; + } + + // Handle failed status + if (result.status === 'failed') { + AgentUtils.showToast('❌ Failed to generate ads - no charge applied', 'error'); + return; + } + + // Extract ad copy content with priority order + let content = ''; + + if (result.ad_copy_content && typeof result.ad_copy_content === 'string') { + content = result.ad_copy_content; + } else if (result.content && typeof result.content === 'string') { + content = result.content; + } else if (result.formatted_report && typeof result.formatted_report === 'string') { + content = result.formatted_report; + } else if (result.output_text && typeof result.output_text === 'string') { + content = result.output_text; + } else { + content = 'Social ads generated successfully!'; + } + + // Format ad copy content with engaging styling + const formattedContent = formatSocialAdContent(content); + + // Update content + contentElement.innerHTML = formattedContent; + + // Show results + resultsContainer.style.display = 'block'; + resultsContainer.scrollIntoView({ behavior: 'smooth' }); + + // Show success message + const successMessage = result.success ? '✅ Social ads created and payment processed!' : '✅ Social ads generated!'; + AgentUtils.showToast(successMessage, 'success'); + } + + // Engaging social ad copy formatter + function formatSocialAdContent(content) { + if (!content || typeof content !== 'string') { + return '

No ad content available.

'; + } + + let html = content; + + // Enhanced header formatting for ad titles and platform sections + html = html.replace(/^# (.*$)/gm, '

$1

'); + html = html.replace(/^## (.*$)/gm, '

$1

'); + html = html.replace(/^### (.*$)/gm, '

$1

'); + + // Eye-catching bold text for call-to-actions and key phrases + html = html.replace(/\*\*(.*?)\*\*/g, '$1'); + + // Engaging bullet point formatting for ad features + const lines = html.split('\n'); + let inList = false; + let processedLines = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + + if (line.startsWith('- ') || line.startsWith('• ')) { + if (!inList) { + processedLines.push(''); + inList = false; + } + processedLines.push(line); + } + } + + if (inList) { + processedLines.push(''); + } + + html = processedLines.join('\n'); + + // Convert line breaks to engaging paragraphs + const paragraphs = html.split(/\n\s*\n/); + html = paragraphs + .filter(p => p.trim() !== '') + .map(p => { + const trimmed = p.trim(); + // Don't wrap headers or lists in paragraphs + if (trimmed.startsWith('') || trimmed.includes('${trimmed}

`; + }) + .join(''); + + // Add creative wrapper with glassmorphism effect + html = `
${html}
`; + + return html; } // Track polling and results to prevent duplicates diff --git a/static/js/agent-utils.js b/static/js/agent-utils.js index f532c96..2f5bbb8 100644 --- a/static/js/agent-utils.js +++ b/static/js/agent-utils.js @@ -173,44 +173,7 @@ window.AgentUtils = { }, 2000); }, - /** - * Display results with markdown parsing - * Standardized across all agents - */ - displayResults(config) { - const resultsContainer = document.getElementById(config.resultsId); - const contentContainer = document.getElementById(config.contentId); - - if (config.result.success && config.result.status === 'completed') { - // Get content from various possible fields - const content = config.result.content || - config.result.job_posting_content || - config.result.ad_copy_content || - config.result.analysis_results || - config.result.insights_summary || - config.result.report_text || - config.result.weather_data || - config.result.formatted_report || - config.result.output_text || - config.defaultMessage || - 'Content generated successfully!'; - - // Parse markdown and display as HTML - const formattedContent = this.parseMarkdown(content); - contentContainer.innerHTML = formattedContent; - - resultsContainer.style.display = 'block'; - - // Update wallet balance if provided - if (config.result.wallet_balance !== undefined) { - this.updateWalletBalance(config.result.wallet_balance); - } - - this.showToast(config.successMessage || '✅ Content generated and payment processed!', 'success'); - } else { - this.showToast(config.errorMessage || '❌ Failed to generate content - no charge applied', 'error'); - } - }, + // NOTE: displayResults() function removed - each agent now has its own custom display logic /** * Generate text for copy/download functionality diff --git a/weather_reporter/templates/weather_reporter/detail.html b/weather_reporter/templates/weather_reporter/detail.html index 264f9e7..0c926a5 100644 --- a/weather_reporter/templates/weather_reporter/detail.html +++ b/weather_reporter/templates/weather_reporter/detail.html @@ -259,16 +259,127 @@ // Simple toast notification - // Display weather results with markdown parsing + // Display weather results with clean weather data formatting function displayResults(result) { - AgentUtils.displayResults({ - result: result, - resultsId: 'weatherResults', - contentId: 'weatherContent', - defaultMessage: 'Weather report generated successfully!', - successMessage: '✅ Weather report completed and payment processed!', - errorMessage: '❌ Failed to generate weather report - no charge applied' - }); + const resultsContainer = document.getElementById('weatherResults'); + const contentElement = document.getElementById('weatherContent'); + + if (!resultsContainer || !contentElement) { + console.error('Weather results elements not found'); + return; + } + + // Update wallet balance if provided + if (result.wallet_balance !== undefined) { + updateWalletBalance(result.wallet_balance); + } + + // Handle errors + if (result.error) { + AgentUtils.showToast(`❌ ${result.error}`, 'error'); + return; + } + + // Handle failed status + if (result.status === 'failed') { + AgentUtils.showToast('❌ Failed to generate weather report - no charge applied', 'error'); + return; + } + + // Extract weather content with priority order + let content = ''; + + if (result.weather_data && typeof result.weather_data === 'string') { + content = result.weather_data; + } else if (result.formatted_report && typeof result.formatted_report === 'string') { + content = result.formatted_report; + } else if (result.content && typeof result.content === 'string') { + content = result.content; + } else if (result.output_text && typeof result.output_text === 'string') { + content = result.output_text; + } else { + content = 'Weather report generated successfully!'; + } + + // Format weather content with clean data presentation + const formattedContent = formatWeatherContent(content); + + // Update content + contentElement.innerHTML = formattedContent; + + // Show results + resultsContainer.style.display = 'block'; + resultsContainer.scrollIntoView({ behavior: 'smooth' }); + + // Show success message + const successMessage = result.success ? '✅ Weather report completed and payment processed!' : '✅ Weather report generated!'; + AgentUtils.showToast(successMessage, 'success'); + } + + // Clean weather data formatter + function formatWeatherContent(content) { + if (!content || typeof content !== 'string') { + return '

No weather data available.

'; + } + + let html = content; + + // Enhanced header formatting for weather sections + html = html.replace(/^# (.*$)/gm, '

$1

'); + html = html.replace(/^## (.*$)/gm, '

$1

'); + html = html.replace(/^### (.*$)/gm, '

$1

'); + + // Temperature and weather metric highlighting + html = html.replace(/\*\*(.*?)\*\*/g, '$1'); + + // Weather condition formatting with clean presentation + const lines = html.split('\n'); + let inList = false; + let processedLines = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + + if (line.startsWith('- ') || line.startsWith('• ')) { + if (!inList) { + processedLines.push('
    '); + inList = true; + } + const listContent = line.substring(2).trim(); + processedLines.push(`
  • ${listContent}
  • `); + } else { + if (inList) { + processedLines.push('
'); + inList = false; + } + processedLines.push(line); + } + } + + if (inList) { + processedLines.push(''); + } + + html = processedLines.join('\n'); + + // Convert line breaks to clean paragraphs + const paragraphs = html.split(/\n\s*\n/); + html = paragraphs + .filter(p => p.trim() !== '') + .map(p => { + const trimmed = p.trim(); + // Don't wrap headers or lists in paragraphs + if (trimmed.startsWith('') || trimmed.includes('${trimmed}

`; + }) + .join(''); + + // Add clean wrapper for weather data + html = `
${html}
`; + + return html; } // Poll for results