From 4a2500299e8fd58f40b545d62dae0282ff20bb01 Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Mon, 12 Jan 2026 15:19:45 +0100 Subject: refactor contact page --- TODO | 3 ++ src/locales/en.cpp | 2 +- src/ui/ui_contacts.cpp | 132 ++++++++++++++++++++++++++----------------------- src/ui/ui_invoices.cpp | 2 +- 4 files changed, 74 insertions(+), 65 deletions(-) diff --git a/TODO b/TODO index ec54557..82db0a8 100644 --- a/TODO +++ b/TODO @@ -5,6 +5,7 @@ Fix: - reload invoice when backing out of edit mode. Unsaved changed are not undone atm - Handle missing file loading crash - handle invalid file format crash. check if xml object is found before using it. +- invoice total is wrong when invoice is not using main currency (final is correct but currency tag is wrong) Refactor: - Refactor zip writing to be faster (Windows is slow) @@ -19,6 +20,8 @@ Testing: - write tests for document saving Features: +- Button to mark expense as paid +- Button to mark invoice as paid - status window for ongoing requests, used can click on item when result is ready. Should be usefull for batch imports. - implement gemini and perplexity api backends - Refactor contact and project UI to be like invoice & expenses diff --git a/src/locales/en.cpp b/src/locales/en.cpp index 2725df0..bc87b10 100644 --- a/src/locales/en.cpp +++ b/src/locales/en.cpp @@ -68,7 +68,7 @@ locale_entry en_locales[] = { {"form.no", "No"}, {"form.change", ICON_FA_PEN_SQUARE" Change"}, {"form.view", "View"}, - {"form.delete", "Delete"}, + {"form.delete", ICON_FA_TRASH_ALT" Delete"}, {"form.cancel", "Cancel"}, {"form.confirmDelete", "Are you sure you want to delete this item?"}, {"form.confirmCancelProject", "Are you sure you want to cancel this Project?"}, diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp index 99896ce..b41180e 100644 --- a/src/ui/ui_contacts.cpp +++ b/src/ui/ui_contacts.cpp @@ -85,74 +85,50 @@ static void draw_contact_list() ImGui::Spacing(); - if (ImGui::BeginTable("TableContacts", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (ImGui::BeginTable("TableContacts", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { ImGui::TableSetupColumn(locale::get("contact.table.identifier"), ImGuiTableColumnFlags_WidthFixed, 80); ImGui::TableSetupColumn(locale::get("contact.table.name"), ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn(locale::get("contact.table.address"), ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 170); + ImGui::PushFont(ui::fontBold); ImGui::TableHeadersRow(); + ImGui::PopFont(); contact contact_list[items_per_page]; u32 contact_count = administration::contact_get_partial_list(current_page, items_per_page, contact_list, &filter); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); for (u32 i = 0; i < contact_count; i++) { contact c = contact_list[i]; ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); ImGui::Text(c.id); + ImGui::TableSetColumnIndex(0); - if (administration::contact_is_valid(c) != A_ERR_SUCCESS) + 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()+2.0f))) { - if (ImGui::WarningIcon(8.0f)) { - ImGui::SetTooltip(locale::get("ui.tooltip.invalidContact")); - } - } - - ImGui::TableSetColumnIndex(1); ImGui::Text(c.name); - ImGui::TableSetColumnIndex(2); ImGui::Text("%s %s", c.addr.address1, c.addr.address2); - - ImGui::TableSetColumnIndex(3); - - char btn_name[20]; - strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); - if (ImGui::Button(btn_name)) { active_contact = c; current_view_state = ui::view_state::VIEW_EXISTING; } - + ImGui::SetItemAllowOverlap(); ImGui::SameLine(); + ImGui::PopID(); - strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); - if (ImGui::Button(btn_name)) { - active_contact = c; - current_view_state = ui::view_state::EDIT_EXISTING; - } + ImGui::Text(c.id); - ImGui::SameLine(); - strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.delete"), i); - if (ImGui::Button(btn_name)) { - selected_for_removal = c; - ImGui::OpenPopup("ConfirmDeletePopup"); + if (administration::contact_is_valid(c) != A_ERR_SUCCESS) + { + if (ImGui::WarningIcon(8.0f)) { + ImGui::SetTooltip(locale::get("ui.tooltip.invalidContact")); + } } - } - // 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::contact_remove(selected_for_removal); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button(locale::get("form.no"), ImVec2(120, 0))) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); + ImGui::TableSetColumnIndex(1); ImGui::Text(c.name); + ImGui::TableSetColumnIndex(2); ImGui::Text("%s %s, %s %s, %s", c.addr.address1, c.addr.address2, c.addr.postal, c.addr.city, c.addr.country_code); } - + ImGui::PopStyleVar(); ImGui::EndTable(); } } @@ -167,39 +143,76 @@ static void draw_contacts_create() if (ImGui::Button(locale::get("form.back"), true, false)) { _reset_to_default_view(); } - - ImGui::ContactForm(&active_contact, false, false); - + ImGui::SameLine(); + a_err contact_validation_err = administration::contact_is_valid(active_contact); bool can_save = contact_validation_err == A_ERR_SUCCESS; if (!can_save) ImGui::BeginDisabled(); - // Save button - ImGui::Spacing(); if (ImGui::Button(locale::get("form.save"), true)) { - administration_writer::set_write_completed_event_callback(_reset_to_default_view); + administration_writer::set_write_completed_event_callback(0); administration::contact_add(active_contact); + current_view_state = ui::view_state::VIEW_EXISTING; } if (!can_save) ImGui::EndDisabled(); + + ImGui::ContactForm(&active_contact, false, false); } static void draw_contacts_update() { if (ImGui::Button(locale::get("form.back"), true, false)) { - _reset_to_default_view(); + current_view_state = ui::view_state::VIEW_EXISTING; } - ImGui::ContactForm(&active_contact, false, false); + ImGui::SameLine(); a_err contact_validation_err = administration::contact_is_valid(active_contact); bool can_save = contact_validation_err == A_ERR_SUCCESS; if (!can_save) ImGui::BeginDisabled(); - // Save button - ImGui::Spacing(); if (ImGui::Button(locale::get("form.save"), true)) { - administration_writer::set_write_completed_event_callback(_reset_to_default_view); + administration_writer::set_write_completed_event_callback(0); administration::contact_update(active_contact); } if (!can_save) ImGui::EndDisabled(); + + ImGui::SameLine(); + + if (ImGui::Button(locale::get("form.delete"))) { + selected_for_removal = active_contact; + ImGui::OpenPopup("ConfirmDeletePopup"); + } + + ImGui::ContactForm(&active_contact, false, false); + + // Confirmation popup before contact is deleted permanently. + 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::contact_remove(selected_for_removal); + ImGui::CloseCurrentPopup(); + _reset_to_default_view(); + } + ImGui::SameLine(); + if (ImGui::Button(locale::get("form.no"), ImVec2(120, 0))) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } +} + +static void draw_contact_view() +{ + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); + } + ImGui::SameLine(); + if (ImGui::Button(locale::get("form.change"))) { + current_view_state = ui::view_state::EDIT_EXISTING; + } + + ImGui::ContactForm(&active_contact, true, false); } void ui::draw_contacts() @@ -209,14 +222,7 @@ void ui::draw_contacts() case ui::view_state::LIST_ALL: draw_contact_list(); break; case ui::view_state::CREATE: draw_contacts_create(); break; case ui::view_state::EDIT_EXISTING: draw_contacts_update(); break; - - case ui::view_state::VIEW_EXISTING: - if (ImGui::Button(locale::get("form.back"), true, false)) { - _reset_to_default_view(); - } - - ImGui::ContactForm(&active_contact, true, false); - break; + case ui::view_state::VIEW_EXISTING: draw_contact_view(); break; default: break; } diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp index e7872d1..16dcc52 100644 --- a/src/ui/ui_invoices.cpp +++ b/src/ui/ui_invoices.cpp @@ -60,7 +60,7 @@ void ui::destroy_invoices() void ui::setup_invoices() { - activity_buffer = (activity*)memops::alloc(sizeof(activity) * 250); + activity_buffer = (activity*)memops::alloc(sizeof(activity) * 250); // @TODO hardcoded current_view_state = ui::view_state::LIST_ALL; _set_active_invoice(administration::invoice_create_empty()); -- cgit v1.2.3-70-g09d2