summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAldrik Ramaekers <aldrikboy@gmail.com>2025-08-15 17:28:00 +0200
committerAldrik Ramaekers <aldrikboy@gmail.com>2025-08-15 17:28:00 +0200
commitf67e92f55b6223f2806c3d5ef1cbe2a638920562 (patch)
treef567321e40d03e6f1e6d31338ef3db2eff988e91 /src
parent572caa74ed824fefa02eb81adc7639a783f243c7 (diff)
working on invoice form
Diffstat (limited to 'src')
-rw-r--r--src/administration.cpp14
-rw-r--r--src/ui/helpers.cpp3
-rw-r--r--src/ui/ui_contacts.cpp108
-rw-r--r--src/ui/ui_invoices.cpp135
4 files changed, 191 insertions, 69 deletions
diff --git a/src/administration.cpp b/src/administration.cpp
index a34ece8..56d8663 100644
--- a/src/administration.cpp
+++ b/src/administration.cpp
@@ -408,6 +408,20 @@ u32 administration_get_project_count()
return list_size(&g_administration.projects);
}
+u32 administration_get_all_projects(project* buffer)
+{
+ u32 write_cursor = 0;
+
+ list_iterator_start(&g_administration.projects);
+ while (list_iterator_hasnext(&g_administration.projects)) {
+ project c = *(project *)list_iterator_next(&g_administration.projects);
+ buffer[write_cursor++] = c;
+ }
+ list_iterator_stop(&g_administration.projects);
+
+ return write_cursor;
+}
+
u32 administration_get_projects(u32 page_index, u32 page_size, project* buffer)
{
assert(buffer);
diff --git a/src/ui/helpers.cpp b/src/ui/helpers.cpp
index 4c6647e..0cce207 100644
--- a/src/ui/helpers.cpp
+++ b/src/ui/helpers.cpp
@@ -110,5 +110,4 @@ int ui_helper_TextInputWithAutocomplete(const char* label, const char* hint, cha
}
}
return result;
-}
-
+} \ No newline at end of file
diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp
index d57776e..7d03ba6 100644
--- a/src/ui/ui_contacts.cpp
+++ b/src/ui/ui_contacts.cpp
@@ -11,6 +11,63 @@ static contact selected_for_removal;
static contact active_contact;
+void ui_draw_address_form(address* buffer)
+{
+ const char* selected_country = NULL;
+ float widthAvailable = ImGui::GetContentRegionAvail().x;
+
+ char id[128];
+
+ ImGui::SetNextItemWidth(widthAvailable*0.5f);
+ snprintf(id, sizeof(id), "%s##%p", localize("contact.form.address1"), buffer);
+ ImGui::InputTextWithHint(id, localize("contact.form.address1"), buffer->address1, IM_ARRAYSIZE(buffer->address1));
+ ImGui::SameLine();ui_helper_draw_required_tag();
+
+ ImGui::SetNextItemWidth(widthAvailable*0.5f);
+ snprintf(id, sizeof(id), "%s##%p", localize("contact.form.address2"), buffer);
+ ImGui::InputTextWithHint(id, localize("contact.form.address2"), buffer->address2, IM_ARRAYSIZE(buffer->address2));
+ ImGui::SameLine();ui_helper_draw_required_tag();
+
+ // 5. Country dropdown.
+ 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") };
+ const char* country_codes[] = {
+ "AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR",
+ "DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL",
+ "PL", "PT", "RO", "SK", "SI", "ES", "SE"
+ };
+ s32 country_count = sizeof(countries) / sizeof(countries[0]);
+ if (selected_country == 0) {
+ for (int i = 0; i < country_count; i++)
+ {
+ if (strcmp(country_codes[i], buffer->country_code) == 0)
+ {
+ selected_country = countries[i];
+ break;
+ }
+ }
+ }
+
+ int selected_country_index = -1;
+ snprintf(id, sizeof(id), "%s##%p", localize("contact.form.country"), buffer);
+ if (ImGui::BeginCombo(id, 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];
+ selected_country_index = n;
+ }
+ }
+ ImGui::EndCombo();
+ }
+ if (selected_country_index != -1) {
+ strops_copy(buffer->country_code, country_codes[selected_country_index], IM_ARRAYSIZE(buffer->country_code));
+ }
+ ImGui::SameLine();ui_helper_draw_required_tag();
+}
+
void ui_setup_contacts()
{
current_view_state = view_state::LIST;
@@ -20,8 +77,6 @@ void ui_setup_contacts()
void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_autocomplete = false, bool* on_autocomplete = 0)
{
- const char* selected_country = NULL;
-
ImGui::Spacing();
float widthAvailable = ImGui::GetContentRegionAvail().x;
@@ -60,53 +115,8 @@ void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_
else ImGui::InputTextWithHint(localize("contact.form.fullname"), localize("contact.form.fullname"), buffer->name, IM_ARRAYSIZE(buffer->name));
ImGui::SameLine();ui_helper_draw_required_tag();
- // 3. Address line 1
- ImGui::SetNextItemWidth(widthAvailable*0.5f);
- ImGui::InputTextWithHint(localize("contact.form.address1"), localize("contact.form.address1"), buffer->address.address1, IM_ARRAYSIZE(buffer->address.address1));
- ImGui::SameLine();ui_helper_draw_required_tag();
-
- // 4. Address line 2
- ImGui::SetNextItemWidth(widthAvailable*0.5f);
- ImGui::InputTextWithHint(localize("contact.form.address2"), localize("contact.form.address2"), buffer->address.address2, IM_ARRAYSIZE(buffer->address.address2));
- ImGui::SameLine();ui_helper_draw_required_tag();
-
- // 5. Country dropdown.
- 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") };
- const char* country_codes[] = {
- "AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR",
- "DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL",
- "PL", "PT", "RO", "SK", "SI", "ES", "SE"
- };
- s32 country_count = sizeof(countries) / sizeof(countries[0]);
- if (selected_country == 0) {
- for (int i = 0; i < country_count; i++)
- {
- if (strcmp(country_codes[i], buffer->address.country_code) == 0)
- {
- selected_country = countries[i];
- break;
- }
- }
- }
-
- int selected_country_index = -1;
- 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];
- selected_country_index = n;
- }
- }
- ImGui::EndCombo();
- }
- if (selected_country_index != -1) {
- strops_copy(buffer->address.country_code, country_codes[selected_country_index], IM_ARRAYSIZE(buffer->address.country_code));
- }
- ImGui::SameLine();ui_helper_draw_required_tag();
+ // 3. Address line 1, 4. address line 2, 5. country
+ ui_draw_address_form(&buffer->address);
// 6. Contact type dropdown.
ImGui::SetNextItemWidth(widthAvailable*0.5f);
diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp
index 8ee099c..2b5a834 100644
--- a/src/ui/ui_invoices.cpp
+++ b/src/ui/ui_invoices.cpp
@@ -1,7 +1,9 @@
+#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#include "ImGuiDatePicker/ImGuiDatePicker.hpp"
+//#include "tinyfiledialogs/tinyfiledialogs.h"
#include "strops.hpp"
#include "ui.hpp"
@@ -9,8 +11,10 @@
#include "administration.hpp"
#include "locales.hpp"
+void ui_draw_address_form(address* buffer);
+
static view_state current_view_state = view_state::LIST;
-static invoice active_invoice;
+static invoice active_invoice = {0};
void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_autocomplete = false, bool* on_autocomplete = 0);
@@ -20,6 +24,88 @@ void ui_setup_invoices()
active_invoice = administration_create_empty_invoice();
}
+void draw_costcenter_selector(char* costcenter_id)
+{
+ cost_center* selected_costcenter = NULL;
+
+ u32 costcenter_count = administration_get_cost_center_count();
+ cost_center* buffer = (cost_center*) malloc(sizeof(cost_center) * costcenter_count);
+ costcenter_count = administration_get_cost_centers(buffer);
+
+ // Select cost center by given id.
+ if (strlen(costcenter_id) > 0)
+ {
+ for (u32 i = 0; i < costcenter_count; i++)
+ {
+ if (strcmp(buffer[i].id, costcenter_id) == 0)
+ {
+ selected_costcenter = &buffer[i];
+ break;
+ }
+ }
+ }
+
+ int selected_costcenter_index = -1;
+ if (ImGui::BeginCombo("Cost center", selected_costcenter == NULL ? NULL : localize(selected_costcenter->description)))
+ {
+ for (u32 n = 0; n < costcenter_count; n++)
+ {
+ bool is_selected = selected_costcenter && strcmp(selected_costcenter->id, buffer[n].id) == 0;
+ if (ImGui::Selectable(localize(buffer[n].description), is_selected)) {
+ selected_costcenter_index = n;
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ if (selected_costcenter_index != -1) {
+ strops_copy(costcenter_id, buffer[selected_costcenter_index].id, 16);
+ }
+
+ free(buffer);
+}
+
+void draw_project_selector(char* project_id)
+{
+ project* selected_project = NULL;
+
+ u32 project_count = administration_get_project_count();
+ project* buffer = (project*) malloc(sizeof(project) * project_count);
+ project_count = administration_get_all_projects(buffer);
+
+ // Select project by given id.
+ if (strlen(project_id) > 0)
+ {
+ for (u32 i = 0; i < project_count; i++)
+ {
+ if (strcmp(buffer[i].id, project_id) == 0)
+ {
+ selected_project = &buffer[i];
+ break;
+ }
+ }
+ }
+
+ int selected_project_index = -1;
+ if (ImGui::BeginCombo("Project", selected_project == NULL ? NULL : selected_project->description))
+ {
+ for (u32 n = 0; n < project_count; n++)
+ {
+ bool is_selected = selected_project && strcmp(selected_project->id, buffer[n].id) == 0;
+ if (ImGui::Selectable(buffer[n].description, is_selected)) {
+ selected_project_index = n;
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ if (selected_project_index != -1) {
+ strops_copy(project_id, buffer[selected_project_index].id, 16);
+ }
+
+ free(buffer);
+}
+
void draw_invoice_form(invoice* buffer, bool viewing_only = false)
{
//float widthAvailable = ImGui::GetContentRegionAvail().x;
@@ -36,20 +122,7 @@ void draw_invoice_form(invoice* buffer, bool viewing_only = false)
// 3. Supplier (you)
ImGui::Text("Supplier: %s", buffer->supplier.name);
- ImGui::Separator();
-
- // 4. Customer information
- ImGui::Text("Customer information");
- bool on_autocomplete;
- draw_contact_form_ex(&buffer->customer, false, true, &on_autocomplete);
-
- if (on_autocomplete) {
- strops_copy(buffer->customer_id, buffer->customer.id, sizeof(buffer->customer_id));
- }
-
- ImGui::Separator();
-
- // 5. Invoice issued at
+ // 6. Invoice issued at
ImGui::BeginDisabled();
tm issued_at_date = *gmtime(&buffer->issued_at);
if (ImGui::DatePicker("##issuedAt", issued_at_date))
@@ -60,7 +133,7 @@ void draw_invoice_form(invoice* buffer, bool viewing_only = false)
ImGui::Text("Invoice issued at");
ImGui::EndDisabled();
- // 6. Invoice expires at
+ // 7. Invoice expires at
ImGui::BeginDisabled();
tm expires_at_date = *gmtime(&buffer->expires_at);
if (ImGui::DatePicker("##expiresAt", expires_at_date))
@@ -71,7 +144,7 @@ void draw_invoice_form(invoice* buffer, bool viewing_only = false)
ImGui::Text("Invoice expires at");
ImGui::EndDisabled();
- // 7. Product/service delivered at
+ // 8. Product/service delivered at
tm delivered_at_date = *gmtime(&buffer->delivered_at);
if (ImGui::DatePicker("##deliveredAt", delivered_at_date))
{
@@ -80,11 +153,37 @@ void draw_invoice_form(invoice* buffer, bool viewing_only = false)
ImGui::SameLine();
ImGui::Text("Product/service delivered at");
+ ImGui::Separator();
+
+ // 4. Customer information
+ ImGui::Text("Billing information");
+ bool on_autocomplete;
+ draw_contact_form_ex(&buffer->customer, false, true, &on_autocomplete);
+
+ if (on_autocomplete) {
+ strops_copy(buffer->customer_id, buffer->customer.id, sizeof(buffer->customer_id));
+ }
+
+ // 5. (optional) shipping address.
+ static bool shipping_is_billing_addr = true;
+ ImGui::Checkbox("Shipping information is billing information", &shipping_is_billing_addr);
+ if (!shipping_is_billing_addr) {
+ ImGui::Spacing();
+ ImGui::Text("Shipping information");
+ ui_draw_address_form(&buffer->shipping_address);
+ }
+ ImGui::Separator();
+
+ // 9. Project selection
+ draw_project_selector(buffer->project_id);
+
+ // 10. Cost center selection
+ draw_costcenter_selector(buffer->cost_center_id);
+
//ImGui::SetNextItemWidth(widthAvailable*0.5f);
//ImGui::InputTextWithHint("Invoice number", "Invoice number", buffer->sequential_number, IM_ARRAYSIZE(buffer->sequential_number));
//ImGui::SameLine();ui_helper_draw_required_tag();
-
if (viewing_only) ImGui::EndDisabled();
}