From 5d34aff5888d3f0c624251f15bedb96c347978d6 Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Sat, 9 Aug 2025 08:33:08 +0200 Subject: refactors --- include/administration.hpp | 70 ++++++++++++++ include/config.hpp | 13 +++ include/locales.hpp | 21 +++++ include/strops.hpp | 3 + include/ui.hpp | 15 +++ run.bat | 9 +- simclist-1.5/simclist.c | 4 +- src/administration.cpp | 11 ++- src/administration.hpp | 70 -------------- src/config.hpp | 13 --- src/locales.cpp | 29 ++++++ src/locales/locales.cpp | 29 ------ src/locales/locales.hpp | 21 ----- src/main.cpp | 4 +- src/strops.cpp | 18 ++++ src/ui/helpers.cpp | 28 ++++++ src/ui/ui_contacts.cpp | 228 +++++++++++++++++++++++++++++++++++++++++++++ src/ui/ui_main.cpp | 110 ++++++++++++++++++++++ src/ui/ui_projects.cpp | 173 ++++++++++++++++++++++++++++++++++ src/views/contacts.cpp | 227 -------------------------------------------- src/views/dashboard.cpp | 110 ---------------------- src/views/projects.cpp | 173 ---------------------------------- src/views/views.cpp | 28 ------ src/views/views.hpp | 15 --- 24 files changed, 724 insertions(+), 698 deletions(-) create mode 100644 include/administration.hpp create mode 100644 include/config.hpp create mode 100644 include/locales.hpp create mode 100644 include/strops.hpp create mode 100644 include/ui.hpp delete mode 100644 src/administration.hpp delete mode 100644 src/config.hpp create mode 100644 src/locales.cpp delete mode 100644 src/locales/locales.cpp delete mode 100644 src/locales/locales.hpp create mode 100644 src/strops.cpp create mode 100644 src/ui/helpers.cpp create mode 100644 src/ui/ui_contacts.cpp create mode 100644 src/ui/ui_main.cpp create mode 100644 src/ui/ui_projects.cpp delete mode 100644 src/views/contacts.cpp delete mode 100644 src/views/dashboard.cpp delete mode 100644 src/views/projects.cpp delete mode 100644 src/views/views.cpp delete mode 100644 src/views/views.hpp diff --git a/include/administration.hpp b/include/administration.hpp new file mode 100644 index 0000000..9506246 --- /dev/null +++ b/include/administration.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include "config.hpp" +#include "simclist.h" + +typedef struct +{ + char id[16]; + char name[64]; + char address1[128]; + char address2[128]; + char country[128]; + char taxid[32]; + char businessid[32]; + char email[64]; + char phone_number[16]; + char bank_account[32]; +} contact; + +typedef enum +{ + RUNNING, + PAUSED, + CANCELLED, +} project_state; + +typedef struct +{ + char id[16]; + char description[64]; + project_state state; + time_t start_date; + time_t end_date; +} project; + +typedef struct +{ + contact company_info; + s32 next_id; + char path[4096]; + char program_version[10]; + char country_code[2]; + list_t contacts; + list_t projects; + // invoices + char ai_service[16]; + char ai_key[32]; + char email_service[16]; + char email_key[32]; +} administration; + +void administration_create(); +void administration_destroy(); + +char* administration_get_file_path(); +s32 administration_create_id(); + +bool administration_remove_contact(contact data); +bool administration_create_contact(contact data); +bool administration_update_contact(contact data); +u32 administration_get_contact_count(); +u32 administration_get_contacts(u32 page_index, u32 page_size, contact* buffer); + +void administration_cancel_project(project data); +bool administration_remove_project(project data); +bool administration_create_project(project data); +bool administration_update_project(project data); +char* administration_project_get_status_string(project data); +u32 administration_get_project_count(); +u32 administration_get_projects(u32 page_index, u32 page_size, project* buffer); \ No newline at end of file diff --git a/include/config.hpp b/include/config.hpp new file mode 100644 index 0000000..3279e2e --- /dev/null +++ b/include/config.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "stdint.h" + +#define s8 int8_t +#define s16 int16_t +#define s32 int32_t +#define s64 int64_t + +#define u8 uint8_t +#define u16 uint16_t +#define u32 uint32_t +#define u64 uint64_t \ No newline at end of file diff --git a/include/locales.hpp b/include/locales.hpp new file mode 100644 index 0000000..78bb682 --- /dev/null +++ b/include/locales.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +typedef struct { + const char* key; + const char* value; +} locale_entry; + +typedef struct { + const char* lang_code; + locale_entry* entries; + int entry_count; +} locale_map; + +extern locale_entry en_locales[]; +extern const int en_locale_count; + +void set_locale(const char key[2]); +const char* localize(const char* key); \ No newline at end of file diff --git a/include/strops.hpp b/include/strops.hpp new file mode 100644 index 0000000..daa1d71 --- /dev/null +++ b/include/strops.hpp @@ -0,0 +1,3 @@ +#pragma once + +size_t strops_copy(char *dst, const char *src, size_t size); \ No newline at end of file diff --git a/include/ui.hpp b/include/ui.hpp new file mode 100644 index 0000000..827980c --- /dev/null +++ b/include/ui.hpp @@ -0,0 +1,15 @@ +#pragma once + +typedef enum +{ + LIST, + EDIT, + CREATE, + VIEW, +} view_state; + +void view_draw_required_tag(); + +void ui_draw_main(); +void ui_draw_contacts(); +void ui_draw_projects(); \ No newline at end of file diff --git a/run.bat b/run.bat index 03e0406..842c2f6 100644 --- a/run.bat +++ b/run.bat @@ -1,11 +1,12 @@ call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 @set OUT_DIR=build\\ @set OUT_EXE=accounting -@set SOURCES=src\*.cpp imgui-1.92.1\backends\imgui_impl_dx11.cpp imgui-1.92.1\backends\imgui_impl_win32.cpp imgui-1.92.1\imgui*.cpp src\views\*.cpp src\locales\*.cpp simclist-1.5\simclist.c +@set LIB_SOURCES=imgui-1.92.1\backends\imgui_impl_dx11.cpp imgui-1.92.1\backends\imgui_impl_win32.cpp imgui-1.92.1\imgui*.cpp simclist-1.5\simclist.c +@set SOURCES= src\*.cpp src\ui\*.cpp src\locales\*.cpp @set LIBS=opengl32.lib Advapi32.lib Shell32.lib Ole32.lib User32.lib Pathcch.lib D3D11.lib -@set FLAGS=/DMODE_DEBUG /DEBUG:FULL /Ob0 /MT /Oy- /Zi +@set FLAGS= /std:c11 /nologo /Ob0 /MT /Oy- /Zi /FS /W4 /EHsc /utf-8 +@set INCLUDE_DIRS=/I"imgui-1.92.1" /I"imgui-1.92.1/backends" /I"/" /I"simclist-1.5" /Iinclude - -cl /std:c11 /nologo %FLAGS% /I"imgui-1.92.1" /I"imgui-1.92.1/backends" /I"/" /I"simclist-1.5" /w /EHsc /Isrc /utf-8 %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fd%OUT_DIR%/vc140.pdb /Fo%OUT_DIR%/ /link %LIBS% +cl %FLAGS% %INCLUDE_DIRS% %SOURCES% %LIB_SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fd%OUT_DIR%/vc140.pdb /Fo%OUT_DIR%/ /link %LIBS% if "%1"=="-r" call "%OUT_DIR%/%OUT_EXE%.exe" if "%1"=="-d" call devenv "%OUT_DIR%/%OUT_EXE%.exe" diff --git a/simclist-1.5/simclist.c b/simclist-1.5/simclist.c index edae4bb..0c34786 100644 --- a/simclist-1.5/simclist.c +++ b/simclist-1.5/simclist.c @@ -1430,8 +1430,8 @@ list_hash_t list_hashcomputer_string(const void *el) { char plus; for (l = 0; str[l] != '\0'; l++) { - if (l) plus = hash ^ str[l]; - else plus = hash ^ (str[l] - str[0]); + if (l) plus = (char)(hash ^ str[l]); + else plus = (char)(hash ^ (str[l] - str[0])); hash += (plus << (CHAR_BIT * (l % sizeof(list_hash_t)))); } diff --git a/src/administration.cpp b/src/administration.cpp index 9362b8d..fb8bd21 100644 --- a/src/administration.cpp +++ b/src/administration.cpp @@ -3,6 +3,7 @@ #include #include +#include "strops.hpp" #include "administration.hpp" administration g_administration; @@ -11,7 +12,7 @@ void administration_create() { list_init(&g_administration.contacts); list_init(&g_administration.projects); - strncpy(g_administration.path, "[unsaved project]", sizeof(g_administration.path)); // @localize + strops_copy(g_administration.path, "[unsaved project]", sizeof(g_administration.path)); // @localize } void administration_destroy() @@ -140,10 +141,12 @@ char* administration_project_get_status_string(project data) { switch(data.state) { - case project_state::RUNNING: return "project.state.running"; break; - case project_state::PAUSED: return "project.state.paused"; break; - case project_state::CANCELLED: return "project.state.cancelled"; break; + case project_state::RUNNING: return "project.state.running"; + case project_state::PAUSED: return "project.state.paused"; + case project_state::CANCELLED: return "project.state.cancelled"; + default: assert(0); break; } + return ""; } bool administration_create_project(project data) diff --git a/src/administration.hpp b/src/administration.hpp deleted file mode 100644 index 9506246..0000000 --- a/src/administration.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -#include "config.hpp" -#include "simclist.h" - -typedef struct -{ - char id[16]; - char name[64]; - char address1[128]; - char address2[128]; - char country[128]; - char taxid[32]; - char businessid[32]; - char email[64]; - char phone_number[16]; - char bank_account[32]; -} contact; - -typedef enum -{ - RUNNING, - PAUSED, - CANCELLED, -} project_state; - -typedef struct -{ - char id[16]; - char description[64]; - project_state state; - time_t start_date; - time_t end_date; -} project; - -typedef struct -{ - contact company_info; - s32 next_id; - char path[4096]; - char program_version[10]; - char country_code[2]; - list_t contacts; - list_t projects; - // invoices - char ai_service[16]; - char ai_key[32]; - char email_service[16]; - char email_key[32]; -} administration; - -void administration_create(); -void administration_destroy(); - -char* administration_get_file_path(); -s32 administration_create_id(); - -bool administration_remove_contact(contact data); -bool administration_create_contact(contact data); -bool administration_update_contact(contact data); -u32 administration_get_contact_count(); -u32 administration_get_contacts(u32 page_index, u32 page_size, contact* buffer); - -void administration_cancel_project(project data); -bool administration_remove_project(project data); -bool administration_create_project(project data); -bool administration_update_project(project data); -char* administration_project_get_status_string(project data); -u32 administration_get_project_count(); -u32 administration_get_projects(u32 page_index, u32 page_size, project* buffer); \ No newline at end of file diff --git a/src/config.hpp b/src/config.hpp deleted file mode 100644 index 3279e2e..0000000 --- a/src/config.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "stdint.h" - -#define s8 int8_t -#define s16 int16_t -#define s32 int32_t -#define s64 int64_t - -#define u8 uint8_t -#define u16 uint16_t -#define u32 uint32_t -#define u64 uint64_t \ No newline at end of file diff --git a/src/locales.cpp b/src/locales.cpp new file mode 100644 index 0000000..6ec1233 --- /dev/null +++ b/src/locales.cpp @@ -0,0 +1,29 @@ +#include "locales.hpp" + +locale_map locales[] = { + {"en", en_locales, en_locale_count}, + // Add new locales here. +}; + +const int locale_map_count = sizeof(locales) / sizeof(locales[0]); + +locale_map g_locale = locales[0]; // Default to english. + +void set_locale(const char* key) +{ + for (int i = 0; i < locale_map_count; ++i) { + if (strcmp(locales[i].lang_code, key) == 0) { + g_locale = locales[i]; + } + } +} + +const char* localize(const char* key) +{ + for (int i = 0; i < g_locale.entry_count; ++i) { + if (strcmp(g_locale.entries[i].key, key) == 0) { + return g_locale.entries[i].value; + } + } + return "[!MISSING!]"; +} \ No newline at end of file diff --git a/src/locales/locales.cpp b/src/locales/locales.cpp deleted file mode 100644 index 6ec1233..0000000 --- a/src/locales/locales.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "locales.hpp" - -locale_map locales[] = { - {"en", en_locales, en_locale_count}, - // Add new locales here. -}; - -const int locale_map_count = sizeof(locales) / sizeof(locales[0]); - -locale_map g_locale = locales[0]; // Default to english. - -void set_locale(const char* key) -{ - for (int i = 0; i < locale_map_count; ++i) { - if (strcmp(locales[i].lang_code, key) == 0) { - g_locale = locales[i]; - } - } -} - -const char* localize(const char* key) -{ - for (int i = 0; i < g_locale.entry_count; ++i) { - if (strcmp(g_locale.entries[i].key, key) == 0) { - return g_locale.entries[i].value; - } - } - return "[!MISSING!]"; -} \ No newline at end of file diff --git a/src/locales/locales.hpp b/src/locales/locales.hpp deleted file mode 100644 index 78bb682..0000000 --- a/src/locales/locales.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include - -typedef struct { - const char* key; - const char* value; -} locale_entry; - -typedef struct { - const char* lang_code; - locale_entry* entries; - int entry_count; -} locale_map; - -extern locale_entry en_locales[]; -extern const int en_locale_count; - -void set_locale(const char key[2]); -const char* localize(const char* key); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 3f6cf03..c1eb694 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ #include #include -#include "views/views.hpp" +#include "ui.hpp" #include "administration.hpp" // Data @@ -128,7 +128,7 @@ int main() ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); - views_draw_dashboard(); + ui_draw_main(); // Rendering ImGui::Render(); diff --git a/src/strops.cpp b/src/strops.cpp new file mode 100644 index 0000000..42042cb --- /dev/null +++ b/src/strops.cpp @@ -0,0 +1,18 @@ +#include + +#include "strops.hpp" + +size_t strops_copy(char *dst, const char *src, size_t size) +{ + size_t srclen; + size --; + srclen = strlen(src); + + if (srclen > size) + srclen = size; + + memcpy(dst, src, srclen); + dst[srclen] = '\0'; + + return (srclen); +} \ No newline at end of file diff --git a/src/ui/helpers.cpp b/src/ui/helpers.cpp new file mode 100644 index 0000000..74876c0 --- /dev/null +++ b/src/ui/helpers.cpp @@ -0,0 +1,28 @@ +#include "ui.hpp" +#include "imgui.h" +#include "locales.hpp" + +void view_draw_required_tag() +{ + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + + const char* text = localize("form.required"); + ImVec2 text_pos = ImGui::GetCursorScreenPos(); + ImVec2 text_size = ImGui::CalcTextSize(text); + text_pos.y += text_size.y/4.0f; + + ImVec4 bg_color = ImVec4(0.9f, 0.235f, 0.235f, 0.4f); // Red background + ImVec4 text_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // White text + float rounding = 2.0f; + float padding = 2.0f; + + // Background rectangle + ImVec2 bg_min = ImVec2(text_pos.x - padding, text_pos.y - padding); + ImVec2 bg_max = ImVec2(text_pos.x + text_size.x + padding, text_pos.y + text_size.y + padding); + draw_list->AddRectFilled(bg_min, bg_max, ImColor(bg_color), rounding); + + // Foreground text + ImGui::PushStyleColor(ImGuiCol_Text, text_color); + ImGui::TextUnformatted(text); + ImGui::PopStyleColor(); +} \ No newline at end of file diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp new file mode 100644 index 0000000..3115a77 --- /dev/null +++ b/src/ui/ui_contacts.cpp @@ -0,0 +1,228 @@ +#include + +#include "strops.hpp" +#include "ui.hpp" +#include "imgui.h" +#include "administration.hpp" +#include "locales.hpp" + +static view_state current_view_state = LIST; +static contact selected_for_removal; + +static contact active_contact; + +static void draw_contact_form() +{ + static const char* selected_country = NULL; + + if (ImGui::Button(localize("form.back"))) { + current_view_state = view_state::LIST; + memset(&active_contact, 0, sizeof(contact)); + selected_country = 0; + return; + } + ImGui::Spacing(); + + bool viewing_only = (current_view_state == view_state::VIEW); + + ImGui::BeginDisabled(); + + float widthAvailable = ImGui::GetContentRegionAvail().x; + + ImGui::SetNextItemWidth(widthAvailable*0.2f); + ImGui::InputText(localize("contact.form.identifier"), active_contact.id, IM_ARRAYSIZE(active_contact.id)); + if (!viewing_only) ImGui::EndDisabled(); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("contact.form.fullname"), localize("contact.form.fullname"), active_contact.name, IM_ARRAYSIZE(active_contact.name)); + ImGui::SameLine();view_draw_required_tag(); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("contact.form.address1"), localize("contact.form.address1"), active_contact.address1, IM_ARRAYSIZE(active_contact.address1)); + ImGui::SameLine();view_draw_required_tag(); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("contact.form.address2"), localize("contact.form.address2"), active_contact.address2, IM_ARRAYSIZE(active_contact.address2)); + ImGui::SameLine();view_draw_required_tag(); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + + const char* countries[] = { localize("country.AT"),localize("country.BE"),localize("country.BG"),localize("country.HR"),localize("country.CY"),localize("country.CZ"),localize("country.DK"),localize("country.EE"),localize("country.FI"),localize("country.FR"),localize("country.DE"),localize("country.GR"),localize("country.HU"),localize("country.IE"),localize("country.IT"),localize("country.LV"),localize("country.LT"),localize("country.LU"),localize("country.MT"),localize("country.NL"),localize("country.PL"),localize("country.PT"),localize("country.RO"),localize("country.SK"),localize("country.SI"),localize("country.ES"),localize("country.SE") }; + s32 country_count = sizeof(countries) / sizeof(countries[0]); + if (selected_country == 0) { + for (int i = 0; i < country_count; i++) + { + if (strcmp(countries[i], active_contact.country) == 0) + { + selected_country = countries[i]; + break; + } + } + } + + if (ImGui::BeginCombo(localize("contact.form.country"), selected_country)) + { + for (int n = 0; n < IM_ARRAYSIZE(countries); n++) + { + bool is_selected = (selected_country == countries[n]); + if (ImGui::Selectable(countries[n], is_selected)) + selected_country = countries[n]; + } + ImGui::EndCombo(); + } + if (selected_country) { + strops_copy(active_contact.country, selected_country, IM_ARRAYSIZE(active_contact.country)); + } + ImGui::SameLine();view_draw_required_tag(); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("contact.form.taxnumber"), localize("contact.form.taxnumber"), active_contact.taxid, IM_ARRAYSIZE(active_contact.taxid)); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("contact.form.businessnumber"), localize("contact.form.businessnumber"), active_contact.businessid, IM_ARRAYSIZE(active_contact.businessid)); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("contact.form.email"), localize("contact.form.email"), active_contact.email, IM_ARRAYSIZE(active_contact.email)); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("contact.form.phonenumber"), localize("contact.form.phonenumber"), active_contact.phone_number, IM_ARRAYSIZE(active_contact.phone_number)); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("contact.form.bankaccount"), localize("contact.form.bankaccount"), active_contact.bank_account, IM_ARRAYSIZE(active_contact.bank_account)); + + if (viewing_only) ImGui::EndDisabled(); + + if (!viewing_only) { + bool can_save = strlen(active_contact.name) > 0 && strlen(active_contact.address1) > 0 && + strlen(active_contact.address2) > 0 && strlen(active_contact.country) > 0; + + if (!can_save) ImGui::BeginDisabled(); + // Save button + ImGui::Spacing(); + if (ImGui::Button(localize("form.save"))) { + if (current_view_state == view_state::CREATE) + administration_create_contact(active_contact); + + else if (current_view_state == view_state::EDIT) + administration_update_contact(active_contact); + + memset(&active_contact, 0, sizeof(contact)); + current_view_state = view_state::LIST; + selected_country = 0; + } + if (!can_save) ImGui::EndDisabled(); + } + else { + // TODO list invoices connected to contact. + } +} + +static void draw_contact_list() +{ + const u32 items_per_page = 50; + static s32 current_page = 0; + s32 max_page = (administration_get_contact_count() + items_per_page - 1) / items_per_page; + if (max_page == 0) max_page = 1; + + if (ImGui::Button(localize("form.create"))) + { + current_view_state = view_state::CREATE; + memset(&active_contact, 0, sizeof(contact)); + snprintf(active_contact.id, IM_ARRAYSIZE(active_contact.id), "C/%d", administration_create_id()); + } + + if (current_page >= max_page-1) current_page = max_page-1; + if (current_page < 0) current_page = 0; + + ImGui::SameLine(); + bool enable_prev = current_page > 0; + if (!enable_prev) ImGui::BeginDisabled(); + if (ImGui::Button("<< Prev") && current_page > 0) current_page--; + if (!enable_prev) ImGui::EndDisabled(); + + ImGui::SameLine(); + ImGui::Text("(%d/%d)", current_page+1, max_page); + + ImGui::SameLine(); + bool enable_next = current_page < max_page-1; + if (!enable_next) ImGui::BeginDisabled(); + if (ImGui::Button("Next >>") && current_page < max_page-1) current_page++; + if (!enable_next) ImGui::EndDisabled(); + + ImGui::Spacing(); + + if (ImGui::BeginTable("TableContacts", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + + ImGui::TableSetupColumn(localize("contact.table.identifier"), ImGuiTableColumnFlags_WidthFixed, 80); + ImGui::TableSetupColumn(localize("contact.table.name"), ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn(localize("contact.table.address"), ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 160); + ImGui::TableHeadersRow(); + + contact contact_list[items_per_page]; + u32 contact_count = administration_get_contacts(current_page, items_per_page, contact_list); + + for (u32 i = 0; i < contact_count; i++) { + contact c = contact_list[i]; + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::Text(c.id); + ImGui::TableSetColumnIndex(1); ImGui::Text(c.name); + ImGui::TableSetColumnIndex(2); ImGui::Text("%s %s", c.address1, c.address2); + + ImGui::TableSetColumnIndex(3); + + char btn_name[20]; + snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.view"), i); + if (ImGui::Button(btn_name)) { + active_contact = c; + current_view_state = view_state::VIEW; + } + + ImGui::SameLine(); + + snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.change"), i); + if (ImGui::Button(btn_name)) { + active_contact = c; + current_view_state = view_state::EDIT; + } + + ImGui::SameLine(); + + // TODO check to make sure no invoices are connected to this contact. + snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.delete"), i); + if (ImGui::Button(btn_name)) { + selected_for_removal = c; + ImGui::OpenPopup("ConfirmDeletePopup"); + } + } + + if (ImGui::BeginPopupModal("ConfirmDeletePopup", nullptr, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar)) { + ImGui::Text(localize("form.confirmDelete")); + ImGui::Separator(); + + if (ImGui::Button(localize("form.yes"), ImVec2(120, 0))) { + administration_remove_contact(selected_for_removal); + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button(localize("form.no"), ImVec2(120, 0))) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + + ImGui::EndTable(); + } +} + +void ui_draw_contacts() +{ + switch(current_view_state) + { + case view_state::LIST: draw_contact_list(); break; + case view_state::CREATE: draw_contact_form(); break; + case view_state::EDIT: draw_contact_form(); break; + case view_state::VIEW: draw_contact_form(); break; + } +} \ No newline at end of file diff --git a/src/ui/ui_main.cpp b/src/ui/ui_main.cpp new file mode 100644 index 0000000..f6661b8 --- /dev/null +++ b/src/ui/ui_main.cpp @@ -0,0 +1,110 @@ +#include "ui.hpp" +#include "imgui.h" +#include "administration.hpp" +#include "locales.hpp" + +typedef enum +{ + INVOICES = 0, + EXPENSES = 1, + CONTACTS = 2, + REPORT_RESULTS = 3, + REPORT_TAX = 4, + PROJECTS = 5, + + END +} dashboard_view_state; + +static dashboard_view_state dashboard_state = dashboard_view_state::INVOICES; +void (*drawcalls[dashboard_view_state::END])(void) = { + 0, + 0, + ui_draw_contacts, + 0, + 0, + ui_draw_projects, +}; + +void ui_draw_main() +{ + // @localize + if (ImGui::BeginMainMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("Open", "Ctrl+O")) { /* Handle Open */ } + if (ImGui::MenuItem("Save", "Ctrl+S")) { /* Handle Save */ } + + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); + } + + ImGuiIO& io = ImGui::GetIO(); + float menuBarHeight = ImGui::GetFrameHeight(); + float statusBarHeight = 26.0f; + float sidePanelWidth = 120.0f; + ImGui::SetNextWindowPos(ImVec2(0, menuBarHeight)); + ImGui::SetNextWindowSize(ImVec2(sidePanelWidth, io.DisplaySize.y - menuBarHeight - statusBarHeight)); + + // Side panel + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); + ImGui::Begin("SidePanel", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse); + { + // Navigation buttons with custom styling + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); // Transparent background + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); // Reduce spacing between buttons + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10.0f, 0.0f)); + + float buttonWidth = sidePanelWidth; + + if (ImGui::Button(localize("nav.invoices"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::INVOICES; + if (ImGui::Button(localize("nav.expenses"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::EXPENSES; + if (ImGui::Button(localize("nav.contacts"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::CONTACTS; + + static bool reports_opened = false; + if (ImGui::Button(localize("nav.reports"), ImVec2(buttonWidth, 24))) reports_opened = !reports_opened; + if (reports_opened) + { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20.0f, 0.0f)); + if (ImGui::Button(localize("nav.reports.results"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::REPORT_RESULTS; + if (ImGui::Button(localize("nav.reports.tax"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::REPORT_TAX; + ImGui::PopStyleVar(); + } + + if (ImGui::Button(localize("nav.Projects"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::PROJECTS; + + ImGui::PopStyleColor(1); + ImGui::PopStyleVar(3); + } + ImGui::End(); + ImGui::PopStyleVar(); + + ImGui::SetNextWindowPos(ImVec2(sidePanelWidth, menuBarHeight)); + ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x - sidePanelWidth, io.DisplaySize.y - menuBarHeight - statusBarHeight)); + + // Main content + ImGui::Begin("AccountingMainWindow", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse); + if (drawcalls[dashboard_state]) drawcalls[dashboard_state](); + ImGui::End(); + + // Status bar. + ImGui::SetNextWindowPos(ImVec2(0, io.DisplaySize.y - statusBarHeight)); + ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, statusBarHeight)); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 3)); + ImGui::Begin("StatusBar", nullptr, + ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoBringToFrontOnFocus | + ImGuiWindowFlags_NoCollapse); + + ImGui::Text("Working on: %s", administration_get_file_path()); // @localize + + ImGui::End(); + ImGui::PopStyleVar(); +} \ No newline at end of file diff --git a/src/ui/ui_projects.cpp b/src/ui/ui_projects.cpp new file mode 100644 index 0000000..9490254 --- /dev/null +++ b/src/ui/ui_projects.cpp @@ -0,0 +1,173 @@ +#include + +#include "ui.hpp" +#include "imgui.h" +#include "administration.hpp" +#include "locales.hpp" + +static view_state current_view_state = LIST; +static project selected_for_cancellation; + +static project active_project; + +static void draw_project_form() +{ + static const char* selected_country = NULL; + + if (ImGui::Button(localize("form.back"))) { + current_view_state = view_state::LIST; + memset(&active_project, 0, sizeof(project)); + selected_country = 0; + return; + } + ImGui::Spacing(); + + bool viewing_only = (current_view_state == view_state::VIEW); + + ImGui::BeginDisabled(); + + float widthAvailable = ImGui::GetContentRegionAvail().x; + + ImGui::SetNextItemWidth(widthAvailable*0.2f); + ImGui::InputText(localize("contact.form.identifier"), active_project.id, IM_ARRAYSIZE(active_project.id)); + if (!viewing_only) ImGui::EndDisabled(); + + ImGui::SetNextItemWidth(widthAvailable*0.5f); + ImGui::InputTextWithHint(localize("project.form.description"), localize("project.form.description"), active_project.description, IM_ARRAYSIZE(active_project.description)); + ImGui::SameLine();view_draw_required_tag(); + + if (viewing_only) ImGui::EndDisabled(); + + if (!viewing_only) { + bool can_save = strlen(active_project.description) > 0; + + if (!can_save) ImGui::BeginDisabled(); + // Save button + ImGui::Spacing(); + if (ImGui::Button(localize("form.save"))) { + if (current_view_state == view_state::CREATE) + administration_create_project(active_project); + + else if (current_view_state == view_state::EDIT) + administration_update_project(active_project); + + memset(&active_project, 0, sizeof(project)); + current_view_state = view_state::LIST; + selected_country = 0; + } + if (!can_save) ImGui::EndDisabled(); + } + else { + // TODO list invoices connected to project. + } +} + +static void draw_project_list() +{ + const u32 items_per_page = 50; + static s32 current_page = 0; + s32 max_page = (administration_get_project_count() + items_per_page - 1) / items_per_page; + if (max_page == 0) max_page = 1; + + if (ImGui::Button(localize("form.create"))) + { + current_view_state = view_state::CREATE; + memset(&active_project, 0, sizeof(project)); + snprintf(active_project.id, IM_ARRAYSIZE(active_project.id), "P/%d", administration_create_id()); + } + + if (current_page >= max_page-1) current_page = max_page-1; + if (current_page < 0) current_page = 0; + + ImGui::SameLine(); + bool enable_prev = current_page > 0; + if (!enable_prev) ImGui::BeginDisabled(); + if (ImGui::Button("<< Prev") && current_page > 0) current_page--; + if (!enable_prev) ImGui::EndDisabled(); + + ImGui::SameLine(); + ImGui::Text("(%d/%d)", current_page+1, max_page); + + ImGui::SameLine(); + bool enable_next = current_page < max_page-1; + if (!enable_next) ImGui::BeginDisabled(); + if (ImGui::Button("Next >>") && current_page < max_page-1) current_page++; + if (!enable_next) ImGui::EndDisabled(); + + ImGui::Spacing(); + + if (ImGui::BeginTable("TableProjects", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + + ImGui::TableSetupColumn(localize("project.table.identifier"), ImGuiTableColumnFlags_WidthFixed, 80); + ImGui::TableSetupColumn(localize("project.table.status"), ImGuiTableColumnFlags_WidthFixed, 140); + ImGui::TableSetupColumn(localize("project.table.description"), ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 160); + ImGui::TableHeadersRow(); + + project project_list[items_per_page]; + u32 project_count = administration_get_projects(current_page, items_per_page, project_list); + + for (u32 i = 0; i < project_count; i++) { + project c = project_list[i]; + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::Text(c.id); + ImGui::TableSetColumnIndex(1); ImGui::Text(localize(administration_project_get_status_string(c))); + ImGui::TableSetColumnIndex(2); ImGui::Text(c.description); + + ImGui::TableSetColumnIndex(3); + + char btn_name[20]; + snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.view"), i); + if (ImGui::Button(btn_name)) { + active_project = c; + current_view_state = view_state::VIEW; + } + + if (c.state == project_state::RUNNING) + { + ImGui::SameLine(); + snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.change"), i); + if (ImGui::Button(btn_name)) { + active_project = c; + current_view_state = view_state::EDIT; + } + + ImGui::SameLine(); + snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.cancel"), i); + if (ImGui::Button(btn_name)) { + selected_for_cancellation = c; + ImGui::OpenPopup("ConfirmCancelProject"); + } + } + } + + if (ImGui::BeginPopupModal("ConfirmCancelProject", nullptr, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar)) { + ImGui::Text(localize("form.confirmCancelProject")); + ImGui::Separator(); + + if (ImGui::Button(localize("form.yes"), ImVec2(120, 0))) { + administration_cancel_project(selected_for_cancellation); + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button(localize("form.no"), ImVec2(120, 0))) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + + ImGui::EndTable(); + } +} + +void ui_draw_projects() +{ + switch(current_view_state) + { + case view_state::LIST: draw_project_list(); break; + case view_state::CREATE: draw_project_form(); break; + case view_state::EDIT: draw_project_form(); break; + case view_state::VIEW: draw_project_form(); break; + } +} \ No newline at end of file diff --git a/src/views/contacts.cpp b/src/views/contacts.cpp deleted file mode 100644 index 31f95e3..0000000 --- a/src/views/contacts.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include - -#include "views.hpp" -#include "imgui.h" -#include "../administration.hpp" -#include "../locales/locales.hpp" - -static view_state current_view_state = LIST; -static contact selected_for_removal; - -static contact active_contact; - -static void draw_contact_form() -{ - static const char* selected_country = NULL; - - if (ImGui::Button(localize("form.back"))) { - current_view_state = view_state::LIST; - memset(&active_contact, 0, sizeof(contact)); - selected_country = 0; - return; - } - ImGui::Spacing(); - - bool viewing_only = (current_view_state == view_state::VIEW); - - ImGui::BeginDisabled(); - - float widthAvailable = ImGui::GetContentRegionAvail().x; - - ImGui::SetNextItemWidth(widthAvailable*0.2f); - ImGui::InputText(localize("contact.form.identifier"), active_contact.id, IM_ARRAYSIZE(active_contact.id)); - if (!viewing_only) ImGui::EndDisabled(); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.fullname"), localize("contact.form.fullname"), active_contact.name, IM_ARRAYSIZE(active_contact.name)); - ImGui::SameLine();view_draw_required_tag(); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.address1"), localize("contact.form.address1"), active_contact.address1, IM_ARRAYSIZE(active_contact.address1)); - ImGui::SameLine();view_draw_required_tag(); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.address2"), localize("contact.form.address2"), active_contact.address2, IM_ARRAYSIZE(active_contact.address2)); - ImGui::SameLine();view_draw_required_tag(); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - - const char* countries[] = { localize("country.AT"),localize("country.BE"),localize("country.BG"),localize("country.HR"),localize("country.CY"),localize("country.CZ"),localize("country.DK"),localize("country.EE"),localize("country.FI"),localize("country.FR"),localize("country.DE"),localize("country.GR"),localize("country.HU"),localize("country.IE"),localize("country.IT"),localize("country.LV"),localize("country.LT"),localize("country.LU"),localize("country.MT"),localize("country.NL"),localize("country.PL"),localize("country.PT"),localize("country.RO"),localize("country.SK"),localize("country.SI"),localize("country.ES"),localize("country.SE") }; - s32 country_count = sizeof(countries) / sizeof(countries[0]); - if (selected_country == 0) { - for (int i = 0; i < country_count; i++) - { - if (strcmp(countries[i], active_contact.country) == 0) - { - selected_country = countries[i]; - break; - } - } - } - - if (ImGui::BeginCombo(localize("contact.form.country"), selected_country)) - { - for (int n = 0; n < IM_ARRAYSIZE(countries); n++) - { - bool is_selected = (selected_country == countries[n]); - if (ImGui::Selectable(countries[n], is_selected)) - selected_country = countries[n]; - } - ImGui::EndCombo(); - } - if (selected_country) { - strncpy(active_contact.country, selected_country, IM_ARRAYSIZE(active_contact.country)); - } - ImGui::SameLine();view_draw_required_tag(); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.taxnumber"), localize("contact.form.taxnumber"), active_contact.taxid, IM_ARRAYSIZE(active_contact.taxid)); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.businessnumber"), localize("contact.form.businessnumber"), active_contact.businessid, IM_ARRAYSIZE(active_contact.businessid)); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.email"), localize("contact.form.email"), active_contact.email, IM_ARRAYSIZE(active_contact.email)); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.phonenumber"), localize("contact.form.phonenumber"), active_contact.phone_number, IM_ARRAYSIZE(active_contact.phone_number)); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.bankaccount"), localize("contact.form.bankaccount"), active_contact.bank_account, IM_ARRAYSIZE(active_contact.bank_account)); - - if (viewing_only) ImGui::EndDisabled(); - - if (!viewing_only) { - bool can_save = strlen(active_contact.name) > 0 && strlen(active_contact.address1) > 0 && - strlen(active_contact.address2) > 0 && strlen(active_contact.country) > 0; - - if (!can_save) ImGui::BeginDisabled(); - // Save button - ImGui::Spacing(); - if (ImGui::Button(localize("form.save"))) { - if (current_view_state == view_state::CREATE) - administration_create_contact(active_contact); - - else if (current_view_state == view_state::EDIT) - administration_update_contact(active_contact); - - memset(&active_contact, 0, sizeof(contact)); - current_view_state = view_state::LIST; - selected_country = 0; - } - if (!can_save) ImGui::EndDisabled(); - } - else { - // TODO list invoices connected to contact. - } -} - -static void draw_contact_list() -{ - const u32 items_per_page = 50; - static s32 current_page = 0; - s32 max_page = (administration_get_contact_count() + items_per_page - 1) / items_per_page; - if (max_page == 0) max_page = 1; - - if (ImGui::Button(localize("form.create"))) - { - current_view_state = view_state::CREATE; - memset(&active_contact, 0, sizeof(contact)); - snprintf(active_contact.id, IM_ARRAYSIZE(active_contact.id), "C/%d", administration_create_id()); - } - - if (current_page >= max_page-1) current_page = max_page-1; - if (current_page < 0) current_page = 0; - - ImGui::SameLine(); - bool enable_prev = current_page > 0; - if (!enable_prev) ImGui::BeginDisabled(); - if (ImGui::Button("<< Prev") && current_page > 0) current_page--; - if (!enable_prev) ImGui::EndDisabled(); - - ImGui::SameLine(); - ImGui::Text("(%d/%d)", current_page+1, max_page); - - ImGui::SameLine(); - bool enable_next = current_page < max_page-1; - if (!enable_next) ImGui::BeginDisabled(); - if (ImGui::Button("Next >>") && current_page < max_page-1) current_page++; - if (!enable_next) ImGui::EndDisabled(); - - ImGui::Spacing(); - - if (ImGui::BeginTable("TableContacts", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { - - ImGui::TableSetupColumn(localize("contact.table.identifier"), ImGuiTableColumnFlags_WidthFixed, 80); - ImGui::TableSetupColumn(localize("contact.table.name"), ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn(localize("contact.table.address"), ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 160); - ImGui::TableHeadersRow(); - - contact contact_list[items_per_page]; - u32 contact_count = administration_get_contacts(current_page, items_per_page, contact_list); - - for (u32 i = 0; i < contact_count; i++) { - contact c = contact_list[i]; - - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); ImGui::Text(c.id); - ImGui::TableSetColumnIndex(1); ImGui::Text(c.name); - ImGui::TableSetColumnIndex(2); ImGui::Text("%s %s", c.address1, c.address2); - - ImGui::TableSetColumnIndex(3); - - char btn_name[20]; - sprintf(btn_name, "%s##%d", localize("form.view"), i); - if (ImGui::Button(btn_name)) { - active_contact = c; - current_view_state = view_state::VIEW; - } - - ImGui::SameLine(); - - sprintf(btn_name, "%s##%d", localize("form.change"), i); - if (ImGui::Button(btn_name)) { - active_contact = c; - current_view_state = view_state::EDIT; - } - - ImGui::SameLine(); - - // TODO check to make sure no invoices are connected to this contact. - sprintf(btn_name, "%s##%d", localize("form.delete"), i); - if (ImGui::Button(btn_name)) { - selected_for_removal = c; - ImGui::OpenPopup("ConfirmDeletePopup"); - } - } - - if (ImGui::BeginPopupModal("ConfirmDeletePopup", nullptr, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar)) { - ImGui::Text(localize("form.confirmDelete")); - ImGui::Separator(); - - if (ImGui::Button(localize("form.yes"), ImVec2(120, 0))) { - administration_remove_contact(selected_for_removal); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button(localize("form.no"), ImVec2(120, 0))) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - } - - ImGui::EndTable(); - } -} - -void views_draw_contacts() -{ - switch(current_view_state) - { - case view_state::LIST: draw_contact_list(); break; - case view_state::CREATE: draw_contact_form(); break; - case view_state::EDIT: draw_contact_form(); break; - case view_state::VIEW: draw_contact_form(); break; - } -} \ No newline at end of file diff --git a/src/views/dashboard.cpp b/src/views/dashboard.cpp deleted file mode 100644 index dcfd002..0000000 --- a/src/views/dashboard.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "views.hpp" -#include "imgui.h" -#include "../administration.hpp" -#include "../locales/locales.hpp" - -typedef enum -{ - INVOICES = 0, - EXPENSES = 1, - CONTACTS = 2, - REPORT_RESULTS = 3, - REPORT_TAX = 4, - PROJECTS = 5, - - END -} dashboard_view_state; - -static dashboard_view_state dashboard_state = dashboard_view_state::INVOICES; -void (*drawcalls[dashboard_view_state::END])(void) = { - 0, - 0, - views_draw_contacts, - 0, - 0, - views_draw_projects, -}; - -void views_draw_dashboard() -{ - // @localize - if (ImGui::BeginMainMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - if (ImGui::MenuItem("Open", "Ctrl+O")) { /* Handle Open */ } - if (ImGui::MenuItem("Save", "Ctrl+S")) { /* Handle Save */ } - - ImGui::EndMenu(); - } - ImGui::EndMainMenuBar(); - } - - ImGuiIO& io = ImGui::GetIO(); - float menuBarHeight = ImGui::GetFrameHeight(); - float statusBarHeight = 26.0f; - float sidePanelWidth = 120.0f; - ImGui::SetNextWindowPos(ImVec2(0, menuBarHeight)); - ImGui::SetNextWindowSize(ImVec2(sidePanelWidth, io.DisplaySize.y - menuBarHeight - statusBarHeight)); - - // Side panel - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - ImGui::Begin("SidePanel", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse); - { - // Navigation buttons with custom styling - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); // Transparent background - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f)); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); // Reduce spacing between buttons - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10.0f, 0.0f)); - - float buttonWidth = sidePanelWidth; - - if (ImGui::Button(localize("nav.invoices"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::INVOICES; - if (ImGui::Button(localize("nav.expenses"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::EXPENSES; - if (ImGui::Button(localize("nav.contacts"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::CONTACTS; - - static bool reports_opened = false; - if (ImGui::Button(localize("nav.reports"), ImVec2(buttonWidth, 24))) reports_opened = !reports_opened; - if (reports_opened) - { - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20.0f, 0.0f)); - if (ImGui::Button(localize("nav.reports.results"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::REPORT_RESULTS; - if (ImGui::Button(localize("nav.reports.tax"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::REPORT_TAX; - ImGui::PopStyleVar(); - } - - if (ImGui::Button(localize("nav.Projects"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::PROJECTS; - - ImGui::PopStyleColor(1); - ImGui::PopStyleVar(3); - } - ImGui::End(); - ImGui::PopStyleVar(); - - ImGui::SetNextWindowPos(ImVec2(sidePanelWidth, menuBarHeight)); - ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x - sidePanelWidth, io.DisplaySize.y - menuBarHeight - statusBarHeight)); - - // Main content - ImGui::Begin("AccountingMainWindow", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse); - if (drawcalls[dashboard_state]) drawcalls[dashboard_state](); - ImGui::End(); - - // Status bar. - ImGui::SetNextWindowPos(ImVec2(0, io.DisplaySize.y - statusBarHeight)); - ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, statusBarHeight)); - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 3)); - ImGui::Begin("StatusBar", nullptr, - ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_NoBringToFrontOnFocus | - ImGuiWindowFlags_NoCollapse); - - ImGui::Text("Working on: %s", administration_get_file_path()); // @localize - - ImGui::End(); - ImGui::PopStyleVar(); -} \ No newline at end of file diff --git a/src/views/projects.cpp b/src/views/projects.cpp deleted file mode 100644 index 14f99c9..0000000 --- a/src/views/projects.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include - -#include "views.hpp" -#include "imgui.h" -#include "../administration.hpp" -#include "../locales/locales.hpp" - -static view_state current_view_state = LIST; -static project selected_for_cancellation; - -static project active_project; - -static void draw_project_form() -{ - static const char* selected_country = NULL; - - if (ImGui::Button(localize("form.back"))) { - current_view_state = view_state::LIST; - memset(&active_project, 0, sizeof(project)); - selected_country = 0; - return; - } - ImGui::Spacing(); - - bool viewing_only = (current_view_state == view_state::VIEW); - - ImGui::BeginDisabled(); - - float widthAvailable = ImGui::GetContentRegionAvail().x; - - ImGui::SetNextItemWidth(widthAvailable*0.2f); - ImGui::InputText(localize("contact.form.identifier"), active_project.id, IM_ARRAYSIZE(active_project.id)); - if (!viewing_only) ImGui::EndDisabled(); - - ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("project.form.description"), localize("project.form.description"), active_project.description, IM_ARRAYSIZE(active_project.description)); - ImGui::SameLine();view_draw_required_tag(); - - if (viewing_only) ImGui::EndDisabled(); - - if (!viewing_only) { - bool can_save = strlen(active_project.description) > 0; - - if (!can_save) ImGui::BeginDisabled(); - // Save button - ImGui::Spacing(); - if (ImGui::Button(localize("form.save"))) { - if (current_view_state == view_state::CREATE) - administration_create_project(active_project); - - else if (current_view_state == view_state::EDIT) - administration_update_project(active_project); - - memset(&active_project, 0, sizeof(project)); - current_view_state = view_state::LIST; - selected_country = 0; - } - if (!can_save) ImGui::EndDisabled(); - } - else { - // TODO list invoices connected to project. - } -} - -static void draw_project_list() -{ - const u32 items_per_page = 50; - static s32 current_page = 0; - s32 max_page = (administration_get_project_count() + items_per_page - 1) / items_per_page; - if (max_page == 0) max_page = 1; - - if (ImGui::Button(localize("form.create"))) - { - current_view_state = view_state::CREATE; - memset(&active_project, 0, sizeof(project)); - snprintf(active_project.id, IM_ARRAYSIZE(active_project.id), "P/%d", administration_create_id()); - } - - if (current_page >= max_page-1) current_page = max_page-1; - if (current_page < 0) current_page = 0; - - ImGui::SameLine(); - bool enable_prev = current_page > 0; - if (!enable_prev) ImGui::BeginDisabled(); - if (ImGui::Button("<< Prev") && current_page > 0) current_page--; - if (!enable_prev) ImGui::EndDisabled(); - - ImGui::SameLine(); - ImGui::Text("(%d/%d)", current_page+1, max_page); - - ImGui::SameLine(); - bool enable_next = current_page < max_page-1; - if (!enable_next) ImGui::BeginDisabled(); - if (ImGui::Button("Next >>") && current_page < max_page-1) current_page++; - if (!enable_next) ImGui::EndDisabled(); - - ImGui::Spacing(); - - if (ImGui::BeginTable("TableProjects", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { - - ImGui::TableSetupColumn(localize("project.table.identifier"), ImGuiTableColumnFlags_WidthFixed, 80); - ImGui::TableSetupColumn(localize("project.table.status"), ImGuiTableColumnFlags_WidthFixed, 140); - ImGui::TableSetupColumn(localize("project.table.description"), ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 160); - ImGui::TableHeadersRow(); - - project project_list[items_per_page]; - u32 project_count = administration_get_projects(current_page, items_per_page, project_list); - - for (u32 i = 0; i < project_count; i++) { - project c = project_list[i]; - - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); ImGui::Text(c.id); - ImGui::TableSetColumnIndex(1); ImGui::Text(localize(administration_project_get_status_string(c))); - ImGui::TableSetColumnIndex(2); ImGui::Text(c.description); - - ImGui::TableSetColumnIndex(3); - - char btn_name[20]; - sprintf(btn_name, "%s##%d", localize("form.view"), i); - if (ImGui::Button(btn_name)) { - active_project = c; - current_view_state = view_state::VIEW; - } - - if (c.state == project_state::RUNNING) - { - ImGui::SameLine(); - sprintf(btn_name, "%s##%d", localize("form.change"), i); - if (ImGui::Button(btn_name)) { - active_project = c; - current_view_state = view_state::EDIT; - } - - ImGui::SameLine(); - sprintf(btn_name, "%s##%d", localize("form.cancel"), i); - if (ImGui::Button(btn_name)) { - selected_for_cancellation = c; - ImGui::OpenPopup("ConfirmCancelProject"); - } - } - } - - if (ImGui::BeginPopupModal("ConfirmCancelProject", nullptr, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar)) { - ImGui::Text(localize("form.confirmCancelProject")); - ImGui::Separator(); - - if (ImGui::Button(localize("form.yes"), ImVec2(120, 0))) { - administration_cancel_project(selected_for_cancellation); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button(localize("form.no"), ImVec2(120, 0))) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - } - - ImGui::EndTable(); - } -} - -void views_draw_projects() -{ - switch(current_view_state) - { - case view_state::LIST: draw_project_list(); break; - case view_state::CREATE: draw_project_form(); break; - case view_state::EDIT: draw_project_form(); break; - case view_state::VIEW: draw_project_form(); break; - } -} \ No newline at end of file diff --git a/src/views/views.cpp b/src/views/views.cpp deleted file mode 100644 index 47eff34..0000000 --- a/src/views/views.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "views.hpp" -#include "imgui.h" -#include "../locales/locales.hpp" - -void view_draw_required_tag() -{ - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - - const char* text = localize("form.required"); - ImVec2 text_pos = ImGui::GetCursorScreenPos(); - ImVec2 text_size = ImGui::CalcTextSize(text); - text_pos.y += text_size.y/4.0f; - - ImVec4 bg_color = ImVec4(0.9f, 0.235f, 0.235f, 0.4f); // Red background - ImVec4 text_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // White text - float rounding = 2.0f; - float padding = 2.0f; - - // Background rectangle - ImVec2 bg_min = ImVec2(text_pos.x - padding, text_pos.y - padding); - ImVec2 bg_max = ImVec2(text_pos.x + text_size.x + padding, text_pos.y + text_size.y + padding); - draw_list->AddRectFilled(bg_min, bg_max, ImColor(bg_color), rounding); - - // Foreground text - ImGui::PushStyleColor(ImGuiCol_Text, text_color); - ImGui::TextUnformatted(text); - ImGui::PopStyleColor(); -} \ No newline at end of file diff --git a/src/views/views.hpp b/src/views/views.hpp deleted file mode 100644 index f47bf3a..0000000 --- a/src/views/views.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -typedef enum -{ - LIST, - EDIT, - CREATE, - VIEW, -} view_state; - -void view_draw_required_tag(); - -void views_draw_dashboard(); -void views_draw_contacts(); -void views_draw_projects(); \ No newline at end of file -- cgit v1.2.3-70-g09d2