summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NOTES.md27
-rw-r--r--include/administration.hpp77
-rw-r--r--include/locales.hpp3
-rw-r--r--include/ui.hpp12
-rw-r--r--run.bat22
-rw-r--r--src/administration.cpp162
-rw-r--r--src/locales.cpp3
-rw-r--r--src/ui/helpers.cpp39
-rw-r--r--src/ui/ui_contacts.cpp92
-rw-r--r--src/ui/ui_invoices.cpp15
-rw-r--r--src/ui/ui_main.cpp34
-rw-r--r--src/ui/ui_projects.cpp10
-rw-r--r--src/ui/ui_settings.cpp35
13 files changed, 464 insertions, 67 deletions
diff --git a/NOTES.md b/NOTES.md
index 2549692..8cb6521 100644
--- a/NOTES.md
+++ b/NOTES.md
@@ -46,6 +46,7 @@ administration.money/
| contacts `list` | List of contacts |
| projects `list` | List of projects |
| invoices `list` | List of invoices |
+| tax brackets `list` | List of available tax brackets |
| AI service | Which AI service to use |
| AI key | API key for selected AI service |
| email service | Which email service to use |
@@ -58,6 +59,7 @@ administration.money/
| address line 1 `required` | Address |
| address line 2 `required` | Zip, place |
| country `required` | Country |
+| type `required` | Contact type, `business` or `consumer` |
| tax number | Tax identification number |
| business number | Business number |
| email | Email address |
@@ -68,7 +70,6 @@ administration.money/
|-|-|
| id `auto` | reference id `I/[id]` |
| sequential number `auto` | Generated sequential invoice number |
-| is outgoing `required` | incoming or outgoing invoice |
| customer `required` | Customer contact information, stored as reference `C/[id]` |
| supplier `required` | Supplier contact information, stored as reference `C/[id]` |
| issue at `required` | Date when invoice was issued |
@@ -77,13 +78,15 @@ administration.money/
| document `required` | Document associated with invoice, stored as filename |
| billing items `required` `list` | List of billed items |
| project `required` | Project, stored as reference `P/[id]` |
-| category `required` | Expense category (incomming invoices only) |
+| cost center id `required` | Cost center, stored as reference `E/[id]` (incomming invoices only) |
+| cost unit id `required` | Cost unit, stored as reference `U/[id]` (incomming invoices only) |
| total `required` | Total amount billed |
| tax `required` | Total tax billed |
| net `required` | Total amount excl. tax |
-| status `required` | Payment status `paid` `expired` `cancelled` `refunded` |
+| status `required` | Payment status `paid` `expired` `cancelled` `refunded`, `corrected` |
| shipping address line 1 `required` | Address |
-| shipping address line 2 `required` | Zip, place, country |
+| shipping address line 2 `required` | Zip, place |
+| country `required` | Country |
| currency `required` | Currency used for billing |
| keep untill `required` | Date untill invoice needs to be stored legally |
| payment on account date | If advance payment received and differs from invoice date (Ireland only) |
@@ -95,7 +98,7 @@ administration.money/
| id `auto` | reference id `B/[id]` |
| invoice `auto` | reference to invoice `I/[id]` |
| description `required` | Description of billed item |
-| tax percentage `required` | Tax percentage (e.g. 0%, 21%, exempt, reversed) |
+| tax bracket `required` | Tax bracket (e.g. 0%, 21%, exempt, reversed) |
| tax section `required` | Tax section (e.g. 1a upto 4b in The Netherlands) |
| amount `required` | Amount of items |
| net per item `required` | Price per item excl. tax |
@@ -113,4 +116,16 @@ administration.money/
| description `required` | Description of project |
| start date `required` | Project started at date |
| status `required` | Status of project `running` `paused` `cancelled` |
-| end date | Project cancelled at date | \ No newline at end of file
+| end date | Project cancelled at date |
+
+| Cost center||
+|-|-|
+| id `auto` | reference id `E/[id]` |
+| code `required` | Code of cost center |
+| description `required` | Description of cost center |
+
+| Cost unit||
+|-|-|
+| id `auto` | reference id `U/[id]` |
+| code `required` | Code of cost center |
+| description `required` | Description of cost center | \ No newline at end of file
diff --git a/include/administration.hpp b/include/administration.hpp
index 9506246..79ca6ab 100644
--- a/include/administration.hpp
+++ b/include/administration.hpp
@@ -5,11 +5,23 @@
typedef struct
{
- char id[16];
- char name[64];
+ char country_code[3];
+ float rate;
+ char description[16];
+} country_tax_bracket;
+
+typedef struct
+{
char address1[128];
char address2[128];
char country[128];
+} address;
+
+typedef struct
+{
+ char id[16];
+ char name[64];
+ address address;
char taxid[32];
char businessid[32];
char email[64];
@@ -33,16 +45,70 @@ typedef struct
time_t end_date;
} project;
+typedef enum
+{
+ INVOICE_PAID,
+ INVOICE_EXPIRED,
+ INVOICE_CANCELLED,
+ INVOICE_REFUNDED,
+ INVOICE_CORRECTED,
+} invoice_status;
+
+typedef struct
+{
+ char id[16];
+ char invoice_id[16];
+ char description[128];
+ country_tax_bracket tax_bracket;
+ char tax_section[16];
+ s32 amount;
+ s32 net_per_item;
+ s32 net;
+ s32 discount;
+ s32 tax;
+ bool is_intra_community;
+ bool is_triangulation;
+ char currency[16];
+ char internal_code[64];
+} billing_item;
+
+typedef struct
+{
+ char id[16];
+ char sequential_number[16];
+ char customer_id[16];
+ char supplier_id[16];
+ time_t issued_at;
+ time_t delivered_at;
+ time_t expires_at;
+ char document[255];
+ list_t billing_items;
+ char project_id[16];
+ char cost_center_id[16];
+ char cost_unit_id[16];
+ s32 total;
+ s32 tax;
+ s32 net;
+ invoice_status status;
+ address shipping_address;
+ char currency[16];
+ time_t keep_untill;
+ time_t payment_on_account_date;
+ char tax_representative[64];
+ char corrected_sequential_number[16];
+} invoice;
+
typedef struct
{
contact company_info;
s32 next_id;
char path[4096];
char program_version[10];
- char country_code[2];
+ char country_code[3];
list_t contacts;
list_t projects;
- // invoices
+ list_t invoices;
+ list_t tax_brackets;
char ai_service[16];
char ai_key[32];
char email_service[16];
@@ -55,6 +121,9 @@ void administration_destroy();
char* administration_get_file_path();
s32 administration_create_id();
+contact administration_get_company_info();
+void administration_set_company_info(contact data);
+
bool administration_remove_contact(contact data);
bool administration_create_contact(contact data);
bool administration_update_contact(contact data);
diff --git a/include/locales.hpp b/include/locales.hpp
index 78bb682..ff116d5 100644
--- a/include/locales.hpp
+++ b/include/locales.hpp
@@ -1,8 +1,5 @@
#pragma once
-#include <stdio.h>
-#include <string.h>
-
typedef struct {
const char* key;
const char* value;
diff --git a/include/ui.hpp b/include/ui.hpp
index 827980c..85a5c2f 100644
--- a/include/ui.hpp
+++ b/include/ui.hpp
@@ -8,8 +8,16 @@ typedef enum
VIEW,
} view_state;
-void view_draw_required_tag();
+void ui_helper_draw_required_tag();
+void ui_helper_show_toast(const char* msg);
+void ui_helper_draw_toasts();
void ui_draw_main();
void ui_draw_contacts();
-void ui_draw_projects(); \ No newline at end of file
+void ui_draw_projects();
+void ui_draw_invoices();
+void ui_draw_settings();
+
+void ui_setup_contacts();
+void ui_setup_projects();
+void ui_setup_settings(); \ No newline at end of file
diff --git a/run.bat b/run.bat
index d8b9a53..eb9e517 100644
--- a/run.bat
+++ b/run.bat
@@ -1,10 +1,28 @@
-call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
+@echo off
+REM Find the latest Visual Studio installation path
+for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property installationPath`) do (
+ set VSPath=%%i
+)
+
+REM Check if found
+if not defined VSPath (
+ echo Visual Studio not found.
+ exit /b 1
+)
+
+set VCVARSALL=%VSPath%\VC\Auxiliary\Build\vcvarsall.bat
+if not exist "%VCVARSALL%" (
+ echo vcvarsall.bat not found at "%VCVARSALL%"
+ exit /b 1
+)
+
+call "%VCVARSALL%" x64
@set OUT_DIR=build\\
@set OUT_EXE=accounting
@set LIB_SOURCES=libs\imgui-1.92.1\backends\imgui_impl_dx11.cpp libs\imgui-1.92.1\backends\imgui_impl_win32.cpp libs\imgui-1.92.1\imgui*.cpp libs\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= /std:c11 /nologo /Ob0 /MT /Oy- /Zi /FS /W4 /EHsc /utf-8
+@set FLAGS=/nologo /Ob0 /MT /Oy- /Zi /FS /W4 /EHsc /utf-8
@set INCLUDE_DIRS=/I"libs/imgui-1.92.1" /I"libs/imgui-1.92.1/backends" /I"/" /I"libs/simclist-1.5" /Iinclude
cl %FLAGS% %INCLUDE_DIRS% %SOURCES% %LIB_SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fd%OUT_DIR%/vc140.pdb /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/src/administration.cpp b/src/administration.cpp
index fb8bd21..5e323d0 100644
--- a/src/administration.cpp
+++ b/src/administration.cpp
@@ -8,17 +8,169 @@
administration g_administration;
+static void administration_create_default_tax_brackets()
+{
+ #define ADD_BRACKET(_country, _rate, _description)\
+ {\
+ country_tax_bracket* tb = (country_tax_bracket*)malloc(sizeof(country_tax_bracket));\
+ memcpy(tb->country_code, _country, sizeof(tb->country_code));\
+ tb->rate = _rate;\
+ memcpy(tb->description, _country, sizeof(tb->description));\
+ list_append(&g_administration.tax_brackets, tb);\
+ }
+
+ // General brackets shared between countries.
+ ADD_BRACKET("00", 0.0f, "tax.reverse_charge");
+ ADD_BRACKET("00", 0.0f, "tax.exempt");
+
+ // Austria
+ ADD_BRACKET("AT", 20.0f, "Standard");
+ ADD_BRACKET("AT", 10.0f, "Reduced");
+ ADD_BRACKET("AT", 13.0f, "Reduced");
+
+ // Belgium
+ ADD_BRACKET("BE", 21.0f, "Standard");
+ ADD_BRACKET("BE", 6.0f, "Reduced");
+ ADD_BRACKET("BE", 12.0f, "Reduced");
+
+ // Bulgaria
+ ADD_BRACKET("BG", 20.0f, "Standard");
+ ADD_BRACKET("BG", 9.0f, "Reduced");
+
+ // Cyprus
+ ADD_BRACKET("CY", 19.0f, "Standard");
+ ADD_BRACKET("CY", 5.0f, "Reduced");
+ ADD_BRACKET("CY", 9.0f, "Reduced");
+
+ // Czechia
+ ADD_BRACKET("CZ", 21.0f, "Standard");
+ ADD_BRACKET("CZ", 12.0f, "Reduced");
+
+ // Croatia
+ ADD_BRACKET("HR", 25.0f, "Standard");
+ ADD_BRACKET("HR", 5.0f, "Reduced");
+ ADD_BRACKET("HR", 13.0f, "Reduced");
+
+ // Denmark
+ ADD_BRACKET("DK", 25.0f, "Standard");
+
+ // Estonia
+ ADD_BRACKET("EE", 22.0f, "Standard");
+ ADD_BRACKET("EE", 9.0f, "Reduced");
+
+ // Finland
+ ADD_BRACKET("FI", 25.5f, "Standard");
+ ADD_BRACKET("FI", 10.0f, "Reduced");
+ ADD_BRACKET("FI", 14.0f, "Reduced");
+
+ // France
+ ADD_BRACKET("FR", 20.0f, "Standard");
+ ADD_BRACKET("FR", 5.5f, "Reduced");
+ ADD_BRACKET("FR", 10.0f, "Reduced");
+ ADD_BRACKET("FR", 2.1f, "SuperReduced");
+
+ // Germany
+ ADD_BRACKET("DE", 19.0f, "Standard");
+ ADD_BRACKET("DE", 7.0f, "Reduced");
+
+ // Greece
+ ADD_BRACKET("GR", 24.0f, "Standard");
+ ADD_BRACKET("GR", 6.0f, "Reduced");
+ ADD_BRACKET("GR", 13.0f, "Reduced");
+
+ // Hungary
+ ADD_BRACKET("HU", 27.0f, "Standard");
+ ADD_BRACKET("HU", 5.0f, "Reduced");
+ ADD_BRACKET("HU", 18.0f, "Reduced");
+
+ // Ireland
+ ADD_BRACKET("IE", 23.0f, "Standard");
+ ADD_BRACKET("IE", 9.0f, "Reduced");
+ ADD_BRACKET("IE", 13.5f, "Reduced");
+ ADD_BRACKET("IE", 4.8f, "SuperReduced");
+
+ // Italy
+ ADD_BRACKET("IT", 22.0f, "Standard");
+ ADD_BRACKET("IT", 5.0f, "Reduced");
+ ADD_BRACKET("IT", 10.0f, "Reduced");
+ ADD_BRACKET("IT", 4.0f, "SuperReduced");
+
+ // Latvia
+ ADD_BRACKET("LV", 21.0f, "Standard");
+ ADD_BRACKET("LV", 5.0f, "Reduced");
+ ADD_BRACKET("LV", 12.0f, "Reduced");
+
+ // Lithuania
+ ADD_BRACKET("LT", 21.0f, "Standard");
+ ADD_BRACKET("LT", 5.0f, "Reduced");
+ ADD_BRACKET("LT", 9.0f, "Reduced");
+
+ // Luxembourg
+ ADD_BRACKET("LU", 17.0f, "Standard");
+ ADD_BRACKET("LU", 8.0f, "Reduced");
+ ADD_BRACKET("LU", 14.0f, "Reduced");
+ ADD_BRACKET("LU", 3.0f, "SuperReduced");
+
+ // Malta
+ ADD_BRACKET("MT", 18.0f, "Standard");
+ ADD_BRACKET("MT", 5.0f, "Reduced");
+ ADD_BRACKET("MT", 7.0f, "Reduced");
+
+ // Netherlands
+ ADD_BRACKET("NL", 21.0f, "Standard");
+ ADD_BRACKET("NL", 9.0f, "Reduced");
+
+ // Poland
+ ADD_BRACKET("PL", 23.0f, "Standard");
+ ADD_BRACKET("PL", 5.0f, "Reduced");
+ ADD_BRACKET("PL", 8.0f, "Reduced");
+
+ // Portugal
+ ADD_BRACKET("PT", 23.0f, "Standard");
+ ADD_BRACKET("PT", 6.0f, "Reduced");
+ ADD_BRACKET("PT", 13.0f, "Reduced");
+
+ // Romania
+ ADD_BRACKET("RO", 19.0f, "Standard");
+ ADD_BRACKET("RO", 5.0f, "Reduced");
+ ADD_BRACKET("RO", 9.0f, "Reduced");
+
+ // Slovakia
+ ADD_BRACKET("SK", 23.0f, "Standard");
+ ADD_BRACKET("SK", 5.0f, "Reduced");
+ ADD_BRACKET("SK", 19.0f, "Reduced");
+
+ // Slovenia
+ ADD_BRACKET("SI", 22.0f, "Standard");
+ ADD_BRACKET("SI", 5.0f, "Reduced");
+ ADD_BRACKET("SI", 9.5f, "Reduced");
+
+ // Spain
+ ADD_BRACKET("ES", 21.0f, "Standard");
+ ADD_BRACKET("ES", 10.0f, "Reduced");
+ ADD_BRACKET("ES", 4.0f, "SuperReduced");
+
+ // Sweden
+ ADD_BRACKET("SE", 25.0f, "Standard");
+ ADD_BRACKET("SE", 6.0f, "Reduced");
+ ADD_BRACKET("SE", 12.0f, "Reduced");
+}
+
void administration_create()
{
list_init(&g_administration.contacts);
list_init(&g_administration.projects);
+ list_init(&g_administration.tax_brackets);
strops_copy(g_administration.path, "[unsaved project]", sizeof(g_administration.path)); // @localize
+
+ administration_create_default_tax_brackets();
}
void administration_destroy()
{
list_destroy(&g_administration.contacts);
list_destroy(&g_administration.projects);
+ list_destroy(&g_administration.tax_brackets);
}
bool administration_create_contact(contact data)
@@ -195,4 +347,14 @@ bool administration_remove_project(project data)
list_iterator_stop(&g_administration.projects);
return false;
+}
+
+contact administration_get_company_info()
+{
+ return g_administration.company_info;
+}
+
+void administration_set_company_info(contact data)
+{
+ g_administration.company_info = data;
} \ No newline at end of file
diff --git a/src/locales.cpp b/src/locales.cpp
index 6ec1233..363d3c9 100644
--- a/src/locales.cpp
+++ b/src/locales.cpp
@@ -1,3 +1,6 @@
+#include <stdio.h>
+#include <string.h>
+
#include "locales.hpp"
locale_map locales[] = {
diff --git a/src/ui/helpers.cpp b/src/ui/helpers.cpp
index 74876c0..e4b25c8 100644
--- a/src/ui/helpers.cpp
+++ b/src/ui/helpers.cpp
@@ -2,7 +2,44 @@
#include "imgui.h"
#include "locales.hpp"
-void view_draw_required_tag()
+static float toast_timer = 0.0f;
+static const char* toast_msg = nullptr;
+void ui_helper_show_toast(const char* msg)
+{
+ toast_msg = msg;
+ toast_timer = 3.0f;
+}
+
+void ui_helper_draw_toasts()
+{
+ if (toast_timer > 0.0f && toast_msg)
+ {
+ toast_timer -= ImGui::GetIO().DeltaTime;
+
+ const float pad = 10.0f;
+ const ImVec2 window_pos = ImVec2(
+ ImGui::GetIO().DisplaySize.x - pad,
+ ImGui::GetIO().DisplaySize.y - pad
+ );
+ const ImVec2 window_pos_pivot = ImVec2(1.0f, 1.0f);
+
+ ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
+ ImGui::SetNextWindowBgAlpha(0.85f); // semi-transparent
+
+ ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration |
+ ImGuiWindowFlags_AlwaysAutoResize |
+ ImGuiWindowFlags_NoFocusOnAppearing |
+ ImGuiWindowFlags_NoNav;
+
+ if (ImGui::Begin("##Toast", nullptr, flags))
+ {
+ ImGui::TextUnformatted(toast_msg);
+ }
+ ImGui::End();
+ }
+}
+
+void ui_helper_draw_required_tag()
{
ImDrawList* draw_list = ImGui::GetWindowDrawList();
diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp
index 3115a77..fd9907f 100644
--- a/src/ui/ui_contacts.cpp
+++ b/src/ui/ui_contacts.cpp
@@ -6,44 +6,51 @@
#include "administration.hpp"
#include "locales.hpp"
-static view_state current_view_state = LIST;
+static view_state current_view_state = view_state::LIST;
static contact selected_for_removal;
static contact active_contact;
-static void draw_contact_form()
+void ui_setup_contacts()
{
- static const char* selected_country = NULL;
+ current_view_state = view_state::LIST;
+ memset(&active_contact, 0, sizeof(contact));
+ memset(&selected_for_removal, 0, sizeof(contact));
+}
- if (ImGui::Button(localize("form.back"))) {
- current_view_state = view_state::LIST;
- memset(&active_contact, 0, sizeof(contact));
- selected_country = 0;
- return;
+bool draw_contact_form(contact* buffer, bool back_button_enabled = true, bool viewing_only = false)
+{
+ const char* selected_country = NULL;
+
+ if (back_button_enabled)
+ {
+ if (ImGui::Button(localize("form.back"))) {
+ current_view_state = view_state::LIST;
+ selected_country = 0;
+ return false;
+ }
}
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));
+ ImGui::InputText(localize("contact.form.identifier"), buffer->id, IM_ARRAYSIZE(buffer->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::InputTextWithHint(localize("contact.form.fullname"), localize("contact.form.fullname"), buffer->name, IM_ARRAYSIZE(buffer->name));
+ ImGui::SameLine();ui_helper_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::InputTextWithHint(localize("contact.form.address1"), localize("contact.form.address1"), buffer->address.address1, IM_ARRAYSIZE(buffer->address.address1));
+ ImGui::SameLine();ui_helper_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::InputTextWithHint(localize("contact.form.address2"), localize("contact.form.address2"), buffer->address.address2, IM_ARRAYSIZE(buffer->address.address2));
+ ImGui::SameLine();ui_helper_draw_required_tag();
ImGui::SetNextItemWidth(widthAvailable*0.5f);
@@ -52,7 +59,7 @@ static void draw_contact_form()
if (selected_country == 0) {
for (int i = 0; i < country_count; i++)
{
- if (strcmp(countries[i], active_contact.country) == 0)
+ if (strcmp(countries[i], buffer->address.country) == 0)
{
selected_country = countries[i];
break;
@@ -71,50 +78,43 @@ static void draw_contact_form()
ImGui::EndCombo();
}
if (selected_country) {
- strops_copy(active_contact.country, selected_country, IM_ARRAYSIZE(active_contact.country));
+ strops_copy(buffer->address.country, selected_country, IM_ARRAYSIZE(buffer->address.country));
}
- ImGui::SameLine();view_draw_required_tag();
+ ImGui::SameLine();ui_helper_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::InputTextWithHint(localize("contact.form.taxnumber"), localize("contact.form.taxnumber"), buffer->taxid, IM_ARRAYSIZE(buffer->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::InputTextWithHint(localize("contact.form.businessnumber"), localize("contact.form.businessnumber"), buffer->businessid, IM_ARRAYSIZE(buffer->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::InputTextWithHint(localize("contact.form.email"), localize("contact.form.email"), buffer->email, IM_ARRAYSIZE(buffer->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::InputTextWithHint(localize("contact.form.phonenumber"), localize("contact.form.phonenumber"), buffer->phone_number, IM_ARRAYSIZE(buffer->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));
+ ImGui::InputTextWithHint(localize("contact.form.bankaccount"), localize("contact.form.bankaccount"), buffer->bank_account, IM_ARRAYSIZE(buffer->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;
+ bool can_save = strlen(buffer->name) > 0 && strlen(buffer->address.address1) > 0 &&
+ strlen(buffer->address.address2) > 0 && strlen(buffer->address.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;
+ return true;
}
if (!can_save) ImGui::EndDisabled();
}
else {
// TODO list invoices connected to contact.
}
+ return false;
}
static void draw_contact_list()
@@ -168,7 +168,7 @@ static void draw_contact_list()
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(2); ImGui::Text("%s %s", c.address.address1, c.address.address2);
ImGui::TableSetColumnIndex(3);
@@ -221,8 +221,20 @@ 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;
+ case view_state::CREATE:
+ if (draw_contact_form(&active_contact))
+ {
+ administration_create_contact(active_contact);
+ current_view_state = view_state::LIST;
+ }
+ break;
+ case view_state::EDIT:
+ if (draw_contact_form(&active_contact))
+ {
+ administration_update_contact(active_contact);
+ current_view_state = view_state::LIST;
+ }
+ break;
+ case view_state::VIEW: draw_contact_form(&active_contact, true, true); break;
}
} \ No newline at end of file
diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp
new file mode 100644
index 0000000..ea45f4e
--- /dev/null
+++ b/src/ui/ui_invoices.cpp
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include "strops.hpp"
+#include "ui.hpp"
+#include "imgui.h"
+#include "administration.hpp"
+#include "locales.hpp"
+
+static view_state current_view_state = LIST;
+static invoice active_invoice;
+
+void ui_draw_invoices()
+{
+
+} \ No newline at end of file
diff --git a/src/ui/ui_main.cpp b/src/ui/ui_main.cpp
index f6661b8..8af8dbc 100644
--- a/src/ui/ui_main.cpp
+++ b/src/ui/ui_main.cpp
@@ -11,20 +11,38 @@ typedef enum
REPORT_RESULTS = 3,
REPORT_TAX = 4,
PROJECTS = 5,
+ SETTINGS = 6,
END
} dashboard_view_state;
static dashboard_view_state dashboard_state = dashboard_view_state::INVOICES;
void (*drawcalls[dashboard_view_state::END])(void) = {
- 0,
+ ui_draw_invoices,
0,
ui_draw_contacts,
0,
0,
ui_draw_projects,
+ ui_draw_settings,
};
+void (*setupcalls[dashboard_view_state::END])(void) = {
+ 0,
+ 0,
+ ui_setup_contacts,
+ 0,
+ 0,
+ ui_setup_projects,
+ ui_setup_settings,
+};
+
+static void set_dashboard_state(dashboard_view_state state)
+{
+ dashboard_state = state;
+ if (setupcalls[dashboard_state]) setupcalls[dashboard_state]();
+}
+
void ui_draw_main()
{
// @localize
@@ -59,21 +77,22 @@ void ui_draw_main()
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;
+ if (ImGui::Button(localize("nav.invoices"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::INVOICES);
+ if (ImGui::Button(localize("nav.expenses"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::EXPENSES);
+ if (ImGui::Button(localize("nav.contacts"), ImVec2(buttonWidth, 24))) set_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;
+ if (ImGui::Button(localize("nav.reports.results"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::REPORT_RESULTS);
+ if (ImGui::Button(localize("nav.reports.tax"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::REPORT_TAX);
ImGui::PopStyleVar();
}
- if (ImGui::Button(localize("nav.Projects"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::PROJECTS;
+ if (ImGui::Button(localize("nav.Projects"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::PROJECTS);
+ if (ImGui::Button("Settings", ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::SETTINGS); //@localize
ImGui::PopStyleColor(1);
ImGui::PopStyleVar(3);
@@ -87,6 +106,7 @@ void ui_draw_main()
// Main content
ImGui::Begin("AccountingMainWindow", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse);
if (drawcalls[dashboard_state]) drawcalls[dashboard_state]();
+ ui_helper_draw_toasts();
ImGui::End();
// Status bar.
diff --git a/src/ui/ui_projects.cpp b/src/ui/ui_projects.cpp
index 9490254..a349814 100644
--- a/src/ui/ui_projects.cpp
+++ b/src/ui/ui_projects.cpp
@@ -5,11 +5,17 @@
#include "administration.hpp"
#include "locales.hpp"
-static view_state current_view_state = LIST;
+static view_state current_view_state = view_state::LIST;
static project selected_for_cancellation;
static project active_project;
+void ui_setup_projects()
+{
+ current_view_state = view_state::LIST;
+ memset(&active_project, 0, sizeof(contact));
+}
+
static void draw_project_form()
{
static const char* selected_country = NULL;
@@ -34,7 +40,7 @@ static void draw_project_form()
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();
+ ImGui::SameLine();ui_helper_draw_required_tag();
if (viewing_only) ImGui::EndDisabled();
diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp
new file mode 100644
index 0000000..81f6d31
--- /dev/null
+++ b/src/ui/ui_settings.cpp
@@ -0,0 +1,35 @@
+#include "ui.hpp"
+#include "imgui.h"
+#include "administration.hpp"
+#include "locales.hpp"
+
+extern bool draw_contact_form(contact* buffer, bool back_button_enabled = true, bool viewing_only = false);
+
+static contact company_info;
+void ui_setup_settings()
+{
+ company_info = administration_get_company_info();
+}
+
+void ui_draw_settings()
+{
+ // @localize
+ if (ImGui::BeginTabBar("SettingsTabBar", 0))
+ {
+ if (ImGui::BeginTabItem("Company"))
+ {
+ bool save = draw_contact_form(&company_info, false);
+
+ if (save) {
+ administration_set_company_info(company_info);
+ }
+ ImGui::EndTabItem();
+ }
+ if (ImGui::BeginTabItem("VAT Rates"))
+ {
+ ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+} \ No newline at end of file