use crate::webui::routes::{self, WebState};
use crate::webui::sse::sse_handler;
use crate::webui::state::AppState;
use crate::webui::templates::Templates;
use axum::{
routing::{delete, get, patch, post},
Router,
};
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::TcpListener;
use tower_http::services::ServeDir;
pub fn build_router(web_state: WebState) -> Router {
Router::new()
.route("/", get(routes::index))
.route("/api/card/description", get(routes::get_description))
.route("/api/card/ticket", get(routes::get_ticket))
.route("/api/card/links", get(routes::get_links))
.route("/api/card/todos", get(routes::get_todos))
.route("/api/card/scraps", get(routes::get_scraps))
.route("/partials/todos", get(routes::get_todos))
.route("/partials/repos", get(routes::get_repos))
.route("/api/status", get(routes::api_status))
.route("/api/todo", post(routes::add_todo))
.route("/api/todo/:id", delete(routes::delete_todo))
.route("/api/todo/:id/next", patch(routes::move_todo_to_next))
.route("/api/todo/:id/:status", patch(routes::update_todo_status))
.route("/api/scrap", post(routes::add_scrap))
.route("/api/description", post(routes::update_description))
.route("/api/ticket", post(routes::update_ticket))
.route("/api/link", post(routes::add_link))
.route("/api/link/:id", delete(routes::delete_link))
.route("/api/sse", get(sse_handler))
.nest_service("/static", ServeDir::new("static"))
.with_state(web_state)
}
pub async fn start_server(port: u16, open_browser: bool) -> anyhow::Result<()> {
let app_state = AppState::new()?;
let templates = Arc::new(Templates::embedded());
let web_state = WebState {
app: app_state.clone(),
templates,
};
let poll_state = app_state.clone();
tokio::spawn(async move {
poll_state.start_change_detection().await;
});
let app = build_router(web_state);
let addr = SocketAddr::from(([127, 0, 0, 1], port));
println!("Starting track webui server...");
println!(" → http://localhost:{}", port);
println!();
println!("Press Ctrl+C to stop the server.");
if open_browser {
let url = format!("http://localhost:{}", port);
if let Err(e) = open::that(&url) {
eprintln!("Warning: Failed to open browser: {}", e);
}
}
let listener = TcpListener::bind(addr).await?;
axum::serve(listener, app).await?;
Ok(())
}