Files
kanban_cpp/panel_calendar.cpp
T

105 lines
3.3 KiB
C++

// panel_calendar.cpp — MVP monthly calendar view.
//
// Renders a simple 7-column grid for the current month with cards bucketed
// by `due_date`. No navigation, no editing — that's tracked as TODO in
// app.md ## Gotchas.
#include "panels.h"
#include "core/icons_tabler.h"
#include <imgui.h>
#include <ctime>
#include <mutex>
namespace kanban_cpp {
void draw_calendar(AppState& s, bool* p_open) {
if (!ImGui::Begin(TI_CALENDAR " Calendar", p_open)) {
ImGui::End();
return;
}
std::time_t now = std::time(nullptr);
std::tm tm_now;
#ifdef _WIN32
localtime_s(&tm_now, &now);
#else
localtime_r(&now, &tm_now);
#endif
// Heading
static const char* months[] = {"Enero","Febrero","Marzo","Abril","Mayo","Junio",
"Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"};
ImGui::Text("%s %d", months[tm_now.tm_mon], tm_now.tm_year + 1900);
ImGui::TextDisabled("(MVP estatico — TODO: navegacion + filtros)");
ImGui::Separator();
std::vector<Card> cards_snap;
{
std::lock_guard<std::mutex> lock(s.mu);
cards_snap = s.cards;
}
// First day of current month + days in month
std::tm tm_first = tm_now;
tm_first.tm_mday = 1;
std::mktime(&tm_first);
int first_wday = tm_first.tm_wday; // 0 = Sunday
int first_wday_mon = (first_wday + 6) % 7; // 0 = Monday (ES convention)
int days_in_month = 31;
{
std::tm tm_test = tm_now;
tm_test.tm_mday = 32;
std::mktime(&tm_test);
days_in_month = 32 - tm_test.tm_mday;
}
// Grid 7 cols
if (ImGui::BeginTable("##cal", 7, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchSame)) {
const char* wdays[] = {"L","M","X","J","V","S","D"};
for (int i = 0; i < 7; ++i) ImGui::TableSetupColumn(wdays[i]);
ImGui::TableHeadersRow();
int day = 1;
int total_cells = first_wday_mon + days_in_month;
int rows = (total_cells + 6) / 7;
int cell_index = 0;
for (int r = 0; r < rows; ++r) {
ImGui::TableNextRow();
for (int c = 0; c < 7; ++c) {
ImGui::TableSetColumnIndex(c);
if (cell_index < first_wday_mon || day > days_in_month) {
ImGui::TextDisabled(" ");
} else {
ImGui::Text("%d", day);
// Count cards whose due_date falls in this day.
int hits = 0;
for (const auto& card : cards_snap) {
if (card.due_date == 0) continue;
std::time_t cd = (std::time_t)card.due_date;
std::tm tmc;
#ifdef _WIN32
localtime_s(&tmc, &cd);
#else
localtime_r(&cd, &tmc);
#endif
if (tmc.tm_year == tm_now.tm_year && tmc.tm_mon == tm_now.tm_mon
&& tmc.tm_mday == day) ++hits;
}
if (hits > 0)
ImGui::TextColored(ImVec4(0.6f, 0.55f, 0.95f, 1.0f),
TI_FLAG " %d", hits);
++day;
}
++cell_index;
}
}
ImGui::EndTable();
}
ImGui::End();
}
} // namespace kanban_cpp