From 42e68e5511cf5d0cda1a4d7ba68656b0bae543ff Mon Sep 17 00:00:00 2001 From: Timon Ostertun Date: Tue, 18 Feb 2025 13:05:22 +0100 Subject: [PATCH 1/8] changed main menu: planning <-> lists --- server/content/boats.php | 2 +- server/content/clubs.php | 2 +- server/content/planning.php | 2 +- server/content/planning_edit.php | 2 +- server/content/planning_list.php | 2 +- server/content/planning_view.php | 2 +- server/content/sailors.php | 2 +- server/page/headerfooter.php | 2 +- server/page/menus.php | 13 +++++-------- 9 files changed, 13 insertions(+), 16 deletions(-) diff --git a/server/content/boats.php b/server/content/boats.php index e06e933..986f782 100644 --- a/server/content/boats.php +++ b/server/content/boats.php @@ -2,7 +2,7 @@ $sp['title'] = 'Boote - Regatten.net ' . $_CLASS['name']; $sp['backbutton'] = 'index'; - $sp['activenav'] = 4; + $sp['activenav'] = 5; // Title $content = "

Boote

"; diff --git a/server/content/clubs.php b/server/content/clubs.php index 14bef9b..a8f2ce0 100644 --- a/server/content/clubs.php +++ b/server/content/clubs.php @@ -2,7 +2,7 @@ $sp['title'] = 'Vereine - Regatten.net ' . $_CLASS['name']; $sp['backbutton'] = 'index'; - $sp['activenav'] = 4; + $sp['activenav'] = 5; // Title $content = "

Vereine

"; diff --git a/server/content/planning.php b/server/content/planning.php index 754c080..73f57a9 100644 --- a/server/content/planning.php +++ b/server/content/planning.php @@ -2,7 +2,7 @@ $sp['title'] = 'Saison-Planung - Regatten.net ' . $_CLASS['name']; $sp['backbutton'] = 'index'; - $sp['activenav'] = 5; + $sp['activenav'] = 4; // Title $content = '

Saison-Planung

'; diff --git a/server/content/planning_edit.php b/server/content/planning_edit.php index 03c78da..a7ed989 100644 --- a/server/content/planning_edit.php +++ b/server/content/planning_edit.php @@ -2,7 +2,7 @@ $sp['title'] = 'Saison-Planung bearbeiten - Regatten.net ' . $_CLASS['name']; $sp['backbutton'] = true; - $sp['activenav'] = 5; + $sp['activenav'] = 4; // Title, Inputs $content = "

Saison-Planung bearbeiten

"; diff --git a/server/content/planning_list.php b/server/content/planning_list.php index 42fab4c..476a133 100644 --- a/server/content/planning_list.php +++ b/server/content/planning_list.php @@ -2,7 +2,7 @@ $sp['title'] = 'Saison-Planungen - Regatten.net ' . $_CLASS['name']; $sp['backbutton'] = true; - $sp['activenav'] = 5; + $sp['activenav'] = 4; // Title $content = '

Saison-Planungen

'; diff --git a/server/content/planning_view.php b/server/content/planning_view.php index 24b9f1a..84d6de9 100644 --- a/server/content/planning_view.php +++ b/server/content/planning_view.php @@ -2,7 +2,7 @@ $sp['title'] = 'Saison-Planung - Regatten.net ' . $_CLASS['name']; $sp['backbutton'] = true; - $sp['activenav'] = 5; + $sp['activenav'] = 4; // Title $content = '

Saison-Planung

'; diff --git a/server/content/sailors.php b/server/content/sailors.php index 42858e7..271e5e2 100644 --- a/server/content/sailors.php +++ b/server/content/sailors.php @@ -2,7 +2,7 @@ $sp['title'] = 'Segler - Regatten.net ' . $_CLASS['name']; $sp['backbutton'] = 'index'; - $sp['activenav'] = 4; + $sp['activenav'] = 5; // Title $content = "

Segler

"; diff --git a/server/page/headerfooter.php b/server/page/headerfooter.php index 6dbf4df..720533d 100644 --- a/server/page/headerfooter.php +++ b/server/page/headerfooter.php @@ -15,6 +15,6 @@ >Start >Regatten >Ranglisten - >Listen + >Planung >Mehr \ No newline at end of file diff --git a/server/page/menus.php b/server/page/menus.php index bf625e4..9e59834 100644 --- a/server/page/menus.php +++ b/server/page/menus.php @@ -68,11 +68,6 @@ - - - Saison-Planung - - Trimm-Bücher @@ -83,6 +78,11 @@ RLP-Rechner + + + Listen + + Kontakt @@ -278,9 +278,6 @@

Mehr Informationen findest Du hier.

-

- Mit der Nutzung dieser App erklärst Du Dich außerdem damit einverstanden, dass wir Cookies einsetzen. -

Alles klar From 0e501e8ba40cab3ad11931c8628ac5f66ca970f1 Mon Sep 17 00:00:00 2001 From: Timon Ostertun Date: Tue, 18 Feb 2025 14:02:06 +0100 Subject: [PATCH 2/8] added table expenditures inkl sync --- client/scripts/database.js | 65 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/client/scripts/database.js b/client/scripts/database.js index 6a73136..6f87354 100644 --- a/client/scripts/database.js +++ b/client/scripts/database.js @@ -1,4 +1,4 @@ -const DB_VERSION = 9; +const DB_VERSION = 10; const USER_ID = localStorage.getItem('auth_user'); const USER_NAME = localStorage.getItem('auth_username'); @@ -619,7 +619,7 @@ function sync() { localTimes[entry['table']] = entry['time']; }); - syncInProgress = 14; + syncInProgress = 15; var syncOkay = true; log("[db] Sync Start"); $('#i-sync').addClass('fa-spin'); @@ -1035,8 +1035,41 @@ function sync() { } }); + // EXPENDITURES + if (localTimes['expenditures'] < serverTimes['expenditures']) { + getJSON(QUERY_URL + 'get_expenditures?changed-after=' + localTimes['expenditures'], function (code, data) { + if (code == 200) { + var os = db.transaction('expenditures', 'readwrite').objectStore('expenditures'); + data.data.forEach(function (entry) { + os.put(entry); + }); + os.openCursor().onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + if (!data.keys.includes(parseInt(cursor.key))) { + os.delete(cursor.key); + } + cursor.continue(); + } else { + var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times'); + osUpdateTimes.put({ table: 'expenditures', time: serverTimes['expenditures'] }); + syncInProgress --; + log('[db] expenditures synced, remaining:', syncInProgress); + } + }; + } else { + log("[db] expenditures: Something went wrong (HTTP " + code + ")"); + syncOkay = false; + syncInProgress --; + log('[db] expenditures failed, remaining:', syncInProgress); + } + }); + } else { + syncInProgress --; + } + } else { - syncInProgress -= 4; + syncInProgress -= 5; } // NEWS @@ -1268,6 +1301,15 @@ function initDatabase() { var osFollows = db.createObjectStore('follows', { keyPath: 'id' }); } + if ((oldVersion < 10) && (newVersion >= 10)) { + log('[db] to version 10'); + var osExpenditures = db.createObjectStore('expenditures', { keyPath: 'id' }); + osExpenditures.createIndex('user_from', 'user_from', { unique: false }); + osExpenditures.createIndex('user_to', 'user_to', { unique: false }); + var osUpdateTimes = upgradeTransaction.objectStore('update_times'); + osUpdateTimes.add({ table: 'expenditures', time: 0 }); + } + // Force resync after db update if (oldVersion >= 1) { var osUpdateTimes = upgradeTransaction.objectStore('update_times'); @@ -1284,6 +1326,22 @@ function initDatabase() { function resetDb() { if (canUseLocalDB) { showLoader(); + db.transaction('clubs', 'readwrite').objectStore('clubs').clear(); + db.transaction('boats', 'readwrite').objectStore('boats').clear(); + db.transaction('sailors', 'readwrite').objectStore('sailors').clear(); + db.transaction('regattas', 'readwrite').objectStore('regattas').clear(); + db.transaction('results', 'readwrite').objectStore('results').clear(); + db.transaction('plannings', 'readwrite').objectStore('plannings').clear(); + db.transaction('trim_boats', 'readwrite').objectStore('trim_boats').clear(); + db.transaction('trim_users', 'readwrite').objectStore('trim_users').clear(); + db.transaction('trim_trims', 'readwrite').objectStore('trim_trims').clear(); + db.transaction('users', 'readwrite').objectStore('users').clear(); + db.transaction('years', 'readwrite').objectStore('years').clear(); + db.transaction('news', 'readwrite').objectStore('news').clear(); + db.transaction('class', 'readwrite').objectStore('class').clear(); + db.transaction('rankings', 'readwrite').objectStore('rankings').clear(); + db.transaction('follows', 'readwrite').objectStore('follows').clear(); + db.transaction('expenditures', 'readwrite').objectStore('expenditures').clear(); var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times'); osUpdateTimes.put({ table: 'last_sync', time: 1 }); osUpdateTimes.put({ table: 'clubs', time: 0 }); @@ -1297,6 +1355,7 @@ function resetDb() { osUpdateTimes.put({ table: 'trim_trims', time: 0 }); osUpdateTimes.put({ table: 'news', time: 0 }); osUpdateTimes.put({ table: 'users', time: 0 }); + osUpdateTimes.put({ table: 'expenditures', time: 0 }); log('[db] DB update times reset'); hideLoader(); } From dd587f7603a1c2d69bbd3793495586479ad54012 Mon Sep 17 00:00:00 2001 From: Timon Ostertun Date: Wed, 19 Feb 2025 14:30:44 +0100 Subject: [PATCH 3/8] added full expenditures functionality --- client/scripts/database.js | 19 +- client/styles/regatten.css | 63 ++++++ server/content/expenditures-user.php | 80 +++++++ server/content/expenditures.php | 63 ++++++ server/page/menus.php | 6 + server/scripts/expenditures-add.js | 319 +++++++++++++++++++++++++++ server/scripts/expenditures-user.js | 317 ++++++++++++++++++++++++++ server/scripts/expenditures.js | 149 +++++++++++++ 8 files changed, 1007 insertions(+), 9 deletions(-) create mode 100644 server/content/expenditures-user.php create mode 100644 server/content/expenditures.php create mode 100644 server/scripts/expenditures-add.js create mode 100644 server/scripts/expenditures-user.js create mode 100644 server/scripts/expenditures.js diff --git a/client/scripts/database.js b/client/scripts/database.js index 6f87354..44823cf 100644 --- a/client/scripts/database.js +++ b/client/scripts/database.js @@ -44,15 +44,17 @@ function search(string, fields) { var keywords = string.split(' '); for (kid in keywords) { var keyword = keywords[kid].toLowerCase(); - var found = false; - for (fid in fields) { - var field = fields[fid].toLowerCase(); - if (field.indexOf(keyword) >= 0) { - found = true; - break; + if (keyword != '') { + var found = false; + for (fid in fields) { + var field = fields[fid].toLowerCase(); + if (field.indexOf(keyword) >= 0) { + found = true; + break; + } } + if (!found) return false; } - if (!found) return false; } return true; } @@ -1304,8 +1306,7 @@ function initDatabase() { if ((oldVersion < 10) && (newVersion >= 10)) { log('[db] to version 10'); var osExpenditures = db.createObjectStore('expenditures', { keyPath: 'id' }); - osExpenditures.createIndex('user_from', 'user_from', { unique: false }); - osExpenditures.createIndex('user_to', 'user_to', { unique: false }); + osExpenditures.createIndex('user', 'user', { unique: false }); var osUpdateTimes = upgradeTransaction.objectStore('update_times'); osUpdateTimes.add({ table: 'expenditures', time: 0 }); } diff --git a/client/styles/regatten.css b/client/styles/regatten.css index 951cde7..ece6131 100644 --- a/client/styles/regatten.css +++ b/client/styles/regatten.css @@ -144,6 +144,69 @@ text-align: right; } +/*** EXPENDITURES LIST ***/ +.expenditures-list.display-border > div { + border-bottom: 1px solid #dee2e6; +} +.expenditures-list > div { + padding-top: 1rem; + padding-bottom: 1rem; + cursor: pointer; +} + +.expenditures-list > div:last-child { + border: 0; + padding-bottom: 0; +} + +.expenditures-list div { + white-space: nowrap; +} + +.expenditures-list > div > div > div { + display: inline-block; +} + +.expenditures-list > div > div:nth-child(1) > div:nth-child(1) { + width: calc(75% - 1.5em); +} +.expenditures-list > div > div:nth-child(1) > div:nth-child(2) { + width: 25%; + text-align: right; +} +.expenditures-list > div > div:nth-child(1) > div:nth-child(3) { + width: 1.5em; + text-align: right; +} + +.expenditures-list > div > div:nth-child(2) > div:nth-child(1) { + width: 6em; +} +.expenditures-list > div > div:nth-child(2) > div:nth-child(2) { + width: calc(70% - 6em); + overflow-x: visible; +} +.expenditures-list > div > div:nth-child(2) > div:nth-child(3) { + width: 30%; + text-align: right; +} + +.expenditures-list > div.sum { + padding: 0; +} +.expenditures-list > div.sum > div:nth-child(1) { + background: #dee2e6; + height: 1px; + display: flex; + justify-content: center; +} +.expenditures-list > div.sum > div:nth-child(1) > div:nth-child(1) { + background: white; + width: initial; + margin-top: -1em; + padding: 0 .5em; +} + /*** NORMAL LIST ***/ .normal-list > div { padding-top: 1rem; diff --git a/server/content/expenditures-user.php b/server/content/expenditures-user.php new file mode 100644 index 0000000..c4334bd --- /dev/null +++ b/server/content/expenditures-user.php @@ -0,0 +1,80 @@ +Ausgaben-Verwaltung"; +$content .= '

'; +$content .= $tpl->load('button', [' Neue Ausgabe', '#', 'html-id' => 'button-add', 'css-class' => 'mt-3 mb-2']); +$content .= $tpl->load('button', [' Neuer Geldtransfer', '#', 'html-id' => 'button-add-transfer', 'css-class' => 'mt-3 mb-0']); + +$sp['output'] .= $tpl->load('card', [$content, 'css-class' => 'show-loggedin']); + +// Not loggedin +$content = '

Ausgaben-Verwaltung

'; +$content .= '

Um die Ausgaben-Verwaltung nutzen zu können, musst Du angemeldet sein.
Melde Dich hier an oder registriere Dich jetzt kostenlos.

'; + +$sp['output'] .= $tpl->load('card', [$content, 'css-class' => 'show-notloggedin']); + +// List +$content = '

'; +$content .= $tpl->load('input', ['html-id' => 'input-search', 'placeholder' => 'Suche', 'type' => 'text', 'css-class' => 'mt-2']); +$content .= '
'; + +$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-list', 'css-class' => 'show-loggedin']); + +// Pagination +$sp['output'] .= $tpl->load('pagination', ['html-id' => 'pagination', 'css-class' => 'show-loggedin']); + +// Legend +$content = '

'; +$content .= ' genehmigt
'; +$content .= ' storniert
'; +$content .= ' wartet auf Zustimmung von
'; +$content .= ' wartet auf Deine Zustimmung'; +$content .= '

'; + +$sp['output'] .= $tpl->load('card', [$content, 'css-class' => 'show-loggedin']); + +// Menu +$items = $tpl->load('menu/item-icon', ['Akzeptieren', '#', 'html-id' => 'menu-item-approve', 'icon' => 'fa-check']); +$items .= $tpl->load('menu/item-icon', ['Ablehnen', '#', 'html-id' => 'menu-item-decline', 'icon' => 'fa-times']); +$items .= $tpl->load('menu/item-icon', ['Stornieren', '#', 'html-id' => 'menu-item-cancel', 'icon' => 'fa-times']); +$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-expenditure', 'title' => 'Ausgabe', 'height' => 200]); + +// Menu Add +$items = $tpl->load('menu/item-simple', ['bezahlt von: ', '#', 'html-id' => 'item-add-user-from']); +$items .= $tpl->load('input', ['html-id' => 'input-add-date', 'placeholder' => 'Datum des Transfers', 'type' => 'date', 'css-class' => 'mt-3']); +$items .= $tpl->load('input', ['html-id' => 'input-add-amount', 'placeholder' => 'Betrag in Euro', 'type' => 'number" min="0.01" step="0.01']); +$options = ''; +$options .= ''; +$options .= ''; +$options .= ''; +$items .= $tpl->load('select', ['html-id' => 'select-add-purpose', 'placeholder' => 'Verwendung', 'options' => $options]); +$items .= $tpl->load('input', ['html-id' => 'input-add-regatta-name', 'placeholder' => 'Name der Regatta (optional)', 'type' => 'text']); +$items .= $tpl->load('input', ['html-id' => 'input-add-purpose-text', 'placeholder' => 'Verwendungszweck (optional)', 'type' => 'text']); +$items .= '

Für wen wurde das Geld ausgegeben? (z.B. Du und Dein Segelpartner)
Hinweis: Der angegebene Betrag wird durch die Personen geteilt, die Du hier auswählst.

'; +$items .= $tpl->load('menu/item-simple', ['Weiteren Benutzer hinzufügen', '#', 'html-id' => 'item-add-user-to']); +$items .= $tpl->load('button', ['Speichern', '#', 'html-id' => 'button-add-save', 'css-class' => 'mb-3']); +$sp['menus'] .= $tpl->load('menu/modal', [$items, 'html-id' => 'menu-add', 'title' => 'Neue Ausgabe', 'height' => '90vh', 'width' => '90vw']); + +// Menu Add Transfer +$items = $tpl->load('menu/item-switch', ['Geld bekommen', 'html-id' => 'switch-add-transfer-received', 'icon' => 'fa-arrow-left']); +$items .= $tpl->load('menu/item-simple', ['von: bitte auswählen', '#', 'html-id' => 'item-add-transfer-user']); +$items .= $tpl->load('input', ['html-id' => 'input-add-transfer-date', 'placeholder' => 'Datum des Transfers', 'type' => 'date', 'css-class' => 'mt-3']); +$items .= $tpl->load('input', ['html-id' => 'input-add-transfer-amount', 'placeholder' => 'Betrag in Euro', 'type' => 'number" min="0.01" step="0.01']); +$items .= $tpl->load('input', ['html-id' => 'input-add-transfer-purpose-text', 'placeholder' => 'Verwendungszweck (optional)', 'type' => 'text']); +$items .= $tpl->load('button', ['Speichern', '#', 'html-id' => 'button-add-transfer-save']); +$sp['menus'] .= $tpl->load('menu/modal', [$items, 'html-id' => 'menu-add-transfer', 'title' => 'Neuer Geldtransfer', 'height' => 470, 'width' => '90vw']); + +// Select user +$items = $tpl->load('input', ['html-id' => 'input-user-search', 'placeholder' => 'Suche...', 'type' => 'text']); +$sp['menus'] .= $tpl->load('menu/modal', [$items, 'html-id' => 'menu-select-user', 'title' => 'Benutzer auswählen', 'height' => 500, 'width' => '90vw']); + +$sp['scripts'] .= $scripts->load('pagination', ['pageChange', 'page', 'pageCount', 'pagination']); +$sp['scripts'] .= $scripts->load('expenditures-add'); +$sp['scripts'] .= $scripts->load('expenditures-user'); + +?> \ No newline at end of file diff --git a/server/content/expenditures.php b/server/content/expenditures.php new file mode 100644 index 0000000..eb1d2a8 --- /dev/null +++ b/server/content/expenditures.php @@ -0,0 +1,63 @@ +Ausgaben-Verwaltung"; +$content .= $tpl->load('button', [' Neue Ausgabe', '#', 'html-id' => 'button-add', 'css-class' => 'mt-3 mb-2']); +$content .= $tpl->load('button', [' Neuer Geldtransfer', '#', 'html-id' => 'button-add-transfer', 'css-class' => 'mt-3 mb-0']); + +$sp['output'] .= $tpl->load('card', [$content, 'css-class' => 'show-loggedin']); + +// Not loggedin +$content = '

Ausgaben-Verwaltung

'; +$content .= '

Um die Ausgaben-Verwaltung nutzen zu können, musst Du angemeldet sein.
Melde Dich hier an oder registriere Dich jetzt kostenlos.

'; + +$sp['output'] .= $tpl->load('card', [$content, 'css-class' => 'show-notloggedin']); + +// List +$content = '

'; +$content .= $tpl->load('input', ['html-id' => 'input-search', 'placeholder' => 'Suche', 'type' => 'text', 'css-class' => 'mt-2']); +$content .= '
'; + +$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-list', 'css-class' => 'show-loggedin']); + +// Pagination +$sp['output'] .= $tpl->load('pagination', ['html-id' => 'pagination', 'css-class' => 'show-loggedin']); + +// Menu Add +$items = $tpl->load('menu/item-simple', ['bezahlt von: ', '#', 'html-id' => 'item-add-user-from']); +$items .= $tpl->load('input', ['html-id' => 'input-add-date', 'placeholder' => 'Datum des Transfers', 'type' => 'date', 'css-class' => 'mt-3']); +$items .= $tpl->load('input', ['html-id' => 'input-add-amount', 'placeholder' => 'Betrag in Euro', 'type' => 'number" min="0.01" step="0.01']); +$options = ''; +$options .= ''; +$options .= ''; +$options .= ''; +$items .= $tpl->load('select', ['html-id' => 'select-add-purpose', 'placeholder' => 'Verwendung', 'options' => $options]); +$items .= $tpl->load('input', ['html-id' => 'input-add-regatta-name', 'placeholder' => 'Name der Regatta (optional)', 'type' => 'text']); +$items .= $tpl->load('input', ['html-id' => 'input-add-purpose-text', 'placeholder' => 'Verwendungszweck (optional)', 'type' => 'text']); +$items .= '

Für wen wurde das Geld ausgegeben? (z.B. Du und Dein Segelpartner)
Hinweis: Der angegebene Betrag wird durch die Personen geteilt, die Du hier auswählst.

'; +$items .= $tpl->load('menu/item-simple', ['Weiteren Benutzer hinzufügen', '#', 'html-id' => 'item-add-user-to']); +$items .= $tpl->load('button', ['Speichern', '#', 'html-id' => 'button-add-save', 'css-class' => 'mb-3']); +$sp['menus'] .= $tpl->load('menu/modal', [$items, 'html-id' => 'menu-add', 'title' => 'Neue Ausgabe', 'height' => '90vh', 'width' => '90vw']); + +// Menu Add Transfer +$items = $tpl->load('menu/item-switch', ['Geld bekommen', 'html-id' => 'switch-add-transfer-received', 'icon' => 'fa-arrow-left']); +$items .= $tpl->load('menu/item-simple', ['von: bitte auswählen', '#', 'html-id' => 'item-add-transfer-user']); +$items .= $tpl->load('input', ['html-id' => 'input-add-transfer-date', 'placeholder' => 'Datum des Transfers', 'type' => 'date', 'css-class' => 'mt-3']); +$items .= $tpl->load('input', ['html-id' => 'input-add-transfer-amount', 'placeholder' => 'Betrag in Euro', 'type' => 'number" min="0.01" step="0.01']); +$items .= $tpl->load('input', ['html-id' => 'input-add-transfer-purpose-text', 'placeholder' => 'Verwendungszweck (optional)', 'type' => 'text']); +$items .= $tpl->load('button', ['Speichern', '#', 'html-id' => 'button-add-transfer-save']); +$sp['menus'] .= $tpl->load('menu/modal', [$items, 'html-id' => 'menu-add-transfer', 'title' => 'Neuer Geldtransfer', 'height' => 470, 'width' => '90vw']); + +// Select user +$items = $tpl->load('input', ['html-id' => 'input-user-search', 'placeholder' => 'Suche...', 'type' => 'text']); +$sp['menus'] .= $tpl->load('menu/modal', [$items, 'html-id' => 'menu-select-user', 'title' => 'Benutzer auswählen', 'height' => 500, 'width' => '90vw']); + +$sp['scripts'] .= $scripts->load('pagination', ['pageChange', 'page', 'pageCount', 'pagination']); +$sp['scripts'] .= $scripts->load('expenditures-add'); +$sp['scripts'] .= $scripts->load('expenditures'); + +?> \ No newline at end of file diff --git a/server/page/menus.php b/server/page/menus.php index 9e59834..8d6a884 100644 --- a/server/page/menus.php +++ b/server/page/menus.php @@ -68,6 +68,12 @@ + + + Ausgaben-Verwaltung + + + Trimm-Bücher diff --git a/server/scripts/expenditures-add.js b/server/scripts/expenditures-add.js new file mode 100644 index 0000000..fb57ba1 --- /dev/null +++ b/server/scripts/expenditures-add.js @@ -0,0 +1,319 @@ +let users = []; +let known = []; +let userSelectedCallback = null; +let excludeUsers = {}; + +function userSelected(id) { + if (typeof userSelectedCallback === 'function') { + userSelectedCallback(id); + } +} + +async function usersSearch() { + $('.item-user-search').remove(); + if ($('#input-user-search').val().length == 0) { + known.forEach(function (entry) { + if (!(entry.id in excludeUsers)) { + $('#menu-select-user').find('.content').find('.list-group').append(entry.content); + } + }); + } + if ($('#input-user-search').val().length >= 3) { + let cnt = 0; + users.forEach(function (entry) { + if (!(entry.id in excludeUsers) && search($('#input-user-search').val(), entry.keywords)) { + $('#menu-select-user').find('.content').find('.list-group').append(entry.content); + cnt++; + } + }); + if (cnt == 0) { + let item = ''; + $('#menu-select-user').find('.content').find('.list-group').append(item); + } + } else { + let item = ''; + $('#menu-select-user').find('.content').find('.list-group').append(item); + } +} + +function addRemoveToUser(userid) { + $('.item-user-to[data-userid=' + userid + ']').remove(); +} + +async function expendituresInitModals() { + $('#button-add-save').click(function () { + showLoader(); + const jqUserFrom = $('#item-add-user-from'); + const userFrom = jqUserFrom.data('userid'); + const jqDate = $('#input-add-date'); + const purposeDate = jqDate.val(); + if (purposeDate == '') { + hideLoader(); + toastError('Es wurde kein Datum ausgewählt!'); + jqDate.focus(); + return; + } + const jqAmount = $('#input-add-amount'); + const amount = jqAmount.val(); + if (amount == '') { + hideLoader(); + toastError('Es wurde kein Betrag ausgewählt!'); + jqAmount.focus(); + return; + } + const purpose = $('#select-add-purpose').val(); + const regattaName = $('#input-add-regatta-name').val(); + const purposeText = $('#input-add-purpose-text').val(); + let usersTo = []; + $('.item-user-to[data-userid]').each(function (index) { + usersTo.push($(this).data('userid')); + }); + let auth = { + id: localStorage.getItem('auth_id'), + hash: localStorage.getItem('auth_hash') + } + $.ajax({ + url: QUERY_URL + 'expenditures_add', + method: 'POST', + data: { + auth: auth, + user_from: userFrom, + date: purposeDate, + amount: Math.round(parseFloat(amount) * 100), + purpose: purpose, + regatta_name: regattaName, + purpose_text: purposeText, + users_to: usersTo + }, + error: function (xhr, status, error) { + if (xhr.status == 401) { + log('authentification failed'); + toastError('Authentifizierung fehlgeschlagen. Versuche es erneut.'); + } else if (xhr.status == 0) { + toastError('Du bist momentan offline.
Stelle eine Internetverbindung her, um die Ausgabe zu speichern'); + } else { + log('expenditures_add: unbekannter Fehler', status, error); + log(xhr); + toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000); + } + hideLoader(); + }, + success: async function (data, status, xhr) { + await sync(); + $('#menu-add').hideMenu(); + hideLoader(); + toastOk('Ausgabe gespeichert. Betrag wurde durch ' + data.count + ' Personen geteilt.'); + } + }); + }); + $('#item-add-user-from').click(async function () { + excludeUsers = {}; + $('#input-user-search').val('').trigger('focusin').trigger('focusout'); + usersSearch(); + userSelectedCallback = async function (userid) { + $('#item-add-user-from').data('userid', userid).find('span').html('bezahlt von: ' + (await dbGetData('users', userid)).username); + $('#menu-select-user').hideMenu(); + $('#menu-add').showMenu(); + } + $('#menu-add').hideMenu(); + $('#menu-select-user').showMenu(); + $('#input-user-search').focus(); + }); + $('#item-add-user-to').click(async function () { + excludeUsers = {}; + $('.item-user-to[data-userid]').each(function (index) { + excludeUsers[$(this).data('userid')] = true; + }); + $('#input-user-search').val('').trigger('focusin').trigger('focusout'); + usersSearch(); + userSelectedCallback = async function (userid) { + let item = '
'; + item += '' + (await dbGetData('users', userid)).username + ''; + item += ''; + item += ''; + $('#item-add-user-to').before(item); + $('#menu-select-user').hideMenu(); + $('#menu-add').showMenu(); + } + $('#menu-add').hideMenu(); + $('#menu-select-user').showMenu(); + $('#input-user-search').focus(); + }); + + $('#button-add-transfer-save').click(function () { + showLoader(); + const jqUser = $('#item-add-transfer-user'); + const selectedUser = jqUser.data('userid'); + if (selectedUser == 0) { + hideLoader(); + toastError('Es wurde keine Person ausgewählt!'); + return; + } + const jqDate = $('#input-add-transfer-date'); + const selectedDate = jqDate.val(); + if (selectedDate == '') { + hideLoader(); + toastError('Es wurde kein Datum ausgewählt!'); + jqDate.focus(); + return; + } + const jqAmount = $('#input-add-transfer-amount'); + const selectedAmount = jqAmount.val(); + if (selectedAmount == '') { + hideLoader(); + toastError('Es wurde kein Betrag ausgewählt!'); + jqAmount.focus(); + return; + } + const jqPurposeText = $('#input-add-transfer-purpose-text'); + const selectedPurposeText = jqPurposeText.val(); + const jqSwitch = $('#switch-add-transfer-received'); + const direction = jqSwitch.prop('checked'); + let auth = { + id: localStorage.getItem('auth_id'), + hash: localStorage.getItem('auth_hash') + } + $.ajax({ + url: QUERY_URL + 'expenditures_add_transfer', + method: 'POST', + data: { + auth: auth, + direction: direction ? 1 : -1, + userid: selectedUser, + date: selectedDate, + amount: Math.round(parseFloat(selectedAmount) * 100), + purpose_text: selectedPurposeText + }, + error: function (xhr, status, error) { + if (xhr.status == 401) { + log('authentification failed'); + toastError('Authentifizierung fehlgeschlagen. Versuche es erneut.'); + } else if (xhr.status == 0) { + toastError('Du bist momentan offline.
Stelle eine Internetverbindung her, um den Geldtransfer zu speichern'); + } else { + log('expenditures_add_transfer: unbekannter Fehler', status, error); + log(xhr); + toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000); + } + hideLoader(); + }, + success: async function (data, status, xhr) { + await sync(); + $('#menu-add-transfer').hideMenu(); + hideLoader(); + toastOk(direction ? 'Geldtransfer gespeichert. ' + (await dbGetData('users', selectedUser)).username + ' muss dies noch bestätigen' : 'Geldtransfer wurde gespeichert'); + } + }); + }); + $('#switch-add-transfer-received').parent().parent().click(async function () { + const jqSwitch = $('#switch-add-transfer-received'); + const jqUser = $('#item-add-transfer-user'); + const direction = jqSwitch.prop('checked'); + jqSwitch.parent().prev().text(direction ? 'Geld gegeben' : 'Geld bekommen').prev().removeClass('fa-arrow-' + (direction ? 'left' : 'right')).addClass('fa-arrow-' + (direction ? 'right' : 'left')); + const selectedUser = jqUser.data('userid'); + if (selectedUser == 0) { + jqUser.find('span').html((direction ? 'an: ' : 'von: ') + 'bitte auswählen'); + } else { + jqUser.find('span').text((direction ? 'an: ' : 'von: ') + (await dbGetData('users', selectedUser)).username); + } + }); + $('#item-add-transfer-user').click(async function () { + excludeUsers = {}; + excludeUsers[USER_ID] = true; + $('#input-user-search').val('').trigger('focusin').trigger('focusout'); + usersSearch(); + userSelectedCallback = async function (userid) { + const direction = $('#switch-add-transfer-received').prop('checked'); + $('#item-add-transfer-user').data('userid', userid).find('span').html((direction ? 'an: ' : 'von: ') + (await dbGetData('users', userid)).username); + $('#menu-select-user').hideMenu(); + $('#menu-add-transfer').showMenu(); + } + $('#menu-add-transfer').hideMenu(); + $('#menu-select-user').showMenu(); + $('#input-user-search').focus(); + }); + + $('#input-user-search').on('input', usersSearch); + + users = []; + known = []; + let itemMe = ''; + itemMe += 'ICH (' + USER_NAME + ')'; + itemMe += ''; + itemMe += ''; + known.push({id: USER_ID, content: itemMe}); + let knownIds = {}; + let allExps = await dbGetData('expenditures'); + let expUsers = {}; + for (let i in allExps) { + let exp = allExps[i]; + let eUId = exp.user; + if (!(eUId in expUsers)) { + expUsers[eUId] = { + userId: eUId, + username: (await dbGetData('users', eUId)).username, + cnt: 0 + }; + } + expUsers[eUId].cnt++; + } + expUsers = Object.values(expUsers); + expUsers.sort(function (a, b) { + return a.username.localeCompare(b.username); + }); + for (let i in expUsers) { + knownIds[expUsers[i].userId] = true; + } + const dbUsers = await dbGetData('users'); + dbUsers.sort(function (a, b) { + return a.username.localeCompare(b.username); + }); + for (let i in dbUsers) { + let item = ''; + item += '' + dbUsers[i].username + ''; + item += ''; + item += ''; + users.push({ + keywords: [dbUsers[i].username], + id: dbUsers[i].id, + content: item + }); + if (dbUsers[i].id in knownIds) known.push({id: dbUsers[i].id, content: item}); + } +} + +async function expendituresShowAdd(defaultUser = 0) { + $('#item-add-user-from').data('userid', USER_ID).find('span').html('bezahlt von: ' + USER_NAME); + $('#input-add-date').val(formatDate('Y-m-d')).trigger('focusin'); + $('#input-add-amount').val(''); + $('#select-add-purpose').val('entryfee'); + $('#input-add-regatta-name').val(''); // TODO: datalist? + $('#input-add-purpose-text').val(''); + $('.item-user-to').remove(); + let item = ''; + item += '' + USER_NAME + ''; + item += ''; + item += ''; + $('#item-add-user-to').before(item); + if (defaultUser > 0) { + item = ''; + item += '' + (await dbGetData('users', defaultUser)).username + ''; + item += ''; + item += ''; + $('#item-add-user-to').before(item); + } + $('#menu-add').showMenu(); +} + +async function expendituresShowAddTransfer(defaultUser = 0) { + $('#switch-add-transfer-received').prop('checked', true).parent().prev().text('Geld gegeben').prev().removeClass('fa-arrow-left').addClass('fa-arrow-right'); + if (defaultUser == 0) { + $('#item-add-transfer-user').data('userid', 0).find('span').html('an: bitte auswählen'); + } else { + $('#item-add-transfer-user').data('userid', defaultUser).find('span').html('an: ' + (await dbGetData('users', defaultUser)).username); + } + $('#input-add-transfer-date').val(formatDate('Y-m-d')).trigger('focusin'); + $('#input-add-transfer-amount').val(''); + $('#input-add-transfer-purpose-text').val(''); + $('#menu-add-transfer').showMenu(); +} diff --git a/server/scripts/expenditures-user.js b/server/scripts/expenditures-user.js new file mode 100644 index 0000000..24cacde --- /dev/null +++ b/server/scripts/expenditures-user.js @@ -0,0 +1,317 @@ +let firstCall = true; +let rows = []; +let displayed = []; +let page = 1; +let pageCount = 0; +const showCount = 25; +let sumsDisplayed = true; + +function createPurpose(exp) { + let purpose = ''; + let extraText = ': '; + switch (exp.purpose) { + case 'transfer': purpose = 'Geldtransfer'; break; + case 'entryfee': purpose = 'Meldegeld'; break; + case 'camping': purpose = 'Camping'; break; + case 'food': purpose = 'Essen'; break; + case 'other': extraText = ''; break; + } + if (exp.purpose_text != '') { + purpose += extraText + exp.purpose_text; + } + return purpose; +} + +async function onListClicked(id) { + let exp = await dbGetData('expenditures', id); + console.log(exp); + + $('#menu-expenditure').find('.menu-title').find('p').text(createPurpose(exp) + ' (' + (exp.direction * exp.amount / 100).toFixed(2) + ' €)'); + + if (exp.approved == 0 && (exp.direction < 0) == (exp.canceled == 0)) { + $('#menu-item-approve').show(); + $('#menu-item-approve').attr('onclick', 'expenditureAction("approve", ' + exp['id'] + ', "' + (exp.canceled == 1 ? 'Stornierung' : 'Ausgabe') + ' genehmigt")'); + $('#menu-item-approve').text(exp.canceled == 1 ? 'Storno akzeptieren' : 'Akzeptieren'); + $('#menu-item-decline').show(); + $('#menu-item-decline').attr('onclick', 'expenditureAction("decline", ' + exp['id'] + ', "Ausgabe ' + (exp.canceled == 1 ? 'erneut angefragt' : 'abgelehnt') + '")'); + $('#menu-item-decline').text(exp.canceled == 1 ? 'Erneut anfragen' : 'Ablehnen'); + } else { + $('#menu-item-approve').hide(); + $('#menu-item-decline').hide(); + } + + if (exp.canceled == 0 && (exp.approved == 1 || exp.direction > 0)) { + $('#menu-item-cancel').show(); + $('#menu-item-cancel').attr('onclick', 'expenditureAction("cancel", ' + exp['id'] + ', "' + (exp.direction > 0 ? 'Ausgabe storniert' : 'Stornierung beantragt') + '")'); + } else { + $('#menu-item-cancel').hide(); + } + + $('#menu-expenditure').showMenu(); + $('#menu-expenditure').scrollTop(0); +} + +function expenditureAction(action, expId, successStr) { + $('#menu-expenditure').hideMenu(); + showLoader(); + let auth = { + id: localStorage.getItem('auth_id'), + hash: localStorage.getItem('auth_hash') + } + $.ajax({ + url: QUERY_URL + 'expenditure_' + action, + method: 'POST', + data: { + auth: auth, + expenditure: expId + }, + error: function (xhr, status, error) { + if (xhr.status == 401) { + log('authentification failed'); + toastError('Authentifizierung fehlgeschlagen. Versuche es erneut.'); + } else if (xhr.status == 0) { + toastError('Du bist momentan offline.
Stelle eine Internetverbindung her, um die Ausgabe zu stornieren.'); + } else { + log('unbekannter Fehler', status, error); + log(xhr); + toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000); + } + hideLoader(); + }, + success: function (data, status, xhr) { + sync(); + hideLoader(); + toastOk(successStr); + } + }); +} + +function pageChange() { + $('#p-count')[0].scrollIntoView({ behavior: "smooth" }); + drawList(); +} + +async function drawList() { + window.setTimeout(function () { + let list = ''; + + if (displayed.length > 0) { + let offset = (page - 1) * (sumsDisplayed ? showCount * 2 : showCount); + let count = (page == pageCount ? (displayed.length - offset) : (sumsDisplayed ? showCount * 2 + 1 : showCount)); + + for (i = 0; i < count; i ++) { + list += displayed[i + offset]; + } + } else { + list = '
Keine Ergebnisse, die der Suche entsprechen
'; + } + + $('#div-list').html(list); + }, 0); +} + +async function reSearch() { + window.setTimeout(function () { + displayed = []; + rows.forEach(function (entry) { + if (search($('#input-search').val(), entry.keywords)) { + displayed.push(entry.content); + } + }); + sumsDisplayed = displayed.length == rows.length; + $('#div-list').toggleClass('display-border', !sumsDisplayed); + pageCount = Math.ceil((displayed.length - (sumsDisplayed ? 1 : 0)) / (sumsDisplayed ? showCount * 2 : showCount)); + if ((page < 1) || (page > pageCount)) { + if (page < 1) { + page = 1; + } else { + page = pageCount; + } + } + drawPagination(); + drawList(); + }, 0); +} + +function cancelCause(cancel_cause) { + switch (cancel_cause) { + case 'not approved': + return 'nicht genehmigt'; + case 'canceled': + return 'storniert'; + } + return 'unbekannter Grund'; +} + +let siteScript = async function() { + if (!isLoggedIn()) { + hideLoader(); + return; + } + + userid = findGetParameter('user'); + let user = null; + if (userid !== null) { + user = await dbGetData('users', userid); + } + if (user === null) { + location.href = LINK_PRE + 'expenditures'; + return; + } + + $('#p-username').text(user.username); + $('.span-username').text(user.username); + + if (firstCall) { + firstCall = false; + initPagination(); + $('#input-search').on('input', reSearch); + $('#button-add').click((e) => expendituresShowAdd(userid)); + $('#button-add-transfer').click((e) => expendituresShowAddTransfer(userid)); + expendituresInitModals(); + } + + let exps = await dbGetDataIndex('expenditures', 'user', user.id); + exps.sort(function (a, b) { + return a.created - b.created; + }); + + let sum = 0; + for (i in exps) { + let exp = exps[i]; + if (exp.canceled == 0) { + sum += exp.direction * exp.amount; + } + exps[i].sum = sum; + exps[i].purpose_html = createPurpose(exp); + exps[i].purpose_date = formatDate("d.m.Y", parseDate(exp.purpose_date)); + } + + let sumText = ''; + if (sum == 0) sumText = 'Du und ' + user.username + ' seid quitt.'; + else if (sum > 0) sumText = user.username + ' schuldet Dir noch ' + (sum / 100).toFixed(2) + ' €.'; // TODO: Ausgleichen Button? + else sumText = 'Du schuldest ' + user.username + ' noch ' + (-sum / 100).toFixed(2) + ' €.'; // TODO: Ausgleichen Button? + + results = exps.reverse(); + + // TODO: open approvals + + let count = results.length; + if (count > 0) { + $('#p-count').text(sumText); + $('#div-list').show(); + $('#input-search').parent().show(); + + rows = []; + + for (id in results) { + let entry = results[id]; + + let rowSum = { keywords: [], content: '' }; + + rowSum.content += '
'; + + // ZEILE SUM + rowSum.content += '
'; + + // sum + rowSum.content += '
'; + if (entry.sum < 0) rowSum.content += ''; + rowSum.content += (entry.sum / 100).toFixed(2); + if (entry.sum < 0) rowSum.content += ''; + rowSum.content += ' €
'; + + rowSum.content += '
'; + + rows.push(rowSum); + + + let row = { keywords: [], content: '' }; + + row.keywords.push((entry.amount / 100).toFixed(2)); + row.keywords.push(entry.purpose_html); + row.keywords.push(entry.purpose_date); + row.keywords.push(entry.regatta_name); + + row.content += '
'; + + // ZEILE 1 + row.content += '
'; + + // purpose + row.content += '' + entry.purpose_html + '
'; + + // amount + row.content += '
'; + if (entry.canceled == 1) row.content += '('; + if (entry.direction < 0) row.content += ''; + row.content += (entry.direction * entry.amount / 100).toFixed(2); + if (entry.direction < 0) row.content += ''; + if (entry.canceled == 1) row.content += ')'; + row.content += ' €
'; + + // icons + if (entry.approved == 1) { + if (entry.canceled == 1) { + row.content += '
'; + } else { + row.content += '
'; + } + } else if ((entry.direction < 0) == (entry.canceled == 1)) { + row.content += '
'; + } else { + row.content += '
'; + } + + row.content += '
'; + + // ZEILE 2 + row.content += '
'; + + // date + row.content += '
' + entry.purpose_date + '
'; + + // regatta + row.content += '
' + entry.regatta_name + '
'; + + // cancel_cause + row.content += '
' + (entry.canceled == 1 ? cancelCause(entry.cancel_cause) : '') + '
'; + + row.content += '
'; + + rows.push(row); + } + + let rowSum = { keywords: [], content: '' }; + + rowSum.content += '
'; + + // ZEILE SUM + rowSum.content += '
'; + + // sum + rowSum.content += '
'; + rowSum.content += (0).toFixed(2); + rowSum.content += ' €
'; + + rowSum.content += '
'; + + rows.push(rowSum); + + reSearch(); + + } else { + $('#p-count').html('Keine Ausgaben gefunden!'); + $('#div-list').hide(); + $('#input-search').parent().hide(); + } + + hideLoader(); +} diff --git a/server/scripts/expenditures.js b/server/scripts/expenditures.js new file mode 100644 index 0000000..9f13014 --- /dev/null +++ b/server/scripts/expenditures.js @@ -0,0 +1,149 @@ +var firstCall = true; +var rows = []; +var displayed = []; +var page = 1; +var pageCount = 0; +const showCount = 25; + +async function onListClicked(id) { + window.location = LINK_PRE + 'expenditures-user?user=' + id; +} + +function pageChange() { + $('#p-count')[0].scrollIntoView({ behavior: "smooth" }); + drawList(); +} + +async function drawList() { + window.setTimeout(function () { + var list = ''; + + if (displayed.length > 0) { + var offset = (page - 1) * showCount; + var count = (page == pageCount ? (displayed.length % showCount) : showCount); + if (count == 0) count = showCount; + + for (i = 0; i < count; i ++) { + list += displayed[i + offset]; + } + } else { + list = '
Keine Ergebnisse, die der Suche entsprechen
'; + } + + $('#div-list').html(list); + }, 0); +} + +async function reSearch() { + window.setTimeout(function () { + displayed = []; + rows.forEach(function (entry) { + if (search($('#input-search').val(), entry.keywords)) { + displayed.push(entry.content); + } + }); + pageCount = Math.ceil(displayed.length / showCount); + if ((page < 1) || (page > pageCount)) { + if (page < 1) { + page = 1; + } else { + page = pageCount; + } + } + drawPagination(); + drawList(); + }, 0); +} + +var siteScript = async function() { + if (!isLoggedIn()) { + hideLoader(); + return; + } + + if (firstCall) { + firstCall = false; + initPagination(); + $('#input-search').on('input', reSearch); + $('#button-add').click((e) => expendituresShowAdd()); + $('#button-add-transfer').click((e) => expendituresShowAddTransfer()); + expendituresInitModals(); + } + + let allExps = await dbGetData('expenditures'); + let expUsers = {}; + for (let i in allExps) { + let exp = allExps[i]; + let eUId = exp.user; + if (!(eUId in expUsers)) { + expUsers[eUId] = { + userId: eUId, + username: (await dbGetData('users', eUId)).username, + balance: 0, + openApprovals: 0, + cnt: 0 + }; + } + if (exp.canceled == 0) { + expUsers[eUId].balance += exp.direction * parseInt(exp.amount); + } + if (exp.approved == 0) { + if (exp.direction < 0 && exp.canceled == 0) expUsers[eUId].openApprovals++; + if (exp.direction > 0 && exp.canceled == 1) expUsers[eUId].openApprovals++; + } + expUsers[eUId].cnt++; + } + let results = Object.values(expUsers); + + let count = results.length; + if (count > 0) { + $('#p-count').hide(); + $('#div-list').show(); + $('#input-search').parent().show(); + + results.sort(function (a, b) { + return b.cnt - a.cnt; + }); + + rows = []; + + for (id in results) { + var entry = results[id]; + + var row = { keywords: [], content: '' }; + row.keywords.push(entry.username); + + row.content += '
'; + + // ZEILE 1 + // Username + row.content += '
' + entry.username + '
'; + + // ZEILE 2 + row.content += '
'; + + // open approvals + row.content += '
' + ((entry.openApprovals > 0) ? (entry.openApprovals + ' offene Genehmigung' + (entry.openApprovals > 1 ? 'en' : '')) : '') + '
'; + + // balance + row.content += '
'; + if (entry.balance < 0) row.content += ''; + row.content += (entry.balance / 100).toFixed(2); + if (entry.balance < 0) row.content += ''; + row.content += ' €
'; + + row.content += '
'; + + rows.push(row); + } + + reSearch(); + + } else { + $('#p-count').show().html('Keine Ausgaben gefunden!'); + $('#div-list').hide(); + $('#input-search').parent().hide(); + } + + hideLoader(); +} From 8f597051ddaac543a63ca9bf63d6b60e4b06bb62 Mon Sep 17 00:00:00 2001 From: Timon Ostertun Date: Wed, 19 Feb 2025 14:31:45 +0100 Subject: [PATCH 4/8] planning_edit: crew: fa-times instead of fa-angle-right to show that by clicking the sailor will be removed --- server/scripts/planning_edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/scripts/planning_edit.js b/server/scripts/planning_edit.js index 7578600..f31339e 100644 --- a/server/scripts/planning_edit.js +++ b/server/scripts/planning_edit.js @@ -367,7 +367,7 @@ async function planningEdit(id) { if (sailor !== null) { var item = ''; item += '' + sailor.name + ''; - item += ''; + item += ''; item += ''; $('#menu-edit').find('.content').find('.list-group').append(item); } From 839f668b088dd62d5869da57ec15291ff346c1c6 Mon Sep 17 00:00:00 2001 From: Timon Ostertun Date: Wed, 19 Feb 2025 14:49:21 +0100 Subject: [PATCH 5/8] expenditures: added badge for open approvals --- client/scripts/regatten.js.php | 28 +++++++++++++++++++++++++--- server/page/menus.php | 2 +- server/scripts/expenditures-add.js | 2 ++ server/scripts/expenditures-user.js | 5 +++-- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/client/scripts/regatten.js.php b/client/scripts/regatten.js.php index 2ee1134..83bb367 100644 --- a/client/scripts/regatten.js.php +++ b/client/scripts/regatten.js.php @@ -62,7 +62,11 @@ var badges = { news: { id: 'badge-more-news', cnt: 0 - } + }, + expenditures: { + id: 'badge-more-expenditures', + cnt: 0 + } } } }; @@ -512,6 +516,24 @@ async function updateNewsBadge() { updateBadge('more/news', sum); } +async function updateExpendituresBadge() { + let allExps = await dbGetData('expenditures'); + let sum = 0; + for (let i in allExps) { + let exp = allExps[i]; + if (exp.approved == 0) { + if (exp.direction < 0 && exp.canceled == 0) sum++; + if (exp.direction > 0 && exp.canceled == 1) sum++; + } + } + updateBadge('more/expenditures', sum); +} + +function updateBadges() { + updateNewsBadge(); + updateExpendituresBadge(); +} + var initRegatten = function() { showLoader(); @@ -568,11 +590,11 @@ var onDatabaseLoaded = function() { onServiceWorkerLoaded(); initPushSettings(); - updateNewsBadge(); + updateBadges(); } var onAfterSync = function() { - updateNewsBadge(); + updateBadges(); } function sendErrorReport() { diff --git a/server/page/menus.php b/server/page/menus.php index 8d6a884..a654a43 100644 --- a/server/page/menus.php +++ b/server/page/menus.php @@ -71,7 +71,7 @@ Ausgaben-Verwaltung - + diff --git a/server/scripts/expenditures-add.js b/server/scripts/expenditures-add.js index fb57ba1..2c18fd7 100644 --- a/server/scripts/expenditures-add.js +++ b/server/scripts/expenditures-add.js @@ -100,6 +100,7 @@ async function expendituresInitModals() { }, success: async function (data, status, xhr) { await sync(); + updateExpendituresBadge(); $('#menu-add').hideMenu(); hideLoader(); toastOk('Ausgabe gespeichert. Betrag wurde durch ' + data.count + ' Personen geteilt.'); @@ -199,6 +200,7 @@ async function expendituresInitModals() { }, success: async function (data, status, xhr) { await sync(); + updateExpendituresBadge(); $('#menu-add-transfer').hideMenu(); hideLoader(); toastOk(direction ? 'Geldtransfer gespeichert. ' + (await dbGetData('users', selectedUser)).username + ' muss dies noch bestätigen' : 'Geldtransfer wurde gespeichert'); diff --git a/server/scripts/expenditures-user.js b/server/scripts/expenditures-user.js index 24cacde..41d6e30 100644 --- a/server/scripts/expenditures-user.js +++ b/server/scripts/expenditures-user.js @@ -78,8 +78,9 @@ function expenditureAction(action, expId, successStr) { } hideLoader(); }, - success: function (data, status, xhr) { - sync(); + success: async function (data, status, xhr) { + await sync(); + updateExpendituresBadge(); hideLoader(); toastOk(successStr); } From a221c86431c06ea65f16d6c0dd26a84fd856378d Mon Sep 17 00:00:00 2001 From: Timon Ostertun Date: Wed, 19 Feb 2025 15:05:19 +0100 Subject: [PATCH 6/8] expenditures: Ausgleichen-Button --- server/scripts/expenditures-add.js | 10 +++++----- server/scripts/expenditures-user.js | 14 +++++++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/server/scripts/expenditures-add.js b/server/scripts/expenditures-add.js index 2c18fd7..dc49a2b 100644 --- a/server/scripts/expenditures-add.js +++ b/server/scripts/expenditures-add.js @@ -307,15 +307,15 @@ async function expendituresShowAdd(defaultUser = 0) { $('#menu-add').showMenu(); } -async function expendituresShowAddTransfer(defaultUser = 0) { - $('#switch-add-transfer-received').prop('checked', true).parent().prev().text('Geld gegeben').prev().removeClass('fa-arrow-left').addClass('fa-arrow-right'); +async function expendituresShowAddTransfer(defaultUser = 0, defaultDirection = true, defaultAmount = '') { + $('#switch-add-transfer-received').prop('checked', defaultDirection).parent().prev().text(defaultDirection ? 'Geld gegeben' : 'Geld bekommen').prev().removeClass(defaultDirection ? 'fa-arrow-left' : 'fa-arrow-right').addClass(defaultDirection ? 'fa-arrow-right' : 'fa-arrow-left'); if (defaultUser == 0) { - $('#item-add-transfer-user').data('userid', 0).find('span').html('an: bitte auswählen'); + $('#item-add-transfer-user').data('userid', 0).find('span').html((defaultDirection ? 'an: ' : 'von: ') + 'bitte auswählen'); } else { - $('#item-add-transfer-user').data('userid', defaultUser).find('span').html('an: ' + (await dbGetData('users', defaultUser)).username); + $('#item-add-transfer-user').data('userid', defaultUser).find('span').html((defaultDirection ? 'an: ' : 'von: ') + (await dbGetData('users', defaultUser)).username); } $('#input-add-transfer-date').val(formatDate('Y-m-d')).trigger('focusin'); - $('#input-add-transfer-amount').val(''); + $('#input-add-transfer-amount').val(defaultAmount).trigger('focusin').trigger('focusout'); $('#input-add-transfer-purpose-text').val(''); $('#menu-add-transfer').showMenu(); } diff --git a/server/scripts/expenditures-user.js b/server/scripts/expenditures-user.js index 41d6e30..2dede7e 100644 --- a/server/scripts/expenditures-user.js +++ b/server/scripts/expenditures-user.js @@ -189,9 +189,16 @@ let siteScript = async function() { } let sumText = ''; - if (sum == 0) sumText = 'Du und ' + user.username + ' seid quitt.'; - else if (sum > 0) sumText = user.username + ' schuldet Dir noch ' + (sum / 100).toFixed(2) + ' €.'; // TODO: Ausgleichen Button? - else sumText = 'Du schuldest ' + user.username + ' noch ' + (-sum / 100).toFixed(2) + ' €.'; // TODO: Ausgleichen Button? + let sumButton = ''; + if (sum == 0) { + sumText = 'Du und ' + user.username + ' seid quitt.'; + } else if (sum > 0) { + sumText = user.username + ' schuldet Dir noch ' + (sum / 100).toFixed(2) + ' €.'; + sumButton = ' Ausgleichen'; + } else { + sumText = 'Du schuldest ' + user.username + ' noch ' + (-sum / 100).toFixed(2) + ' €.'; + sumButton = ' Ausgleichen'; + } results = exps.reverse(); @@ -200,6 +207,7 @@ let siteScript = async function() { let count = results.length; if (count > 0) { $('#p-count').text(sumText); + $('#p-count').html($('#p-count').html() + sumButton); $('#div-list').show(); $('#input-search').parent().show(); From 5dc88a78a24dd6defde3977dea9cb91ccb7df0a1 Mon Sep 17 00:00:00 2001 From: Timon Ostertun Date: Wed, 19 Feb 2025 15:18:08 +0100 Subject: [PATCH 7/8] expenditures: add: regatta_name got datalist --- server/scripts/expenditures-add.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/server/scripts/expenditures-add.js b/server/scripts/expenditures-add.js index dc49a2b..ea508a0 100644 --- a/server/scripts/expenditures-add.js +++ b/server/scripts/expenditures-add.js @@ -282,6 +282,23 @@ async function expendituresInitModals() { }); if (dbUsers[i].id in knownIds) known.push({id: dbUsers[i].id, content: item}); } + + $('#input-add-regatta-name').attr('list', 'list-regattas'); + let listRegattas = $('').appendTo('body'); + let plannings = await dbGetDataIndex('plannings', 'user', USER_ID); + let regattas = []; + for (let i in plannings) { + let regatta = await dbGetData('regattas', plannings[i].regatta); + regatta.year = formatDate('Y', parseDate(regatta.date)); + regattas.push(regatta); + } + regattas.sort(function (a, b) { + if (a.year != b.year) return b.year - a.year; + return a.name.localeCompare(b.name); + }); + for (let i in regattas) { + $('