Compare commits

...

60 Commits

Author SHA1 Message Date
d6d88f5f60 🚀RELEASE v1.3.3
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-19 18:18:44 +02:00
2c208c4381 bumped lfk-client-js 2023-04-19 18:18:26 +02:00
39bc6c4945 🚀RELEASE v1.3.2
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-19 18:17:18 +02:00
b94e3b745f fix(donors): Shortened texts 2023-04-19 18:16:50 +02:00
6f337aeee1 feat(donations): Resolve donations via donor 2023-04-19 18:15:15 +02:00
5d48060834 fix(donors): Removed debug infos 2023-04-19 18:12:24 +02:00
c842c203e2 🚀RELEASE v1.3.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 18:00:58 +02:00
5bcfc8db75 More filtering 2023-04-19 18:00:41 +02:00
27b4dde755 feat(donors): Added name and address filtering 2023-04-19 18:00:16 +02:00
91ab199769 feat(donations): Donation table filtering 2023-04-19 17:53:24 +02:00
e75be49be4 🚀RELEASE v1.3.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 17:41:40 +02:00
505fb8cb08 feat(donations): Implemented donation deletion via confirm modal 2023-04-19 17:41:21 +02:00
e5c9265588 feat(donations): Implemented add donation payment via datatable refresh 2023-04-19 17:34:34 +02:00
02003ec80e feat(donations): Donations reactive create and load into datatable 2023-04-19 17:21:24 +02:00
133470b6f2 feat(donationsoverview): Switched donations overview to datatable 2023-04-19 17:12:04 +02:00
4a6230c439 Merge branch 'dev' of git.odit.services:lfk/frontend into dev
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-19 16:56:23 +02:00
fdc7d80bbf 🚀RELEASE v1.2.0 2023-04-19 16:56:09 +02:00
352551e168 feat(donorsoverview): Dynamicly add newly generated donors 2023-04-19 16:55:14 +02:00
7aec050419 feat(donorsoverview): Implemented delete confirmation with datatable 2023-04-19 16:49:54 +02:00
4289034436 new license file version [CI SKIP] 2023-04-19 14:45:02 +00:00
8f8858f100 feat(DonationsOverview): i18n loading text
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 16:44:39 +02:00
d98fb0d5b2 feat(donoroverview): Added datatable formatters 2023-04-19 16:39:30 +02:00
5014bf5bc5 feat(donors): Load donors paginated 2023-04-19 16:23:00 +02:00
0708cabc75 🚀RELEASE v1.1.0
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-19 16:05:21 +02:00
4fcb26cf93 feat(dashboard): Updated stats icons 2023-04-19 16:04:02 +02:00
269def20d1 feat(dashboard): Added average sponsoring
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-19 15:59:45 +02:00
b8de9e0e42 feat(dashboard): Added average distance 2023-04-19 15:57:46 +02:00
7b2b598588 feat(dashboard): Added total donations 2023-04-19 15:56:21 +02:00
e0b61486b0 feat(dashboar): Added total donors to overview 2023-04-19 15:54:39 +02:00
3f86f7412f Lockfile 2023-04-19 15:53:33 +02:00
6454d960de Bumped client 2023-04-19 15:53:28 +02:00
37154c188b Merge branch 'dev' of git.odit.services:lfk/frontend into dev
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-19 15:38:15 +02:00
8da7578a0a 🚀RELEASE v1.0.0 2023-04-19 15:37:56 +02:00
2a64094006 new license file version [CI SKIP] 2023-04-19 13:37:32 +00:00
e9ce9644ff Merge pull request 'feature/175-request_pagination' (#176) from feature/175-request_pagination into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #176
2023-04-19 13:37:16 +00:00
52439aa5bc Allways set loaded to true
ref #175
2023-04-18 20:47:42 +02:00
ccf865687b Donation paginated loading
ref #175
2023-04-18 20:46:18 +02:00
cac34db1fd Paginated scan loading
ref #175
2023-04-18 20:43:04 +02:00
faf3893180 Paginated runner loading (1000 per page)
ref #175
2023-04-18 20:40:28 +02:00
c33dfcfddd Implemented Async loading of cards via pagination (500 cards per request)
ref #175
2023-04-18 20:38:01 +02:00
019e14ab1f Bumped lfk client
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-18 20:18:46 +02:00
b5790196c6 Merge branch 'dev' of git.odit.services:lfk/frontend into dev
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-17 17:56:42 +02:00
94a64ca690 🚀RELEASE v0.19.0 2023-04-17 17:56:34 +02:00
a6ce04c903 new license file version [CI SKIP] 2023-04-17 15:56:08 +00:00
165c154233 Merge pull request 'feature/173-scanstation_configcodes' (#174) from feature/173-scanstation_configcodes into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #174
2023-04-17 15:55:53 +00:00
318547db46 Adjusted size on smaller devices
ref #173
2023-04-17 17:55:33 +02:00
e60c09e19c I18n
ref #173
2023-04-17 17:52:05 +02:00
4834d1484c Styling
ref #173
2023-04-17 17:51:46 +02:00
4b6342727e Implemented config code generation
ref #173
2023-04-17 17:47:57 +02:00
cb5fa52cd9 Barcode placeholder
ref #173
2023-04-17 17:32:42 +02:00
947d01cf7f Lockfile 2023-04-17 17:32:31 +02:00
3563394fb3 Added bwip-js for barcode generation
ref #173
2023-04-17 17:32:16 +02:00
269d7a7def 🚀RELEASE v0.18.4
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-15 23:32:08 +02:00
e95f2333b0 Hide address2 in orgs by default 2023-04-15 23:30:46 +02:00
950217e0a3 🚀RELEASE v0.18.3
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-15 23:27:36 +02:00
5e65fb3301 Dont show adress 2 in runner overview 2023-04-15 23:27:19 +02:00
2a294cde04 🚀RELEASE v0.18.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-15 19:58:14 +02:00
e95420d79c Push in releaseit 2023-04-15 19:57:59 +02:00
cffbd17dc7 Added timestamps to scanoverview 2023-04-15 19:56:55 +02:00
00de8c3d75 🚀RELEASE v0.18.1
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-15 19:44:17 +02:00
29 changed files with 2751 additions and 1949 deletions

View File

@@ -2,10 +2,131 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [1.3.3](https://git.odit.services/lfk/frontend/compare/1.3.2...1.3.3)
- bumped lfk-client-js [`2c208c4`](https://git.odit.services/lfk/frontend/commit/2c208c438185892270a0ebd37deb6a7c9ac08fc0)
#### [1.3.2](https://git.odit.services/lfk/frontend/compare/1.3.1...1.3.2)
> 19 April 2023
- 🚀RELEASE v1.3.2 [`39bc6c4`](https://git.odit.services/lfk/frontend/commit/39bc6c49450964510f996369d014f92c569188ae)
- fix(donors): Shortened texts [`b94e3b7`](https://git.odit.services/lfk/frontend/commit/b94e3b745f2febbe91e16a7a26f96b47d347ab92)
- feat(donations): Resolve donations via donor [`6f337ae`](https://git.odit.services/lfk/frontend/commit/6f337aeee16267d1e67e3d3855b63b6f2e57979f)
- fix(donors): Removed debug infos [`5d48060`](https://git.odit.services/lfk/frontend/commit/5d48060834717b2244172a0914e2690f8fe634d9)
#### [1.3.1](https://git.odit.services/lfk/frontend/compare/1.3.0...1.3.1)
> 19 April 2023
- feat(donations): Donation table filtering [`91ab199`](https://git.odit.services/lfk/frontend/commit/91ab199769c9f4f8051c74ad43a701db321f3995)
- feat(donors): Added name and address filtering [`27b4dde`](https://git.odit.services/lfk/frontend/commit/27b4dde7551995c9d7e8ca33a9bd97d429a35801)
- 🚀RELEASE v1.3.1 [`c842c20`](https://git.odit.services/lfk/frontend/commit/c842c203e2fbf0a201297d475db9047c0691bd52)
- More filtering [`5bcfc8d`](https://git.odit.services/lfk/frontend/commit/5bcfc8db752fce96e9f523d14cefff1a4f675661)
#### [1.3.0](https://git.odit.services/lfk/frontend/compare/1.2.0...1.3.0)
> 19 April 2023
- feat(donations): Implemented donation deletion via confirm modal [`505fb8c`](https://git.odit.services/lfk/frontend/commit/505fb8cb08b81a7dcb08561bdda0f6464f140d3e)
- 🚀RELEASE v1.3.0 [`e75be49`](https://git.odit.services/lfk/frontend/commit/e75be49be42c3d5581e2204bfa064bfa3778c1b6)
- feat(donationsoverview): Switched donations overview to datatable [`133470b`](https://git.odit.services/lfk/frontend/commit/133470b6f2a63ec087f27c98ef260648a8672e5f)
- feat(donations): Implemented add donation payment via datatable refresh [`e5c9265`](https://git.odit.services/lfk/frontend/commit/e5c92655886ad9a6fcd7565fadd7955c477c3595)
- feat(donations): Donations reactive create and load into datatable [`02003ec`](https://git.odit.services/lfk/frontend/commit/02003ec80efc16aabd126710a6eeac18df43f841)
- feat(DonationsOverview): i18n loading text [`8f8858f`](https://git.odit.services/lfk/frontend/commit/8f8858f10071ddf9988d0ec0e3c4a891db24a102)
- new license file version [CI SKIP] [`4289034`](https://git.odit.services/lfk/frontend/commit/4289034436869750205a946247e7ab5f9892fe98)
#### [1.2.0](https://git.odit.services/lfk/frontend/compare/1.1.0...1.2.0)
> 19 April 2023
- feat(donoroverview): Added datatable formatters [`d98fb0d`](https://git.odit.services/lfk/frontend/commit/d98fb0d5b288c987a45ccbf2bb026ccaab539a71)
- 🚀RELEASE v1.2.0 [`fdc7d80`](https://git.odit.services/lfk/frontend/commit/fdc7d80bbf9bd698128e9ec4f91fa813499777a9)
- feat(donors): Load donors paginated [`5014bf5`](https://git.odit.services/lfk/frontend/commit/5014bf5bc5873cfe4ae04d71b4aff12b257dd2e3)
- feat(donorsoverview): Dynamicly add newly generated donors [`352551e`](https://git.odit.services/lfk/frontend/commit/352551e168b5dced5e7353e82655908d82d28af0)
- feat(donorsoverview): Implemented delete confirmation with datatable [`7aec050`](https://git.odit.services/lfk/frontend/commit/7aec050419f6f1bf853c3e1bc655b01725ed3b65)
#### [1.1.0](https://git.odit.services/lfk/frontend/compare/1.0.0...1.1.0)
> 19 April 2023
- 🚀RELEASE v1.1.0 [`0708cab`](https://git.odit.services/lfk/frontend/commit/0708cabc75e63a876e54a0b343318f8d934ae319)
- feat(dashboar): Added total donors to overview [`e0b6148`](https://git.odit.services/lfk/frontend/commit/e0b61486b089aa1e611ef3569b1521fc331ec0e4)
- feat(dashboard): Updated stats icons [`4fcb26c`](https://git.odit.services/lfk/frontend/commit/4fcb26cf9371e27e5d7e474b3558ef354e9114c0)
- feat(dashboard): Added average sponsoring [`269def2`](https://git.odit.services/lfk/frontend/commit/269def20d114ededaba3153bbd50ec2ddd70e1c6)
- feat(dashboard): Added total donations [`7b2b598`](https://git.odit.services/lfk/frontend/commit/7b2b59858839b98370af6fb1e6028ba0a1639186)
- feat(dashboard): Added average distance [`b8de9e0`](https://git.odit.services/lfk/frontend/commit/b8de9e0e427b3a8b56e6354ad7168ae12c7cce85)
- Lockfile [`3f86f74`](https://git.odit.services/lfk/frontend/commit/3f86f7412ffc4bc27328ad1f7d3c3118546e7e29)
- Bumped client [`6454d96`](https://git.odit.services/lfk/frontend/commit/6454d960de3f9f5ea86679f157b3b7e7cffde74d)
- new license file version [CI SKIP] [`2a64094`](https://git.odit.services/lfk/frontend/commit/2a640940062765a470387103a72ed14a2411d97b)
### [1.0.0](https://git.odit.services/lfk/frontend/compare/0.19.0...1.0.0)
> 19 April 2023
- 🚀RELEASE v1.0.0 [`8da7578`](https://git.odit.services/lfk/frontend/commit/8da7578a0a46a3e97d8c870e29399f6e8821c9fa)
- Merge pull request 'feature/175-request_pagination' (#176) from feature/175-request_pagination into dev [`e9ce964`](https://git.odit.services/lfk/frontend/commit/e9ce9644ff03f981cec6e9ad56aa5fdf0ff71ef4)
- Donation paginated loading [`ccf8656`](https://git.odit.services/lfk/frontend/commit/ccf865687b34016931a702c0a9b98a0a18e2b03a)
- Paginated scan loading [`cac34db`](https://git.odit.services/lfk/frontend/commit/cac34db1fd3bf5dc7c7be64b3a76ca4c8c77938d)
- Implemented Async loading of cards via pagination (500 cards per request) [`c33dfcf`](https://git.odit.services/lfk/frontend/commit/c33dfcfddddfed0902f3fa9b1d8a1d3e1560262f)
- Paginated runner loading (1000 per page) [`faf3893`](https://git.odit.services/lfk/frontend/commit/faf3893180bb735bea6f1ea58c896686b89949fe)
- Allways set loaded to true [`52439aa`](https://git.odit.services/lfk/frontend/commit/52439aa5bc8cfb1d78d5dfce55b1a0df640ad8f5)
- Bumped lfk client [`019e14a`](https://git.odit.services/lfk/frontend/commit/019e14ab1f99906f13d36c7148d0f4b7894072f2)
- new license file version [CI SKIP] [`a6ce04c`](https://git.odit.services/lfk/frontend/commit/a6ce04c90386f16abf235cc7b2f95aeea5011c7d)
#### [0.19.0](https://git.odit.services/lfk/frontend/compare/0.18.4...0.19.0)
> 17 April 2023
- 🚀RELEASE v0.19.0 [`94a64ca`](https://git.odit.services/lfk/frontend/commit/94a64ca69078c7fe2935eeb5f955fab95a79cb85)
- Merge pull request 'feature/173-scanstation_configcodes' (#174) from feature/173-scanstation_configcodes into dev [`165c154`](https://git.odit.services/lfk/frontend/commit/165c1542338c58f2abf42fef2e7b84b40d1e2d9c)
- I18n [`e60c09e`](https://git.odit.services/lfk/frontend/commit/e60c09e19c9cc20338906e84f4db4e009d926360)
- Implemented config code generation [`4b63427`](https://git.odit.services/lfk/frontend/commit/4b6342727ee0ea38597750d8c99edc301f1ccc2d)
- Styling [`4834d14`](https://git.odit.services/lfk/frontend/commit/4834d1484c3fb6ecd4a1b56aa9fbb8125c641a62)
- Adjusted size on smaller devices [`318547d`](https://git.odit.services/lfk/frontend/commit/318547db46045e41de64d5688368e85cd6fb8035)
- Lockfile [`947d01c`](https://git.odit.services/lfk/frontend/commit/947d01cf7fc7fe2ee88c56e017b0d663f1f3b4f9)
- Barcode placeholder [`cb5fa52`](https://git.odit.services/lfk/frontend/commit/cb5fa52cd9a97490b50fb0c02c26615b49650c08)
- Added bwip-js for barcode generation [`3563394`](https://git.odit.services/lfk/frontend/commit/3563394fb33d661890327e2ae08c400830b37844)
#### [0.18.4](https://git.odit.services/lfk/frontend/compare/0.18.3...0.18.4)
> 15 April 2023
- 🚀RELEASE v0.18.4 [`269d7a7`](https://git.odit.services/lfk/frontend/commit/269d7a7defdde059ef2bb5103262cf734e9babe9)
- Hide address2 in orgs by default [`e95f233`](https://git.odit.services/lfk/frontend/commit/e95f2333b0b958ed00c0e097b43aac2e70ad0d38)
#### [0.18.3](https://git.odit.services/lfk/frontend/compare/0.18.2...0.18.3)
> 15 April 2023
- 🚀RELEASE v0.18.3 [`950217e`](https://git.odit.services/lfk/frontend/commit/950217e0a350f9999b879475edf41f2f11c48179)
- Dont show adress 2 in runner overview [`5e65fb3`](https://git.odit.services/lfk/frontend/commit/5e65fb33013c3dad38e7ad6740b017ae206f278f)
#### [0.18.2](https://git.odit.services/lfk/frontend/compare/0.18.1...0.18.2)
> 15 April 2023
- 🚀RELEASE v0.18.2 [`2a294cd`](https://git.odit.services/lfk/frontend/commit/2a294cde040044bbebfb9c8b34b6c91b27772741)
- Added timestamps to scanoverview [`cffbd17`](https://git.odit.services/lfk/frontend/commit/cffbd17dc77054048cc9b14891f960f9a3fd18cb)
- Push in releaseit [`e95420d`](https://git.odit.services/lfk/frontend/commit/e95420d79c3227c0ca0cf0c0b599970c2b7d690e)
#### [0.18.1](https://git.odit.services/lfk/frontend/compare/0.18.0...0.18.1)
> 15 April 2023
- 🚀RELEASE v0.18.1 [`00de8c3`](https://git.odit.services/lfk/frontend/commit/00de8c3d75e90cd4614f42111f5f45bedde64130)
- Missing scanstation translations [`30e3396`](https://git.odit.services/lfk/frontend/commit/30e33968978bf33cedb31bcbf63fac273e1664f5)
- fix: button onclick a11y [`9fe53b0`](https://git.odit.services/lfk/frontend/commit/9fe53b0b9c71e8a6b4aa3f317327ffe729df0834)
- fix(ConfirmStatsClientDeletion): ScanStationService -> StatsClientService [`5291e04`](https://git.odit.services/lfk/frontend/commit/5291e049a1d2e880fbe277095da91b70d4812c3f)
- fix(ConfirmScanStationDeletion): donorControllerRemove -> scanStationControllerRemove [`08fbb50`](https://git.odit.services/lfk/frontend/commit/08fbb504c958415ce75e1e426296f870f0f1358d)
#### [0.18.0](https://git.odit.services/lfk/frontend/compare/0.17.3...0.18.0) #### [0.18.0](https://git.odit.services/lfk/frontend/compare/0.17.3...0.18.0)
> 12 April 2023
- Moved filter function to typed version [`#171`](https://git.odit.services/lfk/frontend/issues/171) - Moved filter function to typed version [`#171`](https://git.odit.services/lfk/frontend/issues/171)
- ScansOverview: migrate to datatable [`#168`](https://git.odit.services/lfk/frontend/issues/168) - ScansOverview: migrate to datatable [`#168`](https://git.odit.services/lfk/frontend/issues/168)
- 🚀RELEASE v0.18.0 [`eb80406`](https://git.odit.services/lfk/frontend/commit/eb80406fdb8abf3f76bca742095e8f1f03480a56)
- wip: ScansOverview -> new datatable [`c87561f`](https://git.odit.services/lfk/frontend/commit/c87561f63b90ab951daf91d9b8b54ba96a94cc7f) - wip: ScansOverview -> new datatable [`c87561f`](https://git.odit.services/lfk/frontend/commit/c87561f63b90ab951daf91d9b8b54ba96a94cc7f)
- Basic card table replace [`5662c3b`](https://git.odit.services/lfk/frontend/commit/5662c3b6da67c00c94254bf39f8820e531fc93ef) - Basic card table replace [`5662c3b`](https://git.odit.services/lfk/frontend/commit/5662c3b6da67c00c94254bf39f8820e531fc93ef)
- RunnersOverview: table responsiveness [`bf1e715`](https://git.odit.services/lfk/frontend/commit/bf1e715261c0076fd8543dd1187c516209a73b16) - RunnersOverview: table responsiveness [`bf1e715`](https://git.odit.services/lfk/frontend/commit/bf1e715261c0076fd8543dd1187c516209a73b16)

View File

@@ -13,7 +13,7 @@
</head> </head>
<body> <body>
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.18.0-RELEASE_INFO</span> <span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-1.3.3-RELEASE_INFO</span>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/env.js"></script> <script src="/env.js"></script>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>

View File

@@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-frontend", "name": "@odit/lfk-frontend",
"version": "0.18.0", "version": "1.3.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"i18n-order": "node order.js", "i18n-order": "node order.js",
@@ -26,7 +26,7 @@
"commit": true, "commit": true,
"requireCleanWorkingDir": false, "requireCleanWorkingDir": false,
"commitMessage": "🚀RELEASE v${version}", "commitMessage": "🚀RELEASE v${version}",
"push": false, "push": true,
"tag": true, "tag": true,
"tagName": null, "tagName": null,
"tagAnnotation": "v${version}" "tagAnnotation": "v${version}"
@@ -39,9 +39,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@odit/lfk-client-js": "0.14.3", "@odit/lfk-client-js": "1.1.1",
"@paralleldrive/cuid2": "^2.2.0", "@paralleldrive/cuid2": "^2.2.0",
"@tanstack/svelte-table": "^8.8.5", "@tanstack/svelte-table": "^8.8.5",
"bwip-js": "^3.4.0",
"check-password-strength": "2.0.7", "check-password-strength": "2.0.7",
"csvtojson": "2.0.10", "csvtojson": "2.0.10",
"gridjs": "3.4.0", "gridjs": "3.4.0",

16
pnpm-lock.yaml generated
View File

@@ -2,14 +2,17 @@ lockfileVersion: '6.0'
dependencies: dependencies:
'@odit/lfk-client-js': '@odit/lfk-client-js':
specifier: 0.14.3 specifier: 1.1.0
version: 0.14.3 version: 1.1.0
'@paralleldrive/cuid2': '@paralleldrive/cuid2':
specifier: ^2.2.0 specifier: ^2.2.0
version: 2.2.0 version: 2.2.0
'@tanstack/svelte-table': '@tanstack/svelte-table':
specifier: ^8.8.5 specifier: ^8.8.5
version: 8.8.5(svelte@3.58.0) version: 8.8.5(svelte@3.58.0)
bwip-js:
specifier: ^3.4.0
version: 3.4.0
check-password-strength: check-password-strength:
specifier: 2.0.7 specifier: 2.0.7
version: 2.0.7 version: 2.0.7
@@ -507,8 +510,8 @@ packages:
'@octokit/openapi-types': 16.0.0 '@octokit/openapi-types': 16.0.0
dev: true dev: true
/@odit/lfk-client-js@0.14.3: /@odit/lfk-client-js@1.1.0:
resolution: {integrity: sha512-oOZ9jjzqcbMA0Sfwxn4q9+8hHckMU2IhAn7v0OAS54zcnquYQANnY4RMEoNIyXd0oEe1z8QewBjyBvFEDg6BmA==} resolution: {integrity: sha512-yhjsi7YMzL9/fJ7o06yszzw15iZhao3VmX0G9oqZWFwYJd1M2td3Lvm76mXNzTVlbdG6W0W3+eEjcalBdo51Pg==}
dev: false dev: false
/@odit/license-exporter@0.0.12: /@odit/license-exporter@0.0.12:
@@ -847,6 +850,11 @@ packages:
run-applescript: 5.0.0 run-applescript: 5.0.0
dev: true dev: true
/bwip-js@3.4.0:
resolution: {integrity: sha512-Gx9LIBhmEFmNH4FJsS+Rs+bG5hUcs+OBemEEQ2ZTLz8tue0PA/lM692Gf2yuYJ2yUpLGtK9tAexs85tXBPG/ww==}
hasBin: true
dev: false
/bytes@3.1.2: /bytes@3.1.2:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}

File diff suppressed because one or more lines are too long

View File

@@ -32,7 +32,7 @@
export let original_data = {}; export let original_data = {};
export let current_cards = []; export let current_cards = [];
export const addCards = (cards) => { export const addCards = (cards) => {
console.log(cards) console.log(cards);
current_cards = current_cards.concat(...cards); current_cards = current_cards.concat(...cards);
options.update((options) => ({ options.update((options) => ({
...options, ...options,
@@ -155,15 +155,27 @@
}).showToast(); }).showToast();
} }
onMount(() => { onMount(async () => {
RunnerCardService.runnerCardControllerGetAll().then((val) => { let page = 0;
current_cards = val; while (page >= 0) {
const cards = await RunnerCardService.runnerCardControllerGetAll(
page,
500
);
if (cards.length == 0) {
page = -2;
}
current_cards = current_cards.concat(...cards);
options.update((options) => ({ options.update((options) => ({
...options, ...options,
data: current_cards, data: current_cards,
})); }));
dataLoaded = true; dataLoaded = true;
}); page++;
}
console.log("All cards loaded");
}); });
</script> </script>
@@ -229,7 +241,7 @@
...options, ...options,
data: current_cards, data: current_cards,
})); }));
$table.resetRowSelection() $table.resetRowSelection();
}} }}
> >
{$_("delete-cards")} {$_("delete-cards")}
@@ -249,7 +261,10 @@
</svg> </svg>
</button> </button>
{/if} {/if}
<GenerateRunnerCards cards_show={selected.length>0} bind:generate_cards={selectedCards} /> <GenerateRunnerCards
cards_show={selected.length > 0}
bind:generate_cards={selectedCards}
/>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="w-full"> <table class="w-full">

View File

@@ -35,7 +35,9 @@
<p class="text-sm">{$_("this-might-take-a-moment")}</p> <p class="text-sm">{$_("this-might-take-a-moment")}</p>
</div> </div>
{:then stats} {:then stats}
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 gap-4"> <div
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 gap-4"
>
<StatCard <StatCard
title={$_("runners")} title={$_("runners")}
value={stats.total_runners} value={stats.total_runners}
@@ -59,18 +61,67 @@
href="/scans/" href="/scans/"
> >
<svg <svg
stroke="currentColor"
fill="currentColor" fill="currentColor"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
size="24"
class="stroke-current text-grey-500"
height="24"
width="24" width="24"
height="24"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
><polyline points="22 12 18 12 15 21 9 3 6 12 2 12" /></svg viewBox="0 0 24 24"
><path fill="none" d="M0 0h24v24H0z" />
<path
fill="currentColor"
d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z"
/></svg
>
</StatCard>
<StatCard
title={$_("total-donors")}
value={stats.total_donors}
href="/donors/"
>
<svg
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
><path fill="none" d="M0 0h24v24H0z" />
<path
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
/></svg
>
</StatCard>
<StatCard
title={$_("total-donation-count")}
value={stats.total_donations}
href="/donations/"
>
<svg
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
><path fill="none" d="M0 0h24v24H0z" />
<path
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
/></svg
>
</StatCard>
<StatCard
title={$_("average-donation")}
value={`${(stats.average_donation / 100).toFixed(2)} €`}
href="/donations/"
>
<svg
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
><path fill="none" d="M0 0h24v24H0z" />
<path
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
/></svg
> >
</StatCard> </StatCard>
<StatCard <StatCard
@@ -105,6 +156,22 @@
/></svg /></svg
> >
</StatCard> </StatCard>
<StatCard
title={$_("average-distance")}
value={`${(stats.average_distance / 1000).toFixed(2)} km`}
href="#"
>
<svg
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
height="24"
width="24"
><path d="M0 0h24v24H0z" fill="none" />
<path
d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"
/></svg
>
</StatCard>
<StatCard <StatCard
title={$_("count_teams")} title={$_("count_teams")}
value={stats.total_teams} value={stats.total_teams}

View File

@@ -9,9 +9,10 @@
} from "@odit/lfk-client-js"; } from "@odit/lfk-client-js";
import Select from "svelte-select"; import Select from "svelte-select";
import Toastify from "toastify-js"; import Toastify from "toastify-js";
import { is_promise } from "svelte/internal"; import { is_promise } from "svelte/internal";
import { createEventDispatcher } from "svelte";
export let modal_open; export let modal_open;
export let current_donations; const dispatch = createEventDispatcher();
const getDonorLabel = (option) => const getDonorLabel = (option) =>
option.firstname + " " + (option.middlename || "") + " " + option.lastname; option.firstname + " " + (option.middlename || "") + " " + option.lastname;
const filterDonors = (label, filterText, option) => const filterDonors = (label, filterText, option) =>
@@ -59,16 +60,16 @@ import { is_promise } from "svelte/internal";
let amount_cent = Math.floor(amount_input * 100); let amount_cent = Math.floor(amount_input * 100);
processed_last_submit = false; processed_last_submit = false;
const toast = Toastify({ const toast = Toastify({
text: $_('adding-donation'), text: $_("adding-donation"),
duration: -1, duration: -1,
}).showToast(); }).showToast();
if (is_fixed) { if (is_fixed) {
let postdata = { let postdata = {
donor, donor,
amount: amount_cent, amount: amount_cent,
paidAmount: 0 paidAmount: 0,
}; };
if(is_paid){ if (is_paid) {
postdata.paidAmount = amount_cent; postdata.paidAmount = amount_cent;
} }
DonationService.donationControllerPostFixed(postdata) DonationService.donationControllerPostFixed(postdata)
@@ -79,12 +80,11 @@ import { is_promise } from "svelte/internal";
modal_open = false; modal_open = false;
// //
Toastify({ Toastify({
text: $_('donation_added'), text: $_("donation_added"),
duration: 500, duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast(); }).showToast();
current_donations.push(result); dispatch("created", { donations: [result] });
current_donations = current_donations;
}) })
.catch((err) => { .catch((err) => {
// //
@@ -108,12 +108,11 @@ import { is_promise } from "svelte/internal";
modal_open = false; modal_open = false;
// //
Toastify({ Toastify({
text: $_('donation_added'), text: $_("donation_added"),
duration: 500, duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast(); }).showToast();
current_donations.push(result); dispatch("created", { donations: [result] });
current_donations = current_donations;
}) })
.catch((err) => { .catch((err) => {
// //
@@ -128,6 +127,207 @@ import { is_promise } from "svelte/internal";
} }
</script> </script>
{#if modal_open}
<div
class="fixed z-10 inset-0 overflow-y-auto"
use:clickOutside
on:click_outside={() => {
modal_open = false;
}}
>
<div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
>
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div
class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop"
/>
</div>
<span
class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span
>
<div
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline"
>
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
>
<svg
class="h-6 w-6 text-blue-600"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
><path fill="none" d="M0 0h24v24H0z" />
<path
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
/></svg
>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{#if is_fixed}
{$_("create-a-new-fixed-donation")}
{:else}{$_("create-a-new-distance-donation")}{/if}
</h3>
<label class="content-center align-middle object-center">
<span class="ml-2 text-base" class:text-gray-300={is_fixed}
>{$_("distance-donation")}</span
>
<input
class="toggle relative w-10 h-5 transition-all duration-200 ease-in-out bg-gray-400 rounded-full shadow-inner outline-none appearance-none align-middle"
type="checkbox"
bind:checked={is_fixed}
/>
<span class="ml-2 text-base" class:text-gray-300={!is_fixed}
>{$_("fixed-donation")}</span
>
</label>
<div class="mt-2 mb-6">
<p class="text-sm text-gray-500">
{$_(
"please-provide-the-nessecary-information-to-create-a-new-donation"
)}
</p>
</div>
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6">
<label
for="donor"
class="block text-sm font-medium text-gray-700"
>{$_("donor")}</label
>
<Select
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
itemFilter={(label, filterText, option) =>
filterDonors(label, filterText, option)}
items={donors}
showChevron={true}
placeholder={$_("search-for-donor-name-or-id")}
noOptionsMessage={$_("no-donors-found")}
on:select={(selectedValue) =>
(donor = selectedValue.detail.value.id)}
on:clear={() => (donors = null)}
/>
</div>
{#if !is_fixed}
<div class="col-span-6">
<label
for="donor"
class="block text-sm font-medium text-gray-700"
>{$_("runner")}</label
>
<Select
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
itemFilter={(label, filterText, option) =>
filterDonors(label, filterText, option)}
items={runners}
showChevron={true}
placeholder={$_("search-for-runner-by-name-or-id")}
noOptionsMessage={$_("no-runners-found")}
on:select={(selectedValue) =>
(runner = selectedValue.detail.value.id)}
on:clear={() => (runner = null)}
/>
</div>
{/if}
<div class="col-span-6">
<label
for="donation_amount_eur"
class="block text-sm font-medium text-gray-700"
>
{#if !is_fixed}
{$_("amount-per-kilometer")}
{:else}{$_("donation-amount")}{/if}</label
>
<div class="mt-1 flex rounded-md shadow-sm">
<input
autocomplete="off"
class:border-red-500={!is_amount_valid}
class:focus:border-red-500={!is_amount_valid}
class:focus:ring-red-500={!is_amount_valid}
bind:value={amount_input}
type="number"
step="0.01"
name="donation_amount_eur"
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
placeholder="2.00"
/>
<span
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
></span
>
</div>
{#if !is_amount_valid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
>
{$_("donation-amount-must-be-greater-that-0-00eur")}
</span>
{/if}
</div>
{#if is_fixed}
<div class="col-span-6">
<label
for="paid"
class="block text-sm font-medium text-gray-700"
>{$_("already-paid")}</label
>
<p class="text-gray-500">
<input
id="paid"
bind:checked={is_paid}
name="paid"
type="checkbox"
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
<span class="align-text-bottom">
{#if is_paid}
{$_("paid")}
{:else}
{$_("open")}
{/if}
</span>
</p>
</div>
{/if}
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button
disabled={!createbtnenabled}
class:opacity-50={!createbtnenabled}
on:click={submit}
type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
>
{$_("create")}
</button>
<button
on:click={() => {
modal_open = false;
}}
type="button"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
>
{$_("cancel")}
</button>
</div>
</div>
</div>
</div>
{/if}
<style> <style>
.toggle:before { .toggle:before {
content: ""; content: "";
@@ -152,173 +352,3 @@ import { is_promise } from "svelte/internal";
left: 1.25rem; left: 1.25rem;
} }
</style> </style>
{#if modal_open}
<div
class="fixed z-10 inset-0 overflow-y-auto"
use:clickOutside
on:click_outside={() => {
modal_open = false;
}}>
<div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div
class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop" />
</div>
<span
class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span>
<div
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<svg
class="h-6 w-6 text-blue-600"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"><path fill="none" d="M0 0h24v24H0z" />
<path
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z" /></svg>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{#if is_fixed}
{$_('create-a-new-fixed-donation')}
{:else}{$_('create-a-new-distance-donation')}{/if}
</h3>
<label class="content-center align-middle object-center">
<span
class="ml-2 text-base"
class:text-gray-300={is_fixed}>{$_('distance-donation')}</span>
<input
class="toggle relative w-10 h-5 transition-all duration-200 ease-in-out bg-gray-400 rounded-full shadow-inner outline-none appearance-none align-middle"
type="checkbox"
bind:checked={is_fixed} />
<span
class="ml-2 text-base "
class:text-gray-300={!is_fixed}>{$_('fixed-donation')}</span>
</label>
<div class="mt-2 mb-6">
<p class="text-sm text-gray-500">
{$_('please-provide-the-nessecary-information-to-create-a-new-donation')}
</p>
</div>
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6">
<label
for="donor"
class="block text-sm font-medium text-gray-700">{$_('donor')}</label>
<Select
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
itemFilter={(label, filterText, option) => filterDonors(label, filterText, option)}
items={donors}
showChevron={true}
placeholder={$_('search-for-donor-name-or-id')}
noOptionsMessage={$_('no-donors-found')}
on:select={(selectedValue) => (donor = selectedValue.detail.value.id)}
on:clear={() => (donors = null)} />
</div>
{#if !is_fixed}
<div class="col-span-6">
<label
for="donor"
class="block text-sm font-medium text-gray-700">{$_('runner')}</label>
<Select
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
itemFilter={(label, filterText, option) => filterDonors(label, filterText, option)}
items={runners}
showChevron={true}
placeholder={$_('search-for-runner-by-name-or-id')}
noOptionsMessage={$_('no-runners-found')}
on:select={(selectedValue) => (runner = selectedValue.detail.value.id)}
on:clear={() => (runner = null)} />
</div>
{/if}
<div class="col-span-6">
<label
for="donation_amount_eur"
class="block text-sm font-medium text-gray-700">
{#if !is_fixed}
{$_('amount-per-kilometer')}
{:else}{$_('donation-amount')}{/if}</label>
<div class="mt-1 flex rounded-md shadow-sm">
<input
autocomplete="off"
class:border-red-500={!is_amount_valid}
class:focus:border-red-500={!is_amount_valid}
class:focus:ring-red-500={!is_amount_valid}
bind:value={amount_input}
type="number"
step="0.01"
name="donation_amount_eur"
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
placeholder="2.00" />
<span
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"></span>
</div>
{#if !is_amount_valid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
{$_('donation-amount-must-be-greater-that-0-00eur')}
</span>
{/if}
</div>
{#if is_fixed}
<div class="col-span-6">
<label
for="paid"
class="block text-sm font-medium text-gray-700">{$_('already-paid')}</label>
<p class="text-gray-500">
<input
id="paid"
bind:checked={is_paid}
name="paid"
type="checkbox"
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" >
<span class="align-text-bottom">
{#if is_paid}
{$_('paid')}
{:else}
{$_('open')}
{/if}
</span>
</p>
</div>
{/if}
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button
disabled={!createbtnenabled}
class:opacity-50={!createbtnenabled}
on:click={submit}
type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
{$_('create')}
</button>
<button
on:click={() => {
modal_open = false;
}}
type="button"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
{$_('cancel')}
</button>
</div>
</div>
</div>
</div>
{/if}

View File

@@ -4,16 +4,18 @@
import { DonationService } from "@odit/lfk-client-js"; import { DonationService } from "@odit/lfk-client-js";
import Toastify from "toastify-js"; import Toastify from "toastify-js";
import { createEventDispatcher } from "svelte";
export let payment_modal_open = false; export let payment_modal_open = false;
export let current_donations = [];
export let editable = {};
export let original_data = {}; export let original_data = {};
export let paid_amount_input = 0; export let paid_amount_input = 0;
$:processed_last_submit=true; const dispatch = createEventDispatcher();
$: processed_last_submit = true;
function focus(el) { function focus(el) {
el.focus(); el.focus();
} }
$: createbtnenabled = is_paid_amount_valid && !(paid_amount_input*100 == original_data.paidAmount) $: createbtnenabled =
is_paid_amount_valid &&
!(paid_amount_input * 100 == original_data.paidAmount);
$: is_paid_amount_valid = paid_amount_input > 0; $: is_paid_amount_valid = paid_amount_input > 0;
(() => { (() => {
document.onkeydown = (e) => { document.onkeydown = (e) => {
@@ -33,61 +35,56 @@
if (processed_last_submit === true) { if (processed_last_submit === true) {
processed_last_submit = false; processed_last_submit = false;
const toast = Toastify({ const toast = Toastify({
text: $_('updating-donation'), text: $_("updating-donation"),
duration: -1, duration: -1,
}).showToast(); }).showToast();
const editable = Object.assign({}, original_data);
editable.donor = editable.donor.id; editable.donor = editable.donor.id;
editable.paidAmount = paid_amount_input*100; editable.paidAmount = paid_amount_input * 100;
if(editable.responseType == "DISTANCEDONATION" || editable.runner){ if (editable.responseType == "DISTANCEDONATION" || editable.runner) {
editable.runner = editable.runner.id; editable.runner = editable.runner.id;
DonationService.donationControllerPutDistance(original_data.id, editable) DonationService.donationControllerPutDistance(
.then((result) => { original_data.id,
let id = original_data.id; editable
editable = {}; )
original_data = {}; .then((result) => {
payment_modal_open = false; payment_modal_open = false;
// //
Toastify({ Toastify({
text: $_('donation-updated'), text: $_("donation-updated"),
duration: 500, duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast(); }).showToast();
current_donations[current_donations.findIndex((c) => c.id === id)] = result; dispatch("created", { donation: response });
current_donations = current_donations; })
}) .catch((err) => {
.catch((err) => { //
// })
}) .finally(() => {
.finally(() => { processed_last_submit = true;
processed_last_submit = true; //
// toast.hideToast();
toast.hideToast(); });
}); } else {
} DonationService.donationControllerPutFixed(original_data.id, editable)
else{ .then((result) => {
DonationService.donationControllerPutFixed(original_data.id, editable) payment_modal_open = false;
.then((result) => { //
let id = original_data.id; Toastify({
editable = {}; text: $_("donation-updated"),
original_data = {}; duration: 500,
payment_modal_open = false; backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
// }).showToast();
Toastify({ dispatch("created", { donation: response });
text: $_('donation-updated'), })
duration: 500, .catch((err) => {
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", //
}).showToast(); })
current_donations[current_donations.findIndex((c) => c.id === id)] = result; .finally(() => {
current_donations = current_donations; processed_last_submit = true;
}) //
.catch((err) => { toast.hideToast();
// });
})
.finally(() => {
processed_last_submit = true;
//
toast.hideToast();
});
} }
} }
} }
@@ -96,57 +93,71 @@
{#if payment_modal_open} {#if payment_modal_open}
<div <div
class="fixed z-10 inset-0 overflow-y-auto" class="fixed z-10 inset-0 overflow-y-auto"
use:clickOutside use:clickOutside
on:click_outside={() => { on:click_outside={() => {
payment_modal_open = false; payment_modal_open = false;
}}> }}
>
<div <div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
>
<div class="fixed inset-0 transition-opacity" aria-hidden="true"> <div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div <div
class="absolute inset-0 bg-gray-500 opacity-75" class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop" /> data-id="modal_backdrop"
/>
</div> </div>
<span <span
class="hidden sm:inline-block sm:align-middle sm:h-screen" class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span> aria-hidden="true">&#8203;</span
>
<div <div
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog" role="dialog"
aria-modal="true" aria-modal="true"
aria-labelledby="modal-headline"> aria-labelledby="modal-headline"
>
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start"> <div class="sm:flex sm:items-start">
<div <div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"> class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
>
<svg <svg
class="h-6 w-6 text-blue-600" class="h-6 w-6 text-blue-600"
fill="currentColor" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" viewBox="0 0 24 24"
width="24" width="24"
height="24"><path fill="none" d="M0 0h24v24H0z" /> height="24"
><path fill="none" d="M0 0h24v24H0z" />
<path <path
fill="currentColor" fill="currentColor"
d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z" /></svg> d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
/></svg
>
</div> </div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900"> <h3 class="text-lg leading-6 font-medium text-gray-900">
{$_('enter-payment')} {$_("enter-payment")}
</h3> </h3>
<div class="mt-2 mb-6"> <div class="mt-2 mb-6">
<p class="text-sm text-gray-500"> <p class="text-sm text-gray-500">
{$_('you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount')} {$_(
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount"
)}
</p> </p>
</div> </div>
<div class="grid grid-cols gap-6"> <div class="grid grid-cols gap-6">
<div class="w-full"> <div class="w-full">
<label <label
for="token" for="token"
class="block text-sm font-medium text-gray-700">{$_('paid-amount')}</label> class="block text-sm font-medium text-gray-700"
<div class="inline-flex border-gray-300 border rounded-l-md rounded-r-md bg-gray-50 text-gray-500 w-full"> >{$_("paid-amount")}</label
<input >
<div
class="inline-flex border-gray-300 border rounded-l-md rounded-r-md bg-gray-50 text-gray-500 w-full"
>
<input
autocomplete="off" autocomplete="off"
class:border-red-500={!is_paid_amount_valid} class:border-red-500={!is_paid_amount_valid}
class:focus:border-red-500={!is_paid_amount_valid} class:focus:border-red-500={!is_paid_amount_valid}
@@ -156,47 +167,55 @@
step="0.01" step="0.01"
name="donation_amount_eur" name="donation_amount_eur"
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm p-2" class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm p-2"
placeholder="2.00" /> placeholder="2.00"
/>
<button <button
on:click={ on:click={() => {
()=>{ paid_amount_input = paid_amount_input = (
paid_amount_input=paid_amount_input = (original_data.amount/100).toFixed(2); original_data.amount / 100
} ).toFixed(2);
} }}
class="inline-flex items-center p-r-2 text-indigo-300 hover:text-indigo-700 text-sm">MAX</button> class="inline-flex items-center p-r-2 text-indigo-300 hover:text-indigo-700 text-sm"
>MAX</button
>
<span <span
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"></span> class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
></span
>
</div> </div>
{#if !is_paid_amount_valid} {#if !is_paid_amount_valid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
{$_('payment-amount-must-be-greater-than-0-00eur')} >
{$_("payment-amount-must-be-greater-than-0-00eur")}
</span> </span>
{/if} {/if}
</div> </div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> </div>
<button <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
disabled={!createbtnenabled} <button
class:opacity-50={!createbtnenabled} disabled={!createbtnenabled}
on:click={submit} class:opacity-50={!createbtnenabled}
type="button" on:click={submit}
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> type="button"
{$_('save-changes')} class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
</button> >
<button {$_("save-changes")}
on:click={() => { </button>
payment_modal_open = false; <button
}} on:click={() => {
type="button" payment_modal_open = false;
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"> }}
{$_('cancel')} type="button"
</button> class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
</div> >
{$_("cancel")}
</button>
</div> </div>
</div> </div>
</div> </div>
</div>
{/if} {/if}

View File

@@ -0,0 +1,122 @@
<script>
import { _ } from "svelte-i18n";
import { clickOutside } from "../base/outsideclick";
import { createEventDispatcher, onMount } from "svelte";
export let modal_open;
export let delete_donation = {
id: 0,
runner: {
firstname: "",
lastname: "",
},
donor: {
firstname: "",
lastname: "",
},
};
const dispatch = createEventDispatcher();
onMount(() => {
document.onkeydown = (e) => {
e = e || window.event;
if (e.key === "Escape") {
modal_open = false;
}
if (e.keyCode === 13) {
if (createbtnenabled === true) {
createbtnenabled = false;
submit();
}
}
};
});
async function submit() {
dispatch("delete", { id: delete_donation.id });
modal_open = false;
}
</script>
{#if modal_open}
<div
class="fixed z-10 inset-0 overflow-y-auto"
use:clickOutside
on:click_outside={() => {
modal_open = false;
}}
>
<div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
>
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div
class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop"
/>
</div>
<span
class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span
>
<div
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline"
>
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
>
<svg
class="h-6 w-6 text-blue-600"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
><path fill="none" d="M0 0h24v24H0z" />
<path
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
/></svg
>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{$_("confirm-delete")}
</h3>
<div class="mt-2 mb-6">
<p class="text-sm text-gray-500">
{$_("please-confirm-the-deletion-of-donation")}
</p>
</div>
<div class="w-full">
<span class="inline-block"
><b>{$_("donor")}</b>: {delete_donation.donor.firstname}
{delete_donation.donor.lastname}</span
>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button
on:click={submit}
type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
>
{$_("delete")}
</button>
<button
on:click={() => {
modal_open = false;
}}
type="button"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
>
{$_("cancel")}
</button>
</div>
</div>
</div>
</div>
{/if}

View File

@@ -0,0 +1,18 @@
<script>
import { _ } from "svelte-i18n";
export let donor;
</script>
{#if !donor || donor.firstname == 0}
{$_("donor-has-no-associated-donations")}
{:else}
<div class="flex items-center">
<a
href="../donors/{donor.id}"
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
>{donor.firstname}
{#if donor.middlename}{donor.middlename}{/if}
{donor.lastname}</a
>
</div>
{/if}

View File

@@ -0,0 +1,18 @@
<script>
import { _ } from "svelte-i18n";
export let runner;
</script>
{#if !runner || runner.firstname == 0}
{$_("fixed-donation")}
{:else}
<div class="text-sm font-medium text-gray-900">
<a
href="../runners/{runner.id}"
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
>{runner.firstname}
{#if runner.middlename}{runner.middlename}{/if}
{runner.lastname}</a
>
</div>
{/if}

View File

@@ -0,0 +1,16 @@
<script>
import { _ } from "svelte-i18n";
export let status;
</script>
{#if status == "PAID"}
<span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
>{$_("paid")}</span
>
{:else}
<span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
>{$_("open")}</span
>
{/if}

View File

@@ -0,0 +1,21 @@
<script>
import { _ } from "svelte-i18n";
import TableActions from "../shared/TableActions.svelte";
export let detailsLink;
export let detailsAction;
export let deleteEnabled;
export let deleteAction;
export let paymentAction;
</script>
<button
on:click={paymentAction}
class="text-[#025a21] hover:text-green-900 mr-4">{$_("enter-payment")}</button
>
<TableActions
bind:detailsAction
bind:detailsLink
bind:deleteAction
bind:deleteEnabled
/>

View File

@@ -5,25 +5,33 @@
import DonationsOverview from "./DonationsOverview.svelte"; import DonationsOverview from "./DonationsOverview.svelte";
$: current_donations = []; $: current_donations = [];
export let modal_open = false; export let modal_open = false;
let addDonations;
</script> </script>
<section class="container p-5"> <section class="container p-5">
<span class="mb-1 text-3xl font-extrabold leading-tight"> <span class="mb-1 text-3xl font-extrabold leading-tight">
{$_('donations')} {$_("donations")}
{#if store.state.jwtinfo.userdetails.permissions.includes('DONATION:CREATE')} {#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}
<button <button
on:click={() => { on:click={() => {
modal_open = true; modal_open = true;
}} }}
type="button" type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
{$_('add-donation')} >
{$_("add-donation")}
</button> </button>
{/if} {/if}
</span> </span>
<DonationsOverview bind:current_donations /> <DonationsOverview bind:current_donations bind:addDonations />
</section> </section>
{#if store.state.jwtinfo.userdetails.permissions.includes('DONATION:CREATE')} {#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}
<AddDonationModal bind:current_donations bind:modal_open /> <AddDonationModal
on:created={(event) => {
console.log(event)
addDonations(event.detail.donations);
}}
bind:modal_open
/>
{/if} {/if}

View File

@@ -1,235 +1,284 @@
<script> <script>
import { getLocaleFromNavigator, _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { DonationService, DonorService } from "@odit/lfk-client-js"; import { DonationService } from "@odit/lfk-client-js";
import store from "../../store"; import store from "../../store";
import Toastify from "toastify-js";
import DonationsEmptyState from "./DonationsEmptyState.svelte"; import DonationsEmptyState from "./DonationsEmptyState.svelte";
import AddDonationPaymentModal from "./AddDonationPaymentModal.svelte"; import AddDonationPaymentModal from "./AddDonationPaymentModal.svelte";
import { onMount } from "svelte";
import {
createSvelteTable,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
renderComponent,
} from "@tanstack/svelte-table";
import { writable } from "svelte/store";
import TableBottom from "../shared/TableBottom.svelte";
import InputElement from "../shared/InputElement.svelte";
import TableHeader from "../shared/TableHeader.svelte";
import DonationDonor from "./DonationDonor.svelte";
import DonationRunner from "./DonationRunner.svelte";
import DonationStatus from "./DonationStatus.svelte";
import DonationTableAction from "./DonationTableAction.svelte";
import DeleteDonationModal from "./DeleteDonationModal.svelte";
import { donationDonorFilter, donationRunnerFilter } from "../shared/tablefilters";
$: searchvalue = ""; $: searchvalue = "";
$: active_deletes = []; $: active_deletes = [];
$: active_edits = [];
$: selectedDonations =
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
$: selected =
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
$: dataLoaded = false;
export let current_donations = []; export let current_donations = [];
export let payment_modal_open = false; export const addDonations = (donations) => {
export let editable = {}; current_donations = current_donations.concat(...donations);
export let original_data = {}; options.update((options) => ({
export let paid_amount_input = 0; ...options,
const donations_promise = DonationService.donationControllerGetAll().then( data: current_donations,
(val) => { }));
current_donations = val; };
}
); //Section table
function should_display_based_on_id(id) { const columns = [
if (searchvalue.toString().slice(-1) === "*") { {
return id.toString().startsWith(searchvalue.replace("*", "")); accessorKey: "id",
} header: () => "id",
return id.toString() === searchvalue; filterFn: `equalsString`,
} },
function open_payment_modal(donation) { {
editable = Object.assign({}, donation); accessorKey: "donor",
original_data = Object.assign({}, donation); header: () => $_("donor"),
paid_amount_input = (donation.paidAmount/100).toFixed(2); cell: (info) => {
payment_modal_open = true; return renderComponent(DonationDonor, { donor: info.getValue() });
},
filterFn: `donor`,
},
{
accessorKey: "runner",
header: () => $_("runner"),
cell: (info) => {
return renderComponent(DonationRunner, { runner: info.getValue() });
},
filterFn: `runner`,
},
{
accessorKey: "amountPerDistance",
header: () => $_("amount-per-kilometer"),
cell: (info) => {
if (!info.getValue()) {
return $_("fixed-donation");
}
return `${(info.getValue() / 100)
.toFixed(2)
.toLocaleString("de-DE", { valute: "EUR" })} €`;
},
enableColumnFilter: false,
},
{
accessorKey: "amount",
header: () => $_("donation-amount"),
cell: (info) => {
return `${(info.getValue() / 100)
.toFixed(2)
.toLocaleString("de-DE", { valute: "EUR" })} €`;
},
enableColumnFilter: false,
},
{
accessorKey: "paidAmount",
header: () => $_("total-paid-amount"),
cell: (info) => {
return `${(info.getValue() / 100)
.toFixed(2)
.toLocaleString("de-DE", { valute: "EUR" })} €`;
},
enableColumnFilter: false,
},
{
accessorKey: "status",
header: () => $_("status"),
cell: (info) => {
return renderComponent(DonationStatus, { status: info.getValue() });
},
enableColumnFilter: false,
},
{
accessorKey: "actions",
header: () => $_("action"),
cell: (info) => {
return renderComponent(DonationTableAction, {
detailsLink: `./${info.row.original.id}`,
deleteAction: () => {
active_deletes = current_donations.filter(
(r) => r.id == info.row.original.id
);
},
paymentAction: () => {
active_edits = current_donations.filter(
(r) => r.id == info.row.original.id
);
},
deleteEnabled:
store.state.jwtinfo.userdetails.permissions.includes(
"DONATION:DELETE"
),
});
},
enableColumnFilter: false,
enableSorting: false,
},
];
const options = writable({
data: [],
columns: columns,
initialState: {
pagination: {
pageSize: 50,
},
},
filterFns: {
donor: donationDonorFilter,
runner: donationRunnerFilter,
},
enableRowSelection: true,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
});
const table = createSvelteTable(options);
async function deleteDonation(delete_donation_id) {
await DonationService.donationControllerRemove(delete_donation_id, true);
current_donations = current_donations.filter(
(r) => r.id !== delete_donation_id
);
options.update((options) => ({
...options,
data: current_donations,
}));
Toastify({
text: $_("donation-deleted"),
duration: 3500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast();
} }
onMount(async () => {
let page = 0;
while (page >= 0) {
const donations = await DonationService.donationControllerGetAll(
page,
500
);
if (donations.length == 0) {
page = -2;
}
current_donations = current_donations.concat(...donations);
options.update((options) => ({
...options,
data: current_donations,
}));
dataLoaded = true;
page++;
}
console.log("All donations loaded");
});
</script> </script>
<AddDonationPaymentModal bind:current_donations bind:original_data bind:editable bind:paid_amount_input bind:payment_modal_open /> <AddDonationPaymentModal
{#if store.state.jwtinfo.userdetails.permissions.includes('DONATION:GET')} original_data={active_edits[0]}
{#await donations_promise} payment_modal_open={active_edits.length > 0}
paid_amount_input={(active_edits[0]?.paidAmount || 0) / 100}
on:created={(event) => {
current_donations[
current_donations.findIndex((d) => d.id === event.detail.donation.id)
].paidAmount = event.detail.donation.paidAmount;
options.update((options) => ({
...options,
data: current_donations,
}));
}}
/>
<DeleteDonationModal
delete_donation={active_deletes[0]}
modal_open={active_deletes.length > 0}
on:delete={(event) => {
deleteDonation(event.detail.id);
}}
/>
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")}
{#if !dataLoaded}
<div <div
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
role="alert"> role="alert"
<p class="font-bold">donations are being loaded</p> >
<p class="text-sm">{$_('this-might-take-a-moment')}</p> <p class="font-bold">{$_("donations-are-being-loaded")}</p>
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
</div> </div>
{:then} {:else if current_donations.length === 0}
{#if current_donations.length === 0} <DonationsEmptyState />
<DonationsEmptyState /> {:else}
{:else} <input
<input type="search"
type="search" bind:value={searchvalue}
bind:value={searchvalue} placeholder={$_("datatable.search")}
placeholder={$_('datatable.search')} aria-label={$_("datatable.search")}
aria-label={$_('datatable.search')} class="mb-4"
class="mb-4" /> />
<div <div
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"> class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
<table class="divide-y divide-gray-200 w-full"> >
<thead class="bg-gray-50"> <table class="w-full">
<tr> <thead>
<th {#each $table.getHeaderGroups() as headerGroup}
scope="col" <tr class="select-none">
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> <th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
{$_('donor')} <InputElement
</th> type="checkbox"
<th checked={$table.getIsAllRowsSelected()}
scope="col" indeterminate={$table.getIsSomeRowsSelected()}
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> on:change={() => $table.toggleAllRowsSelected()}
{$_('runner')} />
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{$_('amount-per-kilometer')}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{$_('donation-amount')}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{$_('paid-amount')}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{$_('status')}
</th>
<th scope="col" class="relative px-6 py-3">
<span class="sr-only">{$_('action')}</span>
</th> </th>
{#each headerGroup.headers as header}
<TableHeader {header} />
{/each}
</tr> </tr>
</thead> {/each}
<tbody class="divide-y divide-gray-200"> </thead>
{#each current_donations as donation} <tbody>
{#if donation.donor.firstname {#each $table.getRowModel().rows as row}
.toLowerCase() <tr>
.includes( <td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
searchvalue.toLowerCase() <InputElement
) || donation.donor.lastname type="checkbox"
.toLowerCase() checked={row.getIsSelected()}
.includes( on:change={() => row.toggleSelected()}
searchvalue.toLowerCase() />
) || donation.runner?.firstname </td>
.toLowerCase() {#each row.getVisibleCells() as cell}
.includes( <td>
searchvalue.toLowerCase() <svelte:component
) || donation.runner?.lastname this={flexRender(
.toLowerCase() cell.column.columnDef.cell,
.includes( cell.getContext()
searchvalue.toLowerCase() )}
) || should_display_based_on_id(donation.id)} />
<tr data-rowid="donation_{donation.id}"> </td>
<td class="px-6 py-4 whitespace-nowrap"> {/each}
<div class="flex items-center"> </tr>
<a {/each}
href="../donors/{donation.donor.id}" </tbody>
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{donation.donor.firstname} </table>
{donation.donor.middlename || ''}
{donation.donor.lastname}</a>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
{#if donation.runner}
<div class="text-sm font-medium text-gray-900">
<a
href="../runners/{donation.runner.id}"
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{donation.runner.firstname}
{donation.runner.middlename || ''}
{donation.runner.lastname}</a>
</div>
{:else}
<div class="text-sm font-medium text-gray-900">
{$_('fixed-donation')}
</div>
{/if}
</td>
<td class="px-6 py-4 whitespace-nowrap">
{#if donation.amountPerDistance}
<div class="text-sm font-medium text-gray-900">
{(donation.amountPerDistance / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })}
</div>
{:else}
<div class="text-sm font-medium text-gray-900">
{$_('fixed-donation')}
</div>
{/if}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">
{(donation.amount / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })}
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">
{(donation.paidAmount / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })}
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
{#if donation.status =="PAID"}
<span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">{$_('paid')}</span>
{:else}
<span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">{$_('open')}</span>
{/if}
</td>
{#if active_deletes[donation.id] === true}
<td
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button
on:click={() => {
active_deletes[donation.id] = false;
}}
tabindex="0"
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
<button
on:click={() => {
DonationService.donationControllerRemove(donation.id, false).then(
(resp) => {
current_donations = current_donations.filter(
(obj) => obj.id !== donation.id
);
Toastify({
text: $_('donation-deleted'),
duration: 500,
backgroundColor:
'linear-gradient(to right, #00b09b, #96c93d)',
}).showToast();
}
);
}}
tabindex="0"
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
</td>
{:else}
<td
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button
on:click={() => {open_payment_modal(donation);}}
class="text-[#025a21] hover:text-green-900 mr-4">{$_('enter-payment')}</button>
<a
href="./{donation.id}"
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
{#if store.state.jwtinfo.userdetails.permissions.includes('DONATION:DELETE')}
<button
on:click={() => {
active_deletes[donation.id] = true;
}}
tabindex="0"
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
{/if}
</td>
{/if}
</tr>
{/if}
{/each}
</tbody>
</table>
</div>
{/if}
{:catch error}
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
<span class="inline-block align-middle mr-8">
<b class="capitalize">{$_('general_promise_error')}</b>
{error}
</span>
</div> </div>
{/await} <div class="h-2" />
<TableBottom {table} {selected} />
{/if}
{/if} {/if}

View File

@@ -2,14 +2,12 @@
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { clickOutside } from "../base/outsideclick"; import { clickOutside } from "../base/outsideclick";
import { import { DonorService } from "@odit/lfk-client-js";
DonorService
} from "@odit/lfk-client-js";
import isEmail from "validator/es/lib/isEmail"; import isEmail from "validator/es/lib/isEmail";
import isMobilePhone from "validator/es/lib/isMobilePhone"; import isMobilePhone from "validator/es/lib/isMobilePhone";
import Toastify from "toastify-js"; import Toastify from "toastify-js";
import { createEventDispatcher } from "svelte";
export let modal_open; export let modal_open;
export let current_donors;
let firstname_input; let firstname_input;
let lastname_input; let lastname_input;
let middlename_input; let middlename_input;
@@ -19,6 +17,7 @@
let address_input2; let address_input2;
let address_zipcode; let address_zipcode;
let address_city; let address_city;
const dispatch = createEventDispatcher();
function focus(el) { function focus(el) {
el.focus(); el.focus();
} }
@@ -75,7 +74,7 @@
if (processed_last_submit === true) { if (processed_last_submit === true) {
processed_last_submit = false; processed_last_submit = false;
const toast = Toastify({ const toast = Toastify({
text: $_('donor-is-being-added'), text: $_("donor-is-being-added"),
duration: -1, duration: -1,
}).showToast(); }).showToast();
let address = {}; let address = {};
@@ -92,7 +91,7 @@
firstname: firstname_input_value, firstname: firstname_input_value,
lastname: lastname_input_value, lastname: lastname_input_value,
address, address,
receiptNeeded: address_checked receiptNeeded: address_checked,
}; };
if (middlename_input_value) { if (middlename_input_value) {
postdata.middlename = middlename_input_value; postdata.middlename = middlename_input_value;
@@ -112,12 +111,11 @@
modal_open = false; modal_open = false;
// //
Toastify({ Toastify({
text: $_('donor-added'), text: $_("donor-added"),
duration: 500, duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast(); }).showToast();
current_donors.push(result); dispatch("created", { donors: [result] });
current_donors = current_donors;
}) })
.catch((err) => { .catch((err) => {
// //
@@ -134,58 +132,70 @@
{#if modal_open} {#if modal_open}
<div <div
class="fixed z-10 inset-0 overflow-y-auto" class="fixed z-10 inset-0 overflow-y-auto"
use:clickOutside use:clickOutside
on:click_outside={() => { on:click_outside={() => {
modal_open = false; modal_open = false;
}}> }}
>
<div <div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
>
<div class="fixed inset-0 transition-opacity" aria-hidden="true"> <div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div <div
class="absolute inset-0 bg-gray-500 opacity-75" class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop" /> data-id="modal_backdrop"
/>
</div> </div>
<span <span
class="hidden sm:inline-block sm:align-middle sm:h-screen" class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span> aria-hidden="true">&#8203;</span
>
<div <div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog" role="dialog"
aria-modal="true" aria-modal="true"
aria-labelledby="modal-headline"> aria-labelledby="modal-headline"
>
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start"> <div class="sm:flex sm:items-start">
<div <div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"> class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
>
<svg <svg
class="h-6 w-6 text-blue-600" class="h-6 w-6 text-blue-600"
fill="currentColor" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" viewBox="0 0 24 24"
width="24" width="24"
height="24"><path fill="none" d="M0 0h24v24H0z" /> height="24"
><path fill="none" d="M0 0h24v24H0z" />
<path <path
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z" /></svg> d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
/></svg
>
</div> </div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900"> <h3 class="text-lg leading-6 font-medium text-gray-900">
{$_('create-a-new-donor')} {$_("create-a-new-donor")}
</h3> </h3>
<div class="mt-2 mb-6"> <div class="mt-2 mb-6">
<p class="text-sm text-gray-500"> <p class="text-sm text-gray-500">
{$_('please-provide-the-nessecary-information-to-add-a-new-donor')} {$_(
"please-provide-the-nessecary-information-to-add-a-new-donor"
)}
</p> </p>
</div> </div>
<div class="grid grid-cols-6 gap-6"> <div class="grid grid-cols-6 gap-6">
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="firstname" for="firstname"
class="block text-sm font-medium text-gray-700">{$_('first-name')}</label> class="block text-sm font-medium text-gray-700"
>{$_("first-name")}</label
>
<input <input
use:focus use:focus
autocomplete="off" autocomplete="off"
placeholder={$_('first-name')} placeholder={$_("first-name")}
class:border-red-500={!isFirstnameValid} class:border-red-500={!isFirstnameValid}
class:focus:border-red-500={!isFirstnameValid} class:focus:border-red-500={!isFirstnameValid}
class:focus:ring-red-500={!isFirstnameValid} class:focus:ring-red-500={!isFirstnameValid}
@@ -193,34 +203,41 @@
bind:this={firstname_input} bind:this={firstname_input}
type="text" type="text"
name="firstname" name="firstname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
{#if !isFirstnameValid} {#if !isFirstnameValid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
{$_('first-name-is-required')} >
{$_("first-name-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="trackname" for="trackname"
class="block text-sm font-medium text-gray-700">{$_('middle-name')}</label> class="block text-sm font-medium text-gray-700"
>{$_("middle-name")}</label
>
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_('middle-name')} placeholder={$_("middle-name")}
bind:value={middlename_input_value} bind:value={middlename_input_value}
bind:this={middlename_input} bind:this={middlename_input}
type="text" type="text"
name="trackname" name="trackname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="lastname" for="lastname"
class="block text-sm font-medium text-gray-700">{$_('last-name')}</label> class="block text-sm font-medium text-gray-700"
>{$_("last-name")}</label
>
<input <input
autocomplete="off" autocomplete="off"
placeholder="{$_('last-name')}" placeholder={$_("last-name")}
class:border-red-500={!isLastnameValid} class:border-red-500={!isLastnameValid}
class:focus:border-red-500={!isLastnameValid} class:focus:border-red-500={!isLastnameValid}
class:focus:ring-red-500={!isLastnameValid} class:focus:ring-red-500={!isLastnameValid}
@@ -228,21 +245,25 @@
bind:this={lastname_input} bind:this={lastname_input}
type="text" type="text"
name="lastname" name="lastname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
{#if !isLastnameValid} {#if !isLastnameValid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
{$_('last-name-is-required')} >
{$_("last-name-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="phone" for="phone"
class="block text-sm font-medium text-gray-700">{$_('phone')}</label> class="block text-sm font-medium text-gray-700"
>{$_("phone")}</label
>
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_('phone')} placeholder={$_("phone")}
class:border-red-500={!isPhoneValidOrEmpty} class:border-red-500={!isPhoneValidOrEmpty}
class:focus:border-red-500={!isPhoneValidOrEmpty} class:focus:border-red-500={!isPhoneValidOrEmpty}
class:focus:ring-red-500={!isPhoneValidOrEmpty} class:focus:ring-red-500={!isPhoneValidOrEmpty}
@@ -250,21 +271,27 @@
bind:this={phone_input} bind:this={phone_input}
type="tel" type="tel"
name="phone" name="phone"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
{#if !isPhoneValidOrEmpty} {#if !isPhoneValidOrEmpty}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
{@html $_('the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number')} >
{@html $_(
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number"
)}
</span> </span>
{/if} {/if}
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="email" for="email"
class="block text-sm font-medium text-gray-700">{$_('e-mail-adress')}</label> class="block text-sm font-medium text-gray-700"
>{$_("e-mail-adress")}</label
>
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_('e-mail-adress')} placeholder={$_("e-mail-adress")}
class:border-red-500={!isEmailValidOrEmpty} class:border-red-500={!isEmailValidOrEmpty}
class:focus:border-red-500={!isEmailValidOrEmpty} class:focus:border-red-500={!isEmailValidOrEmpty}
class:focus:ring-red-500={!isEmailValidOrEmpty} class:focus:ring-red-500={!isEmailValidOrEmpty}
@@ -272,11 +299,13 @@
bind:this={email_input} bind:this={email_input}
type="email" type="email"
name="email" name="email"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
{#if !isEmailValidOrEmpty} {#if !isEmailValidOrEmpty}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
{$_('valid-email-is-required')} >
{$_("valid-email-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
@@ -287,19 +316,22 @@
id="comments" id="comments"
name="comments" name="comments"
type="checkbox" type="checkbox"
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" /> class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div> </div>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label <label for="comments" class="font-medium text-gray-700"
for="comments" >{$_("receipt-needed")}</label
class="font-medium text-gray-700">{$_('receipt-needed')}</label> >
</div> </div>
</div> </div>
{#if address_checked === true} {#if address_checked === true}
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="address1" for="address1"
class="block text-sm font-medium text-gray-700">{$_('address')}</label> class="block text-sm font-medium text-gray-700"
>{$_("address")}</label
>
<input <input
autocomplete="off" autocomplete="off"
placeholder="Address" placeholder="Address"
@@ -310,34 +342,41 @@
bind:this={address_input1} bind:this={address_input1}
type="text" type="text"
name="address1" name="address1"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
{#if !isAddress1Valid} {#if !isAddress1Valid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
{$_('address-is-required')} >
{$_("address-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="address2" for="address2"
class="block text-sm font-medium text-gray-700">{$_('apartment-suite-etc')}</label> class="block text-sm font-medium text-gray-700"
>{$_("apartment-suite-etc")}</label
>
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_('apartment-suite-etc')} placeholder={$_("apartment-suite-etc")}
bind:value={address_input2_value} bind:value={address_input2_value}
bind:this={address_input2} bind:this={address_input2}
type="text" type="text"
name="address2" name="address2"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="zipcode" for="zipcode"
class="block text-sm font-medium text-gray-700">{$_('zip-postal-code')}</label> class="block text-sm font-medium text-gray-700"
>{$_("zip-postal-code")}</label
>
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_('zip-postal-code')} placeholder={$_("zip-postal-code")}
class:border-red-500={!iszipcodevalid} class:border-red-500={!iszipcodevalid}
class:focus:border-red-500={!iszipcodevalid} class:focus:border-red-500={!iszipcodevalid}
class:focus:ring-red-500={!iszipcodevalid} class:focus:ring-red-500={!iszipcodevalid}
@@ -345,18 +384,22 @@
bind:this={address_zipcode} bind:this={address_zipcode}
type="text" type="text"
name="zipcode" name="zipcode"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
{#if !iszipcodevalid} {#if !iszipcodevalid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
{$_('valid-zipcode-postal-code-is-required')} >
{$_("valid-zipcode-postal-code-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="city" for="city"
class="block text-sm font-medium text-gray-700">City</label> class="block text-sm font-medium text-gray-700"
>City</label
>
<input <input
autocomplete="off" autocomplete="off"
placeholder="City" placeholder="City"
@@ -367,11 +410,13 @@
bind:this={address_city} bind:this={address_city}
type="text" type="text"
name="city" name="city"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/>
{#if !iscityvalid} {#if !iscityvalid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
{$_('valid-city-is-required')} >
{$_("valid-city-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
@@ -386,16 +431,18 @@
class:opacity-50={!createbtnenabled} class:opacity-50={!createbtnenabled}
on:click={submit} on:click={submit}
type="button" type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
{$_('create')} >
{$_("create")}
</button> </button>
<button <button
on:click={() => { on:click={() => {
modal_open = false; modal_open = false;
}} }}
type="button" type="button"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"> class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
{$_('cancel')} >
{$_("cancel")}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -13,60 +13,61 @@
dispatch("cancelDelete", { id: delete_donor.id }); dispatch("cancelDelete", { id: delete_donor.id });
} }
function deleteDonor() { function deleteDonor() {
DonorService.donorControllerRemove( dispatch("delete", { id: delete_donor.id });
delete_donor.id,
true
)
.then((resp) => {
Toastify({
text: $_('donor-deleted'),
duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast();
location.replace("./");
})
.catch((err) => {});
} }
</script> </script>
{#if modal_open} {#if modal_open}
<div <div
class="fixed z-10 inset-0 overflow-y-auto" class="fixed z-10 inset-0 overflow-y-auto"
use:clickOutside use:clickOutside
on:click_outside={cancelDelete}> on:click_outside={cancelDelete}
>
<div <div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
>
<div class="fixed inset-0 transition-opacity" aria-hidden="true"> <div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div <div
class="absolute inset-0 bg-gray-500 opacity-75" class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop" /> data-id="modal_backdrop"
/>
</div> </div>
<span <span
class="hidden sm:inline-block sm:align-middle sm:h-screen" class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span> aria-hidden="true">&#8203;</span
>
<div <div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog" role="dialog"
aria-modal="true" aria-modal="true"
aria-labelledby="modal-headline"> aria-labelledby="modal-headline"
>
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start"> <div class="sm:flex sm:items-start">
<div <div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"> class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
<svg class="h-6 w-6 text-blue-600" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M9.33 11.5h2.17A4.5 4.5 0 0116 16H9v1h8v-1a5.58 5.58 0 00-.89-3H19a5 5 0 014.52 2.85A13.15 13.15 0 0113 21c-2.76 0-5.1-.59-7-1.63v-9.3a6.97 6.97 0 013.33 1.43zM5 19a1 1 0 01-1 1H2a1 1 0 01-1-1v-9a1 1 0 011-1h2a1 1 0 011 1v9zM18 5a3 3 0 110 6 3 3 0 010-6zm-7-3a3 3 0 110 6 3 3 0 010-6z"/></svg> >
<svg
class="h-6 w-6 text-blue-600"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path fill="none" d="M0 0h24v24H0z" /><path
d="M9.33 11.5h2.17A4.5 4.5 0 0116 16H9v1h8v-1a5.58 5.58 0 00-.89-3H19a5 5 0 014.52 2.85A13.15 13.15 0 0113 21c-2.76 0-5.1-.59-7-1.63v-9.3a6.97 6.97 0 013.33 1.43zM5 19a1 1 0 01-1 1H2a1 1 0 01-1-1v-9a1 1 0 011-1h2a1 1 0 011 1v9zM18 5a3 3 0 110 6 3 3 0 010-6zm-7-3a3 3 0 110 6 3 3 0 010-6z"
/></svg
>
</div> </div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900"> <h3 class="text-lg leading-6 font-medium text-gray-900">
{$_('attention')} {$_("attention")}
</h3> </h3>
<div class="mt-2 mb-6"> <div class="mt-2 mb-6">
<p class="text-sm text-gray-500"> <p class="text-sm text-gray-500">
{$_( {$_(
'do-you-want-to-delete-this-donor-with-all-related-donations' "do-you-want-to-delete-this-donor-with-all-related-donations"
)} )}
<br /> <br />
{$_('all-associated-donations-will-get-deleted-as-well')} {$_("all-associated-donations-will-get-deleted-as-well")}
</p> </p>
</div> </div>
</div> </div>
@@ -76,14 +77,16 @@
<button <button
on:click={deleteDonor} on:click={deleteDonor}
type="button" type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"> class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
{$_('confirm-delete-donor-with-all-donations')} >
{$_("confirm-delete-donor-with-all-donations")}
</button> </button>
<button <button
on:click={cancelDelete} on:click={cancelDelete}
type="button" type="button"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"> class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
{$_('cancel-keep-donor')} >
{$_("cancel-keep-donor")}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,14 @@
<script>
import { _ } from "svelte-i18n";
export let address;
</script>
{#if !address || !address.address1}
{$_("no-address")}
{:else}
{address.address1}<br />
<!-- {address.address2 || ''}<br /> -->
{address.postalcode}
{address.city}
{address.country}
{/if}

View File

@@ -0,0 +1,29 @@
<script>
import { _ } from "svelte-i18n";
export let donations;
</script>
{#if !donations || donations.length == 0}
{$_('donor-has-no-associated-donations')}
{:else}
{#each donations as donation}
{#if donation.responseType === "DISTANCEDONATION"}
<a
href="../donations/{donation.id}"
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1"
>{donation.runner.firstname}
{donation.runner.middlename || ""}
{donation.runner.lastname}</a
>
{:else}
<a
href="../donations/{donation.id}"
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-700 text-white mr-1"
>{$_("fixed-donation")}:
{(donation.amount / 100)
.toFixed(2)
.toLocaleString("de-DE", { valute: "EUR" })}</a
>
{/if}
{/each}
{/if}

View File

@@ -5,50 +5,73 @@
import DonorsOverview from "./DonorsOverview.svelte"; import DonorsOverview from "./DonorsOverview.svelte";
$: current_donors = []; $: current_donors = [];
export let modal_open = false; export let modal_open = false;
let addDonors;
</script> </script>
<section class="container p-5"> <section class="container p-5">
<span class="mb-1 text-3xl font-extrabold leading-tight"> <span class="mb-1 text-3xl font-extrabold leading-tight">
{$_('donors')} {$_("donors")}
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:CREATE')} {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:CREATE")}
<button <button
on:click={() => { on:click={() => {
modal_open = true; modal_open = true;
}} }}
type="button" type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
{$_('add-donor')} >
{$_("add-donor")}
</button> </button>
{/if} {/if}
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:GET')} {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
<button <button
on:click={() => { on:click={() => {
const data = (current_donors.filter(d=>d.receiptNeeded===true)).map(function (d) { const data = current_donors
d.address.address2=d.address.address2===""?"":" "+d.address.address2; .filter((d) => d.receiptNeeded === true)
const address=`${d.address.address1}${d.address.address2}, ${d.address.postalcode} ${d.address.city}, ${d.address.country}`; .map(function (d) {
return [d.firstname,d.middlename,d.lastname,d.paidDonationAmount,address]; d.address.address2 =
}) d.address.address2 === "" ? "" : " " + d.address.address2;
let csv = `${$_('csv_import__firstname')};${$_('csv_import__middlename')};${$_('csv_import__lastname')};${$_('total_donation_amount_in_eur')};${$_('address')}\n`; const address = `${d.address.address1}${d.address.address2}, ${d.address.postalcode} ${d.address.city}, ${d.address.country}`;
data.forEach(function(row) { return [
csv += row.join(';'); d.firstname,
d.middlename,
d.lastname,
d.paidDonationAmount,
address,
];
});
let csv = `${$_("csv_import__firstname")};${$_(
"csv_import__middlename"
)};${$_("csv_import__lastname")};${$_(
"total_donation_amount_in_eur"
)};${$_("address")}\n`;
data.forEach(function (row) {
csv += row.join(";");
csv += "\n"; csv += "\n";
}); });
let hiddenElement = document.createElement('a'); let hiddenElement = document.createElement("a");
hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv); hiddenElement.href = "data:text/csv;charset=utf-8," + encodeURI(csv);
hiddenElement.target = '_blank'; hiddenElement.target = "_blank";
hiddenElement.download = `${$_('filename_sponsoringquittungsliste')}.csv`; hiddenElement.download = `${$_(
hiddenElement.click(); "filename_sponsoringquittungsliste"
hiddenElement.remove(); )}.csv`;
hiddenElement.click();
hiddenElement.remove();
}} }}
type="button" type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
{$_('sponsoring-quittungs-liste_herunterladen')} >
{$_("sponsoring-quittungs-liste_herunterladen")}
</button> </button>
{/if} {/if}
</span> </span>
<DonorsOverview bind:current_donors /> <DonorsOverview bind:current_donors bind:addDonors />
</section> </section>
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:CREATE')} {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:CREATE")}
<AddDonorModal bind:current_donors bind:modal_open /> <AddDonorModal
on:created={(event) => {
addDonors(event.detail.donors);
}}
bind:modal_open
/>
{/if} {/if}

View File

@@ -5,214 +5,255 @@
import DonorsEmptyState from "./DonorsEmptyState.svelte"; import DonorsEmptyState from "./DonorsEmptyState.svelte";
import ConfirmDonorDeletion from "./ConfirmDonorDeletion.svelte"; import ConfirmDonorDeletion from "./ConfirmDonorDeletion.svelte";
import Toastify from "toastify-js"; import Toastify from "toastify-js";
import TableBottom from "../shared/TableBottom.svelte";
import {
createSvelteTable,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
renderComponent,
} from "@tanstack/svelte-table";
import { writable } from "svelte/store";
import { onMount } from "svelte";
import InputElement from "../shared/InputElement.svelte";
import TableHeader from "../shared/TableHeader.svelte";
import TableActions from "../shared/TableActions.svelte";
import DonorAddress from "./DonorAddress.svelte";
import DonorDonations from "./DonorDonations.svelte";
import { filterAddress, filterName } from "../shared/tablefilters";
$: searchvalue = ""; $: searchvalue = "";
$: active_deletes = []; $: active_deletes = [];
$: current_donations = []; $: selectedDonors =
let modal_open = false; $table?.getSelectedRowModel().rows.map((row) => row.original) || [];
let delete_donor = {}; $: selected =
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
$: dataLoaded = false;
export let current_donors = []; export let current_donors = [];
const donors_promise = DonorService.donorControllerGetAll().then((val) => { export const addDonors = (donors) => {
current_donors = val; current_donors = current_donors.concat(...donors);
options.update((options) => ({
...options,
data: current_donors,
}));
};
//Section table
const columns = [
{
accessorKey: "id",
header: () => "id",
filterFn: `equalsString`,
},
{
accessorKey: "name",
header: () => $_("name"),
cell: (info) => {
const d = info.row.original;
if (d.middlename) {
return `${d.firstname} ${d.middlename} ${d.lastname}`;
} else {
return `${d.firstname} ${d.lastname}`;
}
},
filterFn: `name`,
},
{
accessorKey: "address",
header: () => $_("contact-information"),
cell: (info) => {
return renderComponent(DonorAddress, { address: info.getValue() });
},
filterFn: `address`,
},
{
accessorKey: "donations",
header: () => $_("sponsorings"),
cell: (info) => {
return renderComponent(DonorDonations, { donations: info.getValue() });
},
enableColumnFilter: false,
},
{
accessorKey: "donationAmount",
header: () => $_("total-donation-amount"),
cell: (info) => {
return `${(info.getValue() / 100)
.toFixed(2)
.toLocaleString("de-DE", { valute: "EUR" })}€`;
},
enableColumnFilter: false,
},
{
accessorKey: "paidDonationAmount",
header: () => $_("total-paid-amount"),
cell: (info) => {
return `${(info.getValue() / 100)
.toFixed(2)
.toLocaleString("de-DE", { valute: "EUR" })}€`;
},
enableColumnFilter: false,
},
{
accessorKey: "actions",
header: () => $_("action"),
cell: (info) => {
return renderComponent(TableActions, {
detailsLink: `./${info.row.original.id}`,
deleteAction: () => {
active_deletes = current_donors.filter(
(r) => r.id == info.row.original.id
);
},
deleteEnabled:
store.state.jwtinfo.userdetails.permissions.includes(
"DONOR:DELETE"
),
});
},
enableColumnFilter: false,
enableSorting: false,
},
];
const options = writable({
data: [],
columns: columns,
initialState: {
pagination: {
pageSize: 50,
},
},
filterFns: {
name: filterName,
address: filterAddress,
},
enableRowSelection: true,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
}); });
const donation_promise = DonationService.donationControllerGetAll().then( const table = createSvelteTable(options);
(val) => {
current_donations = val;
}
);
function should_display_based_on_id(id) { function should_display_based_on_id(id) {
if (searchvalue.toString().slice(-1) === "*") { if (searchvalue.toString().slice(-1) === "*") {
return id.toString().startsWith(searchvalue.replace("*", "")); return id.toString().startsWith(searchvalue.replace("*", ""));
} }
return id.toString() === searchvalue; return id.toString() === searchvalue;
} }
onMount(async () => {
let page = 0;
while (page >= 0) {
const donors = await DonorService.donorControllerGetAll(page, 500);
if (donors.length == 0) {
page = -2;
}
current_donors = current_donors.concat(...donors);
options.update((options) => ({
...options,
data: current_donors,
}));
dataLoaded = true;
page++;
}
console.log("All donors loaded");
});
</script> </script>
<ConfirmDonorDeletion <ConfirmDonorDeletion
on:cancelDelete={(event) => { on:cancelDelete={(event) => {
modal_open = false; active_deletes = active_deletes.filter((a) => a.id !== event.detail.id);
active_deletes[event.detail.id] = false;
}} }}
bind:modal_open on:delete={async (event) => {
bind:delete_donor /> await DonorService.donorControllerRemove(event.detail.id, true);
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:GET')} Toastify({
{#await donors_promise && donation_promise} text: $_("donor-deleted"),
duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast();
current_donors = current_donors.filter((d) => d.id !== event.detail.id);
active_deletes = active_deletes.filter((a) => a.id !== event.detail.id);
options.update((options) => ({
...options,
data: current_donors,
}));
}}
modal_open={active_deletes.length > 0}
delete_donor={active_deletes[0]}
/>
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
{#if !dataLoaded}
<div <div
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
role="alert"> role="alert"
<p class="font-bold">{$_('donors-are-being-loaded')}</p> >
<p class="text-sm">{$_('this-might-take-a-moment')}</p> <p class="font-bold">{$_("donors-are-being-loaded")}</p>
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
</div> </div>
{:then} {:else if current_donors.length === 0}
{#if current_donors.length === 0} <DonorsEmptyState />
<DonorsEmptyState /> {:else}
{:else} <input
<input type="search"
type="search" bind:value={searchvalue}
bind:value={searchvalue} placeholder={$_("datatable.search")}
placeholder={$_('datatable.search')} aria-label={$_("datatable.search")}
aria-label={$_('datatable.search')} class="mb-4"
class="mb-4" /> />
<div <div
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"> class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
<table class="divide-y divide-gray-200 w-full"> >
<thead class="bg-gray-50"> <table class="w-full">
<tr> <thead>
<th {#each $table.getHeaderGroups() as headerGroup}
scope="col" <tr class="select-none">
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> <th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
{$_('name')} <InputElement
</th> type="checkbox"
<th checked={$table.getIsAllRowsSelected()}
scope="col" indeterminate={$table.getIsSomeRowsSelected()}
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> on:change={() => $table.toggleAllRowsSelected()}
{$_('contact-information')} />
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{$_('donations')}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{$_('total-donation-amount')}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
{$_('total-paid-amount')}
</th>
<th scope="col" class="relative px-6 py-3">
<span class="sr-only">{$_('action')}</span>
</th> </th>
{#each headerGroup.headers as header}
<TableHeader {header} />
{/each}
</tr> </tr>
</thead> {/each}
<tbody class="divide-y divide-gray-200"> </thead>
{#each current_donors as donor} <tbody>
{#if donor.firstname {#each $table.getRowModel().rows as row}
.toLowerCase() <tr>
.includes( <td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
searchvalue.toLowerCase() <InputElement
) || donor.lastname type="checkbox"
.toLowerCase() checked={row.getIsSelected()}
.includes( on:change={() => row.toggleSelected()}
searchvalue.toLowerCase() />
) || should_display_based_on_id(donor.id)} </td>
<tr data-rowid="donor_{donor.id}"> {#each row.getVisibleCells() as cell}
<td class="px-6 py-4 whitespace-nowrap"> <td>
<div class="flex items-center"> <svelte:component
<div class="ml-4"> this={flexRender(
<div class="text-sm font-medium text-gray-900"> cell.column.columnDef.cell,
{donor.firstname} cell.getContext()
{donor.middlename || ''} )}
{donor.lastname} />
</div> </td>
</div> {/each}
</div> </tr>
</td> {/each}
<td class="px-6 py-4 whitespace-nowrap"> </tbody>
{#if donor.email} </table>
<div class="text-sm text-gray-500">{donor.email}</div>
{/if}
{#if donor.phone}
<div class="text-sm text-gray-500">{donor.phone}</div>
{/if}
{#if donor.address.address1 !== null}
{donor.address.address1}<br />
{donor.address.address2 || ''}<br />
{donor.address.postalcode}
{donor.address.city}
{donor.address.country}
{/if}
</td>
<td class="px-6 py-4 whitespace-nowrap">
{#if current_donations.filter((d) => d.donor.id == donor.id).length > 0}
{#each current_donations.filter((o) => o.donor.id == donor.id) as d}
{#if d.responseType === 'DISTANCEDONATION'}
<a
href="../donations/{d.id}"
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1">{d.runner.firstname}
{d.runner.middlename || ''}
{d.runner.lastname}</a>
{:else}
<a
href="../donations/{d.id}"
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-700 text-white mr-1">{$_('fixed-donation')}:
{(d.amount / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })}</a>
{/if}
{/each}
{:else}{$_('donor-has-no-associated-donations')}{/if}
</td>
<td class="px-6 py-4 whitespace-nowrap">
{(donor.donationAmount / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })}
</td>
<td class="px-6 py-4 whitespace-nowrap">
{(donor.paidDonationAmount / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })}
</td>
{#if active_deletes[donor.id] === true}
<td
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button
on:click={() => {
active_deletes[donor.id] = false;
}}
tabindex="0"
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
<button
on:click={() => {
DonorService.donorControllerRemove(donor.id, false)
.then((resp) => {
current_donors = current_donors.filter((obj) => obj.id !== donor.id);
Toastify({
text: 'Donor deleted',
duration: 500,
backgroundColor:
'linear-gradient(to right, #00b09b, #96c93d)',
}).showToast();
})
.catch((err) => {
modal_open = true;
delete_donor = donor;
});
}}
tabindex="0"
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
</td>
{:else}
<td
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<a
href="./{donor.id}"
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:DELETE')}
<button
on:click={() => {
active_deletes[donor.id] = true;
}}
tabindex="0"
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
{/if}
</td>
{/if}
</tr>
{/if}
{/each}
</tbody>
</table>
</div>
{/if}
{:catch error}
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
<span class="inline-block align-middle mr-8">
<b class="capitalize">{$_('general_promise_error')}</b>
{error}
</span>
</div> </div>
{/await} <div class="h-2" />
<TableBottom {table} {selected} />
{/if}
{/if} {/if}

View File

@@ -132,7 +132,7 @@
<div class="text-sm font-medium text-gray-900"> <div class="text-sm font-medium text-gray-900">
{#if o.address.address1 !== null} {#if o.address.address1 !== null}
{o.address.address1}<br /> {o.address.address1}<br />
{o.address.address2 || ''}<br /> <!-- {o.address.address2 || ''}<br /> -->
{o.address.postalcode} {o.address.postalcode}
{o.address.city} {o.address.city}
{o.address.country} {o.address.country}

View File

@@ -50,7 +50,6 @@
})); }));
}; };
//Section table //Section table
const columns = [ const columns = [
{ {
@@ -157,16 +156,7 @@
}).showToast(); }).showToast();
} }
onMount(() => { onMount(async () => {
RunnerService.runnerControllerGetAll().then((val) => {
current_runners = val;
dataLoaded = true;
options.update((options) => ({
...options,
data: current_runners,
}));
});
RunnerTeamService.runnerTeamControllerGetAll().then((val) => { RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
teams = val; teams = val;
}); });
@@ -175,6 +165,24 @@
orgs = val; orgs = val;
} }
); );
let page = 0;
while (page >= 0) {
const runners = await RunnerService.runnerControllerGetAll(page, 1000);
if (runners.length == 0) {
page = -2;
}
current_runners = current_runners.concat(...runners);
options.update((options) => ({
...options,
data: current_runners,
}));
dataLoaded = true;
page++;
}
console.log("All runners loaded");
}); });
</script> </script>

View File

@@ -30,6 +30,7 @@
$table?.getSelectedRowModel().rows.map((row) => row.index) || []; $table?.getSelectedRowModel().rows.map((row) => row.index) || [];
$: active_delete = undefined; $: active_delete = undefined;
$: dataLoaded = false;
export let current_scans = []; export let current_scans = [];
export const addScans = (scans) => { export const addScans = (scans) => {
current_scans = current_scans.concat(...scans); current_scans = current_scans.concat(...scans);
@@ -39,15 +40,6 @@
})); }));
}; };
const scans_promise = ScanService.scanControllerGetAll().then((val) => {
current_scans = val;
// handler.setRows(val);
current_scans = val;
options.update((options) => ({
...options,
data: current_scans,
}));
});
let allTracks = []; let allTracks = [];
TrackService.trackControllerGetAll().then((val) => { TrackService.trackControllerGetAll().then((val) => {
allTracks = val; allTracks = val;
@@ -95,6 +87,14 @@
}, },
enableColumnFilter: false, enableColumnFilter: false,
}, },
{
accessorKey: "timestamp",
header: () => $_("timestamp"),
cell: (info) => {
return new Date(parseInt(info.getValue()) * 1000).toLocaleString();
},
enableColumnFilter: false,
},
{ {
accessorKey: "distance", accessorKey: "distance",
header: () => $_("distance"), header: () => $_("distance"),
@@ -175,6 +175,26 @@
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast(); }).showToast();
} }
onMount(async () => {
let page = 0;
while (page >= 0) {
const scans = await ScanService.scanControllerGetAll(page, 500);
if (scans.length == 0) {
page = -2;
}
current_scans = current_scans.concat(...scans);
options.update((options) => ({
...options,
data: current_scans,
}));
dataLoaded = true;
page++;
}
console.log("All scans loaded");
});
</script> </script>
<DeleteScanModal <DeleteScanModal
@@ -185,7 +205,7 @@
}} }}
/> />
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")} {#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")}
{#await scans_promise} {#if !dataLoaded}
<div <div
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
role="alert" role="alert"
@@ -193,105 +213,96 @@
<p class="font-bold">{$_("scans-are-being-loaded")}</p> <p class="font-bold">{$_("scans-are-being-loaded")}</p>
<p class="text-sm">{$_("this-might-take-a-moment")}</p> <p class="text-sm">{$_("this-might-take-a-moment")}</p>
</div> </div>
{:then} {:else if current_scans.length === 0}
{#if current_scans.length === 0} <ScansEmptyState />
<ScansEmptyState /> {:else}
{:else} {#if selected.length > 0}
{#if selected.length > 0} <button
<button type="button"
type="button" class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex" id="options-menu"
id="options-menu" on:click={async () => {
on:click={async () => { const prom = [];
const prom = []; for (const scan of selectedScans) {
for (const scan of selectedScans) { prom.push(ScanService.scanControllerRemove(scan.id, true));
prom.push(ScanService.scanControllerRemove(scan.id, true)); }
} await Promise.all(prom);
await Promise.all(prom); for (const scan of selectedScans) {
for (const scan of selectedScans) { current_scans = current_scans.filter((r) => r.id !== scan.id);
current_scans = current_scans.filter((r) => r.id !== scan.id); }
} options.update((options) => ({
options.update((options) => ({ ...options,
...options, data: current_scans,
data: current_scans, }));
})); $table.resetRowSelection();
$table.resetRowSelection(); Toastify({
Toastify({ text: $_("scan-deleted"),
text: $_("scan-deleted"), duration: 3500,
duration: 3500, backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", }).showToast();
}).showToast(); }}
}} >
{$_("delete-scans")}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-5 h-5"
> >
{$_("delete-scans")} <path
<svg stroke-linecap="round"
xmlns="http://www.w3.org/2000/svg" stroke-linejoin="round"
fill="none" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
viewBox="0 0 24 24" />
stroke-width="1.5" </svg>
stroke="currentColor" </button>
class="w-5 h-5" {/if}
> <div class="overflow-x-auto">
<path <table class="w-full">
stroke-linecap="round" <thead>
stroke-linejoin="round" {#each $table.getHeaderGroups() as headerGroup}
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" <tr class="select-none">
/> <th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
</svg> <InputElement
</button> type="checkbox"
{/if} checked={$table.getIsAllRowsSelected()}
<div class="overflow-x-auto"> indeterminate={$table.getIsSomeRowsSelected()}
<table class="w-full"> on:change={() => $table.toggleAllRowsSelected()}
<thead> />
{#each $table.getHeaderGroups() as headerGroup} </th>
<tr class="select-none"> {#each headerGroup.headers as header}
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px"> <TableHeader {header} />
<InputElement {/each}
type="checkbox" </tr>
checked={$table.getIsAllRowsSelected()} {/each}
indeterminate={$table.getIsSomeRowsSelected()} </thead>
on:change={() => $table.toggleAllRowsSelected()} <tbody>
/> {#each $table.getRowModel().rows as row}
</th> <tr>
{#each headerGroup.headers as header} <td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
<TableHeader {header} /> <InputElement
{/each} type="checkbox"
</tr> checked={row.getIsSelected()}
{/each} on:change={() => row.toggleSelected()}
</thead> />
<tbody> </td>
{#each $table.getRowModel().rows as row} {#each row.getVisibleCells() as cell}
<tr> <td>
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px"> <svelte:component
<InputElement this={flexRender(
type="checkbox" cell.column.columnDef.cell,
checked={row.getIsSelected()} cell.getContext()
on:change={() => row.toggleSelected()} )}
/> />
</td> </td>
{#each row.getVisibleCells() as cell} {/each}
<td> </tr>
<svelte:component {/each}
this={flexRender( </tbody>
cell.column.columnDef.cell, </table>
cell.getContext()
)}
/>
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</div>
<TableBottom {table} {selected} />
{/if}
{:catch error}
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
<span class="inline-block align-middle mr-8">
<b class="capitalize">{$_("general_promise_error")}</b>
{error}
</span>
</div> </div>
{/await} <TableBottom {table} {selected} />
{/if}
{/if} {/if}

View File

@@ -1,14 +1,18 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import Toastify from "toastify-js"; import Toastify from "toastify-js";
import { tick, createEventDispatcher } from "svelte"; import { tick, createEventDispatcher } from "svelte";
import bwipjs from "bwip-js";
export let copy_modal_open; export let copy_modal_open;
export let new_station; export let new_station;
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
let valueCopy = null; let valueCopy = null;
let areaDom; let areaDom;
let copied = false; let copied = false;
$: is_qrcode = false;
$: barcode = textToBase64Barcode(new_station.key, is_qrcode);
function close() { function close() {
copy_modal_open = false; copy_modal_open = false;
} }
@@ -36,10 +40,30 @@
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)", "linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
}).showToast(); }).showToast();
} }
// we can notifi by event or storage about copy status // we can notifi by event or storage about copy status
valueCopy = null; valueCopy = null;
} }
function textToBase64Barcode(text, is_qrcode) {
const canvas = document.createElement("canvas");
let bcid = "code128";
if (is_qrcode) {
bcid = "qrcode";
}
let codeconfig = {
bcid,
text: `${text}`,
scale: 4,
includetext: true,
textxalign: "center",
backgroundcolor: "ffffff",
};
if (bcid == "code128") {
codeconfig.height = 10;
}
bwipjs.toCanvas(canvas, codeconfig);
return canvas.toDataURL("image/png");
}
</script> </script>
{#if copy_modal_open} {#if copy_modal_open}
@@ -131,6 +155,44 @@
</div> </div>
</div> </div>
</div> </div>
<div class="mx-auto text-center items-center">
<h2 class="text-lg leading-6 font-medium text-gray-900">
{$_("config-codes")}
</h2>
<span class="flex items-center text-center">
<p class="text-md text-gray-900 mr-3">Format:</p>
<label for="codeswitch" class="text-md text-gray-900 mr-3"
>Code128</label
>
<input
id="codeswitch"
type="checkbox"
bind:checked={is_qrcode}
class="relative shrink-0 w-[3.25rem] h-7 bg-gray-100 checked:bg-none checked:bg-blue-600 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 border border-transparent ring-1 ring-transparent focus:border-blue-600 focus:ring-blue-600 ring-offset-white focus:outline-none appearance-none before:inline-block before:w-6 before:h-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:shadow before:rounded-full before:transform before:ring-0 before:transition before:ease-in-out before:duration-200 dark:before:bg-gray-400 dark:checked:before:bg-blue-200"
/>
<label for="codeswitch" class="text-md text-gray-900 ml-3"
>QR-Code</label
>
</span>
<h3 class="leading-6 font-medium text-gray-900">
{$_("api-endpoint")}
</h3>
<img
class:w-[50%]={is_qrcode}
class:w-full={!is_qrcode}
class="md:w-auto mb-2 mx-auto"
alt="Registrierungscode"
src={textToBase64Barcode(config.baseurl, is_qrcode)}
/>
<h3 class="leading-6 font-medium text-gray-900">{$_("token")}</h3>
<img
class:w-[50%]={is_qrcode}
class:w-full={!is_qrcode}
class="md:w-auto mb-2 mx-auto"
alt="Registrierungscode"
src={barcode}
/>
</div>
</div> </div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button <button

View File

@@ -15,17 +15,48 @@ export const groupFilter = (row, columnId, value) => {
}; };
export const runnerFilter = (row, columnId, value) => { export const runnerFilter = (row, columnId, value) => {
const runner = row.getValue(columnId); const runner = row.getValue(columnId);
if(!runner && value == "blanko"){return true} return filterRunner(runner, value)
if(!runner){return false} };
if(value.startsWith("#")){ export const donationRunnerFilter = (row, columnId, value) => {
return runner.id == value.replace("#","") const runner = row.getValue(columnId);
if (!runner) { return false; }
return filterRunner(runner, value)
};
export const donationDonorFilter = (row, columnId, value) => {
const runner = row.getValue(columnId);
return filterRunner(runner, value)
};
function filterRunner(runner, value) {
if (!runner && value == "blanko") { return true }
if (!runner) { return false }
if (value.startsWith("#")) {
return runner.id == value.replace("#", "")
} }
if(runner.middlename){ if (runner.middlename) {
return `${runner.firstname} ${runner.middlename} ${runner.lastname}`.toLowerCase().includes(value.toLowerCase()) return `${runner.firstname} ${runner.middlename} ${runner.lastname}`.toLowerCase().includes(value.toLowerCase())
} }
return `${runner.firstname} ${runner.lastname}`.toLowerCase().includes(value.toLowerCase()) return `${runner.firstname} ${runner.lastname}`.toLowerCase().includes(value.toLowerCase())
}
export const filterName = (row, columnId, value) => {
const obj = row.original;
if (obj.middlename) {
return `${obj.firstname} ${obj.middlename} ${obj.lastname}`.toLowerCase().includes(value.toLowerCase())
}
return `${obj.firstname} ${obj.lastname}`.toLowerCase().includes(value.toLowerCase())
};
export const filterAddress = (row, columnId, value) => {
const obj = row.original.address;
if (obj.address2) {s
return `${obj.address1} ${obj.address2} ${obj.postalcode} ${obj.city} ${obj.country}`.toLowerCase().includes(value.toLowerCase())
}
return `${obj.address1} ${obj.postalcode} ${obj.city} ${obj.country}`.toLowerCase().includes(value.toLowerCase())
}; };
export const statusFilter = (row, columnId, value) => { export const statusFilter = (row, columnId, value) => {

View File

@@ -1,490 +1,500 @@
{ {
"404message": "Die gesuchte Seite wurde leider nicht gefunden.", "404message": "Die gesuchte Seite wurde leider nicht gefunden.",
"404title": "Fehler 404", "404title": "Fehler 404",
"about": "Über", "about": "Über",
"action": "Aktionen", "action": "Aktionen",
"active": "Aktiv", "active": "Aktiv",
"add-card": "Karte erstellen", "add-card": "Karte erstellen",
"add-donation": "Sponsoring erstellen", "add-donation": "Sponsoring erstellen",
"add-donor": "Sponsor:in erstellen", "add-donor": "Sponsor:in erstellen",
"add-or-update-a-payment": "Zahlung hinzufügen oder bearbeiten", "add-or-update-a-payment": "Zahlung hinzufügen oder bearbeiten",
"add-scan": "Scan erstellen", "add-scan": "Scan erstellen",
"add-the-first-scanstation": "Erstelle deine erste Scannerstation.", "add-the-first-scanstation": "Erstelle deine erste Scannerstation.",
"add-the-first-statsclient": "Erstelle deinen ersten Statsclient.", "add-the-first-statsclient": "Erstelle deinen ersten Statsclient.",
"add-user-group": "Neue Gruppe erstellen", "add-user-group": "Neue Gruppe erstellen",
"add-your-first-card": "Erstelle deine erste Läuferkarte", "add-your-first-card": "Erstelle deine erste Läuferkarte",
"add-your-first-contact": "Erstelle den ersten Kontakt", "add-your-first-contact": "Erstelle den ersten Kontakt",
"add-your-first-donor": "Erstelle die erste Sponsor:in", "add-your-first-donor": "Erstelle die erste Sponsor:in",
"add-your-first-group": "Erstelle die erste Gruppe", "add-your-first-group": "Erstelle die erste Gruppe",
"add-your-first-organization": "Erstelle die erste Organisation", "add-your-first-organization": "Erstelle die erste Organisation",
"add-your-first-runner": "Erstelle die erste Läufer:in", "add-your-first-runner": "Erstelle die erste Läufer:in",
"add-your-first-team": "Erstelle das erste Team", "add-your-first-team": "Erstelle das erste Team",
"add-your-first-track": "Erstelle den ersten Track (Laufstrecke).", "add-your-first-track": "Erstelle den ersten Track (Laufstrecke).",
"add-your-first-user": "Erstelle die erste Benutzer:in", "add-your-first-user": "Erstelle die erste Benutzer:in",
"add-your-fist-donation": "Erstelle dein erstes Sponsoring", "add-your-fist-donation": "Erstelle dein erstes Sponsoring",
"add-your-fist-scan": "Füge deinen ersten Scan hinzu", "add-your-fist-scan": "Füge deinen ersten Scan hinzu",
"adding-card": "Karte wird erstellt", "adding-card": "Karte wird erstellt",
"adding-donation": "Sponsoring wird erstellt...", "adding-donation": "Sponsoring wird erstellt...",
"adding-scan": "Scan wird hinzugefügt", "adding-scan": "Scan wird hinzugefügt",
"address": "Adresse", "address": "Adresse",
"address-is-required": "Du musst eine Adresse angeben", "address-is-required": "Du musst eine Adresse angeben",
"after-deletion-we-cant-restore-your-old-profile": "Nach der Löschung können auch die Admins dein Profil nicht wiederherstellen!", "after-deletion-we-cant-restore-your-old-profile": "Nach der Löschung können auch die Admins dein Profil nicht wiederherstellen!",
"after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that": "Nach der Änderung wirst du abgemeldet - bitte melde dich dann mit deinem neuen Passwort an.", "after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that": "Nach der Änderung wirst du abgemeldet - bitte melde dich dann mit deinem neuen Passwort an.",
"all": "Alle", "all": "Alle",
"all-associated-donations-will-get-deleted-as-well": "Alle Sponsorings dieser Sponsor:in werden ebenfalls gelöscht", "all-associated-donations-will-get-deleted-as-well": "Alle Sponsorings dieser Sponsor:in werden ebenfalls gelöscht",
"all-associated-runners-will-be-deleted-too": "Alle zugehörigen Läufer:innen werden auch gelöscht!", "all-associated-runners-will-be-deleted-too": "Alle zugehörigen Läufer:innen werden auch gelöscht!",
"all-associated-teams-and-runners-will-be-deleted-too": "Alle assoziierten Teams und Läufer:innen werden auch gelöscht!", "all-associated-scans-will-get-deleted-as-well": "Alle Scans dieser Station werden ebenfalls gelöscht",
"already-paid": "Bereits bezahlt", "all-associated-teams-and-runners-will-be-deleted-too": "Alle assoziierten Teams und Läufer:innen werden auch gelöscht!",
"amount": "Anzahl", "already-paid": "Bereits bezahlt",
"amount-per-kilometer": "Betrag pro Kilometer", "amount": "Anzahl",
"apartment-suite-etc": "Apartment, Wohnung, etc.", "amount-per-kilometer": "Betrag pro Kilometer",
"application_name": "Lauf für Kaya! - Admin", "apartment-suite-etc": "Apartment, Wohnung, etc.",
"applying-changes": "Änderungen anwenden", "api-endpoint": "API-Endpunkt",
"attention": "Achtung!", "application_name": "Lauf für Kaya! - Admin",
"author": "Autor:in", "applying-changes": "Änderungen anwenden",
"bitte-bestaetige-diese-laeufer-fuer-den-import": "Bitte die Läufer:innen für den Import bestätigen.", "attention": "Achtung!",
"by": "von", "author": "Autor:in",
"cancel": "Abbrechen", "average-distance": "Durchschnittliche Strecke/Läufer:in",
"cancel-delete": "Löschen abbrechen", "average-donation": "Durchschnittliches Sponsoring",
"cancel-keep-donor": "Abbrechen, Sponsor:in behalten", "bitte-bestaetige-diese-laeufer-fuer-den-import": "Bitte die Läufer:innen für den Import bestätigen.",
"cancel-keep-my-profile": "Abbrechen, mein Profil behalten", "by": "von",
"cancel-keep-organization": "Abbrechen und Organisation bearbeiten", "cancel": "Abbrechen",
"cancel-keep-statsclient": "Abbrechen und Statsclient behalten", "cancel-delete": "Löschen abbrechen",
"cancel-keep-team": "Abbrechen, Team behalten", "cancel-keep-donor": "Abbrechen, Sponsor:in behalten",
"cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.", "cancel-keep-my-profile": "Abbrechen, mein Profil behalten",
"card": "Läuferkarte", "cancel-keep-organization": "Abbrechen und Organisation bearbeiten",
"card-added": "Karte wurde hinzugefügt", "cancel-keep-station": "Abbrechen und Station behalten",
"card-deleted": "Karte gelöscht", "cancel-keep-statsclient": "Abbrechen und Statsclient behalten",
"card-updated": "Karte aktualisiert", "cancel-keep-team": "Abbrechen, Team behalten",
"cards": "Läuferkarten", "cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.",
"cards-deleted": "Karten gelöscht", "card": "Läuferkarte",
"certificates": "Urkunden", "card-added": "Karte wurde hinzugefügt",
"change-your-password-here": "Hier kannst du dein Passwort ändern", "card-deleted": "Karte gelöscht",
"changing-your-password": "Passwort wird geändert", "card-updated": "Karte aktualisiert",
"city": "Stadt", "cards": "Läuferkarten",
"click-to-copy-the-link-into-your-clipboard": "Klicke auf den Link, um ihn in deine Zwischenablage zu kopieren", "cards-deleted": "Karten gelöscht",
"click-to-copy-token-to-clipboard": "Klicke auf den Token, um ihn in deine Zwischenablage zu kopieren", "certificates": "Urkunden",
"close": "Schließen", "change-your-password-here": "Hier kannst du dein Passwort ändern",
"code": "Code", "changing-your-password": "Passwort wird geändert",
"configure-the-tracks-and-minimum-lap-times": "Bearbeite die Tracks und ihre minimale Rundenzeit", "city": "Stadt",
"confirm": "Bestätigen", "click-to-copy-the-link-into-your-clipboard": "Klicke auf den Link, um ihn in deine Zwischenablage zu kopieren",
"confirm-delete": "Löschung Bestätigen", "click-to-copy-token-to-clipboard": "Klicke auf den Token, um ihn in deine Zwischenablage zu kopieren",
"confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor:in mit allen Sponsorings löschen", "close": "Schließen",
"confirm-delete-my-user-profile": "Bestätigung, mein Benutzerprofil löschen", "code": "Code",
"confirm-delete-organization-and-associated-teams-runners": "Bestätugung, lösche die Organisation und alle zugehörigen Teams und Läufer:innen.", "config-codes": "Konfigurations-Codes",
"confirm-delete-statsclient": "Bestätigung, Statsclient löschen", "configure-the-tracks-and-minimum-lap-times": "Bearbeite die Tracks und ihre minimale Rundenzeit",
"confirm-delete-team-and-associated-runners": "Bestätigung, lösche das Team mitsamt seinen Läufer:innen.", "confirm": "Bestätigen",
"confirm-deletion": "Löschung Bestätigen", "confirm-delete": "Löschung Bestätigen",
"confirm-the-new-password": "Neues Passwort bestätigen", "confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor:in mit allen Sponsorings löschen",
"contact": "Kontakt", "confirm-delete-my-user-profile": "Bestätigung, mein Benutzerprofil löschen",
"contact-added": "Kontakt wurde hinzugefügt", "confirm-delete-organization-and-associated-teams-runners": "Bestätugung, lösche die Organisation und alle zugehörigen Teams und Läufer:innen.",
"contact-deleted": "Kontakt gelöscht", "confirm-delete-station-with-all-scans": "Löschen der Scannerstation mit allen Scans bestätigen",
"contact-information": "Kontaktinformation", "confirm-delete-statsclient": "Bestätigung, Statsclient löschen",
"contact-is-being-added": "Kontakt wird erstellt...", "confirm-delete-team-and-associated-runners": "Bestätigung, lösche das Team mitsamt seinen Läufer:innen.",
"contact-is-being-updated": "Kontakt wird aktualisiert ...", "confirm-deletion": "Löschung Bestätigen",
"contact-is-not-a-member-in-any-group": "Kontakt gehört zu keiner Gruppe", "confirm-the-new-password": "Neues Passwort bestätigen",
"contacts": "Kontakte", "contact": "Kontakt",
"contacts-are-being-loaded": "Kontakte werden geladen ...", "contact-added": "Kontakt wurde hinzugefügt",
"copied-link-to-clipboard": "Link wurde in die Zwischenablage kopiert", "contact-deleted": "Kontakt gelöscht",
"copied-token-to-clipboard": "Token wurde in die Zwischenablage kopiert", "contact-information": "Kontaktinformation",
"count_organizations": "Organisationen (Anzahl)", "contact-is-being-added": "Kontakt wird erstellt...",
"count_teams": "Teams (Anzahl)", "contact-is-being-updated": "Kontakt wird aktualisiert ...",
"create": "Erstellen", "contact-is-not-a-member-in-any-group": "Kontakt gehört zu keiner Gruppe",
"create-a-new": "Erstelle eine neue", "contacts": "Kontakte",
"create-a-new-card": "Neue Läuferkarte erstellen", "contacts-are-being-loaded": "Kontakte werden geladen ...",
"create-a-new-contact": "Kontakt erstellen", "copied-link-to-clipboard": "Link wurde in die Zwischenablage kopiert",
"create-a-new-distance-donation": "Erstelle ein neues Sponsoring", "copied-token-to-clipboard": "Token wurde in die Zwischenablage kopiert",
"create-a-new-donor": "Neue Sponsor:in erstellen", "count_organizations": "Organisationen (Anzahl)",
"create-a-new-fixed-donation": "Erstelle eine neue Festbetragsspende", "count_teams": "Teams (Anzahl)",
"create-a-new-organization": "Neue Organisation anlegen", "create": "Erstellen",
"create-a-new-runner": "Neue Läufer:in erstellen", "create-a-new": "Erstelle eine neue",
"create-a-new-scan-fixed-only": "Neuen Scan erstellen (nur mit Festdistanz)", "create-a-new-card": "Neue Läuferkarte erstellen",
"create-a-new-scanstation": "Neue Station erstellen", "create-a-new-contact": "Kontakt erstellen",
"create-a-new-statsclient": "Neuen Statsclient erstellen", "create-a-new-distance-donation": "Erstelle ein neues Sponsoring",
"create-a-new-team": "Erstelle ein neues Team", "create-a-new-donor": "Neue Sponsor:in erstellen",
"create-a-new-track": "Neuen Track erstellen", "create-a-new-fixed-donation": "Erstelle eine neue Festbetragsspende",
"create-a-new-user": "Neue Benutzer:in anlegen", "create-a-new-organization": "Neue Organisation anlegen",
"create-a-new-user-group": "Erstelle eine neue Gruppe", "create-a-new-runner": "Neue Läufer:in erstellen",
"create-and-generate-pdf": "Erstellen und PDF herunterladen", "create-a-new-scan-fixed-only": "Neuen Scan erstellen (nur mit Festdistanz)",
"create-bulk-blanco-cards": "Blankokarten erstellen", "create-a-new-scanstation": "Neue Station erstellen",
"create-bulk-cards": "Blankokarten erstellen", "create-a-new-statsclient": "Neuen Statsclient erstellen",
"create-organization": "Organisation erstellen", "create-a-new-team": "Erstelle ein neues Team",
"create-team": "Team erstellen", "create-a-new-track": "Neuen Track erstellen",
"create-track": "Track erstellen", "create-a-new-user": "Neue Benutzer:in anlegen",
"create-user": "Benutzer anlegen", "create-a-new-user-group": "Erstelle eine neue Gruppe",
"create-without-pdf": "Ohne PDF erstellen", "create-and-generate-pdf": "Erstellen und PDF herunterladen",
"created-blanco-cards": "Blankokarten wurden erstellt", "create-bulk-blanco-cards": "Blankokarten erstellen",
"creating-blanco-cards": "Erstelle Blankokarten", "create-bulk-cards": "Blankokarten erstellen",
"credits": "Credits", "create-organization": "Organisation erstellen",
"csv_import__class": "Klasse", "create-team": "Team erstellen",
"csv_import__firstname": "Vorname", "create-track": "Track erstellen",
"csv_import__lastname": "Nachname", "create-user": "Benutzer anlegen",
"csv_import__middlename": "Mittelname", "create-without-pdf": "Ohne PDF erstellen",
"csv_import__team": "Team", "created-blanco-cards": "Blankokarten wurden erstellt",
"danger-zone": "Gefahrenzone", "creating-blanco-cards": "Erstelle Blankokarten",
"dashboard-greeting": "Hallo", "credits": "Credits",
"dashboard-title": "Dashboard", "csv_import__class": "Klasse",
"datatable": { "csv_import__firstname": "Vorname",
"search": "🔍 Suche ...", "csv_import__lastname": "Nachname",
"an_error_happened_while_fetching_the_data": "Beim Abrufen der Daten ist ein Fehler aufgetreten", "csv_import__middlename": "Mittelname",
"loading": "Wird geladen...", "csv_import__team": "Team",
"next": "Nächste", "danger-zone": "Gefahrenzone",
"of": "von", "dashboard-greeting": "Hallo",
"previous": "Vorherige", "dashboard-title": "Dashboard",
"to": "bis", "datatable": {
"showing": "Zeige", "search": "🔍 Suche ...",
"no_matching_records_found": "Keine passenden Einträge gefunden", "an_error_happened_while_fetching_the_data": "Beim Abrufen der Daten ist ein Fehler aufgetreten",
"page": "Seite", "loading": "Wird geladen...",
"records": "Einträge", "next": "Nächste",
"sort_column_ascending": "Spalte aufsteigend sortieren", "of": "von",
"sort_column_descending": "Spalte absteigend sortieren" "previous": "Vorherige",
}, "to": "bis",
"delete": "Löschen", "showing": "Zeige",
"delete-cards": "Karten löschen", "no_matching_records_found": "Keine passenden Einträge gefunden",
"delete-contact": "Kontakt löschen", "page": "Seite",
"delete-donation": "Sponsoring löschen", "records": "Einträge",
"delete-donor": "Sponsor:in löschen", "sort_column_ascending": "Spalte aufsteigend sortieren",
"delete-group": "Gruppe löschen", "sort_column_descending": "Spalte absteigend sortieren"
"delete-organization": "Organisation löschen", },
"delete-profile": "Profil löschen", "delete": "Löschen",
"delete-runner": "Läufer:in löschen", "delete-cards": "Karten löschen",
"delete-scan": "Scan löschen", "delete-contact": "Kontakt löschen",
"delete-scans": "Scans löschen", "delete-donation": "Sponsoring löschen",
"delete-station": "Station löschen", "delete-donor": "Sponsor:in löschen",
"delete-statsclient": "Statsclient löschen", "delete-group": "Gruppe löschen",
"delete-team": "Team Löschen", "delete-organization": "Organisation löschen",
"delete-user": "Benutzer:in löschen", "delete-profile": "Profil löschen",
"deleted-scan": "Scan wurde gelöscht", "delete-runner": "Läufer:in löschen",
"dependency_name": "Name", "delete-scan": "Scan löschen",
"description": "Beschreibung", "delete-scans": "Scans löschen",
"description-optional": "Beschreibung (optional)", "delete-station": "Station löschen",
"deselect-all": "Alle abwählen", "delete-statsclient": "Statsclient löschen",
"details": "Details", "delete-team": "Team Löschen",
"disabled": "deaktiviert", "delete-user": "Benutzer:in löschen",
"distance": "Distanz", "deleted-scan": "Scan wurde gelöscht",
"distance-donation": "Sponsoring", "dependency_name": "Name",
"distance-in-km": "Distanz (in KM)", "description": "Beschreibung",
"distance-track": "Distanz (+Track)", "description-optional": "Beschreibung (optional)",
"do-you-really-want-to-delete-your-profile": "Möchtest du dein Profil wirklich löschen?", "deselect-all": "Alle abwählen",
"do-you-want-to-delete-the-organization-delete_org-name": "Möchtest du die Organisation {orgname} löschen?", "details": "Details",
"do-you-want-to-delete-the-team-delete_team-name": "Möchtest du das Team {teamname} löschen?", "disabled": "deaktiviert",
"do-you-want-to-delete-this-donor-with-all-related-donations": "Möchtest du diese Sponsor:in mit all ihren Sponsorings löschen?", "distance": "Distanz",
"documentation": "Dokumentation", "distance-donation": "Sponsoring",
"donation-amount": "Sponsoringbetrag", "distance-in-km": "Distanz (in KM)",
"donation-amount-must-be-greater-that-0-00eur": "Der Sponsoringbetrag muss größer als 0.00€ sein.", "distance-track": "Distanz (+Track)",
"donation-deleted": "Sponsoring gelöscht", "do-you-really-want-to-delete-your-profile": "Möchtest du dein Profil wirklich löschen?",
"donation-updated": "Sponsoring wurde aktualisiert", "do-you-want-to-delete-the-organization-delete_org-name": "Möchtest du die Organisation {orgname} löschen?",
"donation_added": "Sponsoring hinzugefügt", "do-you-want-to-delete-the-team-delete_team-name": "Möchtest du das Team {teamname} löschen?",
"donations": "Sponsorings", "do-you-want-to-delete-this-donor-with-all-related-donations": "Möchtest du diese Sponsor:in mit all ihren Sponsorings löschen?",
"donor": "Sponsor:in", "documentation": "Dokumentation",
"donor-added": "Sponsor:in hinzugefügt", "donation-amount": "Sponsoringbetrag",
"donor-deleted": "Sponsor:in gelöscht", "donation-amount-must-be-greater-that-0-00eur": "Der Sponsoringbetrag muss größer als 0.00€ sein.",
"donor-has-no-associated-donations": "Zur Sponsor:in gibt es noch keine Sponsorings", "donation-deleted": "Sponsoring gelöscht",
"donor-is-being-added": "Sponsor:in wird hinzugefügt...", "donation-updated": "Sponsoring wurde aktualisiert",
"donor-is-being-updated": "Sponsor:in wird aktualisiert", "donation_added": "Sponsoring hinzugefügt",
"donors": "Sponsor:innen", "donations": "Sponsorings",
"donors-are-being-loaded": "Sponsor:innen werden geladen", "donations-are-being-loaded": "Sponsorings werden geladen...",
"dont-have-your-email-connected": "Deine E-Mail ist nicht verknüpft?", "donor": "Sponsor:in",
"dont-panic-were-resetting-it": "Keine Panik, wir setzen es zurück ✌", "donor-added": "Sponsor:in hinzugefügt",
"e-mail-adress": "E-Mail-Adresse", "donor-deleted": "Sponsor:in gelöscht",
"edit": "Bearbeiten", "donor-has-no-associated-donations": "Keine Sponsorings",
"edit-a-card": "Läuferkarte bearbeiten", "donor-is-being-added": "Sponsor:in wird hinzugefügt...",
"edit-permissions": "Berechtigungen bearbeiten", "donor-is-being-updated": "Sponsor:in wird aktualisiert",
"email_address_or_username": "E-Mail-Adresse/ Benutzername", "donors": "Sponsor:innen",
"enabled": "aktiviert", "donors-are-being-loaded": "Sponsor:innen werden geladen",
"enabled_large": "Aktiviert", "dont-have-your-email-connected": "Deine E-Mail ist nicht verknüpft?",
"english": "Englisch", "dont-panic-were-resetting-it": "Keine Panik, wir setzen es zurück ✌",
"enter-payment": "Zahlung eingeben", "e-mail-adress": "E-Mail-Adresse",
"error-during-import": "Fehler beim Importieren", "edit": "Bearbeiten",
"error-whyile-copying-to-clipboard": "Fehler beim Kopieren in die Zwischenablage", "edit-a-card": "Läuferkarte bearbeiten",
"error_on_login": "😢Fehler beim Login", "edit-permissions": "Berechtigungen bearbeiten",
"erteilte": "Direkt erteilte", "email_address_or_username": "E-Mail-Adresse/ Benutzername",
"everything-concerning-your-profile": "Alles zu deinem Profil", "enabled": "aktiviert",
"everything-is-more-fun-together": "Im Team macht's mehr Spaß 🏃‍♂️🏃‍♀️🏃‍♂️", "enabled_large": "Aktiviert",
"faq": "FAQ", "english": "Englisch",
"filename_sponsoringquittungsliste": "SponsoringQuittungsListe", "enter-payment": "Zahlung eingeben",
"filter-by-organization-team": "Filtern nach Organisation / Team", "error-during-import": "Fehler beim Importieren",
"first-name": "Vorname", "error-whyile-copying-to-clipboard": "Fehler beim Kopieren in die Zwischenablage",
"first-name-is-required": "Vorname muss angegeben werden", "error_on_login": "😢Fehler beim Login",
"first-scan-of-the-day": "Erster Scan des Tages", "erteilte": "Direkt erteilte",
"fixed-donation": "Festbetragsspende", "everything-concerning-your-profile": "Alles zu deinem Profil",
"forgot_password": "Passwort vergessen?", "everything-is-more-fun-together": "Im Team macht's mehr Spaß 🏃‍♂️🏃‍♀️🏃‍♂️",
"geerbte": "geerbte", "faq": "FAQ",
"general-stats": "Allgemeine Statistiken", "filename_sponsoringquittungsliste": "SponsoringQuittungsListe",
"general_promise_error": "😢 Ein unbekannter Fehler ist aufgetreten", "filter-by-organization-team": "Filtern nach Organisation / Team",
"generate-runner-certificate": "Urkunde generieren", "first-name": "Vorname",
"generate-runner-certificates": "Urkunden generieren", "first-name-is-required": "Vorname muss angegeben werden",
"generate-runnercards": "Läuferkarten generieren", "first-scan-of-the-day": "Erster Scan des Tages",
"generate-sponsoring-contract": "Sponsoringvertrag generieren", "fixed-donation": "Festbetragsspende",
"generate-sponsoring-contracts": "Sponsoringverträge generieren", "forgot_password": "Passwort vergessen?",
"generating-pdf": "PDF wird generiert...", "geerbte": "geerbte",
"generating-pdfs": "PDFs werden generiert...", "general-stats": "Allgemeine Statistiken",
"generic-ui-logic-error": "Etwas ist in der Benutzeroberfläche schiefgelaufen.", "general_promise_error": "😢 Ein unbekannter Fehler ist aufgetreten",
"german": "Deutsch", "generate-runner-certificate": "Urkunde generieren",
"go-to-login": "Zum Login", "generate-runner-certificates": "Urkunden generieren",
"goback": "Zur Startseite", "generate-runnercards": "Läuferkarten generieren",
"granted": "Gewährt", "generate-sponsoring-contract": "Sponsoringvertrag generieren",
"group": "Gruppe", "generate-sponsoring-contracts": "Sponsoringverträge generieren",
"group-added": "Gruppe hinzugefügt", "generating-pdf": "PDF wird generiert...",
"group-is-being-added": "Gruppe wird erstellt", "generating-pdfs": "PDFs werden generiert...",
"group-name-is-required": "Der Gruppenname muss angegeben werden.", "generic-ui-logic-error": "Etwas ist in der Benutzeroberfläche schiefgelaufen.",
"group-updated": "Gruppe aktualisiert", "german": "Deutsch",
"groups": "Gruppen", "go-to-login": "Zum Login",
"groups-are-being-loaded": "Gruppen werden geladen", "goback": "Zur Startseite",
"home": "Start", "granted": "Gewährt",
"icon-image-credits": "Wir möchten uns außerdem für die verwendeten Icons und Bilder bedanken bei:", "group": "Gruppe",
"if-you-want-to-create-multiple-blanco-cards-try-the-add-bulk-button": "Wenn du mehrere Blankokarten erstellen willst, nutze doch den \"Blankokarten erstellen\" Knopf.", "group-added": "Gruppe hinzugefügt",
"import-finished": "Import abgeschlossen", "group-is-being-added": "Gruppe wird erstellt",
"import-runners": "Läufer:innen importieren", "group-name-is-required": "Der Gruppenname muss angegeben werden.",
"import__target-organization": "Ziel Organisation", "group-updated": "Gruppe aktualisiert",
"imprint": "Impressum ", "groups": "Gruppen",
"imprint-loading": "Impressum lädt...", "groups-are-being-loaded": "Gruppen werden geladen",
"inactive": "Inaktiv", "home": "Start",
"installed-version": "Installierte Version", "icon-image-credits": "Wir möchten uns außerdem für die verwendeten Icons und Bilder bedanken bei:",
"internal-error": "Interner Fehler", "if-you-want-to-create-multiple-blanco-cards-try-the-add-bulk-button": "Wenn du mehrere Blankokarten erstellen willst, nutze doch den \"Blankokarten erstellen\" Knopf.",
"invalid": "Ungültig", "import-finished": "Import abgeschlossen",
"invalid-mail-reset": "Das ist keine gültige E-Mail", "import-runners": "Läufer:innen importieren",
"just-enter-how-many-you-want-and-the-system-will-create-them": "Gebe einfach ein, wie viele Blankokarten das System erstellen soll.", "import__target-organization": "Ziel Organisation",
"key": "Schlüssel", "imprint": "Impressum ",
"laeufer-hinzufuegen": "Läufer:in hinzufügen", "imprint-loading": "Impressum lädt...",
"laeufer-importieren": "Läufer:innen importieren", "inactive": "Inaktiv",
"laptime": "Rundenzeit", "installed-version": "Installierte Version",
"last-name": "Nachname", "internal-error": "Interner Fehler",
"last-name-is-required": "Nachname muss angegeben werden", "invalid": "Ungültig",
"lfk-is-os": "Das \"Lauf für Kaya!\" Frontend ist (wie alle anderen Projekte für den \"LfK!\" auch) ein OpenSource Projekt.", "invalid-mail-reset": "Das ist keine gültige E-Mail",
"license": "Lizenz", "just-enter-how-many-you-want-and-the-system-will-create-them": "Gebe einfach ein, wie viele Blankokarten das System erstellen soll.",
"licenses-are-being-loaded": "Lizenzen werden geladen...", "key": "Schlüssel",
"loading-cards": "Läuferkarten werden geladen", "laeufer-hinzufuegen": "Läufer:in hinzufügen",
"loading-contact-details": "Kontaktdaten werden geladen ...", "laeufer-importieren": "Läufer:innen importieren",
"loading-donation-details": "Lade Sponsoringdetails", "laptime": "Rundenzeit",
"loading-donor-details": "Lade Details", "last-name": "Nachname",
"loading-group-detail": "Lade Gruppendetails...", "last-name-is-required": "Nachname muss angegeben werden",
"loading-profile-data": "Lade Profildaten", "lfk-is-os": "Das \"Lauf für Kaya!\" Frontend ist (wie alle anderen Projekte für den \"LfK!\" auch) ein OpenSource Projekt.",
"loading-runners": "Läufer:innen werden geladen...", "license": "Lizenz",
"loading-station-details": "Lade Scanstation-Details ...", "licenses-are-being-loaded": "Lizenzen werden geladen...",
"log_in": "Anmelden", "loading-cards": "Läuferkarten werden geladen",
"log_in_to_your_account": "Bitte melde dich an", "loading-contact-details": "Kontaktdaten werden geladen ...",
"login_is_checked": "Login wird überprüft", "loading-donation-details": "Lade Sponsoringdetails",
"logout": "Abmelden", "loading-donor-details": "Lade Details",
"mail-validation-in-progress": "E-Mail Verifizierung läuft... ", "loading-group-detail": "Lade Gruppendetails...",
"manage-admin-users": "Nutzer verwalten", "loading-profile-data": "Lade Profildaten",
"middle-name": "Mittelname", "loading-runners": "Läufer:innen werden geladen...",
"minimum-lap-time-in-s": "Minimale Rundenzeit (in Sekunden)", "loading-station-details": "Lade Scanstation-Details ...",
"minimum-lap-time-must-be-a-positive-number-or-0": "Die minimale Rundenzeit muss eine positive Zahl oder 0 sein", "log_in": "Anmelden",
"must-be-at-least-10-characters-long": "Passwort muss mindestens 10 Zeichen lang sein!", "log_in_to_your_account": "Bitte melde dich an",
"must-contain-a-lowercase-letter": "Passwort muss einen Großbuchstaben enthalten!", "login_is_checked": "Login wird überprüft",
"must-contain-a-number": "Passwort muss eine Zahl enthalten!", "logout": "Abmelden",
"must-contain-a-uppercase-letter": "Passwort muss einen Kleinbuchstaben enthalten!", "mail-validation-in-progress": "E-Mail Verifizierung läuft... ",
"name": "Name", "manage-admin-users": "Nutzer verwalten",
"name-is-required": "Der Gruppenname muss angegeben werden", "middle-name": "Mittelname",
"new-password": "Neues Passwort", "minimum-lap-time-in-s": "Minimale Rundenzeit (in Sekunden)",
"no-contact-found": "Keine Kontakte gefunden", "minimum-lap-time-must-be-a-positive-number-or-0": "Die minimale Rundenzeit muss eine positive Zahl oder 0 sein",
"no-contact-selected": "Kein Kontakt ausgewählt", "must-be-at-least-10-characters-long": "Passwort muss mindestens 10 Zeichen lang sein!",
"no-contact-specified": "Kein Kontakt angegeben", "must-contain-a-lowercase-letter": "Passwort muss einen Großbuchstaben enthalten!",
"no-donors-found": "Keine Spender:innen gefunden", "must-contain-a-number": "Passwort muss eine Zahl enthalten!",
"no-license-text-could-be-found": "Kein Lizenz-Text gefunden 😢", "must-contain-a-uppercase-letter": "Passwort muss einen Kleinbuchstaben enthalten!",
"no-organization-or-team-found": "Keine Organisationen oder Teams gefunden", "name": "Name",
"no-organization-specified": "Keine Organisation angegeben", "name-is-required": "Der Gruppenname muss angegeben werden",
"no-organizations-found": "Keine Organisationen gefunden", "new-password": "Neues Passwort",
"no-runners-found": "Keine Läufer:innen gefunden", "no-address": "Keine Adresse hinterlegt",
"no-tracks-added-yet": "Es wurden noch keine Tracks erstellt.", "no-contact-found": "Keine Kontakte gefunden",
"non-blanko": "Keine/Blankokarte", "no-contact-selected": "Kein Kontakt ausgewählt",
"open": "OFFEN", "no-contact-specified": "Kein Kontakt angegeben",
"organization": "Organisation", "no-donors-found": "Keine Spender:innen gefunden",
"organization-added": "Organisation hinzugefügt", "no-license-text-could-be-found": "Kein Lizenz-Text gefunden 😢",
"organization-deleted": "Organisation gelöscht", "no-organization-or-team-found": "Keine Organisationen oder Teams gefunden",
"organization-detail-is-being-loaded": "Organisationsdetails werden geladen ...", "no-organization-specified": "Keine Organisation angegeben",
"organization-is-being-added": "Organisation wird hinzugefügt ...", "no-organizations-found": "Keine Organisationen gefunden",
"organization-name-is-required": "Der Name muss angegeben werden", "no-runners-found": "Keine Läufer:innen gefunden",
"organizations": "Organisationen", "no-tracks-added-yet": "Es wurden noch keine Tracks erstellt.",
"organizations-are-being-loaded": "Organisationen werden geladen ...", "non-blanko": "Keine/Blankokarte",
"orgs": "Organisationen", "open": "OFFEN",
"oss_credit_description": "Wir verwenden eine Menge Open Source-Software bei diesen Projekten und möchten uns bei den folgenden Projekten und Mitwirkenden bedanken, die dazu beitragen, Open Source großartig zu machen!", "organization": "Organisation",
"paid": "BEZAHLT", "organization-added": "Organisation hinzugefügt",
"paid-amount": "Gezahlter Betrag", "organization-deleted": "Organisation gelöscht",
"password": "Passwort", "organization-detail-is-being-loaded": "Organisationsdetails werden geladen ...",
"password-changed": "Passwort wurde aktualisiert!", "organization-is-being-added": "Organisation wird hinzugefügt ...",
"password-is-required": "Passwort muss angegeben werden", "organization-name-is-required": "Der Name muss angegeben werden",
"password-reset-failed": "Passwort zurücksetzen ist fehlgeschlagen!", "organizations": "Organisationen",
"password-reset-in-progress": "Passwort wird zurückgesetzt...", "organizations-are-being-loaded": "Organisationen werden geladen ...",
"password-reset-mail-sent": "Passwort-Reset Mail wurde an \"{usersEmail}\" geschickt.", "orgs": "Organisationen",
"password-reset-successful": "Passwort erfolgreich zurückgesetzt!", "oss_credit_description": "Wir verwenden eine Menge Open Source-Software bei diesen Projekten und möchten uns bei den folgenden Projekten und Mitwirkenden bedanken, die dazu beitragen, Open Source großartig zu machen!",
"passwords-dont-match": "Die Passwörter stimmen nicht überein!", "paid": "BEZAHLT",
"payment-amount-must-be-greater-than-0-00eur": "Der Zahlungsbetrag muss größer als 0.00€ sein!", "paid-amount": "Gezahlter Betrag",
"pdf-generation-failed": "PDF Generierung fehlgeschlagen!", "password": "Passwort",
"pdf-successfully-generated": "PDF wurde erfolgreich generiert!", "password-changed": "Passwort wurde aktualisiert!",
"pdfs-successfully-generated": "Alle PDFs wurden generiert!", "password-is-required": "Passwort muss angegeben werden",
"per-kilometer": "pro Kilometer", "password-reset-failed": "Passwort zurücksetzen ist fehlgeschlagen!",
"permissions": "Berechtigungen", "password-reset-in-progress": "Passwort wird zurückgesetzt...",
"permissions-updated": "Berechtigungen aktualisiert!", "password-reset-mail-sent": "Passwort-Reset Mail wurde an \"{usersEmail}\" geschickt.",
"phone": "Telefon", "password-reset-successful": "Passwort erfolgreich zurückgesetzt!",
"please-confirm-the-deletion-of-card": "Bitte bestätige die Löschung der Karte", "passwords-dont-match": "Die Passwörter stimmen nicht überein!",
"please-confirm-the-deletion-of-runner": "Bitte bestätige die Löschung der Läufer:in", "payment-amount-must-be-greater-than-0-00eur": "Der Zahlungsbetrag muss größer als 0.00€ sein!",
"please-confirm-the-deletion-of-scan": "Bitte bestätige die Löschung des Scans", "pdf-generation-failed": "PDF Generierung fehlgeschlagen!",
"please-copy-the-token-and-store-it-somewhere-save": "Bitte kopiere dir den Token und bewahre ihn gut auf.", "pdf-successfully-generated": "PDF wurde erfolgreich generiert!",
"please-provide-a-password": "Bitte gebe ein Passwort an...", "pdfs-successfully-generated": "Alle PDFs wurden generiert!",
"please-provide-the-nessecary-information-to-add-a-new-donor": "Bitte mach die Notwendigen Angaben, um eine neue Sponsor:in zu erstellen", "per-kilometer": "pro Kilometer",
"please-provide-the-nessecary-information-to-create-a-new-donation": "Bitte gebe alle für das Sponsoring notwendigen Daten an.", "permissions": "Berechtigungen",
"please-provide-the-nessecary-information-to-create-a-new-scan": "Bitte gebe alle notwendigen Informationen an, um einen neuen Scan zu erstellen.", "permissions-updated": "Berechtigungen aktualisiert!",
"please-provide-the-required-csv-xlsx-file": "Bitte eine CSV oder XLSX Datei hochladen.", "phone": "Telefon",
"please-provide-the-required-information-for-creating-a-new-user-group": "Bitte gebe alle für eine neue Gruppe notwendigen Informationen an.", "please-confirm-the-deletion-of-card": "Bitte bestätige die Löschung der Karte",
"please-provide-the-required-information-to-add-a-new-contact": "Bitte gebe alle nötigen Informationen an, im den neuen Kontakt zu erstellen.", "please-confirm-the-deletion-of-donation": "Bitte bestätige die Löschung des Sponsorings",
"please-provide-the-required-information-to-add-a-new-organization": "Bitte gebe alle nötigen Informationen an, im die neue Organisation zu erstellen.", "please-confirm-the-deletion-of-runner": "Bitte bestätige die Löschung der Läufer:in",
"please-provide-the-required-information-to-add-a-new-runner": "Bitte die benötigten Informationen angeben.", "please-confirm-the-deletion-of-scan": "Bitte bestätige die Löschung des Scans",
"please-provide-the-required-information-to-add-a-new-team": "Bitte gebe alle nötigen Informationen an, im das neue Team zu erstellen.", "please-copy-the-token-and-store-it-somewhere-save": "Bitte kopiere dir den Token und bewahre ihn gut auf.",
"please-provide-the-required-information-to-add-a-new-track": "Bitte die benötigten Informationen angeben.", "please-provide-a-password": "Bitte gebe ein Passwort an...",
"please-provide-the-required-information-to-add-a-new-user": "Bitte gebe alle nötigen Informationen an, im die neue Benutzer:in zu erstellen.", "please-provide-the-nessecary-information-to-add-a-new-donor": "Bitte mach die Notwendigen Angaben, um eine neue Sponsor:in zu erstellen",
"please-provide-the-required-information-to-create-a-new-scanstation": "Bitte gebe alle für eine Scannerstation notwendigen Informationen an", "please-provide-the-nessecary-information-to-create-a-new-donation": "Bitte gebe alle für das Sponsoring notwendigen Daten an.",
"please-provide-the-required-information-to-create-a-new-statsclient": "Bitte gebe alle für einen Statsclient notwendigen Informationen an", "please-provide-the-nessecary-information-to-create-a-new-scan": "Bitte gebe alle notwendigen Informationen an, um einen neuen Scan zu erstellen.",
"please-request-a-new-reset-mail": "Bitte eine neue Passwortreset-Mail anfordern...", "please-provide-the-required-csv-xlsx-file": "Bitte eine CSV oder XLSX Datei hochladen.",
"please-wait-a-moment-your-login-is-still-being-processed": "Bitte warte einen Moment, deine Anmeldung wird verarbeitet", "please-provide-the-required-information-for-creating-a-new-user-group": "Bitte gebe alle für eine neue Gruppe notwendigen Informationen an.",
"prefix": "Prefix", "please-provide-the-required-information-to-add-a-new-contact": "Bitte gebe alle nötigen Informationen an, im den neuen Kontakt zu erstellen.",
"privacy": "Datenschutz", "please-provide-the-required-information-to-add-a-new-organization": "Bitte gebe alle nötigen Informationen an, im die neue Organisation zu erstellen.",
"privacy-loading": "Datenschutzerklärung lädt...", "please-provide-the-required-information-to-add-a-new-runner": "Bitte die benötigten Informationen angeben.",
"profile": "Profil", "please-provide-the-required-information-to-add-a-new-team": "Bitte gebe alle nötigen Informationen an, im das neue Team zu erstellen.",
"profile-deleted": "Profil gelöscht!", "please-provide-the-required-information-to-add-a-new-track": "Bitte die benötigten Informationen angeben.",
"profile-picture": "Profilbild", "please-provide-the-required-information-to-add-a-new-user": "Bitte gebe alle nötigen Informationen an, im die neue Benutzer:in zu erstellen.",
"profile-updated": "Profil wurde aktualisiert!", "please-provide-the-required-information-to-create-a-new-scanstation": "Bitte gebe alle für eine Scannerstation notwendigen Informationen an",
"read-license": "Lizenz-Text lesen", "please-provide-the-required-information-to-create-a-new-statsclient": "Bitte gebe alle für einen Statsclient notwendigen Informationen an",
"receipt-needed": "Spendenquittung benötigt", "please-request-a-new-reset-mail": "Bitte eine neue Passwortreset-Mail anfordern...",
"repo_link": "Link", "please-wait-a-moment-your-login-is-still-being-processed": "Bitte warte einen Moment, deine Anmeldung wird verarbeitet",
"request-a-new-reset-mail": "Neue Reset-Mail anfordern", "prefix": "Prefix",
"reset-my-password": "Passwort zurücksetzen", "privacy": "Datenschutz",
"reset-password": "Passwort zurücksetzen", "privacy-loading": "Datenschutzerklärung lädt...",
"runner": "Läufer:in", "profile": "Profil",
"runner-added": "Läufer:in hinzugefügt", "profile-deleted": "Profil gelöscht!",
"runner-deleted": "Läufer:in gelöscht", "profile-picture": "Profilbild",
"runner-import": "Läufer:innen Import", "profile-updated": "Profil wurde aktualisiert!",
"runner-is-being-added": "Läufer:in wird hinzugefügt...", "read-license": "Lizenz-Text lesen",
"runner-updated": "Läufer:in aktualisiert!", "receipt-needed": "Spendenquittung benötigt",
"runnercards": "Laeuferkarten", "repo_link": "Link",
"runnerimport_verify_runners_org": "Bitte die Läufer:innen für den Import in die Organisation \"{org_name}\" bestätigen", "request-a-new-reset-mail": "Neue Reset-Mail anfordern",
"runners": "Läufer", "reset-my-password": "Passwort zurücksetzen",
"runners-are-being-imported": "Läufer:innen werden importiert ...", "reset-password": "Passwort zurücksetzen",
"runners-are-being-loaded": "Läufer:innen werden geladen ...", "runner": "Läufer:in",
"save": "Speichern", "runner-added": "Läufer:in hinzugefügt",
"save-changes": "Änderungen speichern", "runner-deleted": "Läufer:in gelöscht",
"scan-added": "Scan hinzugefügt", "runner-import": "Läufer:innen Import",
"scan-deleted": "Scan gelöscht", "runner-is-being-added": "Läufer:in wird hinzugefügt...",
"scan-is-being-updated": "Scan wird aktualisiert", "runner-updated": "Läufer:in aktualisiert!",
"scan-with-fixed-distance": "Scan mit Festdistanz", "runnercards": "Laeuferkarten",
"scans": "Scans", "runnerimport_verify_runners_org": "Bitte die Läufer:innen für den Import in die Organisation \"{org_name}\" bestätigen",
"scans-are-being-loaded": "Scans werden geladen", "runners": "Läufer",
"scanstation": "Scanner Station", "runners-are-being-imported": "Läufer:innen werden importiert ...",
"scanstation-added": "Station wurde erstellt", "runners-are-being-loaded": "Läufer:innen werden geladen ...",
"scanstation-is-being-added": "Scannerstation wird angelegt...", "save": "Speichern",
"scanstations": "Scanner Stationen", "save-changes": "Änderungen speichern",
"scanstations-are-being-loaded": "Scannerstationen werden geladen...", "scan-added": "Scan hinzugefügt",
"search-for-an-organization-by-name-or-id": "Suche eine Organisation (via Name oder Id)", "scan-deleted": "Scan gelöscht",
"search-for-an-organization-or-team-by-name-or-id": "Suche eine Organisation oder ein Team (via Name oder Id)", "scan-is-being-updated": "Scan wird aktualisiert",
"search-for-donor-name-or-id": "Suche eine Spender:in (via Name oder Id)", "scan-with-fixed-distance": "Scan mit Festdistanz",
"search-for-permission": "Berechtigungen durchsuchen", "scans": "Scans",
"search-for-runner-by-name-or-id": "Suche eine Läufer:in (via Name oder Id)", "scans-are-being-loaded": "Scans werden geladen",
"select-all": "Alle auswählen", "scanstation": "Scanner Station",
"select-language": "Sprache auswählen", "scanstation-added": "Station wurde erstellt",
"selfservice-registration": "Selfservice Registrierung", "scanstation-is-being-added": "Scannerstation wird angelegt...",
"send-a-mail-to-lfk-odit-services": "Sende eine Mail an lfk@odit.services", "scanstations": "Scanner Stationen",
"set-the-user-active-inactive": "Den Benutzer auf (in)aktiv setzen", "scanstations-are-being-loaded": "Scannerstationen werden geladen...",
"settings": "Einstellungen", "search-for-an-organization-by-name-or-id": "Suche eine Organisation (via Name oder Id)",
"settings-for-your-profile": "Die Einstellungen deines Accounts", "search-for-an-organization-or-team-by-name-or-id": "Suche eine Organisation oder ein Team (via Name oder Id)",
"something-about-the-group": "Infos zur Gruppe", "search-for-donor-name-or-id": "Suche eine Spender:in (via Name oder Id)",
"sponsoring-quittungs-liste_herunterladen": "Sponsoring-Quittungs-Liste herunterladen", "search-for-permission": "Berechtigungen durchsuchen",
"sponsorings": "Sponsoringerklaerungen", "search-for-runner-by-name-or-id": "Suche eine Läufer:in (via Name oder Id)",
"stats-are-being-loaded": "Die Statistiken werden geladen...", "select-all": "Alle auswählen",
"statsclient-deleted": "Statsclient wurde gelöscht", "select-language": "Sprache auswählen",
"statsclient-is-being-added": "Statsclient wird angelegt...", "selfservice-registration": "Selfservice Registrierung",
"statsclients": "Statsclient (aka Beamershow)", "send-a-mail-to-lfk-odit-services": "Sende eine Mail an lfk@odit.services",
"statsclients-are-being-loaded": "Statsclients werden geladen", "set-the-user-active-inactive": "Den Benutzer auf (in)aktiv setzen",
"status": "Status", "settings": "Einstellungen",
"stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können", "settings-for-your-profile": "Die Einstellungen deines Accounts",
"successful-password-reset": "Passwort erfolgreich zurückgesetzt!", "something-about-the-group": "Infos zur Gruppe",
"team": "Team", "sponsoring-quittungs-liste_herunterladen": "Sponsoring-Quittungs-Liste herunterladen",
"team-added": "Team wurde hinzugefügt", "sponsorings": "Sponsoringerklaerungen",
"team-deleted": "Team gelöscht", "station-deleted": "Scannerstation gelöscht",
"team-detail-is-being-loaded": "Team wird geladen...", "stats-are-being-loaded": "Die Statistiken werden geladen...",
"team-is-being-added": "Team wird erstellt...", "statsclient-deleted": "Statsclient wurde gelöscht",
"team-name": "Teamname", "statsclient-is-being-added": "Statsclient wird angelegt...",
"team-name-is-required": "Teamname ist erforderlich", "statsclients": "Statsclient (aka Beamershow)",
"teams": "Teams", "statsclients-are-being-loaded": "Statsclients werden geladen",
"teams-are-being-loaded": "Teams werden geladen ...", "status": "Status",
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "Die angegebene Telefonnummer ist nicht korrekt. <br /> Bitte gebe eine Telefonnummer im internationalen Format an...", "stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können",
"the-scans-distance-must-be-greater-than-0m": "Die Distanz muss größer als 0m sein.", "successful-password-reset": "Passwort erfolgreich zurückgesetzt!",
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Scannerstation Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!", "team": "Team",
"the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Statsclient Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!", "team-added": "Team wurde hinzugefügt",
"there-are-no-cards-yet": "Es gibt noch keine Läuferkarten.", "team-deleted": "Team gelöscht",
"there-are-no-contacts-added-yet": "Es wurden noch keine Kontakte hinzugefügt.", "team-detail-is-being-loaded": "Team wird geladen...",
"there-are-no-donations-yet": "Es gibt noch keine Sponsorings", "team-is-being-added": "Team wird erstellt...",
"there-are-no-donors-yet": "Es gibt noch keine Sponsor:innen", "team-name": "Teamname",
"there-are-no-groups-yet": "Es gibt noch keine Gruppen", "team-name-is-required": "Teamname ist erforderlich",
"there-are-no-organizations-added-yet": "Es wurden noch keine Organisationen hinzugefügt.", "teams": "Teams",
"there-are-no-runners-added-yet": "Es wurden noch keine Läufer:innen hinzugefügt.", "teams-are-being-loaded": "Teams werden geladen ...",
"there-are-no-scans-yet": "Es gibt noch keine Scans", "the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "Die angegebene Telefonnummer ist nicht korrekt. <br /> Bitte gebe eine Telefonnummer im internationalen Format an...",
"there-are-no-teams-added-yet": "Es wurden noch keine Teams hinzugefügt.", "the-scans-distance-must-be-greater-than-0m": "Die Distanz muss größer als 0m sein.",
"there-are-no-users-added-yet": "Es wurden noch keine Benutzer hinzugefügt.", "the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Scannerstation Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!",
"this-card-is": "Diese Karte ist", "the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Statsclient Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!",
"this-might-take-a-moment": "Das könnte einen kleinen Moment dauern", "there-are-no-cards-yet": "Es gibt noch keine Läuferkarten.",
"this-scanstation-is": "Diese Station ist", "there-are-no-contacts-added-yet": "Es wurden noch keine Kontakte hinzugefügt.",
"token": "Token", "there-are-no-donations-yet": "Es gibt noch keine Sponsorings",
"total-distance": "gelaufene Strecke", "there-are-no-donors-yet": "Es gibt noch keine Sponsor:innen",
"total-donation-amount": "Gesamtbetrag", "there-are-no-groups-yet": "Es gibt noch keine Gruppen",
"total-donations": "Spendensumme", "there-are-no-organizations-added-yet": "Es wurden noch keine Organisationen hinzugefügt.",
"total-paid-amount": "Gezahlter Gesamtbetrag", "there-are-no-runners-added-yet": "Es wurden noch keine Läufer:innen hinzugefügt.",
"total-scans": "gesamte Scans", "there-are-no-scans-yet": "Es gibt noch keine Scans",
"total_donation_amount_in_eur": "Gesamtbetrag in €", "there-are-no-teams-added-yet": "Es wurden noch keine Teams hinzugefügt.",
"track": "Track", "there-are-no-users-added-yet": "Es wurden noch keine Benutzer hinzugefügt.",
"track-added": "Track hinzugefügt", "this-card-is": "Diese Karte ist",
"track-data-is-being-loaded": "Trackdaten werden geladen", "this-might-take-a-moment": "Das könnte einen kleinen Moment dauern",
"track-is-being-added": "Track wird hinzugefügt...", "this-scanstation-is": "Diese Station ist",
"track-is-being-updated": "Track wird aktualisiert...", "timestamp": "Timestamp",
"track-length-in-m": "Tracklänge (in Metern)", "token": "Token",
"track-length-must-be-greater-than-0": "Die Länge muss größer als 0 (Meter) sein", "total-distance": "gelaufene Strecke",
"track-name": "Trackname", "total-donation-amount": "Gesamtbetrag",
"track-name-must-not-be-empty": "Der Name muss angegeben werden", "total-donation-count": "Gesamte Sponsorings",
"track-was-updated": "Track wurde aktualisiert", "total-donations": "Spendensumme",
"tracks": "Tracks", "total-donors": "gesamte Sponsor:innen",
"unpaid": "Offen", "total-paid-amount": "Gezahlt",
"update-card": "Karte aktualisieren", "total-scans": "gesamte Scans",
"update-password": "Passwort ändern", "total_donation_amount_in_eur": "Gesamtbetrag in €",
"updated-contact": "Kontakt aktualisiert!", "track": "Track",
"updated-donor": "Sponsor:in wurde aktualisiert", "track-added": "Track hinzugefügt",
"updated-organization": "Organisation wurde aktualisiert", "track-data-is-being-loaded": "Trackdaten werden geladen",
"updated-scan": "Scan wurde aktualisiert", "track-is-being-added": "Track wird hinzugefügt...",
"updated-team": "Team wurde aktualisiert", "track-is-being-updated": "Track wird aktualisiert...",
"updateing-group": "Gruppe wird aktualisiert...", "track-length-in-m": "Tracklänge (in Metern)",
"updating-card": "Karte wird aktualisiert", "track-length-must-be-greater-than-0": "Die Länge muss größer als 0 (Meter) sein",
"updating-donation": "Sponsoring wird aktualisiert", "track-name": "Trackname",
"updating-organization": "Organisation wird aktualisiert", "track-name-must-not-be-empty": "Der Name muss angegeben werden",
"updating-permissions": "Berechtigungen werden aktualisiert...", "track-was-updated": "Track wurde aktualisiert",
"updating-runner": "Läufer:in wird aktualisiert.", "tracks": "Tracks",
"updating-team": "Team wird aktualisiert", "unpaid": "Offen",
"updating-user": "Benutzer:in wird aktualisiert...", "update-card": "Karte aktualisieren",
"updating-your-profile": "Profil wird aktualisiert...", "update-password": "Passwort ändern",
"user-added": "Benutzer hinzugefügt", "updated-contact": "Kontakt aktualisiert!",
"user-groups": "Benutzergruppen", "updated-donor": "Sponsor:in wurde aktualisiert",
"user-is-being-added": "Benutzer wird hinzugefügt ...", "updated-organization": "Organisation wurde aktualisiert",
"user-updated": "Benutzer:in wurde aktualisiert", "updated-scan": "Scan wurde aktualisiert",
"username": "Benutzername", "updated-team": "Team wurde aktualisiert",
"users": "Benutzer", "updateing-group": "Gruppe wird aktualisiert...",
"valid": "Gültig", "updating-card": "Karte wird aktualisiert",
"valid-city-is-required": "Du musst eine Stadt angeben", "updating-donation": "Sponsoring wird aktualisiert",
"valid-email-is-required": "Es wird eine valide E-Mail Adresse benötigt", "updating-organization": "Organisation wird aktualisiert",
"valid-international-phone-number-is-required": "Du musst eine Telefonnummer im internationalen Format angeben...", "updating-permissions": "Berechtigungen werden aktualisiert...",
"valid-zipcode-postal-code-is-required": "Du musst eine valide Postleitzahl angeben", "updating-runner": "Läufer:in wird aktualisiert.",
"verfuegbare": "Verfügbar", "updating-team": "Team wird aktualisiert",
"welcome_wavinghand": "Willkommen 👋", "updating-user": "Benutzer:in wird aktualisiert...",
"yes-i-copied-the-token": "Ja, ich habe den Token kopiert", "updating-your-profile": "Profil wird aktualisiert...",
"you-are-going-to-loose-all-permissions-and-access-to-the-runner-system": "Du wirst all deine Berechtigungen und den Zugriff aufs Läufersystem verlieren!", "user-added": "Benutzer hinzugefügt",
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "Du kannst den Betrag der Zahlung entweder manuell eingeben oder über den MAX Button auf den Spendenbetrag setzen", "user-groups": "Benutzergruppen",
"you-can-now-use-your-new-password-to-log-in-to-your-account": "Du kannst dich jetzt mit deinem neuen Passwort anmelden! 🎉", "user-is-being-added": "Benutzer wird hinzugefügt ...",
"you-can-provide-a-runner-but-you-dont-have-to": "Du kannst eine Läufer:in angeben, musst aber nicht.", "user-updated": "Benutzer:in wurde aktualisiert",
"you-dont-have-any-scanclients-yet": "Es gibt noch keine Statsclients", "username": "Benutzername",
"you-dont-have-any-scanstations-yet": "Es gibt noch keine Scannerstationen", "users": "Benutzer",
"you-have-to-provide-an-organization": "Du musst eine Organisation angeben", "valid": "Gültig",
"you-have-to-save-your-changes-to-generate-a-link": "Du musst deine Änderungen speichern, um einen Link zu generieren.", "valid-city-is-required": "Du musst eine Stadt angeben",
"you-must-create-at-least-one-card-or-cancel": "Du musst mindestens eine Blankokarte erstellen (oder abbrechen).", "valid-email-is-required": "Es wird eine valide E-Mail Adresse benötigt",
"zip-postal-code": "Postleitzahl", "valid-international-phone-number-is-required": "Du musst eine Telefonnummer im internationalen Format angeben...",
"all-associated-scans-will-get-deleted-as-well": "Alle Scans dieser Station werden ebenfalls gelöscht", "valid-zipcode-postal-code-is-required": "Du musst eine valide Postleitzahl angeben",
"confirm-delete-station-with-all-scans": "Löschen der Scannerstation mit allen Scans bestätigen", "verfuegbare": "Verfügbar",
"cancel-keep-station": "Abbrechen und Station behalten", "welcome_wavinghand": "Willkommen 👋",
"station-deleted": "Scannerstation gelöscht" "yes-i-copied-the-token": "Ja, ich habe den Token kopiert",
"you-are-going-to-loose-all-permissions-and-access-to-the-runner-system": "Du wirst all deine Berechtigungen und den Zugriff aufs Läufersystem verlieren!",
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "Du kannst den Betrag der Zahlung entweder manuell eingeben oder über den MAX Button auf den Spendenbetrag setzen",
"you-can-now-use-your-new-password-to-log-in-to-your-account": "Du kannst dich jetzt mit deinem neuen Passwort anmelden! 🎉",
"you-can-provide-a-runner-but-you-dont-have-to": "Du kannst eine Läufer:in angeben, musst aber nicht.",
"you-dont-have-any-scanclients-yet": "Es gibt noch keine Statsclients",
"you-dont-have-any-scanstations-yet": "Es gibt noch keine Scannerstationen",
"you-have-to-provide-an-organization": "Du musst eine Organisation angeben",
"you-have-to-save-your-changes-to-generate-a-link": "Du musst deine Änderungen speichern, um einen Link zu generieren.",
"you-must-create-at-least-one-card-or-cancel": "Du musst mindestens eine Blankokarte erstellen (oder abbrechen).",
"zip-postal-code": "Postleitzahl"
} }

View File

@@ -1,490 +1,500 @@
{ {
"404message": "Sorry, the page you are looking for could not be found.", "404message": "Sorry, the page you are looking for could not be found.",
"404title": "Error 404", "404title": "Error 404",
"about": "About", "about": "About",
"action": "Action", "action": "Action",
"active": "Active", "active": "Active",
"add-card": "Add Card", "add-card": "Add Card",
"add-donation": "Add donation", "add-donation": "Add donation",
"add-donor": "Add donor", "add-donor": "Add donor",
"add-or-update-a-payment": "Add or update a payment", "add-or-update-a-payment": "Add or update a payment",
"add-scan": "Add scan", "add-scan": "Add scan",
"add-the-first-scanstation": "Add your first scanstation.", "add-the-first-scanstation": "Add your first scanstation.",
"add-the-first-statsclient": "Add your first statsclient.", "add-the-first-statsclient": "Add your first statsclient.",
"add-user-group": "Add User Group", "add-user-group": "Add User Group",
"add-your-first-card": "Add your first card", "add-your-first-card": "Add your first card",
"add-your-first-contact": "Add your first contact", "add-your-first-contact": "Add your first contact",
"add-your-first-donor": "add your first donor", "add-your-first-donor": "add your first donor",
"add-your-first-group": "Add your first group", "add-your-first-group": "Add your first group",
"add-your-first-organization": "Add your first organization", "add-your-first-organization": "Add your first organization",
"add-your-first-runner": "Add your first runner", "add-your-first-runner": "Add your first runner",
"add-your-first-team": "Add your first team", "add-your-first-team": "Add your first team",
"add-your-first-track": "Add your first track.", "add-your-first-track": "Add your first track.",
"add-your-first-user": "Add your first user", "add-your-first-user": "Add your first user",
"add-your-fist-donation": "Add your fist donation", "add-your-fist-donation": "Add your fist donation",
"add-your-fist-scan": "Add your fist scan", "add-your-fist-scan": "Add your fist scan",
"adding-card": "Adding Card", "adding-card": "Adding Card",
"adding-donation": "Adding donation...", "adding-donation": "Adding donation...",
"adding-scan": "Adding Scan", "adding-scan": "Adding Scan",
"address": "Address", "address": "Address",
"address-is-required": "Address is required", "address-is-required": "Address is required",
"after-deletion-we-cant-restore-your-old-profile": "After deletion we can't restore your old profile!", "after-deletion-we-cant-restore-your-old-profile": "After deletion we can't restore your old profile!",
"after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that": "After the update you'll get logged out - Please login with your new password after that.", "after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that": "After the update you'll get logged out - Please login with your new password after that.",
"all": "all", "all": "all",
"all-associated-donations-will-get-deleted-as-well": "All associated donations will get deleted as well", "all-associated-donations-will-get-deleted-as-well": "All associated donations will get deleted as well",
"all-associated-runners-will-be-deleted-too": "All associated runners will be deleted too!", "all-associated-runners-will-be-deleted-too": "All associated runners will be deleted too!",
"all-associated-teams-and-runners-will-be-deleted-too": "All associated teams and runners will be deleted too!", "all-associated-scans-will-get-deleted-as-well": "All associated scans will get deleted as well",
"already-paid": "Already paid", "all-associated-teams-and-runners-will-be-deleted-too": "All associated teams and runners will be deleted too!",
"amount": "Amount", "already-paid": "Already paid",
"amount-per-kilometer": "Amount per kilometer", "amount": "Amount",
"apartment-suite-etc": "Apartment, suite, etc.", "amount-per-kilometer": "Amount per kilometer",
"application_name": "Lauf für Kaya! - Admin", "apartment-suite-etc": "Apartment, suite, etc.",
"applying-changes": "Applying Changes", "api-endpoint": "API-Endpoint",
"attention": "Attention!", "application_name": "Lauf für Kaya! - Admin",
"author": "Author", "applying-changes": "Applying Changes",
"bitte-bestaetige-diese-laeufer-fuer-den-import": "Please confirm these runners for import.", "attention": "Attention!",
"by": "by", "author": "Author",
"cancel": "Cancel", "average-distance": "average distance",
"cancel-delete": "Cancel Delete", "average-donation": "average donation",
"cancel-keep-donor": "Cancel, keep donor", "bitte-bestaetige-diese-laeufer-fuer-den-import": "Please confirm these runners for import.",
"cancel-keep-my-profile": "Cancel, keep my profile", "by": "by",
"cancel-keep-organization": "Cancel, keep organization", "cancel": "Cancel",
"cancel-keep-statsclient": "Cancel and keep statsclient", "cancel-delete": "Cancel Delete",
"cancel-keep-team": "Cancel, keep team", "cancel-keep-donor": "Cancel, keep donor",
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity", "cancel-keep-my-profile": "Cancel, keep my profile",
"card": "card", "cancel-keep-organization": "Cancel, keep organization",
"card-added": "Card added", "cancel-keep-station": "Cancel, keep station",
"card-deleted": "Card deleted", "cancel-keep-statsclient": "Cancel and keep statsclient",
"card-updated": "Card updated", "cancel-keep-team": "Cancel, keep team",
"cards": "Cards", "cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
"cards-deleted": "Cards deleted", "card": "card",
"certificates": "Certificates", "card-added": "Card added",
"change-your-password-here": "Change your password here", "card-deleted": "Card deleted",
"changing-your-password": "Changing your password", "card-updated": "Card updated",
"city": "City", "cards": "Cards",
"click-to-copy-the-link-into-your-clipboard": "Click to copy the link into your clipboard", "cards-deleted": "Cards deleted",
"click-to-copy-token-to-clipboard": "Click to copy the token to your clipboard", "certificates": "Certificates",
"close": "Close", "change-your-password-here": "Change your password here",
"code": "Code", "changing-your-password": "Changing your password",
"configure-the-tracks-and-minimum-lap-times": "configure the tracks & minimum lap times", "city": "City",
"confirm": "Confirm", "click-to-copy-the-link-into-your-clipboard": "Click to copy the link into your clipboard",
"confirm-delete": "Confirm Delete", "click-to-copy-token-to-clipboard": "Click to copy the token to your clipboard",
"confirm-delete-donor-with-all-donations": "Confirm, delete donor with all donations", "close": "Close",
"confirm-delete-my-user-profile": "Confirm, delete my user profile", "code": "Code",
"confirm-delete-organization-and-associated-teams-runners": "Confirm, delete organization and associated teams+runners.", "config-codes": "Config codes",
"confirm-delete-statsclient": "Confirm, delete statsclient", "configure-the-tracks-and-minimum-lap-times": "configure the tracks & minimum lap times",
"confirm-delete-team-and-associated-runners": "Confirm, delete team and associated runners.", "confirm": "Confirm",
"confirm-deletion": "Confirm Deletion", "confirm-delete": "Confirm Delete",
"confirm-the-new-password": "Confirm the new password", "confirm-delete-donor-with-all-donations": "Confirm, delete donor with all donations",
"contact": "Contact", "confirm-delete-my-user-profile": "Confirm, delete my user profile",
"contact-added": "Contact added", "confirm-delete-organization-and-associated-teams-runners": "Confirm, delete organization and associated teams+runners.",
"contact-deleted": "Contact deleted", "confirm-delete-station-with-all-scans": "Confirm deletion of station with all scans",
"contact-information": "Contact Information", "confirm-delete-statsclient": "Confirm, delete statsclient",
"contact-is-being-added": "Contact is being added...", "confirm-delete-team-and-associated-runners": "Confirm, delete team and associated runners.",
"contact-is-being-updated": "Contact is being updated...", "confirm-deletion": "Confirm Deletion",
"contact-is-not-a-member-in-any-group": "Contact is not a member in any group", "confirm-the-new-password": "Confirm the new password",
"contacts": "Contacts", "contact": "Contact",
"contacts-are-being-loaded": "contacts are being loaded...", "contact-added": "Contact added",
"copied-link-to-clipboard": "Copied link to clipboard", "contact-deleted": "Contact deleted",
"copied-token-to-clipboard": "Copied token to clipboard", "contact-information": "Contact Information",
"count_organizations": "# Organizations", "contact-is-being-added": "Contact is being added...",
"count_teams": "# Teams", "contact-is-being-updated": "Contact is being updated...",
"create": "Create", "contact-is-not-a-member-in-any-group": "Contact is not a member in any group",
"create-a-new": "Create a new", "contacts": "Contacts",
"create-a-new-card": "Create a new card", "contacts-are-being-loaded": "contacts are being loaded...",
"create-a-new-contact": "Create a new contact", "copied-link-to-clipboard": "Copied link to clipboard",
"create-a-new-distance-donation": "Create a new distance donation", "copied-token-to-clipboard": "Copied token to clipboard",
"create-a-new-donor": "Create a new donor", "count_organizations": "# Organizations",
"create-a-new-fixed-donation": "Create a new fixed donation", "count_teams": "# Teams",
"create-a-new-organization": "Create a new Organization", "create": "Create",
"create-a-new-runner": "Create a new Runner", "create-a-new": "Create a new",
"create-a-new-scan-fixed-only": "Create a new scan (fixed only)", "create-a-new-card": "Create a new card",
"create-a-new-scanstation": "Create a new station", "create-a-new-contact": "Create a new contact",
"create-a-new-statsclient": "Create a new statsclient", "create-a-new-distance-donation": "Create a new distance donation",
"create-a-new-team": "Create a new team", "create-a-new-donor": "Create a new donor",
"create-a-new-track": "Create a new Track", "create-a-new-fixed-donation": "Create a new fixed donation",
"create-a-new-user": "Create a new User", "create-a-new-organization": "Create a new Organization",
"create-a-new-user-group": "Create a new user group", "create-a-new-runner": "Create a new Runner",
"create-and-generate-pdf": "Create and generate PDF", "create-a-new-scan-fixed-only": "Create a new scan (fixed only)",
"create-bulk-blanco-cards": "Create bulk blanco cards", "create-a-new-scanstation": "Create a new station",
"create-bulk-cards": "Add blanco cards", "create-a-new-statsclient": "Create a new statsclient",
"create-organization": "Create Organization", "create-a-new-team": "Create a new team",
"create-team": "Create Team", "create-a-new-track": "Create a new Track",
"create-track": "Create Track", "create-a-new-user": "Create a new User",
"create-user": "Create User", "create-a-new-user-group": "Create a new user group",
"create-without-pdf": "Create without PDF", "create-and-generate-pdf": "Create and generate PDF",
"created-blanco-cards": "Created blanco cards", "create-bulk-blanco-cards": "Create bulk blanco cards",
"creating-blanco-cards": "Creating blanco cards", "create-bulk-cards": "Add blanco cards",
"credits": "Credits", "create-organization": "Create Organization",
"csv_import__class": "Class", "create-team": "Create Team",
"csv_import__firstname": "Firstname", "create-track": "Create Track",
"csv_import__lastname": "Lastname", "create-user": "Create User",
"csv_import__middlename": "Middlename", "create-without-pdf": "Create without PDF",
"csv_import__team": "Team", "created-blanco-cards": "Created blanco cards",
"danger-zone": "Danger zone", "creating-blanco-cards": "Creating blanco cards",
"dashboard-greeting": "Hello", "credits": "Credits",
"dashboard-title": "Dashboard", "csv_import__class": "Class",
"datatable": { "csv_import__firstname": "Firstname",
"search": "🔍 Search...", "csv_import__lastname": "Lastname",
"sort_column_ascending": "Sort column ascending", "csv_import__middlename": "Middlename",
"sort_column_descending": "Sort column descending", "csv_import__team": "Team",
"previous": "Previous", "danger-zone": "Danger zone",
"next": "Next", "dashboard-greeting": "Hello",
"page": "Page", "dashboard-title": "Dashboard",
"showing": "Showing", "datatable": {
"records": "Records", "search": "🔍 Search...",
"of": "of", "sort_column_ascending": "Sort column ascending",
"to": "to", "sort_column_descending": "Sort column descending",
"loading": "Loading...", "previous": "Previous",
"no_matching_records_found": "No matching records found", "next": "Next",
"an_error_happened_while_fetching_the_data": "An error happened while fetching the data" "page": "Page",
}, "showing": "Showing",
"delete": "Delete", "records": "Records",
"delete-cards": "Delete cards", "of": "of",
"delete-contact": "Delete Contact", "to": "to",
"delete-donation": "Delete Donation", "loading": "Loading...",
"delete-donor": "Delete donor", "no_matching_records_found": "No matching records found",
"delete-group": "Delete Group", "an_error_happened_while_fetching_the_data": "An error happened while fetching the data"
"delete-organization": "Delete Organization", },
"delete-profile": "Delete Profile", "delete": "Delete",
"delete-runner": "Delete Runner", "delete-cards": "Delete cards",
"delete-scan": "Delete scan", "delete-contact": "Delete Contact",
"delete-scans": "Delete scans", "delete-donation": "Delete Donation",
"delete-station": "Delete station", "delete-donor": "Delete donor",
"delete-statsclient": "Delete statsclient", "delete-group": "Delete Group",
"delete-team": "Delete Team", "delete-organization": "Delete Organization",
"delete-user": "Delete User", "delete-profile": "Delete Profile",
"deleted-scan": "Deleted scan", "delete-runner": "Delete Runner",
"dependency_name": "Name", "delete-scan": "Delete scan",
"description": "description", "delete-scans": "Delete scans",
"description-optional": "Description (optional)", "delete-station": "Delete station",
"deselect-all": "deselect all", "delete-statsclient": "Delete statsclient",
"details": "Details", "delete-team": "Delete Team",
"disabled": "disabled", "delete-user": "Delete User",
"distance": "Distance", "deleted-scan": "Deleted scan",
"distance-donation": "distance donation", "dependency_name": "Name",
"distance-in-km": "Distance in km", "description": "description",
"distance-track": "Distance (+Track)", "description-optional": "Description (optional)",
"do-you-really-want-to-delete-your-profile": "Do you really want to delete your profile?", "deselect-all": "deselect all",
"do-you-want-to-delete-the-organization-delete_org-name": "Do you want to delete the organization {orgname}?", "details": "Details",
"do-you-want-to-delete-the-team-delete_team-name": "Do you want to delete the team {teamname}?", "disabled": "disabled",
"do-you-want-to-delete-this-donor-with-all-related-donations": "Do you want to delete this donor with all related donations", "distance": "Distance",
"documentation": "Documentation", "distance-donation": "distance donation",
"donation-amount": "Donation amount", "distance-in-km": "Distance in km",
"donation-amount-must-be-greater-that-0-00eur": "Donation amount must be greater that 0.00€", "distance-track": "Distance (+Track)",
"donation-deleted": "Donation deleted", "do-you-really-want-to-delete-your-profile": "Do you really want to delete your profile?",
"donation-updated": "Donation updated", "do-you-want-to-delete-the-organization-delete_org-name": "Do you want to delete the organization {orgname}?",
"donation_added": "Donation_added", "do-you-want-to-delete-the-team-delete_team-name": "Do you want to delete the team {teamname}?",
"donations": "Donations", "do-you-want-to-delete-this-donor-with-all-related-donations": "Do you want to delete this donor with all related donations",
"donor": "Donor", "documentation": "Documentation",
"donor-added": "Donor added", "donation-amount": "Donation amount",
"donor-deleted": "donor deleted", "donation-amount-must-be-greater-that-0-00eur": "Donation amount must be greater that 0.00€",
"donor-has-no-associated-donations": "Donor has no associated donations.", "donation-deleted": "Donation deleted",
"donor-is-being-added": "Donor is being added...", "donation-updated": "Donation updated",
"donor-is-being-updated": "Donor is being updated", "donation_added": "Donation_added",
"donors": "Donors", "donations": "Donations",
"donors-are-being-loaded": "donors are being loaded", "donations-are-being-loaded": "donations are being loaded",
"dont-have-your-email-connected": "Don't have your email connected?", "donor": "Donor",
"dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌", "donor-added": "Donor added",
"e-mail-adress": "E-Mail Adress", "donor-deleted": "donor deleted",
"edit": "Edit", "donor-has-no-associated-donations": "No donations",
"edit-a-card": "Edit a card", "donor-is-being-added": "Donor is being added...",
"edit-permissions": "edit permissions", "donor-is-being-updated": "Donor is being updated",
"email_address_or_username": "Email / username", "donors": "Donors",
"enabled": "enabled", "donors-are-being-loaded": "donors are being loaded",
"enabled_large": "Enabled", "dont-have-your-email-connected": "Don't have your email connected?",
"english": "English", "dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌",
"enter-payment": "Enter payment", "e-mail-adress": "E-Mail Adress",
"error-during-import": "Error during import", "edit": "Edit",
"error-whyile-copying-to-clipboard": "Error while copying to clipboard", "edit-a-card": "Edit a card",
"error_on_login": "Error on login", "edit-permissions": "edit permissions",
"erteilte": "Directly granted", "email_address_or_username": "Email / username",
"everything-concerning-your-profile": "Everything concerning your profile", "enabled": "enabled",
"everything-is-more-fun-together": "everything is more fun together 🏃‍♂️🏃‍♀️🏃‍♂️", "enabled_large": "Enabled",
"faq": "FAQ", "english": "English",
"filename_sponsoringquittungsliste": "DonorReceiptList", "enter-payment": "Enter payment",
"filter-by-organization-team": "Filter by Organization/ Team", "error-during-import": "Error during import",
"first-name": "First name", "error-whyile-copying-to-clipboard": "Error while copying to clipboard",
"first-name-is-required": "First Name is required", "error_on_login": "Error on login",
"first-scan-of-the-day": "First scan of the day.", "erteilte": "Directly granted",
"fixed-donation": "fixed donation", "everything-concerning-your-profile": "Everything concerning your profile",
"forgot_password": "Forgot your password?", "everything-is-more-fun-together": "everything is more fun together 🏃‍♂️🏃‍♀️🏃‍♂️",
"geerbte": "inherited", "faq": "FAQ",
"general-stats": "General Stats", "filename_sponsoringquittungsliste": "DonorReceiptList",
"general_promise_error": "😢 Error", "filter-by-organization-team": "Filter by Organization/ Team",
"generate-runner-certificate": "Generate runner certificate", "first-name": "First name",
"generate-runner-certificates": "Generate runner certificates", "first-name-is-required": "First Name is required",
"generate-runnercards": "Generate Runnercards", "first-scan-of-the-day": "First scan of the day.",
"generate-sponsoring-contract": "generate sponsoring contract", "fixed-donation": "fixed donation",
"generate-sponsoring-contracts": "generate sponsoring contracts", "forgot_password": "Forgot your password?",
"generating-pdf": "generating PDF...", "geerbte": "inherited",
"generating-pdfs": "generating PDFs...", "general-stats": "General Stats",
"generic-ui-logic-error": "Something went wrong in the UI logic", "general_promise_error": "😢 Error",
"german": "German", "generate-runner-certificate": "Generate runner certificate",
"go-to-login": "Go To Login", "generate-runner-certificates": "Generate runner certificates",
"goback": "Go Home", "generate-runnercards": "Generate Runnercards",
"granted": "granted", "generate-sponsoring-contract": "generate sponsoring contract",
"group": "Group", "generate-sponsoring-contracts": "generate sponsoring contracts",
"group-added": "Group added", "generating-pdf": "generating PDF...",
"group-is-being-added": "Group is being added...", "generating-pdfs": "generating PDFs...",
"group-name-is-required": "Group name is required", "generic-ui-logic-error": "Something went wrong in the UI logic",
"group-updated": "group updated", "german": "German",
"groups": "Groups", "go-to-login": "Go To Login",
"groups-are-being-loaded": "Groups are being loaded", "goback": "Go Home",
"home": "Home", "granted": "granted",
"icon-image-credits": "We also want to thank these projects for illustrations and icons:", "group": "Group",
"if-you-want-to-create-multiple-blanco-cards-try-the-add-bulk-button": "If you want to create multiple blanco cards: Try the 'Add blanco cards' button.", "group-added": "Group added",
"import-finished": "Import finished", "group-is-being-added": "Group is being added...",
"import-runners": "Import runners", "group-name-is-required": "Group name is required",
"import__target-organization": "Target Organization", "group-updated": "group updated",
"imprint": "Imprint", "groups": "Groups",
"imprint-loading": "Imprint loading...", "groups-are-being-loaded": "Groups are being loaded",
"inactive": "Inactive", "home": "Home",
"installed-version": "Installed version", "icon-image-credits": "We also want to thank these projects for illustrations and icons:",
"internal-error": "Internal Error", "if-you-want-to-create-multiple-blanco-cards-try-the-add-bulk-button": "If you want to create multiple blanco cards: Try the 'Add blanco cards' button.",
"invalid": "Invalid", "import-finished": "Import finished",
"invalid-mail-reset": "the provided email is invalid", "import-runners": "Import runners",
"just-enter-how-many-you-want-and-the-system-will-create-them": "Just enter how many you want and the system will create them", "import__target-organization": "Target Organization",
"key": "Key", "imprint": "Imprint",
"laeufer-hinzufuegen": "Add runner", "imprint-loading": "Imprint loading...",
"laeufer-importieren": "Läufer importieren", "inactive": "Inactive",
"laptime": "Laptime", "installed-version": "Installed version",
"last-name": "Last name", "internal-error": "Internal Error",
"last-name-is-required": "Last Name is required", "invalid": "Invalid",
"lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.", "invalid-mail-reset": "the provided email is invalid",
"license": "License", "just-enter-how-many-you-want-and-the-system-will-create-them": "Just enter how many you want and the system will create them",
"licenses-are-being-loaded": "Licenses are being loaded...", "key": "Key",
"loading-cards": "Loading cards", "laeufer-hinzufuegen": "Add runner",
"loading-contact-details": "Loading contact details...", "laeufer-importieren": "Läufer importieren",
"loading-donation-details": "Loading donation details", "laptime": "Laptime",
"loading-donor-details": "Loading donor details", "last-name": "Last name",
"loading-group-detail": "Loading group detail...", "last-name-is-required": "Last Name is required",
"loading-profile-data": "Loading profile data", "lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.",
"loading-runners": "loading runners...", "license": "License",
"loading-station-details": "Loading station details", "licenses-are-being-loaded": "Licenses are being loaded...",
"log_in": "Log in", "loading-cards": "Loading cards",
"log_in_to_your_account": "Log in to your account", "loading-contact-details": "Loading contact details...",
"login_is_checked": "Login is being checked...", "loading-donation-details": "Loading donation details",
"logout": "Logout", "loading-donor-details": "Loading donor details",
"mail-validation-in-progress": "mail validation in progress...", "loading-group-detail": "Loading group detail...",
"manage-admin-users": "manage admin users", "loading-profile-data": "Loading profile data",
"middle-name": "Middle name", "loading-runners": "loading runners...",
"minimum-lap-time-in-s": "minimum lap time in s", "loading-station-details": "Loading station details",
"minimum-lap-time-must-be-a-positive-number-or-0": "minimum lap time must be a positive number or 0", "log_in": "Log in",
"must-be-at-least-10-characters-long": "Must be at least 10 characters long!", "log_in_to_your_account": "Log in to your account",
"must-contain-a-lowercase-letter": "Must contain a lowercase letter!", "login_is_checked": "Login is being checked...",
"must-contain-a-number": "Must contain a number!", "logout": "Logout",
"must-contain-a-uppercase-letter": "Must contain a uppercase letter!", "mail-validation-in-progress": "mail validation in progress...",
"name": "Name", "manage-admin-users": "manage admin users",
"name-is-required": "Name is required", "middle-name": "Middle name",
"new-password": "New password", "minimum-lap-time-in-s": "minimum lap time in s",
"no-contact-found": "No contacts found", "minimum-lap-time-must-be-a-positive-number-or-0": "minimum lap time must be a positive number or 0",
"no-contact-selected": "No contact selected", "must-be-at-least-10-characters-long": "Must be at least 10 characters long!",
"no-contact-specified": "no contact specified", "must-contain-a-lowercase-letter": "Must contain a lowercase letter!",
"no-donors-found": "No donors found", "must-contain-a-number": "Must contain a number!",
"no-license-text-could-be-found": "No license text could be found 😢", "must-contain-a-uppercase-letter": "Must contain a uppercase letter!",
"no-organization-or-team-found": "No organization or team found", "name": "Name",
"no-organization-specified": "no organization specified", "name-is-required": "Name is required",
"no-organizations-found": "No organizations found", "new-password": "New password",
"no-runners-found": "No runners found", "no-address": "no address",
"no-tracks-added-yet": "there are no tracks added yet.", "no-contact-found": "No contacts found",
"non-blanko": "Non/Blanko", "no-contact-selected": "No contact selected",
"open": "OPEN", "no-contact-specified": "no contact specified",
"organization": "Organization", "no-donors-found": "No donors found",
"organization-added": "Organization added", "no-license-text-could-be-found": "No license text could be found 😢",
"organization-deleted": "Organization deleted", "no-organization-or-team-found": "No organization or team found",
"organization-detail-is-being-loaded": "organization detail is being loaded...", "no-organization-specified": "no organization specified",
"organization-is-being-added": "Organization is being added...", "no-organizations-found": "No organizations found",
"organization-name-is-required": "Organization name is required", "no-runners-found": "No runners found",
"organizations": "Organizations", "no-tracks-added-yet": "there are no tracks added yet.",
"organizations-are-being-loaded": "organizations are being loaded...", "non-blanko": "Non/Blanko",
"orgs": "Organizations", "open": "OPEN",
"oss_credit_description": "We use a lot of open source software on these projects, and would like to thank the following projects and contributors who help make open source great!", "organization": "Organization",
"paid": "PAID", "organization-added": "Organization added",
"paid-amount": "Paid amount", "organization-deleted": "Organization deleted",
"password": "Password", "organization-detail-is-being-loaded": "organization detail is being loaded...",
"password-changed": "Password changed!", "organization-is-being-added": "Organization is being added...",
"password-is-required": "Password is required", "organization-name-is-required": "Organization name is required",
"password-reset-failed": "Password reset failed!", "organizations": "Organizations",
"password-reset-in-progress": "Password Reset in Progress...", "organizations-are-being-loaded": "organizations are being loaded...",
"password-reset-mail-sent": "Password reset mail was sent to \"{usersEmail}\".", "orgs": "Organizations",
"password-reset-successful": "Password Reset successful!", "oss_credit_description": "We use a lot of open source software on these projects, and would like to thank the following projects and contributors who help make open source great!",
"passwords-dont-match": "Passwords don't match!", "paid": "PAID",
"payment-amount-must-be-greater-than-0-00eur": "Payment amount must be greater than 0.00€!", "paid-amount": "Paid amount",
"pdf-generation-failed": "PDF generation failed!", "password": "Password",
"pdf-successfully-generated": "PDF successfully generated!", "password-changed": "Password changed!",
"pdfs-successfully-generated": "PDFs successfully generated!", "password-is-required": "Password is required",
"per-kilometer": "per Kilometer", "password-reset-failed": "Password reset failed!",
"permissions": "Permissions", "password-reset-in-progress": "Password Reset in Progress...",
"permissions-updated": "Permissions updated!", "password-reset-mail-sent": "Password reset mail was sent to \"{usersEmail}\".",
"phone": "Phone", "password-reset-successful": "Password Reset successful!",
"please-confirm-the-deletion-of-card": "Please confirm the deletion of this card", "passwords-dont-match": "Passwords don't match!",
"please-confirm-the-deletion-of-runner": "Please confirm the deletion of this runner", "payment-amount-must-be-greater-than-0-00eur": "Payment amount must be greater than 0.00€!",
"please-confirm-the-deletion-of-scan": "Please confirm the deletion of scan", "pdf-generation-failed": "PDF generation failed!",
"please-copy-the-token-and-store-it-somewhere-save": "Please copy the token and store it somewhere safe.", "pdf-successfully-generated": "PDF successfully generated!",
"please-provide-a-password": "Please provide a password...", "pdfs-successfully-generated": "PDFs successfully generated!",
"please-provide-the-nessecary-information-to-add-a-new-donor": "Please provide the nessecary information to add a new donor", "per-kilometer": "per Kilometer",
"please-provide-the-nessecary-information-to-create-a-new-donation": "Please provide the nessecary information to create a new donation", "permissions": "Permissions",
"please-provide-the-nessecary-information-to-create-a-new-scan": "Please provide the nessecary information to create a new scan.", "permissions-updated": "Permissions updated!",
"please-provide-the-required-csv-xlsx-file": "Please provide the required csv/ xlsx file", "phone": "Phone",
"please-provide-the-required-information-for-creating-a-new-user-group": "Please provide the required information for creating a new user group.", "please-confirm-the-deletion-of-card": "Please confirm the deletion of this card",
"please-provide-the-required-information-to-add-a-new-contact": "Please provide the required information to add a new contact.", "please-confirm-the-deletion-of-donation": "Please confirm the deletion of this donation",
"please-provide-the-required-information-to-add-a-new-organization": "Please provide the required information to add a new organization.", "please-confirm-the-deletion-of-runner": "Please confirm the deletion of this runner",
"please-provide-the-required-information-to-add-a-new-runner": "Please provide the required information to add a new runner.", "please-confirm-the-deletion-of-scan": "Please confirm the deletion of scan",
"please-provide-the-required-information-to-add-a-new-team": "Please provide the required information to add a new team.", "please-copy-the-token-and-store-it-somewhere-save": "Please copy the token and store it somewhere safe.",
"please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.", "please-provide-a-password": "Please provide a password...",
"please-provide-the-required-information-to-add-a-new-user": "Please provide the required information to add a new user.", "please-provide-the-nessecary-information-to-add-a-new-donor": "Please provide the nessecary information to add a new donor",
"please-provide-the-required-information-to-create-a-new-scanstation": "Please provide the required information to create a new scanstation", "please-provide-the-nessecary-information-to-create-a-new-donation": "Please provide the nessecary information to create a new donation",
"please-provide-the-required-information-to-create-a-new-statsclient": "Please provide the required information to create a new statsclient", "please-provide-the-nessecary-information-to-create-a-new-scan": "Please provide the nessecary information to create a new scan.",
"please-request-a-new-reset-mail": "Please request a new reset mail...", "please-provide-the-required-csv-xlsx-file": "Please provide the required csv/ xlsx file",
"please-wait-a-moment-your-login-is-still-being-processed": "Please wait a moment, your login is still being processed", "please-provide-the-required-information-for-creating-a-new-user-group": "Please provide the required information for creating a new user group.",
"prefix": "Prefix", "please-provide-the-required-information-to-add-a-new-contact": "Please provide the required information to add a new contact.",
"privacy": "Privacy", "please-provide-the-required-information-to-add-a-new-organization": "Please provide the required information to add a new organization.",
"privacy-loading": "Privacy loading...", "please-provide-the-required-information-to-add-a-new-runner": "Please provide the required information to add a new runner.",
"profile": "Profile", "please-provide-the-required-information-to-add-a-new-team": "Please provide the required information to add a new team.",
"profile-deleted": "Profile deleted!", "please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.",
"profile-picture": "Profile Picture", "please-provide-the-required-information-to-add-a-new-user": "Please provide the required information to add a new user.",
"profile-updated": "Profile updated!", "please-provide-the-required-information-to-create-a-new-scanstation": "Please provide the required information to create a new scanstation",
"read-license": "Read License", "please-provide-the-required-information-to-create-a-new-statsclient": "Please provide the required information to create a new statsclient",
"receipt-needed": "Receipt needed", "please-request-a-new-reset-mail": "Please request a new reset mail...",
"repo_link": "Link", "please-wait-a-moment-your-login-is-still-being-processed": "Please wait a moment, your login is still being processed",
"request-a-new-reset-mail": "Request a new reset mail", "prefix": "Prefix",
"reset-my-password": "Reset my password", "privacy": "Privacy",
"reset-password": "Reset your password", "privacy-loading": "Privacy loading...",
"runner": "Runner", "profile": "Profile",
"runner-added": "Runner added", "profile-deleted": "Profile deleted!",
"runner-deleted": "runner deleted", "profile-picture": "Profile Picture",
"runner-import": "Runner Import", "profile-updated": "Profile updated!",
"runner-is-being-added": "Runner is being added...", "read-license": "Read License",
"runner-updated": "Runner updated!", "receipt-needed": "Receipt needed",
"runnercards": "Runnercards", "repo_link": "Link",
"runnerimport_verify_runners_org": "Please confirm these runners for import into the organization \"{org_name}\"", "request-a-new-reset-mail": "Request a new reset mail",
"runners": "Runners", "reset-my-password": "Reset my password",
"runners-are-being-imported": "Runners are being imported...", "reset-password": "Reset your password",
"runners-are-being-loaded": "runners are being loaded...", "runner": "Runner",
"save": "Save", "runner-added": "Runner added",
"save-changes": "Save Changes", "runner-deleted": "runner deleted",
"scan-added": "Scan added", "runner-import": "Runner Import",
"scan-deleted": "scan deleted", "runner-is-being-added": "Runner is being added...",
"scan-is-being-updated": "Scan is being updated", "runner-updated": "Runner updated!",
"scan-with-fixed-distance": "Scan with fixed distance", "runnercards": "Runnercards",
"scans": "Scans", "runnerimport_verify_runners_org": "Please confirm these runners for import into the organization \"{org_name}\"",
"scans-are-being-loaded": "Scans are being loaded", "runners": "Runners",
"scanstation": "Scanstation", "runners-are-being-imported": "Runners are being imported...",
"scanstation-added": "Scanstation added", "runners-are-being-loaded": "runners are being loaded...",
"scanstation-is-being-added": "Adding scanstation...", "save": "Save",
"scanstations": "Scanstations", "save-changes": "Save Changes",
"scanstations-are-being-loaded": "Loading scanstations...", "scan-added": "Scan added",
"search-for-an-organization-by-name-or-id": "Search for an organization (by name or id)", "scan-deleted": "scan deleted",
"search-for-an-organization-or-team-by-name-or-id": "Search for an organization or team (by name or id)", "scan-is-being-updated": "Scan is being updated",
"search-for-donor-name-or-id": "Search for donor (by name or id)", "scan-with-fixed-distance": "Scan with fixed distance",
"search-for-permission": "Search for permission", "scans": "Scans",
"search-for-runner-by-name-or-id": "Search for runner (by name or id)", "scans-are-being-loaded": "Scans are being loaded",
"select-all": "select all", "scanstation": "Scanstation",
"select-language": "Select language", "scanstation-added": "Scanstation added",
"selfservice-registration": "Selfservice registration", "scanstation-is-being-added": "Adding scanstation...",
"send-a-mail-to-lfk-odit-services": "send a mail to lfk@odit.services", "scanstations": "Scanstations",
"set-the-user-active-inactive": "set the user active/ inactive", "scanstations-are-being-loaded": "Loading scanstations...",
"settings": "Settings", "search-for-an-organization-by-name-or-id": "Search for an organization (by name or id)",
"settings-for-your-profile": "Settings for your profile", "search-for-an-organization-or-team-by-name-or-id": "Search for an organization or team (by name or id)",
"something-about-the-group": "Something about the group...", "search-for-donor-name-or-id": "Search for donor (by name or id)",
"sponsoring-quittungs-liste_herunterladen": "Download donor receipt list", "search-for-permission": "Search for permission",
"sponsorings": "Sponsorings", "search-for-runner-by-name-or-id": "Search for runner (by name or id)",
"stats-are-being-loaded": "stats are being loaded...", "select-all": "select all",
"statsclient-deleted": "Deleted statsclient", "select-language": "Select language",
"statsclient-is-being-added": "Statsclient is being added...", "selfservice-registration": "Selfservice registration",
"statsclients": "Statsclients (aka Beamershow)", "send-a-mail-to-lfk-odit-services": "send a mail to lfk@odit.services",
"statsclients-are-being-loaded": "Loading statsclients", "set-the-user-active-inactive": "set the user active/ inactive",
"status": "Status", "settings": "Settings",
"stuff-that-could-harm-your-profile": "Stuff that could harm your profile", "settings-for-your-profile": "Settings for your profile",
"successful-password-reset": "Successful password reset!", "something-about-the-group": "Something about the group...",
"team": "Team", "sponsoring-quittungs-liste_herunterladen": "Download donor receipt list",
"team-added": "Team added", "sponsorings": "Sponsorings",
"team-deleted": "Team deleted", "station-deleted": "station deleted",
"team-detail-is-being-loaded": "team detail is being loaded...", "stats-are-being-loaded": "stats are being loaded...",
"team-is-being-added": "Team is being added...", "statsclient-deleted": "Deleted statsclient",
"team-name": "Team name", "statsclient-is-being-added": "Statsclient is being added...",
"team-name-is-required": "team name is required", "statsclients": "Statsclients (aka Beamershow)",
"teams": "Teams", "statsclients-are-being-loaded": "Loading statsclients",
"teams-are-being-loaded": "teams are being loaded...", "status": "Status",
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "the provided phone number is invalid.<br />please enter a valid international number...", "stuff-that-could-harm-your-profile": "Stuff that could harm your profile",
"the-scans-distance-must-be-greater-than-0m": "The scan's distance must be greater than 0m", "successful-password-reset": "Successful password reset!",
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The scanstation api token will only get displayed once - you won't be able to change or view it again!", "team": "Team",
"the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The statsclient api token will only get displayed once - you won't be able to change or view it again!", "team-added": "Team added",
"there-are-no-cards-yet": "There are no cards yet.", "team-deleted": "Team deleted",
"there-are-no-contacts-added-yet": "There are no contacts added yet.", "team-detail-is-being-loaded": "team detail is being loaded...",
"there-are-no-donations-yet": "There are no donations yet", "team-is-being-added": "Team is being added...",
"there-are-no-donors-yet": "There are no donors yet", "team-name": "Team name",
"there-are-no-groups-yet": "There are no groups yet", "team-name-is-required": "team name is required",
"there-are-no-organizations-added-yet": "There are no organizations added yet.", "teams": "Teams",
"there-are-no-runners-added-yet": "There are no runners added yet.", "teams-are-being-loaded": "teams are being loaded...",
"there-are-no-scans-yet": "There are no scans yet", "the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "the provided phone number is invalid.<br />please enter a valid international number...",
"there-are-no-teams-added-yet": "There are no teams added yet.", "the-scans-distance-must-be-greater-than-0m": "The scan's distance must be greater than 0m",
"there-are-no-users-added-yet": "There are no users added yet.", "the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The scanstation api token will only get displayed once - you won't be able to change or view it again!",
"this-card-is": "This card is", "the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The statsclient api token will only get displayed once - you won't be able to change or view it again!",
"this-might-take-a-moment": "This might take a moment 👀", "there-are-no-cards-yet": "There are no cards yet.",
"this-scanstation-is": "This scanstation is", "there-are-no-contacts-added-yet": "There are no contacts added yet.",
"token": "Token", "there-are-no-donations-yet": "There are no donations yet",
"total-distance": "total distance", "there-are-no-donors-yet": "There are no donors yet",
"total-donation-amount": "total donation amount", "there-are-no-groups-yet": "There are no groups yet",
"total-donations": "total donations", "there-are-no-organizations-added-yet": "There are no organizations added yet.",
"total-paid-amount": "Total paid amount", "there-are-no-runners-added-yet": "There are no runners added yet.",
"total-scans": "total scans", "there-are-no-scans-yet": "There are no scans yet",
"total_donation_amount_in_eur": "Total donation amount in €", "there-are-no-teams-added-yet": "There are no teams added yet.",
"track": "Track", "there-are-no-users-added-yet": "There are no users added yet.",
"track-added": "Track added", "this-card-is": "This card is",
"track-data-is-being-loaded": "Track data is being loaded", "this-might-take-a-moment": "This might take a moment 👀",
"track-is-being-added": "Track is being added...", "this-scanstation-is": "This scanstation is",
"track-is-being-updated": "Track is being updated...", "timestamp": "timestamp",
"track-length-in-m": "Track Length in m", "token": "Token",
"track-length-must-be-greater-than-0": "Track length must be greater than 0", "total-distance": "total distance",
"track-name": "Track name", "total-donation-amount": "total donation amount",
"track-name-must-not-be-empty": "Track name must not be empty", "total-donation-count": "total donations (count)",
"track-was-updated": "Track was updated!", "total-donations": "total donations",
"tracks": "Tracks", "total-donors": "total donors",
"unpaid": "Unpaid", "total-paid-amount": "Paid",
"update-card": "Update Card", "total-scans": "total scans",
"update-password": "Update password", "total_donation_amount_in_eur": "Total donation amount in €",
"updated-contact": "Updated contact!", "track": "Track",
"updated-donor": "updated donor", "track-added": "Track added",
"updated-organization": "updated organization", "track-data-is-being-loaded": "Track data is being loaded",
"updated-scan": "updated scan", "track-is-being-added": "Track is being added...",
"updated-team": "Updated team", "track-is-being-updated": "Track is being updated...",
"updateing-group": "updateing group...", "track-length-in-m": "Track Length in m",
"updating-card": "Updating card", "track-length-must-be-greater-than-0": "Track length must be greater than 0",
"updating-donation": "Updating donation", "track-name": "Track name",
"updating-organization": "updating organization", "track-name-must-not-be-empty": "Track name must not be empty",
"updating-permissions": "updating permissions...", "track-was-updated": "Track was updated!",
"updating-runner": "Updating runner...", "tracks": "Tracks",
"updating-team": "Updating team", "unpaid": "Unpaid",
"updating-user": "updating user...", "update-card": "Update Card",
"updating-your-profile": "Updating your profile...", "update-password": "Update password",
"user-added": "User added", "updated-contact": "Updated contact!",
"user-groups": "User Groups", "updated-donor": "updated donor",
"user-is-being-added": "User is being added...", "updated-organization": "updated organization",
"user-updated": "User updated", "updated-scan": "updated scan",
"username": "Username", "updated-team": "Updated team",
"users": "Users", "updateing-group": "updateing group...",
"valid": "Valid", "updating-card": "Updating card",
"valid-city-is-required": "Valid city is required", "updating-donation": "Updating donation",
"valid-email-is-required": "valid email is required", "updating-organization": "updating organization",
"valid-international-phone-number-is-required": "valid international phone number is required...", "updating-permissions": "updating permissions...",
"valid-zipcode-postal-code-is-required": "Valid zipcode/ postal code is required", "updating-runner": "Updating runner...",
"verfuegbare": "availdable", "updating-team": "Updating team",
"welcome_wavinghand": "Welcome 👋", "updating-user": "updating user...",
"yes-i-copied-the-token": "Yes, I copied the token", "updating-your-profile": "Updating your profile...",
"you-are-going-to-loose-all-permissions-and-access-to-the-runner-system": "You are going to loose all permissions and access to the runner system!", "user-added": "User added",
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "You can enter the donation's paid amount manually or use the MAX button to use the donation's exact amount.", "user-groups": "User Groups",
"you-can-now-use-your-new-password-to-log-in-to-your-account": "You can now use your new password to log in to your account! 🎉", "user-is-being-added": "User is being added...",
"you-can-provide-a-runner-but-you-dont-have-to": "You can provide a runner, but you don't have to.", "user-updated": "User updated",
"you-dont-have-any-scanclients-yet": "You don't have any statsclients yet", "username": "Username",
"you-dont-have-any-scanstations-yet": "You don't have any scanstations yet", "users": "Users",
"you-have-to-provide-an-organization": "You have to provide an organization", "valid": "Valid",
"you-have-to-save-your-changes-to-generate-a-link": "You have to save your changes to generate a link.", "valid-city-is-required": "Valid city is required",
"you-must-create-at-least-one-card-or-cancel": "You must create at least one card (or cancel).", "valid-email-is-required": "valid email is required",
"zip-postal-code": "ZIP/ postal code", "valid-international-phone-number-is-required": "valid international phone number is required...",
"all-associated-scans-will-get-deleted-as-well": "All associated scans will get deleted as well", "valid-zipcode-postal-code-is-required": "Valid zipcode/ postal code is required",
"confirm-delete-station-with-all-scans": "Confirm deletion of station with all scans", "verfuegbare": "availdable",
"cancel-keep-station": "Cancel, keep station", "welcome_wavinghand": "Welcome 👋",
"station-deleted": "station deleted" "yes-i-copied-the-token": "Yes, I copied the token",
"you-are-going-to-loose-all-permissions-and-access-to-the-runner-system": "You are going to loose all permissions and access to the runner system!",
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "You can enter the donation's paid amount manually or use the MAX button to use the donation's exact amount.",
"you-can-now-use-your-new-password-to-log-in-to-your-account": "You can now use your new password to log in to your account! 🎉",
"you-can-provide-a-runner-but-you-dont-have-to": "You can provide a runner, but you don't have to.",
"you-dont-have-any-scanclients-yet": "You don't have any statsclients yet",
"you-dont-have-any-scanstations-yet": "You don't have any scanstations yet",
"you-have-to-provide-an-organization": "You have to provide an organization",
"you-have-to-save-your-changes-to-generate-a-link": "You have to save your changes to generate a link.",
"you-must-create-at-least-one-card-or-cancel": "You must create at least one card (or cancel).",
"zip-postal-code": "ZIP/ postal code"
} }