From 6abbea56a6bfa69cb5e576223301f0c992b646fa Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Sat, 8 Nov 2025 14:13:43 +0100 Subject: activity sidebar for invoices. --- src/ui/ui_expenses.cpp | 185 ++++++++++++++++++++++++++++++++++++------------- src/ui/ui_invoices.cpp | 74 ++++++++++++++++---- 2 files changed, 197 insertions(+), 62 deletions(-) (limited to 'src/ui') diff --git a/src/ui/ui_expenses.cpp b/src/ui/ui_expenses.cpp index 5556cd6..3ea31e1 100644 --- a/src/ui/ui_expenses.cpp +++ b/src/ui/ui_expenses.cpp @@ -26,19 +26,34 @@ #include "administration.hpp" #include "administration_writer.hpp" +static activity* activity_buffer = 0; +static u32 activity_count; + static importer::invoice_request* active_import_request = 0; static ui::view_state current_view_state = ui::view_state::LIST_ALL; static invoice active_invoice = {0}; static invoice selected_for_removal = {0}; - +static const float sidepanel_width = 200.0f; static billing_item* invoice_items_buffer = 0; void draw_invoice_items_form(invoice* invoice, bool outgoing = true); +static void _reload_activities() +{ + activity_count = administration::activity_get_all_for_object(activity_buffer, active_invoice.id); +} + +static void _set_active_invoice(invoice inv) +{ + active_invoice = inv; + _reload_activities(); +} + void ui::destroy_expenses() { memops::unalloc(invoice_items_buffer); + memops::unalloc(activity_buffer); } void ui::setup_expenses() @@ -50,7 +65,8 @@ void ui::setup_expenses() current_view_state = ui::view_state::LIST_ALL; } - active_invoice = administration::invoice_create_empty(); + activity_buffer = (activity*)memops::alloc(sizeof(activity) * 250); + _set_active_invoice(administration::invoice_create_empty()); u32 invoice_items_count = MAX_BILLING_ITEMS; invoice_items_buffer = (billing_item*)memops::alloc(sizeof(billing_item) * invoice_items_count); @@ -215,22 +231,35 @@ static void draw_expenses_list() ImGui::Spacing(); - if (ImGui::BeginTable("TableInvoices", 7, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (ImGui::BeginTable("TableInvoices", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { ImGui::TableSetupColumn(locale::get("invoice.table.invoicenumber"), ImGuiTableColumnFlags_WidthFixed, 120); ImGui::TableSetupColumn(locale::get("invoice.table.sender")); ImGui::TableSetupColumn(locale::get("invoice.table.customer")); - ImGui::TableSetupColumn(locale::get("invoice.table.issuedat")); - ImGui::TableSetupColumn(locale::get("invoice.table.total")); - ImGui::TableSetupColumn(locale::get("invoice.table.status")); - ImGui::TableSetupColumn(""); + ImGui::TableSetupColumn(locale::get("invoice.table.issuedat"), ImGuiTableColumnFlags_WidthFixed, 90); + ImGui::TableSetupColumn(locale::get("invoice.table.total"), ImGuiTableColumnFlags_WidthFixed, 90); + ImGui::TableSetupColumn(locale::get("invoice.table.status"), ImGuiTableColumnFlags_WidthFixed, 90); ImGui::TableHeadersRow(); for (u32 i = 0; i < invoice_count; i++) { invoice c = invoice_list[i]; ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); ImGui::Text(c.sequential_number); + ImGui::TableSetColumnIndex(0); + + ImGui::PushID(i); + ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap; + bool selected = false; + if (ImGui::Selectable("##invisible_selectable", selected, selectable_flags, ImVec2(0, ImGui::GetFrameHeight()-4.0f))) + { + _set_active_invoice(c); + current_view_state = ui::view_state::VIEW_EXISTING; + } + ImGui::SetItemAllowOverlap(); + ImGui::SameLine(); + ImGui::PopID(); + + ImGui::Text(c.sequential_number); if (administration::invoice_is_valid(&c) != A_ERR_SUCCESS) { @@ -249,8 +278,8 @@ static void draw_expenses_list() ImGui::TableSetColumnIndex(3); ImGui::Text(buf); ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f %s", c.total, c.currency); ImGui::TableSetColumnIndex(5); ImGui::Text("%s", locale::get(administration::invoice_get_status_string(&c))); - ImGui::TableSetColumnIndex(6); + /* char btn_name[20]; strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); if (ImGui::Button(btn_name)) { @@ -271,23 +300,7 @@ static void draw_expenses_list() if (ImGui::Button(btn_name)) { selected_for_removal = c; ImGui::OpenPopup("ConfirmDeletePopup"); - } - } - - // Confirmation popup before contact is deleted definitively. - if (ImGui::BeginPopupModal("ConfirmDeletePopup", nullptr, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar)) { - ImGui::Text(locale::get("form.confirmDelete")); - ImGui::Separator(); - - if (ImGui::Button(locale::get("form.yes"), ImVec2(120, 0))) { - administration::invoice_remove(&selected_for_removal); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button(locale::get("form.no"), ImVec2(120, 0))) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); + }*/ } ImGui::EndTable(); @@ -299,26 +312,75 @@ static void _reset_to_default_view() current_view_state = ui::view_state::LIST_ALL; ui::destroy_expenses(); ui::setup_expenses(); + activity_count = 0; +} + +static void _reset_to_invoice_view() +{ + current_view_state = ui::view_state::VIEW_EXISTING; +} + +static void _draw_activity_sidepanel() +{ + ImGui::SameLine(); + ImGui::SeparatorEx(1 << 1, 3.0f); + ImGui::SameLine(); + + ImGui::BeginChild("##historyPanel", ImVec2(sidepanel_width, 0), ImGuiChildFlags_None); + { + for (u32 i = 0; i < activity_count; i++) + { + activity ac = activity_buffer[i]; + + char time_buffer[26]; + struct tm* tm_info; + tm_info = localtime(&ac.timestamp); + strftime(time_buffer, 26, "%d/%m/%Y %H:%M", tm_info); + + ImGui::Text(time_buffer); + + ImGui::PushFont(ui::fontBold); + ImGui::Text(ac.user_name); + ImGui::PopFont(); + ImGui::SameLine(); + + ImGui::TextWrapped("%s", locale::get(ac.message)); + ImGui::Spacing(); + } + } + + ImGui::EndChild(); } static void draw_expense_update() { - if (ImGui::Button(locale::get("form.back"), true, false)) { - _reset_to_default_view(); + if (ImGui::Button(locale::get("form.cancel"), true, false)) { + current_view_state = ui::view_state::VIEW_EXISTING; } - - draw_expense_form(&active_invoice); - bool can_save = administration::invoice_is_valid(&active_invoice) == A_ERR_SUCCESS; - if (!can_save) ImGui::BeginDisabled(); - + { // Save button + bool can_save = administration::invoice_is_valid(&active_invoice) == A_ERR_SUCCESS; + if (!can_save) ImGui::BeginDisabled(); + ImGui::SameLine(); + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_invoice_view); + administration::invoice_update(&active_invoice); + + _reload_activities(); + } + if (!can_save) ImGui::EndDisabled(); + } + + ImGui::Spacing(); + ImGui::Separator(3.0f); ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"), true)) { - administration_writer::set_write_completed_event_callback(_reset_to_default_view); - administration::invoice_update(&active_invoice); - } + + float availableWidth = ImGui::GetContentRegionAvail().x; + ImGui::BeginChild("##invoicePanel", ImVec2(availableWidth - sidepanel_width, 0), ImGuiChildFlags_None); + draw_expense_form(&active_invoice); + ImGui::EndChild(); - if (!can_save) ImGui::EndDisabled(); + _draw_activity_sidepanel(); } static void draw_expense_create() @@ -326,19 +388,28 @@ static void draw_expense_create() if (ImGui::Button(locale::get("form.back"), true, false)) { _reset_to_default_view(); } - - draw_expense_form(&active_invoice); - bool can_save = administration::invoice_is_valid(&active_invoice) == A_ERR_SUCCESS; - if (!can_save) ImGui::BeginDisabled(); - - ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"), true)) { - administration_writer::set_write_completed_event_callback(_reset_to_default_view); - administration::invoice_add(&active_invoice); - } + { // Save button + bool can_save = administration::invoice_is_valid(&active_invoice) == A_ERR_SUCCESS; + if (!can_save) ImGui::BeginDisabled(); + ImGui::SameLine(); + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_invoice_view); + administration::invoice_add(&active_invoice); + + _reload_activities(); + } + if (!can_save) ImGui::EndDisabled(); + } - if (!can_save) ImGui::EndDisabled(); + ImGui::Spacing(); + ImGui::Separator(3.0f); + ImGui::Spacing(); + + float availableWidth = ImGui::GetContentRegionAvail().x; + ImGui::BeginChild("##invoicePanel", ImVec2(availableWidth - sidepanel_width, 0), ImGuiChildFlags_None); + draw_expense_form(&active_invoice); + ImGui::EndChild(); } static void draw_expense_view() @@ -347,7 +418,23 @@ static void draw_expense_view() _reset_to_default_view(); } + ImGui::SameLine(); + + if (ImGui::Button(locale::get("form.change"))) { + _set_active_invoice(administration::invoice_create_copy(&active_invoice)); // We create a copy because of billing item list pointers. + current_view_state = ui::view_state::EDIT_EXISTING; + } + + ImGui::Spacing(); + ImGui::Separator(3.0f); + ImGui::Spacing(); + + float availableWidth = ImGui::GetContentRegionAvail().x; + ImGui::BeginChild("##invoicePanel", ImVec2(availableWidth - sidepanel_width, 0), ImGuiChildFlags_None); draw_expense_form(&active_invoice, true); + ImGui::EndChild(); + + _draw_activity_sidepanel(); } static void draw_import_request() diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp index 0e81259..ff3c73b 100644 --- a/src/ui/ui_invoices.cpp +++ b/src/ui/ui_invoices.cpp @@ -25,23 +25,38 @@ #include "administration.hpp" #include "administration_writer.hpp" +static activity* activity_buffer = 0; +static u32 activity_count; static ui::view_state current_view_state = ui::view_state::LIST_ALL; static invoice active_invoice = {0}; static invoice selected_for_removal = {0}; static const float sidepanel_width = 200.0f; - static billing_item* invoice_items_buffer = 0; +static void _reload_activities() +{ + activity_count = administration::activity_get_all_for_object(activity_buffer, active_invoice.id); +} + +static void _set_active_invoice(invoice inv) +{ + active_invoice = inv; + _reload_activities(); +} + void ui::destroy_invoices() { memops::unalloc(invoice_items_buffer); + memops::unalloc(activity_buffer); } void ui::setup_invoices() { + activity_buffer = (activity*)memops::alloc(sizeof(activity) * 250); + current_view_state = ui::view_state::LIST_ALL; - active_invoice = administration::invoice_create_empty(); + _set_active_invoice(administration::invoice_create_empty()); u32 invoice_items_count = MAX_BILLING_ITEMS; invoice_items_buffer = (billing_item*)memops::alloc(sizeof(billing_item) * invoice_items_count); @@ -279,7 +294,7 @@ static void draw_invoices_list() if (ImGui::Button(locale::get("form.create"))) { current_view_state = ui::view_state::CREATE; - active_invoice = administration::invoice_create_empty(); // @leak + _set_active_invoice(administration::invoice_create_empty()); active_invoice.supplier = administration::company_info_get(); active_invoice.is_outgoing = 1; active_invoice.status = invoice_status::INVOICE_CONCEPT; @@ -328,7 +343,7 @@ static void draw_invoices_list() bool selected = false; if (ImGui::Selectable("##invisible_selectable", selected, selectable_flags, ImVec2(0, ImGui::GetFrameHeight()-4.0f))) { - active_invoice = c; + _set_active_invoice(c); current_view_state = ui::view_state::VIEW_EXISTING; } ImGui::SetItemAllowOverlap(); @@ -372,11 +387,44 @@ static void _reset_to_default_view() current_view_state = ui::view_state::LIST_ALL; ui::destroy_invoices(); ui::setup_invoices(); + activity_count = 0; +} + +static void _draw_activity_sidepanel() +{ + ImGui::SameLine(); + ImGui::SeparatorEx(1 << 1, 3.0f); + ImGui::SameLine(); + + ImGui::BeginChild("##historyPanel", ImVec2(sidepanel_width, 0), ImGuiChildFlags_None); + { + for (u32 i = 0; i < activity_count; i++) + { + activity ac = activity_buffer[i]; + + char time_buffer[26]; + struct tm* tm_info; + tm_info = localtime(&ac.timestamp); + strftime(time_buffer, 26, "%d/%m/%Y %H:%M", tm_info); + + ImGui::Text(time_buffer); + + ImGui::PushFont(ui::fontBold); + ImGui::Text(ac.user_name); + ImGui::PopFont(); + ImGui::SameLine(); + + ImGui::TextWrapped("%s", locale::get(ac.message)); + ImGui::Spacing(); + } + } + + ImGui::EndChild(); } static void draw_invoice_update() { - if (ImGui::Button(locale::get("form.back"), true, false)) { + if (ImGui::Button(locale::get("form.cancel"), true, false)) { current_view_state = ui::view_state::VIEW_EXISTING; } @@ -387,6 +435,8 @@ static void draw_invoice_update() if (ImGui::Button(locale::get("form.save"), true)) { administration_writer::set_write_completed_event_callback(_reset_to_invoice_view); administration::invoice_update(&active_invoice); + + _reload_activities(); } if (!can_save) ImGui::EndDisabled(); } @@ -399,6 +449,8 @@ static void draw_invoice_update() ImGui::BeginChild("##invoicePanel", ImVec2(availableWidth - sidepanel_width, 0), ImGuiChildFlags_None); draw_invoice_form(&active_invoice); ImGui::EndChild(); + + _draw_activity_sidepanel(); } static void draw_invoice_create() @@ -414,6 +466,8 @@ static void draw_invoice_create() if (ImGui::Button(locale::get("form.save"), true)) { administration_writer::set_write_completed_event_callback(_reset_to_invoice_view); administration::invoice_add(&active_invoice); + + _reload_activities(); } if (!can_save) ImGui::EndDisabled(); } @@ -437,7 +491,7 @@ static void draw_invoice_view() ImGui::SameLine(); if (ImGui::Button(locale::get("form.change"))) { - active_invoice = administration::invoice_create_copy(&active_invoice); // We create a copy because of billing item list pointers. + _set_active_invoice(administration::invoice_create_copy(&active_invoice)); // We create a copy because of billing item list pointers. current_view_state = ui::view_state::EDIT_EXISTING; } @@ -480,13 +534,7 @@ static void draw_invoice_view() draw_invoice_form(&active_invoice, true); ImGui::EndChild(); - ImGui::SameLine(); - ImGui::SeparatorEx(1 << 1, 3.0f); - ImGui::SameLine(); - - ImGui::BeginChild("##historyPanel", ImVec2(sidepanel_width, 0), ImGuiChildFlags_None); - // Sidepanel - ImGui::EndChild(); + _draw_activity_sidepanel(); } void ui::draw_invoices() -- cgit v1.2.3-70-g09d2