Compare commits
	
		
			35 Commits
		
	
	
		
			2139b197ba
			...
			dev
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						878d3acc9c
	
				 | 
					
					
						|||
| 
						
						
							
						
						5a7bc239d2
	
				 | 
					
					
						|||
| 
						
						
							
						
						661a698fba
	
				 | 
					
					
						|||
| 
						
						
							
						
						1b088b87bf
	
				 | 
					
					
						|||
| 
						
						
							
						
						d5fecd3f31
	
				 | 
					
					
						|||
| 
						
						
							
						
						e9938a5472
	
				 | 
					
					
						|||
| 
						
						
							
						
						77413c7e53
	
				 | 
					
					
						|||
| 
						
						
							
						
						72e5425c08
	
				 | 
					
					
						|||
| 
						
						
							
						
						53f5fa3988
	
				 | 
					
					
						|||
| 
						
						
							
						
						6ef6dc0078
	
				 | 
					
					
						|||
| 
						
						
							
						
						b89d4f248c
	
				 | 
					
					
						|||
| 
						
						
							
						
						e2a1c9a508
	
				 | 
					
					
						|||
| 
						
						
							
						
						444b1f5370
	
				 | 
					
					
						|||
| 
						
						
							
						
						06d22c929f
	
				 | 
					
					
						|||
| 
						
						
							
						
						650083965a
	
				 | 
					
					
						|||
| 
						
						
							
						
						3709881176
	
				 | 
					
					
						|||
| 
						
						
							
						
						a00af08b3f
	
				 | 
					
					
						|||
| 
						
						
							
						
						9ef34359d8
	
				 | 
					
					
						|||
| 
						
						
							
						
						4d79589903
	
				 | 
					
					
						|||
| 
						
						
							
						
						bbf659e52d
	
				 | 
					
					
						|||
| 
						
						
							
						
						1386b80d0c
	
				 | 
					
					
						|||
| 
						
						
							
						
						30a26ef3ed
	
				 | 
					
					
						|||
| 
						
						
							
						
						ca066aa7a7
	
				 | 
					
					
						|||
| 
						
						
							
						
						7d9314f05c
	
				 | 
					
					
						|||
| 
						
						
							
						
						286bd61497
	
				 | 
					
					
						|||
| 
						
						
							
						
						50b5e4e455
	
				 | 
					
					
						|||
| 
						
						
							
						
						2c91f46375
	
				 | 
					
					
						|||
| 
						
						
							
						
						0cb1193269
	
				 | 
					
					
						|||
| 
						
						
							
						
						564a971c63
	
				 | 
					
					
						|||
| 
						
						
							
						
						3842d8b104
	
				 | 
					
					
						|||
| 
						
						
							
						
						a827279163
	
				 | 
					
					
						|||
| 
						
						
							
						
						b0063cdead
	
				 | 
					
					
						|||
| 
						
						
							
						
						9298a0dc92
	
				 | 
					
					
						|||
| 
						
						
							
						
						b9e2e65331
	
				 | 
					
					
						|||
| 
						
						
							
						
						27e7bbb9d1
	
				 | 
					
					
						
							
								
								
									
										59
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -2,8 +2,67 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
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.14.2](https://git.odit.services/lfk/frontend/compare/1.14.1...1.14.2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- feat(GenerateRunnerCertificates): support skipping runners without scans [`5a7bc23`](https://git.odit.services/lfk/frontend/commit/5a7bc239d2f93ced9ebdc5b113fe27d0d8d3899c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [1.14.1](https://git.odit.services/lfk/frontend/compare/1.14.0...1.14.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 26 May 2025
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- fix: ensure numeric values are parsed as integers in DocumentServer methods [`1b088b8`](https://git.odit.services/lfk/frontend/commit/1b088b87bf6e67796c2509d9c21f21833cb4df0f)
 | 
				
			||||||
 | 
					- chore(release): 1.14.1 [`661a698`](https://git.odit.services/lfk/frontend/commit/661a698fbaeb2432bec758ed632a520676ae86b2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [1.14.0](https://git.odit.services/lfk/frontend/compare/1.13.5...1.14.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 20 May 2025
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- wip [`564a971`](https://git.odit.services/lfk/frontend/commit/564a971c63403af2e2eb550db814519576d62023)
 | 
				
			||||||
 | 
					- wip [`50b5e4e`](https://git.odit.services/lfk/frontend/commit/50b5e4e455ce705fc5ef7f3d069d88c9ff48a6af)
 | 
				
			||||||
 | 
					- wip [`2c91f46`](https://git.odit.services/lfk/frontend/commit/2c91f463758c8452561fbcc5dad8412edba8915d)
 | 
				
			||||||
 | 
					- wip [`1386b80`](https://git.odit.services/lfk/frontend/commit/1386b80d0c8569cf127f8235b3dd249c2775594a)
 | 
				
			||||||
 | 
					- wip [`6ef6dc0`](https://git.odit.services/lfk/frontend/commit/6ef6dc007837c237273a29ca489ef0cdb92f7c6c)
 | 
				
			||||||
 | 
					- wip [`3709881`](https://git.odit.services/lfk/frontend/commit/370988117683ab1fdc149a30f920cc6a66575c7a)
 | 
				
			||||||
 | 
					- chore(release): 1.14.0 [`d5fecd3`](https://git.odit.services/lfk/frontend/commit/d5fecd3f31916b80c305d76f37c4600f1d242eba)
 | 
				
			||||||
 | 
					- wip [`77413c7`](https://git.odit.services/lfk/frontend/commit/77413c7e5350a1d8643d2baf135b531235f78e64)
 | 
				
			||||||
 | 
					- wip [`0cb1193`](https://git.odit.services/lfk/frontend/commit/0cb1193269912b047abfacb6012463093c2adcfa)
 | 
				
			||||||
 | 
					- wip [`9ef3435`](https://git.odit.services/lfk/frontend/commit/9ef34359d8ac32674c28825b91b6aa2877e63552)
 | 
				
			||||||
 | 
					- wip [`a00af08`](https://git.odit.services/lfk/frontend/commit/a00af08b3f7c8278cfc54af6f593a9dcf4509ab4)
 | 
				
			||||||
 | 
					- wip [`286bd61`](https://git.odit.services/lfk/frontend/commit/286bd614976dcf8bcb14cffd092f23ef65393917)
 | 
				
			||||||
 | 
					- wip [`b89d4f2`](https://git.odit.services/lfk/frontend/commit/b89d4f248c5575548d77336832c64dc6e395efc3)
 | 
				
			||||||
 | 
					- inputElementID param [`4d79589`](https://git.odit.services/lfk/frontend/commit/4d79589903bb0726f6bcb2c0e5089a9e20f7db17)
 | 
				
			||||||
 | 
					- wip [`53f5fa3`](https://git.odit.services/lfk/frontend/commit/53f5fa3988e81215e17e41b7dd92e9ddf897610a)
 | 
				
			||||||
 | 
					- wip [`444b1f5`](https://git.odit.services/lfk/frontend/commit/444b1f537016b303a57fcaaac4468a749fe4f33c)
 | 
				
			||||||
 | 
					- disable autocomplete [`72e5425`](https://git.odit.services/lfk/frontend/commit/72e5425c0847102b0ed3f88abe17dc22ccea0a30)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [1.13.5](https://git.odit.services/lfk/frontend/compare/1.13.4...1.13.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 20 May 2025
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- add missing cursor-pointer [`6500839`](https://git.odit.services/lfk/frontend/commit/650083965a35cf3b05b6b67389ff8035dc5fa3fa)
 | 
				
			||||||
 | 
					- refactor(DonationsOverview): drop checkboxes - they dont do anything [`06d22c9`](https://git.odit.services/lfk/frontend/commit/06d22c929f94587d9bdbcb4abfc0a770cf94a771)
 | 
				
			||||||
 | 
					- chore(release): 1.13.5 [`e2a1c9a`](https://git.odit.services/lfk/frontend/commit/e2a1c9a508c6061e55438afefcd641e3d9423aaa)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [1.13.4](https://git.odit.services/lfk/frontend/compare/1.13.3...1.13.4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 20 May 2025
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- feat(donationcreate): improved focus handling [`a827279`](https://git.odit.services/lfk/frontend/commit/a82727916345c7e713d4225c4771ef3f23d1392c)
 | 
				
			||||||
 | 
					- chore(release): 1.13.4 [`bbf659e`](https://git.odit.services/lfk/frontend/commit/bbf659e52d249732fadb659fdbd24a89d2e8ec42)
 | 
				
			||||||
 | 
					- chore(deps): remove unused [`3842d8b`](https://git.odit.services/lfk/frontend/commit/3842d8b1048ce12f0f70bf3d0530590470f0d200)
 | 
				
			||||||
 | 
					- fix(donationcreate): clearing [`9298a0d`](https://git.odit.services/lfk/frontend/commit/9298a0dc922ee5ed5b7c9017c865ad4b68fca3c8)
 | 
				
			||||||
 | 
					- feat(donationcreate): autofocus runner input on page load [`b9e2e65`](https://git.odit.services/lfk/frontend/commit/b9e2e653310c686bc06b9f27c38b49e9c6a3eaef)
 | 
				
			||||||
 | 
					- fix(DonationCreate): remove duplicate spaces from getRunnerLabel [`30a26ef`](https://git.odit.services/lfk/frontend/commit/30a26ef3ed55d072cd9bf2aea1b200fadc2a05f1)
 | 
				
			||||||
 | 
					- fix(donationcreate): improved resetAll [`7d9314f`](https://git.odit.services/lfk/frontend/commit/7d9314f05c58c1b50901f3797c0b461c4c79e5d2)
 | 
				
			||||||
 | 
					- fix(DeleteDonationModal): cannot overflow [`ca066aa`](https://git.odit.services/lfk/frontend/commit/ca066aa7a7a8d7c46e0f59370b06636faf5736ca)
 | 
				
			||||||
 | 
					- feat(donationcreate): full width [`b0063cd`](https://git.odit.services/lfk/frontend/commit/b0063cdead5f71c334c36e5587a58e957825dbcd)
 | 
				
			||||||
 | 
					- feat(donationcreate): add runner id to select [`27e7bbb`](https://git.odit.services/lfk/frontend/commit/27e7bbb9d142fbea659e89fb2335cc6c567d14ce)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### [1.13.3](https://git.odit.services/lfk/frontend/compare/1.13.2...1.13.3)
 | 
					#### [1.13.3](https://git.odit.services/lfk/frontend/compare/1.13.2...1.13.3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 19 May 2025
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- chore(release): 1.13.3 [`2139b19`](https://git.odit.services/lfk/frontend/commit/2139b197ba672275e2a0b5ffbcf7fa43f80874e6)
 | 
				
			||||||
- Refactor code structure for improved readability and maintainability [`e3c6d5a`](https://git.odit.services/lfk/frontend/commit/e3c6d5a5c0eaac2c91432b0be37d6fa11e57f644)
 | 
					- Refactor code structure for improved readability and maintainability [`e3c6d5a`](https://git.odit.services/lfk/frontend/commit/e3c6d5a5c0eaac2c91432b0be37d6fa11e57f644)
 | 
				
			||||||
- refactor(donation): Refactor donor selection and add new donor creation functionality [`8c3f009`](https://git.odit.services/lfk/frontend/commit/8c3f0092d2735b1c85976f4e6955780b1035f68a)
 | 
					- refactor(donation): Refactor donor selection and add new donor creation functionality [`8c3f009`](https://git.odit.services/lfk/frontend/commit/8c3f0092d2735b1c85976f4e6955780b1035f68a)
 | 
				
			||||||
- fix(donation): Ensure all selections are cleared on reset [`4e1a944`](https://git.odit.services/lfk/frontend/commit/4e1a944a2d7d0d0666fb8d2181a9941d0f11957f)
 | 
					- fix(donation): Ensure all selections are cleared on reset [`4e1a944`](https://git.odit.services/lfk/frontend/commit/4e1a944a2d7d0d0666fb8d2181a9941d0f11957f)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <span style="display: none; visibility: hidden" id="buildinfo"
 | 
					    <span style="display: none; visibility: hidden" id="buildinfo"
 | 
				
			||||||
      >RELEASE_INFO-1.13.3-RELEASE_INFO</span
 | 
					      >RELEASE_INFO-1.14.2-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>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "@odit/lfk-frontend",
 | 
					  "name": "@odit/lfk-frontend",
 | 
				
			||||||
  "version": "1.13.3",
 | 
					  "version": "1.14.2",
 | 
				
			||||||
  "type": "module",
 | 
					  "type": "module",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "i18n-order": "node order.js",
 | 
					    "i18n-order": "node order.js",
 | 
				
			||||||
@@ -52,7 +52,6 @@
 | 
				
			|||||||
    "html5-qrcode": "^2.3.8",
 | 
					    "html5-qrcode": "^2.3.8",
 | 
				
			||||||
    "localforage": "1.10.0",
 | 
					    "localforage": "1.10.0",
 | 
				
			||||||
    "papaparse": "^5.5.2",
 | 
					    "papaparse": "^5.5.2",
 | 
				
			||||||
    "svelecte": "3",
 | 
					 | 
				
			||||||
    "svelte": "3.58.0",
 | 
					    "svelte": "3.58.0",
 | 
				
			||||||
    "svelte-french-toast": "1.2.0",
 | 
					    "svelte-french-toast": "1.2.0",
 | 
				
			||||||
    "svelte-i18n": "4.0.1",
 | 
					    "svelte-i18n": "4.0.1",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										15
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@@ -38,9 +38,6 @@ importers:
 | 
				
			|||||||
      papaparse:
 | 
					      papaparse:
 | 
				
			||||||
        specifier: ^5.5.2
 | 
					        specifier: ^5.5.2
 | 
				
			||||||
        version: 5.5.2
 | 
					        version: 5.5.2
 | 
				
			||||||
      svelecte:
 | 
					 | 
				
			||||||
        specifier: '3'
 | 
					 | 
				
			||||||
        version: 3.17.3
 | 
					 | 
				
			||||||
      svelte:
 | 
					      svelte:
 | 
				
			||||||
        specifier: 3.58.0
 | 
					        specifier: 3.58.0
 | 
				
			||||||
        version: 3.58.0
 | 
					        version: 3.58.0
 | 
				
			||||||
@@ -1986,9 +1983,6 @@ packages:
 | 
				
			|||||||
    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
 | 
					    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
 | 
				
			||||||
    engines: {node: '>= 0.4'}
 | 
					    engines: {node: '>= 0.4'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  svelecte@3.17.3:
 | 
					 | 
				
			||||||
    resolution: {integrity: sha512-wnvoRxJIFFkm+CmXgjL4R3i/TcuYUIBkE+jDJSBD7AdSOzk1K6u3+nW4zwxaGT29zyZpiZkWeiy7lO62r5F+tg==}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  svelte-french-toast@1.2.0:
 | 
					  svelte-french-toast@1.2.0:
 | 
				
			||||||
    resolution: {integrity: sha512-5PW+6RFX3xQPbR44CngYAP1Sd9oCq9P2FOox4FZffzJuZI2mHOB7q5gJBVnOiLF5y3moVGZ7u2bYt7+yPAgcEQ==}
 | 
					    resolution: {integrity: sha512-5PW+6RFX3xQPbR44CngYAP1Sd9oCq9P2FOox4FZffzJuZI2mHOB7q5gJBVnOiLF5y3moVGZ7u2bYt7+yPAgcEQ==}
 | 
				
			||||||
    peerDependencies:
 | 
					    peerDependencies:
 | 
				
			||||||
@@ -2010,9 +2004,6 @@ packages:
 | 
				
			|||||||
  svelte-select@3.17.0:
 | 
					  svelte-select@3.17.0:
 | 
				
			||||||
    resolution: {integrity: sha512-ITmX/XUiSdkaILmsTviKRkZPaXckM5/FA7Y8BhiUPoamaZG/ZDyOo6ydjFu9fDVFTbwoAUGUi6HBjs+ZdK2AwA==}
 | 
					    resolution: {integrity: sha512-ITmX/XUiSdkaILmsTviKRkZPaXckM5/FA7Y8BhiUPoamaZG/ZDyOo6ydjFu9fDVFTbwoAUGUi6HBjs+ZdK2AwA==}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  svelte-tiny-virtual-list@2.1.2:
 | 
					 | 
				
			||||||
    resolution: {integrity: sha512-jeP/WMvgFUR4mYXHGPiCexjX5DuzSO+3xzHNhxfcsFyy+uYPtnqI5UGb383swpzQAyXB0OBqYfzpYihD/5gxnA==}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  svelte-writable-derived@3.1.1:
 | 
					  svelte-writable-derived@3.1.1:
 | 
				
			||||||
    resolution: {integrity: sha512-w4LR6/bYZEuCs7SGr+M54oipk/UQKtiMadyOhW0PTwAtJ/Ai12QS77sLngEcfBx2q4H8ZBQucc9ktSA5sUGZWw==}
 | 
					    resolution: {integrity: sha512-w4LR6/bYZEuCs7SGr+M54oipk/UQKtiMadyOhW0PTwAtJ/Ai12QS77sLngEcfBx2q4H8ZBQucc9ktSA5sUGZWw==}
 | 
				
			||||||
    peerDependencies:
 | 
					    peerDependencies:
 | 
				
			||||||
@@ -3955,10 +3946,6 @@ snapshots:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  supports-preserve-symlinks-flag@1.0.0: {}
 | 
					  supports-preserve-symlinks-flag@1.0.0: {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  svelecte@3.17.3:
 | 
					 | 
				
			||||||
    dependencies:
 | 
					 | 
				
			||||||
      svelte-tiny-virtual-list: 2.1.2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  svelte-french-toast@1.2.0(svelte@3.58.0):
 | 
					  svelte-french-toast@1.2.0(svelte@3.58.0):
 | 
				
			||||||
    dependencies:
 | 
					    dependencies:
 | 
				
			||||||
      svelte: 3.58.0
 | 
					      svelte: 3.58.0
 | 
				
			||||||
@@ -3981,8 +3968,6 @@ snapshots:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  svelte-select@3.17.0: {}
 | 
					  svelte-select@3.17.0: {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  svelte-tiny-virtual-list@2.1.2: {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  svelte-writable-derived@3.1.1(svelte@3.58.0):
 | 
					  svelte-writable-derived@3.1.1(svelte@3.58.0):
 | 
				
			||||||
    dependencies:
 | 
					    dependencies:
 | 
				
			||||||
      svelte: 3.58.0
 | 
					      svelte: 3.58.0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -180,7 +180,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -189,7 +189,7 @@
 | 
				
			|||||||
              edit_modal_open = false;
 | 
					              edit_modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,7 @@
 | 
				
			|||||||
          <button
 | 
					          <button
 | 
				
			||||||
            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-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"
 | 
					            class="confirm_deletion_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("delete")}
 | 
					            {$_("delete")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
@@ -112,7 +112,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -469,7 +469,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -194,7 +194,7 @@
 | 
				
			|||||||
              payment_modal_open = false;
 | 
					              payment_modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,7 +81,7 @@
 | 
				
			|||||||
                /></svg
 | 
					                /></svg
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="mt-3 sm:text-left max-h-[75vh] overflow-y-auto">
 | 
					            <div class="mt-3 sm:text-left max-h-[75vh]">
 | 
				
			||||||
              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
					              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
                {$_("please-confirm-the-deletion-of-donation")}
 | 
					                {$_("please-confirm-the-deletion-of-donation")}
 | 
				
			||||||
              </h3>
 | 
					              </h3>
 | 
				
			||||||
@@ -102,7 +102,7 @@
 | 
				
			|||||||
          <button
 | 
					          <button
 | 
				
			||||||
            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-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"
 | 
					            class="confirm_deletion_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("delete")}
 | 
					            {$_("delete")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
@@ -111,7 +111,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,11 +12,13 @@
 | 
				
			|||||||
{#if paymentAction}
 | 
					{#if paymentAction}
 | 
				
			||||||
	<button
 | 
						<button
 | 
				
			||||||
		on:click={paymentAction}
 | 
							on:click={paymentAction}
 | 
				
			||||||
  class="text-[#025a21] hover:text-green-900 mr-4">{$_("enter-payment")}</button
 | 
							class="text-[#025a21] cursor-pointer hover:text-green-900 mr-4"
 | 
				
			||||||
 | 
							>{$_("enter-payment")}</button
 | 
				
			||||||
	>
 | 
						>
 | 
				
			||||||
{:else}
 | 
					{:else}
 | 
				
			||||||
<span class="inline-block opacity-0 cursor-default mr-4" style="">{$_("enter-payment")}</span>
 | 
						<span class="inline-block opacity-0 cursor-default mr-4" style=""
 | 
				
			||||||
 | 
							>{$_("enter-payment")}</span
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
<TableActions
 | 
					<TableActions
 | 
				
			||||||
	bind:detailsAction
 | 
						bind:detailsAction
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -247,14 +247,6 @@
 | 
				
			|||||||
        <thead class="border-b border-gray-400">
 | 
					        <thead class="border-b border-gray-400">
 | 
				
			||||||
          {#each $table.getHeaderGroups() as headerGroup}
 | 
					          {#each $table.getHeaderGroups() as headerGroup}
 | 
				
			||||||
            <tr class="select-none">
 | 
					            <tr class="select-none">
 | 
				
			||||||
              <th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
 | 
					 | 
				
			||||||
                <InputElement
 | 
					 | 
				
			||||||
                  type="checkbox"
 | 
					 | 
				
			||||||
                  checked={$table.getIsAllRowsSelected()}
 | 
					 | 
				
			||||||
                  indeterminate={$table.getIsSomeRowsSelected()}
 | 
					 | 
				
			||||||
                  on:change={() => $table.toggleAllRowsSelected()}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
              </th>
 | 
					 | 
				
			||||||
              {#each headerGroup.headers as header}
 | 
					              {#each headerGroup.headers as header}
 | 
				
			||||||
                <TableHeader {header} />
 | 
					                <TableHeader {header} />
 | 
				
			||||||
              {/each}
 | 
					              {/each}
 | 
				
			||||||
@@ -264,13 +256,6 @@
 | 
				
			|||||||
        <tbody>
 | 
					        <tbody>
 | 
				
			||||||
          {#each $table.getRowModel().rows as row}
 | 
					          {#each $table.getRowModel().rows as row}
 | 
				
			||||||
            <tr class="odd:bg-white even:bg-gray-100">
 | 
					            <tr class="odd:bg-white even:bg-gray-100">
 | 
				
			||||||
              <td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
 | 
					 | 
				
			||||||
                <InputElement
 | 
					 | 
				
			||||||
                  type="checkbox"
 | 
					 | 
				
			||||||
                  checked={row.getIsSelected()}
 | 
					 | 
				
			||||||
                  on:change={() => row.toggleSelected()}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
              </td>
 | 
					 | 
				
			||||||
              {#each row.getVisibleCells() as cell}
 | 
					              {#each row.getVisibleCells() as cell}
 | 
				
			||||||
                <td>
 | 
					                <td>
 | 
				
			||||||
                  <svelte:component
 | 
					                  <svelte:component
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -433,7 +433,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,14 +72,14 @@
 | 
				
			|||||||
					<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"
 | 
											class="confirm_deletion_button"
 | 
				
			||||||
					>
 | 
										>
 | 
				
			||||||
						{$_("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="w-full 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 hidden lg:block"
 | 
											class="cancel_modal_button"
 | 
				
			||||||
					>
 | 
										>
 | 
				
			||||||
						{$_("cancel-keep-donor")}
 | 
											{$_("cancel-keep-donor")}
 | 
				
			||||||
					</button>
 | 
										</button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -174,7 +174,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -294,7 +294,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,14 +86,14 @@
 | 
				
			|||||||
					<button
 | 
										<button
 | 
				
			||||||
						on:click={deleteOrg}
 | 
											on:click={deleteOrg}
 | 
				
			||||||
						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"
 | 
											class="confirm_deletion_button"
 | 
				
			||||||
					>
 | 
										>
 | 
				
			||||||
						{$_("confirm-delete-organization-and-associated-teams-runners")}
 | 
											{$_("confirm-delete-organization-and-associated-teams-runners")}
 | 
				
			||||||
					</button>
 | 
										</button>
 | 
				
			||||||
					<button
 | 
										<button
 | 
				
			||||||
						on:click={cancelDelete}
 | 
											on:click={cancelDelete}
 | 
				
			||||||
						type="button"
 | 
											type="button"
 | 
				
			||||||
						class="w-full 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 hidden lg:block"
 | 
											class="cancel_modal_button"
 | 
				
			||||||
					>
 | 
										>
 | 
				
			||||||
						{$_("cancel-keep-organization")}
 | 
											{$_("cancel-keep-organization")}
 | 
				
			||||||
					</button>
 | 
										</button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class DocumentServer {
 | 
					class DocumentServer {
 | 
				
			||||||
  baseUrl: string;
 | 
					  baseUrl: string;
 | 
				
			||||||
  apiKey: string;
 | 
					  apiKey: string;
 | 
				
			||||||
@@ -12,19 +13,19 @@ class DocumentServer {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (let i = 0; i < cards.length; i++) {
 | 
					    for (let i = 0; i < cards.length; i++) {
 | 
				
			||||||
      const card = {
 | 
					      const card = {
 | 
				
			||||||
        id: cards[i].id,
 | 
					        id: parseInt(cards[i].id),
 | 
				
			||||||
        enabled: cards[i].enabled,
 | 
					        enabled: cards[i].enabled,
 | 
				
			||||||
        code: cards[i].code,
 | 
					        code: cards[i].code,
 | 
				
			||||||
        runner: {
 | 
					        runner: {
 | 
				
			||||||
          id: cards[i]?.runner?.id,
 | 
					          id: parseInt(cards[i]?.runner?.id),
 | 
				
			||||||
          first_name: cards[i]?.runner?.firstname,
 | 
					          first_name: cards[i]?.runner?.firstname,
 | 
				
			||||||
          middle_name: cards[i]?.runner?.middlename,
 | 
					          middle_name: cards[i]?.runner?.middlename,
 | 
				
			||||||
          last_name: cards[i]?.runner?.lastname,
 | 
					          last_name: cards[i]?.runner?.lastname,
 | 
				
			||||||
          group: {
 | 
					          group: {
 | 
				
			||||||
            id: cards[i]?.runner?.group.id,
 | 
					            id: parseInt(cards[i]?.runner?.group?.id),
 | 
				
			||||||
            name: cards[i]?.runner?.group.name,
 | 
					            name: cards[i]?.runner?.group.name,
 | 
				
			||||||
            parent_group: {
 | 
					            parent_group: {
 | 
				
			||||||
              id: cards[i]?.runner?.group?.parentGroup?.id,
 | 
					              id: parseInt(cards[i]?.runner?.group?.parentGroup?.id),
 | 
				
			||||||
              name: cards[i]?.runner?.group?.parentGroup?.name,
 | 
					              name: cards[i]?.runner?.group?.parentGroup?.name,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
@@ -57,15 +58,15 @@ class DocumentServer {
 | 
				
			|||||||
    for (let i = 0; i < runners.length; i++) {
 | 
					    for (let i = 0; i < runners.length; i++) {
 | 
				
			||||||
      console.log(runners[i]);
 | 
					      console.log(runners[i]);
 | 
				
			||||||
      const card = {
 | 
					      const card = {
 | 
				
			||||||
        id: runners[i].id,
 | 
					        id: parseInt(runners[i].id),
 | 
				
			||||||
        first_name: runners[i].firstname,
 | 
					        first_name: runners[i].firstname,
 | 
				
			||||||
        middle_name: runners[i].middlename,
 | 
					        middle_name: runners[i].middlename,
 | 
				
			||||||
        last_name: runners[i].lastname,
 | 
					        last_name: runners[i].lastname,
 | 
				
			||||||
        group: {
 | 
					        group: {
 | 
				
			||||||
          id: runners[i].group.id,
 | 
					          id: parseInt(runners[i].group.id),
 | 
				
			||||||
          name: runners[i].group.name,
 | 
					          name: runners[i].group.name,
 | 
				
			||||||
          parent_group: {
 | 
					          parent_group: {
 | 
				
			||||||
            id: runners[i]?.group?.parentGroup?.id,
 | 
					            id: parseInt(runners[i]?.group?.parentGroup?.id),
 | 
				
			||||||
            name: runners[i]?.group?.parentGroup?.name,
 | 
					            name: runners[i]?.group?.parentGroup?.name,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@@ -96,28 +97,28 @@ class DocumentServer {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (let i = 0; i < runners.length; i++) {
 | 
					    for (let i = 0; i < runners.length; i++) {
 | 
				
			||||||
      const certificate = {
 | 
					      const certificate = {
 | 
				
			||||||
        id: runners[i].id,
 | 
					        id: parseInt(runners[i].id),
 | 
				
			||||||
        first_name: runners[i].firstname,
 | 
					        first_name: runners[i].firstname,
 | 
				
			||||||
        middle_name: runners[i].middlename,
 | 
					        middle_name: runners[i].middlename,
 | 
				
			||||||
        last_name: runners[i].lastname,
 | 
					        last_name: runners[i].lastname,
 | 
				
			||||||
        self_service_link: runners[i].selfserviceLink,
 | 
					        self_service_link: runners[i].selfserviceLink,
 | 
				
			||||||
        group: {
 | 
					        group: {
 | 
				
			||||||
          id: runners[i].group.id,
 | 
					          id: parseInt(runners[i].group.id),
 | 
				
			||||||
          name: runners[i].group.name,
 | 
					          name: runners[i].group.name,
 | 
				
			||||||
          parent_group: {
 | 
					          parent_group: {
 | 
				
			||||||
            id: runners[i]?.group?.parentGroup?.id,
 | 
					            id: parseInt(runners[i]?.group?.parentGroup?.id),
 | 
				
			||||||
            name: runners[i]?.group?.parentGroup?.name,
 | 
					            name: runners[i]?.group?.parentGroup?.name,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        distance: runners[i].distance,
 | 
					        distance: parseInt(runners[i].distance),
 | 
				
			||||||
        distance_donations: runners[i].distanceDonations.map(
 | 
					        distance_donations: runners[i].distanceDonations.map(
 | 
				
			||||||
          (distanceDonation: any) => {
 | 
					          (distanceDonation: any) => {
 | 
				
			||||||
            return {
 | 
					            return {
 | 
				
			||||||
              id: distanceDonation.id,
 | 
					              id: distanceDonation.id,
 | 
				
			||||||
              amount: distanceDonation.amount,
 | 
					              amount: parseInt(distanceDonation.amount),
 | 
				
			||||||
              amount_per_distance: distanceDonation.amountPerDistance,
 | 
					              amount_per_distance: parseInt(distanceDonation.amountPerDistance),
 | 
				
			||||||
              donor: {
 | 
					              donor: {
 | 
				
			||||||
                id: distanceDonation.donor.id,
 | 
					                id: parseInt(distanceDonation.donor.id),
 | 
				
			||||||
                first_name: distanceDonation.donor.firstname,
 | 
					                first_name: distanceDonation.donor.firstname,
 | 
				
			||||||
                middle_name: distanceDonation.donor.middlename,
 | 
					                middle_name: distanceDonation.donor.middlename,
 | 
				
			||||||
                last_name: distanceDonation.donor.lastname,
 | 
					                last_name: distanceDonation.donor.lastname,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,13 +20,13 @@
 | 
				
			|||||||
  export let generate_orgs = [];
 | 
					  export let generate_orgs = [];
 | 
				
			||||||
  export let generate_teams = [];
 | 
					  export let generate_teams = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function generateCertificates(locale) {
 | 
					  function generateCertificates(locale, include0runners = false) {
 | 
				
			||||||
    if (generate_orgs.length > 0) {
 | 
					    if (generate_orgs.length > 0) {
 | 
				
			||||||
      generateOrgCertificates(locale);
 | 
					      generateOrgCertificates(locale, include0runners = false);
 | 
				
			||||||
    } else if (generate_teams.length > 0) {
 | 
					    } else if (generate_teams.length > 0) {
 | 
				
			||||||
      generateTeamCertificates(locale);
 | 
					      generateTeamCertificates(locale, include0runners = false);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      generateRunnerCertificates(locale);
 | 
					      generateRunnerCertificates(locale, include0runners = false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  function download(blob, fileName) {
 | 
					  function download(blob, fileName) {
 | 
				
			||||||
@@ -41,7 +41,7 @@
 | 
				
			|||||||
    toast.success($_("pdf-successfully-generated"));
 | 
					    toast.success($_("pdf-successfully-generated"));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function generateRunnerCertificates(locale) {
 | 
					  async function generateRunnerCertificates(locale, include0runners = false) {
 | 
				
			||||||
    toast.loading($_("generating-pdf"));
 | 
					    toast.loading($_("generating-pdf"));
 | 
				
			||||||
    const current_donations =
 | 
					    const current_donations =
 | 
				
			||||||
      (await DonationService.donationControllerGetAll()) || [];
 | 
					      (await DonationService.donationControllerGetAll()) || [];
 | 
				
			||||||
@@ -50,8 +50,16 @@
 | 
				
			|||||||
	  const linkRunner = await RunnerService.runnerControllerGetOne(runner.id)
 | 
						  const linkRunner = await RunnerService.runnerControllerGetOne(runner.id)
 | 
				
			||||||
      linkRunner.distanceDonations =
 | 
					      linkRunner.distanceDonations =
 | 
				
			||||||
        current_donations.filter((d) => d.runner?.id == runner.id) || [];
 | 
					        current_donations.filter((d) => d.runner?.id == runner.id) || [];
 | 
				
			||||||
 | 
					      // check if linkRunner.distance is 0, if so, and include0runners is false, skip this runner
 | 
				
			||||||
 | 
					      if (
 | 
				
			||||||
 | 
					        !include0runners &&
 | 
				
			||||||
 | 
					        (linkRunner.distance === 0 || linkRunner.distance === null)
 | 
				
			||||||
 | 
					      ) {
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
        certificateRunners.push(linkRunner);
 | 
					        certificateRunners.push(linkRunner);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    documentServer
 | 
					    documentServer
 | 
				
			||||||
      .generateCertificates(certificateRunners, locale)
 | 
					      .generateCertificates(certificateRunners, locale)
 | 
				
			||||||
      .then((blob) => {
 | 
					      .then((blob) => {
 | 
				
			||||||
@@ -66,7 +74,7 @@
 | 
				
			|||||||
      .catch((err) => {});
 | 
					      .catch((err) => {});
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function generateTeamCertificates(locale) {
 | 
					  async function generateTeamCertificates(locale, include0runners = false) {
 | 
				
			||||||
    toast.loading($_("generating-pdfs"));
 | 
					    toast.loading($_("generating-pdfs"));
 | 
				
			||||||
    let count = 0;
 | 
					    let count = 0;
 | 
				
			||||||
    const current_donations =
 | 
					    const current_donations =
 | 
				
			||||||
@@ -80,8 +88,16 @@
 | 
				
			|||||||
      for (let runner of runners) {
 | 
					      for (let runner of runners) {
 | 
				
			||||||
        runner.distanceDonations =
 | 
					        runner.distanceDonations =
 | 
				
			||||||
          current_donations.filter((d) => d.runner?.id == runner.id) || [];
 | 
					          current_donations.filter((d) => d.runner?.id == runner.id) || [];
 | 
				
			||||||
 | 
					        // check if runner.distance is 0, if so, and include0runners is false, skip this runner
 | 
				
			||||||
 | 
					        if (
 | 
				
			||||||
 | 
					          !include0runners &&
 | 
				
			||||||
 | 
					          (runner.distance === 0 || runner.distance === null)
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
          certificateRunners.push(runner);
 | 
					          certificateRunners.push(runner);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      documentServer
 | 
					      documentServer
 | 
				
			||||||
        .generateCertificates(certificateRunners, locale)
 | 
					        .generateCertificates(certificateRunners, locale)
 | 
				
			||||||
        .then((blob) => {
 | 
					        .then((blob) => {
 | 
				
			||||||
@@ -95,7 +111,7 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function generateOrgCertificates(locale) {
 | 
					  async function generateOrgCertificates(locale, include0runners = false) {
 | 
				
			||||||
    toast.loading($_("generating-pdfs"));
 | 
					    toast.loading($_("generating-pdfs"));
 | 
				
			||||||
    const current_donations =
 | 
					    const current_donations =
 | 
				
			||||||
      (await DonationService.donationControllerGetAll()) || [];
 | 
					      (await DonationService.donationControllerGetAll()) || [];
 | 
				
			||||||
@@ -114,8 +130,16 @@
 | 
				
			|||||||
      for (let runner of runners) {
 | 
					      for (let runner of runners) {
 | 
				
			||||||
        runner.distanceDonations =
 | 
					        runner.distanceDonations =
 | 
				
			||||||
          current_donations.filter((d) => d.runner?.id == runner.id) || [];
 | 
					          current_donations.filter((d) => d.runner?.id == runner.id) || [];
 | 
				
			||||||
 | 
					          // check if runner.distance is 0, if so, and include0runners is false, skip this runner
 | 
				
			||||||
 | 
					          if (
 | 
				
			||||||
 | 
					            !include0runners &&
 | 
				
			||||||
 | 
					            (runner.distance === 0 || runner.distance === null)
 | 
				
			||||||
 | 
					          ) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
            certificateRunners.push(runner);
 | 
					            certificateRunners.push(runner);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      await documentServer
 | 
					      await documentServer
 | 
				
			||||||
        .generateCertificates(certificateRunners, locale)
 | 
					        .generateCertificates(certificateRunners, locale)
 | 
				
			||||||
        .then((blob) => {
 | 
					        .then((blob) => {
 | 
				
			||||||
@@ -163,7 +187,7 @@
 | 
				
			|||||||
{#if certificates_show}
 | 
					{#if certificates_show}
 | 
				
			||||||
	<button
 | 
						<button
 | 
				
			||||||
		on:click={() => {
 | 
							on:click={() => {
 | 
				
			||||||
      generateCertificates("de");
 | 
								generateCertificates("de", true);
 | 
				
			||||||
		}}
 | 
							}}
 | 
				
			||||||
		class="w-full 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:w-auto sm:text-sm mb-1 lg:mb-0"
 | 
							class="w-full 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:w-auto sm:text-sm mb-1 lg:mb-0"
 | 
				
			||||||
	>
 | 
						>
 | 
				
			||||||
@@ -171,10 +195,26 @@
 | 
				
			|||||||
	</button>
 | 
						</button>
 | 
				
			||||||
	<button
 | 
						<button
 | 
				
			||||||
		on:click={() => {
 | 
							on:click={() => {
 | 
				
			||||||
      generateCertificates("en");
 | 
								generateCertificates("de", false);
 | 
				
			||||||
 | 
							}}
 | 
				
			||||||
 | 
							class="w-full 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:w-auto sm:text-sm mb-1 lg:mb-0"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							{$_("generate-runner-certificates")}: DE [{$_('exclude_0m_runners_certificate')}]
 | 
				
			||||||
 | 
						</button>
 | 
				
			||||||
 | 
						<button
 | 
				
			||||||
 | 
							on:click={() => {
 | 
				
			||||||
 | 
								generateCertificates("en", true);
 | 
				
			||||||
		}}
 | 
							}}
 | 
				
			||||||
		class="w-full 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:w-auto sm:text-sm mb-1 lg:mb-0"
 | 
							class="w-full 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:w-auto sm:text-sm mb-1 lg:mb-0"
 | 
				
			||||||
	>
 | 
						>
 | 
				
			||||||
		{$_("generate-runner-certificates")}: EN
 | 
							{$_("generate-runner-certificates")}: EN
 | 
				
			||||||
	</button>
 | 
						</button>
 | 
				
			||||||
 | 
						<button
 | 
				
			||||||
 | 
							on:click={() => {
 | 
				
			||||||
 | 
								generateCertificates("en", false);
 | 
				
			||||||
 | 
							}}
 | 
				
			||||||
 | 
							class="w-full 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:w-auto sm:text-sm mb-1 lg:mb-0"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							{$_("generate-runner-certificates")}: EN [{$_('exclude_0m_runners_certificate')}]
 | 
				
			||||||
 | 
						</button>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -338,7 +338,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@
 | 
				
			|||||||
          <button
 | 
					          <button
 | 
				
			||||||
            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-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"
 | 
					            class="confirm_deletion_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("delete")}
 | 
					            {$_("delete")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
@@ -99,7 +99,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -261,7 +261,7 @@
 | 
				
			|||||||
										cancelModal();
 | 
															cancelModal();
 | 
				
			||||||
									}}
 | 
														}}
 | 
				
			||||||
									type="button"
 | 
														type="button"
 | 
				
			||||||
									class="w-full 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 hidden lg:block"
 | 
														class="cancel_modal_button"
 | 
				
			||||||
								>
 | 
													>
 | 
				
			||||||
									{$_("cancel")}
 | 
														{$_("cancel")}
 | 
				
			||||||
								</button>
 | 
													</button>
 | 
				
			||||||
@@ -375,7 +375,7 @@
 | 
				
			|||||||
										cancelModal();
 | 
															cancelModal();
 | 
				
			||||||
									}}
 | 
														}}
 | 
				
			||||||
									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"
 | 
														class="confirm_deletion_button"
 | 
				
			||||||
								>
 | 
													>
 | 
				
			||||||
									{$_("cancel")}
 | 
														{$_("cancel")}
 | 
				
			||||||
								</button>
 | 
													</button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -195,7 +195,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@
 | 
				
			|||||||
          <button
 | 
					          <button
 | 
				
			||||||
            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-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"
 | 
					            class="confirm_deletion_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("delete")}
 | 
					            {$_("delete")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
@@ -99,7 +99,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -203,7 +203,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,14 +82,14 @@
 | 
				
			|||||||
          <button
 | 
					          <button
 | 
				
			||||||
            on:click={deleteStation}
 | 
					            on:click={deleteStation}
 | 
				
			||||||
            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"
 | 
					            class="confirm_deletion_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("confirm-delete-station-with-all-scans")}
 | 
					            {$_("confirm-delete-station-with-all-scans")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
          <button
 | 
					          <button
 | 
				
			||||||
            on:click={cancelDelete}
 | 
					            on:click={cancelDelete}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel-keep-station")}
 | 
					            {$_("cancel-keep-station")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,14 +85,14 @@
 | 
				
			|||||||
          <button
 | 
					          <button
 | 
				
			||||||
            on:click={deleteMe}
 | 
					            on:click={deleteMe}
 | 
				
			||||||
            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"
 | 
					            class="confirm_deletion_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("confirm-delete-my-user-profile")}
 | 
					            {$_("confirm-delete-my-user-profile")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
          <button
 | 
					          <button
 | 
				
			||||||
            on:click={cancelDelete}
 | 
					            on:click={cancelDelete}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel-keep-my-profile")}
 | 
					            {$_("cancel-keep-my-profile")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -148,7 +148,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,14 +81,14 @@
 | 
				
			|||||||
          <button
 | 
					          <button
 | 
				
			||||||
            on:click={deleteClient}
 | 
					            on:click={deleteClient}
 | 
				
			||||||
            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"
 | 
					            class="confirm_deletion_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("confirm-delete-statsclient")}
 | 
					            {$_("confirm-delete-statsclient")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
          <button
 | 
					          <button
 | 
				
			||||||
            on:click={cancelDelete}
 | 
					            on:click={cancelDelete}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel-keep-statsclient")}
 | 
					            {$_("cancel-keep-statsclient")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -199,7 +199,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,14 +85,14 @@
 | 
				
			|||||||
					<button
 | 
										<button
 | 
				
			||||||
						on:click={deleteTeam}
 | 
											on:click={deleteTeam}
 | 
				
			||||||
						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"
 | 
											class="confirm_deletion_button"
 | 
				
			||||||
					>
 | 
										>
 | 
				
			||||||
						{$_("confirm-delete-team-and-associated-runners")}
 | 
											{$_("confirm-delete-team-and-associated-runners")}
 | 
				
			||||||
					</button>
 | 
										</button>
 | 
				
			||||||
					<button
 | 
										<button
 | 
				
			||||||
						on:click={cancelDelete}
 | 
											on:click={cancelDelete}
 | 
				
			||||||
						type="button"
 | 
											type="button"
 | 
				
			||||||
						class="w-full 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 hidden lg:block"
 | 
											class="cancel_modal_button"
 | 
				
			||||||
					>
 | 
										>
 | 
				
			||||||
						{$_("cancel-keep-team")}
 | 
											{$_("cancel-keep-team")}
 | 
				
			||||||
					</button>
 | 
										</button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,9 @@
 | 
				
			|||||||
		DonorService,
 | 
							DonorService,
 | 
				
			||||||
		RunnerService,
 | 
							RunnerService,
 | 
				
			||||||
	} from "@odit/lfk-client-js";
 | 
						} from "@odit/lfk-client-js";
 | 
				
			||||||
  import Select from "svelte-select";
 | 
					 | 
				
			||||||
	import toast from "svelte-french-toast";
 | 
						import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
						import VirtualSelect from "./VirtualSelect.svelte";
 | 
				
			||||||
 | 
						import { onMount } from "svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let runners = [];
 | 
						let runners = [];
 | 
				
			||||||
	let donors = [];
 | 
						let donors = [];
 | 
				
			||||||
@@ -19,7 +20,7 @@
 | 
				
			|||||||
		postalcode: "",
 | 
							postalcode: "",
 | 
				
			||||||
		country: "Germany",
 | 
							country: "Germany",
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
  let amount = 0;
 | 
						let amount = null;
 | 
				
			||||||
	let address_checked = false;
 | 
						let address_checked = false;
 | 
				
			||||||
	let donor_create_new = false;
 | 
						let donor_create_new = false;
 | 
				
			||||||
	let last_created = null;
 | 
						let last_created = null;
 | 
				
			||||||
@@ -51,37 +52,40 @@
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	loadDonors();
 | 
						loadDonors();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const getRunnerLabel = (option) =>
 | 
						const getRunnerLabel = (option) => {
 | 
				
			||||||
    option.firstname + " " + (option.middlename || "") + " " + option.lastname;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const filterRunners = (label, filterText, option) => {
 | 
					 | 
				
			||||||
    if (filterText.startsWith("#")) {
 | 
					 | 
				
			||||||
      return option.value.id == parseInt(filterText.replace("#", ""));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
		return (
 | 
							return (
 | 
				
			||||||
      label.toLowerCase().includes(filterText.toLowerCase()) ||
 | 
								[option.firstname, option.middlename, option.lastname]
 | 
				
			||||||
      option.value.toString().startsWith(filterText.toLowerCase())
 | 
									.join(" ")
 | 
				
			||||||
 | 
									.replace("  ", " ") +
 | 
				
			||||||
 | 
								" [#" +
 | 
				
			||||||
 | 
								option.id +
 | 
				
			||||||
 | 
								"]"
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let selectRefRunner;
 | 
				
			||||||
 | 
						let selectRefDonor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function resetAll() {
 | 
						function resetAll() {
 | 
				
			||||||
		runnerinfo = { id: 0, firstname: "", lastname: "" };
 | 
							runnerinfo = { id: 0, firstname: "", lastname: "" };
 | 
				
			||||||
		donorinfo = { id: 0, firstname: "", lastname: "" };
 | 
							donorinfo = { id: 0, firstname: "", lastname: "" };
 | 
				
			||||||
    amount = 0;
 | 
							amount = null;
 | 
				
			||||||
		address_checked = false;
 | 
							address_checked = false;
 | 
				
			||||||
		donor_create_new = false;
 | 
							donor_create_new = false;
 | 
				
			||||||
    const clears = document.getElementsByClassName("clearSelect");
 | 
							selectRefRunner?.reset();
 | 
				
			||||||
    for (let i = 0; i < clears.length; i++) {
 | 
							selectRefDonor?.reset();
 | 
				
			||||||
      clears[i].click();
 | 
							document.querySelector("#jjqzqicxujrnnh1x3447x18x").focus();
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						onMount(() => {
 | 
				
			||||||
 | 
							document.querySelector("#jjqzqicxujrnnh1x3447x18x").focus();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="p-4">
 | 
					<div class="p-4">
 | 
				
			||||||
	<h3 class="text-3xl font-bold">{$_("fast_donation_create")}</h3>
 | 
						<h3 class="text-3xl font-bold">{$_("fast_donation_create")}</h3>
 | 
				
			||||||
	<!--  -->
 | 
						<!--  -->
 | 
				
			||||||
	<div>
 | 
						<div>
 | 
				
			||||||
    <div class="w-full max-w-md space-y-4 mb-6">
 | 
							<div class="w-full space-y-4 mb-6">
 | 
				
			||||||
			{#if last_created}
 | 
								{#if last_created}
 | 
				
			||||||
				<div class="mt-4 p-3 bg-green-50 border border-green-200 rounded-md">
 | 
									<div class="mt-4 p-3 bg-green-50 border border-green-200 rounded-md">
 | 
				
			||||||
					<p class="text-black">
 | 
										<p class="text-black">
 | 
				
			||||||
@@ -93,23 +97,32 @@
 | 
				
			|||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			{/if}
 | 
								{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <!-- Runner Selection -->
 | 
								<!--  -->
 | 
				
			||||||
      <div>
 | 
					 | 
				
			||||||
			<h4 class="text-xl font-semibold">{$_("runner")}</h4>
 | 
								<h4 class="text-xl font-semibold">{$_("runner")}</h4>
 | 
				
			||||||
        <Select
 | 
								<VirtualSelect
 | 
				
			||||||
          containerClasses="rounded-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
									inputElementID="jjqzqicxujrnnh1x3447x18x"
 | 
				
			||||||
          itemFilter={(label, filterText, option) =>
 | 
									bind:this={selectRefRunner}
 | 
				
			||||||
            filterRunners(label, filterText, option)}
 | 
									on:onClear={() => {
 | 
				
			||||||
          items={runners}
 | 
										console.log("Cleared selection");
 | 
				
			||||||
          showChevron={true}
 | 
									}}
 | 
				
			||||||
          placeholder={$_("search-for-runner-by-name-or-id")}
 | 
									options={runners}
 | 
				
			||||||
          noOptionsMessage={$_("no-runners-found")}
 | 
									filterFn={(item, searchTerm) => {
 | 
				
			||||||
          on:select={(selectedValue) => {
 | 
										if (searchTerm.startsWith("#")) {
 | 
				
			||||||
            runnerinfo = selectedValue.detail.value;
 | 
											const id = parseInt(searchTerm.replace("#", ""));
 | 
				
			||||||
 | 
											return item.value.id === id;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										return item.label.toLowerCase().includes(searchTerm.toLowerCase());
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
									bind:selected={runnerinfo}
 | 
				
			||||||
 | 
									inputAriaLabel={$_("search-for-runner-by-name-or-id")}
 | 
				
			||||||
 | 
									inputPlaceholder={$_("search-for-runner-by-name-or-id")}
 | 
				
			||||||
 | 
									noOptionsText={$_("no-runners-found")}
 | 
				
			||||||
 | 
									on:onSelected={(data) => {
 | 
				
			||||||
 | 
										if (data.detail !== null) {
 | 
				
			||||||
 | 
											document.querySelector("#donation_amount_eur").focus();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}}
 | 
									}}
 | 
				
			||||||
          on:clear={() => (runnerinfo = { id: 0, firstname: "", lastname: "" })}
 | 
					 | 
				
			||||||
			/>
 | 
								/>
 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<!-- Amount Input -->
 | 
								<!-- Amount Input -->
 | 
				
			||||||
			<div>
 | 
								<div>
 | 
				
			||||||
@@ -121,11 +134,18 @@
 | 
				
			|||||||
						class:focus:border-red-500={!amount > 0}
 | 
											class:focus:border-red-500={!amount > 0}
 | 
				
			||||||
						class:focus:ring-red-500={!amount > 0}
 | 
											class:focus:ring-red-500={!amount > 0}
 | 
				
			||||||
						bind:value={amount}
 | 
											bind:value={amount}
 | 
				
			||||||
 | 
											on:keydown={(e) => {
 | 
				
			||||||
 | 
												if (e.key === "Enter") {
 | 
				
			||||||
 | 
													e.preventDefault();
 | 
				
			||||||
 | 
													document.querySelector("#button_existing_donor").focus();
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
						type="number"
 | 
											type="number"
 | 
				
			||||||
						step="0.01"
 | 
											step="0.01"
 | 
				
			||||||
 | 
											id="donation_amount_eur"
 | 
				
			||||||
						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 border-neutral-300 border bg-neutral-50 text-neutral-800 p-2"
 | 
											class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 p-2"
 | 
				
			||||||
            placeholder="2.00"
 | 
											placeholder="z.B. 1,50"
 | 
				
			||||||
					/>
 | 
										/>
 | 
				
			||||||
					<span
 | 
										<span
 | 
				
			||||||
						class="inline-flex items-center px-3 rounded-r-md border border-neutral-300 bg-neutral-50 text-neutral-500 text-sm"
 | 
											class="inline-flex items-center px-3 rounded-r-md border border-neutral-300 bg-neutral-50 text-neutral-500 text-sm"
 | 
				
			||||||
@@ -142,6 +162,18 @@
 | 
				
			|||||||
				<div class="mb-2">
 | 
									<div class="mb-2">
 | 
				
			||||||
					<div class="flex border rounded-md overflow-hidden shadow-sm">
 | 
										<div class="flex border rounded-md overflow-hidden shadow-sm">
 | 
				
			||||||
						<button
 | 
											<button
 | 
				
			||||||
 | 
												on:keydown={(e) => {
 | 
				
			||||||
 | 
													if (e.key === "ArrowRight") {
 | 
				
			||||||
 | 
														e.preventDefault();
 | 
				
			||||||
 | 
														document.querySelector("#button_new_donor").focus();
 | 
				
			||||||
 | 
														document.querySelector("#button_new_donor").click();
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
													if (e.key === "Enter") {
 | 
				
			||||||
 | 
														e.preventDefault();
 | 
				
			||||||
 | 
														document.querySelector("#zt12c3udy3bme5bqobmqcif1").focus();
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
												id="button_existing_donor"
 | 
				
			||||||
							class:bg-indigo-600={!donor_create_new}
 | 
												class:bg-indigo-600={!donor_create_new}
 | 
				
			||||||
							class:text-white={!donor_create_new}
 | 
												class:text-white={!donor_create_new}
 | 
				
			||||||
							class="py-2 px-4 w-1/2 transition-colors"
 | 
												class="py-2 px-4 w-1/2 transition-colors"
 | 
				
			||||||
@@ -153,10 +185,25 @@
 | 
				
			|||||||
							{$_("existing-donor")}
 | 
												{$_("existing-donor")}
 | 
				
			||||||
						</button>
 | 
											</button>
 | 
				
			||||||
						<button
 | 
											<button
 | 
				
			||||||
 | 
												on:keydown={(e) => {
 | 
				
			||||||
 | 
													if (e.key === "ArrowLeft") {
 | 
				
			||||||
 | 
														e.preventDefault();
 | 
				
			||||||
 | 
														document.querySelector("#button_existing_donor").focus();
 | 
				
			||||||
 | 
														document.querySelector("#button_existing_donor").click();
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
													if (e.key === "Enter") {
 | 
				
			||||||
 | 
														e.preventDefault();
 | 
				
			||||||
 | 
														document.querySelector("#button_new_donor").click();
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
												id="button_new_donor"
 | 
				
			||||||
							class={`py-2 px-4 w-1/2 transition-colors ${donor_create_new ? "bg-indigo-600 text-white" : "bg-gray-100 text-gray-700"}`}
 | 
												class={`py-2 px-4 w-1/2 transition-colors ${donor_create_new ? "bg-indigo-600 text-white" : "bg-gray-100 text-gray-700"}`}
 | 
				
			||||||
							on:click={() => {
 | 
												on:click={() => {
 | 
				
			||||||
								donor_create_new = true;
 | 
													donor_create_new = true;
 | 
				
			||||||
								donorinfo = { id: 0, firstname: "", lastname: "" };
 | 
													donorinfo = { id: 0, firstname: "", lastname: "" };
 | 
				
			||||||
 | 
													setTimeout(() => {
 | 
				
			||||||
 | 
														document.querySelector("#firstname").focus();
 | 
				
			||||||
 | 
													}, 50);
 | 
				
			||||||
							}}
 | 
												}}
 | 
				
			||||||
						>
 | 
											>
 | 
				
			||||||
							{$_("new-donor")}
 | 
												{$_("new-donor")}
 | 
				
			||||||
@@ -165,19 +212,31 @@
 | 
				
			|||||||
				</div>
 | 
									</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				{#if !donor_create_new}
 | 
									{#if !donor_create_new}
 | 
				
			||||||
          <Select
 | 
										<VirtualSelect
 | 
				
			||||||
            containerClasses="rounded-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
											inputElementID="zt12c3udy3bme5bqobmqcif1"
 | 
				
			||||||
            itemFilter={(label, filterText, option) =>
 | 
											bind:this={selectRefDonor}
 | 
				
			||||||
              filterRunners(label, filterText, option)}
 | 
											on:onClear={() => {
 | 
				
			||||||
            items={donors}
 | 
												console.log("Cleared selection");
 | 
				
			||||||
            showChevron={true}
 | 
											}}
 | 
				
			||||||
            placeholder={$_("search-for-donor")}
 | 
											options={donors}
 | 
				
			||||||
            noOptionsMessage={$_("no-donors-found")}
 | 
											filterFn={(item, searchTerm) => {
 | 
				
			||||||
            on:select={(selectedValue) => {
 | 
												return item.label
 | 
				
			||||||
              donorinfo = selectedValue.detail.value;
 | 
													.toLowerCase()
 | 
				
			||||||
 | 
													.includes(searchTerm.toLowerCase());
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
											bind:selected={donorinfo}
 | 
				
			||||||
 | 
											inputAriaLabel={$_("search-for-donor")}
 | 
				
			||||||
 | 
											inputPlaceholder={$_("search-for-donor")}
 | 
				
			||||||
 | 
											noOptionsText={$_("no-donors-found")}
 | 
				
			||||||
 | 
											on:onSelected={(data) => {
 | 
				
			||||||
 | 
												console.log(data.detail);
 | 
				
			||||||
 | 
												if (data.detail !== null) {
 | 
				
			||||||
 | 
													document.querySelector("#submit_button").focus();
 | 
				
			||||||
 | 
													setTimeout(() => {
 | 
				
			||||||
 | 
														document.querySelector("#submit_button").focus();
 | 
				
			||||||
 | 
													}, 100);
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
						}}
 | 
											}}
 | 
				
			||||||
            on:clear={() =>
 | 
					 | 
				
			||||||
              (donorinfo = { id: 0, firstname: "", lastname: "" })}
 | 
					 | 
				
			||||||
					/>
 | 
										/>
 | 
				
			||||||
				{:else}
 | 
									{:else}
 | 
				
			||||||
					<div class="space-y-3">
 | 
										<div class="space-y-3">
 | 
				
			||||||
@@ -192,6 +251,11 @@
 | 
				
			|||||||
							<input
 | 
												<input
 | 
				
			||||||
								type="text"
 | 
													type="text"
 | 
				
			||||||
								id="firstname"
 | 
													id="firstname"
 | 
				
			||||||
 | 
													on:keydown={(e) => {
 | 
				
			||||||
 | 
														if (e.key === "Enter") {
 | 
				
			||||||
 | 
															document.querySelector("#lastname").focus();
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													}}
 | 
				
			||||||
								bind:value={donorinfo.firstname}
 | 
													bind:value={donorinfo.firstname}
 | 
				
			||||||
								class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 p-2"
 | 
													class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 p-2"
 | 
				
			||||||
								placeholder={$_("first-name")}
 | 
													placeholder={$_("first-name")}
 | 
				
			||||||
@@ -306,6 +370,7 @@
 | 
				
			|||||||
			<!-- Submit Button -->
 | 
								<!-- Submit Button -->
 | 
				
			||||||
			<div class="mt-6">
 | 
								<div class="mt-6">
 | 
				
			||||||
				<button
 | 
									<button
 | 
				
			||||||
 | 
										id="submit_button"
 | 
				
			||||||
					type="button"
 | 
										type="button"
 | 
				
			||||||
					class="w-full inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-400 disabled:cursor-not-allowed"
 | 
										class="w-full inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-400 disabled:cursor-not-allowed"
 | 
				
			||||||
					disabled={!amount > 0 ||
 | 
										disabled={!amount > 0 ||
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										357
									
								
								src/components/tools/VirtualSelect.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								src/components/tools/VirtualSelect.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,357 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { createEventDispatcher, onMount, tick } from "svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Generate a default unique ID
 | 
				
			||||||
 | 
						function generateDefaultID() {
 | 
				
			||||||
 | 
							return "virtual-select-" + Math.random().toString(36).slice(2);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Props
 | 
				
			||||||
 | 
						export let options = [];
 | 
				
			||||||
 | 
						export let selected = null;
 | 
				
			||||||
 | 
						export let inputPlaceholder = "Search options...";
 | 
				
			||||||
 | 
						export let noOptionsText = "No options found";
 | 
				
			||||||
 | 
						export let inputAriaLabel = "Search and select an option";
 | 
				
			||||||
 | 
						export let toggleAriaLabel = "Toggle dropdown";
 | 
				
			||||||
 | 
						export let clearAriaLabel = "Clear selection";
 | 
				
			||||||
 | 
						export let filterFn = null; // Custom filter function
 | 
				
			||||||
 | 
						export let autofocus = false; // Autofocus input
 | 
				
			||||||
 | 
						export let inputElementID = generateDefaultID(); // Input element ID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Internal state
 | 
				
			||||||
 | 
						let searchTerm = "";
 | 
				
			||||||
 | 
						let filteredOptions = options;
 | 
				
			||||||
 | 
						let isOpen = false;
 | 
				
			||||||
 | 
						let container;
 | 
				
			||||||
 | 
						let visibleItems = [];
 | 
				
			||||||
 | 
						let startIndex = 0;
 | 
				
			||||||
 | 
						let itemHeight = 40; // Fixed height for each option (in pixels)
 | 
				
			||||||
 | 
						let visibleCount = 10; // Default number of items to render
 | 
				
			||||||
 | 
						let focusedIndex = -1; // Track the focused option index (-1 means no focus)
 | 
				
			||||||
 | 
						let inputElement; // Reference to input element
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter options based on search term
 | 
				
			||||||
 | 
						$: {
 | 
				
			||||||
 | 
							filteredOptions = searchTerm
 | 
				
			||||||
 | 
								? filterFn
 | 
				
			||||||
 | 
									? options.filter((option) => filterFn(option, searchTerm))
 | 
				
			||||||
 | 
									: options.filter((option) =>
 | 
				
			||||||
 | 
											option.label.toLowerCase().includes(searchTerm.toLowerCase())
 | 
				
			||||||
 | 
										)
 | 
				
			||||||
 | 
								: options;
 | 
				
			||||||
 | 
							// Reset scroll and focus when filtered options change
 | 
				
			||||||
 | 
							startIndex = 0;
 | 
				
			||||||
 | 
							focusedIndex = -1;
 | 
				
			||||||
 | 
							updateVisibleItems();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Update visible items based on scroll position
 | 
				
			||||||
 | 
						function updateVisibleItems() {
 | 
				
			||||||
 | 
							if (!container) return;
 | 
				
			||||||
 | 
							const scrollTop = container.scrollTop;
 | 
				
			||||||
 | 
							startIndex = Math.floor(scrollTop / itemHeight);
 | 
				
			||||||
 | 
							const endIndex = Math.min(
 | 
				
			||||||
 | 
								startIndex + visibleCount,
 | 
				
			||||||
 | 
								filteredOptions.length
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
							visibleItems = filteredOptions.slice(startIndex, endIndex);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handle scroll event
 | 
				
			||||||
 | 
						function handleScroll() {
 | 
				
			||||||
 | 
							updateVisibleItems();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Calculate visible item count based on container height
 | 
				
			||||||
 | 
						async function updateVisibleCount() {
 | 
				
			||||||
 | 
							if (container) {
 | 
				
			||||||
 | 
								await tick(); // Wait for DOM to render
 | 
				
			||||||
 | 
								visibleCount = Math.ceil(container.clientHeight / itemHeight) + 2; // Buffer of 2 items
 | 
				
			||||||
 | 
								updateVisibleItems();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handle option selection
 | 
				
			||||||
 | 
						function selectOption(option) {
 | 
				
			||||||
 | 
							selected = option.value;
 | 
				
			||||||
 | 
							isOpen = false;
 | 
				
			||||||
 | 
							searchTerm = option.label; // Set searchTerm to the selected option's label
 | 
				
			||||||
 | 
							focusedIndex = -1;
 | 
				
			||||||
 | 
							dispatch("onSelected", option.value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handle clear selection
 | 
				
			||||||
 | 
						function clearSelection() {
 | 
				
			||||||
 | 
							selected = null;
 | 
				
			||||||
 | 
							searchTerm = "";
 | 
				
			||||||
 | 
							focusedIndex = -1;
 | 
				
			||||||
 | 
							dispatch("onSelected", null);
 | 
				
			||||||
 | 
							dispatch("onClear");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reset component state
 | 
				
			||||||
 | 
						export function reset() {
 | 
				
			||||||
 | 
							selected = null;
 | 
				
			||||||
 | 
							searchTerm = "";
 | 
				
			||||||
 | 
							isOpen = false;
 | 
				
			||||||
 | 
							focusedIndex = -1;
 | 
				
			||||||
 | 
							startIndex = 0;
 | 
				
			||||||
 | 
							updateVisibleItems();
 | 
				
			||||||
 | 
							dispatch("onSelected", null);
 | 
				
			||||||
 | 
							dispatch("onClear");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Toggle dropdown
 | 
				
			||||||
 | 
						async function toggleDropdown() {
 | 
				
			||||||
 | 
							isOpen = !isOpen;
 | 
				
			||||||
 | 
							if (isOpen) {
 | 
				
			||||||
 | 
								forceVisibleItems();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handle click outside to close dropdown
 | 
				
			||||||
 | 
						function handleClickOutside(event) {
 | 
				
			||||||
 | 
							if (!event.target.closest(".select-container")) {
 | 
				
			||||||
 | 
								isOpen = false;
 | 
				
			||||||
 | 
								focusedIndex = -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handle input focus to open dropdown
 | 
				
			||||||
 | 
						async function handleInputFocus() {
 | 
				
			||||||
 | 
							// forceVisibleItems();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handle input typing to open dropdown
 | 
				
			||||||
 | 
						async function handleInput() {
 | 
				
			||||||
 | 
							forceVisibleItems();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						async function forceVisibleItems() {
 | 
				
			||||||
 | 
							isOpen = true;
 | 
				
			||||||
 | 
							await updateVisibleCount(); // Ensure items render on focus
 | 
				
			||||||
 | 
							// these 2 timeouts are a more or less tmp fix for rendering items when dropdown opens
 | 
				
			||||||
 | 
							setTimeout(async () => {
 | 
				
			||||||
 | 
								await updateVisibleCount(); // Ensure items render on focus
 | 
				
			||||||
 | 
							}, 25);
 | 
				
			||||||
 | 
							setTimeout(async () => {
 | 
				
			||||||
 | 
								await updateVisibleCount(); // Ensure items render on focus
 | 
				
			||||||
 | 
							}, 50);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handle keyboard navigation
 | 
				
			||||||
 | 
						function handleKeydown(event, index) {
 | 
				
			||||||
 | 
							if (!isOpen) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (event.key === "ArrowDown") {
 | 
				
			||||||
 | 
								event.preventDefault();
 | 
				
			||||||
 | 
								if (focusedIndex < filteredOptions.length - 1) {
 | 
				
			||||||
 | 
									focusedIndex += 1;
 | 
				
			||||||
 | 
									scrollToFocusedItem();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (event.key === "ArrowUp") {
 | 
				
			||||||
 | 
								event.preventDefault();
 | 
				
			||||||
 | 
								if (focusedIndex > 0) {
 | 
				
			||||||
 | 
									focusedIndex -= 1;
 | 
				
			||||||
 | 
									scrollToFocusedItem();
 | 
				
			||||||
 | 
								} else if (focusedIndex === -1 && filteredOptions.length > 0) {
 | 
				
			||||||
 | 
									focusedIndex = 0;
 | 
				
			||||||
 | 
									scrollToFocusedItem();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (event.key === "Enter" && index >= 0) {
 | 
				
			||||||
 | 
								event.preventDefault();
 | 
				
			||||||
 | 
								selectOption(filteredOptions[index]);
 | 
				
			||||||
 | 
							} else if (event.key === "Escape") {
 | 
				
			||||||
 | 
								event.preventDefault();
 | 
				
			||||||
 | 
								isOpen = false;
 | 
				
			||||||
 | 
								focusedIndex = -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Scroll to the focused item
 | 
				
			||||||
 | 
						function scrollToFocusedItem() {
 | 
				
			||||||
 | 
							if (!container || focusedIndex < 0) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const itemTop = focusedIndex * itemHeight;
 | 
				
			||||||
 | 
							const itemBottom = itemTop + itemHeight;
 | 
				
			||||||
 | 
							const containerTop = container.scrollTop;
 | 
				
			||||||
 | 
							const containerBottom = containerTop + container.clientHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (itemTop < containerTop) {
 | 
				
			||||||
 | 
								container.scrollTop = itemTop;
 | 
				
			||||||
 | 
							} else if (itemBottom > containerBottom) {
 | 
				
			||||||
 | 
								container.scrollTop = itemBottom - container.clientHeight;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							updateVisibleItems();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Initialize container size observer and autofocus fallback
 | 
				
			||||||
 | 
						onMount(async () => {
 | 
				
			||||||
 | 
							if (container) {
 | 
				
			||||||
 | 
								const resizeObserver = new ResizeObserver(updateVisibleCount);
 | 
				
			||||||
 | 
								resizeObserver.observe(container);
 | 
				
			||||||
 | 
								return () => resizeObserver.disconnect();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Fallback autofocus with tick to ensure inputElement is bound
 | 
				
			||||||
 | 
							if (autofocus && inputElement) {
 | 
				
			||||||
 | 
								await tick();
 | 
				
			||||||
 | 
								inputElement.focus();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get display text for the input
 | 
				
			||||||
 | 
						function getDisplayText() {
 | 
				
			||||||
 | 
							if (!selected) return inputPlaceholder;
 | 
				
			||||||
 | 
							const selectedOption = options.find((option) => option.value === selected);
 | 
				
			||||||
 | 
							return selectedOption ? selectedOption.label : inputPlaceholder;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<svelte:window on:click={handleClickOutside} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="select-container relative w-full">
 | 
				
			||||||
 | 
						<!-- Select element with inline search -->
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							class="border rounded-md px-3 py-2 bg-white shadow-sm flex items-center gap-2"
 | 
				
			||||||
 | 
							role="combobox"
 | 
				
			||||||
 | 
							aria-expanded={isOpen}
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<input
 | 
				
			||||||
 | 
								autocomplete="off"
 | 
				
			||||||
 | 
								type="text"
 | 
				
			||||||
 | 
								id={inputElementID}
 | 
				
			||||||
 | 
								bind:value={searchTerm}
 | 
				
			||||||
 | 
								bind:this={inputElement}
 | 
				
			||||||
 | 
								placeholder={getDisplayText()}
 | 
				
			||||||
 | 
								class="w-full bg-transparent focus:outline-none {selected
 | 
				
			||||||
 | 
									? 'text-black'
 | 
				
			||||||
 | 
									: 'text-gray-700'}"
 | 
				
			||||||
 | 
								{autofocus}
 | 
				
			||||||
 | 
								on:focus={handleInputFocus}
 | 
				
			||||||
 | 
								on:input={handleInput}
 | 
				
			||||||
 | 
								on:keydown={(e) => {
 | 
				
			||||||
 | 
									if (e.key === "Enter" && !isOpen) {
 | 
				
			||||||
 | 
										toggleDropdown();
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										handleKeydown(e, focusedIndex);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								aria-label={inputAriaLabel}
 | 
				
			||||||
 | 
							/>
 | 
				
			||||||
 | 
							{#if selected}
 | 
				
			||||||
 | 
								<button
 | 
				
			||||||
 | 
									type="button"
 | 
				
			||||||
 | 
									class="w-5 h-5 flex items-center justify-center text-gray-500 hover:text-gray-700"
 | 
				
			||||||
 | 
									on:click={clearSelection}
 | 
				
			||||||
 | 
									on:keydown={(e) => {
 | 
				
			||||||
 | 
										if (e.key === "Enter" || e.key === " ") {
 | 
				
			||||||
 | 
											e.preventDefault();
 | 
				
			||||||
 | 
											clearSelection();
 | 
				
			||||||
 | 
										} else if (e.key === "Escape") {
 | 
				
			||||||
 | 
											e.preventDefault();
 | 
				
			||||||
 | 
											isOpen = false;
 | 
				
			||||||
 | 
											focusedIndex = -1;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
									role="button"
 | 
				
			||||||
 | 
									tabindex="0"
 | 
				
			||||||
 | 
									aria-label={clearAriaLabel}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										class="w-4 h-4"
 | 
				
			||||||
 | 
										fill="none"
 | 
				
			||||||
 | 
										stroke="currentColor"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											stroke-linecap="round"
 | 
				
			||||||
 | 
											stroke-linejoin="round"
 | 
				
			||||||
 | 
											stroke-width="2"
 | 
				
			||||||
 | 
											d="M6 18L18 6M6 6l12 12"
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
									</svg>
 | 
				
			||||||
 | 
								</button>
 | 
				
			||||||
 | 
							{/if}
 | 
				
			||||||
 | 
							<svg
 | 
				
			||||||
 | 
								class="w-4 h-4 text-gray-500 transform {isOpen ? 'rotate-180' : ''}"
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke="currentColor"
 | 
				
			||||||
 | 
								viewBox="0 0 24 24"
 | 
				
			||||||
 | 
								on:click={toggleDropdown}
 | 
				
			||||||
 | 
								role="button"
 | 
				
			||||||
 | 
								tabindex="0"
 | 
				
			||||||
 | 
								on:keydown={(e) => {
 | 
				
			||||||
 | 
									if (e.key === "Enter") toggleDropdown();
 | 
				
			||||||
 | 
									else if (e.key === "Escape") {
 | 
				
			||||||
 | 
										e.preventDefault();
 | 
				
			||||||
 | 
										isOpen = false;
 | 
				
			||||||
 | 
										focusedIndex = -1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								aria-label={toggleAriaLabel}
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<path
 | 
				
			||||||
 | 
									stroke-linecap="round"
 | 
				
			||||||
 | 
									stroke-linejoin="round"
 | 
				
			||||||
 | 
									stroke
 | 
				
			||||||
 | 
									Politeness="round"
 | 
				
			||||||
 | 
									stroke-width="2"
 | 
				
			||||||
 | 
									d="M19 9l-7 7-7-7"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							</svg>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<!-- Dropdown -->
 | 
				
			||||||
 | 
						{#if isOpen}
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								class="absolute z-10 w-full mt-1 bg-white border rounded-md shadow-lg max-h-80 overflow-auto"
 | 
				
			||||||
 | 
								bind:this={container}
 | 
				
			||||||
 | 
								on:scroll={handleScroll}
 | 
				
			||||||
 | 
								role="listbox"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								{#if filteredOptions.length > 0}
 | 
				
			||||||
 | 
									<!-- Virtualized list container -->
 | 
				
			||||||
 | 
									<div style="height: {filteredOptions.length * itemHeight}px;">
 | 
				
			||||||
 | 
										<div style="transform: translateY({startIndex * itemHeight}px);">
 | 
				
			||||||
 | 
											{#each visibleItems as item, i (item.label + "-" + (startIndex + i))}
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													class="px-3 py-2 hover:bg-blue-100 cursor-pointer {selected ===
 | 
				
			||||||
 | 
													item.value
 | 
				
			||||||
 | 
														? 'bg-blue-50'
 | 
				
			||||||
 | 
														: ''} {focusedIndex === startIndex + i
 | 
				
			||||||
 | 
														? 'bg-blue-200 outline outline-2 outline-blue-500'
 | 
				
			||||||
 | 
														: ''}"
 | 
				
			||||||
 | 
													on:click={() => selectOption(item)}
 | 
				
			||||||
 | 
													on:keydown={(e) => handleKeydown(e, startIndex + i)}
 | 
				
			||||||
 | 
													role="option"
 | 
				
			||||||
 | 
													tabindex="0"
 | 
				
			||||||
 | 
													aria-selected={selected === item.value}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													{item.label}
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											{/each}
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								{:else}
 | 
				
			||||||
 | 
									<div class="px-3 py-2 text-gray-500">{noOptionsText}</div>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						{/if}
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
						/* Ensure Tailwind classes handle additional styling */
 | 
				
			||||||
 | 
						:global(.select-container input:focus) {
 | 
				
			||||||
 | 
							border-color: #3b82f6; /* Tailwind's blue-500 */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						:global([role="option"]:focus) {
 | 
				
			||||||
 | 
							outline: 2px solid #3b82f6;
 | 
				
			||||||
 | 
							outline-offset: -2px;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						:global([role="button"]:focus) {
 | 
				
			||||||
 | 
							outline: 2px solid #3b82f6;
 | 
				
			||||||
 | 
							outline-offset: -2px;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@@ -230,7 +230,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -287,7 +287,7 @@
 | 
				
			|||||||
              modal_open = false;
 | 
					              modal_open = false;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            type="button"
 | 
					            type="button"
 | 
				
			||||||
            class="w-full 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 hidden lg:block"
 | 
					            class="cancel_modal_button"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {$_("cancel")}
 | 
					            {$_("cancel")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -227,11 +227,12 @@
 | 
				
			|||||||
    "enabled_large": "Aktiviert",
 | 
					    "enabled_large": "Aktiviert",
 | 
				
			||||||
    "english": "Englisch",
 | 
					    "english": "Englisch",
 | 
				
			||||||
    "enter-payment": "Zahlung eingeben",
 | 
					    "enter-payment": "Zahlung eingeben",
 | 
				
			||||||
    "error-creating-donation": "Fehler bei der Anlage",
 | 
					    "error-creating-donation": "Fehler beim Erstellen des Sponsorings",
 | 
				
			||||||
    "error-during-import": "Fehler beim Importieren",
 | 
					    "error-during-import": "Fehler beim Importieren",
 | 
				
			||||||
    "error-whyile-copying-to-clipboard": "Fehler beim Kopieren in die Zwischenablage",
 | 
					    "error-whyile-copying-to-clipboard": "Fehler beim Kopieren in die Zwischenablage",
 | 
				
			||||||
    "error_on_login": "😢Fehler beim Login",
 | 
					    "error_on_login": "😢Fehler beim Login",
 | 
				
			||||||
    "everything-concerning-your-profile": "Alles zu deinem Profil",
 | 
					    "everything-concerning-your-profile": "Alles zu deinem Profil",
 | 
				
			||||||
 | 
					    "exclude_0m_runners_certificate": "ohne 0m Läufer",
 | 
				
			||||||
    "existing-donor": "Existierende Sponsor:in",
 | 
					    "existing-donor": "Existierende Sponsor:in",
 | 
				
			||||||
    "faq": "FAQ",
 | 
					    "faq": "FAQ",
 | 
				
			||||||
    "fast_card_replacement": "Karten-Schnellzusweisung (Mit Mobilgeräteunterstützung)",
 | 
					    "fast_card_replacement": "Karten-Schnellzusweisung (Mit Mobilgeräteunterstützung)",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -227,10 +227,12 @@
 | 
				
			|||||||
    "enabled_large": "Enabled",
 | 
					    "enabled_large": "Enabled",
 | 
				
			||||||
    "english": "English",
 | 
					    "english": "English",
 | 
				
			||||||
    "enter-payment": "Enter payment",
 | 
					    "enter-payment": "Enter payment",
 | 
				
			||||||
 | 
					    "error-creating-donation": "error creating the sponsoring",
 | 
				
			||||||
    "error-during-import": "Error during import",
 | 
					    "error-during-import": "Error during import",
 | 
				
			||||||
    "error-whyile-copying-to-clipboard": "Error while copying to clipboard",
 | 
					    "error-whyile-copying-to-clipboard": "Error while copying to clipboard",
 | 
				
			||||||
    "error_on_login": "Error on login",
 | 
					    "error_on_login": "Error on login",
 | 
				
			||||||
    "everything-concerning-your-profile": "Everything concerning your profile",
 | 
					    "everything-concerning-your-profile": "Everything concerning your profile",
 | 
				
			||||||
 | 
					    "exclude_0m_runners_certificate": "exclude runners without scans",
 | 
				
			||||||
    "existing-donor": "Existing Donor",
 | 
					    "existing-donor": "Existing Donor",
 | 
				
			||||||
    "faq": "FAQ",
 | 
					    "faq": "FAQ",
 | 
				
			||||||
    "fast_card_replacement": "Fast card replacement (with mobile support)",
 | 
					    "fast_card_replacement": "Fast card replacement (with mobile support)",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,3 +31,9 @@
 | 
				
			|||||||
.donation_active_tab {
 | 
					.donation_active_tab {
 | 
				
			||||||
	@apply min-w-0 flex-1 bg-blue-400 text-white first:border-s-0 border-s border-b-2 border-neutral-200 py-4 px-4 text-sm font-medium text-center overflow-hidden cursor-pointer focus:outline-hidden;
 | 
						@apply min-w-0 flex-1 bg-blue-400 text-white first:border-s-0 border-s border-b-2 border-neutral-200 py-4 px-4 text-sm font-medium text-center overflow-hidden cursor-pointer focus:outline-hidden;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.confirm_deletion_button {
 | 
				
			||||||
 | 
						@apply w-full cursor-pointer 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.cancel_modal_button {
 | 
				
			||||||
 | 
						@apply w-full cursor-pointer 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 hidden lg:block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user