// panel_dashboard.cpp — KPI grid using kpi_card + sparkline from the registry. #include "panels.h" #include "core/icons_tabler.h" #include "viz/kpi_card.h" #include "viz/sparkline.h" #include #include #include namespace kanban_cpp { namespace { float pct_by_status(const std::vector& cards, const std::string& status) { if (cards.empty()) return 0.0f; int hits = 0; for (const auto& c : cards) if (c.status == status) ++hits; return 100.0f * static_cast(hits) / static_cast(cards.size()); } } // namespace void draw_dashboard(AppState& s, bool* p_open) { if (!ImGui::Begin(TI_DASHBOARD " Dashboard", p_open)) { ImGui::End(); return; } ImGui::TextDisabled("KPIs sinteticos (TODO: backend /api/stats endpoint)"); ImGui::Separator(); // Snapshot counts int total = static_cast(s.cards.size()); std::map by_priority; std::map by_status; for (const auto& c : s.cards) { if (!c.priority.empty()) by_priority[c.priority]++; if (!c.status.empty()) by_status[c.status]++; } // Fake history for sparkline — until backend wires real time-series. static float hist_total[12] = {3,4,5,5,7,8,9,8,10,11,12,13}; static float hist_doing[12] = {1,1,2,2,3,3,4,4,5,5,6,6}; // KPI grid (use Columns for a quick 3-up layout) ImGui::Columns(3, "##kpi_cols", false); kpi_card("Total cards", static_cast(total), 0.0f, hist_total, 12, "%.0f", TI_LAYOUT_KANBAN); ImGui::NextColumn(); kpi_card("Doing now", static_cast(by_status["doing"]), 0.0f, hist_doing, 12, "%.0f", TI_PLAYER_PLAY); ImGui::NextColumn(); kpi_card("Critical", static_cast(by_priority["critical"]), 0.0f, nullptr, 0, "%.0f", TI_FLAG); ImGui::Columns(1); ImGui::Separator(); // Status breakdown ImGui::Text("Status breakdown"); for (const auto& kv : by_status) { ImGui::Text(" %-12s %d", kv.first.c_str(), kv.second); } ImGui::End(); } } // namespace kanban_cpp