(* Server-side React UI components using server-reason-react *) open Dream open Lwt.Infix open Database (* HTML helpers *) let html ?(title="Website Monitor") ?(body="") ?(extra_head="") () = Printf.sprintf {| %s %s
%s
|} title extra_head body (* Dashboard page *) let serve_dashboard req = Websites.get_all () >>= fun websites -> let active_websites = List.filter (fun w -> w.active) websites in let healthy_count = List.fold_left (fun acc w -> match w.last_status with | None -> acc | Some status -> if status = w.expected_status then acc + 1 else acc) 0 active_websites in let total_active = List.length active_websites in let websites_cards = List.map (fun w -> let status_icon = match w.last_status with | None -> "" | Some status -> if status = w.expected_status then "" else "" in let last_checked = match w.last_checked with | None -> "Never" | Some t -> try let t' = Ptime.v (Unix.gettimeofday ()) in let diff = Ptime.diff t' t |> Ptime.Span.to_float_s in if diff < 60.0 then Printf.sprintf "%.0f seconds ago" diff else if diff < 3600.0 then Printf.sprintf "%.0f minutes ago" (diff /. 60.0) else Printf.sprintf "%.1f hours ago" (diff /. 3600.0) with _ -> "Unknown" in Printf.sprintf {|
%s

%s

%s

%s
Last checked: %s View Details
|} status_icon w.name w.url (if w.active then "bg-green-100 text-green-800" else "bg-gray-100 text-gray-800") (if w.active then "Active" else "Inactive") last_checked ) websites |> String.concat "\n" in let body = Printf.sprintf {|

Dashboard

Total Websites

%d

Active

%d

Healthy

%d

Unhealthy

%d

Website Status

%s
|} (List.length websites) total_active healthy_count (total_active - healthy_count) websites_cards in let html_content = html ~title:"Website Monitor - Dashboard" ~body () in Lwt.return (Dream.html html_content) (* Websites management page *) let serve_websites_page req = Websites.get_all () >>= fun websites -> let website_rows = List.map (fun w -> let status_badge = match w.last_status with | None -> "Unknown" | Some status -> if status = w.expected_status then "OK" else Printf.sprintf "%d" status in let active_badge = if w.active then "Active" else "Inactive" in Printf.sprintf {| %s %s %s %s %s %d |} w.name w.url status_badge active_badge (match w.last_checked with | None -> "Never" | Some t -> Ptime.to_rfc3339 t) w.check_interval w.id w.id w.id ) websites |> String.concat "\n" in let body = Printf.sprintf {|

Websites

%s
Name URL Status Active Last Checked Interval (s) Actions
|} website_rows in let html_content = html ~title:"Website Monitor - Websites" ~body () in Lwt.return (Dream.html html_content) (* Alerts management page *) let serve_alerts_page req = Alerts.get_all () >>= fun alerts -> let alert_rows = List.map (fun a -> let type_badge = match a.alert_type with | "email" -> "Email" | "webhook" -> "Webhook" | _ -> Printf.sprintf "%s" a.alert_type in let enabled_badge = if a.enabled then "Enabled" else "Disabled" in Printf.sprintf {| %Ld %s %s %s %s |} a.website_id type_badge enabled_badge a.config (Ptime.to_rfc3339 a.created_at) a.id a.id a.id ) alerts |> String.concat "\n" in let body = Printf.sprintf {|

Alerts

%s
Website ID Type Status Config Created Actions
|} alert_rows in let html_content = html ~title:"Website Monitor - Alerts" ~body () in Lwt.return (Dream.html html_content) (* Settings page *) let serve_settings_page req = let body = Printf.sprintf {|

Settings

Monitoring Settings

Email Configuration

System Information

Version
1.0.0
Environment
Production
Scheduler Status
Running
Database
Connected
|} in let html_content = html ~title:"Website Monitor - Settings" ~body () in Lwt.return (Dream.html html_content)