use crate::db::{ColumnInfo, TablePreview};
use maud::{Markup, html};
#[derive(Clone, Debug)]
pub struct DbTableSummary {
pub name: String,
pub row_count: i64,
pub columns: Vec<ColumnInfo>,
pub preview: TablePreview,
}
pub fn debug_view(
duck_path: &str,
sqlite_path: &str,
duck_tables: &[DbTableSummary],
sqlite_tables: &[DbTableSummary],
sync_message: Option<&str>,
) -> Markup {
html! {
div class="debug-wrapper" {
div class="flex flex-wrap justify-between items-center gap-4 mb-6 pb-4 border-b border-stone-300" {
div {
p class="text-xs font-bold uppercase tracking-widest text-[#5b7c60]" {
"System Diagnostics"
}
h2 class="text-2xl font-bold text-stone-800" {
"Database & Architecture Explorer"
}
p class="text-xs text-stone-500 mt-0.5" {
"Real-time inspection of DuckDB (Pokedex cache) and SQLite (Battles engine)."
}
}
div class="flex items-center gap-3" {
div id="sync-status" {
@if let Some(msg) = sync_message {
span class="text-xs font-semibold px-2 py-1 bg-green-100 text-green-800 rounded" {
(msg)
}
}
}
button
type="button"
class="cottage-btn cottage-btn-secondary text-xs"
hx-post="/debug/sync"
hx-target="#sync-status" {
"๐ Resync PokeAPI Cache"
}
form hx-post="/logout" hx-target="#main-content" class="inline m-0" {
button type="submit" class="cottage-btn cottage-btn-danger text-xs" {
"๐ Lock Debug"
}
}
}
}
// DuckDB Section
div class="db-panel-card" {
div class="db-panel-header" {
div {
h3 class="text-lg font-bold text-stone-800 flex items-center gap-2" {
span { "๐ฆ" }
"DuckDB Database Engine"
}
p class="text-xs text-stone-500 font-mono mt-0.5" {
"File path: " (duck_path) " โข Tables: " (duck_tables.len())
}
}
span class="text-xs bg-[#e6ede7] text-[#435e47] px-2.5 py-1 rounded-full font-bold border border-[#bad3bc]" {
"In-Process Analytical Store"
}
}
@if duck_tables.is_empty() {
p class="text-sm text-stone-500 italic p-4" { "No tables found in DuckDB." }
} @else {
@for t in duck_tables {
(table_summary_section("duckdb", t))
}
}
}
// SQLite Section
div class="db-panel-card" {
div class="db-panel-header" {
div {
h3 class="text-lg font-bold text-stone-800 flex items-center gap-2" {
span { "๐๏ธ" }
"SQLite Database Engine"
}
p class="text-xs text-stone-500 font-mono mt-0.5" {
"File path: " (sqlite_path) " โข Tables: " (sqlite_tables.len())
}
}
span class="text-xs bg-[#e6eff5] text-[#28557d] px-2.5 py-1 rounded-full font-bold border border-[#bad5ec]" {
"Transactional Battle Store"
}
}
@if sqlite_tables.is_empty() {
p class="text-sm text-stone-500 italic p-4" { "No tables found in SQLite." }
} @else {
@for t in sqlite_tables {
(table_summary_section("sqlite", t))
}
}
}
}
}
}
fn table_summary_section(_db_type: &str, t: &DbTableSummary) -> Markup {
html! {
div class="mb-6 p-4 bg-[#fbf8f2] border border-[#e3d5c1] rounded-xl" {
div class="flex flex-wrap justify-between items-center gap-2 mb-3" {
div class="flex items-center gap-2" {
span class="font-mono text-sm font-bold text-[#5a4432]" { (t.name) }
span class="text-xs text-stone-500 font-mono" {
"(" (t.row_count) " total rows)"
}
}
div class="text-xs text-stone-500" {
(t.columns.len()) " columns"
}
}
// Schema details
details class="mb-3" {
summary class="text-xs text-[#5b7c60] font-semibold cursor-pointer select-none" {
"View Table Schema Columns"
}
div class="mt-2 overflow-x-auto" {
table class="w-full text-xs font-mono border-collapse" {
thead {
tr class="bg-stone-200 text-stone-700" {
th class="p-1.5 text-left border border-stone-300" { "Column" }
th class="p-1.5 text-left border border-stone-300" { "Type" }
th class="p-1.5 text-left border border-stone-300" { "Nullable" }
th class="p-1.5 text-left border border-stone-300" { "PK" }
}
}
tbody {
@for col in &t.columns {
tr class="hover:bg-stone-100" {
td class="p-1.5 border border-stone-300 font-bold" { (col.name) }
td class="p-1.5 border border-stone-300 text-stone-600" { (col.data_type) }
td class="p-1.5 border border-stone-300" { (if col.is_nullable { "YES" } else { "NO" }) }
td class="p-1.5 border border-stone-300" { (if col.is_pk { "โ" } else { "" }) }
}
}
}
}
}
}
// Data Preview
@if t.preview.rows.is_empty() {
p class="text-xs text-stone-400 italic" { "Table is currently empty." }
} @else {
div class="db-table-scroll" {
table class="db-grid-table" {
thead {
tr {
@for col_name in &t.preview.columns {
th { (col_name) }
}
}
}
tbody {
@for row in &t.preview.rows {
tr {
@for cell in row {
td title=(cell) { (cell) }
}
}
}
}
}
}
}
}
}
}