From 4f5a46d18738869742f88c7718d1660a8caabbaa Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Sun, 3 Aug 2025 10:46:01 -0400 Subject: [PATCH] Added confirm modal, ability to add profiles. --- finnow-api/.gdbinit | 1 + finnow-api/dub.selections.json | 2 +- finnow-api/schema.sql | 2 +- finnow-api/source/transaction/api.d | 17 +++-- finnow-api/source/util/data.d | 9 ++- finnow-api/source/util/pagination.d | 13 ++-- web-app/src/assets/main.css | 16 ++--- web-app/src/components/AppButton.vue | 65 +++++++++++++++++++ web-app/src/components/ConfirmModal.vue | 28 ++++++++ web-app/src/components/ModalWrapper.vue | 39 ++++++----- web-app/src/pages/ProfilesPage.vue | 38 +++++++++-- web-app/src/pages/UserHomePage.vue | 2 + web-app/src/pages/home/AccountsModule.vue | 2 +- web-app/src/pages/home/ProfileModule.vue | 41 ++++++++++-- web-app/src/pages/home/TransactionsModule.vue | 44 +++++++++++++ 15 files changed, 265 insertions(+), 54 deletions(-) create mode 100644 finnow-api/.gdbinit create mode 100644 web-app/src/components/AppButton.vue create mode 100644 web-app/src/components/ConfirmModal.vue create mode 100644 web-app/src/pages/home/TransactionsModule.vue diff --git a/finnow-api/.gdbinit b/finnow-api/.gdbinit new file mode 100644 index 0000000..85ffcf3 --- /dev/null +++ b/finnow-api/.gdbinit @@ -0,0 +1 @@ +handle SIG34 nostop noprint pass noignore \ No newline at end of file diff --git a/finnow-api/dub.selections.json b/finnow-api/dub.selections.json index c22c2ea..99f3b3c 100644 --- a/finnow-api/dub.selections.json +++ b/finnow-api/dub.selections.json @@ -6,7 +6,7 @@ "dxml": "0.4.4", "handy-http-data": "1.3.0", "handy-http-handlers": "1.1.0", - "handy-http-primitives": "1.8.0", + "handy-http-primitives": "1.8.1", "handy-http-starter": "1.5.0", "handy-http-transport": "1.7.0", "handy-http-websockets": "1.2.0", diff --git a/finnow-api/schema.sql b/finnow-api/schema.sql index 5e65577..5f58e66 100644 --- a/finnow-api/schema.sql +++ b/finnow-api/schema.sql @@ -1,4 +1,4 @@ --- This schema is included at compile-time into data : SqliteDataSource. +-- This schema is included at compile-time into source/profile/data_impl_sqlite.d SqliteProfileDataSource -- Basic/Utility Entities diff --git a/finnow-api/source/transaction/api.d b/finnow-api/source/transaction/api.d index bb3ea9c..3712932 100644 --- a/finnow-api/source/transaction/api.d +++ b/finnow-api/source/transaction/api.d @@ -3,6 +3,7 @@ module transaction.api; import handy_http_primitives; import handy_http_data.json; import handy_http_handlers.path_handler; +import slf4d; import transaction.model; import transaction.data; @@ -16,15 +17,18 @@ import util.data; immutable DEFAULT_TRANSACTION_PAGE = PageRequest(0, 10, [Sort("created_at", SortDir.DESC)]); struct TransactionResponse { - import std.typecons : Nullable, nullable; + import asdf : serdeTransformOut; + ulong id; string timestamp; string addedAt; ulong amount; string currency; string description; - Nullable!ulong vendorId; - Nullable!ulong categoryId; + @serdeTransformOut!serializeOptional + Optional!ulong vendorId; + @serdeTransformOut!serializeOptional + Optional!ulong categoryId; static TransactionResponse of(in Transaction tx) { return TransactionResponse( @@ -34,8 +38,8 @@ struct TransactionResponse { tx.amount, tx.currency.code.idup, tx.description, - tx.vendorId.toNullable, - tx.categoryId.toNullable + tx.vendorId, + tx.categoryId ); } } @@ -44,7 +48,8 @@ void getTransactions(ref ServerHttpRequest request, ref ServerHttpResponse respo ProfileDataSource ds = getProfileDataSource(request); PageRequest pr = PageRequest.parse(request, DEFAULT_TRANSACTION_PAGE); Page!Transaction page = ds.getTransactionRepository().findAll(pr); - writeJsonBody(response, page.mapItems(&TransactionResponse.of)); + Page!TransactionResponse responsePage = page.mapTo!()(&TransactionResponse.of); + writeJsonBody(response, responsePage); } void getVendors(ref ServerHttpRequest request, ref ServerHttpResponse response) { diff --git a/finnow-api/source/util/data.d b/finnow-api/source/util/data.d index 18c14b7..4ae7845 100644 --- a/finnow-api/source/util/data.d +++ b/finnow-api/source/util/data.d @@ -13,8 +13,15 @@ Optional!T toOptional(T)(Nullable!T value) { Nullable!T toNullable(T)(Optional!T value) { if (value.isNull) { - return Nullable!T.init; + return Nullable!(T)(); } else { return Nullable!T(value.value); } } + +auto serializeOptional(T)(Optional!T value) { + if (value.isNull) { + return Nullable!T(); + } + return Nullable!T(value.value); +} diff --git a/finnow-api/source/util/pagination.d b/finnow-api/source/util/pagination.d index 9419d76..8290843 100644 --- a/finnow-api/source/util/pagination.d +++ b/finnow-api/source/util/pagination.d @@ -97,13 +97,10 @@ struct PageRequest { struct Page(T) { T[] items; PageRequest pageRequest; -} -Page!U mapItems(T, U)(in Page!T page, U function(const(T)) fn) { - import std.algorithm : map; - import std.array : array; - return Page!U( - page.items.map!fn.array, - page.pageRequest - ); + Page!U mapTo(U)(U function(T) fn) { + import std.algorithm : map; + import std.array : array; + return Page!(U)(this.items.map!(fn).array, this.pageRequest); + } } diff --git a/web-app/src/assets/main.css b/web-app/src/assets/main.css index 736615d..3b56a92 100644 --- a/web-app/src/assets/main.css +++ b/web-app/src/assets/main.css @@ -46,12 +46,12 @@ a:hover { max-width: 600px; margin-left: auto; margin-right: auto; - padding: 0.5em; - padding-bottom: 1em; + padding: 0.5rem; + padding-bottom: 1rem; background-color: var(--bg-page); - border-bottom-left-radius: 2em; - border-bottom-right-radius: 2em; + border-bottom-left-radius: 2rem; + border-bottom-right-radius: 2rem; } .app-page-title { @@ -64,7 +64,7 @@ a:hover { display: flex; flex-wrap: wrap; gap: 20px; - padding: 1em; + padding: 1rem; } .app-module { @@ -72,10 +72,10 @@ a:hover { min-height: 200px; flex-grow: 1; background-color: var(--bg-secondary); - border-radius: 0.5em; - padding: 0.5em; + border-radius: 0.5rem; + padding: 0.5rem; } -.app-module > h2 { +.app-module-header { margin: 0; } diff --git a/web-app/src/components/AppButton.vue b/web-app/src/components/AppButton.vue new file mode 100644 index 0000000..9de07da --- /dev/null +++ b/web-app/src/components/AppButton.vue @@ -0,0 +1,65 @@ + + + diff --git a/web-app/src/components/ConfirmModal.vue b/web-app/src/components/ConfirmModal.vue new file mode 100644 index 0000000..f5e0840 --- /dev/null +++ b/web-app/src/components/ConfirmModal.vue @@ -0,0 +1,28 @@ + + diff --git a/web-app/src/components/ModalWrapper.vue b/web-app/src/components/ModalWrapper.vue index 704537d..20d258f 100644 --- a/web-app/src/components/ModalWrapper.vue +++ b/web-app/src/components/ModalWrapper.vue @@ -1,13 +1,23 @@