use anyhow::Result;
use std::io::Write;
use std::process::Command;
use std::time::Instant;
use crate::Storage;
pub fn handle_web(
storage: &Storage,
page: Option<&str>,
_port: u16,
no_browser: bool,
start: Instant,
) -> Result<()> {
let html_content = generate_dashboard_html(storage, page)?;
let temp_dir = std::env::temp_dir();
let html_file = temp_dir.join("prompthive-dashboard.html");
let mut file = std::fs::File::create(&html_file)?;
file.write_all(html_content.as_bytes())?;
file.flush()?;
println!("✓ Generated dashboard at: {}", html_file.display());
if !no_browser {
let url = format!("file://{}", html_file.display());
println!("🌐 Opening dashboard in browser...");
#[cfg(target_os = "macos")]
let browser_result = Command::new("open").arg(&url).status();
#[cfg(target_os = "linux")]
let browser_result = Command::new("xdg-open").arg(&url).status();
#[cfg(target_os = "windows")]
let browser_result = Command::new("start").arg(&url).status();
match browser_result {
Ok(_) => println!("✓ Dashboard opened successfully"),
Err(e) => {
println!("⚠️ Could not open browser automatically: {}", e);
println!("📄 Open this file manually: {}", html_file.display());
}
}
} else {
println!("📄 Dashboard file: {}", html_file.display());
}
println!(
"⏱️ Dashboard generated ({}ms)",
start.elapsed().as_millis()
);
Ok(())
}
fn generate_dashboard_html(storage: &Storage, page: Option<&str>) -> Result<String> {
let prompts = storage.list_prompts()?;
let prompt_count = prompts.len();
let page_title = match page {
Some("stats") => "Statistics",
Some("prompts") => "Prompts",
_ => "Overview",
};
let content = match page {
Some("stats") => format!(
"<h2>📈 Statistics</h2><p>Total prompts: {}</p>",
prompt_count
),
Some("prompts") => generate_prompts_html(&prompts)?,
_ => format!(
"<h2>📊 Overview</h2><p>PromptHive Dashboard</p><p>Total prompts: {}</p>",
prompt_count
),
};
let mut html = String::new();
html.push_str("<!DOCTYPE html>\n");
html.push_str("<html lang=\"en\">\n");
html.push_str("<head>\n");
html.push_str(" <meta charset=\"UTF-8\">\n");
html.push_str(
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n",
);
html.push_str(&format!(
" <title>PromptHive Dashboard - {}</title>\n",
page_title
));
html.push_str(" <style>\n");
html.push_str(
" body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }\n",
);
html.push_str(" .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; }\n");
html.push_str(" .nav { margin-bottom: 30px; }\n");
html.push_str(
" .nav a { margin-right: 20px; text-decoration: none; color: #0066cc; }\n",
);
html.push_str(" .nav a.active { font-weight: bold; }\n");
html.push_str(" h1 { color: #333; }\n");
html.push_str(" .prompt-item { background: #f9f9f9; padding: 15px; margin: 10px 0; border-radius: 5px; }\n");
html.push_str(" </style>\n");
html.push_str("</head>\n");
html.push_str("<body>\n");
html.push_str(" <div class=\"container\">\n");
html.push_str(" <h1>🚀 PromptHive Dashboard</h1>\n");
html.push_str(" <div class=\"nav\">\n");
let overview_class = if page.is_none() { "active" } else { "" };
let stats_class = if page == Some("stats") { "active" } else { "" };
let prompts_class = if page == Some("prompts") {
"active"
} else {
""
};
html.push_str(&format!(
" <a href=\"#\" class=\"{}\">📊 Overview</a>\n",
overview_class
));
html.push_str(&format!(
" <a href=\"#\" class=\"{}\">📈 Statistics</a>\n",
stats_class
));
html.push_str(&format!(
" <a href=\"#\" class=\"{}\">📝 Prompts</a>\n",
prompts_class
));
html.push_str(" </div>\n");
html.push_str(" <div>\n");
html.push_str(&content);
html.push_str(" </div>\n");
html.push_str(
" <footer style=\"margin-top: 40px; text-align: center; color: #666;\">\n",
);
html.push_str(" <p>Generated by PromptHive • <a href=\"https://prompthive.sh\">prompthive.sh</a></p>\n");
html.push_str(" </footer>\n");
html.push_str(" </div>\n");
html.push_str("</body>\n");
html.push_str("</html>");
Ok(html)
}
fn generate_prompts_html(prompts: &[String]) -> Result<String> {
let mut html = String::new();
html.push_str("<h2>📝 Your Prompts</h2>");
if prompts.is_empty() {
html.push_str("<p>No prompts found. Create your first prompt with: <code>ph new my-first-prompt</code></p>");
} else {
for prompt_name in prompts.iter().take(50) {
html.push_str("<div class=\"prompt-item\">📄 ");
html.push_str(prompt_name);
html.push_str("</div>");
}
}
Ok(html)
}