Compare commits
	
		
			1421 Commits
		
	
	
		
			0.1.5
			...
			feature/an
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						8c56aa3c46
	
				 | 
					
					
						|||
| 
						
						
							
						
						1505080afd
	
				 | 
					
					
						|||
| 
						
						
							
						
						f642849dbb
	
				 | 
					
					
						|||
| 
						
						
							
						
						7ac92ae6ca
	
				 | 
					
					
						|||
| 
						
						
							
						
						95af9f9914
	
				 | 
					
					
						|||
| 
						
						
							
						
						1004aee16c
	
				 | 
					
					
						|||
| 
						
						
							
						
						0baf2fc460
	
				 | 
					
					
						|||
| 
						
						
							
						
						09b59175ee
	
				 | 
					
					
						|||
| 
						
						
							
						
						a21f61f3f3
	
				 | 
					
					
						|||
| 
						
						
							
						
						8cb6093f0b
	
				 | 
					
					
						|||
| 
						
						
							
						
						7a92adcd3a
	
				 | 
					
					
						|||
| 
						
						
							
						
						27396e17f2
	
				 | 
					
					
						|||
| 
						
						
							
						
						fefd5c8237
	
				 | 
					
					
						|||
| 
						
						
							
						
						f9993c60f5
	
				 | 
					
					
						|||
| 
						
						
							
						
						8e314f8676
	
				 | 
					
					
						|||
| 
						
						
							
						
						98a3b07237
	
				 | 
					
					
						|||
| 
						
						
							
						
						efad6fdf2e
	
				 | 
					
					
						|||
| 
						
						
							
						
						bce6d484a9
	
				 | 
					
					
						|||
| 
						
						
							
						
						2dea19df89
	
				 | 
					
					
						|||
| 
						
						
							
						
						6c986467d3
	
				 | 
					
					
						|||
| 
						
						
							
						
						3cedbebe40
	
				 | 
					
					
						|||
| 
						
						
							
						
						dc986e4fe5
	
				 | 
					
					
						|||
| 
						
						
							
						
						cae6be6f86
	
				 | 
					
					
						|||
| 
						
						
							
						
						1d6ed99073
	
				 | 
					
					
						|||
| 
						
						
							
						
						1605b0f7b2
	
				 | 
					
					
						|||
| 
						
						
							
						
						244be471f0
	
				 | 
					
					
						|||
| 
						
						
							
						
						a12c4f87d2
	
				 | 
					
					
						|||
| 
						
						
							
						
						312457494c
	
				 | 
					
					
						|||
| 
						
						
							
						
						3288ffb3cc
	
				 | 
					
					
						|||
| 
						
						
							
						
						81a8ce002c
	
				 | 
					
					
						|||
| 
						
						
							
						
						e1bf435080
	
				 | 
					
					
						|||
| 
						
						
							
						
						80ab4e037e
	
				 | 
					
					
						|||
| 
						
						
							
						
						3fab344779
	
				 | 
					
					
						|||
| 
						
						
							
						
						d841727439
	
				 | 
					
					
						|||
| 
						
						
							
						
						87df34bb56
	
				 | 
					
					
						|||
| 
						
						
							
						
						9c3b742a98
	
				 | 
					
					
						|||
| 
						
						
							
						
						68bf3717f9
	
				 | 
					
					
						|||
| 
						
						
							
						
						f88c6e0dba
	
				 | 
					
					
						|||
| 
						
						
							
						
						12050cdda9
	
				 | 
					
					
						|||
| 
						
						
							
						
						01e77a97f3
	
				 | 
					
					
						|||
| 
						
						
							
						
						10824b5d9b
	
				 | 
					
					
						|||
| 
						
						
							
						
						d9870e03bc
	
				 | 
					
					
						|||
| 
						
						
							
						
						785b9e0b60
	
				 | 
					
					
						|||
| 
						
						
							
						
						fce2bc645e
	
				 | 
					
					
						|||
| 
						
						
							
						
						991716a7f5
	
				 | 
					
					
						|||
| 
						
						
							
						
						aa720f2460
	
				 | 
					
					
						|||
| 
						
						
							
						
						ac4ef8fb6d
	
				 | 
					
					
						|||
| 
						
						
							
						
						eae0afda23
	
				 | 
					
					
						|||
| 
						
						
							
						
						5291f8a4d1
	
				 | 
					
					
						|||
| 
						
						
							
						
						e2d7de1e9e
	
				 | 
					
					
						|||
| 
						
						
							
						
						d7c9c27ec7
	
				 | 
					
					
						|||
| 
						
						
							
						
						153b1b3c2b
	
				 | 
					
					
						|||
| 
						
						
							
						
						ec63c7c1c5
	
				 | 
					
					
						|||
| 
						
						
							
						
						05c2535698
	
				 | 
					
					
						|||
| 
						
						
							
						
						e261d5e345
	
				 | 
					
					
						|||
| 
						
						
							
						
						c00497d776
	
				 | 
					
					
						|||
| 
						
						
							
						
						766eeab49f
	
				 | 
					
					
						|||
| 
						
						
							
						
						3c9b404234
	
				 | 
					
					
						|||
| 
						
						
							
						
						9c56b3883e
	
				 | 
					
					
						|||
| 
						
						
							
						
						3d506db975
	
				 | 
					
					
						|||
| 
						
						
							
						
						d7e84a79a8
	
				 | 
					
					
						|||
| 
						
						
							
						
						102471eaaa
	
				 | 
					
					
						|||
| 
						
						
							
						
						90b0fec236
	
				 | 
					
					
						|||
| 
						
						
							
						
						4883e179e7
	
				 | 
					
					
						|||
| 
						
						
							
						
						13c6e96292
	
				 | 
					
					
						|||
| 
						
						
							
						
						f547c0cc81
	
				 | 
					
					
						|||
| 
						
						
							
						
						fbe38eede9
	
				 | 
					
					
						|||
| 
						
						
							
						
						22551c379f
	
				 | 
					
					
						|||
| 
						
						
							
						
						a102af5a78
	
				 | 
					
					
						|||
| 
						
						
							
						
						e9dffcea83
	
				 | 
					
					
						|||
| 
						
						
							
						
						b9563d75dd
	
				 | 
					
					
						|||
| 
						
						
							
						
						3a569422ad
	
				 | 
					
					
						|||
| 
						
						
							
						
						0ee43f80a6
	
				 | 
					
					
						|||
| 
						
						
							
						
						f4542adf3b
	
				 | 
					
					
						|||
| 
						
						
							
						
						9f0623d194
	
				 | 
					
					
						|||
| 
						
						
							
						
						5bab95a942
	
				 | 
					
					
						|||
| 
						
						
							
						
						831f36946d
	
				 | 
					
					
						|||
| 
						
						
							
						
						a4fbabaf9a
	
				 | 
					
					
						|||
| 
						
						
							
						
						04897c7d2e
	
				 | 
					
					
						|||
| 
						
						
							
						
						b7e6fdaeac
	
				 | 
					
					
						|||
| 
						
						
							
						
						481f6b686e
	
				 | 
					
					
						|||
| 
						
						
							
						
						e7a69ebdca
	
				 | 
					
					
						|||
| 
						
						
							
						
						194c3c4886
	
				 | 
					
					
						|||
| 
						
						
							
						
						f5a46aa203
	
				 | 
					
					
						|||
| 
						
						
							
						
						443371e2fd
	
				 | 
					
					
						|||
| 
						
						
							
						
						d7ab9247cd
	
				 | 
					
					
						|||
| 
						
						
							
						
						a2cd54fba4
	
				 | 
					
					
						|||
| 
						
						
							
						
						9048f3df77
	
				 | 
					
					
						|||
| 
						
						
							
						
						fecf3b59a3
	
				 | 
					
					
						|||
| 
						
						
							
						
						18a4623e71
	
				 | 
					
					
						|||
| 
						
						
							
						
						968a7ccc0e
	
				 | 
					
					
						|||
| 
						
						
							
						
						6249502a88
	
				 | 
					
					
						|||
| 
						
						
							
						
						8a78034079
	
				 | 
					
					
						|||
| 
						
						
							
						
						7633b7b056
	
				 | 
					
					
						|||
| 
						
						
							
						
						b8e6b24bf3
	
				 | 
					
					
						|||
| 
						
						
							
						
						97b7ca931f
	
				 | 
					
					
						|||
| 
						
						
							
						
						48dd9acde5
	
				 | 
					
					
						|||
| 
						
						
							
						
						5147a20b3c
	
				 | 
					
					
						|||
| 
						
						
							
						
						bb2319a78d
	
				 | 
					
					
						|||
| 
						
						
							
						
						7c10d95c1c
	
				 | 
					
					
						|||
| 
						
						
							
						
						f734d1e3f6
	
				 | 
					
					
						|||
| 
						
						
							
						
						e567bb35c3
	
				 | 
					
					
						|||
| 
						
						
							
						
						3ec18a6964
	
				 | 
					
					
						|||
| 
						
						
							
						
						847fa288f1
	
				 | 
					
					
						|||
| 
						
						
							
						
						824ecfab2e
	
				 | 
					
					
						|||
| 
						
						
							
						
						5f5d8277b9
	
				 | 
					
					
						|||
| 
						
						
							
						
						0a6cf619b0
	
				 | 
					
					
						|||
| 
						
						
							
						
						050a146ae0
	
				 | 
					
					
						|||
| 
						
						
							
						
						1bc53146b9
	
				 | 
					
					
						|||
| 
						
						
							
						
						e82350df4a
	
				 | 
					
					
						|||
| 
						
						
							
						
						3d3ce2918b
	
				 | 
					
					
						|||
| 
						
						
							
						
						79e6a4212d
	
				 | 
					
					
						|||
| 
						
						
							
						
						37cdbba0a3
	
				 | 
					
					
						|||
| 
						
						
							
						
						c37fb98bed
	
				 | 
					
					
						|||
| 
						
						
							
						
						975f145444
	
				 | 
					
					
						|||
| 
						
						
							
						
						391186d01f
	
				 | 
					
					
						|||
| 
						
						
							
						
						ae056cd88c
	
				 | 
					
					
						|||
| 
						
						
							
						
						7f989b206b
	
				 | 
					
					
						|||
| 
						
						
							
						
						65ce02e777
	
				 | 
					
					
						|||
| 
						
						
							
						
						878d9714cb
	
				 | 
					
					
						|||
| 
						
						
							
						
						f99b7f4bb8
	
				 | 
					
					
						|||
| 
						
						
							
						
						e23098410c
	
				 | 
					
					
						|||
| 
						
						
							
						
						04494d2a2a
	
				 | 
					
					
						|||
| 
						
						
							
						
						e2d6fbb513
	
				 | 
					
					
						|||
| 
						
						
							
						
						477c650f3f
	
				 | 
					
					
						|||
| 
						
						
							
						
						fc15c68cba
	
				 | 
					
					
						|||
| 
						
						
							
						
						32b5f5420b
	
				 | 
					
					
						|||
| 
						
						
							
						
						ee87f82799
	
				 | 
					
					
						|||
| 
						
						
							
						
						7c08f522aa
	
				 | 
					
					
						|||
| 
						
						
							
						
						e211554579
	
				 | 
					
					
						|||
| 
						
						
							
						
						7ba890dfd7
	
				 | 
					
					
						|||
| 
						
						
							
						
						68b4309164
	
				 | 
					
					
						|||
| 
						
						
							
						
						d803f3d490
	
				 | 
					
					
						|||
| 
						
						
							
						
						5468766d87
	
				 | 
					
					
						|||
| 
						
						
							
						
						e967d8d20c
	
				 | 
					
					
						|||
| 
						
						
							
						
						ad4db882f0
	
				 | 
					
					
						|||
| 
						
						
							
						
						84aa846b87
	
				 | 
					
					
						|||
| 
						
						
							
						
						3532968b33
	
				 | 
					
					
						|||
| 
						
						
							
						
						6bb49db4ee
	
				 | 
					
					
						|||
| 
						
						
							
						
						38fb111f7a
	
				 | 
					
					
						|||
| 
						
						
							
						
						a50447f457
	
				 | 
					
					
						|||
| 
						
						
							
						
						b1a2044631
	
				 | 
					
					
						|||
| 
						
						
							
						
						c883920caa
	
				 | 
					
					
						|||
| 
						
						
							
						
						21453ef272
	
				 | 
					
					
						|||
| 
						
						
							
						
						10182433f8
	
				 | 
					
					
						|||
| 
						
						
							
						
						b338f33a63
	
				 | 
					
					
						|||
| 
						
						
							
						
						cb82200481
	
				 | 
					
					
						|||
| 
						
						
							
						
						9abf74d6d2
	
				 | 
					
					
						|||
| 
						
						
							
						
						50e81a6cb5
	
				 | 
					
					
						|||
| 
						
						
							
						
						8fae1fb6b3
	
				 | 
					
					
						|||
| 
						
						
							
						
						372fa110ec
	
				 | 
					
					
						|||
| 
						
						
							
						
						35bec9fe58
	
				 | 
					
					
						|||
| 
						
						
							
						
						93d67bdba9
	
				 | 
					
					
						|||
| 
						
						
							
						
						a5e72a18e3
	
				 | 
					
					
						|||
| 
						
						
							
						
						91d2f46b93
	
				 | 
					
					
						|||
| 
						
						
							
						
						c60bae4533
	
				 | 
					
					
						|||
| 
						
						
							
						
						43ac878d44
	
				 | 
					
					
						|||
| 
						
						
							
						
						ceabd06a43
	
				 | 
					
					
						|||
| 
						
						
							
						
						9bfc0c5338
	
				 | 
					
					
						|||
| 
						
						
							
						
						fb8206ff13
	
				 | 
					
					
						|||
| 
						
						
							
						
						dceb0ef461
	
				 | 
					
					
						|||
| 
						
						
							
						
						88bc1982ca
	
				 | 
					
					
						|||
| 
						
						
							
						
						e741a9d7e7
	
				 | 
					
					
						|||
| 
						
						
							
						
						65f1d22205
	
				 | 
					
					
						|||
| 
						
						
							
						
						d867c08aba
	
				 | 
					
					
						|||
| 6193eff38e | |||
| 
						
						
							
						
						f1929e7cf9
	
				 | 
					
					
						|||
| 
						
						
							
						
						373484c242
	
				 | 
					
					
						|||
| 
						
						
							
						
						f77460bb0c
	
				 | 
					
					
						|||
| 
						
						
							
						
						574e0dcb05
	
				 | 
					
					
						|||
| 
						
						
							
						
						7b19a0aa08
	
				 | 
					
					
						|||
| 08642d7618 | |||
| 
						
						
							
						
						c3e9c27cd3
	
				 | 
					
					
						|||
| 
						
						
							
						
						29a2854671
	
				 | 
					
					
						|||
| 
						
						
							
						
						8e6786e722
	
				 | 
					
					
						|||
| 
						
						
							
						
						6ad40564e3
	
				 | 
					
					
						|||
| 
						
						
							
						
						776973bfe9
	
				 | 
					
					
						|||
| 
						
						
							
						
						6025e43baa
	
				 | 
					
					
						|||
| 
						
						
							
						
						d9a47f882c
	
				 | 
					
					
						|||
| 
						
						
							
						
						4235758a6d
	
				 | 
					
					
						|||
| 
						
						
							
						
						59fe2dfabb
	
				 | 
					
					
						|||
| 
						
						
							
						
						6364536dcd
	
				 | 
					
					
						|||
| 
						
						
							
						
						a8a771114d
	
				 | 
					
					
						|||
| 
						
						
							
						
						4e0a2c8301
	
				 | 
					
					
						|||
| 
						
						
							
						
						b6fed92a17
	
				 | 
					
					
						|||
| 
						
						
							
						
						97b57aeb0c
	
				 | 
					
					
						|||
| 
						
						
							
						
						e25ed1fff9
	
				 | 
					
					
						|||
| 
						
						
							
						
						a2ff5b8a14
	
				 | 
					
					
						|||
| 
						
						
							
						
						0284f18beb
	
				 | 
					
					
						|||
| 
						
						
							
						
						803d64c78c
	
				 | 
					
					
						|||
| 
						
						
							
						
						dacb2f8ace
	
				 | 
					
					
						|||
| 
						
						
							
						
						b7a53960e5
	
				 | 
					
					
						|||
| 
						
						
							
						
						66f1e6b4fe
	
				 | 
					
					
						|||
| 
						
						
							
						
						33166bfafc
	
				 | 
					
					
						|||
| 
						
						
							
						
						b2648645e8
	
				 | 
					
					
						|||
| 
						
						
							
						
						53e3ddb751
	
				 | 
					
					
						|||
| 
						
						
							
						
						edc2dcab92
	
				 | 
					
					
						|||
| 
						
						
							
						
						d49f545d94
	
				 | 
					
					
						|||
| 
						
						
							
						
						3b98c99b72
	
				 | 
					
					
						|||
| 
						
						
							
						
						1da775a09b
	
				 | 
					
					
						|||
| 
						
						
							
						
						f0475bd9a0
	
				 | 
					
					
						|||
| 
						
						
							
						
						15d8afefbb
	
				 | 
					
					
						|||
| 
						
						
							
						
						f3bcc01685
	
				 | 
					
					
						|||
| 
						
						
							
						
						95238606d5
	
				 | 
					
					
						|||
| 
						
						
							
						
						bbf8170cb9
	
				 | 
					
					
						|||
| 8c628f23dc | |||
| 
						
						
							
						
						811f5d5754
	
				 | 
					
					
						|||
| 
						
						
							
						
						69ec7fc1fe
	
				 | 
					
					
						|||
| 
						
						
							
						
						064197d222
	
				 | 
					
					
						|||
| 
						
						
							
						
						e9cf2bc849
	
				 | 
					
					
						|||
| 
						
						
							
						
						103ad57ddc
	
				 | 
					
					
						|||
| 
						
						
							
						
						2856c5c1b7
	
				 | 
					
					
						|||
| 
						
						
							
						
						a953349c14
	
				 | 
					
					
						|||
| 
						
						
							
						
						175d86745f
	
				 | 
					
					
						|||
| 
						
						
							
						
						081a141218
	
				 | 
					
					
						|||
| 
						
						
							
						
						e904ab0b84
	
				 | 
					
					
						|||
| 
						
						
							
						
						a2f9dbbe01
	
				 | 
					
					
						|||
| 
						
						
							
						
						8b922309b9
	
				 | 
					
					
						|||
| 
						
						
							
						
						4c81e3c432
	
				 | 
					
					
						|||
| 
						
						
							
						
						6c1a707166
	
				 | 
					
					
						|||
| 
						
						
							
						
						7d8253618b
	
				 | 
					
					
						|||
| 
						
						
							
						
						dbaf85799a
	
				 | 
					
					
						|||
| 
						
						
							
						
						daeea24e0e
	
				 | 
					
					
						|||
| 
						
						
							
						
						0fca0352c5
	
				 | 
					
					
						|||
| 
						
						
							
						
						8eaad8219a
	
				 | 
					
					
						|||
| 
						
						
							
						
						6bc92f4a08
	
				 | 
					
					
						|||
| 
						
						
							
						
						8be40e2d80
	
				 | 
					
					
						|||
| 
						
						
							
						
						01b415d4cb
	
				 | 
					
					
						|||
| 
						
						
							
						
						5e82638f35
	
				 | 
					
					
						|||
| 
						
						
							
						
						46d076af9d
	
				 | 
					
					
						|||
| 38a665024e | |||
| 
						
						
							
						
						d32eb8266b
	
				 | 
					
					
						|||
| 
						
						
							
						
						bc4ac0f316
	
				 | 
					
					
						|||
| 
						
						
							
						
						6952b8727f
	
				 | 
					
					
						|||
| 
						
						
							
						
						81d4da6550
	
				 | 
					
					
						|||
| 
						
						
							
						
						6154ca7ddf
	
				 | 
					
					
						|||
| 
						
						
							
						
						8fb1e0ca0f
	
				 | 
					
					
						|||
| 
						
						
							
						
						763a01af09
	
				 | 
					
					
						|||
| 
						
						
							
						
						663cb29ccd
	
				 | 
					
					
						|||
| 
						
						
							
						
						56c3365656
	
				 | 
					
					
						|||
| 
						
						
							
						
						e7b2c64798
	
				 | 
					
					
						|||
| 
						
						
							
						
						7cb6b63eb9
	
				 | 
					
					
						|||
| 
						
						
							
						
						d6d88f5f60
	
				 | 
					
					
						|||
| 
						
						
							
						
						2c208c4381
	
				 | 
					
					
						|||
| 
						
						
							
						
						39bc6c4945
	
				 | 
					
					
						|||
| 
						
						
							
						
						b94e3b745f
	
				 | 
					
					
						|||
| 
						
						
							
						
						6f337aeee1
	
				 | 
					
					
						|||
| 
						
						
							
						
						5d48060834
	
				 | 
					
					
						|||
| 
						
						
							
						
						c842c203e2
	
				 | 
					
					
						|||
| 
						
						
							
						
						5bcfc8db75
	
				 | 
					
					
						|||
| 
						
						
							
						
						27b4dde755
	
				 | 
					
					
						|||
| 
						
						
							
						
						91ab199769
	
				 | 
					
					
						|||
| 
						
						
							
						
						e75be49be4
	
				 | 
					
					
						|||
| 
						
						
							
						
						505fb8cb08
	
				 | 
					
					
						|||
| 
						
						
							
						
						e5c9265588
	
				 | 
					
					
						|||
| 
						
						
							
						
						02003ec80e
	
				 | 
					
					
						|||
| 
						
						
							
						
						133470b6f2
	
				 | 
					
					
						|||
| 
						
						
							
						
						4a6230c439
	
				 | 
					
					
						|||
| 
						
						
							
						
						fdc7d80bbf
	
				 | 
					
					
						|||
| 
						
						
							
						
						352551e168
	
				 | 
					
					
						|||
| 
						
						
							
						
						7aec050419
	
				 | 
					
					
						|||
| 4289034436 | |||
| 
						
						
							
						
						8f8858f100
	
				 | 
					
					
						|||
| 
						
						
							
						
						d98fb0d5b2
	
				 | 
					
					
						|||
| 
						
						
							
						
						5014bf5bc5
	
				 | 
					
					
						|||
| 
						
						
							
						
						0708cabc75
	
				 | 
					
					
						|||
| 
						
						
							
						
						4fcb26cf93
	
				 | 
					
					
						|||
| 
						
						
							
						
						269def20d1
	
				 | 
					
					
						|||
| 
						
						
							
						
						b8de9e0e42
	
				 | 
					
					
						|||
| 
						
						
							
						
						7b2b598588
	
				 | 
					
					
						|||
| 
						
						
							
						
						e0b61486b0
	
				 | 
					
					
						|||
| 
						
						
							
						
						3f86f7412f
	
				 | 
					
					
						|||
| 
						
						
							
						
						6454d960de
	
				 | 
					
					
						|||
| 
						
						
							
						
						37154c188b
	
				 | 
					
					
						|||
| 
						
						
							
						
						8da7578a0a
	
				 | 
					
					
						|||
| 2a64094006 | |||
| e9ce9644ff | |||
| 
						
						
							
						
						52439aa5bc
	
				 | 
					
					
						|||
| 
						
						
							
						
						ccf865687b
	
				 | 
					
					
						|||
| 
						
						
							
						
						cac34db1fd
	
				 | 
					
					
						|||
| 
						
						
							
						
						faf3893180
	
				 | 
					
					
						|||
| 
						
						
							
						
						c33dfcfddd
	
				 | 
					
					
						|||
| 
						
						
							
						
						019e14ab1f
	
				 | 
					
					
						|||
| 
						
						
							
						
						b5790196c6
	
				 | 
					
					
						|||
| 
						
						
							
						
						94a64ca690
	
				 | 
					
					
						|||
| a6ce04c903 | |||
| 165c154233 | |||
| 
						
						
							
						
						318547db46
	
				 | 
					
					
						|||
| 
						
						
							
						
						e60c09e19c
	
				 | 
					
					
						|||
| 
						
						
							
						
						4834d1484c
	
				 | 
					
					
						|||
| 
						
						
							
						
						4b6342727e
	
				 | 
					
					
						|||
| 
						
						
							
						
						cb5fa52cd9
	
				 | 
					
					
						|||
| 
						
						
							
						
						947d01cf7f
	
				 | 
					
					
						|||
| 
						
						
							
						
						3563394fb3
	
				 | 
					
					
						|||
| 
						
						
							
						
						269d7a7def
	
				 | 
					
					
						|||
| 
						
						
							
						
						e95f2333b0
	
				 | 
					
					
						|||
| 
						
						
							
						
						950217e0a3
	
				 | 
					
					
						|||
| 
						
						
							
						
						5e65fb3301
	
				 | 
					
					
						|||
| 
						
						
							
						
						2a294cde04
	
				 | 
					
					
						|||
| 
						
						
							
						
						e95420d79c
	
				 | 
					
					
						|||
| 
						
						
							
						
						cffbd17dc7
	
				 | 
					
					
						|||
| 
						
						
							
						
						00de8c3d75
	
				 | 
					
					
						|||
| 
						
						
							
						
						1f4711d07a
	
				 | 
					
					
						|||
| 
						
						
							
						
						30e3396897
	
				 | 
					
					
						|||
| 
						
						
							
						
						5291e049a1
	
				 | 
					
					
						|||
| 
						
						
							
						
						08fbb504c9
	
				 | 
					
					
						|||
| 
						
						
							
						
						e9ca1d3e5d
	
				 | 
					
					
						|||
| 
						
						
							
						
						eb80406fdb
	
				 | 
					
					
						|||
| 
						
						
							
						
						9fe53b0b9c
	
				 | 
					
					
						|||
| 
						
						
							
						
						9ae5e62e5d
	
				 | 
					
					
						|||
| 
						
						
							
						
						1613ae7de6
	
				 | 
					
					
						|||
| ed1caa7be7 | |||
| d88f3a5a27 | |||
| 
						
						
							
						
						c98eb49ae3
	
				 | 
					
					
						|||
| 
						
						
							
						
						6d9d8a4724
	
				 | 
					
					
						|||
| 
						
						
							
						
						7d8c68a455
	
				 | 
					
					
						|||
| 
						
						
							
						
						8f33640bec
	
				 | 
					
					
						|||
| 
						
						
							
						
						f89023e24a
	
				 | 
					
					
						|||
| 
						
						
							
						
						f5d14f2e18
	
				 | 
					
					
						|||
| 
						
						
							
						
						9811ede3b2
	
				 | 
					
					
						|||
| 
						
						
							
						
						b2e51fea48
	
				 | 
					
					
						|||
| 
						
						
							
						
						2a915620c9
	
				 | 
					
					
						|||
| 
						
						
							
						
						526688935f
	
				 | 
					
					
						|||
| 
						
						
							
						
						c7dcf7c66d
	
				 | 
					
					
						|||
| 
						
						
							
						
						06411dc147
	
				 | 
					
					
						|||
| 
						
						
							
						
						195d182cc9
	
				 | 
					
					
						|||
| 
						
						
							
						
						17217dae76
	
				 | 
					
					
						|||
| 
						
						
							
						
						f105cc0a41
	
				 | 
					
					
						|||
| 
						
						
							
						
						2f62c7ae89
	
				 | 
					
					
						|||
| 
						
						
							
						
						f6c1fea17c
	
				 | 
					
					
						|||
| 
						
						
							
						
						178dc93319
	
				 | 
					
					
						|||
| 
						
						
							
						
						8ffe8eff06
	
				 | 
					
					
						|||
| 
						
						
							
						
						bd4952ee57
	
				 | 
					
					
						|||
| 
						
						
							
						
						4b171fd04f
	
				 | 
					
					
						|||
| 
						
						
							
						
						2c198cfde8
	
				 | 
					
					
						|||
| 
						
						
							
						
						7c6d39b5fa
	
				 | 
					
					
						|||
| 
						
						
							
						
						9c13b2f9e9
	
				 | 
					
					
						|||
| 
						
						
							
						
						1ec9556aa6
	
				 | 
					
					
						|||
| 
						
						
							
						
						adec38b50b
	
				 | 
					
					
						|||
| 
						
						
							
						
						a35af6f020
	
				 | 
					
					
						|||
| 
						
						
							
						
						e74ff5e885
	
				 | 
					
					
						|||
| 
						
						
							
						
						c87561f63b
	
				 | 
					
					
						|||
| 
						
						
							
						
						c681570134
	
				 | 
					
					
						|||
| 
						
						
							
						
						53b945c72f
	
				 | 
					
					
						|||
| 
						
						
							
						
						f6985daec7
	
				 | 
					
					
						|||
| 
						
						
							
						
						5662c3b6da
	
				 | 
					
					
						|||
| 
						
						
							
						
						9def0b27c9
	
				 | 
					
					
						|||
| 
						
						
							
						
						52a02c82d2
	
				 | 
					
					
						|||
| 
						
						
							
						
						c241961d0a
	
				 | 
					
					
						|||
| 
						
						
							
						
						8f50555a06
	
				 | 
					
					
						|||
| 
						
						
							
						
						b35375c929
	
				 | 
					
					
						|||
| 
						
						
							
						
						bf1e715261
	
				 | 
					
					
						|||
| 
						
						
							
						
						0240e1dca2
	
				 | 
					
					
						|||
| 
						
						
							
						
						7cec2a00c5
	
				 | 
					
					
						|||
| 
						
						
							
						
						239f79fecb
	
				 | 
					
					
						|||
| 
						
						
							
						
						0265a59b82
	
				 | 
					
					
						|||
| 
						
						
							
						
						57dce34fc5
	
				 | 
					
					
						|||
| 
						
						
							
						
						d8110580e9
	
				 | 
					
					
						|||
| 
						
						
							
						
						03b7ada5ef
	
				 | 
					
					
						|||
| 
						
						
							
						
						1df505ea00
	
				 | 
					
					
						|||
| 
						
						
							
						
						3e8dac3203
	
				 | 
					
					
						|||
| 
						
						
							
						
						95707a71a9
	
				 | 
					
					
						|||
| 
						
						
							
						
						fc2c2907c4
	
				 | 
					
					
						|||
| 
						
						
							
						
						ebdd1c2c0c
	
				 | 
					
					
						|||
| 
						
						
							
						
						13254b24dd
	
				 | 
					
					
						|||
| 
						
						
							
						
						e17eb64031
	
				 | 
					
					
						|||
| 
						
						
							
						
						a0727a0291
	
				 | 
					
					
						|||
| 
						
						
							
						
						f7f7926829
	
				 | 
					
					
						|||
| 
						
						
							
						
						9b7dca341b
	
				 | 
					
					
						|||
| 
						
						
							
						
						da3300562a
	
				 | 
					
					
						|||
| 
						
						
							
						
						e2ddb5a14c
	
				 | 
					
					
						|||
| 
						
						
							
						
						fb9645aed6
	
				 | 
					
					
						|||
| 
						
						
							
						
						a4ebc7e126
	
				 | 
					
					
						|||
| 
						
						
							
						
						fd5db7d68a
	
				 | 
					
					
						|||
| 
						
						
							
						
						e7eddb4f08
	
				 | 
					
					
						|||
| 
						
						
							
						
						94155845f0
	
				 | 
					
					
						|||
| 
						
						
							
						
						3abf608b15
	
				 | 
					
					
						|||
| 
						
						
							
						
						d31fe2363b
	
				 | 
					
					
						|||
| 
						
						
							
						
						11a56f87e8
	
				 | 
					
					
						|||
| 
						
						
							
						
						19793cdcd4
	
				 | 
					
					
						|||
| 
						
						
							
						
						9363773fa1
	
				 | 
					
					
						|||
| 
						
						
							
						
						c7990882cf
	
				 | 
					
					
						|||
| 
						
						
							
						
						d4ab76ea1b
	
				 | 
					
					
						|||
| 
						
						
							
						
						2c992a0e63
	
				 | 
					
					
						|||
| 
						
						
							
						
						88f96acc3c
	
				 | 
					
					
						|||
| 
						
						
							
						
						245db06173
	
				 | 
					
					
						|||
| 
						
						
							
						
						49c2cd5c4b
	
				 | 
					
					
						|||
| 
						
						
							
						
						64db553185
	
				 | 
					
					
						|||
| 
						
						
							
						
						a06a19ce9c
	
				 | 
					
					
						|||
| 
						
						
							
						
						592ddc1541
	
				 | 
					
					
						|||
| 
						
						
							
						
						cb5f2b73d0
	
				 | 
					
					
						|||
| 
						
						
							
						
						2304b12c1c
	
				 | 
					
					
						|||
| 
						
						
							
						
						38d3e1912c
	
				 | 
					
					
						|||
| 
						
						
							
						
						fbc14fd7b4
	
				 | 
					
					
						|||
| 
						
						
							
						
						0283df22c8
	
				 | 
					
					
						|||
| 
						
						
							
						
						845737ee8e
	
				 | 
					
					
						|||
| 
						
						
							
						
						6993511c67
	
				 | 
					
					
						|||
| 
						
						
							
						
						9111ad147c
	
				 | 
					
					
						|||
| 
						
						
							
						
						333214aa8f
	
				 | 
					
					
						|||
| 
						
						
							
						
						c0cde02fec
	
				 | 
					
					
						|||
| 
						
						
							
						
						070a20a2e5
	
				 | 
					
					
						|||
| 
						
						
							
						
						c5e8409079
	
				 | 
					
					
						|||
| 
						
						
							
						
						67eff0eda9
	
				 | 
					
					
						|||
| 
						
						
							
						
						3de7b632e0
	
				 | 
					
					
						|||
| 
						
						
							
						
						842248e4c4
	
				 | 
					
					
						|||
| 
						
						
							
						
						c5d7ec25b5
	
				 | 
					
					
						|||
| 
						
						
							
						
						a9a965d698
	
				 | 
					
					
						|||
| 
						
						
							
						
						dc866dd540
	
				 | 
					
					
						|||
| 
						
						
							
						
						89252619b1
	
				 | 
					
					
						|||
| 
						
						
							
						
						2699b06d7c
	
				 | 
					
					
						|||
| 
						
						
							
						
						fd0d45f721
	
				 | 
					
					
						|||
| 
						
						
							
						
						5ecf838dd2
	
				 | 
					
					
						|||
| 
						
						
							
						
						45a7a90cb8
	
				 | 
					
					
						|||
| 
						
						
							
						
						cac851f2b1
	
				 | 
					
					
						|||
| 
						
						
							
						
						238082b657
	
				 | 
					
					
						|||
| 
						
						
							
						
						aecbabe522
	
				 | 
					
					
						|||
| 
						
						
							
						
						a9cdac4f74
	
				 | 
					
					
						|||
| 
						
						
							
						
						a59dbbe50e
	
				 | 
					
					
						|||
| 
						
						
							
						
						9bec95ede8
	
				 | 
					
					
						|||
| 
						
						
							
						
						70307a9e82
	
				 | 
					
					
						|||
| 
						
						
							
						
						ef077b4e6a
	
				 | 
					
					
						|||
| 
						
						
							
						
						dcabed4e93
	
				 | 
					
					
						|||
| 
						
						
							
						
						1af047f66e
	
				 | 
					
					
						|||
| 
						
						
							
						
						ee91748b3c
	
				 | 
					
					
						|||
| 
						
						
							
						
						e5241d619b
	
				 | 
					
					
						|||
| 
						
						
							
						
						d79608edbb
	
				 | 
					
					
						|||
| 
						
						
							
						
						4cbd26580e
	
				 | 
					
					
						|||
| 
						
						
							
						
						fe62ad5539
	
				 | 
					
					
						|||
| 
						
						
							
						
						eb13f038a1
	
				 | 
					
					
						|||
| 9505c2b030 | |||
| 008835c24f | |||
| 7083b3d8d2 | |||
| 754931b2f6 | |||
| 2dc8ffba32 | |||
| d0fe6a2e85 | |||
| 85705b6e68 | |||
| 3ea7a015a9 | |||
| 44329413ed | |||
| 46db68ab22 | |||
| dc9d7f22a2 | |||
| f917018fd9 | |||
| 7b420c430d | |||
| 00359d25c1 | |||
| d8a3063735 | |||
| 
						
						
							
						
						6491af19e3
	
				 | 
					
					
						|||
| 61328d20ed | |||
| 
						
						
							
						
						0a6d92a1f3
	
				 | 
					
					
						|||
| 
						
						
							
						
						3a576d1073
	
				 | 
					
					
						|||
| 
						
						
							
						
						b30b98b521
	
				 | 
					
					
						|||
| 
						
						
							
						
						43d82a2af0
	
				 | 
					
					
						|||
| 6a4495b813 | |||
| 
						
						
							
						
						e8a0ad6647
	
				 | 
					
					
						|||
| 
						
						
							
						
						92b89cc4d8
	
				 | 
					
					
						|||
| 
						
						
							
						
						268b1b1d98
	
				 | 
					
					
						|||
| 
						
						
							
						
						75bc89ca30
	
				 | 
					
					
						|||
| 0625937068 | |||
| 
						
						
							
						
						32a9074963
	
				 | 
					
					
						|||
| 
						
						
							
						
						b869b5fd2a
	
				 | 
					
					
						|||
| 3a3e2f7157 | |||
| bea57aa03a | |||
| 30991d5364 | |||
| 5cc8b0811c | |||
| 2c73b9862d | |||
| 732b2f061e | |||
| 3680533eef | |||
| 1307d72c9d | |||
| 405dfa0c34 | |||
| 5c2d154ad1 | |||
| f2bf8d9bac | |||
| 
						
						
							
						
						f9cfd6bd06
	
				 | 
					
					
						|||
| 
						
						
							
						
						287f63fa52
	
				 | 
					
					
						|||
| 
						
						
							
						
						5fe47634e8
	
				 | 
					
					
						|||
| a6590910cf | |||
| ad454c386c | |||
| 
						
						
							
						
						0b2c296de0
	
				 | 
					
					
						|||
| 
						
						
							
						
						0e85940cba
	
				 | 
					
					
						|||
| 8d479c32f8 | |||
| 549785cf7d | |||
| 
						
						
							
						
						aafc4c8d62
	
				 | 
					
					
						|||
| 
						
						
							
						
						47dedbdc73
	
				 | 
					
					
						|||
| 
						
						
							
						
						6fe134afc8
	
				 | 
					
					
						|||
| 
						
						
							
						
						63a50f92e7
	
				 | 
					
					
						|||
| 
						
						
							
						
						ca6da15ef7
	
				 | 
					
					
						|||
| 
						
						
							
						
						8dfa19fa0f
	
				 | 
					
					
						|||
| 
						
						
							
						
						0feee0ae2f
	
				 | 
					
					
						|||
| 2a6a39916a | |||
| 
						
						
							
						
						f0a2b2859f
	
				 | 
					
					
						|||
| 
						
						
							
						
						32ddb66fc8
	
				 | 
					
					
						|||
| 
						
						
							
						
						df63c2388d
	
				 | 
					
					
						|||
| 
						
						
							
						
						757655ea63
	
				 | 
					
					
						|||
| 329c1cc037 | |||
| da6dd55d13 | |||
| 0e5490f1c8 | |||
| b82d638de1 | |||
| 224034dcc6 | |||
| 026d3d41c1 | |||
| fd1a06b359 | |||
| 
						
						
							
						
						452d010183
	
				 | 
					
					
						|||
| 
						
						
							
						
						eb1c17e3ac
	
				 | 
					
					
						|||
| 
						
						
							
						
						a101873eb0
	
				 | 
					
					
						|||
| 
						
						
							
						
						3d2acb692a
	
				 | 
					
					
						|||
| 
						
						
							
						
						0900c2691e
	
				 | 
					
					
						|||
| 
						
						
							
						
						1337676e08
	
				 | 
					
					
						|||
| 2e075eafab | |||
| 14d64b6070 | |||
| 81b8fbf4e3 | |||
| 24d074752f | |||
| 08047a9307 | |||
| 1b0cd5b90b | |||
| 65e8998894 | |||
| 449948050b | |||
| cf97281592 | |||
| 75684efa1a | |||
| 2c4f27a943 | |||
| 53b7dec7cd | |||
| 
						
						
							
						
						e0cbfb000b
	
				 | 
					
					
						|||
| 3a66f4c862 | |||
| 
						
						
							
						
						85ceaa464f
	
				 | 
					
					
						|||
| 
						
						
							
						
						976755338b
	
				 | 
					
					
						|||
| 
						
						
							
						
						1c980059cf
	
				 | 
					
					
						|||
| 
						
						
							
						
						2d8c4c1698
	
				 | 
					
					
						|||
| 
						
						
							
						
						19a333d7bd
	
				 | 
					
					
						|||
| 
						
						
							
						
						96c55db63d
	
				 | 
					
					
						|||
| 
						
						
							
						
						fecb07ee37
	
				 | 
					
					
						|||
| 
						
						
							
						
						e10c6480a5
	
				 | 
					
					
						|||
| 
						
						
							
						
						f3cc07c009
	
				 | 
					
					
						|||
| 
						
						
							
						
						068076dd47
	
				 | 
					
					
						|||
| 
						
						
							
						
						02158605be
	
				 | 
					
					
						|||
| 
						
						
							
						
						674e6a90ec
	
				 | 
					
					
						|||
| 
						
						
							
						
						f679330466
	
				 | 
					
					
						|||
| 
						
						
							
						
						93fc7c2e83
	
				 | 
					
					
						|||
| 
						
						
							
						
						f299617c60
	
				 | 
					
					
						|||
| 
						
						
							
						
						28cbc5b98c
	
				 | 
					
					
						|||
| 
						
						
							
						
						c28f1ee0bc
	
				 | 
					
					
						|||
| 
						
						
							
						
						cff112d705
	
				 | 
					
					
						|||
| 9fc4ad63c4 | |||
| 97054a71c1 | |||
| 
						
						
							
						
						2391668a25
	
				 | 
					
					
						|||
| 717d33547c | |||
| 997be32679 | |||
| 
						
						
							
						
						134f00c40e
	
				 | 
					
					
						|||
| 
						
						
							
						
						47c898bdfd
	
				 | 
					
					
						|||
| e752ee12d1 | |||
| 
						
						
							
						
						cc4515ff66
	
				 | 
					
					
						|||
| f190292171 | |||
| 
						
						
							
						
						b246f2b349
	
				 | 
					
					
						|||
| 76b69d851a | |||
| 224f586368 | |||
| 9add6c8ff1 | |||
| 7a63d4eed1 | |||
| e54a4807f7 | |||
| cee04c1d6f | |||
| cbec78589d | |||
| a85db7cb3f | |||
| 2bd3779839 | |||
| 303e33cafb | |||
| b4e689dddf | |||
| 98a0b036c5 | |||
| fb3f30fb10 | |||
| 6213952007 | |||
| 07ac041d69 | |||
| 5c02028841 | |||
| c561b53670 | |||
| dcd0d5a362 | |||
| 18acac83bc | |||
| d7d44470bb | |||
| 0f0aae7ba4 | |||
| 4c0886a5d9 | |||
| 04a3038369 | |||
| bdcf5d3fc0 | |||
| c7a858eed7 | |||
| de5aa9237d | |||
| d015f97395 | |||
| 57618156b4 | |||
| 865254d646 | |||
| 1dbab03fe7 | |||
| a943aaf5fc | |||
| 6e6e8b2617 | |||
| 4c2c24af2c | |||
| 3d3a10aafb | |||
| 000fc97beb | |||
| 5645eeaafa | |||
| 961477d522 | |||
| a5f71015a6 | |||
| e42ea943b7 | |||
| 9c5fc6b61c | |||
| 302caf015f | |||
| e11296071a | |||
| 112eb29f93 | |||
| c6c97516b3 | |||
| 03676b2894 | |||
| 9ca57fac2e | |||
| 18f151c1fb | |||
| e90e56d8b2 | |||
| d241ca5698 | |||
| b512cf8667 | |||
| a24d2923c6 | |||
| 467808abef | |||
| 861f1f2216 | |||
| 509b22bea0 | |||
| 7447b2f4c1 | |||
| fef14b6e4f | |||
| 01d2a7e6aa | |||
| ac586fec5a | |||
| 5476808683 | |||
| 331d737796 | |||
| ef81b8adf9 | |||
| 8a7d635cef | |||
| 4c259c1eef | |||
| 5b4ede5e2f | |||
| d0ab3dda78 | |||
| d9cf51b4bb | |||
| aa17f24220 | |||
| cf60edf7d4 | |||
| ffbc243194 | |||
| b6b07cf30c | |||
| 495a6b22bd | |||
| 0acaffbdfa | |||
| 6043bc4517 | |||
| e6ed066e3f | |||
| ee4e8655b8 | |||
| 37970d2be6 | |||
| 1376788016 | |||
| 4cad86cf85 | |||
| 6304116edb | |||
| 834ff8fa63 | |||
| 1f428a535e | |||
| 0c40966970 | |||
| 9da071fe9b | |||
| 892a04f289 | |||
| 27cc9727f1 | |||
| f0738d451b | |||
| 9e6a8daf2c | |||
| bfacfec765 | |||
| 0bae5bf32b | |||
| 22b09d16d0 | |||
| 9c867e106e | |||
| 304f28a3c1 | |||
| d65d3793de | |||
| 3638d87bd2 | |||
| b97a92860d | |||
| 7c86a5eeb3 | |||
| d23dbaaf69 | |||
| e6ffc371e1 | |||
| 3177c6eaa3 | |||
| acd2f0519d | |||
| 18ec100c33 | |||
| fa55fce76e | |||
| f47d5e347d | |||
| 7488a8b597 | |||
| 2e3ac154be | |||
| 2472640755 | |||
| 7b685d6cad | |||
| 17f6f4e616 | |||
| 48cfc15cfb | |||
| bb9b779cee | |||
| af63ce67ae | |||
| 5cc4871ec4 | |||
| c8cfe669b8 | |||
| 8b74d6d759 | |||
| a9227768de | |||
| d966e1d4de | |||
| ceb2146c1b | |||
| 8d006d8c74 | |||
| 777304f259 | |||
| 12433f7c23 | |||
| 44b53da345 | |||
| ab45fc144e | |||
| e99e9e0708 | |||
| 467404bfc8 | |||
| ce50fa2a62 | |||
| 10a011d842 | |||
| 5352410d0c | |||
| c5d155396a | |||
| 93187099d3 | |||
| aa24b1dce5 | |||
| eb3ede9593 | |||
| d7fecfbd0b | |||
| b065b4ff21 | |||
| 87370d24be | |||
| 8f8b9988ad | |||
| f8ccf4f5d8 | |||
| 25d8b86efd | |||
| 0cd3e937d8 | |||
| 89bb9c215e | |||
| 2d18686ce7 | |||
| 1d999d4910 | |||
| 7dfaa7579a | |||
| 08cb079e97 | |||
| 450aa83592 | |||
| 0614c76e92 | |||
| 97e338f9d4 | |||
| 636f018daa | |||
| c8d639024a | |||
| 6be2ee626a | |||
| f7fc1967a5 | |||
| aedb8a765b | |||
| cf58bd15c3 | |||
| 34f4f68524 | |||
| 09b8144080 | |||
| f1e6fb4ce7 | |||
| 2ca63fd1f6 | |||
| a5d25e7d92 | |||
| 4167819e7a | |||
| 5bd3a463f0 | |||
| 79c447b4c6 | |||
| 540304f947 | |||
| 75d8f7331b | |||
| b2509e9e53 | |||
| 7862f44653 | |||
| 962dd0c1bb | |||
| 5d5f7c7f5c | |||
| 6aaf838451 | |||
| ad3bd312e9 | |||
| 5fa9939696 | |||
| 4956bb0e9c | |||
| c074c12be7 | |||
| ddbc293e9c | |||
| a3921b45c7 | |||
| 38e1c8c5a1 | |||
| c2d29ff233 | |||
| 2316baa898 | |||
| f185d559c0 | |||
| 73d95bc004 | |||
| fcd55f89d7 | |||
| f9fe793573 | |||
| bc36411993 | |||
| 48506236bf | |||
| ded9b589fe | |||
| 67c3732fad | |||
| 2932f4591e | |||
| df53c07450 | |||
| 40899e9d80 | |||
| f794af0950 | |||
| 1665a1a093 | |||
| 4a36fb6d95 | |||
| acf78a8822 | |||
| f5c1ec9939 | |||
| 4b3d38b05b | |||
| 23e0b53107 | |||
| c907486c4d | |||
| 6b5945add8 | |||
| 55693de934 | |||
| d467475b6d | |||
| 44bc14820f | |||
| ec447e2e36 | |||
| 0af2647965 | |||
| 08442154f4 | |||
| 9f7d2234fb | |||
| ddd82a71a7 | |||
| 014ba3bf67 | |||
| c87321f804 | |||
| 8b451b3c67 | |||
| 0cfc87fbe6 | |||
| ae9673070c | |||
| 008027db0e | |||
| aec5e3473e | |||
| 95c8fde72f | |||
| 0f32968fae | |||
| ae79e9fea1 | |||
| 1a52aaf8d1 | |||
| d6c315ab8e | |||
| 983ce56048 | |||
| de2fe0e9f1 | |||
| c3c95bf291 | |||
| d2050b5948 | |||
| 6b92405bae | |||
| 49e87ccb15 | |||
| 50fffef13b | |||
| 82b1811971 | |||
| aeadef60bb | |||
| a1ab65a0e9 | |||
| 17e0805fe6 | |||
| ddd9c396b6 | |||
| ef49e507c1 | |||
| fbe74a5d80 | |||
| 076893981f | |||
| fac059f02c | |||
| 0313f8cc49 | |||
| 7ad6b73574 | |||
| 3cd0468b19 | |||
| f46ccb610e | |||
| 8a32569a3b | |||
| 535b23ae91 | |||
| 4715978f81 | |||
| a516aa7775 | |||
| 77e9c205f9 | |||
| e852305400 | |||
| c6a15264b3 | |||
| 2d0beaaaad | |||
| 5c5ef95d2b | |||
| e838e6f321 | |||
| ca983c72d4 | |||
| 91dd5256e9 | |||
| 3d4dc2d72b | |||
| ba3471068a | |||
| 5a7b2cf886 | |||
| cc926e84fb | |||
| fff16e6650 | |||
| d6f6d10cb6 | |||
| 1249904582 | |||
| 8e0437728b | |||
| fb0c0718e4 | |||
| aa8196db3a | |||
| b2223b5110 | |||
| 3837c5673a | |||
| 910a0860a0 | |||
| 009431fb98 | |||
| 579ece6256 | |||
| 822e97d3c3 | |||
| e0ae2ec42b | |||
| 859f6e2567 | |||
| 120d3c9dc8 | |||
| 342a95ddbe | |||
| 0b6134dd80 | |||
| e76854c23b | |||
| 24b98983cf | |||
| 3945f3cf38 | |||
| 5d7eb690e4 | |||
| bef180f4ba | |||
| e76e5abcf8 | |||
| 418f9c2662 | |||
| 716b72880a | |||
| 5de0fd792f | |||
| 13b557aba8 | |||
| 34dfc9add6 | |||
| 3a4575f251 | |||
| 178c2579d5 | |||
| 50be992b72 | |||
| d00f46eee1 | |||
| 44d6cba403 | |||
| 37bc5ff17b | |||
| e459bb04cc | |||
| 01eba88adf | |||
| 016fba5279 | |||
| da5d62ae03 | |||
| eb46c5eea6 | |||
| 100094e803 | |||
| e723cbf3b3 | |||
| 00d16ef59f | |||
| 5204ba5e24 | |||
| 629aabd3a3 | |||
| 1b9b9ed372 | |||
| b4e7f9046c | |||
| f09224d5c0 | |||
| 5f6ee33e2b | |||
| 635e2ba0e0 | |||
| 6109996ade | |||
| e4b80c9ab3 | |||
| 7521ad8bbb | |||
| b994065e18 | |||
| 5b1b84caff | |||
| d28a0e1dbb | |||
| 94d52df322 | |||
| 0ae3d36f0c | |||
| a7fb2b8a1a | |||
| 16d0dbab5b | |||
| 99c3050411 | |||
| 937265e828 | |||
| 60cd52a959 | |||
| b009501a53 | |||
| ee49e78dcd | |||
| 60aa919b14 | |||
| 8252a35771 | |||
| fc668c6880 | |||
| bb7f2a611a | |||
| c575c73764 | |||
| bd3ea721c3 | |||
| 82423ec467 | |||
| 64311e9652 | |||
| 77662b9c19 | |||
| b1031e3115 | |||
| 64c96f25d4 | |||
| 5ad42d6ca7 | |||
| 0386d4e88a | |||
| cda4512822 | |||
| eb6af4b4f0 | |||
| 4e51b128e6 | |||
| 0277263f98 | |||
| 99fb420d58 | |||
| a45c5da0a7 | |||
| ff1bc8a44a | |||
| 284bdc6e33 | |||
| 107360cd93 | |||
| abf9aa475b | |||
| 6156e04eb3 | |||
| b541c93797 | |||
| 6fd6413d6f | |||
| dfa38d3421 | |||
| 6e04b71c1a | |||
| 5afa541b30 | |||
| 9e5a093a3a | |||
| 2cf8e0291a | |||
| 53aa3bc3ae | |||
| 1ada5d9c2c | |||
| eb0910be57 | |||
| e9d5527482 | |||
| e6df764562 | |||
| 915bbbbde0 | |||
| f67e089ff3 | |||
| b841cc8b95 | |||
| 5f4b4baadb | |||
| 94b5a54655 | |||
| 95eb8b6ae4 | |||
| 8acbfa8967 | |||
| 1a115a8423 | |||
| 5a2172bb9b | |||
| 6b590671bc | |||
| cee1ab1347 | |||
| 9d0c6b9ef4 | |||
| 0e682bf630 | |||
| 8b95b300e2 | |||
| e1bd364278 | |||
| 7edc3427e1 | |||
| d3a3de2eac | |||
| bc2a8caf3e | |||
| d00446dc7b | |||
| 40ada1c31e | |||
| f24b2b9b4c | |||
| 2a644d7070 | |||
| ee0c1496e6 | |||
| 1da15783d5 | |||
| 6a925cb27f | |||
| 88ad64f113 | |||
| 1bc840430f | |||
| 76be8d5a87 | |||
| 8c4a54eb07 | |||
| dab5bee3c0 | |||
| bc8548fa1e | |||
| 476f919121 | |||
| 1c330d0301 | |||
| 47f0cd0b58 | |||
| f97be4e729 | |||
| 48b8dfe973 | |||
| 64b6c4d5f7 | |||
| fe16c66cf2 | |||
| 8d8695ba13 | |||
| e296256332 | |||
| 65111e87c1 | |||
| 95b1490f84 | |||
| 27a1f57ed3 | |||
| c6db6c5535 | |||
| bd22d3be36 | |||
| ba9d4587cb | |||
| 74c042a86b | |||
| 95fcd1dcc4 | |||
| 2de861d4c1 | |||
| e6d80c8ccb | |||
| 1aa2b3b065 | |||
| 88566719ec | |||
| 870e772da2 | |||
| e8e3ddceff | |||
| a5d1b76891 | |||
| e93f4e99f9 | |||
| 50aa891709 | |||
| 4b47e70b13 | |||
| c4acf774ec | |||
| 7ff1d50079 | |||
| 258b3cea66 | |||
| a3daa2d24f | |||
| 9f754ef0e9 | |||
| 773fbfc579 | |||
| 85fa9d942e | |||
| 83e782c7c5 | |||
| 9ee768551f | |||
| e45f8fa9ef | |||
| 891ea2da12 | |||
| 5e417f0714 | |||
| c53b579fca | |||
| ca9c390bb2 | |||
| 7d654f4a20 | |||
| b810bb01db | |||
| c2bd696bfe | |||
| 9fec315910 | |||
| 9a8a978e49 | |||
| e24b84e709 | |||
| 305b18ef57 | |||
| 22e9f53c42 | |||
| 6870e31a81 | |||
| e07d1e42e2 | |||
| c89caf7855 | |||
| 3b7c25b106 | |||
| 6079e1fa90 | |||
| 434466b306 | |||
| e1ac35f848 | |||
| 5994b22464 | |||
| bfc93158f5 | |||
| 29f99f0b20 | |||
| e4872131c8 | |||
| 16e1434f2a | |||
| 842badfa69 | |||
| 8ebc88aebb | |||
| c111ec9d91 | |||
| e85cdaf324 | |||
| 599d340a72 | |||
| 89b7fb8072 | |||
| dcaca2ecbd | |||
| b8725c96cd | |||
| 36930259d2 | |||
| 4397566f1e | |||
| 7c324869a4 | |||
| 7e80608066 | |||
| af7e44cf7c | |||
| 05099d066b | |||
| 937486a66b | |||
| e8de1f6d9c | |||
| cd9a5469fd | |||
| 1124f25ea3 | |||
| a79a87de4c | |||
| d2193bf428 | |||
| d9eab9f254 | |||
| 7d08ea8466 | |||
| ba1eb2fa73 | |||
| 4dbca6096f | |||
| 03be2d0492 | |||
| b0aca9de13 | |||
| 019a0297a9 | |||
| 0f93febd86 | |||
| d6c96b781f | |||
| 918bb94644 | |||
| a8774fa524 | |||
| e4b908ecde | |||
| 247ba40309 | |||
| fcf01ba677 | |||
| fb5a64c251 | |||
| 3d51ba0dc2 | |||
| 07636f51c4 | |||
| eff2050959 | |||
| c96a21cf99 | |||
| d4d847059a | |||
| 880d722912 | |||
| 1ef1053d3f | |||
| fa522a85d6 | |||
| f09e58c69c | |||
| 63e02492e8 | |||
| fd406eb3e6 | |||
| 88ade26ef7 | |||
| 3aea259e41 | |||
| 0f64767437 | |||
| d2430badbe | |||
| a880ed2b18 | |||
| e0f0fa9a2a | |||
| 5d2025aa43 | |||
| 8b7f5a765b | |||
| 9cd94004fc | |||
| 8042bca7cc | |||
| 8d89d158d1 | |||
| ccacdf274b | |||
| f1ceef05fc | |||
| c5697242ee | |||
| d0a48ab94b | |||
| 2b037d41ac | |||
| b7d38dd849 | |||
| 02d24139e9 | |||
| ad638e8bc8 | |||
| 76cb20debe | |||
| 3e9383e6d9 | |||
| aec8bf56a2 | |||
| 18335e3325 | |||
| bca9605d4a | |||
| 0321f0e979 | |||
| f97c2a36f6 | |||
| 5d945f5bc5 | |||
| 1c4975589f | |||
| fffe5c2c4b | |||
| 3a57e1c766 | |||
| 8b70882fec | |||
| 7fb7ba0d2b | |||
| 78514c6572 | |||
| 19393006ef | |||
| cb704c4551 | |||
| 04a09c3ce5 | |||
| ca8f978667 | |||
| 0cc91ac037 | |||
| 1b6f86669c | |||
| 264868bb6a | |||
| 02087a541e | |||
| dee0e37a85 | |||
| ea7a4a560b | |||
| f63e17775c | |||
| c4240d36f7 | |||
| ed13a0d14b | |||
| 8fa0be7633 | |||
| a99c022608 | |||
| 12bcbd28f3 | |||
| 4ece21cdf2 | |||
| a7642c2da4 | |||
| 32024cf2c5 | |||
| ef373caba7 | |||
| 396bd22199 | |||
| 4bff50a088 | |||
| dbc0ab76af | |||
| 289a8c14d3 | |||
| 44ed633cbf | |||
| 0a55d73146 | |||
| 40dda1150c | |||
| 09b61ec684 | |||
| e53467da22 | |||
| 09d27c0b05 | |||
| 3b18be5874 | |||
| ff15308c03 | |||
| fa3dc870d3 | |||
| 5e6ada140c | |||
| e8f7c1c832 | |||
| 266a11f64f | |||
| e442b92a5f | |||
| b337873ca2 | |||
| 896fff04aa | |||
| 6d0bca6d67 | |||
| d53c1ae2bd | |||
| afd73d53be | |||
| 652e55e80e | |||
| 9aa8e7edff | |||
| d67dfdf2e7 | |||
| 51f2d96ad6 | |||
| 30867b4ba1 | |||
| ec8d946a41 | |||
| 1eea935207 | |||
| 616990b930 | |||
| e5c31c9dd4 | |||
| 4f3f7d1edb | |||
| 86f13003b5 | |||
| 6d2431b683 | |||
| 57e17f2864 | |||
| bcc7d7770e | |||
| 89ea40d7f3 | |||
| 56b5008278 | |||
| 555778fca4 | |||
| ec1a6226a9 | |||
| 3c541ada89 | |||
| 5f677e71e9 | |||
| 5b3e66c4f6 | |||
| 9b0252fb75 | |||
| 2e3750c87c | |||
| 377d691053 | |||
| e90fe73aa2 | |||
| 3baa681c2b | |||
| a588bc4631 | |||
| b195c707b0 | |||
| 25ac84e5fd | |||
| 5e9df32bfa | |||
| 722feac8bd | |||
| 4be87a64b9 | |||
| 505ca6a58e | |||
| 5f1c8f3627 | |||
| 3834079481 | |||
| 9faa93e292 | |||
| 27609dc5e0 | |||
| 2b57d49e4e | |||
| dc0c738471 | |||
| ca41f4d4f2 | |||
| e1427f3ecb | |||
| e2fb9a66ad | |||
| 7278648642 | |||
| a4c955ce85 | |||
| f086027910 | |||
| 543b3bd937 | |||
| c0534a3b06 | |||
| 0c9785af36 | |||
| 482149139a | |||
| c89038f337 | |||
| 696d3ffabf | |||
| 14e5d0e740 | |||
| e4ae1dd475 | |||
| 46cd262fab | |||
| 3f5418083f | |||
| 1586c2f9e6 | |||
| e64b318a42 | |||
| 2033572c83 | |||
| ce678c1b76 | |||
| 83495b101c | |||
| 6c2a5f904d | |||
| c1251d3332 | |||
| 4ef1b7abe8 | |||
| d822e4ab3f | |||
| b01fe050d2 | |||
| 1a4cf211eb | |||
| 4541304fa8 | |||
| 894160f3f7 | |||
| 6a91bd53e2 | |||
| 0f013304ef | |||
| 6f4f4ccb16 | |||
| 7138ca1f5f | |||
| 45e7f6a0d1 | |||
| a7098df9cf | |||
| 054c7faaac | |||
| c3a4c659c0 | |||
| 087c85e586 | |||
| 43df188df1 | |||
| 1d40c6d068 | |||
| 6614242df6 | |||
| b25dc623cf | |||
| 9d3bb4e4e3 | |||
| 5dc11c285d | |||
| 575b4ce970 | |||
| e23821a7cb | |||
| e415258787 | |||
| eddfeb10a5 | |||
| 0361f8ad69 | |||
| 1451991d03 | |||
| 92fee08dc4 | |||
| 7b7e484091 | |||
| e7291a31f3 | |||
| 2dc31912cc | |||
| 428a8a10ff | |||
| 8b2f1965e2 | |||
| b18a99e4df | |||
| 1fac0c8640 | |||
| f0be73c2cd | |||
| 42bd632539 | |||
| f8014c6213 | |||
| 65f49489ad | |||
| e9e24d5f2d | |||
| 369b09972c | |||
| e4e2bdac72 | |||
| ec0db39184 | |||
| a02be78df5 | |||
| 3490abe9a7 | |||
| b5013426e6 | |||
| 7dd0881d29 | |||
| acf0562851 | |||
| 80c3a90d6f | |||
| c6985087a8 | |||
| ef50e2d5ce | |||
| ed1dc6e8d5 | |||
| c2d7a319a0 | |||
| 0e04298b7c | |||
| 3a5a73b02c | |||
| 901c7c1241 | |||
| 4e82369b16 | |||
| 945963db32 | |||
| 5741cbe756 | |||
| 6401aeb3a8 | |||
| 6a0c129d39 | |||
| bbec9ffcdf | |||
| 541f1fa2e3 | |||
| 7897820632 | |||
| 0dd9de2abc | |||
| 7131ba99b6 | |||
| c69026aa5b | |||
| 16ac96c64e | |||
| 1bb79b1c98 | |||
| eeee272f03 | |||
| 2563e9d1d6 | |||
| 24bec66390 | |||
| 3d30734dc2 | |||
| cbc1d53cc2 | |||
| 9a1f7a13f8 | |||
| d48b9b7f91 | |||
| 358865dc6a | |||
| e750c37473 | |||
| 71a589c10c | |||
| 3281239ff5 | |||
| 3e2cdddd5a | |||
| 1d4c3e51c7 | |||
| 1694c71528 | |||
| 169ffc1b0b | |||
| 89eb3259d4 | |||
| ffd88ffc66 | |||
| 6c2d13bd17 | |||
| 8d92a75ef0 | |||
| acb86ae266 | |||
| 473cf978b4 | |||
| 4debab2636 | |||
| e91e197873 | |||
| b30b6734a1 | |||
| dadb80608a | |||
| 16c9969fb9 | |||
| dc1644ed25 | |||
| 2cc9b3e1ed | |||
| 415f340a68 | |||
| 2d4869128d | |||
| ae8bc01d9b | |||
| e2552d9442 | |||
| 5d1b5d80b6 | |||
| 366804aa29 | |||
| 9240e0c903 | |||
| 7baaf2cff3 | |||
| 9fbc1ba031 | |||
| 6704c07db0 | |||
| a87165148a | |||
| ec4bcd093b | |||
| 5552055b98 | |||
| 03aa67034d | |||
| fc21427685 | |||
| 819b02a204 | |||
| de0bd5fd57 | |||
| 8aa1d94a1a | |||
| f8a59133a2 | |||
| c382f770dc | |||
| cde4ec13ef | |||
| ecad1ea839 | |||
| 6b91b22713 | |||
| e34c91b2cc | |||
| 822759a688 | |||
| b606037890 | |||
| 74d9b94119 | |||
| b1e9f955b0 | |||
| e0356fa360 | |||
| fbc67eeb98 | |||
| 09fd73b130 | |||
| 259a76f46b | |||
| c6504c2eaf | |||
| 7d104a1514 | |||
| b3bd61c89e | |||
| e49dca0275 | |||
| 03125b3a2d | |||
| a523379b3a | |||
| aa6348a29a | |||
| b9f0f1a69a | |||
| a284806d3c | |||
| 7e10c1db65 | |||
| 11790638d6 | |||
| 0583cbe266 | |||
| 2e6874c822 | |||
| 2ce41990bf | |||
| c8aeba38ba | |||
| 5e02502a5c | |||
| 382cc3d844 | |||
| dd74d9ee89 | |||
| 383f82807f | |||
| d4579a9a41 | |||
| 66a07c6a51 | |||
| 66ffd8e936 | |||
| 44f07ca231 | |||
| ff14f024af | |||
| dccf7c6c8d | |||
| 10d7955f99 | |||
| 64ade901de | |||
| eb0dd3f781 | |||
| 66e6cd80d3 | |||
| 959b32de1c | |||
| 9c6dc5b424 | |||
| aaab95d414 | |||
| 7d4e93912c | |||
| d65b463547 | |||
| 6e5a4bcb39 | |||
| 1a799dc30a | |||
| e3d2676858 | |||
| 42851686ca | |||
| e3943d868a | |||
| 7654b795c7 | |||
| 489244f1a9 | |||
| cbcce336d6 | |||
| 52a96b2a4f | |||
| ce6002a631 | |||
| 84a9cf069a | |||
| 83f19a7572 | |||
| a1a4c8b56d | |||
| d8901126d0 | |||
| 854db4ece8 | |||
| 07f2e65fc7 | |||
| ccf09f97d5 | |||
| 8f9a4ebc04 | |||
| f1833f13d5 | |||
| 6a81e369fa | |||
| 597e9e1ea9 | |||
| 9bb027ec4c | |||
| fbbbaa5d49 | |||
| aaec5a3fc9 | |||
| 7cd24cd51d | |||
| c81b34c1d0 | |||
| 7b1acc494d | |||
| 6ff90694e2 | |||
| 157c7c66b5 | |||
| 93249258c6 | |||
| 01c01a46fa | |||
| 0e2a10fe94 | |||
| 0b9f3de47c | |||
| bc239eead1 | |||
| 7a09869b0c | |||
| bdc0de6ada | |||
| 6870a7f9b1 | |||
| ace1a1b063 | |||
| d87b879cc3 | |||
| 65b36f8e69 | |||
| 87387a54f2 | |||
| b497cebe76 | |||
| 0fa107a75b | |||
| b34e3aeed0 | |||
| 35b18d72fd | |||
| 4b80f30afb | |||
| 86c54e04a8 | |||
| ef9fc596f5 | |||
| ad34e455ce | |||
| 01fdd0bee2 | |||
| 32ffa345cd | |||
| 6fc3c16073 | |||
| 7d58657c80 | |||
| fcd657c10e | |||
| 4ab77c5557 | |||
| 2bbaa500f4 | |||
| 722a20e141 | |||
| 041c24a837 | |||
| 39a3baa00b | |||
| f7acbb1eaa | |||
| e6fbf7aa5b | |||
| 87926e69db | |||
| 36a084eab6 | |||
| a9e319e0c0 | |||
| ea23b97231 | |||
| 7df76f9642 | |||
| f6db117a5e | |||
| 23c3cd605d | |||
| 77690702c0 | |||
| e0093480d9 | |||
| c7679b7a67 | |||
| e6ac34bde8 | |||
| 8c4b595c30 | |||
| be629e5c6b | |||
| 63569684a3 | |||
| 5937a0d7ce | |||
| 4512272c1c | |||
| ce1f3842e0 | |||
| ee01c3a059 | |||
| 81c1537bad | |||
| 98ecfab032 | |||
| b948b8c1a4 | |||
| f856c6ae37 | |||
| 2dd2580530 | |||
| f0c100aee4 | 
@@ -1,3 +1,4 @@
 | 
				
			|||||||
public/env.sample.js
 | 
					public/env.sample.js
 | 
				
			||||||
public/workbox-*.js
 | 
					.pnpm-store
 | 
				
			||||||
public/workbox-*.js.map
 | 
					.yarn
 | 
				
			||||||
 | 
					.pnp.*
 | 
				
			||||||
							
								
								
									
										41
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								.drone.yml
									
									
									
									
									
								
							@@ -1,41 +0,0 @@
 | 
				
			|||||||
---
 | 
					 | 
				
			||||||
kind: pipeline
 | 
					 | 
				
			||||||
type: docker
 | 
					 | 
				
			||||||
name: build:dev
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
steps:
 | 
					 | 
				
			||||||
  - name: build dev
 | 
					 | 
				
			||||||
    image: plugins/docker
 | 
					 | 
				
			||||||
    depends_on: [clone]
 | 
					 | 
				
			||||||
    settings:
 | 
					 | 
				
			||||||
      username:
 | 
					 | 
				
			||||||
        from_secret: DOCKER_REGISTRY_USER
 | 
					 | 
				
			||||||
      password:
 | 
					 | 
				
			||||||
        from_secret: DOCKER_REGISTRY_PASSWORD
 | 
					 | 
				
			||||||
      repo: registry.odit.services/lfk/frontend
 | 
					 | 
				
			||||||
      tags:
 | 
					 | 
				
			||||||
        - dev
 | 
					 | 
				
			||||||
      registry: registry.odit.services
 | 
					 | 
				
			||||||
  - name: run full license export
 | 
					 | 
				
			||||||
    depends_on: ["clone"]
 | 
					 | 
				
			||||||
    image: node:alpine
 | 
					 | 
				
			||||||
    commands:
 | 
					 | 
				
			||||||
      - yarn
 | 
					 | 
				
			||||||
      - yarn licenses:export
 | 
					 | 
				
			||||||
  - name: push new licenses file to repo
 | 
					 | 
				
			||||||
    depends_on: ["run full license export"]
 | 
					 | 
				
			||||||
    image: appleboy/drone-git-push
 | 
					 | 
				
			||||||
    settings:
 | 
					 | 
				
			||||||
      branch: dev
 | 
					 | 
				
			||||||
      commit: true
 | 
					 | 
				
			||||||
      commit_message: new license file version [CI SKIP]
 | 
					 | 
				
			||||||
      author_email: bot@odit.services
 | 
					 | 
				
			||||||
      remote: git@git.odit.services:lfk/frontend.git
 | 
					 | 
				
			||||||
      ssh_key:
 | 
					 | 
				
			||||||
        from_secret: GITLAB_SSHKEY
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
trigger:
 | 
					 | 
				
			||||||
  branch:
 | 
					 | 
				
			||||||
    - dev
 | 
					 | 
				
			||||||
  event:
 | 
					 | 
				
			||||||
    - push
 | 
					 | 
				
			||||||
							
								
								
									
										33
									
								
								.gitea/workflows/release.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.gitea/workflows/release.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					name: Build release images
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  push:
 | 
				
			||||||
 | 
					    tags:
 | 
				
			||||||
 | 
					      - "*.*.*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  build-container:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v4
 | 
				
			||||||
 | 
					      - name: Set up Node.js
 | 
				
			||||||
 | 
					        uses: actions/setup-node@v4
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          node-version: 19
 | 
				
			||||||
 | 
					      - run: npm i -g pnpm@10.8 && pnpm i
 | 
				
			||||||
 | 
					      - run: pnpm licenses:export
 | 
				
			||||||
 | 
					      - name: Login to registry
 | 
				
			||||||
 | 
					        uses: docker/login-action@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          registry: registry.odit.services
 | 
				
			||||||
 | 
					          username: ${{ vars.REGISTRY_USERNAME }}
 | 
				
			||||||
 | 
					          password: ${{ secrets.REGISTRY_PASSWORD }}
 | 
				
			||||||
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
 | 
					        uses: docker/setup-buildx-action@v3
 | 
				
			||||||
 | 
					      - name: Build and push
 | 
				
			||||||
 | 
					        uses: docker/build-push-action@v6
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          push: true
 | 
				
			||||||
 | 
					          tags: |
 | 
				
			||||||
 | 
					            ${{ vars.REGISTRY }}/lfk/frontend:${{ github.ref_name }}
 | 
				
			||||||
 | 
					          platforms: linux/amd64,linux/arm64
 | 
				
			||||||
							
								
								
									
										14
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,8 @@
 | 
				
			|||||||
.vscode
 | 
					 | 
				
			||||||
.idea
 | 
					 | 
				
			||||||
node_modules
 | 
					node_modules
 | 
				
			||||||
dist
 | 
					 | 
				
			||||||
dist-ssr
 | 
					 | 
				
			||||||
public/env.js
 | 
					 | 
				
			||||||
/build
 | 
					 | 
				
			||||||
yarn.lock
 | 
					 | 
				
			||||||
package-lock.json
 | 
					 | 
				
			||||||
*.map
 | 
					*.map
 | 
				
			||||||
 | 
					public/env.js
 | 
				
			||||||
 | 
					public/index.html
 | 
				
			||||||
 | 
					/dist
 | 
				
			||||||
 | 
					.pnpm-store
 | 
				
			||||||
 | 
					.yarn
 | 
				
			||||||
 | 
					.pnp.*
 | 
				
			||||||
							
								
								
									
										12
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "recommendations": [
 | 
				
			||||||
 | 
					    "2gua.rainbow-brackets",
 | 
				
			||||||
 | 
					    "christian-kohler.npm-intellisense",
 | 
				
			||||||
 | 
					    "remimarsal.prettier-now",
 | 
				
			||||||
 | 
					    "svelte.svelte-vscode",
 | 
				
			||||||
 | 
					    "lokalise.i18n-ally",
 | 
				
			||||||
 | 
					    "fivethree.vscode-svelte-snippets",
 | 
				
			||||||
 | 
					    "voorjaar.windicss-intellisense"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "unwantedRecommendations": ["antfu.i18n-ally"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								.vscode/i18n-ally-custom-framework.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.vscode/i18n-ally-custom-framework.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					languageIds:
 | 
				
			||||||
 | 
					  - javascript
 | 
				
			||||||
 | 
					  - svelte
 | 
				
			||||||
 | 
					  - html
 | 
				
			||||||
 | 
					monopoly: false
 | 
				
			||||||
 | 
					refactorTemplates:
 | 
				
			||||||
 | 
					  - "{$_('$1')}"
 | 
				
			||||||
							
								
								
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "i18n-ally.localesPaths": "src/locales",
 | 
				
			||||||
 | 
					  "i18n-ally.keystyle": "nested",
 | 
				
			||||||
 | 
					  "windicss.enableCodeFolding": false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1854
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										1854
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										25
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -1,19 +1,16 @@
 | 
				
			|||||||
FROM node:15.4.0-alpine3.12
 | 
					FROM registry.odit.services/hub/library/node:23.10.0-alpine3.21 AS build
 | 
				
			||||||
 | 
					ARG NPM_REGISTRY_URL=https://registry.npmjs.org
 | 
				
			||||||
WORKDIR /app
 | 
					WORKDIR /app
 | 
				
			||||||
RUN npm i -g pnpm
 | 
					
 | 
				
			||||||
COPY package.json ./
 | 
					COPY package.json pnpm-lock.yaml vite.config.js index.html ./
 | 
				
			||||||
RUN pnpm i
 | 
					RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@10.8
 | 
				
			||||||
COPY package.json *.config.js workbox-config.js ./
 | 
					RUN mkdir /pnpm && pnpm config set store-dir /pnpm && pnpm i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY src ./src
 | 
					COPY src ./src
 | 
				
			||||||
COPY public ./public
 | 
					COPY public ./public
 | 
				
			||||||
RUN pnpm run build:sw
 | 
					RUN pnpm build
 | 
				
			||||||
RUN pnpm run build
 | 
					
 | 
				
			||||||
# final image
 | 
					# final image
 | 
				
			||||||
FROM alpine
 | 
					FROM registry.odit.services/library/nginx-brotli:3.15 AS final
 | 
				
			||||||
COPY --from=0 /app/build /app
 | 
					COPY --from=build /app/dist /usr/share/nginx/html
 | 
				
			||||||
RUN rm -rf /app/build/_dist_/components
 | 
					 | 
				
			||||||
RUN rm -rf /app/build/_dist_/locales
 | 
					 | 
				
			||||||
RUN rm -rf /app/build-manifest.json
 | 
					 | 
				
			||||||
FROM fholzer/nginx-brotli:v1.19.1
 | 
					 | 
				
			||||||
COPY --from=1 /app /usr/share/nginx/html
 | 
					 | 
				
			||||||
COPY ./nginx.conf /etc/nginx/nginx.conf
 | 
					COPY ./nginx.conf /etc/nginx/nginx.conf
 | 
				
			||||||
							
								
								
									
										362
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										362
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,362 @@
 | 
				
			|||||||
 | 
					Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Creative
 | 
				
			||||||
 | 
					Commons Corporation ("Creative Commons") is not a law firm and does not provide
 | 
				
			||||||
 | 
					legal services or legal advice. Distribution of Creative Commons public licenses
 | 
				
			||||||
 | 
					does not create a lawyer-client or other relationship. Creative Commons makes
 | 
				
			||||||
 | 
					its licenses and related information available on an "as-is" basis. Creative
 | 
				
			||||||
 | 
					Commons gives no warranties regarding its licenses, any material licensed
 | 
				
			||||||
 | 
					under their terms and conditions, or any related information. Creative Commons
 | 
				
			||||||
 | 
					disclaims all liability for damages resulting from their use to the fullest
 | 
				
			||||||
 | 
					extent possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using Creative Commons Public Licenses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Creative Commons public licenses provide a standard set of terms and conditions
 | 
				
			||||||
 | 
					that creators and other rights holders may use to share original works of
 | 
				
			||||||
 | 
					authorship and other material subject to copyright and certain other rights
 | 
				
			||||||
 | 
					specified in the public license below. The following considerations are for
 | 
				
			||||||
 | 
					informational purposes only, are not exhaustive, and do not form part of our
 | 
				
			||||||
 | 
					licenses.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Considerations for licensors: Our public licenses are intended for use by
 | 
				
			||||||
 | 
					those authorized to give the public permission to use material in ways otherwise
 | 
				
			||||||
 | 
					restricted by copyright and certain other rights. Our licenses are irrevocable.
 | 
				
			||||||
 | 
					Licensors should read and understand the terms and conditions of the license
 | 
				
			||||||
 | 
					they choose before applying it. Licensors should also secure all rights necessary
 | 
				
			||||||
 | 
					before applying our licenses so that the public can reuse the material as
 | 
				
			||||||
 | 
					expected. Licensors should clearly mark any material not subject to the license.
 | 
				
			||||||
 | 
					This includes other CC-licensed material, or material used under an exception
 | 
				
			||||||
 | 
					or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Considerations for the public: By using one of our public licenses, a licensor
 | 
				
			||||||
 | 
					grants the public permission to use the licensed material under specified
 | 
				
			||||||
 | 
					terms and conditions. If the licensor's permission is not necessary for any
 | 
				
			||||||
 | 
					reason–for example, because of any applicable exception or limitation to copyright–then
 | 
				
			||||||
 | 
					that use is not regulated by the license. Our licenses grant only permissions
 | 
				
			||||||
 | 
					under copyright and certain other rights that a licensor has authority to
 | 
				
			||||||
 | 
					grant. Use of the licensed material may still be restricted for other reasons,
 | 
				
			||||||
 | 
					including because others have copyright or other rights in the material. A
 | 
				
			||||||
 | 
					licensor may make special requests, such as asking that all changes be marked
 | 
				
			||||||
 | 
					or described. Although not required by our licenses, you are encouraged to
 | 
				
			||||||
 | 
					respect those requests where reasonable. More considerations for the public
 | 
				
			||||||
 | 
					: wiki.creativecommons.org/Considerations_for_licensees
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public
 | 
				
			||||||
 | 
					License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By exercising the Licensed Rights (defined below), You accept and agree to
 | 
				
			||||||
 | 
					be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike
 | 
				
			||||||
 | 
					4.0 International Public License ("Public License"). To the extent this Public
 | 
				
			||||||
 | 
					License may be interpreted as a contract, You are granted the Licensed Rights
 | 
				
			||||||
 | 
					in consideration of Your acceptance of these terms and conditions, and the
 | 
				
			||||||
 | 
					Licensor grants You such rights in consideration of benefits the Licensor
 | 
				
			||||||
 | 
					receives from making the Licensed Material available under these terms and
 | 
				
			||||||
 | 
					conditions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Section 1 – Definitions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a. Adapted Material means material subject to Copyright and Similar Rights
 | 
				
			||||||
 | 
					that is derived from or based upon the Licensed Material and in which the
 | 
				
			||||||
 | 
					Licensed Material is translated, altered, arranged, transformed, or otherwise
 | 
				
			||||||
 | 
					modified in a manner requiring permission under the Copyright and Similar
 | 
				
			||||||
 | 
					Rights held by the Licensor. For purposes of this Public License, where the
 | 
				
			||||||
 | 
					Licensed Material is a musical work, performance, or sound recording, Adapted
 | 
				
			||||||
 | 
					Material is always produced where the Licensed Material is synched in timed
 | 
				
			||||||
 | 
					relation with a moving image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					b. Adapter's License means the license You apply to Your Copyright and Similar
 | 
				
			||||||
 | 
					Rights in Your contributions to Adapted Material in accordance with the terms
 | 
				
			||||||
 | 
					and conditions of this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					c. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses,
 | 
				
			||||||
 | 
					approved by Creative Commons as essentially the equivalent of this Public
 | 
				
			||||||
 | 
					License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					d. Copyright and Similar Rights means copyright and/or similar rights closely
 | 
				
			||||||
 | 
					related to copyright including, without limitation, performance, broadcast,
 | 
				
			||||||
 | 
					sound recording, and Sui Generis Database Rights, without regard to how the
 | 
				
			||||||
 | 
					rights are labeled or categorized. For purposes of this Public License, the
 | 
				
			||||||
 | 
					rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					e. Effective Technological Measures means those measures that, in the absence
 | 
				
			||||||
 | 
					of proper authority, may not be circumvented under laws fulfilling obligations
 | 
				
			||||||
 | 
					under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996,
 | 
				
			||||||
 | 
					and/or similar international agreements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					f. Exceptions and Limitations means fair use, fair dealing, and/or any other
 | 
				
			||||||
 | 
					exception or limitation to Copyright and Similar Rights that applies to Your
 | 
				
			||||||
 | 
					use of the Licensed Material.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					g. License Elements means the license attributes listed in the name of a Creative
 | 
				
			||||||
 | 
					Commons Public License. The License Elements of this Public License are Attribution,
 | 
				
			||||||
 | 
					NonCommercial, and ShareAlike.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h. Licensed Material means the artistic or literary work, database, or other
 | 
				
			||||||
 | 
					material to which the Licensor applied this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i. Licensed Rights means the rights granted to You subject to the terms and
 | 
				
			||||||
 | 
					conditions of this Public License, which are limited to all Copyright and
 | 
				
			||||||
 | 
					Similar Rights that apply to Your use of the Licensed Material and that the
 | 
				
			||||||
 | 
					Licensor has authority to license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					j. Licensor means the individual(s) or entity(ies) granting rights under this
 | 
				
			||||||
 | 
					Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					k. NonCommercial means not primarily intended for or directed towards commercial
 | 
				
			||||||
 | 
					advantage or monetary compensation. For purposes of this Public License, the
 | 
				
			||||||
 | 
					exchange of the Licensed Material for other material subject to Copyright
 | 
				
			||||||
 | 
					and Similar Rights by digital file-sharing or similar means is NonCommercial
 | 
				
			||||||
 | 
					provided there is no payment of monetary compensation in connection with the
 | 
				
			||||||
 | 
					exchange.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					l. Share means to provide material to the public by any means or process that
 | 
				
			||||||
 | 
					requires permission under the Licensed Rights, such as reproduction, public
 | 
				
			||||||
 | 
					display, public performance, distribution, dissemination, communication, or
 | 
				
			||||||
 | 
					importation, and to make material available to the public including in ways
 | 
				
			||||||
 | 
					that members of the public may access the material from a place and at a time
 | 
				
			||||||
 | 
					individually chosen by them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					m. Sui Generis Database Rights means rights other than copyright resulting
 | 
				
			||||||
 | 
					from Directive 96/9/EC of the European Parliament and of the Council of 11
 | 
				
			||||||
 | 
					March 1996 on the legal protection of databases, as amended and/or succeeded,
 | 
				
			||||||
 | 
					as well as other essentially equivalent rights anywhere in the world.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					n. You means the individual or entity exercising the Licensed Rights under
 | 
				
			||||||
 | 
					this Public License. Your has a corresponding meaning.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Section 2 – Scope.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   a. License grant.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Subject to the terms and conditions of this Public License, the Licensor
 | 
				
			||||||
 | 
					hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive,
 | 
				
			||||||
 | 
					irrevocable license to exercise the Licensed Rights in the Licensed Material
 | 
				
			||||||
 | 
					to:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial
 | 
				
			||||||
 | 
					purposes only; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					B. produce, reproduce, and Share Adapted Material for NonCommercial purposes
 | 
				
			||||||
 | 
					only.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions
 | 
				
			||||||
 | 
					and Limitations apply to Your use, this Public License does not apply, and
 | 
				
			||||||
 | 
					You do not need to comply with its terms and conditions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      3. Term. The term of this Public License is specified in Section 6(a).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					4. Media and formats; technical modifications allowed. The Licensor authorizes
 | 
				
			||||||
 | 
					You to exercise the Licensed Rights in all media and formats whether now known
 | 
				
			||||||
 | 
					or hereafter created, and to make technical modifications necessary to do
 | 
				
			||||||
 | 
					so. The Licensor waives and/or agrees not to assert any right or authority
 | 
				
			||||||
 | 
					to forbid You from making technical modifications necessary to exercise the
 | 
				
			||||||
 | 
					Licensed Rights, including technical modifications necessary to circumvent
 | 
				
			||||||
 | 
					Effective Technological Measures. For purposes of this Public License, simply
 | 
				
			||||||
 | 
					making modifications authorized by this Section 2(a)(4) never produces Adapted
 | 
				
			||||||
 | 
					Material.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      5. Downstream recipients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed
 | 
				
			||||||
 | 
					Material automatically receives an offer from the Licensor to exercise the
 | 
				
			||||||
 | 
					Licensed Rights under the terms and conditions of this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					B. Additional offer from the Licensor – Adapted Material. Every recipient
 | 
				
			||||||
 | 
					of Adapted Material from You automatically receives an offer from the Licensor
 | 
				
			||||||
 | 
					to exercise the Licensed Rights in the Adapted Material under the conditions
 | 
				
			||||||
 | 
					of the Adapter's License You apply.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C. No downstream restrictions. You may not offer or impose any additional
 | 
				
			||||||
 | 
					or different terms or conditions on, or apply any Effective Technological
 | 
				
			||||||
 | 
					Measures to, the Licensed Material if doing so restricts exercise of the Licensed
 | 
				
			||||||
 | 
					Rights by any recipient of the Licensed Material.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					6. No endorsement. Nothing in this Public License constitutes or may be construed
 | 
				
			||||||
 | 
					as permission to assert or imply that You are, or that Your use of the Licensed
 | 
				
			||||||
 | 
					Material is, connected with, or sponsored, endorsed, or granted official status
 | 
				
			||||||
 | 
					by, the Licensor or others designated to receive attribution as provided in
 | 
				
			||||||
 | 
					Section 3(a)(1)(A)(i).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   b. Other rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Moral rights, such as the right of integrity, are not licensed under this
 | 
				
			||||||
 | 
					Public License, nor are publicity, privacy, and/or other similar personality
 | 
				
			||||||
 | 
					rights; however, to the extent possible, the Licensor waives and/or agrees
 | 
				
			||||||
 | 
					not to assert any such rights held by the Licensor to the limited extent necessary
 | 
				
			||||||
 | 
					to allow You to exercise the Licensed Rights, but not otherwise.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. Patent and trademark rights are not licensed under this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. To the extent possible, the Licensor waives any right to collect royalties
 | 
				
			||||||
 | 
					from You for the exercise of the Licensed Rights, whether directly or through
 | 
				
			||||||
 | 
					a collecting society under any voluntary or waivable statutory or compulsory
 | 
				
			||||||
 | 
					licensing scheme. In all other cases the Licensor expressly reserves any right
 | 
				
			||||||
 | 
					to collect such royalties, including when the Licensed Material is used other
 | 
				
			||||||
 | 
					than for NonCommercial purposes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Section 3 – License Conditions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Your exercise of the Licensed Rights is expressly made subject to the following
 | 
				
			||||||
 | 
					conditions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   a. Attribution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. If You Share the Licensed Material (including in modified form), You must:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A. retain the following if it is supplied by the Licensor with the Licensed
 | 
				
			||||||
 | 
					Material:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i. identification of the creator(s) of the Licensed Material and any others
 | 
				
			||||||
 | 
					designated to receive attribution, in any reasonable manner requested by the
 | 
				
			||||||
 | 
					Licensor (including by pseudonym if designated);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ii. a copyright notice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            iii. a notice that refers to this Public License;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            iv. a notice that refers to the disclaimer of warranties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					B. indicate if You modified the Licensed Material and retain an indication
 | 
				
			||||||
 | 
					of any previous modifications; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C. indicate the Licensed Material is licensed under this Public License, and
 | 
				
			||||||
 | 
					include the text of, or the URI or hyperlink to, this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner
 | 
				
			||||||
 | 
					based on the medium, means, and context in which You Share the Licensed Material.
 | 
				
			||||||
 | 
					For example, it may be reasonable to satisfy the conditions by providing a
 | 
				
			||||||
 | 
					URI or hyperlink to a resource that includes the required information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. If requested by the Licensor, You must remove any of the information required
 | 
				
			||||||
 | 
					by Section 3(a)(1)(A) to the extent reasonably practicable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					b. ShareAlike.In addition to the conditions in Section 3(a), if You Share
 | 
				
			||||||
 | 
					Adapted Material You produce, the following conditions also apply.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. The Adapter's License You apply must be a Creative Commons license with
 | 
				
			||||||
 | 
					the same License Elements, this version or later, or a BY-NC-SA Compatible
 | 
				
			||||||
 | 
					License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. You must include the text of, or the URI or hyperlink to, the Adapter's
 | 
				
			||||||
 | 
					License You apply. You may satisfy this condition in any reasonable manner
 | 
				
			||||||
 | 
					based on the medium, means, and context in which You Share Adapted Material.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. You may not offer or impose any additional or different terms or conditions
 | 
				
			||||||
 | 
					on, or apply any Effective Technological Measures to, Adapted Material that
 | 
				
			||||||
 | 
					restrict exercise of the rights granted under the Adapter's License You apply.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Section 4 – Sui Generis Database Rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Where the Licensed Rights include Sui Generis Database Rights that apply to
 | 
				
			||||||
 | 
					Your use of the Licensed Material:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract,
 | 
				
			||||||
 | 
					reuse, reproduce, and Share all or a substantial portion of the contents of
 | 
				
			||||||
 | 
					the database for NonCommercial purposes only;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					b. if You include all or a substantial portion of the database contents in
 | 
				
			||||||
 | 
					a database in which You have Sui Generis Database Rights, then the database
 | 
				
			||||||
 | 
					in which You have Sui Generis Database Rights (but not its individual contents)
 | 
				
			||||||
 | 
					is Adapted Material, including for purposes of Section 3(b); and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					c. You must comply with the conditions in Section 3(a) if You Share all or
 | 
				
			||||||
 | 
					a substantial portion of the contents of the database.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For the avoidance of doubt, this Section 4 supplements and does not replace
 | 
				
			||||||
 | 
					Your obligations under this Public License where the Licensed Rights include
 | 
				
			||||||
 | 
					other Copyright and Similar Rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Section 5 – Disclaimer of Warranties and Limitation of Liability.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a. Unless otherwise separately undertaken by the Licensor, to the extent possible,
 | 
				
			||||||
 | 
					the Licensor offers the Licensed Material as-is and as-available, and makes
 | 
				
			||||||
 | 
					no representations or warranties of any kind concerning the Licensed Material,
 | 
				
			||||||
 | 
					whether express, implied, statutory, or other. This includes, without limitation,
 | 
				
			||||||
 | 
					warranties of title, merchantability, fitness for a particular purpose, non-infringement,
 | 
				
			||||||
 | 
					absence of latent or other defects, accuracy, or the presence or absence of
 | 
				
			||||||
 | 
					errors, whether or not known or discoverable. Where disclaimers of warranties
 | 
				
			||||||
 | 
					are not allowed in full or in part, this disclaimer may not apply to You.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					b. To the extent possible, in no event will the Licensor be liable to You
 | 
				
			||||||
 | 
					on any legal theory (including, without limitation, negligence) or otherwise
 | 
				
			||||||
 | 
					for any direct, special, indirect, incidental, consequential, punitive, exemplary,
 | 
				
			||||||
 | 
					or other losses, costs, expenses, or damages arising out of this Public License
 | 
				
			||||||
 | 
					or use of the Licensed Material, even if the Licensor has been advised of
 | 
				
			||||||
 | 
					the possibility of such losses, costs, expenses, or damages. Where a limitation
 | 
				
			||||||
 | 
					of liability is not allowed in full or in part, this limitation may not apply
 | 
				
			||||||
 | 
					to You.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					c. The disclaimer of warranties and limitation of liability provided above
 | 
				
			||||||
 | 
					shall be interpreted in a manner that, to the extent possible, most closely
 | 
				
			||||||
 | 
					approximates an absolute disclaimer and waiver of all liability.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Section 6 – Term and Termination.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a. This Public License applies for the term of the Copyright and Similar Rights
 | 
				
			||||||
 | 
					licensed here. However, if You fail to comply with this Public License, then
 | 
				
			||||||
 | 
					Your rights under this Public License terminate automatically.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					b. Where Your right to use the Licensed Material has terminated under Section
 | 
				
			||||||
 | 
					6(a), it reinstates:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. automatically as of the date the violation is cured, provided it is cured
 | 
				
			||||||
 | 
					within 30 days of Your discovery of the violation; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      2. upon express reinstatement by the Licensor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For the avoidance of doubt, this Section 6(b) does not affect any right the
 | 
				
			||||||
 | 
					Licensor may have to seek remedies for Your violations of this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					c. For the avoidance of doubt, the Licensor may also offer the Licensed Material
 | 
				
			||||||
 | 
					under separate terms or conditions or stop distributing the Licensed Material
 | 
				
			||||||
 | 
					at any time; however, doing so will not terminate this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Section 7 – Other Terms and Conditions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a. The Licensor shall not be bound by any additional or different terms or
 | 
				
			||||||
 | 
					conditions communicated by You unless expressly agreed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					b. Any arrangements, understandings, or agreements regarding the Licensed
 | 
				
			||||||
 | 
					Material not stated herein are separate from and independent of the terms
 | 
				
			||||||
 | 
					and conditions of this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Section 8 – Interpretation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a. For the avoidance of doubt, this Public License does not, and shall not
 | 
				
			||||||
 | 
					be interpreted to, reduce, limit, restrict, or impose conditions on any use
 | 
				
			||||||
 | 
					of the Licensed Material that could lawfully be made without permission under
 | 
				
			||||||
 | 
					this Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					b. To the extent possible, if any provision of this Public License is deemed
 | 
				
			||||||
 | 
					unenforceable, it shall be automatically reformed to the minimum extent necessary
 | 
				
			||||||
 | 
					to make it enforceable. If the provision cannot be reformed, it shall be severed
 | 
				
			||||||
 | 
					from this Public License without affecting the enforceability of the remaining
 | 
				
			||||||
 | 
					terms and conditions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					c. No term or condition of this Public License will be waived and no failure
 | 
				
			||||||
 | 
					to comply consented to unless expressly agreed to by the Licensor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					d. Nothing in this Public License constitutes or may be interpreted as a limitation
 | 
				
			||||||
 | 
					upon, or waiver of, any privileges and immunities that apply to the Licensor
 | 
				
			||||||
 | 
					or You, including from the legal processes of any jurisdiction or authority.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Creative Commons is not a party to its public licenses. Notwithstanding, Creative
 | 
				
			||||||
 | 
					Commons may elect to apply one of its public licenses to material it publishes
 | 
				
			||||||
 | 
					and in those instances will be considered the "Licensor." The text of the
 | 
				
			||||||
 | 
					Creative Commons public licenses is dedicated to the public domain under the
 | 
				
			||||||
 | 
					CC0 Public Domain Dedication. Except for the limited purpose of indicating
 | 
				
			||||||
 | 
					that material is shared under a Creative Commons public license or as otherwise
 | 
				
			||||||
 | 
					permitted by the Creative Commons policies published at creativecommons.org/policies,
 | 
				
			||||||
 | 
					Creative Commons does not authorize the use of the trademark "Creative Commons"
 | 
				
			||||||
 | 
					or any other trademark or logo of Creative Commons without its prior written
 | 
				
			||||||
 | 
					consent including, without limitation, in connection with any unauthorized
 | 
				
			||||||
 | 
					modifications to any of its public licenses or any other arrangements, understandings,
 | 
				
			||||||
 | 
					or agreements concerning use of licensed material. For the avoidance of doubt,
 | 
				
			||||||
 | 
					this paragraph does not form part of the public licenses.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Creative Commons may be contacted at creativecommons.org.
 | 
				
			||||||
							
								
								
									
										27
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					# @odit/lfk-frontend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ✒️ Overview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is an API client for [https://git.odit.services/lfk/backend](@lfk/backend)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This application is intended for use by admin users/ members only.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 🚀 Getting Started
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					pnpm i
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Development
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					pnpm dev
 | 
				
			||||||
 | 
					/
 | 
				
			||||||
 | 
					pnpm dev --open
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					pnpm build
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
const config = {
 | 
					 | 
				
			||||||
	baseurl: 'https://dev.lauf-fuer-kaya.de',
 | 
					 | 
				
			||||||
	fallback_username: 'admin',
 | 
					 | 
				
			||||||
	fallback_password: '72fpTzsev4xUu78QPs2FCbwZ3',
 | 
					 | 
				
			||||||
	prefersHashRouting: true
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										22
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					<!doctype html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					  <head>
 | 
				
			||||||
 | 
					    <meta charset="utf-8" />
 | 
				
			||||||
 | 
					    <link rel="icon" href="/favicon.png" />
 | 
				
			||||||
 | 
					    <link rel="manifest" href="/manifest.webmanifest" />
 | 
				
			||||||
 | 
					    <link rel="apple-touch-icon" href="/lfk-logo.png" />
 | 
				
			||||||
 | 
					    <meta name="theme-color" content="#FFFFFF" />
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
				
			||||||
 | 
					    <meta name="description" content="Lauf Für Kaya! - Admin" />
 | 
				
			||||||
 | 
					    <title>Lauf für Kaya! - Admin</title>
 | 
				
			||||||
 | 
					  </head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <body>
 | 
				
			||||||
 | 
					    <span style="display: none; visibility: hidden" id="buildinfo"
 | 
				
			||||||
 | 
					      >RELEASE_INFO-1.11.5-RELEASE_INFO</span
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					    <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
				
			||||||
 | 
					    <script src="/env.js"></script>
 | 
				
			||||||
 | 
					    <script type="module" src="/src/main.js"></script>
 | 
				
			||||||
 | 
					  </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										16
									
								
								nginx.conf
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								nginx.conf
									
									
									
									
									
								
							@@ -6,10 +6,24 @@ http {
 | 
				
			|||||||
    server {
 | 
					    server {
 | 
				
			||||||
        error_page 404 /index.html;
 | 
					        error_page 404 /index.html;
 | 
				
			||||||
        root /usr/share/nginx/html;
 | 
					        root /usr/share/nginx/html;
 | 
				
			||||||
 | 
					        location /assets {
 | 
				
			||||||
 | 
					            expires 1y;
 | 
				
			||||||
 | 
					            log_not_found off;
 | 
				
			||||||
 | 
					            access_log off;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        location = /index.html {
 | 
				
			||||||
 | 
					            add_header Cache-Control 'no-store';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        location = / {
 | 
				
			||||||
 | 
					            add_header Cache-Control 'no-store';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        location = /env.js {
 | 
				
			||||||
 | 
					            add_header Cache-Control 'no-store';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        location / {
 | 
					        location / {
 | 
				
			||||||
            try_files $uri $uri/ /index.html;
 | 
					            try_files $uri $uri/ /index.html;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
 | 
					        location ~* \.(?:ico|css|gif|jpe?g|png)$ {
 | 
				
			||||||
            expires 1y;
 | 
					            expires 1y;
 | 
				
			||||||
            add_header Pragma public;
 | 
					            add_header Pragma public;
 | 
				
			||||||
            add_header Cache-Control "public";
 | 
					            add_header Cache-Control "public";
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								order.js
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								order.js
									
									
									
									
									
								
							@@ -1,11 +1,13 @@
 | 
				
			|||||||
const fs = require('fs');
 | 
					import fs from "fs";
 | 
				
			||||||
// get all language files
 | 
					// get all language files
 | 
				
			||||||
const files = fs.readdirSync('./src/locales/');
 | 
					const files = fs.readdirSync("./src/locales/");
 | 
				
			||||||
files.forEach((f) => {
 | 
					files.forEach((f) => {
 | 
				
			||||||
  // read file as object
 | 
					  // read file as object
 | 
				
			||||||
  const unordered = JSON.parse(fs.readFileSync(`src/locales/${f}`));
 | 
					  const unordered = JSON.parse(fs.readFileSync(`src/locales/${f}`));
 | 
				
			||||||
  // order object by keys alpabetically A-Z
 | 
					  // order object by keys alpabetically A-Z
 | 
				
			||||||
	const ordered = Object.keys(unordered).sort().reduce((obj, key) => {
 | 
					  const ordered = Object.keys(unordered)
 | 
				
			||||||
 | 
					    .sort()
 | 
				
			||||||
 | 
					    .reduce((obj, key) => {
 | 
				
			||||||
      obj[key] = unordered[key];
 | 
					      obj[key] = unordered[key];
 | 
				
			||||||
      return obj;
 | 
					      return obj;
 | 
				
			||||||
    }, {});
 | 
					    }, {});
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										79
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								package.json
									
									
									
									
									
								
							@@ -1,57 +1,66 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "@odit/lfk-frontend",
 | 
					  "name": "@odit/lfk-frontend",
 | 
				
			||||||
	"version": "0.1.5",
 | 
					  "version": "1.11.5",
 | 
				
			||||||
 | 
					  "type": "module",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "i18n-order": "node order.js",
 | 
					    "i18n-order": "node order.js",
 | 
				
			||||||
		"dev": "snowpack dev",
 | 
					    "dev": "vite",
 | 
				
			||||||
		"build": "snowpack build",
 | 
					    "format": "prettier --write --plugin-search-dir=. .",
 | 
				
			||||||
		"build:sw": "workbox generateSW workbox-config.js",
 | 
					    "build": "vite build",
 | 
				
			||||||
    "release": "release-it",
 | 
					    "release": "release-it",
 | 
				
			||||||
		"changelog": "npx auto-changelog --commit-limit false --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs",
 | 
					 | 
				
			||||||
    "licenses:export": "license-exporter --json -o public"
 | 
					    "licenses:export": "license-exporter --json -o public"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
	"dependencies": {
 | 
					  "license": "CC-BY-NC-SA-4.0",
 | 
				
			||||||
		"@odit/lfk-client-js": "0.0.10",
 | 
					 | 
				
			||||||
		"filepond": "4.25.1",
 | 
					 | 
				
			||||||
		"gridjs": "3.2.1",
 | 
					 | 
				
			||||||
		"localforage": "1.9.0",
 | 
					 | 
				
			||||||
		"lodash.isequal": "^4.5.0",
 | 
					 | 
				
			||||||
		"svelte-filepond": "0.0.1",
 | 
					 | 
				
			||||||
		"svelte-focus-trap": "1.0.1",
 | 
					 | 
				
			||||||
		"svelte-i18n": "3.3.0",
 | 
					 | 
				
			||||||
		"tailwindcss": "2.0.2",
 | 
					 | 
				
			||||||
		"tinro": "0.5.6",
 | 
					 | 
				
			||||||
		"toastify-js": "1.9.3",
 | 
					 | 
				
			||||||
		"validator": "13.5.2"
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
		"@odit/license-exporter": "0.0.9",
 | 
					    "@odit/license-exporter": "0.2.0",
 | 
				
			||||||
		"@snowpack/plugin-svelte": "3.4.1",
 | 
					    "@sveltejs/vite-plugin-svelte": "2.1.1",
 | 
				
			||||||
		"auto-changelog": "^2.2.1",
 | 
					    "@types/papaparse": "^5.3.15",
 | 
				
			||||||
		"autoprefixer": "10.2.1",
 | 
					    "@types/underscore": "^1.13.0",
 | 
				
			||||||
		"postcss": "8.2.4",
 | 
					    "auto-changelog": "2.5.0",
 | 
				
			||||||
		"postcss-load-config": "3.0.0",
 | 
					    "prettier": "3.5.3",
 | 
				
			||||||
		"release-it": "^14.2.2",
 | 
					    "prettier-plugin-svelte": "3.3.3",
 | 
				
			||||||
		"snowpack": "3.0.0-rc.2",
 | 
					    "release-it": "17.10.0",
 | 
				
			||||||
		"svelte": "3.31.2",
 | 
					    "svelte-select": "3.17.0",
 | 
				
			||||||
		"svelte-preprocess": "4.6.1",
 | 
					    "vite": "6.3.2"
 | 
				
			||||||
		"workbox-cli": "6.0.2"
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "release-it": {
 | 
					  "release-it": {
 | 
				
			||||||
    "git": {
 | 
					    "git": {
 | 
				
			||||||
      "commit": true,
 | 
					      "commit": true,
 | 
				
			||||||
      "requireCleanWorkingDir": false,
 | 
					      "requireCleanWorkingDir": false,
 | 
				
			||||||
			"commitMessage": "🚀RELEASE v${version}",
 | 
					      "commitMessage": "chore(release): ${version}",
 | 
				
			||||||
			"push": false,
 | 
					      "push": true,
 | 
				
			||||||
      "tag": true,
 | 
					      "tag": true,
 | 
				
			||||||
			"tagName": null,
 | 
					      "tagName": "${version}",
 | 
				
			||||||
			"tagAnnotation": "v${version}"
 | 
					      "tagAnnotation": "${version}"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "npm": {
 | 
					    "npm": {
 | 
				
			||||||
      "publish": false
 | 
					      "publish": false
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "hooks": {
 | 
					    "hooks": {
 | 
				
			||||||
			"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js  && git add public/index.html"
 | 
					      "after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js  && git add index.html && node order.js  && git add src/locales"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@bwip-js/browser": "^4.6.0",
 | 
				
			||||||
 | 
					    "@fontsource/athiti": "^5.2.5",
 | 
				
			||||||
 | 
					    "@odit/lfk-client-js": "1.2.4",
 | 
				
			||||||
 | 
					    "@paralleldrive/cuid2": "2.2.2",
 | 
				
			||||||
 | 
					    "@tailwindcss/vite": "^4.1.4",
 | 
				
			||||||
 | 
					    "@tanstack/svelte-table": "8.9.1",
 | 
				
			||||||
 | 
					    "check-password-strength": "2.0.10",
 | 
				
			||||||
 | 
					    "html5-qrcode": "^2.3.8",
 | 
				
			||||||
 | 
					    "localforage": "1.10.0",
 | 
				
			||||||
 | 
					    "papaparse": "^5.5.2",
 | 
				
			||||||
 | 
					    "svelte": "3.58.0",
 | 
				
			||||||
 | 
					    "svelte-french-toast": "1.2.0",
 | 
				
			||||||
 | 
					    "svelte-i18n": "4.0.1",
 | 
				
			||||||
 | 
					    "tailwindcss": "^4.1.4",
 | 
				
			||||||
 | 
					    "tinro": "0.6.12",
 | 
				
			||||||
 | 
					    "underscore": "^1.13.7",
 | 
				
			||||||
 | 
					    "validator": "13.15.0",
 | 
				
			||||||
 | 
					    "xlsx": "0.18.5"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "volta": {
 | 
				
			||||||
 | 
					    "node": "20.0.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3980
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										3980
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3
									
								
								pnpm-workspace.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								pnpm-workspace.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					onlyBuiltDependencies:
 | 
				
			||||||
 | 
					  - es5-ext
 | 
				
			||||||
 | 
					  - esbuild
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								public/beep.mp3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/beep.mp3
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,5 +1,12 @@
 | 
				
			|||||||
const config = {
 | 
					const config = {
 | 
				
			||||||
	baseurl: 'http://localhost:4010',
 | 
					  baseurl: "http://localhost:4010",
 | 
				
			||||||
 | 
					  baseurl_selfservice: "http://localhost:5174",
 | 
				
			||||||
 | 
					  baseurl_documentserver: "http://localhost:4010/documents",
 | 
				
			||||||
 | 
					  documentserver_key:
 | 
				
			||||||
 | 
					    "NqZSYTy5AFQ7MppbLW5moqpTk7u7YrNUHKYhKYuThnnya2WpCOIU694hIZT1FzYe",
 | 
				
			||||||
  // optional
 | 
					  // optional
 | 
				
			||||||
	prefersHashRouting: true
 | 
					  default_username: "demo",
 | 
				
			||||||
 | 
					  default_password: "demo",
 | 
				
			||||||
 | 
					  prefersHashRouting: true,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					window.config = config;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
  <meta charset="utf-8" />
 | 
					 | 
				
			||||||
  <link rel="icon" href="/favicon.png" />
 | 
					 | 
				
			||||||
  <link rel="manifest" href="/manifest.webmanifest">
 | 
					 | 
				
			||||||
  <link rel="apple-touch-icon" href="/lfk-logo.png">
 | 
					 | 
				
			||||||
  <meta name="theme-color" content="#FFFFFF">
 | 
					 | 
				
			||||||
  <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
					 | 
				
			||||||
  <meta name="description" content="Lauf Für Kaya! - Admin" />
 | 
					 | 
				
			||||||
  <title>Lauf für Kaya! - Admin</title>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<body>
 | 
					 | 
				
			||||||
  <span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.1.5-RELEASE_INFO</span>
 | 
					 | 
				
			||||||
  <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
					 | 
				
			||||||
  <script src="/env.js"></script>
 | 
					 | 
				
			||||||
  <script defer type="module" src="/_dist_/index.js"></script>
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,4 +0,0 @@
 | 
				
			|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98.1 118">
 | 
					 | 
				
			||||||
  <path fill="#ff3e00" d="M91.8 15.6C80.9-.1 59.2-4.7 43.6 5.2L16.1 22.8A31.25 31.25 0 001.9 43.9c-1.3 7.3-.2 14.8 3.3 21.3-2.4 3.6-4 7.6-4.7 11.8-1.6 8.9.5 18.1 5.7 25.4 11 15.7 32.6 20.3 48.2 10.4l27.5-17.5c7.5-4.7 12.7-12.4 14.2-21.1 1.3-7.3.2-14.8-3.3-21.3 2.4-3.6 4-7.6 4.7-11.8 1.7-9-.4-18.2-5.7-25.5"/>
 | 
					 | 
				
			||||||
  <path fill="#fff" d="M40.9 103.9a21.8 21.8 0 01-23.4-8.7c-3.2-4.4-4.4-9.9-3.5-15.3l.6-2.6.5-1.6 1.4 1c3.3 2.4 6.9 4.2 10.8 5.4l1 .3-.1 1c-.1 1.4.3 2.9 1.1 4.1a6.62 6.62 0 008.8 2L65.5 72c1.4-.9 2.3-2.2 2.6-3.8.3-1.6-.1-3.3-1-4.6a6.56 6.56 0 00-8.8-1.9l-10.5 6.7a18.6 18.6 0 01-5.6 2.4 21.8 21.8 0 01-23.4-8.7 20.2 20.2 0 01-3.4-15.3c.9-5.2 4.1-9.9 8.6-12.7l27.5-17.5c1.7-1.1 3.6-1.9 5.6-2.5a21.8 21.8 0 0123.4 8.7c3.2 4.4 4.4 9.9 3.5 15.3-.2.9-.4 1.7-.7 2.6l-.5 1.6-1.4-1c-3.3-2.4-6.9-4.2-10.8-5.4l-1-.3.1-1c.1-1.4-.3-2.9-1.1-4.1a6.56 6.56 0 00-8.8-1.9L32.4 46.1c-1.4.9-2.3 2.2-2.6 3.8s.1 3.3 1 4.6a6.56 6.56 0 008.8 1.9l10.5-6.7c1.7-1.1 3.6-1.9 5.6-2.5a21.8 21.8 0 0123.4 8.7c3.2 4.4 4.4 9.9 3.5 15.3-.9 5.2-4.1 9.9-8.6 12.7l-27.5 17.5c-1.7 1.1-3.6 1.9-5.6 2.5"/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 1.1 KiB  | 
@@ -1,11 +1,18 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "Lauf für Kaya! - Admin",
 | 
					  "name": "Lauf für Kaya! - Admin",
 | 
				
			||||||
  "short_name": "LfK!Admin",
 | 
					  "short_name": "LfK!Admin",
 | 
				
			||||||
	"start_url": ".",
 | 
					  "start_url": "/?utm_source=pwa",
 | 
				
			||||||
 | 
					  "orientation": "portrait-primary",
 | 
				
			||||||
  "display": "standalone",
 | 
					  "display": "standalone",
 | 
				
			||||||
  "background_color": "#fff",
 | 
					  "background_color": "#fff",
 | 
				
			||||||
  "theme_color": "#fff",
 | 
					  "theme_color": "#fff",
 | 
				
			||||||
  "description": "Lauf für Kaya! - Admin",
 | 
					  "description": "Lauf für Kaya! - Admin",
 | 
				
			||||||
 | 
					  "shortcuts": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "Users",
 | 
				
			||||||
 | 
					      "url": "/users/?utm_source=pwa"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
  "icons": [
 | 
					  "icons": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "src": "/favicon.png",
 | 
					      "src": "/favicon.png",
 | 
				
			||||||
@@ -22,6 +29,11 @@
 | 
				
			|||||||
      "sizes": "1540x144",
 | 
					      "sizes": "1540x144",
 | 
				
			||||||
      "type": "image/png"
 | 
					      "type": "image/png"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
		{ "src": "/maskable_icon_x1.png", "sizes": "750x750", "type": "image/png", "purpose": "any maskable" }
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "/maskable_icon_x1.png",
 | 
				
			||||||
 | 
					      "sizes": "750x750",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "purpose": "any maskable"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,2 +0,0 @@
 | 
				
			|||||||
if(!self.define){const e=e=>{"require"!==e&&(e+=".js");let r=Promise.resolve();return i[e]||(r=new Promise((async r=>{if("document"in self){const i=document.createElement("script");i.src=e,document.head.appendChild(i),i.onload=r}else importScripts(e),r()}))),r.then((()=>{if(!i[e])throw new Error(`Module ${e} didn’t register its module`);return i[e]}))},r=(r,i)=>{Promise.all(r.map(e)).then((e=>i(1===e.length?e[0]:e)))},i={require:Promise.resolve(r)};self.define=(r,s,o)=>{i[r]||(i[r]=Promise.resolve().then((()=>{let i={};const c={uri:location.origin+r.slice(1)};return Promise.all(s.map((r=>{switch(r){case"exports":return i;case"module":return c;default:return e(r)}}))).then((e=>{const r=o(...e);return i.default||(i.default=r),i}))})))}}define("./sw.js",["./workbox-c8ead010"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.precacheAndRoute([{url:"favicon.ico",revision:"ba44f340afba5bb1a07f14decc15dd04"},{url:"favicon.png",revision:"07a9941cec62319578fa2a1734db9959"},{url:"favicon.svg",revision:"689d6c6fda51e359c0e5725d9e905064"},{url:"index.html",revision:"931c34f3675364dcc09411aa0f223776"},{url:"logo.svg",revision:"4c9e31a1f4268d7e36e22cda7656e561"},{url:"manifest.webmanifest",revision:"75c93eb352c4877216e77b1d7f73445f"},{url:"robots.txt",revision:"61c27d2cd39a713f7829422c3d9edcc7"}],{})}));
 | 
					 | 
				
			||||||
//# sourceMappingURL=sw.js.map
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,30 +0,0 @@
 | 
				
			|||||||
/** @type {import("snowpack").SnowpackUserConfig } */
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
	mount: {
 | 
					 | 
				
			||||||
		public: '/',
 | 
					 | 
				
			||||||
		src: '/_dist_'
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	plugins: [ '@snowpack/plugin-svelte' ],
 | 
					 | 
				
			||||||
	install: [
 | 
					 | 
				
			||||||
		/* ... */
 | 
					 | 
				
			||||||
	],
 | 
					 | 
				
			||||||
	installOptions: {
 | 
					 | 
				
			||||||
		/* ... */
 | 
					 | 
				
			||||||
		sourceMap: false
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	devOptions: {
 | 
					 | 
				
			||||||
		/* ... */
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	buildOptions: {
 | 
					 | 
				
			||||||
		/* ... */
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	proxy: {
 | 
					 | 
				
			||||||
		/* ... */
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	alias: {
 | 
					 | 
				
			||||||
		/* ... */
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	experiments: {
 | 
					 | 
				
			||||||
		optimize: { bundle: true, minify: true }
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										172
									
								
								src/App.svelte
									
									
									
									
									
								
							
							
						
						
									
										172
									
								
								src/App.svelte
									
									
									
									
									
								
							@@ -1,6 +1,4 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
  import "./TailwindStyles.svelte";
 | 
					 | 
				
			||||||
  import "toastify-js/src/toastify.css";
 | 
					 | 
				
			||||||
  import { Route, router } from "tinro";
 | 
					  import { Route, router } from "tinro";
 | 
				
			||||||
  router.subscribe((routeInfo) => {
 | 
					  router.subscribe((routeInfo) => {
 | 
				
			||||||
    window.scrollTo(0, 0);
 | 
					    window.scrollTo(0, 0);
 | 
				
			||||||
@@ -24,40 +22,67 @@
 | 
				
			|||||||
    name: "lfk_admin",
 | 
					    name: "lfk_admin",
 | 
				
			||||||
    version: 1.0,
 | 
					    version: 1.0,
 | 
				
			||||||
    storeName: "lfk_admin",
 | 
					    storeName: "lfk_admin",
 | 
				
			||||||
    description: "LfK! admin dashbaord",
 | 
					    description: "LfK! admin dashboard",
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					  window.onunhandledrejection = (event) => {
 | 
				
			||||||
 | 
					    if (event.reason.toString() == "Error: Unauthorized") {
 | 
				
			||||||
 | 
					      localForage.clear();
 | 
				
			||||||
 | 
					      location.replace("/");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
  //
 | 
					  //
 | 
				
			||||||
  import Login from "./components/Login.svelte";
 | 
					  import Login from "./components/auth/Login.svelte";
 | 
				
			||||||
  import Dashboard from "./components/Dashboard.svelte";
 | 
					  import Dashboard from "./components/dashboard/Dashboard.svelte";
 | 
				
			||||||
  import store from "./store.js";
 | 
					  import store from "./store.js";
 | 
				
			||||||
  import NotFound from "./components/NotFound.svelte";
 | 
					  import ForgotPassword from "./components/auth/ForgotPassword.svelte";
 | 
				
			||||||
  import ForgotPassword from "./components/ForgotPassword.svelte";
 | 
					  import MainDashContent from "./components/dashboard/MainDashContent.svelte";
 | 
				
			||||||
  import MainDashContent from "./components/MainDashContent.svelte";
 | 
					  import Users from "./components/users/Users.svelte";
 | 
				
			||||||
  import Users from "./components/Users.svelte";
 | 
					  import About from "./components/general/About.svelte";
 | 
				
			||||||
  import About from "./components/About.svelte";
 | 
					  import Settings from "./components/settings/Settings.svelte";
 | 
				
			||||||
  import Settings from "./components/Settings.svelte";
 | 
					  import Transition from "./components/base/Transition.svelte";
 | 
				
			||||||
  import Transition from "./components/Transition.svelte";
 | 
					  import Orgs from "./components/orgs/Orgs.svelte";
 | 
				
			||||||
  import Orgs from "./components/Orgs.svelte";
 | 
					  import CardAssignment from "./components/general/CardAssignment.svelte";
 | 
				
			||||||
  import Runners from "./components/Runners.svelte";
 | 
					  import Runners from "./components/runners/Runners.svelte";
 | 
				
			||||||
  import Footer from "./components/Footer.svelte";
 | 
					  import Footer from "./components/general/Footer.svelte";
 | 
				
			||||||
  import Tracks from "./components/Tracks.svelte";
 | 
					  import TracksOverview from "./components/tracks/TracksOverview.svelte";
 | 
				
			||||||
  import TracksOverview from "./components/TracksOverview.svelte";
 | 
					  import OrgDetail from "./components/orgs/OrgDetail.svelte";
 | 
				
			||||||
  import OrgDetail from "./components/OrgDetail.svelte";
 | 
					  import Teams from "./components/teams/Teams.svelte";
 | 
				
			||||||
  import Teams from "./components/Teams.svelte";
 | 
					  import { OpenAPI } from "@odit/lfk-client-js";
 | 
				
			||||||
  import { OpenAPI, AuthService } from "@odit/lfk-client-js";
 | 
					  import UserDetail from "./components/users/UserDetail.svelte";
 | 
				
			||||||
  import UserDetail from "./components/UserDetail.svelte";
 | 
					 | 
				
			||||||
  OpenAPI.BASE = config.baseurl;
 | 
					  OpenAPI.BASE = config.baseurl;
 | 
				
			||||||
  import { register as registerSW } from "./swmodule";
 | 
					  import TeamDetail from "./components/teams/TeamDetail.svelte";
 | 
				
			||||||
 | 
					  import UserPermissions from "./components/users/UserPermissions.svelte";
 | 
				
			||||||
 | 
					  import GroupPermissions from "./components/groups/GroupPermissions.svelte";
 | 
				
			||||||
 | 
					  import RunnerDetail from "./components/runners/RunnerDetail.svelte";
 | 
				
			||||||
 | 
					  import ResetPassword from "./components/auth/ResetPassword.svelte";
 | 
				
			||||||
 | 
					  import Contacts from "./components/contacts/Contacts.svelte";
 | 
				
			||||||
 | 
					  import ContactDetail from "./components/contacts/ContactDetail.svelte";
 | 
				
			||||||
 | 
					  import Donors from "./components/donors/Donors.svelte";
 | 
				
			||||||
 | 
					  import Groups from "./components/groups/Groups.svelte";
 | 
				
			||||||
 | 
					  import DonorDetail from "./components/donors/DonorDetail.svelte";
 | 
				
			||||||
 | 
					  import Donations from "./components/donations/Donations.svelte";
 | 
				
			||||||
 | 
					  import DonationDetail from "./components/donations/DonationDetail.svelte";
 | 
				
			||||||
 | 
					  import GroupDetail from "./components/groups/GroupDetail.svelte";
 | 
				
			||||||
 | 
					  import ScanStations from "./components/scanstations/ScanStations.svelte";
 | 
				
			||||||
 | 
					  import ScanStationDetail from "./components/scanstations/ScanStationDetail.svelte";
 | 
				
			||||||
 | 
					  import Scans from "./components/scans/Scans.svelte";
 | 
				
			||||||
 | 
					  import ScanDetail from "./components/scans/ScanDetail.svelte";
 | 
				
			||||||
 | 
					  import Cards from "./components/cards/Cards.svelte";
 | 
				
			||||||
 | 
					  import StatsClients from "./components/statsclients/StatsClients.svelte";
 | 
				
			||||||
 | 
					  import StatsClientDetail from "./components/statsclients/StatsClientDetail.svelte";
 | 
				
			||||||
  store.init();
 | 
					  store.init();
 | 
				
			||||||
  // registerSW();
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<Route>
 | 
					<Route>
 | 
				
			||||||
  {#if $router.path === '/forgot_password'}
 | 
					  {#if $router.path === "/forgot_password"}
 | 
				
			||||||
    <Route path="/forgot_password">
 | 
					    <Route path="/forgot_password">
 | 
				
			||||||
      <ForgotPassword />
 | 
					      <ForgotPassword />
 | 
				
			||||||
    </Route>
 | 
					    </Route>
 | 
				
			||||||
  {:else if $router.path === '/about'}
 | 
					  {:else if $router.path.includes("/reset")}
 | 
				
			||||||
 | 
					    <Route path="/reset/:resetkey" let:params>
 | 
				
			||||||
 | 
					      <ResetPassword {params} />
 | 
				
			||||||
 | 
					    </Route>
 | 
				
			||||||
 | 
					  {:else if $router.path === "/about"}
 | 
				
			||||||
    <Route path="/about">
 | 
					    <Route path="/about">
 | 
				
			||||||
      <About />
 | 
					      <About />
 | 
				
			||||||
    </Route>
 | 
					    </Route>
 | 
				
			||||||
@@ -71,9 +96,27 @@
 | 
				
			|||||||
          <Route path="/">
 | 
					          <Route path="/">
 | 
				
			||||||
            <Users />
 | 
					            <Users />
 | 
				
			||||||
          </Route>
 | 
					          </Route>
 | 
				
			||||||
          <Route path="/:userid" let:params>
 | 
					          <Route path="/:userid/*" let:params>
 | 
				
			||||||
 | 
					            <Route path="/">
 | 
				
			||||||
              <UserDetail {params} />
 | 
					              <UserDetail {params} />
 | 
				
			||||||
            </Route>
 | 
					            </Route>
 | 
				
			||||||
 | 
					            <Route path="/permissions/">
 | 
				
			||||||
 | 
					              <UserPermissions {params} />
 | 
				
			||||||
 | 
					            </Route>
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/groups/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <Groups />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <Route path="/:groupid/*" let:params>
 | 
				
			||||||
 | 
					            <Route path="/">
 | 
				
			||||||
 | 
					              <GroupDetail {params} />
 | 
				
			||||||
 | 
					            </Route>
 | 
				
			||||||
 | 
					            <Route path="/permissions/">
 | 
				
			||||||
 | 
					              <GroupPermissions {params} />
 | 
				
			||||||
 | 
					            </Route>
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
        </Route>
 | 
					        </Route>
 | 
				
			||||||
        <Route path="/tracks/*">
 | 
					        <Route path="/tracks/*">
 | 
				
			||||||
          <Route path="/">
 | 
					          <Route path="/">
 | 
				
			||||||
@@ -81,12 +124,35 @@
 | 
				
			|||||||
          </Route>
 | 
					          </Route>
 | 
				
			||||||
          <Route path="/:trackid" let:params />
 | 
					          <Route path="/:trackid" let:params />
 | 
				
			||||||
        </Route>
 | 
					        </Route>
 | 
				
			||||||
        <Route path="/runners">
 | 
					        <Route path="/runners/*">
 | 
				
			||||||
          <Runners />
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <Runners created_via="all" />
 | 
				
			||||||
          </Route>
 | 
					          </Route>
 | 
				
			||||||
        <Route path="/teams">
 | 
					          <Route path="/:runnerid" let:params>
 | 
				
			||||||
 | 
					            <RunnerDetail {params} />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/cardassignment/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <CardAssignment />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/teams/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
            <Teams />
 | 
					            <Teams />
 | 
				
			||||||
          </Route>
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <Route path="/:teamid" let:params>
 | 
				
			||||||
 | 
					            <TeamDetail {params} />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/contacts/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <Contacts />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <Route path="/:contact" let:params>
 | 
				
			||||||
 | 
					            <ContactDetail {params} />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
        <Route path="/orgs/*">
 | 
					        <Route path="/orgs/*">
 | 
				
			||||||
          <Route path="/">
 | 
					          <Route path="/">
 | 
				
			||||||
            <Orgs />
 | 
					            <Orgs />
 | 
				
			||||||
@@ -95,6 +161,54 @@
 | 
				
			|||||||
            <OrgDetail {params} />
 | 
					            <OrgDetail {params} />
 | 
				
			||||||
          </Route>
 | 
					          </Route>
 | 
				
			||||||
        </Route>
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/donors/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <Donors />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <Route path="/:donorid" let:params>
 | 
				
			||||||
 | 
					            <DonorDetail {params} />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/donations/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <Donations />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <Route path="/:donationid" let:params>
 | 
				
			||||||
 | 
					            <DonationDetail {params} />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/cards/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <Cards />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <!-- <Route path="/:scanid" let:params>
 | 
				
			||||||
 | 
					            <ScanDetail {params} />
 | 
				
			||||||
 | 
					          </Route> -->
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/scans/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <Scans />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <Route path="/:scanid" let:params>
 | 
				
			||||||
 | 
					            <ScanDetail {params} />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/scanstations/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <ScanStations />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <Route path="/:stationid" let:params>
 | 
				
			||||||
 | 
					            <ScanStationDetail {params} />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
 | 
					        <Route path="/statsclients/*">
 | 
				
			||||||
 | 
					          <Route path="/">
 | 
				
			||||||
 | 
					            <StatsClients />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					          <Route path="/:clientid" let:params>
 | 
				
			||||||
 | 
					            <StatsClientDetail {params} />
 | 
				
			||||||
 | 
					          </Route>
 | 
				
			||||||
 | 
					        </Route>
 | 
				
			||||||
        <Route path="/about">
 | 
					        <Route path="/about">
 | 
				
			||||||
          <About />
 | 
					          <About />
 | 
				
			||||||
        </Route>
 | 
					        </Route>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
<style global>
 | 
					 | 
				
			||||||
  /*! @import */
 | 
					 | 
				
			||||||
  @tailwind base;
 | 
					 | 
				
			||||||
  @tailwind components;
 | 
					 | 
				
			||||||
  @tailwind utilities;
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@@ -1,194 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  import { clickOutside } from "./outsideclick";
 | 
					 | 
				
			||||||
  import { focusTrap } from "svelte-focus-trap";
 | 
					 | 
				
			||||||
  export let modal_open;
 | 
					 | 
				
			||||||
  (function () {
 | 
					 | 
				
			||||||
    document.onkeydown = function (e) {
 | 
					 | 
				
			||||||
      e = e || window.event;
 | 
					 | 
				
			||||||
      if (e.key === "Escape") {
 | 
					 | 
				
			||||||
        modal_open = false;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
  })();
 | 
					 | 
				
			||||||
  const license_promise = fetch("/licenses.json");
 | 
					 | 
				
			||||||
  let licenses = [];
 | 
					 | 
				
			||||||
  $: currentlicense = "";
 | 
					 | 
				
			||||||
  $: licensetext = "";
 | 
					 | 
				
			||||||
  license_promise
 | 
					 | 
				
			||||||
    .then((response) => response.json())
 | 
					 | 
				
			||||||
    .then((json) => {
 | 
					 | 
				
			||||||
      licenses = json;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if modal_open}
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="fixed z-10 inset-0 overflow-y-auto"
 | 
					 | 
				
			||||||
    use:focusTrap
 | 
					 | 
				
			||||||
    use:clickOutside
 | 
					 | 
				
			||||||
    on:click_outside={() => {
 | 
					 | 
				
			||||||
      modal_open = false;
 | 
					 | 
				
			||||||
    }}>
 | 
					 | 
				
			||||||
    <div
 | 
					 | 
				
			||||||
      class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
 | 
					 | 
				
			||||||
      <div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
					 | 
				
			||||||
        <div
 | 
					 | 
				
			||||||
          class="absolute inset-0 bg-gray-500 opacity-75"
 | 
					 | 
				
			||||||
          data-id="modal_backdrop" />
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
      <span
 | 
					 | 
				
			||||||
        class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
					 | 
				
			||||||
        aria-hidden="true">​</span>
 | 
					 | 
				
			||||||
      <div
 | 
					 | 
				
			||||||
        class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
 | 
					 | 
				
			||||||
        role="dialog"
 | 
					 | 
				
			||||||
        aria-modal="true"
 | 
					 | 
				
			||||||
        aria-labelledby="modal-headline">
 | 
					 | 
				
			||||||
        <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
 | 
					 | 
				
			||||||
          <div class="sm:flex sm:items-start">
 | 
					 | 
				
			||||||
            <div
 | 
					 | 
				
			||||||
              class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
 | 
					 | 
				
			||||||
              <svg
 | 
					 | 
				
			||||||
                fill="currentColor"
 | 
					 | 
				
			||||||
                class="h-6 w-6 text-blue-600"
 | 
					 | 
				
			||||||
                xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
                viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
                width="24"
 | 
					 | 
				
			||||||
                height="24"><path fill="none" d="M0 0h24v24H0z" />
 | 
					 | 
				
			||||||
                <path
 | 
					 | 
				
			||||||
                  d="M14 20v2H2v-2h12zM14.586.686l7.778 7.778L20.95 9.88l-1.06-.354L17.413 12l5.657 5.657-1.414 1.414L16 13.414l-2.404 2.404.283 1.132-1.415 1.414-7.778-7.778 1.415-1.414 1.13.282 6.294-6.293-.353-1.06L14.586.686z" /></svg>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
 | 
					 | 
				
			||||||
              <h3 class="text-lg leading-6 font-medium">
 | 
					 | 
				
			||||||
                {$_('read-license')}
 | 
					 | 
				
			||||||
              </h3>
 | 
					 | 
				
			||||||
              <div class="mt-2 mb-6">
 | 
					 | 
				
			||||||
                <p class="text-sm text-gray-500">{currentlicense}</p>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
              <div class="mt-2 mb-6">
 | 
					 | 
				
			||||||
                <p class="text-sm text-gray-500">{licensetext}</p>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
 | 
					 | 
				
			||||||
          <button
 | 
					 | 
				
			||||||
            on:click={() => {
 | 
					 | 
				
			||||||
              modal_open = false;
 | 
					 | 
				
			||||||
            }}
 | 
					 | 
				
			||||||
            type="button"
 | 
					 | 
				
			||||||
            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
 | 
					 | 
				
			||||||
            {$_('close')}
 | 
					 | 
				
			||||||
          </button>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
<!-- /// -->
 | 
					 | 
				
			||||||
<div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12">
 | 
					 | 
				
			||||||
  <div class="text-center mb-8">
 | 
					 | 
				
			||||||
    <h1
 | 
					 | 
				
			||||||
      class="mt-9 font-display text-4xl leading-none font-semibold text-white sm:text-5xl lg:text-6xl">
 | 
					 | 
				
			||||||
      {$_('about')}
 | 
					 | 
				
			||||||
      🧾
 | 
					 | 
				
			||||||
    </h1>
 | 
					 | 
				
			||||||
    <p
 | 
					 | 
				
			||||||
      class="mt-2 max-w-xl mx-auto text-xl lg:max-w-3xl lg:text-2xl text-gray-300">
 | 
					 | 
				
			||||||
      Lauf für Kaya!
 | 
					 | 
				
			||||||
      <strong class="text-white font-medium">
 | 
					 | 
				
			||||||
        {$_('by')}
 | 
					 | 
				
			||||||
        <a href="https://odit.services" class="underline">ODIT.Services</a>
 | 
					 | 
				
			||||||
      </strong>
 | 
					 | 
				
			||||||
      <br />
 | 
					 | 
				
			||||||
      <span class="text-lg">{$_('lfk-is-os')}</span>
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="pt-0 pb-16 overflow-hidden lg:pt-12 lg:py-24">
 | 
					 | 
				
			||||||
  <div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
 | 
					 | 
				
			||||||
    <h2 class="text-4xl font-display font-semibold md:text-5xl">
 | 
					 | 
				
			||||||
      {$_('credits')}
 | 
					 | 
				
			||||||
    </h2>
 | 
					 | 
				
			||||||
    <div class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
 | 
					 | 
				
			||||||
      <p class="text-center">{$_('oss_credit_description')}</p>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="w-screen leading-8 pl-5 mt-5">
 | 
					 | 
				
			||||||
      {#await license_promise}
 | 
					 | 
				
			||||||
        <p class="text-center w-full">{$_('licenses-are-being-loaded')}</p>
 | 
					 | 
				
			||||||
      {:then}
 | 
					 | 
				
			||||||
        <table>
 | 
					 | 
				
			||||||
          <thead>
 | 
					 | 
				
			||||||
            <tr>
 | 
					 | 
				
			||||||
              <th>{$_('dependency_name')}</th>
 | 
					 | 
				
			||||||
              <th>{$_('license')}</th>
 | 
					 | 
				
			||||||
              <th>{$_('repo_link')}</th>
 | 
					 | 
				
			||||||
              <th>{$_('installed-version')}</th>
 | 
					 | 
				
			||||||
              <th>{$_('author')}</th>
 | 
					 | 
				
			||||||
            </tr>
 | 
					 | 
				
			||||||
          </thead>
 | 
					 | 
				
			||||||
          <tbody>
 | 
					 | 
				
			||||||
            {#each licenses as l}
 | 
					 | 
				
			||||||
              <tr>
 | 
					 | 
				
			||||||
                <td>{l.name}</td>
 | 
					 | 
				
			||||||
                <td>
 | 
					 | 
				
			||||||
                  {l.license || '?'}<br /><span
 | 
					 | 
				
			||||||
                    class="underline cursor-pointer"
 | 
					 | 
				
			||||||
                    on:click={() => {
 | 
					 | 
				
			||||||
                      modal_open = true;
 | 
					 | 
				
			||||||
                      currentlicense = l.name + '@' + l.version;
 | 
					 | 
				
			||||||
                      licensetext = l.licensetext || $_('no-license-text-could-be-found');
 | 
					 | 
				
			||||||
                    }}>{$_('read-license')}</span>
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
                <td>
 | 
					 | 
				
			||||||
                  {(l.repo?.url || l.repo)
 | 
					 | 
				
			||||||
                    .replace('git+', '')
 | 
					 | 
				
			||||||
                    .replace('git://', '')}
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
                <td>{l.version || '?'}</td>
 | 
					 | 
				
			||||||
                <td>{l.author?.name || l.author || '?'}</td>
 | 
					 | 
				
			||||||
              </tr>
 | 
					 | 
				
			||||||
            {/each}
 | 
					 | 
				
			||||||
          </tbody>
 | 
					 | 
				
			||||||
        </table>
 | 
					 | 
				
			||||||
      {:catch error}
 | 
					 | 
				
			||||||
        <div
 | 
					 | 
				
			||||||
          class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
 | 
					 | 
				
			||||||
          <span class="inline-block align-middle mr-8">
 | 
					 | 
				
			||||||
            <b class="capitalize">{$_('general_promise_error')}</b>
 | 
					 | 
				
			||||||
            {error}
 | 
					 | 
				
			||||||
          </span>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      {/await}
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <h2 class="text-4xl font-display font-semibold md:text-5xl">{$_('faq')}</h2>
 | 
					 | 
				
			||||||
    <div class="mt-6 border-t-2 border-gray-100 pt-10">
 | 
					 | 
				
			||||||
      <dl class="md:grid md:grid-cols-2 md:gap-8">
 | 
					 | 
				
			||||||
        <div>
 | 
					 | 
				
			||||||
          <div>
 | 
					 | 
				
			||||||
            <dt class="text-lg leading-6 font-medium">Q</dt>
 | 
					 | 
				
			||||||
            <dd class="mt-2">
 | 
					 | 
				
			||||||
              <p class="text-base text-gray-500">A</p>
 | 
					 | 
				
			||||||
            </dd>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div class="mt-12 sm:mt-0">
 | 
					 | 
				
			||||||
          <div id="team-pricing">
 | 
					 | 
				
			||||||
            <dt class="text-lg leading-6 font-medium">Q</dt>
 | 
					 | 
				
			||||||
            <dd class="mt-2">
 | 
					 | 
				
			||||||
              <p class="text-base text-gray-500">A</p>
 | 
					 | 
				
			||||||
            </dd>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div class="mt-12">
 | 
					 | 
				
			||||||
            <dt class="text-lg leading-6 font-medium">Q</dt>
 | 
					 | 
				
			||||||
            <dd class="mt-2">
 | 
					 | 
				
			||||||
              <p class="text-base text-gray-500">A</p>
 | 
					 | 
				
			||||||
            </dd>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </dl>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,80 +0,0 @@
 | 
				
			|||||||
<h3 class="text-lg">Standard Avatars</h3>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-4 h-4">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-8 h-8">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-12 h-12">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-16 h-16">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-20 h-20">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-24 h-24">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<h3 class="text-lg">Status Avatars</h3>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-4 h-4">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
  <div class="absolute rounded-full right-0 bottom-0 w-1 h-1 bg-gray-200" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-8 h-8">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
  <div class="absolute rounded-full right-0 bottom-0 w-2 h-2 bg-green-400" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-12 h-12">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
  <div class="absolute rounded-full right-0 bottom-0 w-4 h-4 bg-red-600" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-16 h-16">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
  <div class="absolute rounded-full right-0 bottom-0 w-5 h-5 bg-gray-200" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-20 h-20">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
  <div class="absolute rounded-full right-0 bottom-0 w-6 h-6 bg-green-400" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="relative rounded-full w-24 h-24">
 | 
					 | 
				
			||||||
  <img
 | 
					 | 
				
			||||||
    alt=""
 | 
					 | 
				
			||||||
    src="https://gustui.s3.amazonaws.com/avatar.png"
 | 
					 | 
				
			||||||
    class="absolute left-0 top-0 w-full h-full rounded-full object-cover" />
 | 
					 | 
				
			||||||
  <div class="absolute rounded-full right-0 bottom-0 w-6 h-6 bg-red-600" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,53 +0,0 @@
 | 
				
			|||||||
<h3 class="text-lg">badges</h3>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="text-sm font-medium bg-green-100 py-1 px-2 rounded text-green-500 align-middle">Paid</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="text-sm font-medium bg-red-100 py-1 px-2 rounded text-red-500 align-middle">Overdue</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-blue-600">Primary</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-gray-600">Secondary</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-green-600">Success</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-red-600">Danger</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="rounded-sm py-1 px-2 text-xs font-medium text-black bg-yellow-400">Warning</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-indigo-300">Info</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="rounded-sm py-1 px-2 text-xs font-medium text-black bg-gray-200">Light</span>
 | 
					 | 
				
			||||||
<span
 | 
					 | 
				
			||||||
  class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-gray-900">Dark</span>
 | 
					 | 
				
			||||||
<h3 class="text-lg">closable badges</h3>
 | 
					 | 
				
			||||||
<span class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-blue-600">
 | 
					 | 
				
			||||||
  Primary
 | 
					 | 
				
			||||||
  <span class="ml-2 text-base cursor-pointer">×</span>
 | 
					 | 
				
			||||||
</span>
 | 
					 | 
				
			||||||
<span class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-gray-600">
 | 
					 | 
				
			||||||
  Secondary
 | 
					 | 
				
			||||||
  <span class="ml-2 text-base cursor-pointer">×</span>
 | 
					 | 
				
			||||||
</span>
 | 
					 | 
				
			||||||
<span class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-green-600">
 | 
					 | 
				
			||||||
  Success
 | 
					 | 
				
			||||||
  <span class="ml-2 text-base cursor-pointer">×</span>
 | 
					 | 
				
			||||||
</span>
 | 
					 | 
				
			||||||
<span class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-red-600">
 | 
					 | 
				
			||||||
  Danger
 | 
					 | 
				
			||||||
  <span class="ml-2 text-base cursor-pointer">×</span>
 | 
					 | 
				
			||||||
</span>
 | 
					 | 
				
			||||||
<span class="rounded-sm py-1 px-2 text-xs font-medium text-black bg-yellow-400">
 | 
					 | 
				
			||||||
  Warning
 | 
					 | 
				
			||||||
  <span class="ml-2 text-base cursor-pointer">×</span>
 | 
					 | 
				
			||||||
</span>
 | 
					 | 
				
			||||||
<span class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-indigo-300">
 | 
					 | 
				
			||||||
  Info
 | 
					 | 
				
			||||||
  <span class="ml-2 text-base cursor-pointer">×</span>
 | 
					 | 
				
			||||||
</span>
 | 
					 | 
				
			||||||
<span class="rounded-sm py-1 px-2 text-xs font-medium text-black bg-gray-200">
 | 
					 | 
				
			||||||
  Light<span class="ml-2 text-base cursor-pointer">×</span>
 | 
					 | 
				
			||||||
</span>
 | 
					 | 
				
			||||||
<span class="rounded-sm py-1 px-2 text-xs font-medium text-white bg-gray-900">
 | 
					 | 
				
			||||||
  Dark
 | 
					 | 
				
			||||||
  <span class="ml-2 text-base cursor-pointer">×</span>
 | 
					 | 
				
			||||||
</span>
 | 
					 | 
				
			||||||
@@ -1,62 +0,0 @@
 | 
				
			|||||||
<div class="flex flex-row mb-4">
 | 
					 | 
				
			||||||
  <div class="w-full">
 | 
					 | 
				
			||||||
    <nav class="w-full flex">
 | 
					 | 
				
			||||||
      <ol class="list-none flex flex-row items-center justify-start">
 | 
					 | 
				
			||||||
        <li class="mr-2 flex items-center">
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            stroke="currentColor"
 | 
					 | 
				
			||||||
            fill="none"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            class="h-3 w-3 stroke-current"
 | 
					 | 
				
			||||||
            height="1em"
 | 
					 | 
				
			||||||
            width="1em"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"><path
 | 
					 | 
				
			||||||
              d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
 | 
					 | 
				
			||||||
            <polyline points="9 22 9 12 15 12 15 22" /></svg>
 | 
					 | 
				
			||||||
        </li>
 | 
					 | 
				
			||||||
        <li class="flex items-center">
 | 
					 | 
				
			||||||
          <a class="mr-2" href="/">Home</a><svg
 | 
					 | 
				
			||||||
            stroke="currentColor"
 | 
					 | 
				
			||||||
            fill="none"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            class="h-3 w-3 mr-2 stroke-current"
 | 
					 | 
				
			||||||
            height="1em"
 | 
					 | 
				
			||||||
            width="1em"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"><line
 | 
					 | 
				
			||||||
              x1="5"
 | 
					 | 
				
			||||||
              y1="12"
 | 
					 | 
				
			||||||
              x2="19"
 | 
					 | 
				
			||||||
              y2="12" />
 | 
					 | 
				
			||||||
            <polyline points="12 5 19 12 12 19" /></svg>
 | 
					 | 
				
			||||||
        </li>
 | 
					 | 
				
			||||||
        <li class="flex items-center">
 | 
					 | 
				
			||||||
          <a class="mr-2" href="/">Second level</a><svg
 | 
					 | 
				
			||||||
            stroke="currentColor"
 | 
					 | 
				
			||||||
            fill="none"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            class="h-3 w-3 mr-2 stroke-current"
 | 
					 | 
				
			||||||
            height="1em"
 | 
					 | 
				
			||||||
            width="1em"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"><line
 | 
					 | 
				
			||||||
              x1="5"
 | 
					 | 
				
			||||||
              y1="12"
 | 
					 | 
				
			||||||
              x2="19"
 | 
					 | 
				
			||||||
              y2="12" />
 | 
					 | 
				
			||||||
            <polyline points="12 5 19 12 12 19" /></svg>
 | 
					 | 
				
			||||||
        </li>
 | 
					 | 
				
			||||||
        <li class="flex items-center">
 | 
					 | 
				
			||||||
          <a class="mr-2" href="/">Third level</a>
 | 
					 | 
				
			||||||
        </li>
 | 
					 | 
				
			||||||
      </ol>
 | 
					 | 
				
			||||||
    </nav>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,75 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import Avatars from "./Avatars.svelte";
 | 
					 | 
				
			||||||
  import Badges from "./Badges.svelte";
 | 
					 | 
				
			||||||
  import BreadcrumbNav from "./BreadcrumbNav.svelte";
 | 
					 | 
				
			||||||
  import FileUpload from "./FileUpload.svelte";
 | 
					 | 
				
			||||||
  import Pagination from "./Pagination.svelte";
 | 
					 | 
				
			||||||
  import Table from "./Table.svelte";
 | 
					 | 
				
			||||||
  import Tabs from "./Tabs.svelte";
 | 
					 | 
				
			||||||
  import Tags from "./Tags.svelte";
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="border-4 border-dashed rounded h-96 mb-4" />
 | 
					 | 
				
			||||||
<div class="mb-8">
 | 
					 | 
				
			||||||
  <FileUpload />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="mb-8">
 | 
					 | 
				
			||||||
  <Tabs />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="mb-8">
 | 
					 | 
				
			||||||
  <Tags />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="mb-8">
 | 
					 | 
				
			||||||
  <Badges />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="mb-8">
 | 
					 | 
				
			||||||
  <Avatars />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<Pagination />
 | 
					 | 
				
			||||||
<div class="mb-8">
 | 
					 | 
				
			||||||
  <Table />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div
 | 
					 | 
				
			||||||
  class="widget w-full p-4 mb-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890">
 | 
					 | 
				
			||||||
  <div class="flex flex-row items-center justify-between mb-6">
 | 
					 | 
				
			||||||
    <div class="flex flex-col">
 | 
					 | 
				
			||||||
      <div class="text-sm font-light text-grey-500">Regular</div>
 | 
					 | 
				
			||||||
      <div class="text-sm font-bold"><span>Text inputs</span></div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div class="flex flex-col lg:flex-row lg:flex-wrap w-full lg:space-x-4">
 | 
					 | 
				
			||||||
    <div class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div class="form-element ">
 | 
					 | 
				
			||||||
        <div class="form-label">Label</div><input
 | 
					 | 
				
			||||||
          name="name"
 | 
					 | 
				
			||||||
          type="text"
 | 
					 | 
				
			||||||
          class="form-input"
 | 
					 | 
				
			||||||
          placeholder="Enter something..." />
 | 
					 | 
				
			||||||
        <div class="form-hint">This is a hint</div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div class="form-element ">
 | 
					 | 
				
			||||||
        <div class="form-label">First name</div><input
 | 
					 | 
				
			||||||
          name="name"
 | 
					 | 
				
			||||||
          type="text"
 | 
					 | 
				
			||||||
          class="form-input form-input-invalid"
 | 
					 | 
				
			||||||
          placeholder="john@example.com" />
 | 
					 | 
				
			||||||
        <div class="form-error">First name is required</div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div class="form-element ">
 | 
					 | 
				
			||||||
        <div class="form-label">First name</div><input
 | 
					 | 
				
			||||||
          name="name"
 | 
					 | 
				
			||||||
          type="text"
 | 
					 | 
				
			||||||
          class="form-input form-input-valid"
 | 
					 | 
				
			||||||
          placeholder="john@example.com" />
 | 
					 | 
				
			||||||
        <div class="form-success">First name is valid</div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="mb-8">
 | 
					 | 
				
			||||||
  <BreadcrumbNav />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,281 +0,0 @@
 | 
				
			|||||||
<div class="w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890">
 | 
					 | 
				
			||||||
  <div class="flex flex-row items-center justify-between mb-6">
 | 
					 | 
				
			||||||
    <div class="flex flex-col">
 | 
					 | 
				
			||||||
      <div class="text-sm font-light text-grey-500">Conversions</div>
 | 
					 | 
				
			||||||
      <div class="text-sm font-bold"><span>This year</span></div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="relative"><button
 | 
					 | 
				
			||||||
        class="btn btn-default btn-circle btn-icon bg-transparent hover:bg-transparent active:bg-transparent relative"><svg
 | 
					 | 
				
			||||||
          stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round"
 | 
					 | 
				
			||||||
          stroke-linejoin="round" class="stroke-current stroke-1" size="18" height="18" width="18"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg">
 | 
					 | 
				
			||||||
          <circle cx="12" cy="12" r="1"></circle>
 | 
					 | 
				
			||||||
          <circle cx="12" cy="5" r="1"></circle>
 | 
					 | 
				
			||||||
          <circle cx="12" cy="19" r="1"></circle>
 | 
					 | 
				
			||||||
        </svg></button>
 | 
					 | 
				
			||||||
      <div class="dropdown absolute top-0 right-0 mt-8 ">
 | 
					 | 
				
			||||||
        <div class="dropdown-content w-48 bottom-start">
 | 
					 | 
				
			||||||
          <div class="flex flex-col w-full">
 | 
					 | 
				
			||||||
            <ul class="list-none">
 | 
					 | 
				
			||||||
              <li><a
 | 
					 | 
				
			||||||
                  class="flex flex-row items-center justify-start h-10 w-full px-2 bg-white hover:bg-grey-100 dark:bg-grey-895 dark:hover:bg-grey-890"
 | 
					 | 
				
			||||||
                  href="/">Today</a></li>
 | 
					 | 
				
			||||||
              <li><a
 | 
					 | 
				
			||||||
                  class="flex flex-row items-center justify-start h-10 w-full px-2 bg-white hover:bg-grey-100 dark:bg-grey-895 dark:hover:bg-grey-890"
 | 
					 | 
				
			||||||
                  href="/">This week</a></li>
 | 
					 | 
				
			||||||
              <li><a
 | 
					 | 
				
			||||||
                  class="flex flex-row items-center justify-start h-10 w-full px-2 bg-white hover:bg-grey-100 dark:bg-grey-895 dark:hover:bg-grey-890"
 | 
					 | 
				
			||||||
                  href="/">This month</a></li>
 | 
					 | 
				
			||||||
              <li><a
 | 
					 | 
				
			||||||
                  class="flex flex-row items-center justify-start h-10 w-full px-2 bg-white hover:bg-grey-100 dark:bg-grey-895 dark:hover:bg-grey-890"
 | 
					 | 
				
			||||||
                  href="/">This year</a></li>
 | 
					 | 
				
			||||||
            </ul>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div class="flex flex-row w-full">
 | 
					 | 
				
			||||||
    <div style="width:100%;height:240px">
 | 
					 | 
				
			||||||
      <div class="recharts-responsive-container" style="width:100%;height:100%">
 | 
					 | 
				
			||||||
        <div class="recharts-wrapper"
 | 
					 | 
				
			||||||
          style="position: relative; cursor: default; width: 704px; height: 240px;"><svg
 | 
					 | 
				
			||||||
            class="recharts-surface" width="704" height="240" viewBox="0 0 704 240" version="1.1">
 | 
					 | 
				
			||||||
            <defs>
 | 
					 | 
				
			||||||
              <clipPath id="recharts3-clip">
 | 
					 | 
				
			||||||
                <rect x="40" y="10" height="190" width="654"></rect>
 | 
					 | 
				
			||||||
              </clipPath>
 | 
					 | 
				
			||||||
            </defs>
 | 
					 | 
				
			||||||
            <g class="recharts-layer recharts-cartesian-axis recharts-xAxis xAxis">
 | 
					 | 
				
			||||||
              <g class="recharts-cartesian-axis-ticks">
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30" x="67.25"
 | 
					 | 
				
			||||||
                    y="208" stroke="none" fill="#666" class="recharts-text recharts-cartesian-axis-tick-value"
 | 
					 | 
				
			||||||
                    text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="67.25" dy="0.71em">Jan</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="121.75" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="121.75" dy="0.71em">Feb</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="176.25" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="176.25" dy="0.71em">Mar</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="230.75" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="230.75" dy="0.71em">Apr</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="285.25" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="285.25" dy="0.71em">May</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="339.75" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="339.75" dy="0.71em">Jun</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="394.25" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="394.25" dy="0.71em">Jul</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="448.75" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="448.75" dy="0.71em">Aug</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="503.25" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="503.25" dy="0.71em">Sep</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="557.75" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="557.75" dy="0.71em">Oct</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="612.25" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="612.25" dy="0.71em">Nov</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="654" height="30"
 | 
					 | 
				
			||||||
                    x="666.75" y="208" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="middle">
 | 
					 | 
				
			||||||
                    <tspan x="666.75" dy="0.71em">Dec</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
              </g>
 | 
					 | 
				
			||||||
            </g>
 | 
					 | 
				
			||||||
            <g class="recharts-layer recharts-cartesian-axis recharts-yAxis yAxis">
 | 
					 | 
				
			||||||
              <g class="recharts-cartesian-axis-ticks">
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="30" height="190" x="32"
 | 
					 | 
				
			||||||
                    y="200" stroke="none" fill="#666" class="recharts-text recharts-cartesian-axis-tick-value"
 | 
					 | 
				
			||||||
                    text-anchor="end">
 | 
					 | 
				
			||||||
                    <tspan x="32" dy="0.355em">0</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="30" height="190" x="32"
 | 
					 | 
				
			||||||
                    y="152.5" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="end">
 | 
					 | 
				
			||||||
                    <tspan x="32" dy="0.355em">65</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="30" height="190" x="32"
 | 
					 | 
				
			||||||
                    y="105" stroke="none" fill="#666" class="recharts-text recharts-cartesian-axis-tick-value"
 | 
					 | 
				
			||||||
                    text-anchor="end">
 | 
					 | 
				
			||||||
                    <tspan x="32" dy="0.355em">130</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="30" height="190" x="32"
 | 
					 | 
				
			||||||
                    y="57.5" stroke="none" fill="#666"
 | 
					 | 
				
			||||||
                    class="recharts-text recharts-cartesian-axis-tick-value" text-anchor="end">
 | 
					 | 
				
			||||||
                    <tspan x="32" dy="0.355em">195</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
                <g class="recharts-layer recharts-cartesian-axis-tick"><text width="30" height="190" x="32"
 | 
					 | 
				
			||||||
                    y="10" stroke="none" fill="#666" class="recharts-text recharts-cartesian-axis-tick-value"
 | 
					 | 
				
			||||||
                    text-anchor="end">
 | 
					 | 
				
			||||||
                    <tspan x="32" dy="0.355em">260</tspan>
 | 
					 | 
				
			||||||
                  </text></g>
 | 
					 | 
				
			||||||
              </g>
 | 
					 | 
				
			||||||
            </g>
 | 
					 | 
				
			||||||
            <g class="recharts-layer recharts-bar">
 | 
					 | 
				
			||||||
              <g class="recharts-layer recharts-bar-rectangles">
 | 
					 | 
				
			||||||
                <g class="recharts-layer">
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="119.11538461538461" x="55" y="80.88461538461539"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 55,80.88461538461539 h 10 v 119.11538461538461 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="95" x="109.5" y="105" radius="0"
 | 
					 | 
				
			||||||
                      class="recharts-rectangle" d="M 109.5,105 h 10 v 95 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="122.03846153846155" x="164" y="77.96153846153845"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 164,77.96153846153845 h 10 v 122.03846153846155 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="81.11538461538461" x="218.5"
 | 
					 | 
				
			||||||
                      y="118.88461538461539" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 218.5,118.88461538461539 h 10 v 81.11538461538461 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="114" x="273" y="86" radius="0"
 | 
					 | 
				
			||||||
                      class="recharts-rectangle" d="M 273,86 h 10 v 114 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="117.65384615384616" x="327.5"
 | 
					 | 
				
			||||||
                      y="82.34615384615384" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 327.5,82.34615384615384 h 10 v 117.65384615384616 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="103.76923076923076" x="382" y="96.23076923076924"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 382,96.23076923076924 h 10 v 103.76923076923076 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="92.80769230769232" x="436.5"
 | 
					 | 
				
			||||||
                      y="107.19230769230768" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 436.5,107.19230769230768 h 10 v 92.80769230769232 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="92.80769230769232" x="491" y="107.19230769230768"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 491,107.19230769230768 h 10 v 92.80769230769232 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="127.8846153846154" x="545.5" y="72.1153846153846"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 545.5,72.1153846153846 h 10 v 127.8846153846154 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="105.23076923076924" x="600" y="94.76923076923076"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 600,94.76923076923076 h 10 v 105.23076923076924 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#90caf9" width="10" height="115.46153846153845" x="654.5"
 | 
					 | 
				
			||||||
                      y="84.53846153846155" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 654.5,84.53846153846155 h 10 v 115.46153846153845 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                </g>
 | 
					 | 
				
			||||||
              </g>
 | 
					 | 
				
			||||||
            </g>
 | 
					 | 
				
			||||||
            <g class="recharts-layer recharts-bar">
 | 
					 | 
				
			||||||
              <g class="recharts-layer recharts-bar-rectangles">
 | 
					 | 
				
			||||||
                <g class="recharts-layer">
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="112.53846153846155" x="69" y="87.46153846153845"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 69,87.46153846153845 h 10 v 112.53846153846155 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="151.26923076923077" x="123.5"
 | 
					 | 
				
			||||||
                      y="48.730769230769226" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 123.5,48.730769230769226 h 10 v 151.26923076923077 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="181.23076923076923" x="178" y="18.769230769230774"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 178,18.769230769230774 h 10 v 181.23076923076923 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="165.8846153846154" x="232.5" y="34.11538461538461"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 232.5,34.11538461538461 h 10 v 165.8846153846154 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="156.38461538461536" x="287" y="43.61538461538464"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 287,43.61538461538464 h 10 v 156.38461538461536 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="118.38461538461539" x="341.5"
 | 
					 | 
				
			||||||
                      y="81.61538461538461" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 341.5,81.61538461538461 h 10 v 118.38461538461539 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="138.84615384615384" x="396" y="61.15384615384616"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 396,61.15384615384616 h 10 v 138.84615384615384 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="175.3846153846154" x="450.5"
 | 
					 | 
				
			||||||
                      y="24.615384615384613" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 450.5,24.615384615384613 h 10 v 175.3846153846154 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="155.65384615384613" x="505" y="44.34615384615387"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 505,44.34615384615387 h 10 v 155.65384615384613 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="179.76923076923077" x="559.5"
 | 
					 | 
				
			||||||
                      y="20.230769230769226" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 559.5,20.230769230769226 h 10 v 179.76923076923077 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="173.19230769230768" x="614" y="26.80769230769232"
 | 
					 | 
				
			||||||
                      radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 614,26.80769230769232 h 10 v 173.19230769230768 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                  <g class="recharts-layer recharts-bar-rectangle">
 | 
					 | 
				
			||||||
                    <path fill="#1e88e5" width="10" height="146.15384615384616" x="668.5"
 | 
					 | 
				
			||||||
                      y="53.84615384615384" radius="0" class="recharts-rectangle"
 | 
					 | 
				
			||||||
                      d="M 668.5,53.84615384615384 h 10 v 146.15384615384616 h -10 Z"></path>
 | 
					 | 
				
			||||||
                  </g>
 | 
					 | 
				
			||||||
                </g>
 | 
					 | 
				
			||||||
              </g>
 | 
					 | 
				
			||||||
            </g>
 | 
					 | 
				
			||||||
          </svg>
 | 
					 | 
				
			||||||
          <div class="recharts-tooltip-wrapper"
 | 
					 | 
				
			||||||
            style="pointer-events: none; visibility: hidden; position: absolute; top: 0px; transform: translate(538.875px, 126px);">
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div style="position:absolute;width:0;height:0;visibility:hidden;display:none"></div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,359 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  import { active } from "tinro";
 | 
					 | 
				
			||||||
  import localForage from "localforage";
 | 
					 | 
				
			||||||
  import { router } from "tinro";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  import store from "../store";
 | 
					 | 
				
			||||||
  import NoComponentLoaded from "./NoComponentLoaded.svelte";
 | 
					 | 
				
			||||||
  import { AuthService, OpenAPI } from "@odit/lfk-client-js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let activePage = "dashboard";
 | 
					 | 
				
			||||||
  let dropdown1 = false;
 | 
					 | 
				
			||||||
  let navOpen = false;
 | 
					 | 
				
			||||||
  function ismobile() {
 | 
					 | 
				
			||||||
    let check = false;
 | 
					 | 
				
			||||||
    (function (a) {
 | 
					 | 
				
			||||||
      if (
 | 
					 | 
				
			||||||
        /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
 | 
					 | 
				
			||||||
          a
 | 
					 | 
				
			||||||
        ) ||
 | 
					 | 
				
			||||||
        /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
 | 
					 | 
				
			||||||
          a.substr(0, 4)
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
        check = true;
 | 
					 | 
				
			||||||
    })(navigator.userAgent || navigator.vendor || window.opera);
 | 
					 | 
				
			||||||
    return check;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  $: mobile = ismobile();
 | 
					 | 
				
			||||||
  function logout() {
 | 
					 | 
				
			||||||
    localForage.clear();
 | 
					 | 
				
			||||||
    location.replace("/");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<section class="min-h-screen bg-gray-50 dark:bg-black dark:text-gray-100">
 | 
					 | 
				
			||||||
  <nav
 | 
					 | 
				
			||||||
    class:hidden={!navOpen && mobile}
 | 
					 | 
				
			||||||
    class="select-none fixed top-0 left-0 z-20 h-full pb-10 overflow-x-hidden overflow-y-auto transition origin-left transform border-r w-60 md:translate-x-0">
 | 
					 | 
				
			||||||
    <a href="/" class="flex items-center px-4 py-5">
 | 
					 | 
				
			||||||
      <img
 | 
					 | 
				
			||||||
        src="/lfk-logo.png"
 | 
					 | 
				
			||||||
        alt="Logo"
 | 
					 | 
				
			||||||
        class="h-10" />
 | 
					 | 
				
			||||||
      <h3 class="text-lg">Lauf für Kaya! Admin</h3>
 | 
					 | 
				
			||||||
    </a>
 | 
					 | 
				
			||||||
    <nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation">
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={$router.path === '/'}
 | 
					 | 
				
			||||||
        class:bg-gray-100={$router.path === '/'}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="/">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
          fill="currentColor">
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z" />
 | 
					 | 
				
			||||||
        </svg>
 | 
					 | 
				
			||||||
        <span>{$_('dashboard-title')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={$router.path.includes('/orgs/')}
 | 
					 | 
				
			||||||
        class:bg-gray-100={$router.path.includes('/orgs/')}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="/orgs/">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          fill="currentColor"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
          width="24"
 | 
					 | 
				
			||||||
          height="24"><path fill="none" d="M0 0h24v24H0z" />
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            d="M17 19h2v-8h-6v8h2v-6h2v6zM3 19V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v5h2v10h1v2H2v-2h1zm4-8v2h2v-2H7zm0 4v2h2v-2H7zm0-8v2h2V7H7z" /></svg>
 | 
					 | 
				
			||||||
        <span>{$_('orgs')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={$router.path === '/users/'}
 | 
					 | 
				
			||||||
        class:bg-gray-100={$router.path === '/users/'}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="/users/">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          fill="currentColor"
 | 
					 | 
				
			||||||
          width="24"
 | 
					 | 
				
			||||||
          height="24"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 640 512"><path
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" /></svg>
 | 
					 | 
				
			||||||
        <span>{$_('users')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={$router.path === '/runners/'}
 | 
					 | 
				
			||||||
        class:bg-gray-100={$router.path === '/runners/'}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="/runners/">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          fill="currentColor"
 | 
					 | 
				
			||||||
          width="24"
 | 
					 | 
				
			||||||
          height="24"><path fill="none" d="M0 0h24v24H0z" />
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" /></svg>
 | 
					 | 
				
			||||||
        <span>{$_('runners')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={$router.path === '/teams/'}
 | 
					 | 
				
			||||||
        class:bg-gray-100={$router.path === '/teams/'}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="/teams/">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          fill="currentColor"
 | 
					 | 
				
			||||||
          width="24"
 | 
					 | 
				
			||||||
          height="24"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 640 512"><path
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" /></svg>
 | 
					 | 
				
			||||||
        <span>{$_('teams')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={$router.path === '/tracks/'}
 | 
					 | 
				
			||||||
        class:bg-gray-100={$router.path === '/tracks/'}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="/tracks/">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          fill="currentColor"
 | 
					 | 
				
			||||||
          width="24"
 | 
					 | 
				
			||||||
          height="24"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 640 512"><path
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            d="M635.7 167.2L556.1 31.7c-8.8-15-28.3-20.1-43.5-11.5l-69 39.1L503.3 161c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L416 75l-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L333.2 122 278 153.3 337.8 255c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-59.7-101.7-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-27.9-47.5-55.2 31.3 59.7 101.7c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L84.9 262.9l-69 39.1C.7 310.7-4.6 329.8 4.2 344.8l79.6 135.6c8.8 15 28.3 20.1 43.5 11.5L624.1 210c15.2-8.6 20.4-27.8 11.6-42.8z" /></svg>
 | 
					 | 
				
			||||||
        <span>{$_('tracks')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={activePage === 'blub'}
 | 
					 | 
				
			||||||
        class:bg-gray-100={activePage === 'blub'}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="#">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
          fill="currentColor">
 | 
					 | 
				
			||||||
          <path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z" />
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            fill-rule="evenodd"
 | 
					 | 
				
			||||||
            d="M4 5a2 2 0 012-2 3 3 0 003 3h2a3 3 0 003-3 2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm9.707 5.707a1 1 0 00-1.414-1.414L9 12.586l-1.293-1.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
 | 
					 | 
				
			||||||
            clip-rule="evenodd" />
 | 
					 | 
				
			||||||
        </svg>
 | 
					 | 
				
			||||||
        <span>Checklists</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <div>
 | 
					 | 
				
			||||||
        <div
 | 
					 | 
				
			||||||
          tabindex="0"
 | 
					 | 
				
			||||||
          class:dark:bg-gray-900={activePage === 'blub'}
 | 
					 | 
				
			||||||
          class:bg-gray-100={activePage === 'blub'}
 | 
					 | 
				
			||||||
          class="flex items-center justify-between px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
          role="button"
 | 
					 | 
				
			||||||
          on:click={() => {
 | 
					 | 
				
			||||||
            dropdown1 = !dropdown1;
 | 
					 | 
				
			||||||
          }}>
 | 
					 | 
				
			||||||
          <div class="flex items-center">
 | 
					 | 
				
			||||||
            <svg
 | 
					 | 
				
			||||||
              class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
              xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
              viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
              fill="currentColor">
 | 
					 | 
				
			||||||
              <path
 | 
					 | 
				
			||||||
                fill-rule="evenodd"
 | 
					 | 
				
			||||||
                d="M12.316 3.051a1 1 0 01.633 1.265l-4 12a1 1 0 11-1.898-.632l4-12a1 1 0 011.265-.633zM5.707 6.293a1 1 0 010 1.414L3.414 10l2.293 2.293a1 1 0 11-1.414 1.414l-3-3a1 1 0 010-1.414l3-3a1 1 0 011.414 0zm8.586 0a1 1 0 011.414 0l3 3a1 1 0 010 1.414l-3 3a1 1 0 11-1.414-1.414L16.586 10l-2.293-2.293a1 1 0 010-1.414z"
 | 
					 | 
				
			||||||
                clip-rule="evenodd" />
 | 
					 | 
				
			||||||
            </svg>
 | 
					 | 
				
			||||||
            <span>Integrations</span>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          {#if dropdown1}
 | 
					 | 
				
			||||||
            <svg
 | 
					 | 
				
			||||||
              class="flex-shrink-0 w-4 h-4 ml-2 transition transform"
 | 
					 | 
				
			||||||
              xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
              style="transform:rotate(90deg)"
 | 
					 | 
				
			||||||
              viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
              fill="currentColor">
 | 
					 | 
				
			||||||
              <path
 | 
					 | 
				
			||||||
                fill-rule="evenodd"
 | 
					 | 
				
			||||||
                d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
 | 
					 | 
				
			||||||
                clip-rule="evenodd" />
 | 
					 | 
				
			||||||
            </svg>
 | 
					 | 
				
			||||||
          {:else}
 | 
					 | 
				
			||||||
            <svg
 | 
					 | 
				
			||||||
              class="flex-shrink-0 w-4 h-4 ml-2 transition transform"
 | 
					 | 
				
			||||||
              xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
              viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
              fill="currentColor">
 | 
					 | 
				
			||||||
              <path
 | 
					 | 
				
			||||||
                fill-rule="evenodd"
 | 
					 | 
				
			||||||
                d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
 | 
					 | 
				
			||||||
                clip-rule="evenodd" />
 | 
					 | 
				
			||||||
            </svg>
 | 
					 | 
				
			||||||
          {/if}
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        {#if dropdown1}
 | 
					 | 
				
			||||||
          <div class="mb-4">
 | 
					 | 
				
			||||||
            <a
 | 
					 | 
				
			||||||
              class="flex items-center py-2 pl-12 pr-4 transition cursor-pointer hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
              href="#">Shopify</a>
 | 
					 | 
				
			||||||
            <a
 | 
					 | 
				
			||||||
              class="flex items-center py-2 pl-12 pr-4 transition cursor-pointer hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
              href="#">Slack</a>
 | 
					 | 
				
			||||||
            <a
 | 
					 | 
				
			||||||
              class="flex items-center py-2 pl-12 pr-4 transition cursor-pointer hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
              href="#">Zapier</a>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        {/if}
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="#">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
          fill="currentColor">
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            fill-rule="evenodd"
 | 
					 | 
				
			||||||
            d="M5 5a3 3 0 015-2.236A3 3 0 0114.83 6H16a2 2 0 110 4h-5V9a1 1 0 10-2 0v1H4a2 2 0 110-4h1.17C5.06 5.687 5 5.35 5 5zm4 1V5a1 1 0 10-1 1h1zm3 0a1 1 0 10-1-1v1h1z"
 | 
					 | 
				
			||||||
            clip-rule="evenodd" />
 | 
					 | 
				
			||||||
          <path d="M9 11H3v5a2 2 0 002 2h4v-7zM11 18h4a2 2 0 002-2v-5h-6v7z" />
 | 
					 | 
				
			||||||
        </svg>
 | 
					 | 
				
			||||||
        <span>{$_('changelog')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={$router.path === '/settings/'}
 | 
					 | 
				
			||||||
        class:bg-gray-100={$router.path === '/settings/'}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="/settings/">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
          fill="currentColor">
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            fill-rule="evenodd"
 | 
					 | 
				
			||||||
            d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z"
 | 
					 | 
				
			||||||
            clip-rule="evenodd" />
 | 
					 | 
				
			||||||
        </svg>
 | 
					 | 
				
			||||||
        <span>{$_('settings')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class:dark:bg-gray-900={$router.path === '/about/'}
 | 
					 | 
				
			||||||
        class:bg-gray-100={$router.path === '/about/'}
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        href="/about/">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          fill="none"
 | 
					 | 
				
			||||||
          stroke="currentColor"
 | 
					 | 
				
			||||||
          stroke-width="2"
 | 
					 | 
				
			||||||
          stroke-linecap="round"
 | 
					 | 
				
			||||||
          stroke-linejoin="round"
 | 
					 | 
				
			||||||
          viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" />
 | 
					 | 
				
			||||||
          <path d="M12 16v-4M12 8h.01" /></svg>
 | 
					 | 
				
			||||||
        <span>{$_('about')}</span>
 | 
					 | 
				
			||||||
      </a>
 | 
					 | 
				
			||||||
      <span
 | 
					 | 
				
			||||||
        tabindex="0"
 | 
					 | 
				
			||||||
        class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
 | 
					 | 
				
			||||||
        on:click={() => {
 | 
					 | 
				
			||||||
          AuthService.authControllerLogout();
 | 
					 | 
				
			||||||
          logout();
 | 
					 | 
				
			||||||
        }}>
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
 | 
					 | 
				
			||||||
          fill="currentColor"
 | 
					 | 
				
			||||||
          width="24"
 | 
					 | 
				
			||||||
          height="24"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z" />
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22zm7-6v-3h-8v-2h8V8l5 4-5 4z" /></svg>
 | 
					 | 
				
			||||||
        <span>{$_('logout')}</span>
 | 
					 | 
				
			||||||
      </span>
 | 
					 | 
				
			||||||
    </nav>
 | 
					 | 
				
			||||||
  </nav>
 | 
					 | 
				
			||||||
  <div class="ml-0 transition md:ml-60">
 | 
					 | 
				
			||||||
    <header
 | 
					 | 
				
			||||||
      class="flex items-center justify-between w-full px-4 border-b h-14">
 | 
					 | 
				
			||||||
      <button
 | 
					 | 
				
			||||||
        on:click={() => {
 | 
					 | 
				
			||||||
          navOpen = !navOpen;
 | 
					 | 
				
			||||||
        }}
 | 
					 | 
				
			||||||
        class="block btn btn-light md:hidden">
 | 
					 | 
				
			||||||
        <span class="sr-only">Menu</span>
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          class="w-4 h-4"
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
          fill="currentColor">
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            fill-rule="evenodd"
 | 
					 | 
				
			||||||
            d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
 | 
					 | 
				
			||||||
            clip-rule="evenodd" />
 | 
					 | 
				
			||||||
        </svg>
 | 
					 | 
				
			||||||
      </button>
 | 
					 | 
				
			||||||
      <!-- <div class="hidden -ml-3 form-icon md:block w-96">
 | 
					 | 
				
			||||||
        <svg
 | 
					 | 
				
			||||||
          xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
          fill="none"
 | 
					 | 
				
			||||||
          viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
          stroke="currentColor">
 | 
					 | 
				
			||||||
          <path
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
 | 
					 | 
				
			||||||
        </svg>
 | 
					 | 
				
			||||||
        <input
 | 
					 | 
				
			||||||
          class="border-0 form-input"
 | 
					 | 
				
			||||||
          placeholder="Search for articles..." />
 | 
					 | 
				
			||||||
      </div> -->
 | 
					 | 
				
			||||||
      <div class="flex items-end">
 | 
					 | 
				
			||||||
        <a href="#" class="flex text-gray-500">
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            class="flex-shrink-0 w-5 h-5"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
            viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
            fill="currentColor">
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              d="M10 2a6 6 0 00-6 6v3.586l-.707.707A1 1 0 004 14h12a1 1 0 00.707-1.707L16 11.586V8a6 6 0 00-6-6zM10 18a3 3 0 01-3-3h6a3 3 0 01-3 3z" />
 | 
					 | 
				
			||||||
          </svg>
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
        <a href="/profile/" class="ml-4">
 | 
					 | 
				
			||||||
          <img
 | 
					 | 
				
			||||||
            class="h-8 w-8 rounded-full"
 | 
					 | 
				
			||||||
            src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
 | 
					 | 
				
			||||||
            alt="Profile Picture" />
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </header>
 | 
					 | 
				
			||||||
    <slot>
 | 
					 | 
				
			||||||
      <NoComponentLoaded />
 | 
					 | 
				
			||||||
    </slot>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <!-- Sidebar Backdrop -->
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    on:click={() => {
 | 
					 | 
				
			||||||
      navOpen = false;
 | 
					 | 
				
			||||||
    }}
 | 
					 | 
				
			||||||
    class:hidden={!navOpen}
 | 
					 | 
				
			||||||
    class="fixed inset-0 z-10 w-screen h-screen bg-black bg-opacity-25 md:hidden" />
 | 
					 | 
				
			||||||
</section>
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _, json } from "svelte-i18n";
 | 
					 | 
				
			||||||
  import { getlang } from "./datatable_i18n";
 | 
					 | 
				
			||||||
  import { Grid } from "gridjs";
 | 
					 | 
				
			||||||
  import "gridjs/dist/theme/mermaid.css";
 | 
					 | 
				
			||||||
  //
 | 
					 | 
				
			||||||
  let table;
 | 
					 | 
				
			||||||
  const datatable = new Grid({
 | 
					 | 
				
			||||||
    columns: ["Name", "Email", "Phone Number"],
 | 
					 | 
				
			||||||
    language: getlang($json("datatable")),
 | 
					 | 
				
			||||||
    sort: true,
 | 
					 | 
				
			||||||
    search: { enabled: true },
 | 
					 | 
				
			||||||
    data: [
 | 
					 | 
				
			||||||
      ["John", "john@example.com", "(353) 01 222 3333"],
 | 
					 | 
				
			||||||
      ["Mark", "mark@gmail.com", "(01) 22 888 4444"],
 | 
					 | 
				
			||||||
      ["Eoin", "eoin@gmail.com", "0097 22 654 00033"],
 | 
					 | 
				
			||||||
      ["Sarah", "sarahcdd@gmail.com", "+322 876 1233"],
 | 
					 | 
				
			||||||
      ["Afshin", "afshin@mail.com", "(353) 22 87 8356"],
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    pagination: {
 | 
					 | 
				
			||||||
      enabled: true,
 | 
					 | 
				
			||||||
      limit: 2,
 | 
					 | 
				
			||||||
      summary: false,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  setTimeout(() => {
 | 
					 | 
				
			||||||
    datatable.render(table);
 | 
					 | 
				
			||||||
  }, 0);
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div bind:this={table} />
 | 
					 | 
				
			||||||
@@ -1,74 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import "filepond/dist/filepond.css";
 | 
					 | 
				
			||||||
  import FilePond from "svelte-filepond";
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  let pond;
 | 
					 | 
				
			||||||
  // pond.getFiles() will return the active files
 | 
					 | 
				
			||||||
  // the name to use for the internal file input
 | 
					 | 
				
			||||||
  let name = "filepond";
 | 
					 | 
				
			||||||
  function handleInit() {
 | 
					 | 
				
			||||||
    // console.log("FilePond has initialised");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  function handleAddFile(err, fileItem) {
 | 
					 | 
				
			||||||
    // console.log("A file has been added", fileItem);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  const labelInvalidField = $_("filepond__field-contains-invalid-files");
 | 
					 | 
				
			||||||
  const labelFileWaitingForSize = $_("filepond__waiting-for-size");
 | 
					 | 
				
			||||||
  const labelFileSizeNotAvailable = $_("filepond__size-not-available");
 | 
					 | 
				
			||||||
  const labelFileLoading = $_("filepond__loading");
 | 
					 | 
				
			||||||
  const labelFileLoadError = $_("filepond__error-during-load");
 | 
					 | 
				
			||||||
  const labelFileProcessing = $_("filepond__uploading");
 | 
					 | 
				
			||||||
  const labelFileProcessingComplete = $_("filepond__upload-complete");
 | 
					 | 
				
			||||||
  const labelFileProcessingAborted = $_("filepond__upload-cancelled");
 | 
					 | 
				
			||||||
  const labelFileProcessingError = $_("filepond__error-during-upload");
 | 
					 | 
				
			||||||
  const labelFileProcessingRevertError = $_("filepond__error-during-revert");
 | 
					 | 
				
			||||||
  const labelFileRemoveError = $_("filepond__error-during-remove");
 | 
					 | 
				
			||||||
  const labelTapToCancel = $_("filepond__tap-to-cancel");
 | 
					 | 
				
			||||||
  const labelTapToRetry = $_("filepond__tap-to-retry");
 | 
					 | 
				
			||||||
  const labelTapToUndo = $_("filepond__tap-to-undo");
 | 
					 | 
				
			||||||
  const labelButtonRemoveItem = $_("filepond__remove");
 | 
					 | 
				
			||||||
  const labelButtonAbortItemLoad = $_("filepond__abort");
 | 
					 | 
				
			||||||
  const labelButtonRetryItemLoad = $_("filepond__retry");
 | 
					 | 
				
			||||||
  const labelButtonAbortItemProcessing = $_("filepond__cancel");
 | 
					 | 
				
			||||||
  const labelButtonUndoItemProcessing = $_("filepond__undo");
 | 
					 | 
				
			||||||
  const labelButtonRetryItemProcessing = $_("filepond__retry");
 | 
					 | 
				
			||||||
  const labelButtonProcessItem = $_("filepond__upload");
 | 
					 | 
				
			||||||
  const labelIdle =
 | 
					 | 
				
			||||||
    $_("drag-and-drop-your-files-or") +
 | 
					 | 
				
			||||||
    ` <span class="filepond--label-action"> ` +
 | 
					 | 
				
			||||||
    $_("browse") +
 | 
					 | 
				
			||||||
    ` </span>`;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="app">
 | 
					 | 
				
			||||||
  <FilePond
 | 
					 | 
				
			||||||
    bind:this={pond}
 | 
					 | 
				
			||||||
    {name}
 | 
					 | 
				
			||||||
    {labelFileWaitingForSize}
 | 
					 | 
				
			||||||
    {labelFileSizeNotAvailable}
 | 
					 | 
				
			||||||
    {labelFileLoading}
 | 
					 | 
				
			||||||
    {labelFileLoadError}
 | 
					 | 
				
			||||||
    {labelFileProcessing}
 | 
					 | 
				
			||||||
    {labelFileProcessingComplete}
 | 
					 | 
				
			||||||
    {labelFileProcessingAborted}
 | 
					 | 
				
			||||||
    {labelFileProcessingError}
 | 
					 | 
				
			||||||
    {labelFileProcessingRevertError}
 | 
					 | 
				
			||||||
    {labelFileRemoveError}
 | 
					 | 
				
			||||||
    {labelTapToCancel}
 | 
					 | 
				
			||||||
    {labelTapToRetry}
 | 
					 | 
				
			||||||
    {labelTapToUndo}
 | 
					 | 
				
			||||||
    {labelButtonRemoveItem}
 | 
					 | 
				
			||||||
    {labelButtonAbortItemLoad}
 | 
					 | 
				
			||||||
    {labelButtonRetryItemLoad}
 | 
					 | 
				
			||||||
    {labelButtonAbortItemProcessing}
 | 
					 | 
				
			||||||
    {labelButtonUndoItemProcessing}
 | 
					 | 
				
			||||||
    {labelButtonRetryItemProcessing}
 | 
					 | 
				
			||||||
    {labelButtonProcessItem}
 | 
					 | 
				
			||||||
    {labelIdle}
 | 
					 | 
				
			||||||
    {labelInvalidField}
 | 
					 | 
				
			||||||
    server="/api"
 | 
					 | 
				
			||||||
    allowMultiple={false}
 | 
					 | 
				
			||||||
    credits={false}
 | 
					 | 
				
			||||||
    oninit={handleInit}
 | 
					 | 
				
			||||||
    onaddfile={handleAddFile} />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,32 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  const releaseinfo = document
 | 
					 | 
				
			||||||
    .getElementById("buildinfo")
 | 
					 | 
				
			||||||
    .textContent.replace("RELEASE_INFO-", "")
 | 
					 | 
				
			||||||
    .replace("-RELEASE_INFO", "");
 | 
					 | 
				
			||||||
  const year = new Date().getFullYear();
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<footer class="p-5 w-full">
 | 
					 | 
				
			||||||
  <p class="text-sm text-gray-500 mt-4">
 | 
					 | 
				
			||||||
    Lauf für Kaya! Läufersystem - Copyright ©
 | 
					 | 
				
			||||||
    {year}
 | 
					 | 
				
			||||||
    + proudly powered by
 | 
					 | 
				
			||||||
    <a
 | 
					 | 
				
			||||||
      class="underline"
 | 
					 | 
				
			||||||
      href="https://odit.services"
 | 
					 | 
				
			||||||
      rel="noopener,noreferrer"
 | 
					 | 
				
			||||||
      target="_blank">ODIT.Services</a>
 | 
					 | 
				
			||||||
  </p>
 | 
					 | 
				
			||||||
  <p class="text-sm text-gray-500 mt-4">
 | 
					 | 
				
			||||||
    <a
 | 
					 | 
				
			||||||
      class="underline"
 | 
					 | 
				
			||||||
      target="_blank"
 | 
					 | 
				
			||||||
      rel="noopener, noreferrer"
 | 
					 | 
				
			||||||
      href="https://git.odit.services/lfk/frontend/">LfK!Frontend</a>@<a
 | 
					 | 
				
			||||||
      class="underline"
 | 
					 | 
				
			||||||
      target="_blank"
 | 
					 | 
				
			||||||
      rel="noopener, noreferrer"
 | 
					 | 
				
			||||||
      href="https://git.odit.services/lfk/frontend/src/tag/{releaseinfo}">{releaseinfo}</a>
 | 
					 | 
				
			||||||
  </p>
 | 
					 | 
				
			||||||
</footer>
 | 
					 | 
				
			||||||
@@ -1,274 +0,0 @@
 | 
				
			|||||||
<!--
 | 
					 | 
				
			||||||
  This example requires Tailwind CSS v2.0+ 
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  This example requires some changes to your config:
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  ```
 | 
					 | 
				
			||||||
  // tailwind.config.js
 | 
					 | 
				
			||||||
  module.exports = {
 | 
					 | 
				
			||||||
    // ...
 | 
					 | 
				
			||||||
    plugins: [
 | 
					 | 
				
			||||||
      // ...
 | 
					 | 
				
			||||||
      require('@tailwindcss/forms'),
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  ```
 | 
					 | 
				
			||||||
-->
 | 
					 | 
				
			||||||
<div>
 | 
					 | 
				
			||||||
  <div class="md:grid md:grid-cols-3 md:gap-6">
 | 
					 | 
				
			||||||
    <div class="md:col-span-1">
 | 
					 | 
				
			||||||
      <div class="px-4 sm:px-0">
 | 
					 | 
				
			||||||
        <h3 class="text-lg font-medium leading-6 text-gray-900">Profile</h3>
 | 
					 | 
				
			||||||
        <p class="mt-1 text-sm text-gray-600">
 | 
					 | 
				
			||||||
          This information will be displayed publicly so be careful what you share.
 | 
					 | 
				
			||||||
        </p>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="mt-5 md:mt-0 md:col-span-2">
 | 
					 | 
				
			||||||
      <form action="#" method="POST">
 | 
					 | 
				
			||||||
        <div class="shadow sm:rounded-md sm:overflow-hidden">
 | 
					 | 
				
			||||||
          <div class="px-4 py-5 bg-white space-y-6 sm:p-6">
 | 
					 | 
				
			||||||
            <div class="grid grid-cols-3 gap-6">
 | 
					 | 
				
			||||||
              <div class="col-span-3 sm:col-span-2">
 | 
					 | 
				
			||||||
                <label for="company_website" class="block text-sm font-medium text-gray-700">
 | 
					 | 
				
			||||||
                  Website
 | 
					 | 
				
			||||||
                </label>
 | 
					 | 
				
			||||||
                <div class="mt-1 flex rounded-md shadow-sm">
 | 
					 | 
				
			||||||
                  <span class="inline-flex items-center px-3 rounded-l-md border border-r-0 border-gray-300 bg-gray-50 text-gray-500 text-sm">
 | 
					 | 
				
			||||||
                    http://
 | 
					 | 
				
			||||||
                  </span>
 | 
					 | 
				
			||||||
                  <input type="text" name="company_website" id="company_website" class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300" placeholder="www.example.com">
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <div>
 | 
					 | 
				
			||||||
              <label for="about" class="block text-sm font-medium text-gray-700">
 | 
					 | 
				
			||||||
                About
 | 
					 | 
				
			||||||
              </label>
 | 
					 | 
				
			||||||
              <div class="mt-1">
 | 
					 | 
				
			||||||
                <textarea id="about" name="about" rows="3" class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md" placeholder="you@example.com"></textarea>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
              <p class="mt-2 text-sm text-gray-500">
 | 
					 | 
				
			||||||
                Brief description for your profile. URLs are hyperlinked.
 | 
					 | 
				
			||||||
              </p>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <div>
 | 
					 | 
				
			||||||
              <!-- svelte-ignore a11y-label-has-associated-control -->
 | 
					 | 
				
			||||||
              <label class="block text-sm font-medium text-gray-700">
 | 
					 | 
				
			||||||
                Photo
 | 
					 | 
				
			||||||
              </label>
 | 
					 | 
				
			||||||
              <div class="mt-2 flex items-center">
 | 
					 | 
				
			||||||
                <span class="inline-block h-12 w-12 rounded-full overflow-hidden bg-gray-100">
 | 
					 | 
				
			||||||
                  <svg class="h-full w-full text-gray-300" fill="currentColor" viewBox="0 0 24 24">
 | 
					 | 
				
			||||||
                    <path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
 | 
					 | 
				
			||||||
                  </svg>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
                <button type="button" class="ml-5 bg-white py-2 px-3 border border-gray-300 rounded-md shadow-sm text-sm leading-4 font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
 | 
					 | 
				
			||||||
                  Change
 | 
					 | 
				
			||||||
                </button>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <div>
 | 
					 | 
				
			||||||
              <!-- svelte-ignore a11y-label-has-associated-control -->
 | 
					 | 
				
			||||||
              <label class="block text-sm font-medium text-gray-700">
 | 
					 | 
				
			||||||
                Cover photo
 | 
					 | 
				
			||||||
              </label>
 | 
					 | 
				
			||||||
              <div class="mt-2 flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-md">
 | 
					 | 
				
			||||||
                <div class="space-y-1 text-center">
 | 
					 | 
				
			||||||
                  <svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48" aria-hidden="true">
 | 
					 | 
				
			||||||
                    <path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
 | 
					 | 
				
			||||||
                  </svg>
 | 
					 | 
				
			||||||
                  <div class="flex text-sm text-gray-600">
 | 
					 | 
				
			||||||
                    <label for="file-upload" class="relative cursor-pointer bg-white rounded-md font-medium text-indigo-600 hover:text-indigo-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500">
 | 
					 | 
				
			||||||
                      <span>Upload a file</span>
 | 
					 | 
				
			||||||
                      <input id="file-upload" name="file-upload" type="file" class="sr-only">
 | 
					 | 
				
			||||||
                    </label>
 | 
					 | 
				
			||||||
                    <p class="pl-1">or drag and drop</p>
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                  <p class="text-xs text-gray-500">
 | 
					 | 
				
			||||||
                    PNG, JPG, GIF up to 10MB
 | 
					 | 
				
			||||||
                  </p>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
 | 
					 | 
				
			||||||
            <button type="submit" class="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">
 | 
					 | 
				
			||||||
              Save
 | 
					 | 
				
			||||||
            </button>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </form>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="hidden sm:block" aria-hidden="true">
 | 
					 | 
				
			||||||
  <div class="py-5">
 | 
					 | 
				
			||||||
    <div class="border-t border-gray-200"></div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="mt-10 sm:mt-0">
 | 
					 | 
				
			||||||
  <div class="md:grid md:grid-cols-3 md:gap-6">
 | 
					 | 
				
			||||||
    <div class="md:col-span-1">
 | 
					 | 
				
			||||||
      <div class="px-4 sm:px-0">
 | 
					 | 
				
			||||||
        <h3 class="text-lg font-medium leading-6 text-gray-900">Personal Information</h3>
 | 
					 | 
				
			||||||
        <p class="mt-1 text-sm text-gray-600">
 | 
					 | 
				
			||||||
          Use a permanent address where you can receive mail.
 | 
					 | 
				
			||||||
        </p>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="mt-5 md:mt-0 md:col-span-2">
 | 
					 | 
				
			||||||
      <form action="#" method="POST">
 | 
					 | 
				
			||||||
        <div class="shadow overflow-hidden sm:rounded-md">
 | 
					 | 
				
			||||||
          <div class="px-4 py-5 bg-white sm:p-6">
 | 
					 | 
				
			||||||
            <div class="grid grid-cols-6 gap-6">
 | 
					 | 
				
			||||||
              <div class="col-span-6 sm:col-span-3">
 | 
					 | 
				
			||||||
                <label for="first_name" class="block text-sm font-medium text-gray-700">First name</label>
 | 
					 | 
				
			||||||
                <input type="text" name="first_name" id="first_name" autocomplete="given-name" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <div class="col-span-6 sm:col-span-3">
 | 
					 | 
				
			||||||
                <label for="last_name" class="block text-sm font-medium text-gray-700">Last name</label>
 | 
					 | 
				
			||||||
                <input type="text" name="last_name" id="last_name" autocomplete="family-name" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <div class="col-span-6 sm:col-span-4">
 | 
					 | 
				
			||||||
                <label for="email_address" class="block text-sm font-medium text-gray-700">Email address</label>
 | 
					 | 
				
			||||||
                <input type="text" name="email_address" id="email_address" autocomplete="email" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <div class="col-span-6 sm:col-span-3">
 | 
					 | 
				
			||||||
                <label for="country" class="block text-sm font-medium text-gray-700">Country / Region</label>
 | 
					 | 
				
			||||||
                <select id="country" name="country" autocomplete="country" class="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
 | 
					 | 
				
			||||||
                  <option>United States</option>
 | 
					 | 
				
			||||||
                  <option>Canada</option>
 | 
					 | 
				
			||||||
                  <option>Mexico</option>
 | 
					 | 
				
			||||||
                </select>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <div class="col-span-6">
 | 
					 | 
				
			||||||
                <label for="street_address" class="block text-sm font-medium text-gray-700">Street address</label>
 | 
					 | 
				
			||||||
                <input type="text" name="street_address" id="street_address" autocomplete="street-address" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <div class="col-span-6 sm:col-span-6 lg:col-span-2">
 | 
					 | 
				
			||||||
                <label for="city" class="block text-sm font-medium text-gray-700">City</label>
 | 
					 | 
				
			||||||
                <input type="text" name="city" id="city" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <div class="col-span-6 sm:col-span-3 lg:col-span-2">
 | 
					 | 
				
			||||||
                <label for="state" class="block text-sm font-medium text-gray-700">State / Province</label>
 | 
					 | 
				
			||||||
                <input type="text" name="state" id="state" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <div class="col-span-6 sm:col-span-3 lg:col-span-2">
 | 
					 | 
				
			||||||
                <label for="postal_code" class="block text-sm font-medium text-gray-700">ZIP / Postal</label>
 | 
					 | 
				
			||||||
                <input type="text" name="postal_code" id="postal_code" autocomplete="postal-code" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
 | 
					 | 
				
			||||||
            <button type="submit" class="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">
 | 
					 | 
				
			||||||
              Save
 | 
					 | 
				
			||||||
            </button>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </form>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="hidden sm:block" aria-hidden="true">
 | 
					 | 
				
			||||||
  <div class="py-5">
 | 
					 | 
				
			||||||
    <div class="border-t border-gray-200"></div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="mt-10 sm:mt-0">
 | 
					 | 
				
			||||||
  <div class="md:grid md:grid-cols-3 md:gap-6">
 | 
					 | 
				
			||||||
    <div class="md:col-span-1">
 | 
					 | 
				
			||||||
      <div class="px-4 sm:px-0">
 | 
					 | 
				
			||||||
        <h3 class="text-lg font-medium leading-6 text-gray-900">Notifications</h3>
 | 
					 | 
				
			||||||
        <p class="mt-1 text-sm text-gray-600">
 | 
					 | 
				
			||||||
          Decide which communications you'd like to receive and how.
 | 
					 | 
				
			||||||
        </p>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="mt-5 md:mt-0 md:col-span-2">
 | 
					 | 
				
			||||||
      <form action="#" method="POST">
 | 
					 | 
				
			||||||
        <div class="shadow overflow-hidden sm:rounded-md">
 | 
					 | 
				
			||||||
          <div class="px-4 py-5 bg-white space-y-6 sm:p-6">
 | 
					 | 
				
			||||||
            <fieldset>
 | 
					 | 
				
			||||||
              <legend class="text-base font-medium text-gray-900">By Email</legend>
 | 
					 | 
				
			||||||
              <div class="mt-4 space-y-4">
 | 
					 | 
				
			||||||
                <div class="flex items-start">
 | 
					 | 
				
			||||||
                  <div class="flex items-center h-5">
 | 
					 | 
				
			||||||
                    <input id="comments" name="comments" type="checkbox" class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded">
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                  <div class="ml-3 text-sm">
 | 
					 | 
				
			||||||
                    <label for="comments" class="font-medium text-gray-700">Comments</label>
 | 
					 | 
				
			||||||
                    <p class="text-gray-500">Get notified when someones posts a comment on a posting.</p>
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div class="flex items-start">
 | 
					 | 
				
			||||||
                  <div class="flex items-center h-5">
 | 
					 | 
				
			||||||
                    <input id="candidates" name="candidates" type="checkbox" class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded">
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                  <div class="ml-3 text-sm">
 | 
					 | 
				
			||||||
                    <label for="candidates" class="font-medium text-gray-700">Candidates</label>
 | 
					 | 
				
			||||||
                    <p class="text-gray-500">Get notified when a candidate applies for a job.</p>
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div class="flex items-start">
 | 
					 | 
				
			||||||
                  <div class="flex items-center h-5">
 | 
					 | 
				
			||||||
                    <input id="offers" name="offers" type="checkbox" class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded">
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                  <div class="ml-3 text-sm">
 | 
					 | 
				
			||||||
                    <label for="offers" class="font-medium text-gray-700">Offers</label>
 | 
					 | 
				
			||||||
                    <p class="text-gray-500">Get notified when a candidate accepts or rejects an offer.</p>
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </fieldset>
 | 
					 | 
				
			||||||
            <fieldset>
 | 
					 | 
				
			||||||
              <div>
 | 
					 | 
				
			||||||
                <legend class="text-base font-medium text-gray-900">Push Notifications</legend>
 | 
					 | 
				
			||||||
                <p class="text-sm text-gray-500">These are delivered via SMS to your mobile phone.</p>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
              <div class="mt-4 space-y-4">
 | 
					 | 
				
			||||||
                <div class="flex items-center">
 | 
					 | 
				
			||||||
                  <input id="push_everything" name="push_notifications" type="radio" class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300">
 | 
					 | 
				
			||||||
                  <label for="push_everything" class="ml-3 block text-sm font-medium text-gray-700">
 | 
					 | 
				
			||||||
                    Everything
 | 
					 | 
				
			||||||
                  </label>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div class="flex items-center">
 | 
					 | 
				
			||||||
                  <input id="push_email" name="push_notifications" type="radio" class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300">
 | 
					 | 
				
			||||||
                  <label for="push_email" class="ml-3 block text-sm font-medium text-gray-700">
 | 
					 | 
				
			||||||
                    Same as email
 | 
					 | 
				
			||||||
                  </label>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div class="flex items-center">
 | 
					 | 
				
			||||||
                  <input id="push_nothing" name="push_notifications" type="radio" class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300">
 | 
					 | 
				
			||||||
                  <label for="push_nothing" class="ml-3 block text-sm font-medium text-gray-700">
 | 
					 | 
				
			||||||
                    No push notifications
 | 
					 | 
				
			||||||
                  </label>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </fieldset>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
 | 
					 | 
				
			||||||
            <button type="submit" class="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">
 | 
					 | 
				
			||||||
              Save
 | 
					 | 
				
			||||||
            </button>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </form>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,97 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import store from "../store.js";
 | 
					 | 
				
			||||||
  store.init();
 | 
					 | 
				
			||||||
  const login = () => {
 | 
					 | 
				
			||||||
    store.login();
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div
 | 
					 | 
				
			||||||
  class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
 | 
					 | 
				
			||||||
  <div class="max-w-md w-full space-y-8">
 | 
					 | 
				
			||||||
    <div>
 | 
					 | 
				
			||||||
      <img
 | 
					 | 
				
			||||||
        class="mx-auto h-12 w-auto"
 | 
					 | 
				
			||||||
        src="/lfk-logo.png"
 | 
					 | 
				
			||||||
        alt="" />
 | 
					 | 
				
			||||||
      <h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
 | 
					 | 
				
			||||||
        Sign in to your account
 | 
					 | 
				
			||||||
      </h2>
 | 
					 | 
				
			||||||
      <p class="mt-2 text-center text-sm text-gray-600">
 | 
					 | 
				
			||||||
        Or
 | 
					 | 
				
			||||||
        <a href="#" class="font-medium text-indigo-600 hover:text-indigo-500">
 | 
					 | 
				
			||||||
          start your 14-day free trial
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
      </p>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div>
 | 
					 | 
				
			||||||
      <input type="hidden" name="remember" value="true" />
 | 
					 | 
				
			||||||
      <div class="rounded-md shadow-sm -space-y-px">
 | 
					 | 
				
			||||||
        <div>
 | 
					 | 
				
			||||||
          <label for="email-address" class="sr-only">Email address</label>
 | 
					 | 
				
			||||||
          <input
 | 
					 | 
				
			||||||
            id="email-address"
 | 
					 | 
				
			||||||
            name="email"
 | 
					 | 
				
			||||||
            type="email"
 | 
					 | 
				
			||||||
            autocomplete="email"
 | 
					 | 
				
			||||||
            required
 | 
					 | 
				
			||||||
            class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
 | 
					 | 
				
			||||||
            placeholder="Email address" />
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div>
 | 
					 | 
				
			||||||
          <label for="password" class="sr-only">Password</label>
 | 
					 | 
				
			||||||
          <input
 | 
					 | 
				
			||||||
            id="password"
 | 
					 | 
				
			||||||
            name="password"
 | 
					 | 
				
			||||||
            type="password"
 | 
					 | 
				
			||||||
            autocomplete="current-password"
 | 
					 | 
				
			||||||
            required
 | 
					 | 
				
			||||||
            class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
 | 
					 | 
				
			||||||
            placeholder="Password" />
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      <div class="flex items-center justify-between">
 | 
					 | 
				
			||||||
        <div class="flex items-center">
 | 
					 | 
				
			||||||
          <input
 | 
					 | 
				
			||||||
            id="remember_me"
 | 
					 | 
				
			||||||
            name="remember_me"
 | 
					 | 
				
			||||||
            type="checkbox"
 | 
					 | 
				
			||||||
            class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded" />
 | 
					 | 
				
			||||||
          <label for="remember_me" class="ml-2 block text-sm text-gray-900">
 | 
					 | 
				
			||||||
            Remember me
 | 
					 | 
				
			||||||
          </label>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div class="text-sm">
 | 
					 | 
				
			||||||
          <a href="#" class="font-medium text-indigo-600 hover:text-indigo-500">
 | 
					 | 
				
			||||||
            Forgot your password?
 | 
					 | 
				
			||||||
          </a>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      <div>
 | 
					 | 
				
			||||||
        <button
 | 
					 | 
				
			||||||
        on:click="{login}"
 | 
					 | 
				
			||||||
          type="submit"
 | 
					 | 
				
			||||||
          class="group relative w-full flex justify-center py-2 px-4 border border-transparent 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">
 | 
					 | 
				
			||||||
          <span class="absolute left-0 inset-y-0 flex items-center pl-3">
 | 
					 | 
				
			||||||
            <!-- Heroicon name: lock-closed -->
 | 
					 | 
				
			||||||
            <svg
 | 
					 | 
				
			||||||
              class="h-5 w-5 text-indigo-500 group-hover:text-indigo-400"
 | 
					 | 
				
			||||||
              xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
              viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
              fill="currentColor"
 | 
					 | 
				
			||||||
              aria-hidden="true">
 | 
					 | 
				
			||||||
              <path
 | 
					 | 
				
			||||||
                fill-rule="evenodd"
 | 
					 | 
				
			||||||
                d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
 | 
					 | 
				
			||||||
                clip-rule="evenodd" />
 | 
					 | 
				
			||||||
            </svg>
 | 
					 | 
				
			||||||
          </span>
 | 
					 | 
				
			||||||
          Sign in
 | 
					 | 
				
			||||||
        </button>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  import StatCards from "./StatCards.svelte";
 | 
					 | 
				
			||||||
  import store from "../store";
 | 
					 | 
				
			||||||
  import ComponentDump from "./ComponentDump.svelte";
 | 
					 | 
				
			||||||
  let navOpen = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div
 | 
					 | 
				
			||||||
  class="p-5 overflow-x-hidden"
 | 
					 | 
				
			||||||
  on:click={() => {
 | 
					 | 
				
			||||||
    navOpen = false;
 | 
					 | 
				
			||||||
  }}>
 | 
					 | 
				
			||||||
  <!-- <div class="border-4 border-dashed rounded h-96" /> -->
 | 
					 | 
				
			||||||
  <h1 class="text-3xl leading-tight">
 | 
					 | 
				
			||||||
    <span class="font-extrabold">{$_('dashboard-title')}</span> <span>
 | 
					 | 
				
			||||||
      -
 | 
					 | 
				
			||||||
      {$_('dashboard-greeting')},
 | 
					 | 
				
			||||||
      <span
 | 
					 | 
				
			||||||
        class="text-blue-500">{store.state.jwtinfo.userdetails.firstname}</span>
 | 
					 | 
				
			||||||
      👋</span>
 | 
					 | 
				
			||||||
  </h1>
 | 
					 | 
				
			||||||
  <StatCards />
 | 
					 | 
				
			||||||
  <ComponentDump />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,83 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  export let params;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<section class="container p-5">
 | 
					 | 
				
			||||||
  <span class="mb-1 text-3xl font-extrabold leading-tight">
 | 
					 | 
				
			||||||
    Orgs
 | 
					 | 
				
			||||||
  </span>
 | 
					 | 
				
			||||||
  <p class="mb-8 text-lg text-gray-500">
 | 
					 | 
				
			||||||
    configure the tracks & minimum lap times
 | 
					 | 
				
			||||||
  </p>
 | 
					 | 
				
			||||||
  <div class="flex flex-row mb-4">
 | 
					 | 
				
			||||||
    <div class="w-full">
 | 
					 | 
				
			||||||
      <nav class="w-full flex">
 | 
					 | 
				
			||||||
        <ol class="list-none flex flex-row items-center justify-start">
 | 
					 | 
				
			||||||
          <li class="mr-2 flex items-center">
 | 
					 | 
				
			||||||
            <svg
 | 
					 | 
				
			||||||
              stroke="currentColor"
 | 
					 | 
				
			||||||
              fill="none"
 | 
					 | 
				
			||||||
              stroke-width="2"
 | 
					 | 
				
			||||||
              viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
              stroke-linecap="round"
 | 
					 | 
				
			||||||
              stroke-linejoin="round"
 | 
					 | 
				
			||||||
              class="h-3 w-3 stroke-current"
 | 
					 | 
				
			||||||
              height="1em"
 | 
					 | 
				
			||||||
              width="1em"
 | 
					 | 
				
			||||||
              xmlns="http://www.w3.org/2000/svg"><path
 | 
					 | 
				
			||||||
                d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
 | 
					 | 
				
			||||||
              <polyline points="9 22 9 12 15 12 15 22" /></svg>
 | 
					 | 
				
			||||||
          </li>
 | 
					 | 
				
			||||||
          <li class="flex items-center">
 | 
					 | 
				
			||||||
            <a class="mr-2" href="/">Home</a><svg
 | 
					 | 
				
			||||||
              stroke="currentColor"
 | 
					 | 
				
			||||||
              fill="none"
 | 
					 | 
				
			||||||
              stroke-width="2"
 | 
					 | 
				
			||||||
              viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
              stroke-linecap="round"
 | 
					 | 
				
			||||||
              stroke-linejoin="round"
 | 
					 | 
				
			||||||
              class="h-3 w-3 mr-2 stroke-current"
 | 
					 | 
				
			||||||
              height="1em"
 | 
					 | 
				
			||||||
              width="1em"
 | 
					 | 
				
			||||||
              xmlns="http://www.w3.org/2000/svg"><line
 | 
					 | 
				
			||||||
                x1="5"
 | 
					 | 
				
			||||||
                y1="12"
 | 
					 | 
				
			||||||
                x2="19"
 | 
					 | 
				
			||||||
                y2="12" />
 | 
					 | 
				
			||||||
              <polyline points="12 5 19 12 12 19" /></svg>
 | 
					 | 
				
			||||||
          </li>
 | 
					 | 
				
			||||||
          <li class="mr-2 flex items-center">
 | 
					 | 
				
			||||||
            <svg
 | 
					 | 
				
			||||||
              xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
              viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
              width="24"
 | 
					 | 
				
			||||||
              height="24"><path fill="none" d="M0 0h24v24H0z" />
 | 
					 | 
				
			||||||
              <path
 | 
					 | 
				
			||||||
                d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z" /></svg>
 | 
					 | 
				
			||||||
          </li>
 | 
					 | 
				
			||||||
          <li class="flex items-center">
 | 
					 | 
				
			||||||
            <a class="mr-2" href="./">Orgs</a><svg
 | 
					 | 
				
			||||||
              stroke="currentColor"
 | 
					 | 
				
			||||||
              fill="none"
 | 
					 | 
				
			||||||
              stroke-width="2"
 | 
					 | 
				
			||||||
              viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
              stroke-linecap="round"
 | 
					 | 
				
			||||||
              stroke-linejoin="round"
 | 
					 | 
				
			||||||
              class="h-3 w-3 mr-2 stroke-current"
 | 
					 | 
				
			||||||
              height="1em"
 | 
					 | 
				
			||||||
              width="1em"
 | 
					 | 
				
			||||||
              xmlns="http://www.w3.org/2000/svg"><line
 | 
					 | 
				
			||||||
                x1="5"
 | 
					 | 
				
			||||||
                y1="12"
 | 
					 | 
				
			||||||
                x2="19"
 | 
					 | 
				
			||||||
                y2="12" />
 | 
					 | 
				
			||||||
              <polyline points="12 5 19 12 12 19" /></svg>
 | 
					 | 
				
			||||||
          </li>
 | 
					 | 
				
			||||||
          <li class="flex items-center">
 | 
					 | 
				
			||||||
            <span class="mr-2">Org-Details #{params.orgid}</span>
 | 
					 | 
				
			||||||
          </li>
 | 
					 | 
				
			||||||
        </ol>
 | 
					 | 
				
			||||||
      </nav>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</section>
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<section class="container p-5">
 | 
					 | 
				
			||||||
  <span class="mb-1 text-3xl font-extrabold leading-tight">
 | 
					 | 
				
			||||||
    Orgs
 | 
					 | 
				
			||||||
  </span>
 | 
					 | 
				
			||||||
  <p class="mb-8 text-lg text-gray-500">
 | 
					 | 
				
			||||||
    add, delete, edit organizations
 | 
					 | 
				
			||||||
  </p>
 | 
					 | 
				
			||||||
  <nav><a class="underline" href="./1">Org 1</a></nav>
 | 
					 | 
				
			||||||
</section>
 | 
					 | 
				
			||||||
@@ -1,103 +0,0 @@
 | 
				
			|||||||
<!-- This example requires Tailwind CSS v2.0+ -->
 | 
					 | 
				
			||||||
<div
 | 
					 | 
				
			||||||
  class="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6">
 | 
					 | 
				
			||||||
  <div class="flex-1 flex justify-between sm:hidden">
 | 
					 | 
				
			||||||
    <a
 | 
					 | 
				
			||||||
      href="#"
 | 
					 | 
				
			||||||
      class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:text-gray-500">
 | 
					 | 
				
			||||||
      Previous
 | 
					 | 
				
			||||||
    </a>
 | 
					 | 
				
			||||||
    <a
 | 
					 | 
				
			||||||
      href="#"
 | 
					 | 
				
			||||||
      class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:text-gray-500">
 | 
					 | 
				
			||||||
      Next
 | 
					 | 
				
			||||||
    </a>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
 | 
					 | 
				
			||||||
    <div>
 | 
					 | 
				
			||||||
      <p class="text-sm text-gray-700">
 | 
					 | 
				
			||||||
        Showing
 | 
					 | 
				
			||||||
        <span class="font-medium">1</span>
 | 
					 | 
				
			||||||
        to
 | 
					 | 
				
			||||||
        <span class="font-medium">10</span>
 | 
					 | 
				
			||||||
        of
 | 
					 | 
				
			||||||
        <span class="font-medium">97</span>
 | 
					 | 
				
			||||||
        results
 | 
					 | 
				
			||||||
      </p>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div>
 | 
					 | 
				
			||||||
      <nav
 | 
					 | 
				
			||||||
        class="relative z-0 inline-flex shadow-sm -space-x-px"
 | 
					 | 
				
			||||||
        aria-label="Pagination">
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          href="#"
 | 
					 | 
				
			||||||
          class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
 | 
					 | 
				
			||||||
          <span class="sr-only">Previous</span>
 | 
					 | 
				
			||||||
          <!-- Heroicon name: chevron-left -->
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            class="h-5 w-5"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
            viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            aria-hidden="true">
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              fill-rule="evenodd"
 | 
					 | 
				
			||||||
              d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
 | 
					 | 
				
			||||||
              clip-rule="evenodd" />
 | 
					 | 
				
			||||||
          </svg>
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          href="#"
 | 
					 | 
				
			||||||
          class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
 | 
					 | 
				
			||||||
          1
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          href="#"
 | 
					 | 
				
			||||||
          class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
 | 
					 | 
				
			||||||
          2
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          href="#"
 | 
					 | 
				
			||||||
          class="hidden md:inline-flex relative items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
 | 
					 | 
				
			||||||
          3
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
        <span
 | 
					 | 
				
			||||||
          class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700">
 | 
					 | 
				
			||||||
          ...
 | 
					 | 
				
			||||||
        </span>
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          href="#"
 | 
					 | 
				
			||||||
          class="hidden md:inline-flex relative items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
 | 
					 | 
				
			||||||
          8
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          href="#"
 | 
					 | 
				
			||||||
          class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
 | 
					 | 
				
			||||||
          9
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          href="#"
 | 
					 | 
				
			||||||
          class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
 | 
					 | 
				
			||||||
          10
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          href="#"
 | 
					 | 
				
			||||||
          class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
 | 
					 | 
				
			||||||
          <span class="sr-only">Next</span>
 | 
					 | 
				
			||||||
          <!-- Heroicon name: chevron-right -->
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            class="h-5 w-5"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
            viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            aria-hidden="true">
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              fill-rule="evenodd"
 | 
					 | 
				
			||||||
              d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
 | 
					 | 
				
			||||||
              clip-rule="evenodd" />
 | 
					 | 
				
			||||||
          </svg>
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
      </nav>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,242 +0,0 @@
 | 
				
			|||||||
<div class="min-h-screen w-full p-4">
 | 
					 | 
				
			||||||
  <div class="section-title w-full mb-6 pt-3">
 | 
					 | 
				
			||||||
    <div class="flex flex-row items-center justify-between mb-4">
 | 
					 | 
				
			||||||
      <div class="flex flex-col">
 | 
					 | 
				
			||||||
        <div class="text-xs uppercase font-light text-grey-500">Pages</div>
 | 
					 | 
				
			||||||
        <div class="text-xl font-bold">User profile</div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="w-full p-4 mb-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890">
 | 
					 | 
				
			||||||
    <div class="flex flex-row items-center justify-start p-4">
 | 
					 | 
				
			||||||
      <div class="flex-shrink-0 w-24">
 | 
					 | 
				
			||||||
        <img
 | 
					 | 
				
			||||||
          src="/images/faces/m1.png"
 | 
					 | 
				
			||||||
          alt="media"
 | 
					 | 
				
			||||||
          class="shadow rounded-full h-20 w-20 shadow-outline mb-2" />
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
      <div class="py-2 px-2">
 | 
					 | 
				
			||||||
        <p class="text-base font-bold whitespace-no-wrap">Lucas Smith</p>
 | 
					 | 
				
			||||||
        <p class="text-sm text-grey-500 whitespace-no-wrap">
 | 
					 | 
				
			||||||
          Vital Database Dude
 | 
					 | 
				
			||||||
        </p>
 | 
					 | 
				
			||||||
        <div
 | 
					 | 
				
			||||||
          class="flex flex-row items-center justify-start w-full py-1 space-x-2">
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            stroke="currentColor"
 | 
					 | 
				
			||||||
            fill="none"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            class="stroke-current text-xl text-twitter"
 | 
					 | 
				
			||||||
            height="1em"
 | 
					 | 
				
			||||||
            width="1em"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"><path
 | 
					 | 
				
			||||||
              d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z" /></svg><svg
 | 
					 | 
				
			||||||
            stroke="currentColor"
 | 
					 | 
				
			||||||
            fill="none"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            class="stroke-current text-xl text-facebook"
 | 
					 | 
				
			||||||
            height="1em"
 | 
					 | 
				
			||||||
            width="1em"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"><path
 | 
					 | 
				
			||||||
              d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" /></svg><svg
 | 
					 | 
				
			||||||
            stroke="currentColor"
 | 
					 | 
				
			||||||
            fill="none"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            class="stroke-current text-xl text-instagram"
 | 
					 | 
				
			||||||
            height="1em"
 | 
					 | 
				
			||||||
            width="1em"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"><rect
 | 
					 | 
				
			||||||
              x="2"
 | 
					 | 
				
			||||||
              y="2"
 | 
					 | 
				
			||||||
              width="20"
 | 
					 | 
				
			||||||
              height="20"
 | 
					 | 
				
			||||||
              rx="5"
 | 
					 | 
				
			||||||
              ry="5" />
 | 
					 | 
				
			||||||
            <path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" />
 | 
					 | 
				
			||||||
            <line x1="17.5" y1="6.5" x2="17.5" y2="6.5" /></svg>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
      <div class="ml-auto flex-shrink-0 space-x-2 hidden lg:flex">
 | 
					 | 
				
			||||||
        <button
 | 
					 | 
				
			||||||
          class="btn btn-default btn-rounded bg-blue-500 hover:bg-blue-600 text-white">Subscribe</button><button
 | 
					 | 
				
			||||||
          class="btn btn-default btn-rounded bg-blue-500 hover:bg-blue-600 text-white">Follow</button>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="flex flex-wrap">
 | 
					 | 
				
			||||||
      <div class="w-full p-4">
 | 
					 | 
				
			||||||
        <div class="flex flex-wrap flex-col w-full tabs">
 | 
					 | 
				
			||||||
          <div class="flex lg:flex-wrap flex-row lg:space-x-2">
 | 
					 | 
				
			||||||
            <div class="flex-none">
 | 
					 | 
				
			||||||
              <button class="tab tab-underline tab-active" type="button">Account
 | 
					 | 
				
			||||||
                settings</button>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="flex-none">
 | 
					 | 
				
			||||||
              <button class="tab tab-underline" type="button">Email preferences</button>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="flex-none">
 | 
					 | 
				
			||||||
              <button class="tab tab-underline" type="button">Security settings</button>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div class="tab-content block">
 | 
					 | 
				
			||||||
            <div class="py-4 w-full lg:w-1/2">
 | 
					 | 
				
			||||||
              <div class="flex flex-col">
 | 
					 | 
				
			||||||
                <form class="form flex flex-wrap w-full">
 | 
					 | 
				
			||||||
                  <div class="w-full">
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">First name</div><input
 | 
					 | 
				
			||||||
                        name="first-name"
 | 
					 | 
				
			||||||
                        type="text"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter you first name" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Last name</div><input
 | 
					 | 
				
			||||||
                        name="last-name"
 | 
					 | 
				
			||||||
                        type="text"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter you last name" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Email address</div><input
 | 
					 | 
				
			||||||
                        name="email"
 | 
					 | 
				
			||||||
                        type="email"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter you email address" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Company</div><input
 | 
					 | 
				
			||||||
                        name="company"
 | 
					 | 
				
			||||||
                        type="text"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter you company" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Position</div><input
 | 
					 | 
				
			||||||
                        name="position"
 | 
					 | 
				
			||||||
                        type="text"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter you position" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Language</div><select
 | 
					 | 
				
			||||||
                        name="language"
 | 
					 | 
				
			||||||
                        class="form-select "><option>Select language</option>
 | 
					 | 
				
			||||||
                        <option value="english">English</option>
 | 
					 | 
				
			||||||
                        <option value="spanish">Spanish</option>
 | 
					 | 
				
			||||||
                        <option value="portuguese">Portuguese</option></select>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                  </div><input
 | 
					 | 
				
			||||||
                    type="submit"
 | 
					 | 
				
			||||||
                    class="btn btn-default bg-blue-500 hover:bg-blue-600 text-white btn-rounded" />
 | 
					 | 
				
			||||||
                </form>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div class="tab-content hidden">
 | 
					 | 
				
			||||||
            <div class="py-4 w-full lg:w-1/2">
 | 
					 | 
				
			||||||
              <div class="flex flex-col">
 | 
					 | 
				
			||||||
                <form class="form flex flex-wrap w-full">
 | 
					 | 
				
			||||||
                  <div class="w-full">
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Current email</div><input
 | 
					 | 
				
			||||||
                        name="email"
 | 
					 | 
				
			||||||
                        type="email"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter you current email address" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">New email</div><input
 | 
					 | 
				
			||||||
                        name="email"
 | 
					 | 
				
			||||||
                        type="email"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter you new email address" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Daily updates</div>
 | 
					 | 
				
			||||||
                      <div class="flex items-center justify-start space-x-2">
 | 
					 | 
				
			||||||
                        <label
 | 
					 | 
				
			||||||
                          class="flex items-center justify-start space-x-2"><input
 | 
					 | 
				
			||||||
                            type="radio"
 | 
					 | 
				
			||||||
                            name="daily-updates"
 | 
					 | 
				
			||||||
                            class="form-radio h-4 w-4 "
 | 
					 | 
				
			||||||
                            value="yes" /><span
 | 
					 | 
				
			||||||
                            class="">Yes</span></label><label
 | 
					 | 
				
			||||||
                          class="flex items-center justify-start space-x-2"><input
 | 
					 | 
				
			||||||
                            type="radio"
 | 
					 | 
				
			||||||
                            name="daily-updates"
 | 
					 | 
				
			||||||
                            class="form-radio h-4 w-4 "
 | 
					 | 
				
			||||||
                            value="no" /><span class="">No</span></label>
 | 
					 | 
				
			||||||
                      </div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Weekly updates</div>
 | 
					 | 
				
			||||||
                      <div class="flex items-center justify-start space-x-2">
 | 
					 | 
				
			||||||
                        <label
 | 
					 | 
				
			||||||
                          class="flex items-center justify-start space-x-2"><input
 | 
					 | 
				
			||||||
                            type="radio"
 | 
					 | 
				
			||||||
                            name="weekle-updates"
 | 
					 | 
				
			||||||
                            class="form-radio h-4 w-4 "
 | 
					 | 
				
			||||||
                            value="yes" /><span
 | 
					 | 
				
			||||||
                            class="">Yes</span></label><label
 | 
					 | 
				
			||||||
                          class="flex items-center justify-start space-x-2"><input
 | 
					 | 
				
			||||||
                            type="radio"
 | 
					 | 
				
			||||||
                            name="weekle-updates"
 | 
					 | 
				
			||||||
                            class="form-radio h-4 w-4 "
 | 
					 | 
				
			||||||
                            value="no" /><span class="">No</span></label>
 | 
					 | 
				
			||||||
                      </div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                  </div><input
 | 
					 | 
				
			||||||
                    type="submit"
 | 
					 | 
				
			||||||
                    class="btn btn-default bg-blue-500 hover:bg-blue-600 text-white btn-rounded" />
 | 
					 | 
				
			||||||
                </form>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div class="tab-content hidden">
 | 
					 | 
				
			||||||
            <div class="py-4 w-full lg:w-1/2">
 | 
					 | 
				
			||||||
              <div class="flex flex-col">
 | 
					 | 
				
			||||||
                <form class="form flex flex-wrap w-full">
 | 
					 | 
				
			||||||
                  <div class="w-full">
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Current password</div><input
 | 
					 | 
				
			||||||
                        name="current-password"
 | 
					 | 
				
			||||||
                        type="password"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter your current password" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">New password</div><input
 | 
					 | 
				
			||||||
                        name="new-password"
 | 
					 | 
				
			||||||
                        type="password"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter your new password" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="form-element">
 | 
					 | 
				
			||||||
                      <div class="form-label">Confirm new password</div><input
 | 
					 | 
				
			||||||
                        name="confirm-new-password"
 | 
					 | 
				
			||||||
                        type="password"
 | 
					 | 
				
			||||||
                        class="form-input "
 | 
					 | 
				
			||||||
                        placeholder="Enter your new password confirmation" />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                  </div><input
 | 
					 | 
				
			||||||
                    type="submit"
 | 
					 | 
				
			||||||
                    class="btn btn-default bg-blue-500 hover:bg-blue-600 text-white btn-rounded" />
 | 
					 | 
				
			||||||
                </form>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<section class="container p-5">
 | 
					 | 
				
			||||||
  <span class="mb-1 text-3xl font-extrabold leading-tight">
 | 
					 | 
				
			||||||
    {$_('runners')}
 | 
					 | 
				
			||||||
  </span>
 | 
					 | 
				
			||||||
  <p class="mb-8 text-lg text-gray-500">läuft bei ihnen</p>
 | 
					 | 
				
			||||||
</section>
 | 
					 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
import FormLayout from "./FormLayout.svelte";
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12">
 | 
					 | 
				
			||||||
  <div class="text-center mb-8">
 | 
					 | 
				
			||||||
    <h1
 | 
					 | 
				
			||||||
      class="mt-9 font-display text-4xl leading-none font-semibold text-white sm:text-5xl lg:text-6xl">
 | 
					 | 
				
			||||||
      🔨<br />{$_('settings')}
 | 
					 | 
				
			||||||
    </h1>
 | 
					 | 
				
			||||||
    <p
 | 
					 | 
				
			||||||
      class="mt-2 max-w-xl mx-auto text-xl lg:max-w-3xl lg:text-2xl text-gray-300">
 | 
					 | 
				
			||||||
      <span class="text-lg">configure your profile however you want</span>
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="pt-0 pb-16 bg-gray-50 overflow-hidden lg:pt-12 lg:py-24">
 | 
					 | 
				
			||||||
  <div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
 | 
					 | 
				
			||||||
    <!-- <h2 class="text-4xl font-display font-semibold text-gray-900 md:text-5xl">
 | 
					 | 
				
			||||||
      General
 | 
					 | 
				
			||||||
    </h2> -->
 | 
					 | 
				
			||||||
    <div
 | 
					 | 
				
			||||||
      class="max-w-3xl mx-auto text-xl leading-8 font-medium text-gray-900 mb-16">
 | 
					 | 
				
			||||||
      <p class="text-center">
 | 
					 | 
				
			||||||
        Lorem ipsum dolor sit amet consectetur, adipisicing elit. Temporibus et
 | 
					 | 
				
			||||||
        amet voluptate nulla accusantium vero blanditiis nobis facere veritatis.
 | 
					 | 
				
			||||||
        Impedit deserunt saepe aliquid unde consequuntur officia consequatur
 | 
					 | 
				
			||||||
        fugit iusto dolorem?
 | 
					 | 
				
			||||||
      </p>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <FormLayout />
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,82 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  let open = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="md:flex flex-col md:flex-row h-screen w-full">
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="flex flex-col w-full md:w-64 text-gray-700 bg-white dark-mode:text-gray-200 dark-mode:bg-gray-800 flex-shrink-0">
 | 
					 | 
				
			||||||
    <div
 | 
					 | 
				
			||||||
      class="flex-shrink-0 px-8 py-4 flex flex-row items-center justify-between">
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        href="/#/test"
 | 
					 | 
				
			||||||
        class="text-lg font-semibold tracking-widest text-gray-900 uppercase rounded-lg dark-mode:text-white focus:outline-none focus:shadow-outline">Sidebar</a>
 | 
					 | 
				
			||||||
      <button
 | 
					 | 
				
			||||||
        class="rounded-lg md:hidden focus:outline-none focus:shadow-outline">
 | 
					 | 
				
			||||||
        <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
 | 
					 | 
				
			||||||
          {#if open}
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              fill-rule="evenodd"
 | 
					 | 
				
			||||||
              d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
 | 
					 | 
				
			||||||
              clip-rule="evenodd" />
 | 
					 | 
				
			||||||
          {/if}
 | 
					 | 
				
			||||||
          {#if !open}
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              fill-rule="evenodd"
 | 
					 | 
				
			||||||
              d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z"
 | 
					 | 
				
			||||||
              clip-rule="evenodd" />
 | 
					 | 
				
			||||||
          {/if}
 | 
					 | 
				
			||||||
        </svg>
 | 
					 | 
				
			||||||
      </button>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <nav
 | 
					 | 
				
			||||||
      :class:block={open}
 | 
					 | 
				
			||||||
      :class:hidden={!open}
 | 
					 | 
				
			||||||
      class="flex-grow md:block px-4 pb-4 md:pb-0 md:overflow-y-auto">
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class="block px-4 py-2 mt-2 text-sm font-semibold text-gray-900 bg-gray-200 rounded-lg dark-mode:bg-gray-700 dark-mode:hover:bg-gray-600 dark-mode:focus:bg-gray-600 dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:text-gray-200 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
 | 
					 | 
				
			||||||
        href="#">Blog</a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class="block px-4 py-2 mt-2 text-sm font-semibold text-gray-900 bg-transparent rounded-lg dark-mode:bg-transparent dark-mode:hover:bg-gray-600 dark-mode:focus:bg-gray-600 dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:text-gray-200 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
 | 
					 | 
				
			||||||
        href="#">Portfolio</a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class="block px-4 py-2 mt-2 text-sm font-semibold text-gray-900 bg-transparent rounded-lg dark-mode:bg-transparent dark-mode:hover:bg-gray-600 dark-mode:focus:bg-gray-600 dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:text-gray-200 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
 | 
					 | 
				
			||||||
        href="#">About</a>
 | 
					 | 
				
			||||||
      <a
 | 
					 | 
				
			||||||
        class="block px-4 py-2 mt-2 text-sm font-semibold text-gray-900 bg-transparent rounded-lg dark-mode:bg-transparent dark-mode:hover:bg-gray-600 dark-mode:focus:bg-gray-600 dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:text-gray-200 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
 | 
					 | 
				
			||||||
        href="#">Contact</a>
 | 
					 | 
				
			||||||
      <div class="relative">
 | 
					 | 
				
			||||||
        <button
 | 
					 | 
				
			||||||
          on:click={() => {
 | 
					 | 
				
			||||||
            open = !open;
 | 
					 | 
				
			||||||
          }}
 | 
					 | 
				
			||||||
          class="flex flex-row items-center w-full px-4 py-2 mt-2 text-sm font-semibold text-left bg-transparent rounded-lg dark-mode:bg-transparent dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:focus:bg-gray-600 dark-mode:hover:bg-gray-600 md:block hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline">
 | 
					 | 
				
			||||||
          <span>Dropdown</span>
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            viewBox="0 0 20 20"
 | 
					 | 
				
			||||||
            class="inline w-4 h-4 mt-1 ml-1 transition-transform duration-200 transform md:-mt-1"><path
 | 
					 | 
				
			||||||
              fill-rule="evenodd"
 | 
					 | 
				
			||||||
              d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
 | 
					 | 
				
			||||||
              clip-rule="evenodd" /></svg>
 | 
					 | 
				
			||||||
        </button>
 | 
					 | 
				
			||||||
        <div
 | 
					 | 
				
			||||||
          class:block={open}
 | 
					 | 
				
			||||||
          class:hidden={!open}
 | 
					 | 
				
			||||||
          class="absolute right-0 w-full mt-2 origin-top-right rounded-md shadow-lg">
 | 
					 | 
				
			||||||
          <div
 | 
					 | 
				
			||||||
            class="px-2 py-2 bg-white rounded-md shadow dark-mode:bg-gray-800">
 | 
					 | 
				
			||||||
            <a
 | 
					 | 
				
			||||||
              class="block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark-mode:bg-transparent dark-mode:hover:bg-gray-600 dark-mode:focus:bg-gray-600 dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
 | 
					 | 
				
			||||||
              href="#">Link #1</a>
 | 
					 | 
				
			||||||
            <a
 | 
					 | 
				
			||||||
              class="block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark-mode:bg-transparent dark-mode:hover:bg-gray-600 dark-mode:focus:bg-gray-600 dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
 | 
					 | 
				
			||||||
              href="#">Link #2</a>
 | 
					 | 
				
			||||||
            <a
 | 
					 | 
				
			||||||
              class="block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark-mode:bg-transparent dark-mode:hover:bg-gray-600 dark-mode:focus:bg-gray-600 dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
 | 
					 | 
				
			||||||
              href="#">Link #3</a>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </nav>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,165 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { StatsService } from "@odit/lfk-client-js";
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  const stats_promise = StatsService.statsControllerGet();
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!--  -->
 | 
					 | 
				
			||||||
<h1>{$_('general-stats')}</h1>
 | 
					 | 
				
			||||||
{#await stats_promise}
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
 | 
					 | 
				
			||||||
    role="alert">
 | 
					 | 
				
			||||||
    <p class="font-bold">{$_('stats-are-being-loaded')}</p>
 | 
					 | 
				
			||||||
    <p class="text-sm">{$_('this-might-take-a-moment')}</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
{:then stats}
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="flex flex-col lg:flex-row w-full lg:space-x-2 space-y-2 lg:space-y-0 mb-2 lg:mb-4">
 | 
					 | 
				
			||||||
    <a href="/runners/" class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div
 | 
					 | 
				
			||||||
        class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
 | 
					 | 
				
			||||||
        <div class="flex flex-row items-center justify-between">
 | 
					 | 
				
			||||||
          <div class="flex flex-col">
 | 
					 | 
				
			||||||
            <div class="text-xs uppercase font-light text-grey-500">
 | 
					 | 
				
			||||||
              {$_('runners')}
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="text-xl font-bold">{stats.total_runners}</div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            height="24"
 | 
					 | 
				
			||||||
            width="24"
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" /></svg>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </a>
 | 
					 | 
				
			||||||
    <div class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div
 | 
					 | 
				
			||||||
        class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
 | 
					 | 
				
			||||||
        <div class="flex flex-row items-center justify-between">
 | 
					 | 
				
			||||||
          <div class="flex flex-col">
 | 
					 | 
				
			||||||
            <div class="text-xs uppercase font-light text-grey-500">
 | 
					 | 
				
			||||||
              {$_('total-scans')}
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="text-xl font-bold">{stats.total_scans}</div>
 | 
					 | 
				
			||||||
          </div><svg
 | 
					 | 
				
			||||||
            stroke="currentColor"
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            size="24"
 | 
					 | 
				
			||||||
            class="stroke-current text-grey-500"
 | 
					 | 
				
			||||||
            height="24"
 | 
					 | 
				
			||||||
            width="24"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"><polyline
 | 
					 | 
				
			||||||
              points="22 12 18 12 15 21 9 3 6 12 2 12" /></svg>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div
 | 
					 | 
				
			||||||
        class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
 | 
					 | 
				
			||||||
        <div class="flex flex-row items-center justify-between">
 | 
					 | 
				
			||||||
          <div class="flex flex-col">
 | 
					 | 
				
			||||||
            <div class="text-xs uppercase font-light text-grey-500">
 | 
					 | 
				
			||||||
              {$_('total-donations')}
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="text-xl font-bold">{stats.total_donation} €</div>
 | 
					 | 
				
			||||||
          </div><svg
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
            height="24"
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            width="24"><path d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z" /></svg>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div
 | 
					 | 
				
			||||||
        class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
 | 
					 | 
				
			||||||
        <div class="flex flex-row items-center justify-between">
 | 
					 | 
				
			||||||
          <div class="flex flex-col">
 | 
					 | 
				
			||||||
            <div class="text-xs uppercase font-light text-grey-500">
 | 
					 | 
				
			||||||
              {$_('total-distance')}
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="text-xl font-bold">
 | 
					 | 
				
			||||||
              {stats.total_distance / 1000}
 | 
					 | 
				
			||||||
              km
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
            height="24"
 | 
					 | 
				
			||||||
            width="24"><path d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z" /></svg>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <a href="/teams/" class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div
 | 
					 | 
				
			||||||
        class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
 | 
					 | 
				
			||||||
        <div class="flex flex-row items-center justify-between">
 | 
					 | 
				
			||||||
          <div class="flex flex-col">
 | 
					 | 
				
			||||||
            <div class="text-xs uppercase font-light text-grey-500">
 | 
					 | 
				
			||||||
              {$_('count_teams')}
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="text-xl font-bold">{stats.total_teams}</div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            stroke="currentColor"
 | 
					 | 
				
			||||||
            fill="none"
 | 
					 | 
				
			||||||
            stroke-width="2"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
            stroke-linecap="round"
 | 
					 | 
				
			||||||
            stroke-linejoin="round"
 | 
					 | 
				
			||||||
            size="24"
 | 
					 | 
				
			||||||
            class="stroke-current text-grey-500"
 | 
					 | 
				
			||||||
            height="24"
 | 
					 | 
				
			||||||
            width="24"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"><path
 | 
					 | 
				
			||||||
              d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
 | 
					 | 
				
			||||||
            <circle cx="9" cy="7" r="4" />
 | 
					 | 
				
			||||||
            <path d="M23 21v-2a4 4 0 0 0-3-3.87" />
 | 
					 | 
				
			||||||
            <path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </a>
 | 
					 | 
				
			||||||
    <a href="/orgs/" class="w-full lg:w-1/4">
 | 
					 | 
				
			||||||
      <div
 | 
					 | 
				
			||||||
        class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
 | 
					 | 
				
			||||||
        <div class="flex flex-row items-center justify-between">
 | 
					 | 
				
			||||||
          <div class="flex flex-col">
 | 
					 | 
				
			||||||
            <div class="text-xs uppercase font-light text-grey-500">
 | 
					 | 
				
			||||||
              {$_('count_organizations')}
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="text-xl font-bold">{stats.total_orgs}</div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <svg
 | 
					 | 
				
			||||||
            height="24"
 | 
					 | 
				
			||||||
            fill="currentColor"
 | 
					 | 
				
			||||||
            width="24"
 | 
					 | 
				
			||||||
            xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
            viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z" />
 | 
					 | 
				
			||||||
            <path
 | 
					 | 
				
			||||||
              d="M17 11V3H7v4H3v14h8v-4h2v4h8V11h-4zM7 19H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm4 4H9v-2h2v2zm0-4H9V9h2v2zm0-4H9V5h2v2zm4 8h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm4 12h-2v-2h2v2zm0-4h-2v-2h2v2z" /></svg>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </a>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
{:catch error}
 | 
					 | 
				
			||||||
  <div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
 | 
					 | 
				
			||||||
    <span class="inline-block align-middle mr-8">
 | 
					 | 
				
			||||||
      <b class="capitalize">{$_('general_promise_error')}</b>
 | 
					 | 
				
			||||||
      {error}
 | 
					 | 
				
			||||||
    </span>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
{/await}
 | 
					 | 
				
			||||||
@@ -1,84 +0,0 @@
 | 
				
			|||||||
<!-- This example requires Tailwind CSS v2.0+ -->
 | 
					 | 
				
			||||||
<div class="flex flex-col">
 | 
					 | 
				
			||||||
  <div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
 | 
					 | 
				
			||||||
    <div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
 | 
					 | 
				
			||||||
      <div
 | 
					 | 
				
			||||||
        class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
 | 
					 | 
				
			||||||
        <table class="min-w-full divide-y divide-gray-200">
 | 
					 | 
				
			||||||
          <thead class="bg-gray-50">
 | 
					 | 
				
			||||||
            <tr>
 | 
					 | 
				
			||||||
              <th
 | 
					 | 
				
			||||||
                scope="col"
 | 
					 | 
				
			||||||
                class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
 | 
					 | 
				
			||||||
                Name
 | 
					 | 
				
			||||||
              </th>
 | 
					 | 
				
			||||||
              <th
 | 
					 | 
				
			||||||
                scope="col"
 | 
					 | 
				
			||||||
                class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
 | 
					 | 
				
			||||||
                Title
 | 
					 | 
				
			||||||
              </th>
 | 
					 | 
				
			||||||
              <th
 | 
					 | 
				
			||||||
                scope="col"
 | 
					 | 
				
			||||||
                class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
 | 
					 | 
				
			||||||
                Status
 | 
					 | 
				
			||||||
              </th>
 | 
					 | 
				
			||||||
              <th
 | 
					 | 
				
			||||||
                scope="col"
 | 
					 | 
				
			||||||
                class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
 | 
					 | 
				
			||||||
                Role
 | 
					 | 
				
			||||||
              </th>
 | 
					 | 
				
			||||||
              <th scope="col" class="relative px-6 py-3">
 | 
					 | 
				
			||||||
                <span class="sr-only">Edit</span>
 | 
					 | 
				
			||||||
              </th>
 | 
					 | 
				
			||||||
            </tr>
 | 
					 | 
				
			||||||
          </thead>
 | 
					 | 
				
			||||||
          <tbody class="divide-y divide-gray-200">
 | 
					 | 
				
			||||||
            <tr>
 | 
					 | 
				
			||||||
              <td class="px-6 py-4 whitespace-nowrap">
 | 
					 | 
				
			||||||
                <div class="flex items-center">
 | 
					 | 
				
			||||||
                  <div class="flex-shrink-0 h-10 w-10">
 | 
					 | 
				
			||||||
                    <img
 | 
					 | 
				
			||||||
                      class="h-10 w-10 rounded-full"
 | 
					 | 
				
			||||||
                      src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=4&w=256&h=256&q=60"
 | 
					 | 
				
			||||||
                      alt="" />
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                  <div class="ml-4">
 | 
					 | 
				
			||||||
                    <div class="text-sm font-medium text-gray-900">
 | 
					 | 
				
			||||||
                      Jane Cooper
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="text-sm text-gray-500">
 | 
					 | 
				
			||||||
                      jane.cooper@example.com
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
              </td>
 | 
					 | 
				
			||||||
              <td class="px-6 py-4 whitespace-nowrap">
 | 
					 | 
				
			||||||
                <div class="text-sm text-gray-900">
 | 
					 | 
				
			||||||
                  Regional Paradigm Technician
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div class="text-sm text-gray-500">Optimization</div>
 | 
					 | 
				
			||||||
              </td>
 | 
					 | 
				
			||||||
              <td class="px-6 py-4 whitespace-nowrap">
 | 
					 | 
				
			||||||
                <span
 | 
					 | 
				
			||||||
                  class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
 | 
					 | 
				
			||||||
                  Active
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
              </td>
 | 
					 | 
				
			||||||
              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
 | 
					 | 
				
			||||||
                Admin
 | 
					 | 
				
			||||||
              </td>
 | 
					 | 
				
			||||||
              <td
 | 
					 | 
				
			||||||
                class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
 | 
					 | 
				
			||||||
                <a
 | 
					 | 
				
			||||||
                  href="#"
 | 
					 | 
				
			||||||
                  class="text-indigo-600 hover:text-indigo-900">Edit</a>
 | 
					 | 
				
			||||||
              </td>
 | 
					 | 
				
			||||||
            </tr>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <!-- More rows... -->
 | 
					 | 
				
			||||||
          </tbody>
 | 
					 | 
				
			||||||
        </table>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
<h3 class="text-lg">Tabs</h3>
 | 
					 | 
				
			||||||
<div
 | 
					 | 
				
			||||||
  class="w-full flex sm:border-b sm:border-gray-300 relative flex-col sm:flex-row">
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="flex-1 sm:text-center font-medium pb-3 cursor-pointer hover:text-blue-400 false">
 | 
					 | 
				
			||||||
    1
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="flex-1 sm:text-center font-medium pb-3 cursor-pointer hover:text-blue-400 false">
 | 
					 | 
				
			||||||
    2
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="flex-1 sm:text-center font-medium pb-3 cursor-pointer hover:text-blue-400 false">
 | 
					 | 
				
			||||||
    3
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="hidden sm:block absolute bottom-0 left-0 h-1 bg-blue-400 transition-transform duration-300 ease-out w-1/4 transform translate-x-double" />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,102 +0,0 @@
 | 
				
			|||||||
<div>
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 bg-blue-200 text-blue-700 rounded-full">
 | 
					 | 
				
			||||||
    <svg
 | 
					 | 
				
			||||||
      xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
      width="16"
 | 
					 | 
				
			||||||
      height="16"
 | 
					 | 
				
			||||||
      viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
      fill="none"
 | 
					 | 
				
			||||||
      stroke="currentColor"
 | 
					 | 
				
			||||||
      stroke-width="2"
 | 
					 | 
				
			||||||
      stroke-linecap="round"
 | 
					 | 
				
			||||||
      stroke-linejoin="round"
 | 
					 | 
				
			||||||
      class="feather feather-bell-off mr-2">
 | 
					 | 
				
			||||||
      <path d="M13.73 21a2 2 0 0 1-3.46 0" />
 | 
					 | 
				
			||||||
      <path d="M18.63 13A17.89 17.89 0 0 1 18 8" />
 | 
					 | 
				
			||||||
      <path d="M6.26 6.26A5.86 5.86 0 0 0 6 8c0 7-3 9-3 9h14" />
 | 
					 | 
				
			||||||
      <path d="M18 8a6 6 0 0 0-9.33-5" />
 | 
					 | 
				
			||||||
      <line x1="1" y1="1" x2="23" y2="23" />
 | 
					 | 
				
			||||||
    </svg>
 | 
					 | 
				
			||||||
    Tag
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="ml-4 text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 bg-green-200 text-green-700 rounded-full">
 | 
					 | 
				
			||||||
    <svg
 | 
					 | 
				
			||||||
      xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
      width="16"
 | 
					 | 
				
			||||||
      height="16"
 | 
					 | 
				
			||||||
      viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
      fill="none"
 | 
					 | 
				
			||||||
      stroke="currentColor"
 | 
					 | 
				
			||||||
      stroke-width="2"
 | 
					 | 
				
			||||||
      stroke-linecap="round"
 | 
					 | 
				
			||||||
      stroke-linejoin="round"
 | 
					 | 
				
			||||||
      class="feather feather-arrow-right mr-2">
 | 
					 | 
				
			||||||
      <line x1="5" y1="12" x2="19" y2="12" />
 | 
					 | 
				
			||||||
      <polyline points="12 5 19 12 12 19" />
 | 
					 | 
				
			||||||
    </svg>
 | 
					 | 
				
			||||||
    Tag
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="ml-4 text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 bg-orange-200 text-orange-700 rounded-full">
 | 
					 | 
				
			||||||
    <svg
 | 
					 | 
				
			||||||
      xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
      width="16"
 | 
					 | 
				
			||||||
      height="16"
 | 
					 | 
				
			||||||
      viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
      fill="none"
 | 
					 | 
				
			||||||
      stroke="currentColor"
 | 
					 | 
				
			||||||
      stroke-width="2"
 | 
					 | 
				
			||||||
      stroke-linecap="round"
 | 
					 | 
				
			||||||
      stroke-linejoin="round"
 | 
					 | 
				
			||||||
      class="feather feather-activity mr-2">
 | 
					 | 
				
			||||||
      <polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
 | 
					 | 
				
			||||||
    </svg>
 | 
					 | 
				
			||||||
    Tag
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="ml-4 text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 bg-red-200 text-red-700 rounded-full">
 | 
					 | 
				
			||||||
    <svg
 | 
					 | 
				
			||||||
      xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
      width="16"
 | 
					 | 
				
			||||||
      height="16"
 | 
					 | 
				
			||||||
      viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
      fill="none"
 | 
					 | 
				
			||||||
      stroke="currentColor"
 | 
					 | 
				
			||||||
      stroke-width="2"
 | 
					 | 
				
			||||||
      stroke-linecap="round"
 | 
					 | 
				
			||||||
      stroke-linejoin="round"
 | 
					 | 
				
			||||||
      class="feather feather-archive mr-2">
 | 
					 | 
				
			||||||
      <polyline points="21 8 21 21 3 21 3 8" />
 | 
					 | 
				
			||||||
      <rect x="1" y="3" width="22" height="5" />
 | 
					 | 
				
			||||||
      <line x1="10" y1="12" x2="14" y2="12" />
 | 
					 | 
				
			||||||
    </svg>
 | 
					 | 
				
			||||||
    Tag
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="ml-4 text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 rounded-full bg-white text-gray-700 border">
 | 
					 | 
				
			||||||
    <svg
 | 
					 | 
				
			||||||
      xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
      width="16"
 | 
					 | 
				
			||||||
      height="16"
 | 
					 | 
				
			||||||
      viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
      fill="none"
 | 
					 | 
				
			||||||
      stroke="currentColor"
 | 
					 | 
				
			||||||
      stroke-width="2"
 | 
					 | 
				
			||||||
      stroke-linecap="round"
 | 
					 | 
				
			||||||
      stroke-linejoin="round"
 | 
					 | 
				
			||||||
      class="feather feather-hard-drive mr-2">
 | 
					 | 
				
			||||||
      <line x1="22" y1="12" x2="2" y2="12" />
 | 
					 | 
				
			||||||
      <path
 | 
					 | 
				
			||||||
        d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" />
 | 
					 | 
				
			||||||
      <line x1="6" y1="16" x2="6.01" y2="16" />
 | 
					 | 
				
			||||||
      <line x1="10" y1="16" x2="10.01" y2="16" />
 | 
					 | 
				
			||||||
    </svg>
 | 
					 | 
				
			||||||
    Tag
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<section class="container p-5">
 | 
					 | 
				
			||||||
  <span class="mb-1 text-3xl font-extrabold leading-tight">
 | 
					 | 
				
			||||||
    {$_('teams')}
 | 
					 | 
				
			||||||
  </span>
 | 
					 | 
				
			||||||
  <p class="mb-8 text-lg text-gray-500">everything is more fun together 🏃♂️🏃♀️🏃♂️</p>
 | 
					 | 
				
			||||||
</section>
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _, locale } from "svelte-i18n";
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div>$locale $_('hallo')</div>
 | 
					 | 
				
			||||||
@@ -1,189 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _, json } from "svelte-i18n";
 | 
					 | 
				
			||||||
  import Toastify from "toastify-js";
 | 
					 | 
				
			||||||
  import TracksEmptyState from "./TracksEmptyState.svelte";
 | 
					 | 
				
			||||||
  import { TrackService } from "@odit/lfk-client-js";
 | 
					 | 
				
			||||||
  const tracks_promise = TrackService.trackControllerGetAll();
 | 
					 | 
				
			||||||
  import { getlang } from "./datatable_i18n";
 | 
					 | 
				
			||||||
  import { Grid, html } from "gridjs";
 | 
					 | 
				
			||||||
  import "gridjs/dist/theme/mermaid.css";
 | 
					 | 
				
			||||||
  import { tracks as tracksstore } from "../store.js";
 | 
					 | 
				
			||||||
  $: trackscache = [];
 | 
					 | 
				
			||||||
  $: blocked = [];
 | 
					 | 
				
			||||||
  let table;
 | 
					 | 
				
			||||||
  let datatable;
 | 
					 | 
				
			||||||
  let datatable_inited = false;
 | 
					 | 
				
			||||||
  tracksstore.subscribe((val) => {
 | 
					 | 
				
			||||||
    trackscache = val;
 | 
					 | 
				
			||||||
    setTimeout(() => {
 | 
					 | 
				
			||||||
      if (val.length > 0) {
 | 
					 | 
				
			||||||
        renderdatatable();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }, 100);
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  tracks_promise.then((data) => {
 | 
					 | 
				
			||||||
    tracksstore.set(data);
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  window.track__edit_cancel = () => renderdatatable();
 | 
					 | 
				
			||||||
  window.track__edit_save = () => {
 | 
					 | 
				
			||||||
    const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
 | 
					 | 
				
			||||||
    if (blocked.includes(trackid)) {
 | 
					 | 
				
			||||||
      //
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      blocked.push(trackid);
 | 
					 | 
				
			||||||
      const elem = document.querySelector(
 | 
					 | 
				
			||||||
        `[data-id="triggered_table_actions_${trackid}"]`
 | 
					 | 
				
			||||||
      ).parentNode.parentNode.parentNode;
 | 
					 | 
				
			||||||
      Toastify({
 | 
					 | 
				
			||||||
        text: "Track is being updated...",
 | 
					 | 
				
			||||||
        duration: 500,
 | 
					 | 
				
			||||||
      }).showToast();
 | 
					 | 
				
			||||||
      TrackService.trackControllerPut(trackid, {
 | 
					 | 
				
			||||||
        id: trackid,
 | 
					 | 
				
			||||||
        name: elem.childNodes[0].childNodes[0].value,
 | 
					 | 
				
			||||||
        distance: parseInt(elem.childNodes[1].childNodes[0].value),
 | 
					 | 
				
			||||||
        minimumLapTime: parseInt(elem.childNodes[2].childNodes[0].value),
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
        .then((r) => {
 | 
					 | 
				
			||||||
          Toastify({
 | 
					 | 
				
			||||||
            text: "Track was updated!",
 | 
					 | 
				
			||||||
            backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
 | 
					 | 
				
			||||||
            duration: 1000,
 | 
					 | 
				
			||||||
          }).showToast();
 | 
					 | 
				
			||||||
          blocked = blocked.filter((e) => e !== trackid);
 | 
					 | 
				
			||||||
          document
 | 
					 | 
				
			||||||
            .querySelector(`[data-id="default_table_actions_${trackid}"]`)
 | 
					 | 
				
			||||||
            .classList.remove("hidden");
 | 
					 | 
				
			||||||
          document
 | 
					 | 
				
			||||||
            .querySelector(`[data-id="triggered_table_actions_${trackid}"]`)
 | 
					 | 
				
			||||||
            .classList.add("hidden");
 | 
					 | 
				
			||||||
          //
 | 
					 | 
				
			||||||
          elem.childNodes[0].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[0].childNodes[0].value}</td>`;
 | 
					 | 
				
			||||||
          elem.childNodes[1].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[1].childNodes[0].value}</td>`;
 | 
					 | 
				
			||||||
          elem.childNodes[2].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[2].childNodes[0].value}</td>`;
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .catch((err) => {
 | 
					 | 
				
			||||||
          console.error(err);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  window.track__delete_handler = () => {
 | 
					 | 
				
			||||||
    const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
 | 
					 | 
				
			||||||
    document
 | 
					 | 
				
			||||||
      .querySelector(`[data-id="default_table_actions_${trackid}"]`)
 | 
					 | 
				
			||||||
      .classList.add("hidden");
 | 
					 | 
				
			||||||
    document
 | 
					 | 
				
			||||||
      .querySelector(`[data-id="deleteconfirmation_table_actions_${trackid}"]`)
 | 
					 | 
				
			||||||
      .classList.remove("hidden");
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  window.track__delete_cancel = () => {
 | 
					 | 
				
			||||||
    const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
 | 
					 | 
				
			||||||
    document
 | 
					 | 
				
			||||||
      .querySelector(`[data-id="default_table_actions_${trackid}"]`)
 | 
					 | 
				
			||||||
      .classList.remove("hidden");
 | 
					 | 
				
			||||||
    document
 | 
					 | 
				
			||||||
      .querySelector(`[data-id="deleteconfirmation_table_actions_${trackid}"]`)
 | 
					 | 
				
			||||||
      .classList.add("hidden");
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  window.track__delete_confirm = () => {
 | 
					 | 
				
			||||||
    const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
 | 
					 | 
				
			||||||
    TrackService.trackControllerRemove(trackid)
 | 
					 | 
				
			||||||
      .then(() => {
 | 
					 | 
				
			||||||
        const newStoreVal = trackscache.filter((obj) => obj.id !== trackid);
 | 
					 | 
				
			||||||
        tracksstore.set(newStoreVal);
 | 
					 | 
				
			||||||
        renderdatatable();
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      .catch((err) => {
 | 
					 | 
				
			||||||
        console.log(err);
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  window.track__edit_handler = () => {
 | 
					 | 
				
			||||||
    const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
 | 
					 | 
				
			||||||
    document
 | 
					 | 
				
			||||||
      .querySelector(`[data-id="default_table_actions_${trackid}"]`)
 | 
					 | 
				
			||||||
      .classList.add("hidden");
 | 
					 | 
				
			||||||
    document
 | 
					 | 
				
			||||||
      .querySelector(`[data-id="triggered_table_actions_${trackid}"]`)
 | 
					 | 
				
			||||||
      .classList.remove("hidden");
 | 
					 | 
				
			||||||
    const elem = document.querySelector(
 | 
					 | 
				
			||||||
      `[data-id="triggered_table_actions_${trackid}"]`
 | 
					 | 
				
			||||||
    ).parentNode.parentNode.parentNode;
 | 
					 | 
				
			||||||
    const trackname = elem.childNodes[0].textContent;
 | 
					 | 
				
			||||||
    const tracklength = parseInt(elem.childNodes[1].textContent);
 | 
					 | 
				
			||||||
    const trackmintime = parseInt(elem.childNodes[2].textContent);
 | 
					 | 
				
			||||||
    elem.childNodes[0].innerHTML = `<input type="text" value="${trackname}" name="trackname" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2">`;
 | 
					 | 
				
			||||||
    elem.childNodes[1].innerHTML = `<input type="text" value="${tracklength}" name="tracklength" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2">`;
 | 
					 | 
				
			||||||
    elem.childNodes[2].innerHTML = `<input type="text" value="${trackmintime}" name="trackmintime" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2">`;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  //
 | 
					 | 
				
			||||||
  function renderdatatable() {
 | 
					 | 
				
			||||||
    let tabledata = [];
 | 
					 | 
				
			||||||
    trackscache.forEach((track) => {
 | 
					 | 
				
			||||||
      tabledata.push([
 | 
					 | 
				
			||||||
        track.name,
 | 
					 | 
				
			||||||
        track.distance,
 | 
					 | 
				
			||||||
        track.minimumLapTime || 0,
 | 
					 | 
				
			||||||
        html(`
 | 
					 | 
				
			||||||
        <div class="hidden" data-id="triggered_table_actions_${track.id}">
 | 
					 | 
				
			||||||
          <button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_save()">Save</button>
 | 
					 | 
				
			||||||
          <button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_cancel()">Cancel</button>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div data-id="default_table_actions_${track.id}">
 | 
					 | 
				
			||||||
          <button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_handler()">Edit</button>
 | 
					 | 
				
			||||||
          <button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_handler()">Delete</button>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div class="hidden" data-id="deleteconfirmation_table_actions_${track.id}">
 | 
					 | 
				
			||||||
          <button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_cancel()">Cancel</button>
 | 
					 | 
				
			||||||
          <button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_confirm()">Confirm</button>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      `),
 | 
					 | 
				
			||||||
      ]);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (datatable_inited === false) {
 | 
					 | 
				
			||||||
      datatable = new Grid({
 | 
					 | 
				
			||||||
        columns: [
 | 
					 | 
				
			||||||
          $_("track-name"),
 | 
					 | 
				
			||||||
          $_("track-length-in-m"),
 | 
					 | 
				
			||||||
          $_("minimum-lap-time-in-s"),
 | 
					 | 
				
			||||||
          $_("action"),
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        language: getlang($json("datatable")),
 | 
					 | 
				
			||||||
        sort: true,
 | 
					 | 
				
			||||||
        search: { enabled: true },
 | 
					 | 
				
			||||||
        data: tabledata,
 | 
					 | 
				
			||||||
        pagination: {
 | 
					 | 
				
			||||||
          enabled: true,
 | 
					 | 
				
			||||||
          limit: 25,
 | 
					 | 
				
			||||||
          summary: false,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      }).render(table);
 | 
					 | 
				
			||||||
      datatable_inited = true;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      datatable.updateConfig({ data: tabledata }).forceRender();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if trackscache.length > 0}
 | 
					 | 
				
			||||||
  <div bind:this={table} />
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
{#await tracks_promise}
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
 | 
					 | 
				
			||||||
    role="alert">
 | 
					 | 
				
			||||||
    <p class="font-bold">{$_('track-data-is-being-loaded')}</p>
 | 
					 | 
				
			||||||
    <p class="text-sm">{$_('this-might-take-a-moment')}</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
{:then}
 | 
					 | 
				
			||||||
  {#if trackscache.length === 0}
 | 
					 | 
				
			||||||
    <TracksEmptyState />
 | 
					 | 
				
			||||||
  {/if}
 | 
					 | 
				
			||||||
{:catch error}
 | 
					 | 
				
			||||||
  <div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
 | 
					 | 
				
			||||||
    <span class="inline-block align-middle mr-8">
 | 
					 | 
				
			||||||
      <b class="capitalize">{$_('general_promise_error')}</b>
 | 
					 | 
				
			||||||
      {error}
 | 
					 | 
				
			||||||
    </span>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
{/await}
 | 
					 | 
				
			||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  import AddTrackModal from "./AddTrackModal.svelte";
 | 
					 | 
				
			||||||
  let modal_open = false;
 | 
					 | 
				
			||||||
  import Tracks from "./Tracks.svelte";
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<section class="container p-5">
 | 
					 | 
				
			||||||
  <span class="mb-1 text-3xl font-extrabold leading-tight">
 | 
					 | 
				
			||||||
    Tracks
 | 
					 | 
				
			||||||
    <button
 | 
					 | 
				
			||||||
      on:click={() => {
 | 
					 | 
				
			||||||
        modal_open = true;
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
      type="button"
 | 
					 | 
				
			||||||
      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
 | 
					 | 
				
			||||||
      Create Track
 | 
					 | 
				
			||||||
    </button>
 | 
					 | 
				
			||||||
  </span>
 | 
					 | 
				
			||||||
  <p class="mb-8 text-lg text-gray-500">
 | 
					 | 
				
			||||||
    configure the tracks & minimum lap times
 | 
					 | 
				
			||||||
  </p>
 | 
					 | 
				
			||||||
  <Tracks />
 | 
					 | 
				
			||||||
</section>
 | 
					 | 
				
			||||||
<AddTrackModal bind:modal_open />
 | 
					 | 
				
			||||||
@@ -1,171 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  import lodashIsEqual from "lodash.isequal";
 | 
					 | 
				
			||||||
  import { UserService } from "@odit/lfk-client-js";
 | 
					 | 
				
			||||||
  import "gridjs/dist/theme/mermaid.css";
 | 
					 | 
				
			||||||
  import PromiseError from "./PromiseError.svelte";
 | 
					 | 
				
			||||||
  export let params;
 | 
					 | 
				
			||||||
  const user_promise = UserService.userControllerGetOne(params.userid);
 | 
					 | 
				
			||||||
  let data_loaded = false;
 | 
					 | 
				
			||||||
  let original_data = undefined;
 | 
					 | 
				
			||||||
  $: editable_userdata = undefined;
 | 
					 | 
				
			||||||
  user_promise.then((data) => {
 | 
					 | 
				
			||||||
    data_loaded = true;
 | 
					 | 
				
			||||||
    original_data = data;
 | 
					 | 
				
			||||||
    editable_userdata = data;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  // $: changes_performed = lodashIsEqual(original_data, editable_userdata);
 | 
					 | 
				
			||||||
  $: changes_performed = !lodashIsEqual({ test: 1 }, { test: 1 });
 | 
					 | 
				
			||||||
  function submit() {
 | 
					 | 
				
			||||||
    if (data_loaded === true && changes_performed === true) {
 | 
					 | 
				
			||||||
      console.log("ok, submitting...");
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      console.log("no changes performed");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#await user_promise}
 | 
					 | 
				
			||||||
  <!--  -->
 | 
					 | 
				
			||||||
{:then user}
 | 
					 | 
				
			||||||
  <section class="container p-5 select-none">
 | 
					 | 
				
			||||||
    <div class="flex flex-row mb-4">
 | 
					 | 
				
			||||||
      <div class="w-full">
 | 
					 | 
				
			||||||
        <nav class="w-full flex">
 | 
					 | 
				
			||||||
          <ol class="list-none flex flex-row items-center justify-start">
 | 
					 | 
				
			||||||
            <li class="flex items-center">
 | 
					 | 
				
			||||||
              <svg
 | 
					 | 
				
			||||||
                class="flex-shrink-0 w-5 h-5 mr-2"
 | 
					 | 
				
			||||||
                fill="currentColor"
 | 
					 | 
				
			||||||
                width="24"
 | 
					 | 
				
			||||||
                height="24"
 | 
					 | 
				
			||||||
                xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
                viewBox="0 0 640 512"><path
 | 
					 | 
				
			||||||
                  fill="currentColor"
 | 
					 | 
				
			||||||
                  d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" /></svg>
 | 
					 | 
				
			||||||
            </li>
 | 
					 | 
				
			||||||
            <li class="flex items-center">
 | 
					 | 
				
			||||||
              <a class="mr-2" href="./">{$_('users')}</a><svg
 | 
					 | 
				
			||||||
                stroke="currentColor"
 | 
					 | 
				
			||||||
                fill="none"
 | 
					 | 
				
			||||||
                stroke-width="2"
 | 
					 | 
				
			||||||
                viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
                stroke-linecap="round"
 | 
					 | 
				
			||||||
                stroke-linejoin="round"
 | 
					 | 
				
			||||||
                class="h-3 w-3 mr-2 stroke-current"
 | 
					 | 
				
			||||||
                height="1em"
 | 
					 | 
				
			||||||
                width="1em"
 | 
					 | 
				
			||||||
                xmlns="http://www.w3.org/2000/svg"><line
 | 
					 | 
				
			||||||
                  x1="5"
 | 
					 | 
				
			||||||
                  y1="12"
 | 
					 | 
				
			||||||
                  x2="19"
 | 
					 | 
				
			||||||
                  y2="12" />
 | 
					 | 
				
			||||||
                <polyline points="12 5 19 12 12 19" /></svg>
 | 
					 | 
				
			||||||
            </li>
 | 
					 | 
				
			||||||
            <li class="flex items-center">
 | 
					 | 
				
			||||||
              <span class="mr-2">{user.firstname}
 | 
					 | 
				
			||||||
                {user.middlename || ''}
 | 
					 | 
				
			||||||
                {user.lastname}</span>
 | 
					 | 
				
			||||||
            </li>
 | 
					 | 
				
			||||||
          </ol>
 | 
					 | 
				
			||||||
        </nav>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="mb-8 text-3xl font-extrabold leading-tight">
 | 
					 | 
				
			||||||
      {user.firstname}
 | 
					 | 
				
			||||||
      {user.middlename || ''}
 | 
					 | 
				
			||||||
      {user.lastname}
 | 
					 | 
				
			||||||
      <span data-id="user_actions_${user.id}">
 | 
					 | 
				
			||||||
        <button
 | 
					 | 
				
			||||||
          class="hidden w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-400 text-base font-medium text-white sm:w-auto sm:text-sm"
 | 
					 | 
				
			||||||
          data-userid="${user.id}"
 | 
					 | 
				
			||||||
          onclick="user__delete_cancel()">{$_('cancel')}</button>
 | 
					 | 
				
			||||||
        <button
 | 
					 | 
				
			||||||
          class="hidden w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm"
 | 
					 | 
				
			||||||
          data-userid="${user.id}"
 | 
					 | 
				
			||||||
          onclick="user__delete_confirm()">{$_('confirm-delete')}</button>
 | 
					 | 
				
			||||||
        <button
 | 
					 | 
				
			||||||
          type="button"
 | 
					 | 
				
			||||||
          class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('delete-user')}</button>
 | 
					 | 
				
			||||||
        <button
 | 
					 | 
				
			||||||
          disabled={!changes_performed}
 | 
					 | 
				
			||||||
          class:opacity-50={!changes_performed}
 | 
					 | 
				
			||||||
          type="button"
 | 
					 | 
				
			||||||
          on:click={submit}
 | 
					 | 
				
			||||||
          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:ml-3 sm:w-auto sm:text-sm">{$_('save-changes')}</button>
 | 
					 | 
				
			||||||
      </span>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <!--  -->
 | 
					 | 
				
			||||||
    <div class="mt-2 flex items-center">
 | 
					 | 
				
			||||||
      <img
 | 
					 | 
				
			||||||
        alt={$_('profile-picture')}
 | 
					 | 
				
			||||||
        class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100"
 | 
					 | 
				
			||||||
        src={user.profilePic} />
 | 
					 | 
				
			||||||
      <!-- <span
 | 
					 | 
				
			||||||
        class="inline-block h-12 w-12 rounded-full overflow-hidden bg-gray-100"><svg
 | 
					 | 
				
			||||||
          class="h-full w-full text-gray-300"
 | 
					 | 
				
			||||||
          fill="currentColor"
 | 
					 | 
				
			||||||
          viewBox="0 0 24 24"><path
 | 
					 | 
				
			||||||
            d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" /></svg></span> -->
 | 
					 | 
				
			||||||
      <button
 | 
					 | 
				
			||||||
        type="button"
 | 
					 | 
				
			||||||
        class="ml-5 bg-white py-2 px-3 border border-gray-300 rounded-md shadow-sm text-sm leading-4 font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Change</button>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <!--  -->
 | 
					 | 
				
			||||||
    <div class="mt-3 text-sm w-full">
 | 
					 | 
				
			||||||
      <input
 | 
					 | 
				
			||||||
        id="enabled"
 | 
					 | 
				
			||||||
        on:change={() => {
 | 
					 | 
				
			||||||
          editable_userdata.enabled = !editable_userdata.enabled;
 | 
					 | 
				
			||||||
          // TODO: this reactive set does not work?
 | 
					 | 
				
			||||||
        }}
 | 
					 | 
				
			||||||
        name="enabled"
 | 
					 | 
				
			||||||
        type="checkbox"
 | 
					 | 
				
			||||||
        checked={editable_userdata.enabled}
 | 
					 | 
				
			||||||
        class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
 | 
					 | 
				
			||||||
      <label
 | 
					 | 
				
			||||||
        for="enabled"
 | 
					 | 
				
			||||||
        class="ml-1 font-medium text-gray-700">Active?</label>
 | 
					 | 
				
			||||||
      <p class="text-gray-500">set the user active/ inactive</p>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="text-sm w-full">
 | 
					 | 
				
			||||||
      <label
 | 
					 | 
				
			||||||
        for="firstname"
 | 
					 | 
				
			||||||
        class="font-medium text-gray-700">{$_('first-name')}</label>
 | 
					 | 
				
			||||||
      <input
 | 
					 | 
				
			||||||
        autocomplete="off"
 | 
					 | 
				
			||||||
        placeholder={$_('first-name')}
 | 
					 | 
				
			||||||
        type="text"
 | 
					 | 
				
			||||||
        bind:value={editable_userdata.firstname}
 | 
					 | 
				
			||||||
        name="firstname"
 | 
					 | 
				
			||||||
        class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="text-sm w-full">
 | 
					 | 
				
			||||||
      <label
 | 
					 | 
				
			||||||
        for="middlename"
 | 
					 | 
				
			||||||
        class="font-medium text-gray-700">{$_('middle-name')}</label>
 | 
					 | 
				
			||||||
      <input
 | 
					 | 
				
			||||||
        autocomplete="off"
 | 
					 | 
				
			||||||
        placeholder={$_('middle-name')}
 | 
					 | 
				
			||||||
        type="text"
 | 
					 | 
				
			||||||
        bind:value={editable_userdata.middlename}
 | 
					 | 
				
			||||||
        name="middlename"
 | 
					 | 
				
			||||||
        class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="text-sm w-full">
 | 
					 | 
				
			||||||
      <label
 | 
					 | 
				
			||||||
        for="lastname"
 | 
					 | 
				
			||||||
        class="font-medium text-gray-700">{$_('last-name')}</label>
 | 
					 | 
				
			||||||
      <input
 | 
					 | 
				
			||||||
        autocomplete="off"
 | 
					 | 
				
			||||||
        placeholder={$_('last-name')}
 | 
					 | 
				
			||||||
        type="text"
 | 
					 | 
				
			||||||
        bind:value={editable_userdata.lastname}
 | 
					 | 
				
			||||||
        name="lastname"
 | 
					 | 
				
			||||||
        class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </section>
 | 
					 | 
				
			||||||
{:catch error}
 | 
					 | 
				
			||||||
  <PromiseError {error} />
 | 
					 | 
				
			||||||
{/await}
 | 
					 | 
				
			||||||
@@ -1,147 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					 | 
				
			||||||
  import Toastify from "toastify-js";
 | 
					 | 
				
			||||||
  import { UserService } from "@odit/lfk-client-js";
 | 
					 | 
				
			||||||
  const users_promise = UserService.userControllerGetAll();
 | 
					 | 
				
			||||||
  import "gridjs/dist/theme/mermaid.css";
 | 
					 | 
				
			||||||
  import { users as usersstore } from "../store.js";
 | 
					 | 
				
			||||||
  import UsersEmptyState from "./UsersEmptyState.svelte";
 | 
					 | 
				
			||||||
  $: searchvalue = "";
 | 
					 | 
				
			||||||
  $: userscache = [];
 | 
					 | 
				
			||||||
  $: advanced_search = false;
 | 
					 | 
				
			||||||
  usersstore.subscribe((val) => {
 | 
					 | 
				
			||||||
    userscache = val;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  users_promise.then((data) => {
 | 
					 | 
				
			||||||
    console.log(data);
 | 
					 | 
				
			||||||
    usersstore.set(data);
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#await users_promise}
 | 
					 | 
				
			||||||
  <div
 | 
					 | 
				
			||||||
    class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
 | 
					 | 
				
			||||||
    role="alert">
 | 
					 | 
				
			||||||
    <p class="font-bold">users are being loaded...</p>
 | 
					 | 
				
			||||||
    <p class="text-sm">{$_('this-might-take-a-moment')}</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
{:then users}
 | 
					 | 
				
			||||||
  {#if userscache.length === 0}
 | 
					 | 
				
			||||||
    <UsersEmptyState />
 | 
					 | 
				
			||||||
  {:else}
 | 
					 | 
				
			||||||
    {#if advanced_search}
 | 
					 | 
				
			||||||
      advanced search
 | 
					 | 
				
			||||||
    {:else}
 | 
					 | 
				
			||||||
      <input
 | 
					 | 
				
			||||||
        type="search"
 | 
					 | 
				
			||||||
        bind:value={searchvalue}
 | 
					 | 
				
			||||||
        placeholder={$_('datatable.search')}
 | 
					 | 
				
			||||||
        aria-label={$_('datatable.search')}
 | 
					 | 
				
			||||||
        class="gridjs-input gridjs-search-input mb-4" />
 | 
					 | 
				
			||||||
    {/if}
 | 
					 | 
				
			||||||
    <button
 | 
					 | 
				
			||||||
      on:click={() => {
 | 
					 | 
				
			||||||
        advanced_search = !advanced_search;
 | 
					 | 
				
			||||||
      }}
 | 
					 | 
				
			||||||
      type="button"
 | 
					 | 
				
			||||||
      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm">
 | 
					 | 
				
			||||||
      {#if advanced_search}
 | 
					 | 
				
			||||||
        toggle simple search
 | 
					 | 
				
			||||||
      {:else}toggle advanced search{/if}
 | 
					 | 
				
			||||||
    </button>
 | 
					 | 
				
			||||||
    <div
 | 
					 | 
				
			||||||
      class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
 | 
					 | 
				
			||||||
      <table class="divide-y divide-gray-200 w-full">
 | 
					 | 
				
			||||||
        <thead class="bg-gray-50">
 | 
					 | 
				
			||||||
          <tr>
 | 
					 | 
				
			||||||
            <th
 | 
					 | 
				
			||||||
              scope="col"
 | 
					 | 
				
			||||||
              class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
 | 
					 | 
				
			||||||
              Name
 | 
					 | 
				
			||||||
            </th>
 | 
					 | 
				
			||||||
            <th
 | 
					 | 
				
			||||||
              scope="col"
 | 
					 | 
				
			||||||
              class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
 | 
					 | 
				
			||||||
              Status
 | 
					 | 
				
			||||||
            </th>
 | 
					 | 
				
			||||||
            <th
 | 
					 | 
				
			||||||
              scope="col"
 | 
					 | 
				
			||||||
              class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
 | 
					 | 
				
			||||||
              Groups
 | 
					 | 
				
			||||||
            </th>
 | 
					 | 
				
			||||||
            <th scope="col" class="relative px-6 py-3">
 | 
					 | 
				
			||||||
              <span class="sr-only">Action</span>
 | 
					 | 
				
			||||||
            </th>
 | 
					 | 
				
			||||||
          </tr>
 | 
					 | 
				
			||||||
        </thead>
 | 
					 | 
				
			||||||
        <tbody class="divide-y divide-gray-200">
 | 
					 | 
				
			||||||
          {#each users as u}
 | 
					 | 
				
			||||||
            {#if Object.values(u)
 | 
					 | 
				
			||||||
              .toString()
 | 
					 | 
				
			||||||
              .toLowerCase()
 | 
					 | 
				
			||||||
              .includes(searchvalue)}
 | 
					 | 
				
			||||||
              <tr>
 | 
					 | 
				
			||||||
                <td class="px-6 py-4 whitespace-nowrap">
 | 
					 | 
				
			||||||
                  <div class="flex items-center">
 | 
					 | 
				
			||||||
                    {#if u.profilePic}
 | 
					 | 
				
			||||||
                      <div class="flex-shrink-0 h-10 w-10">
 | 
					 | 
				
			||||||
                        <img
 | 
					 | 
				
			||||||
                          class="h-10 w-10 rounded-full"
 | 
					 | 
				
			||||||
                          src={u.profilePic}
 | 
					 | 
				
			||||||
                          alt="" />
 | 
					 | 
				
			||||||
                      </div>
 | 
					 | 
				
			||||||
                    {/if}
 | 
					 | 
				
			||||||
                    <div class="ml-4">
 | 
					 | 
				
			||||||
                      <div
 | 
					 | 
				
			||||||
                        class="text-sm font-medium text-gray-900 dark:text-gray-100">
 | 
					 | 
				
			||||||
                        {u.firstname}
 | 
					 | 
				
			||||||
                        {u.middlename || ''}
 | 
					 | 
				
			||||||
                        {u.lastname}
 | 
					 | 
				
			||||||
                      </div>
 | 
					 | 
				
			||||||
                      <div class="text-sm text-gray-500">
 | 
					 | 
				
			||||||
                        {u.email || u.username}
 | 
					 | 
				
			||||||
                      </div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                  </div>
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
                <td class="px-6 py-4 whitespace-nowrap">
 | 
					 | 
				
			||||||
                  {#if u.enabled}
 | 
					 | 
				
			||||||
                    <span
 | 
					 | 
				
			||||||
                      class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">Active</span>
 | 
					 | 
				
			||||||
                  {:else}
 | 
					 | 
				
			||||||
                    <span
 | 
					 | 
				
			||||||
                      class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Inactive</span>
 | 
					 | 
				
			||||||
                  {/if}
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
 | 
					 | 
				
			||||||
                  {#each u.groups as g}
 | 
					 | 
				
			||||||
                    <a
 | 
					 | 
				
			||||||
                      href="../groups/{g.id}"
 | 
					 | 
				
			||||||
                      class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{g.name}</a>
 | 
					 | 
				
			||||||
                  {/each}
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
                <td
 | 
					 | 
				
			||||||
                  class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
 | 
					 | 
				
			||||||
                  <a
 | 
					 | 
				
			||||||
                    href="./{u.id}"
 | 
					 | 
				
			||||||
                    class="text-indigo-600 hover:text-indigo-900">Edit</a>
 | 
					 | 
				
			||||||
                  <span
 | 
					 | 
				
			||||||
                    tabindex="0"
 | 
					 | 
				
			||||||
                    href="#"
 | 
					 | 
				
			||||||
                    class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</span>
 | 
					 | 
				
			||||||
                </td>
 | 
					 | 
				
			||||||
              </tr>
 | 
					 | 
				
			||||||
            {/if}
 | 
					 | 
				
			||||||
          {/each}
 | 
					 | 
				
			||||||
        </tbody>
 | 
					 | 
				
			||||||
      </table>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  {/if}
 | 
					 | 
				
			||||||
{:catch error}
 | 
					 | 
				
			||||||
  <div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
 | 
					 | 
				
			||||||
    <span class="inline-block align-middle mr-8">
 | 
					 | 
				
			||||||
      <b class="capitalize">{$_('general_promise_error')}</b>
 | 
					 | 
				
			||||||
      {error}
 | 
					 | 
				
			||||||
    </span>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
{/await}
 | 
					 | 
				
			||||||
@@ -1,33 +1,22 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
  import { ApiError, AuthService } from "@odit/lfk-client-js";
 | 
					  import { AuthService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
  import Toastify from "toastify-js";
 | 
					 | 
				
			||||||
  import "toastify-js/src/toastify.css";
 | 
					 | 
				
			||||||
  import isEmail from "validator/es/lib/isEmail";
 | 
					  import isEmail from "validator/es/lib/isEmail";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let reset_mail_sent = false;
 | 
					  let reset_mail_sent = false;
 | 
				
			||||||
  let usersEmail = "";
 | 
					  let usersEmail = "";
 | 
				
			||||||
  function reset() {
 | 
					  function reset() {
 | 
				
			||||||
    if (isEmail(usersEmail)) {
 | 
					    if (isEmail(usersEmail)) {
 | 
				
			||||||
      AuthService.authControllerGetResetToken({ email: usersEmail })
 | 
					      toast.loading($_("mail-validation-in-progress"));
 | 
				
			||||||
 | 
					      AuthService.authControllerGetResetToken("de", { email: usersEmail })
 | 
				
			||||||
        .then((resp) => {
 | 
					        .then((resp) => {
 | 
				
			||||||
          console.log(resp);
 | 
					          toast.dismiss();
 | 
				
			||||||
          console.log(resp.resetToken);
 | 
					 | 
				
			||||||
          Toastify({
 | 
					 | 
				
			||||||
            text: $_("mail-validation-in-progress"),
 | 
					 | 
				
			||||||
            duration: 3500,
 | 
					 | 
				
			||||||
          }).showToast();
 | 
					 | 
				
			||||||
          reset_mail_sent = true;
 | 
					          reset_mail_sent = true;
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .catch((err) => {
 | 
					        .catch((err) => {});
 | 
				
			||||||
          console.log(err.body.name);
 | 
					 | 
				
			||||||
          console.log(err.body.message);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      Toastify({
 | 
					      toast($_("invalid-mail-reset"));
 | 
				
			||||||
        text: $_("invalid-mail-reset"),
 | 
					 | 
				
			||||||
        duration: 3500,
 | 
					 | 
				
			||||||
      }).showToast();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
@@ -37,19 +26,18 @@
 | 
				
			|||||||
    <div class="max-w-md w-full py-12 px-6">
 | 
					    <div class="max-w-md w-full py-12 px-6">
 | 
				
			||||||
      <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
					      <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
				
			||||||
      <p class="mt-6 text-lg text-center font-bold text-gray-900">
 | 
					      <p class="mt-6 text-lg text-center font-bold text-gray-900">
 | 
				
			||||||
        {$_('application_name')}
 | 
					        {$_("application_name")}
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <p class="mt-2 mb-2 text-sm text-center text-gray-900">
 | 
					      <p class="mt-2 mb-2 text-sm text-center text-gray-900">
 | 
				
			||||||
        Passwort-Reset Mail wurde an
 | 
					        {$_("password-reset-mail-sent", { values: { usersEmail: usersEmail } })}
 | 
				
			||||||
        {usersEmail}
 | 
					 | 
				
			||||||
        geschickt
 | 
					 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <div class="mt-6">
 | 
					      <div class="mt-6">
 | 
				
			||||||
        <div class="mt-6">
 | 
					        <div class="mt-6">
 | 
				
			||||||
          <a
 | 
					          <a
 | 
				
			||||||
            href="/"
 | 
					            href="/"
 | 
				
			||||||
            class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md text-gray-900 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm">
 | 
					            class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md text-gray-900 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
 | 
				
			||||||
            {$_('goback')}
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("goback")}
 | 
				
			||||||
          </a>
 | 
					          </a>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
@@ -60,25 +48,26 @@
 | 
				
			|||||||
    <div class="max-w-md w-full py-12 px-6">
 | 
					    <div class="max-w-md w-full py-12 px-6">
 | 
				
			||||||
      <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
					      <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
				
			||||||
      <p class="mt-6 text-lg text-center font-bold text-gray-900">
 | 
					      <p class="mt-6 text-lg text-center font-bold text-gray-900">
 | 
				
			||||||
        {$_('application_name')}
 | 
					        {$_("application_name")}
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <p class="mt-6 text-sm text-center text-gray-900">
 | 
					      <p class="mt-6 text-sm text-center text-gray-900">
 | 
				
			||||||
        {$_('forgot_password?')}
 | 
					        {$_("forgot_password")}
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <p class="mt-2 mb-2 text-sm text-center text-gray-900">
 | 
					      <p class="mt-2 mb-2 text-sm text-center text-gray-900">
 | 
				
			||||||
        {$_('dont-panic-were-resetting-it')}
 | 
					        {$_("dont-panic-were-resetting-it")}
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <div>
 | 
					      <div>
 | 
				
			||||||
        <div class="rounded-md shadow-sm">
 | 
					        <div class="rounded-md shadow-sm">
 | 
				
			||||||
          <div>
 | 
					          <div>
 | 
				
			||||||
            <input
 | 
					            <input
 | 
				
			||||||
              aria-label={$_('e-mail-adress')}
 | 
					              aria-label={$_("e-mail-adress")}
 | 
				
			||||||
              name="email"
 | 
					              name="email"
 | 
				
			||||||
              type="email"
 | 
					              type="email"
 | 
				
			||||||
              required=""
 | 
					              required=""
 | 
				
			||||||
              class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border text-gray-900 rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
 | 
					              class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border text-gray-900 rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
 | 
				
			||||||
              placeholder={$_('e-mail-adress')}
 | 
					              placeholder={$_("e-mail-adress")}
 | 
				
			||||||
              bind:value={usersEmail} />
 | 
					              bind:value={usersEmail}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -86,19 +75,22 @@
 | 
				
			|||||||
          <button
 | 
					          <button
 | 
				
			||||||
            on:click={reset}
 | 
					            on:click={reset}
 | 
				
			||||||
            type="submit"
 | 
					            type="submit"
 | 
				
			||||||
            class="relative block w-full py-2 px-3 border border-transparent rounded-md text-white font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm">
 | 
					            class="relative block w-full py-2 px-3 border border-transparent rounded-md text-white font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
            <span class="absolute left-0 inset-y pl-3">
 | 
					            <span class="absolute left-0 inset-y pl-3">
 | 
				
			||||||
              <svg
 | 
					              <svg
 | 
				
			||||||
                class="h-5 w-5 text-gray-500"
 | 
					                class="h-5 w-5 text-gray-500"
 | 
				
			||||||
                fill="currentColor"
 | 
					                fill="currentColor"
 | 
				
			||||||
                viewBox="0 0 20 20">
 | 
					                viewBox="0 0 20 20"
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
                <path
 | 
					                <path
 | 
				
			||||||
                  fill-rule="evenodd"
 | 
					                  fill-rule="evenodd"
 | 
				
			||||||
                  d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
 | 
					                  d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
 | 
				
			||||||
                  clip-rule="evenodd" />
 | 
					                  clip-rule="evenodd"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
              </svg>
 | 
					              </svg>
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
            {$_('reset-my-password')}
 | 
					            {$_("reset-my-password")}
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="mt-6">
 | 
					        <div class="mt-6">
 | 
				
			||||||
@@ -107,24 +99,30 @@
 | 
				
			|||||||
              <div class="w-full border-t border-gray-300" />
 | 
					              <div class="w-full border-t border-gray-300" />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="relative flex justify-center text-sm">
 | 
					            <div class="relative flex justify-center text-sm">
 | 
				
			||||||
              <span
 | 
					              <span class="px-2 bg-gray-100 text-gray-500"
 | 
				
			||||||
                class="px-2 bg-gray-100 text-gray-500">{$_('dont-have-your-email-connected')}</span>
 | 
					                >{$_("dont-have-your-email-connected")}</span
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <span
 | 
					          <span
 | 
				
			||||||
            class="mt-2 text-sm px-2 bg-gray-100 text-gray-500 justify-center relative flex">{$_('cannot-reset-your-password-directly')}</span>
 | 
					            class="mt-2 text-sm px-2 bg-gray-100 text-gray-500 justify-center relative flex"
 | 
				
			||||||
 | 
					            >{$_("cannot-reset-your-password-directly")}</span
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div class="mt-6">
 | 
					          <div class="mt-6">
 | 
				
			||||||
            <a
 | 
					            <a
 | 
				
			||||||
              href="mailto:lfk@odit.services"
 | 
					              href="mailto:lfk@odit.services"
 | 
				
			||||||
              class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md text-gray-900 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm">
 | 
					              class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md text-gray-900 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
 | 
				
			||||||
              {$_('send-a-mail-to-lfk-odit-services')}
 | 
					            >
 | 
				
			||||||
 | 
					              {$_("send-a-mail-to-lfk-odit-services")}
 | 
				
			||||||
            </a>
 | 
					            </a>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div class="mt-6">
 | 
					          <div class="mt-6">
 | 
				
			||||||
            <a
 | 
					            <a
 | 
				
			||||||
              href="/"
 | 
					              href="/"
 | 
				
			||||||
              class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md text-gray-900 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm">{$_('goback')}</a>
 | 
					              class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md text-gray-900 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
 | 
				
			||||||
 | 
					              >{$_("goback")}</a
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
@@ -1,14 +1,15 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
  import store from "../store.js";
 | 
					  import store from "../../store.js";
 | 
				
			||||||
  import localForage from "localforage";
 | 
					  import localForage from "localforage";
 | 
				
			||||||
  import { _ } from "svelte-i18n";
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
  store.init();
 | 
					  store.init();
 | 
				
			||||||
  import { OpenAPI, AuthService } from "@odit/lfk-client-js";
 | 
					  import { OpenAPI, AuthService } from "@odit/lfk-client-js";
 | 
				
			||||||
  import Footer from "./Footer.svelte";
 | 
					  import Footer from "../general/Footer.svelte";
 | 
				
			||||||
  import Toastify from "toastify-js";
 | 
					  import isEmail from "validator/es/lib/isEmail";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
  // ------
 | 
					  // ------
 | 
				
			||||||
  let username = "demo";
 | 
					  let username = config.default_username || "";
 | 
				
			||||||
  let password = "demo";
 | 
					  let password = config.default_password || "";
 | 
				
			||||||
  let is_blocked_by_autologin = false;
 | 
					  let is_blocked_by_autologin = false;
 | 
				
			||||||
  let last_loginclick_processed = true;
 | 
					  let last_loginclick_processed = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,11 +20,6 @@
 | 
				
			|||||||
        OpenAPI.TOKEN = value.access_token;
 | 
					        OpenAPI.TOKEN = value.access_token;
 | 
				
			||||||
        const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
 | 
					        const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
 | 
				
			||||||
        store.login(value, jwtinfo);
 | 
					        store.login(value, jwtinfo);
 | 
				
			||||||
        Toastify({
 | 
					 | 
				
			||||||
          text: $_("welcome_wavinghand"),
 | 
					 | 
				
			||||||
          duration: 500,
 | 
					 | 
				
			||||||
          backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
 | 
					 | 
				
			||||||
        }).showToast();
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
@@ -32,45 +28,38 @@
 | 
				
			|||||||
    // prevent login button spamming
 | 
					    // prevent login button spamming
 | 
				
			||||||
    if (last_loginclick_processed && is_blocked_by_autologin === false) {
 | 
					    if (last_loginclick_processed && is_blocked_by_autologin === false) {
 | 
				
			||||||
      last_loginclick_processed = false;
 | 
					      last_loginclick_processed = false;
 | 
				
			||||||
      Toastify({
 | 
					      toast.loading($_("login_is_checked"));
 | 
				
			||||||
        text: $_("login_is_checked"),
 | 
					      let postdata = {};
 | 
				
			||||||
        duration: 500,
 | 
					      if (isEmail(username)) {
 | 
				
			||||||
      }).showToast();
 | 
					        postdata = {
 | 
				
			||||||
      AuthService.authControllerLogin({
 | 
					          email: username,
 | 
				
			||||||
 | 
					          password,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        postdata = {
 | 
				
			||||||
          username,
 | 
					          username,
 | 
				
			||||||
          password,
 | 
					          password,
 | 
				
			||||||
      })
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      AuthService.authControllerLogin(postdata)
 | 
				
			||||||
        .then(async (result) => {
 | 
					        .then(async (result) => {
 | 
				
			||||||
          await localForage.setItem("logindata", result);
 | 
					          await localForage.setItem("logindata", result);
 | 
				
			||||||
          OpenAPI.TOKEN = result.access_token;
 | 
					          OpenAPI.TOKEN = result.access_token;
 | 
				
			||||||
          const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
 | 
					          const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
 | 
				
			||||||
          store.login(result.access_token, jwtinfo);
 | 
					          store.login(result.access_token, jwtinfo);
 | 
				
			||||||
          location.replace("/");
 | 
					          location.replace("/");
 | 
				
			||||||
          Toastify({
 | 
					          toast.dismiss();
 | 
				
			||||||
            text: $_("welcome_wavinghand"),
 | 
					 | 
				
			||||||
            duration: 500,
 | 
					 | 
				
			||||||
            backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
 | 
					 | 
				
			||||||
          }).showToast();
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .catch((err) => {
 | 
					        .catch((err) => {
 | 
				
			||||||
          Toastify({
 | 
					          toast.dismiss();
 | 
				
			||||||
            text: $_("error_on_login"),
 | 
					          toast.error($_("error_on_login"));
 | 
				
			||||||
            duration: 500,
 | 
					 | 
				
			||||||
            backgroundColor:
 | 
					 | 
				
			||||||
              "linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
 | 
					 | 
				
			||||||
          }).showToast();
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .finally(() => {
 | 
					        .finally(() => {
 | 
				
			||||||
          last_loginclick_processed = true;
 | 
					          last_loginclick_processed = true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      // last login was not processed yet
 | 
					      // last login was not processed yet
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      Toastify({
 | 
					      toast($_("please-wait-a-moment-your-login-is-still-being-processed"));
 | 
				
			||||||
        text: "chill...",
 | 
					 | 
				
			||||||
        duration: 1500,
 | 
					 | 
				
			||||||
        backgroundColor:
 | 
					 | 
				
			||||||
          "linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
 | 
					 | 
				
			||||||
      }).showToast();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  function handleKeydown(e) {
 | 
					  function handleKeydown(e) {
 | 
				
			||||||
@@ -81,34 +70,37 @@
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div
 | 
					<div
 | 
				
			||||||
  class="min-h-screen flex items-center justify-center bg-gray-100 text-gray-900">
 | 
					  class="min-h-screen flex items-center justify-center bg-gray-100 text-gray-900"
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
  <div class="max-w-md w-full py-12 px-6" role="main">
 | 
					  <div class="max-w-md w-full py-12 px-6" role="main">
 | 
				
			||||||
    <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
					    <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
				
			||||||
    <p class="mt-6 text-lg text-center font-bold">{$_('application_name')}</p>
 | 
					    <p class="mt-6 text-xl text-center font-bold">{$_("application_name")}</p>
 | 
				
			||||||
    <p class="mt-6 text-sm text-center">{$_('log_in_to_your_account')}</p>
 | 
					    <p class="mt-2 mb-6 text-sm text-center">{$_("log_in_to_your_account")}</p>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
      <div class="rounded-md shadow-sm">
 | 
					      <div class="rounded-md shadow-sm">
 | 
				
			||||||
        <div>
 | 
					        <div>
 | 
				
			||||||
          <!-- svelte-ignore a11y-autofocus -->
 | 
					          <!-- svelte-ignore a11y-autofocus -->
 | 
				
			||||||
          <input
 | 
					          <input
 | 
				
			||||||
            autofocus
 | 
					            autofocus
 | 
				
			||||||
            aria-label={$_('email_address_or_username')}
 | 
					            aria-label={$_("email_address_or_username")}
 | 
				
			||||||
            type="text"
 | 
					            type="text"
 | 
				
			||||||
            required=""
 | 
					            required=""
 | 
				
			||||||
            class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
 | 
					            class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
 | 
				
			||||||
            on:keydown={handleKeydown}
 | 
					            on:keydown={handleKeydown}
 | 
				
			||||||
            placeholder={$_('email_address_or_username')}
 | 
					            placeholder={$_("email_address_or_username")}
 | 
				
			||||||
            bind:value={username} />
 | 
					            bind:value={username}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="-mt-px relative">
 | 
					        <div class="-mt-px relative">
 | 
				
			||||||
          <input
 | 
					          <input
 | 
				
			||||||
            aria-label={$_('password')}
 | 
					            aria-label={$_("password")}
 | 
				
			||||||
            type="password"
 | 
					            type="password"
 | 
				
			||||||
            required=""
 | 
					            required=""
 | 
				
			||||||
            bind:value={password}
 | 
					            bind:value={password}
 | 
				
			||||||
            class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
 | 
					            class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
 | 
				
			||||||
            on:keydown={handleKeydown}
 | 
					            on:keydown={handleKeydown}
 | 
				
			||||||
            placeholder={$_('password')} />
 | 
					            placeholder={$_("password")}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -116,29 +108,33 @@
 | 
				
			|||||||
        <button
 | 
					        <button
 | 
				
			||||||
          on:click={login}
 | 
					          on:click={login}
 | 
				
			||||||
          type="submit"
 | 
					          type="submit"
 | 
				
			||||||
          class="relative block w-full py-2 px-3 border border-transparent rounded-md text-white font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm">
 | 
					          class="relative block w-full py-2 px-3 border border-transparent rounded-md text-white font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm"
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
          <span class="absolute left-0 inset-y pl-3">
 | 
					          <span class="absolute left-0 inset-y pl-3">
 | 
				
			||||||
            <svg
 | 
					            <svg
 | 
				
			||||||
              class="h-5 w-5 text-gray-500"
 | 
					              class="h-5 w-5 text-gray-500"
 | 
				
			||||||
              fill="currentColor"
 | 
					              fill="currentColor"
 | 
				
			||||||
              viewBox="0 0 20 20">
 | 
					              viewBox="0 0 20 20"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
              <path
 | 
					              <path
 | 
				
			||||||
                fill-rule="evenodd"
 | 
					                fill-rule="evenodd"
 | 
				
			||||||
                d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
 | 
					                d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
 | 
				
			||||||
                clip-rule="evenodd" />
 | 
					                clip-rule="evenodd"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
            </svg>
 | 
					            </svg>
 | 
				
			||||||
          </span>
 | 
					          </span>
 | 
				
			||||||
          {$_('log_in')}
 | 
					          {$_("log_in")}
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="mt-2">
 | 
					    <!-- <div class="mt-2">
 | 
				
			||||||
      <a
 | 
					      <a
 | 
				
			||||||
        href="/forgot_password"
 | 
					        href="/forgot_password"
 | 
				
			||||||
        class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm">
 | 
					        class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
 | 
				
			||||||
        {$_('forgot_password?')}
 | 
					      >
 | 
				
			||||||
 | 
					        {$_("forgot_password")}
 | 
				
			||||||
      </a>
 | 
					      </a>
 | 
				
			||||||
    </div>
 | 
					    </div> -->
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<Footer />
 | 
					<Footer />
 | 
				
			||||||
							
								
								
									
										52
									
								
								src/components/auth/PasswordStrength.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/components/auth/PasswordStrength.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					<script context="module">
 | 
				
			||||||
 | 
					  import { passwordStrength } from "check-password-strength";
 | 
				
			||||||
 | 
					  export function password_strong_enough(password_change) {
 | 
				
			||||||
 | 
					    let strength = passwordStrength(password_change);
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      strength?.contains.includes("lowercase") &&
 | 
				
			||||||
 | 
					      strength?.contains.includes("uppercase") &&
 | 
				
			||||||
 | 
					      strength?.contains.includes("number") &&
 | 
				
			||||||
 | 
					      strength?.length > 9
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  export function password_strong_enough_and_equal(
 | 
				
			||||||
 | 
					    password_change,
 | 
				
			||||||
 | 
					    password_confirm
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      password_strong_enough(password_change) &&
 | 
				
			||||||
 | 
					      password_change === password_confirm
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { getLocaleFromNavigator, _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { passwordStrength as Strength } from "check-password-strength";
 | 
				
			||||||
 | 
					  export let password_change;
 | 
				
			||||||
 | 
					  export let password_confirm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $: strength = Strength(password_change);
 | 
				
			||||||
 | 
					  $: passwords_match =
 | 
				
			||||||
 | 
					    !password_confirm || password_confirm === password_change;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="ml-4">
 | 
				
			||||||
 | 
					  <ul class="list-disc font-medium tracking-wide text-red-500 text-xs">
 | 
				
			||||||
 | 
					    {#if !strength.contains.includes("lowercase")}
 | 
				
			||||||
 | 
					      <li>{$_("must-contain-a-lowercase-letter")}</li>
 | 
				
			||||||
 | 
					    {/if}
 | 
				
			||||||
 | 
					    {#if !strength.contains.includes("uppercase")}
 | 
				
			||||||
 | 
					      <li>{$_("must-contain-a-uppercase-letter")}</li>
 | 
				
			||||||
 | 
					    {/if}
 | 
				
			||||||
 | 
					    {#if !strength.contains.includes("number")}
 | 
				
			||||||
 | 
					      <li>{$_("must-contain-a-number")}</li>
 | 
				
			||||||
 | 
					    {/if}
 | 
				
			||||||
 | 
					    {#if !(strength.length > 9)}
 | 
				
			||||||
 | 
					      <li>{$_("must-be-at-least-10-characters-long")}</li>
 | 
				
			||||||
 | 
					    {/if}
 | 
				
			||||||
 | 
					    {#if !(passwords_match == true)}
 | 
				
			||||||
 | 
					      <li>{$_("passwords-dont-match")}</li>
 | 
				
			||||||
 | 
					    {/if}
 | 
				
			||||||
 | 
					  </ul>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
							
								
								
									
										135
									
								
								src/components/auth/ResetPassword.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/components/auth/ResetPassword.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { AuthService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
					  import PasswordStrength, {
 | 
				
			||||||
 | 
					    password_strong_enough,
 | 
				
			||||||
 | 
					  } from "../auth/PasswordStrength.svelte";
 | 
				
			||||||
 | 
					  let state = "reset_in_progress";
 | 
				
			||||||
 | 
					  let password = "";
 | 
				
			||||||
 | 
					  export let params;
 | 
				
			||||||
 | 
					  function set_new_password() {
 | 
				
			||||||
 | 
					    if (password.trim() !== "") {
 | 
				
			||||||
 | 
					      toast.loading($_("password-reset-in-progress"));
 | 
				
			||||||
 | 
					      AuthService.authControllerResetPassword(atob(params.resetkey), {
 | 
				
			||||||
 | 
					        password,
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					        .then((resp) => {
 | 
				
			||||||
 | 
					          toast.dismiss();
 | 
				
			||||||
 | 
					          toast($_("password-reset-successful"));
 | 
				
			||||||
 | 
					          state = "reset_success";
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .catch((err) => {
 | 
				
			||||||
 | 
					          state = "reset_error";
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      toast.dismiss();
 | 
				
			||||||
 | 
					      toast.error($_("please-provide-a-password"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if state === "reset_success"}
 | 
				
			||||||
 | 
					  <div class="min-h-screen flex items-center justify-center bg-gray-100">
 | 
				
			||||||
 | 
					    <div class="max-w-md w-full py-12 px-6">
 | 
				
			||||||
 | 
					      <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
				
			||||||
 | 
					      <p class="mt-6 text-lg text-center font-bold text-gray-900">
 | 
				
			||||||
 | 
					        {$_("application_name")}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					      <p class="mt-2 mb-2 text-sm text-center text-gray-900 font-bold">
 | 
				
			||||||
 | 
					        {$_("successful-password-reset")}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					      <p class="mt-2 mb-2 text-sm text-center text-gray-900">
 | 
				
			||||||
 | 
					        {$_("you-can-now-use-your-new-password-to-log-in-to-your-account")}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					      <div class="mt-6">
 | 
				
			||||||
 | 
					        <div class="mt-6">
 | 
				
			||||||
 | 
					          <a
 | 
				
			||||||
 | 
					            href="/login/"
 | 
				
			||||||
 | 
					            class="text-center relative block w-full py-2 px-3 border border-transparent rounded-md text-white font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("go-to-login")}
 | 
				
			||||||
 | 
					          </a>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{:else if state === "reset_error"}
 | 
				
			||||||
 | 
					  <div class="min-h-screen flex items-center justify-center bg-gray-100">
 | 
				
			||||||
 | 
					    <div class="max-w-md w-full py-12 px-6">
 | 
				
			||||||
 | 
					      <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
				
			||||||
 | 
					      <p class="mt-6 text-lg text-center font-bold text-gray-900">
 | 
				
			||||||
 | 
					        {$_("application_name")}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					      <p class="mt-2 mb-2 text-sm text-center text-gray-900 font-bold">
 | 
				
			||||||
 | 
					        {$_("password-reset-failed")}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					      <p class="mt-2 mb-2 text-sm text-center text-gray-900">
 | 
				
			||||||
 | 
					        {$_("please-request-a-new-reset-mail")}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					      <div class="mt-6">
 | 
				
			||||||
 | 
					        <div class="mt-6">
 | 
				
			||||||
 | 
					          <a
 | 
				
			||||||
 | 
					            href="/forgot_password/"
 | 
				
			||||||
 | 
					            class="text-center relative block w-full py-2 px-3 border border-transparent rounded-md text-white font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("request-a-new-reset-mail")}
 | 
				
			||||||
 | 
					          </a>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{:else if state === "reset_in_progress"}
 | 
				
			||||||
 | 
					  <div class="min-h-screen flex items-center justify-center bg-gray-100">
 | 
				
			||||||
 | 
					    <div class="max-w-md w-full py-12 px-6">
 | 
				
			||||||
 | 
					      <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
 | 
				
			||||||
 | 
					      <p class="mt-6 text-lg text-center font-bold text-gray-900">
 | 
				
			||||||
 | 
					        {$_("application_name")}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					      <p class="mt-2 mb-4 text-md text-center text-gray-900">
 | 
				
			||||||
 | 
					        {$_("reset-password")}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <div class="rounded-md shadow-sm">
 | 
				
			||||||
 | 
					          <div>
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					              aria-label={$_("new-password")}
 | 
				
			||||||
 | 
					              name="password"
 | 
				
			||||||
 | 
					              type="password"
 | 
				
			||||||
 | 
					              required=""
 | 
				
			||||||
 | 
					              class="border-gray-300 placeholder-gray-500 appearance-none rounded-md relative block w-full px-3 py-2 border text-gray-900 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
 | 
				
			||||||
 | 
					              placeholder={$_("new-password")}
 | 
				
			||||||
 | 
					              bind:value={password}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <PasswordStrength bind:password_change={password} />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="mt-5">
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={set_new_password}
 | 
				
			||||||
 | 
					            disabled={!password_strong_enough(password)}
 | 
				
			||||||
 | 
					            class:opacity-50={!password_strong_enough(password)}
 | 
				
			||||||
 | 
					            type="submit"
 | 
				
			||||||
 | 
					            class="relative block w-full py-2 px-3 border border-transparent rounded-md text-white font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <span class="absolute left-0 inset-y pl-3">
 | 
				
			||||||
 | 
					              <svg
 | 
				
			||||||
 | 
					                class="h-5 w-5 text-gray-500"
 | 
				
			||||||
 | 
					                fill="currentColor"
 | 
				
			||||||
 | 
					                viewBox="0 0 20 20"
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                <path
 | 
				
			||||||
 | 
					                  fill-rule="evenodd"
 | 
				
			||||||
 | 
					                  d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
 | 
				
			||||||
 | 
					                  clip-rule="evenodd"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					              </svg>
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					            {$_("reset-my-password")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
@@ -4,19 +4,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<body class="antialiased font-sans">
 | 
					<body class="antialiased font-sans">
 | 
				
			||||||
  <div class="flex min-h-screen">
 | 
					  <div class="flex min-h-screen">
 | 
				
			||||||
    <div class="w-full bg-white flex items-center justify-center ">
 | 
					    <div class="w-full bg-white flex items-center justify-center">
 | 
				
			||||||
      <div class="max-w-sm m-8">
 | 
					      <div class="max-w-sm m-8">
 | 
				
			||||||
        <div class="text-black text-5xl md:text-15xl font-black">
 | 
					        <div class="text-black text-5xl md:text-15xl font-black">
 | 
				
			||||||
          Internal Error
 | 
					          {$_("internal-error")}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="w-16 h-1 bg-purple-light my-3 md:my-6" />
 | 
					        <div class="w-16 h-1 bg-purple-light my-3 md:my-6" />
 | 
				
			||||||
        <p
 | 
					        <p
 | 
				
			||||||
          class="text-grey-darker text-2xl md:text-3xl font-light mb-8 leading-normal">
 | 
					          class="text-grey-darker text-2xl md:text-3xl font-light mb-8 leading-normal"
 | 
				
			||||||
          Something went wrong in the UI logic
 | 
					        >
 | 
				
			||||||
 | 
					          {$_("generic-ui-logic-error")}
 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
        <a
 | 
					        <a
 | 
				
			||||||
          href="/"
 | 
					          href="/"
 | 
				
			||||||
          class="bg-transparent text-grey-darkest font-bold uppercase tracking-wide py-3 px-6 border-2 border-grey-light hover:border-grey rounded-lg">{$_('goback')}</a>
 | 
					          class="bg-transparent text-grey-darkest font-bold uppercase tracking-wide py-3 px-6 border-2 border-grey-light hover:border-grey rounded-lg"
 | 
				
			||||||
 | 
					          >{$_("goback")}</a
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
 | 
					<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
 | 
				
			||||||
  <span class="inline-block align-middle mr-8">
 | 
					  <span class="inline-block align-middle mr-8">
 | 
				
			||||||
    <b class="capitalize">{$_('general_promise_error')}</b>
 | 
					    <b>{$_("general_promise_error")}</b>
 | 
				
			||||||
    {error}
 | 
					    {error}
 | 
				
			||||||
  </span>
 | 
					  </span>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
							
								
								
									
										25
									
								
								src/components/base/datatable_i18n.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/components/base/datatable_i18n.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					export function getlang(langkeys) {
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    search: {
 | 
				
			||||||
 | 
					      placeholder: langkeys.search,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    sort: {
 | 
				
			||||||
 | 
					      sortAsc: langkeys.sort_column_ascending,
 | 
				
			||||||
 | 
					      sortDesc: langkeys.sort_column_descending,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    pagination: {
 | 
				
			||||||
 | 
					      previous: langkeys.previous,
 | 
				
			||||||
 | 
					      next: langkeys.next,
 | 
				
			||||||
 | 
					      navigate: (page, pages) =>
 | 
				
			||||||
 | 
					        `${langkeys.page} ${page} ${langkeys.of} ${pages}`,
 | 
				
			||||||
 | 
					      page: (page) => `${langkeys.page} ${page}`,
 | 
				
			||||||
 | 
					      showing: langkeys.showing,
 | 
				
			||||||
 | 
					      of: langkeys.of,
 | 
				
			||||||
 | 
					      to: langkeys.to,
 | 
				
			||||||
 | 
					      results: langkeys.records,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    loading: langkeys.loading,
 | 
				
			||||||
 | 
					    noRecordsFound: langkeys.no_matching_records_found,
 | 
				
			||||||
 | 
					    error: langkeys.an_error_happened_while_fetching_the_data,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								src/components/base/importfixes.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/components/base/importfixes.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<!--
 | 
				
			||||||
 | 
					    Temporary tailwind import fixes for classes that wouldn't be directly used otherwise. 
 | 
				
			||||||
 | 
					    Or as others may call it: Real big bullshit time.
 | 
				
			||||||
 | 
					    Issue: https://git.odit.services/lfk/frontend/issues/136
 | 
				
			||||||
 | 
					 -->
 | 
				
			||||||
 | 
					<div class="opacity-50" />
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/components/base/outsideclick.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/components/base/outsideclick.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/** Dispatch event on click outside of node */
 | 
				
			||||||
 | 
					export function clickOutside(node) {
 | 
				
			||||||
 | 
					  const handleClick = (event) => {
 | 
				
			||||||
 | 
					    if (event.target.getAttribute("data-id") === "modal_backdrop") {
 | 
				
			||||||
 | 
					      node.dispatchEvent(new CustomEvent("click_outside", node));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  document.removeEventListener("click", handleClick, true);
 | 
				
			||||||
 | 
					  document.addEventListener("click", handleClick, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										323
									
								
								src/components/base/simple.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								src/components/base/simple.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,323 @@
 | 
				
			|||||||
 | 
					.simplecontent * {
 | 
				
			||||||
 | 
					  margin: 0;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent address,
 | 
				
			||||||
 | 
					.simplecontent area,
 | 
				
			||||||
 | 
					.simplecontent article,
 | 
				
			||||||
 | 
					.simplecontent aside,
 | 
				
			||||||
 | 
					.simplecontent audio,
 | 
				
			||||||
 | 
					.simplecontent blockquote,
 | 
				
			||||||
 | 
					.simplecontent datalist,
 | 
				
			||||||
 | 
					.simplecontent details,
 | 
				
			||||||
 | 
					.simplecontent dl,
 | 
				
			||||||
 | 
					.simplecontent fieldset,
 | 
				
			||||||
 | 
					.simplecontent figure,
 | 
				
			||||||
 | 
					.simplecontent form,
 | 
				
			||||||
 | 
					.simplecontent iframe,
 | 
				
			||||||
 | 
					.simplecontent img,
 | 
				
			||||||
 | 
					.simplecontent input,
 | 
				
			||||||
 | 
					.simplecontent meter,
 | 
				
			||||||
 | 
					.simplecontent nav,
 | 
				
			||||||
 | 
					.simplecontent ol,
 | 
				
			||||||
 | 
					.simplecontent optgroup,
 | 
				
			||||||
 | 
					.simplecontent option,
 | 
				
			||||||
 | 
					.simplecontent output,
 | 
				
			||||||
 | 
					.simplecontent p,
 | 
				
			||||||
 | 
					.simplecontent pre,
 | 
				
			||||||
 | 
					.simplecontent progress,
 | 
				
			||||||
 | 
					.simplecontent ruby,
 | 
				
			||||||
 | 
					.simplecontent section,
 | 
				
			||||||
 | 
					.simplecontent table,
 | 
				
			||||||
 | 
					.simplecontent textarea,
 | 
				
			||||||
 | 
					.simplecontent ul,
 | 
				
			||||||
 | 
					.simplecontent video {
 | 
				
			||||||
 | 
					  margin-bottom: 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent button,
 | 
				
			||||||
 | 
					.simplecontent html,
 | 
				
			||||||
 | 
					.simplecontent input,
 | 
				
			||||||
 | 
					.simplecontent select {
 | 
				
			||||||
 | 
					  font-family: var(--nc-font-sans);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent body {
 | 
				
			||||||
 | 
					  margin: 0 auto;
 | 
				
			||||||
 | 
					  max-width: 750px;
 | 
				
			||||||
 | 
					  padding: 2rem;
 | 
				
			||||||
 | 
					  border-radius: 6px;
 | 
				
			||||||
 | 
					  overflow-x: hidden;
 | 
				
			||||||
 | 
					  word-break: break-word;
 | 
				
			||||||
 | 
					  overflow-wrap: break-word;
 | 
				
			||||||
 | 
					  background: var(--nc-bg-1);
 | 
				
			||||||
 | 
					  color: var(--nc-tx-2);
 | 
				
			||||||
 | 
					  font-size: 1.03rem;
 | 
				
			||||||
 | 
					  line-height: 1.5;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h1,
 | 
				
			||||||
 | 
					.simplecontent h2,
 | 
				
			||||||
 | 
					.simplecontent h3,
 | 
				
			||||||
 | 
					.simplecontent h4,
 | 
				
			||||||
 | 
					.simplecontent h5,
 | 
				
			||||||
 | 
					.simplecontent h6 {
 | 
				
			||||||
 | 
					  line-height: 1;
 | 
				
			||||||
 | 
					  color: var(--nc-tx-1);
 | 
				
			||||||
 | 
					  padding-top: 0.875rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h1,
 | 
				
			||||||
 | 
					.simplecontent h2,
 | 
				
			||||||
 | 
					.simplecontent h3 {
 | 
				
			||||||
 | 
					  color: var(--nc-tx-1);
 | 
				
			||||||
 | 
					  padding-bottom: 2px;
 | 
				
			||||||
 | 
					  margin-bottom: 8px;
 | 
				
			||||||
 | 
					  border-bottom: 1px solid var(--nc-bg-2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h4,
 | 
				
			||||||
 | 
					.simplecontent h5,
 | 
				
			||||||
 | 
					.simplecontent h6 {
 | 
				
			||||||
 | 
					  margin-bottom: 0.3rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h1 {
 | 
				
			||||||
 | 
					  font-size: 2.25rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h2 {
 | 
				
			||||||
 | 
					  font-size: 1.85rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h3 {
 | 
				
			||||||
 | 
					  font-size: 1.55rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h4 {
 | 
				
			||||||
 | 
					  font-size: 1.25rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h5 {
 | 
				
			||||||
 | 
					  font-size: 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent h6 {
 | 
				
			||||||
 | 
					  font-size: 0.875rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent a {
 | 
				
			||||||
 | 
					  color: #3d5af1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent a:hover {
 | 
				
			||||||
 | 
					  color: var(--nc-lk-2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent abbr:hover {
 | 
				
			||||||
 | 
					  cursor: help;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent blockquote {
 | 
				
			||||||
 | 
					  padding: 1.5rem;
 | 
				
			||||||
 | 
					  background: #ddd;
 | 
				
			||||||
 | 
					  border-left: 5px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent abbr {
 | 
				
			||||||
 | 
					  cursor: help;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent blockquote :last-child {
 | 
				
			||||||
 | 
					  padding-bottom: 0;
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent header {
 | 
				
			||||||
 | 
					  background: #ddd;
 | 
				
			||||||
 | 
					  border-bottom: 1px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					  padding: 2rem 1.5rem;
 | 
				
			||||||
 | 
					  margin: -2rem calc(0px - (50vw - 50%)) 2rem;
 | 
				
			||||||
 | 
					  padding-left: calc(50vw - 50%);
 | 
				
			||||||
 | 
					  padding-right: calc(50vw - 50%);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent header h1,
 | 
				
			||||||
 | 
					.simplecontent header h2,
 | 
				
			||||||
 | 
					.simplecontent header h3 {
 | 
				
			||||||
 | 
					  padding-bottom: 0;
 | 
				
			||||||
 | 
					  border-bottom: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent header > :first-child {
 | 
				
			||||||
 | 
					  margin-top: 0;
 | 
				
			||||||
 | 
					  padding-top: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent header > :last-child {
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent a button,
 | 
				
			||||||
 | 
					.simplecontent button,
 | 
				
			||||||
 | 
					.simplecontent input[type="button"],
 | 
				
			||||||
 | 
					.simplecontent input[type="reset"],
 | 
				
			||||||
 | 
					.simplecontent input[type="submit"] {
 | 
				
			||||||
 | 
					  font-size: 1rem;
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					  padding: 6px 12px;
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					  white-space: nowrap;
 | 
				
			||||||
 | 
					  background: #3d5af1;
 | 
				
			||||||
 | 
					  color: var(--nc-lk-tx);
 | 
				
			||||||
 | 
					  border: 0;
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  color: var(--nc-lk-tx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent a button[disabled],
 | 
				
			||||||
 | 
					.simplecontent button[disabled],
 | 
				
			||||||
 | 
					.simplecontent input[type="button"][disabled],
 | 
				
			||||||
 | 
					.simplecontent input[type="reset"][disabled],
 | 
				
			||||||
 | 
					.simplecontent input[type="submit"][disabled] {
 | 
				
			||||||
 | 
					  cursor: default;
 | 
				
			||||||
 | 
					  opacity: 0.5;
 | 
				
			||||||
 | 
					  cursor: not-allowed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent .button:focus,
 | 
				
			||||||
 | 
					.simplecontent .button:hover,
 | 
				
			||||||
 | 
					.simplecontent button:focus,
 | 
				
			||||||
 | 
					.simplecontent button:hover,
 | 
				
			||||||
 | 
					.simplecontent input[type="button"]:focus,
 | 
				
			||||||
 | 
					.simplecontent input[type="button"]:hover,
 | 
				
			||||||
 | 
					.simplecontent input[type="reset"]:focus,
 | 
				
			||||||
 | 
					.simplecontent input[type="reset"]:hover,
 | 
				
			||||||
 | 
					.simplecontent input[type="submit"]:focus,
 | 
				
			||||||
 | 
					.simplecontent input[type="submit"]:hover {
 | 
				
			||||||
 | 
					  background: var(--nc-lk-2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent code,
 | 
				
			||||||
 | 
					.simplecontent kbd,
 | 
				
			||||||
 | 
					.simplecontent pre,
 | 
				
			||||||
 | 
					.simplecontent samp {
 | 
				
			||||||
 | 
					  font-family: var(--nc-font-mono);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent code,
 | 
				
			||||||
 | 
					.simplecontent kbd,
 | 
				
			||||||
 | 
					.simplecontent pre,
 | 
				
			||||||
 | 
					.simplecontent samp {
 | 
				
			||||||
 | 
					  background: #ddd;
 | 
				
			||||||
 | 
					  border: 1px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
 | 
					  padding: 3px 6px;
 | 
				
			||||||
 | 
					  font-size: 0.9rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent kbd {
 | 
				
			||||||
 | 
					  border-bottom: 3px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent pre {
 | 
				
			||||||
 | 
					  padding: 1rem 1.4rem;
 | 
				
			||||||
 | 
					  max-width: 100%;
 | 
				
			||||||
 | 
					  overflow: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent pre code {
 | 
				
			||||||
 | 
					  background: inherit;
 | 
				
			||||||
 | 
					  font-size: inherit;
 | 
				
			||||||
 | 
					  color: inherit;
 | 
				
			||||||
 | 
					  border: 0;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					  margin: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent code pre {
 | 
				
			||||||
 | 
					  display: inline;
 | 
				
			||||||
 | 
					  background: inherit;
 | 
				
			||||||
 | 
					  font-size: inherit;
 | 
				
			||||||
 | 
					  color: inherit;
 | 
				
			||||||
 | 
					  border: 0;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					  margin: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent details {
 | 
				
			||||||
 | 
					  padding: 0.6rem 1rem;
 | 
				
			||||||
 | 
					  background: #ddd;
 | 
				
			||||||
 | 
					  border: 1px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent summary {
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent details[open] {
 | 
				
			||||||
 | 
					  padding-bottom: 0.75rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent details[open] summary {
 | 
				
			||||||
 | 
					  margin-bottom: 6px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent details[open] > :last-child {
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent dt {
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent dd::before {
 | 
				
			||||||
 | 
					  content: "→ ";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent hr {
 | 
				
			||||||
 | 
					  border: 0;
 | 
				
			||||||
 | 
					  border-bottom: 1px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					  margin: 1rem auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent fieldset {
 | 
				
			||||||
 | 
					  margin-top: 1rem;
 | 
				
			||||||
 | 
					  padding: 2rem;
 | 
				
			||||||
 | 
					  border: 1px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent legend {
 | 
				
			||||||
 | 
					  padding: auto 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent table {
 | 
				
			||||||
 | 
					  border-collapse: collapse;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent td,
 | 
				
			||||||
 | 
					.simplecontent th {
 | 
				
			||||||
 | 
					  border: 1px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					  text-align: left;
 | 
				
			||||||
 | 
					  padding: 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent th {
 | 
				
			||||||
 | 
					  background: #ddd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent tr:nth-child(even) {
 | 
				
			||||||
 | 
					  background: #ddd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent table caption {
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					  margin-bottom: 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent textarea {
 | 
				
			||||||
 | 
					  max-width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent ol,
 | 
				
			||||||
 | 
					.simplecontent ul {
 | 
				
			||||||
 | 
					  padding-left: 2rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent li {
 | 
				
			||||||
 | 
					  margin-top: 0.4rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent ol ol,
 | 
				
			||||||
 | 
					.simplecontent ol ul,
 | 
				
			||||||
 | 
					.simplecontent ul ol,
 | 
				
			||||||
 | 
					.simplecontent ul ul {
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent mark {
 | 
				
			||||||
 | 
					  padding: 3px 6px;
 | 
				
			||||||
 | 
					  background: var(--nc-ac-1);
 | 
				
			||||||
 | 
					  color: var(--nc-ac-tx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent input,
 | 
				
			||||||
 | 
					.simplecontent select,
 | 
				
			||||||
 | 
					.simplecontent textarea {
 | 
				
			||||||
 | 
					  padding: 6px 12px;
 | 
				
			||||||
 | 
					  margin-bottom: 0.5rem;
 | 
				
			||||||
 | 
					  background: #ddd;
 | 
				
			||||||
 | 
					  color: var(--nc-tx-2);
 | 
				
			||||||
 | 
					  border: 1px solid var(--nc-bg-3);
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
 | 
					  box-shadow: none;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent img {
 | 
				
			||||||
 | 
					  max-width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent blockquote {
 | 
				
			||||||
 | 
					  background: #ececec;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent ol {
 | 
				
			||||||
 | 
					  list-style-type: decimal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.simplecontent ul {
 | 
				
			||||||
 | 
					  list-style-type: circle;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										218
									
								
								src/components/cards/AddCardBulkModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								src/components/cards/AddCardBulkModal.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,218 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { clickOutside } from "../base/outsideclick";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  import { RunnerCardService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
					  import { createEventDispatcher } from "svelte";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
					  import DocumentServer from "../pdf_generation/DocumentServer";
 | 
				
			||||||
 | 
					  export let bulk_modal_open;
 | 
				
			||||||
 | 
					  const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					  const documentServer = new DocumentServer(config.baseurl_documentserver,config.documentserver_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $: card_count = 0;
 | 
				
			||||||
 | 
					  $: is_card_count_valid = card_count > 0;
 | 
				
			||||||
 | 
					  $: processed_last_submit = true;
 | 
				
			||||||
 | 
					  $: createbtnenabled = is_card_count_valid;
 | 
				
			||||||
 | 
					  (() => {
 | 
				
			||||||
 | 
					    document.onkeydown = (e) => {
 | 
				
			||||||
 | 
					      e = e || window.event;
 | 
				
			||||||
 | 
					      if (e.key === "Escape") {
 | 
				
			||||||
 | 
					        bulk_modal_open = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (e.keyCode === 13) {
 | 
				
			||||||
 | 
					        if (createbtnenabled === true) {
 | 
				
			||||||
 | 
					          createbtnenabled = false;
 | 
				
			||||||
 | 
					          submit_with_print();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					  function submit_without_print() {
 | 
				
			||||||
 | 
					    if (processed_last_submit === true) {
 | 
				
			||||||
 | 
					      processed_last_submit = false;
 | 
				
			||||||
 | 
					      toast.loading($_("creating-blanco-cards"));
 | 
				
			||||||
 | 
					      RunnerCardService.runnerCardControllerPostBlancoBulk(card_count, true)
 | 
				
			||||||
 | 
					        .then((result) => {
 | 
				
			||||||
 | 
					          bulk_modal_open = false;
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					          toast.dismiss();
 | 
				
			||||||
 | 
					          toast.success($_("created-blanco-cards"));
 | 
				
			||||||
 | 
					          dispatch("created", { cards: result });
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .catch((err) => {
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .finally(() => {
 | 
				
			||||||
 | 
					          processed_last_submit = true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function submit_with_print() {
 | 
				
			||||||
 | 
					    if (processed_last_submit === true) {
 | 
				
			||||||
 | 
					      processed_last_submit = false;
 | 
				
			||||||
 | 
					      toast.dismiss();
 | 
				
			||||||
 | 
					      toast.loading($_("creating-blanco-cards"));
 | 
				
			||||||
 | 
					      RunnerCardService.runnerCardControllerPostBlancoBulk(card_count, true)
 | 
				
			||||||
 | 
					        .then((result) => {
 | 
				
			||||||
 | 
					          bulk_modal_open = false;
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					          toast.dismiss();
 | 
				
			||||||
 | 
					          toast.success($_("created-blanco-cards"));
 | 
				
			||||||
 | 
					          toast.loading($_("generating-pdf"));
 | 
				
			||||||
 | 
					          dispatch("created", { cards: result });
 | 
				
			||||||
 | 
					          documentServer.generateCards(result, "de")
 | 
				
			||||||
 | 
					            .then((blob) => {
 | 
				
			||||||
 | 
					              const url = window.URL.createObjectURL(blob);
 | 
				
			||||||
 | 
					              let a = document.createElement("a");
 | 
				
			||||||
 | 
					              a.href = url;
 | 
				
			||||||
 | 
					              a.download = "Bulkcards.pdf";
 | 
				
			||||||
 | 
					              document.body.appendChild(a);
 | 
				
			||||||
 | 
					              a.click();
 | 
				
			||||||
 | 
					              a.remove();
 | 
				
			||||||
 | 
					              toast.dismiss();
 | 
				
			||||||
 | 
					              toast.success($_("pdf-successfully-generated"));
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch((err) => {
 | 
				
			||||||
 | 
					              console.error(err);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .catch((err) => {
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .finally(() => {
 | 
				
			||||||
 | 
					          processed_last_submit = true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if bulk_modal_open}
 | 
				
			||||||
 | 
					  <div
 | 
				
			||||||
 | 
					    class="fixed z-10 inset-0 overflow-y-hidden"
 | 
				
			||||||
 | 
					    use:clickOutside
 | 
				
			||||||
 | 
					    on:click_outside={() => {
 | 
				
			||||||
 | 
					      bulk_modal_open = false;
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      class="flex items-end justify-center h-screen text-center sm:block p-0 lg:p-4"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          class="absolute inset-0 bg-gray-500 opacity-75"
 | 
				
			||||||
 | 
					          data-id="modal_backdrop"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <span
 | 
				
			||||||
 | 
					        class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
				
			||||||
 | 
					        aria-hidden="true">​</span
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full relative z-10"
 | 
				
			||||||
 | 
					        role="dialog"
 | 
				
			||||||
 | 
					        aria-modal="true"
 | 
				
			||||||
 | 
					        aria-labelledby="modal-headline"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 rounded-t-xl">
 | 
				
			||||||
 | 
					          <div class="">
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <svg
 | 
				
			||||||
 | 
					                class="size-6 text-blue-600"
 | 
				
			||||||
 | 
					                fill="currentColor"
 | 
				
			||||||
 | 
					                xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					                viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                width="24"
 | 
				
			||||||
 | 
					                height="24"
 | 
				
			||||||
 | 
					                ><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
					                <path
 | 
				
			||||||
 | 
					                  fill="currentColor"
 | 
				
			||||||
 | 
					                  d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
 | 
				
			||||||
 | 
					                /></svg
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="mt-3 sm:mt-0">
 | 
				
			||||||
 | 
					              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					                {$_("create-bulk-blanco-cards")}
 | 
				
			||||||
 | 
					              </h3>
 | 
				
			||||||
 | 
					              <div class="mb-6">
 | 
				
			||||||
 | 
					                <p class="text-sm text-gray-500">
 | 
				
			||||||
 | 
					                  {$_(
 | 
				
			||||||
 | 
					                    "just-enter-how-many-you-want-and-the-system-will-create-them"
 | 
				
			||||||
 | 
					                  )}
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div class="grid grid-cols-6 gap-2 lg:gap-6 text-left">
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="amount"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("amount")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <div class="mt-1 flex rounded-md shadow-sm">
 | 
				
			||||||
 | 
					                    <input
 | 
				
			||||||
 | 
					                      autocomplete="off"
 | 
				
			||||||
 | 
					                      class:border-red-500={!is_card_count_valid}
 | 
				
			||||||
 | 
					                      class:focus:border-red-500={!is_card_count_valid}
 | 
				
			||||||
 | 
					                      class:focus:ring-red-500={!is_card_count_valid}
 | 
				
			||||||
 | 
					                      bind:value={card_count}
 | 
				
			||||||
 | 
					                      type="number"
 | 
				
			||||||
 | 
					                      step="1"
 | 
				
			||||||
 | 
					                      name="amount"
 | 
				
			||||||
 | 
					                      class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
 | 
				
			||||||
 | 
					                      placeholder="400"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                      class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
 | 
				
			||||||
 | 
					                      >{$_("cards")}</span
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  {#if !is_card_count_valid}
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                      class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {$_("you-must-create-at-least-one-card-or-cancel")}
 | 
				
			||||||
 | 
					                    </span>
 | 
				
			||||||
 | 
					                  {/if}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="bg-gray-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10">
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            disabled={!createbtnenabled}
 | 
				
			||||||
 | 
					            class:opacity-50={!createbtnenabled}
 | 
				
			||||||
 | 
					            on:click={submit_with_print}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("create-and-generate-pdf")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            disabled={!createbtnenabled}
 | 
				
			||||||
 | 
					            class:opacity-50={!createbtnenabled}
 | 
				
			||||||
 | 
					            on:click={submit_without_print}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white hover:bg-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("create-without-pdf")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={() => {
 | 
				
			||||||
 | 
					              bulk_modal_open = false;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="mr-auto w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("cancel")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										191
									
								
								src/components/cards/AddCardModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								src/components/cards/AddCardModal.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { clickOutside } from "../base/outsideclick";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  import { RunnerCardService, RunnerService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
					  import Select from "svelte-select";
 | 
				
			||||||
 | 
					  import { createEventDispatcher } from "svelte";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
					  export let modal_open;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					  const getRunnerLabel = (option) => {
 | 
				
			||||||
 | 
					    if (option.middlename) {
 | 
				
			||||||
 | 
					      return option.firstname + " " + option.middlename + " " + option.lastname;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return option.firstname + " " + option.lastname;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const filterRunners = (label, filterText, option) => {
 | 
				
			||||||
 | 
					    if (filterText.startsWith("#")) {
 | 
				
			||||||
 | 
					      return option.value.id == parseInt(filterText.replace("#", ""));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      label.toLowerCase().includes(filterText.toLowerCase()) ||
 | 
				
			||||||
 | 
					      option.value.toString().startsWith(filterText.toLowerCase())
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  function focus(el) {
 | 
				
			||||||
 | 
					    el.focus();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  $: runner = 0;
 | 
				
			||||||
 | 
					  $: enabled = true;
 | 
				
			||||||
 | 
					  $: processed_last_submit = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let loading = true;
 | 
				
			||||||
 | 
					  let runners = [];
 | 
				
			||||||
 | 
					  RunnerService.runnerControllerGetAll().then((val) => {
 | 
				
			||||||
 | 
					    runners = val.map((r) => {
 | 
				
			||||||
 | 
					      return { label: getRunnerLabel(r), value: r };
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    loading = false;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  $: createbtnenabled = true;
 | 
				
			||||||
 | 
					  (() => {
 | 
				
			||||||
 | 
					    document.onkeydown = (e) => {
 | 
				
			||||||
 | 
					      e = e || window.event;
 | 
				
			||||||
 | 
					      if (e.key === "Escape") {
 | 
				
			||||||
 | 
					        modal_open = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (e.keyCode === 13) {
 | 
				
			||||||
 | 
					        if (createbtnenabled === true) {
 | 
				
			||||||
 | 
					          createbtnenabled = false;
 | 
				
			||||||
 | 
					          submit();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					  function submit() {
 | 
				
			||||||
 | 
					    if (processed_last_submit === true) {
 | 
				
			||||||
 | 
					      processed_last_submit = false;
 | 
				
			||||||
 | 
					      toast.loading($_("adding-card"));
 | 
				
			||||||
 | 
					      let postdata = {
 | 
				
			||||||
 | 
					        runner,
 | 
				
			||||||
 | 
					        enabled,
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      RunnerCardService.runnerCardControllerPost(postdata)
 | 
				
			||||||
 | 
					        .then((result) => {
 | 
				
			||||||
 | 
					          runner = 0;
 | 
				
			||||||
 | 
					          modal_open = false;
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					          toast.dismiss();
 | 
				
			||||||
 | 
					          toast.success($_("card-added"));
 | 
				
			||||||
 | 
					          dispatch("created", { cards: [result] });
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .catch((err) => {
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .finally(() => {
 | 
				
			||||||
 | 
					          processed_last_submit = true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if modal_open}
 | 
				
			||||||
 | 
					  <div
 | 
				
			||||||
 | 
					    class="fixed z-10 inset-0 overflow-y-hidden"
 | 
				
			||||||
 | 
					    use:clickOutside
 | 
				
			||||||
 | 
					    on:click_outside={() => {
 | 
				
			||||||
 | 
					      modal_open = false;
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      class="flex items-end justify-center h-screen text-center sm:block p-0 lg:p-4"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          class="absolute inset-0 bg-gray-500 opacity-75"
 | 
				
			||||||
 | 
					          data-id="modal_backdrop"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <span
 | 
				
			||||||
 | 
					        class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
				
			||||||
 | 
					        aria-hidden="true">​</span
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        class="inline-block align-bottom text-left shadow-xl transform transition-all sm:align-middle w-full lg:w-auto min-w-auto lg:min-w-[35vw] relative z-10"
 | 
				
			||||||
 | 
					        role="dialog"
 | 
				
			||||||
 | 
					        aria-modal="true"
 | 
				
			||||||
 | 
					        aria-labelledby="modal-headline"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 rounded-t-xl">
 | 
				
			||||||
 | 
					          <div class="">
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <svg
 | 
				
			||||||
 | 
					                class="size-6 text-blue-600"
 | 
				
			||||||
 | 
					                fill="currentColor"
 | 
				
			||||||
 | 
					                xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					                viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                width="24"
 | 
				
			||||||
 | 
					                height="24"
 | 
				
			||||||
 | 
					                ><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
					                <path
 | 
				
			||||||
 | 
					                  fill="currentColor"
 | 
				
			||||||
 | 
					                  d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
 | 
				
			||||||
 | 
					                /></svg
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="mt-3 sm:mt-0">
 | 
				
			||||||
 | 
					              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					                {$_("create-a-new-card")}
 | 
				
			||||||
 | 
					              </h3>
 | 
				
			||||||
 | 
					              <div class="mb-6">
 | 
				
			||||||
 | 
					                <p class="text-sm text-gray-500">
 | 
				
			||||||
 | 
					                  {$_("you-can-provide-a-runner-but-you-dont-have-to")}
 | 
				
			||||||
 | 
					                  {$_(
 | 
				
			||||||
 | 
					                    "if-you-want-to-create-multiple-blanco-cards-try-the-add-bulk-button"
 | 
				
			||||||
 | 
					                  )}
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div class="grid grid-cols-6 gap-2 lg:gap-6 text-left">
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="donor"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("runner")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <Select
 | 
				
			||||||
 | 
					                    containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                    itemFilter={(label, filterText, option) =>
 | 
				
			||||||
 | 
					                      filterRunners(label, filterText, option)}
 | 
				
			||||||
 | 
					                    items={runners}
 | 
				
			||||||
 | 
					                    bind:loading
 | 
				
			||||||
 | 
					                    showChevron={!loading}
 | 
				
			||||||
 | 
					                    placeholder={$_("search-for-runner-by-name-or-id")}
 | 
				
			||||||
 | 
					                    noOptionsMessage={$_("no-runners-found")}
 | 
				
			||||||
 | 
					                    on:select={(selectedValue) =>
 | 
				
			||||||
 | 
					                      (runner = selectedValue.detail.value.id)}
 | 
				
			||||||
 | 
					                    on:clear={() => (runner = null)}
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="bg-gray-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10">
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            disabled={!createbtnenabled}
 | 
				
			||||||
 | 
					            class:opacity-50={!createbtnenabled}
 | 
				
			||||||
 | 
					            on:click={submit}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("create")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={() => {
 | 
				
			||||||
 | 
					              modal_open = false;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            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"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("cancel")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										200
									
								
								src/components/cards/CardDetailModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								src/components/cards/CardDetailModal.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,200 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { clickOutside } from "../base/outsideclick";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  import { RunnerCardService, RunnerService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
					  import Select from "svelte-select";
 | 
				
			||||||
 | 
					  import { createEventDispatcher } from "svelte";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
					  export let edit_modal_open;
 | 
				
			||||||
 | 
					  export let runner = {};
 | 
				
			||||||
 | 
					  export let editable = {};
 | 
				
			||||||
 | 
					  export let original_data = {};
 | 
				
			||||||
 | 
					  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 (
 | 
				
			||||||
 | 
					      label.toLowerCase().includes(filterText.toLowerCase()) ||
 | 
				
			||||||
 | 
					      option.value.toString().startsWith(filterText.toLowerCase())
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function focus(el) {
 | 
				
			||||||
 | 
					    el.focus();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  $: runners = [];
 | 
				
			||||||
 | 
					  $: enabled = true;
 | 
				
			||||||
 | 
					  $: processed_last_submit = true;
 | 
				
			||||||
 | 
					  const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					  RunnerService.runnerControllerGetAll().then((val) => {
 | 
				
			||||||
 | 
					    runners = val.map((r) => {
 | 
				
			||||||
 | 
					      return { label: getRunnerLabel(r), value: r };
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  $: createbtnenabled = !(
 | 
				
			||||||
 | 
					    JSON.stringify(editable) === JSON.stringify(original_data)
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  (() => {
 | 
				
			||||||
 | 
					    document.onkeydown = (e) => {
 | 
				
			||||||
 | 
					      e = e || window.event;
 | 
				
			||||||
 | 
					      if (e.key === "Escape") {
 | 
				
			||||||
 | 
					        edit_modal_open = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (e.keyCode === 13) {
 | 
				
			||||||
 | 
					        if (createbtnenabled === true) {
 | 
				
			||||||
 | 
					          createbtnenabled = false;
 | 
				
			||||||
 | 
					          submit();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					  function submit() {
 | 
				
			||||||
 | 
					    if (processed_last_submit === true) {
 | 
				
			||||||
 | 
					      processed_last_submit = false;
 | 
				
			||||||
 | 
					      toast.loading($_("updating-card"));
 | 
				
			||||||
 | 
					      RunnerCardService.runnerCardControllerPut(original_data.id, editable)
 | 
				
			||||||
 | 
					        .then((result) => {
 | 
				
			||||||
 | 
					          runner = {};
 | 
				
			||||||
 | 
					          editable = {};
 | 
				
			||||||
 | 
					          original_data = {};
 | 
				
			||||||
 | 
					          edit_modal_open = false;
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					          toast.dismiss();
 | 
				
			||||||
 | 
					          toast.success($_("card-updated"));
 | 
				
			||||||
 | 
					          dispatch("dataUpdated", { card: result });
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .catch((err) => {
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .finally(() => {
 | 
				
			||||||
 | 
					          processed_last_submit = true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if edit_modal_open}
 | 
				
			||||||
 | 
					  <div
 | 
				
			||||||
 | 
					    class="fixed z-10 inset-0 overflow-y-hidden"
 | 
				
			||||||
 | 
					    use:clickOutside
 | 
				
			||||||
 | 
					    on:click_outside={() => {
 | 
				
			||||||
 | 
					      edit_modal_open = false;
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      class="flex items-end justify-center h-screen text-center sm:block p-0 lg:p-4"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          class="absolute inset-0 bg-gray-500 opacity-75"
 | 
				
			||||||
 | 
					          data-id="modal_backdrop"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <span
 | 
				
			||||||
 | 
					        class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
				
			||||||
 | 
					        aria-hidden="true">​</span
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        class="inline-block align-bottom text-left shadow-xl transform transition-all sm:align-middle w-full lg:w-auto min-w-auto lg:min-w-[35vw] relative z-10"
 | 
				
			||||||
 | 
					        role="dialog"
 | 
				
			||||||
 | 
					        aria-modal="true"
 | 
				
			||||||
 | 
					        aria-labelledby="modal-headline"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 rounded-t-xl">
 | 
				
			||||||
 | 
					          <div class="">
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <svg
 | 
				
			||||||
 | 
					                class="size-6 text-blue-600"
 | 
				
			||||||
 | 
					                fill="currentColor"
 | 
				
			||||||
 | 
					                xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					                viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                width="24"
 | 
				
			||||||
 | 
					                height="24"
 | 
				
			||||||
 | 
					                ><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
					                <path
 | 
				
			||||||
 | 
					                  fill="currentColor"
 | 
				
			||||||
 | 
					                  d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
 | 
				
			||||||
 | 
					                /></svg
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="mt-3 sm:text-left max-h-[75vh] overflow-y-auto">
 | 
				
			||||||
 | 
					              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					                {$_("edit-a-card")}
 | 
				
			||||||
 | 
					              </h3>
 | 
				
			||||||
 | 
					              <div class="mb-6">
 | 
				
			||||||
 | 
					                <p class="text-sm text-gray-500">
 | 
				
			||||||
 | 
					                  {$_("you-can-provide-a-runner-but-you-dont-have-to")}
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div class="grid grid-cols-6 gap-2 lg:gap-6 text-left">
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="runner"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("runner")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <Select
 | 
				
			||||||
 | 
					                    containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                    itemFilter={(label, filterText, option) =>
 | 
				
			||||||
 | 
					                      filterRunners(label, filterText, option)}
 | 
				
			||||||
 | 
					                    items={runners}
 | 
				
			||||||
 | 
					                    showChevron={true}
 | 
				
			||||||
 | 
					                    placeholder={$_("search-for-runner-by-name-or-id")}
 | 
				
			||||||
 | 
					                    noOptionsMessage={$_("no-runners-found")}
 | 
				
			||||||
 | 
					                    bind:selectedValue={runner}
 | 
				
			||||||
 | 
					                    on:select={(selectedValue) =>
 | 
				
			||||||
 | 
					                      (editable.runner = selectedValue.detail.value.id)}
 | 
				
			||||||
 | 
					                    on:clear={() => (editable.runner = null)}
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <p class="text-gray-500">
 | 
				
			||||||
 | 
					                    <input
 | 
				
			||||||
 | 
					                      id="enabled"
 | 
				
			||||||
 | 
					                      on:change={() => {
 | 
				
			||||||
 | 
					                        editable.enabled = !editable.enabled;
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
 | 
					                      name="enabled"
 | 
				
			||||||
 | 
					                      type="checkbox"
 | 
				
			||||||
 | 
					                      checked={editable.enabled}
 | 
				
			||||||
 | 
					                      class="focus:ring-indigo-500 size-4 text-indigo-600 border-gray-300 rounded"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    {$_("this-card-is")}
 | 
				
			||||||
 | 
					                    {#if editable.enabled}
 | 
				
			||||||
 | 
					                      {$_("enabled")}
 | 
				
			||||||
 | 
					                    {:else}{$_("disabled")}{/if}
 | 
				
			||||||
 | 
					                  </p>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="bg-gray-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10">
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            disabled={!createbtnenabled}
 | 
				
			||||||
 | 
					            class:opacity-50={!createbtnenabled}
 | 
				
			||||||
 | 
					            on:click={submit}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("save-changes")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={() => {
 | 
				
			||||||
 | 
					              edit_modal_open = false;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            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"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("cancel")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/components/cards/CardRunner.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/components/cards/CardRunner.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  export let runner;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if !runner}
 | 
				
			||||||
 | 
					  {$_("non-blanko")}
 | 
				
			||||||
 | 
					{:else}
 | 
				
			||||||
 | 
					  <a class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-blue-100 text-blue-800" href={`/runners/${runner.id}`}>
 | 
				
			||||||
 | 
					    {#if runner.middlename}
 | 
				
			||||||
 | 
					      {runner.firstname} {runner.middlename} {runner.lastname}
 | 
				
			||||||
 | 
					    {:else}
 | 
				
			||||||
 | 
					      {runner.firstname} {runner.lastname}
 | 
				
			||||||
 | 
					    {/if}
 | 
				
			||||||
 | 
					  </a>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/components/cards/CardStatus.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/components/cards/CardStatus.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  export let enabled = false;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if enabled}
 | 
				
			||||||
 | 
					  <span
 | 
				
			||||||
 | 
					    class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
 | 
				
			||||||
 | 
					    >{$_("enabled")}</span
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					{:else}
 | 
				
			||||||
 | 
					  <span
 | 
				
			||||||
 | 
					    class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-red-100 text-red-800"
 | 
				
			||||||
 | 
					    >{$_("disabled")}</span
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										53
									
								
								src/components/cards/Cards.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/components/cards/Cards.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import store from "../../store";
 | 
				
			||||||
 | 
					  import AddCardBulkModal from "./AddCardBulkModal.svelte";
 | 
				
			||||||
 | 
					  import AddCardModal from "./AddCardModal.svelte";
 | 
				
			||||||
 | 
					  import CardsOverview from "./CardsOverview.svelte";
 | 
				
			||||||
 | 
					  $: current_cards = [];
 | 
				
			||||||
 | 
					  export let modal_open = false;
 | 
				
			||||||
 | 
					  export let bulk_modal_open = false;
 | 
				
			||||||
 | 
					  let addCards;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section class="container p-5">
 | 
				
			||||||
 | 
					  <h4 class="mb-1 text-3xl font-extrabold leading-tight">
 | 
				
			||||||
 | 
					    {$_("cards")}
 | 
				
			||||||
 | 
					  </h4>
 | 
				
			||||||
 | 
					  {#if store.state.jwtinfo.userdetails.permissions.includes("CARD:CREATE")}
 | 
				
			||||||
 | 
					    <button
 | 
				
			||||||
 | 
					      on:click={() => {
 | 
				
			||||||
 | 
					        modal_open = true;
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      type="button"
 | 
				
			||||||
 | 
					      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm  mb-1 lg:mb-0"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {$_("add-card")}
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					    <button
 | 
				
			||||||
 | 
					      on:click={() => {
 | 
				
			||||||
 | 
					        bulk_modal_open = true;
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      type="button"
 | 
				
			||||||
 | 
					      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm  mb-1 lg:mb-0"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {$_("create-bulk-cards")}
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  {/if}
 | 
				
			||||||
 | 
					  <CardsOverview bind:current_cards bind:addCards />
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:CREATE")}
 | 
				
			||||||
 | 
					  <AddCardModal
 | 
				
			||||||
 | 
					    bind:modal_open
 | 
				
			||||||
 | 
					    on:created={(event) => {
 | 
				
			||||||
 | 
					      addCards(event.detail.cards);
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  />
 | 
				
			||||||
 | 
					  <AddCardBulkModal
 | 
				
			||||||
 | 
					    bind:bulk_modal_open
 | 
				
			||||||
 | 
					    on:created={(event) => {
 | 
				
			||||||
 | 
					      addCards(event.detail.cards);
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  />
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/components/cards/CardsEmptyState.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/components/cards/CardsEmptyState.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import cards_empty from "./cards.svg";
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="text-center items-center justify-center">
 | 
				
			||||||
 | 
					  <p class="mb-16 text-lg text-gray-500">
 | 
				
			||||||
 | 
					    <img class="m-auto mt-2" style="height:15rem" src={cards_empty} alt="" />
 | 
				
			||||||
 | 
					    <span class="font-bold">{$_("there-are-no-cards-yet")}</span><br />
 | 
				
			||||||
 | 
					    <span>{$_("add-your-first-card")}</span>
 | 
				
			||||||
 | 
					  </p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
							
								
								
									
										314
									
								
								src/components/cards/CardsOverview.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								src/components/cards/CardsOverview.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,314 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { RunnerCardService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
					  import store from "../../store";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
					  import CardsEmptyState from "./CardsEmptyState.svelte";
 | 
				
			||||||
 | 
					  import CardDetailModal from "./CardDetailModal.svelte";
 | 
				
			||||||
 | 
					  import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
 | 
				
			||||||
 | 
					  import InputElement from "../shared/InputElement.svelte";
 | 
				
			||||||
 | 
					  import {
 | 
				
			||||||
 | 
					    createSvelteTable,
 | 
				
			||||||
 | 
					    flexRender,
 | 
				
			||||||
 | 
					    getCoreRowModel,
 | 
				
			||||||
 | 
					    getFilteredRowModel,
 | 
				
			||||||
 | 
					    getPaginationRowModel,
 | 
				
			||||||
 | 
					    getSortedRowModel,
 | 
				
			||||||
 | 
					    renderComponent,
 | 
				
			||||||
 | 
					  } from "@tanstack/svelte-table";
 | 
				
			||||||
 | 
					  import { writable } from "svelte/store";
 | 
				
			||||||
 | 
					  import TableBottom from "../shared/TableBottom.svelte";
 | 
				
			||||||
 | 
					  import TableActions from "../shared/TableActions.svelte";
 | 
				
			||||||
 | 
					  import TableHeader from "../shared/TableHeader.svelte";
 | 
				
			||||||
 | 
					  import CardStatus from "./CardStatus.svelte";
 | 
				
			||||||
 | 
					  import CardRunner from "./CardRunner.svelte";
 | 
				
			||||||
 | 
					  import { onMount } from "svelte";
 | 
				
			||||||
 | 
					  import { runnerFilter, statusFilter } from "../shared/tablefilters";
 | 
				
			||||||
 | 
					  import DeleteCardModal from "./DeleteCardModal.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export let edit_modal_open = false;
 | 
				
			||||||
 | 
					  export let runner = {};
 | 
				
			||||||
 | 
					  export let editable = {};
 | 
				
			||||||
 | 
					  export let original_data = {};
 | 
				
			||||||
 | 
					  export let current_cards = [];
 | 
				
			||||||
 | 
					  export const addCards = (cards) => {
 | 
				
			||||||
 | 
					    current_cards = current_cards.concat(...cards);
 | 
				
			||||||
 | 
					    options.update((options) => ({
 | 
				
			||||||
 | 
					      ...options,
 | 
				
			||||||
 | 
					      data: current_cards,
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $: dataLoaded = false;
 | 
				
			||||||
 | 
					  $: selected =
 | 
				
			||||||
 | 
					    $table?.getSelectedRowModel().rows.map((row) => row.index) || [];
 | 
				
			||||||
 | 
					  $: selectedCards =
 | 
				
			||||||
 | 
					    $table?.getSelectedRowModel().rows.map((row) => row.original) || [];
 | 
				
			||||||
 | 
					  $: active_delete = undefined;
 | 
				
			||||||
 | 
					  $: cards_show = generate_cards.length > 0;
 | 
				
			||||||
 | 
					  $: generate_cards = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const columns = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      accessorKey: "code",
 | 
				
			||||||
 | 
					      header: () => $_("code"),
 | 
				
			||||||
 | 
					      filterFn: `includesString`,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      accessorKey: "runner",
 | 
				
			||||||
 | 
					      header: () => $_("runner"),
 | 
				
			||||||
 | 
					      cell: (info) => {
 | 
				
			||||||
 | 
					        return renderComponent(CardRunner, { runner: info.getValue() });
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      filterFn: `runner`,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      accessorKey: "enabled",
 | 
				
			||||||
 | 
					      cell: (info) => {
 | 
				
			||||||
 | 
					        return renderComponent(CardStatus, { enabled: info.getValue() });
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      header: () => $_("status"),
 | 
				
			||||||
 | 
					      filterFn: `status`,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      accessorKey: "actions",
 | 
				
			||||||
 | 
					      header: () => $_("action"),
 | 
				
			||||||
 | 
					      cell: (info) => {
 | 
				
			||||||
 | 
					        return renderComponent(TableActions, {
 | 
				
			||||||
 | 
					          detailsAction: () => {
 | 
				
			||||||
 | 
					            open_edit_modal(
 | 
				
			||||||
 | 
					              current_cards[
 | 
				
			||||||
 | 
					                current_cards.findIndex((r) => r.id == info.row.original.id)
 | 
				
			||||||
 | 
					              ]
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          deleteAction: () => {
 | 
				
			||||||
 | 
					            active_delete =
 | 
				
			||||||
 | 
					              current_cards[
 | 
				
			||||||
 | 
					                current_cards.findIndex((r) => r.id == info.row.original.id)
 | 
				
			||||||
 | 
					              ];
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          deleteEnabled:
 | 
				
			||||||
 | 
					            store.state.jwtinfo.userdetails.permissions.includes("CARD:DELETE"),
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      enableColumnFilter: false,
 | 
				
			||||||
 | 
					      enableSorting: false,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const options = writable({
 | 
				
			||||||
 | 
					    data: [],
 | 
				
			||||||
 | 
					    columns: columns,
 | 
				
			||||||
 | 
					    initialState: {
 | 
				
			||||||
 | 
					      pagination: {
 | 
				
			||||||
 | 
					        pageSize: 50,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    filterFns: {
 | 
				
			||||||
 | 
					      runner: runnerFilter,
 | 
				
			||||||
 | 
					      status: statusFilter,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    enableRowSelection: true,
 | 
				
			||||||
 | 
					    getCoreRowModel: getCoreRowModel(),
 | 
				
			||||||
 | 
					    getFilteredRowModel: getFilteredRowModel(),
 | 
				
			||||||
 | 
					    getPaginationRowModel: getPaginationRowModel(),
 | 
				
			||||||
 | 
					    getSortedRowModel: getSortedRowModel(),
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const table = createSvelteTable(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function open_edit_modal(card) {
 | 
				
			||||||
 | 
					    const getRunnerLabel = (option) =>
 | 
				
			||||||
 | 
					      option.firstname +
 | 
				
			||||||
 | 
					      " " +
 | 
				
			||||||
 | 
					      (option.middlename || "") +
 | 
				
			||||||
 | 
					      " " +
 | 
				
			||||||
 | 
					      option.lastname;
 | 
				
			||||||
 | 
					    if (card.runner?.id) {
 | 
				
			||||||
 | 
					      runner = Object.assign(
 | 
				
			||||||
 | 
					        { runner },
 | 
				
			||||||
 | 
					        { label: getRunnerLabel(card.runner), value: card.runner }
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      card.runner = card.runner.id;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      card.runner = null;
 | 
				
			||||||
 | 
					      runner = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    editable = Object.assign(editable, card);
 | 
				
			||||||
 | 
					    original_data = Object.assign(original_data, card);
 | 
				
			||||||
 | 
					    edit_modal_open = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async function deleteCard(delete_card_id) {
 | 
				
			||||||
 | 
					    await RunnerCardService.runnerCardControllerRemove(delete_card_id, true);
 | 
				
			||||||
 | 
					    current_cards = current_cards.filter((r) => r.id !== delete_card_id);
 | 
				
			||||||
 | 
					    options.update((options) => ({
 | 
				
			||||||
 | 
					      ...options,
 | 
				
			||||||
 | 
					      data: current_cards,
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					    toast.success($_("card-deleted"));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMount(async () => {
 | 
				
			||||||
 | 
					    let page = 0;
 | 
				
			||||||
 | 
					    let pagesize = 500;
 | 
				
			||||||
 | 
					    while (page >= 0) {
 | 
				
			||||||
 | 
					      const cards = await RunnerCardService.runnerCardControllerGetAll(
 | 
				
			||||||
 | 
					        page,
 | 
				
			||||||
 | 
					        pagesize
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      if (cards.length == 0) {
 | 
				
			||||||
 | 
					        page = -2;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      current_cards = current_cards.concat(...cards);
 | 
				
			||||||
 | 
					      options.update((options) => ({
 | 
				
			||||||
 | 
					        ...options,
 | 
				
			||||||
 | 
					        data: current_cards,
 | 
				
			||||||
 | 
					      }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      dataLoaded = true;
 | 
				
			||||||
 | 
					      page++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:UPDATE")}
 | 
				
			||||||
 | 
					  <CardDetailModal
 | 
				
			||||||
 | 
					    bind:edit_modal_open
 | 
				
			||||||
 | 
					    bind:runner
 | 
				
			||||||
 | 
					    bind:editable
 | 
				
			||||||
 | 
					    bind:original_data
 | 
				
			||||||
 | 
					    on:dataUpdated={(editevent) => {
 | 
				
			||||||
 | 
					      console.log(editevent.detail.card)
 | 
				
			||||||
 | 
					      current_cards = current_cards.filter((c) => c.id !== editevent.detail.card.id).concat([editevent.detail.card]).sort((a, b) => a.code - b.code);
 | 
				
			||||||
 | 
					      options.update((options) => ({
 | 
				
			||||||
 | 
					        ...options,
 | 
				
			||||||
 | 
					        data: current_cards,
 | 
				
			||||||
 | 
					      }));
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  />
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
 | 
				
			||||||
 | 
					  <DeleteCardModal
 | 
				
			||||||
 | 
					    delete_card={active_delete}
 | 
				
			||||||
 | 
					    modal_open={active_delete != undefined}
 | 
				
			||||||
 | 
					    on:delete={(event) => {
 | 
				
			||||||
 | 
					      deleteCard(event.detail.id);
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  />
 | 
				
			||||||
 | 
					  {#if !dataLoaded}
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
 | 
				
			||||||
 | 
					      role="alert"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <p class="font-bold">{$_("loading-cards")}</p>
 | 
				
			||||||
 | 
					      <p class="text-sm">{$_("this-might-take-a-moment")}</p>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  {:else if current_cards.length === 0}
 | 
				
			||||||
 | 
					    <CardsEmptyState />
 | 
				
			||||||
 | 
					  {:else}
 | 
				
			||||||
 | 
					    <div class="h-12 mt-1">
 | 
				
			||||||
 | 
					      {#if selected.length > 0}
 | 
				
			||||||
 | 
					        <button
 | 
				
			||||||
 | 
					          type="button"
 | 
				
			||||||
 | 
					          class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm inline-flex"
 | 
				
			||||||
 | 
					          id="options-menu"
 | 
				
			||||||
 | 
					          on:click={async () => {
 | 
				
			||||||
 | 
					            const prom = [];
 | 
				
			||||||
 | 
					            for (const card of selectedCards) {
 | 
				
			||||||
 | 
					              prom.push(
 | 
				
			||||||
 | 
					                await RunnerCardService.runnerCardControllerRemove(
 | 
				
			||||||
 | 
					                  card.id,
 | 
				
			||||||
 | 
					                  true
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            await Promise.all(prom);
 | 
				
			||||||
 | 
					            for (const card of selectedCards) {
 | 
				
			||||||
 | 
					              current_cards = current_cards.filter((r) => r.id !== card.id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            options.update((options) => ({
 | 
				
			||||||
 | 
					              ...options,
 | 
				
			||||||
 | 
					              data: current_cards,
 | 
				
			||||||
 | 
					            }));
 | 
				
			||||||
 | 
					            $table.resetRowSelection();
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          {$_("delete-cards")}
 | 
				
			||||||
 | 
					          <svg
 | 
				
			||||||
 | 
					            xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					            fill="none"
 | 
				
			||||||
 | 
					            viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					            stroke-width="1.5"
 | 
				
			||||||
 | 
					            stroke="currentColor"
 | 
				
			||||||
 | 
					            class="w-5 h-5"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <path
 | 
				
			||||||
 | 
					              stroke-linecap="round"
 | 
				
			||||||
 | 
					              stroke-linejoin="round"
 | 
				
			||||||
 | 
					              d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </svg>
 | 
				
			||||||
 | 
					        </button>
 | 
				
			||||||
 | 
					      {/if}
 | 
				
			||||||
 | 
					      <GenerateRunnerCards
 | 
				
			||||||
 | 
					        cards_show={selected.length > 0}
 | 
				
			||||||
 | 
					        bind:generate_cards={selectedCards}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="overflow-x-auto">
 | 
				
			||||||
 | 
					      <table class="w-full">
 | 
				
			||||||
 | 
					        <thead class="border-b border-gray-400">
 | 
				
			||||||
 | 
					          {#each $table.getHeaderGroups() as headerGroup}
 | 
				
			||||||
 | 
					            <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}
 | 
				
			||||||
 | 
					                <TableHeader {header} />
 | 
				
			||||||
 | 
					              {/each}
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					          {/each}
 | 
				
			||||||
 | 
					        </thead>
 | 
				
			||||||
 | 
					        <tbody>
 | 
				
			||||||
 | 
					          {#each $table.getRowModel().rows as row}
 | 
				
			||||||
 | 
					            <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}
 | 
				
			||||||
 | 
					                <td>
 | 
				
			||||||
 | 
					                  <svelte:component
 | 
				
			||||||
 | 
					                    this={flexRender(
 | 
				
			||||||
 | 
					                      cell.column.columnDef.cell,
 | 
				
			||||||
 | 
					                      cell.getContext()
 | 
				
			||||||
 | 
					                    )}
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                </td>
 | 
				
			||||||
 | 
					              {/each}
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					          {/each}
 | 
				
			||||||
 | 
					        </tbody>
 | 
				
			||||||
 | 
					      </table>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <TableBottom {table} {selected} />
 | 
				
			||||||
 | 
					  {/if}
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
					  table tbody tr td:nth-child(2) {
 | 
				
			||||||
 | 
					    font-family: monospace;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										123
									
								
								src/components/cards/DeleteCardModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								src/components/cards/DeleteCardModal.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { clickOutside } from "../base/outsideclick";
 | 
				
			||||||
 | 
					  import { createEventDispatcher, onMount } from "svelte";
 | 
				
			||||||
 | 
					  export let modal_open;
 | 
				
			||||||
 | 
					  export let delete_card = {
 | 
				
			||||||
 | 
					    id: 0,
 | 
				
			||||||
 | 
					    code: "",
 | 
				
			||||||
 | 
					    runner: {
 | 
				
			||||||
 | 
					      firstname: "",
 | 
				
			||||||
 | 
					      lastname: "",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					  onMount(() => {
 | 
				
			||||||
 | 
					    document.onkeydown = (e) => {
 | 
				
			||||||
 | 
					      e = e || window.event;
 | 
				
			||||||
 | 
					      if (e.key === "Escape") {
 | 
				
			||||||
 | 
					        modal_open = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (e.keyCode === 13) {
 | 
				
			||||||
 | 
					        if (createbtnenabled === true) {
 | 
				
			||||||
 | 
					          createbtnenabled = false;
 | 
				
			||||||
 | 
					          submit();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  async function submit() {
 | 
				
			||||||
 | 
					    dispatch("delete", { id: delete_card.id });
 | 
				
			||||||
 | 
					    modal_open = false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if modal_open}
 | 
				
			||||||
 | 
					  <div
 | 
				
			||||||
 | 
					    class="fixed z-10 inset-0 overflow-y-hidden"
 | 
				
			||||||
 | 
					    use:clickOutside
 | 
				
			||||||
 | 
					    on:click_outside={() => {
 | 
				
			||||||
 | 
					      modal_open = false;
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      class="flex items-end justify-center h-screen text-center sm:block p-0 lg:p-4"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          class="absolute inset-0 bg-gray-500 opacity-75"
 | 
				
			||||||
 | 
					          data-id="modal_backdrop"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <span
 | 
				
			||||||
 | 
					        class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
				
			||||||
 | 
					        aria-hidden="true">​</span
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        class="inline-block align-bottom text-left shadow-xl transform transition-all sm:align-middle w-full lg:w-auto min-w-auto lg:min-w-[35vw] relative z-10"
 | 
				
			||||||
 | 
					        role="dialog"
 | 
				
			||||||
 | 
					        aria-modal="true"
 | 
				
			||||||
 | 
					        aria-labelledby="modal-headline"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 rounded-t-xl">
 | 
				
			||||||
 | 
					          <div class="">
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <svg
 | 
				
			||||||
 | 
					                class="size-6 text-blue-600"
 | 
				
			||||||
 | 
					                fill="currentColor"
 | 
				
			||||||
 | 
					                xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					                viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                width="24"
 | 
				
			||||||
 | 
					                height="24"
 | 
				
			||||||
 | 
					                ><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
					                <path
 | 
				
			||||||
 | 
					                  fill="currentColor"
 | 
				
			||||||
 | 
					                  d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
 | 
				
			||||||
 | 
					                /></svg
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="mt-3 sm:text-left max-h-[75vh] overflow-y-auto">
 | 
				
			||||||
 | 
					              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					                {$_("please-confirm-the-deletion-of-card")}
 | 
				
			||||||
 | 
					              </h3>
 | 
				
			||||||
 | 
					              <div class="w-full">
 | 
				
			||||||
 | 
					                {$_("card")} #{delete_card.code}<br />
 | 
				
			||||||
 | 
					                <span class="inline-block">
 | 
				
			||||||
 | 
					                  {$_("runner")}:
 | 
				
			||||||
 | 
					                  {#if delete_card.runner}
 | 
				
			||||||
 | 
					                    <span class="inline-block"
 | 
				
			||||||
 | 
					                      >{delete_card.runner.firstname}
 | 
				
			||||||
 | 
					                      {delete_card.runner.lastname}</span
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                  {:else}
 | 
				
			||||||
 | 
					                    {$_("non-blanko")}
 | 
				
			||||||
 | 
					                  {/if}</span
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="bg-gray-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10">
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={submit}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-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"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("delete")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={() => {
 | 
				
			||||||
 | 
					              modal_open = false;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            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"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("cancel")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										1
									
								
								src/components/cards/cards.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/components/cards/cards.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 653.9 247.6"><path d="M272 211l-53 12s-11-2-1-17l4-4 27-14v-2l-6-41-2-16 17-17 4-3 44 41v1l-19 33z" fill="#ffb7b7"/><path d="M253 198l-54 13a6 6 0 01-5-7 16 16 0 012-5 48 48 0 016-9l28-14-4-24-1-12-2-8-2-16 21-19 22 21 22 20-3 5-3 7-17 30-3 6z" fill="#ffb7b7"/><path d="M346 190s-20-1-28-15a24 24 0 01-3-14l-8-17-11-23-30-4-2 1-21 19-7 6-10 9-49 44a37 37 0 01-7 9 50 50 0 01-9 7c-10 5-24 9-44 7L10 248 0 176l89-29 131-86 89 23 41 58z" fill="#ffb7b7"/><path d="M648 0H275a5 5 0 00-5 5v221a5 5 0 005 6h373a5 5 0 006-6V5a5 5 0 00-6-5z" fill="#fff"/><path d="M648 0H275a5 5 0 00-5 5v221a5 5 0 005 6h373a5 5 0 006-6V5a5 5 0 00-6-5zm4 226a4 4 0 01-4 4H275a4 4 0 01-3-4V5a4 4 0 013-3h373a4 4 0 014 3z" fill="#3f3d56"/><path d="M312 30a9 9 0 119-9 9 9 0 01-9 9zm0-17a8 8 0 107 8 8 8 0 00-7-8z" fill="#6c63ff"/><path d="M297 21a8 8 0 016-8 8 8 0 100 16 8 8 0 01-6-8zM349 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM368 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM386 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM415 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM434 130a7 7 0 01-7-7v-20a7 7 0 0113 0v20a7 7 0 01-6 7zM452 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM481 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM499 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM518 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM546 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM565 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7zM583 130a7 7 0 01-7-7v-20a7 7 0 0114 0v20a7 7 0 01-7 7z" fill="#6c63ff"/><path d="M396 208h-99a5 5 0 110-10h99a5 5 0 010 10zM364 188h-35a5 5 0 110-10h35a5 5 0 110 10z" fill="#e6e6e6"/><path fill="#3f3d56" d="M271 46h381v2H271z"/><path opacity=".1" d="M228 203l-1-2 33-15 8-27-12-10 1-1 13 10-8 30-34 15zM196 199l-9 4-17 2a50 50 0 01-9 7l-16-1-26-1 88-74 18 4-29 59z"/><path d="M318 175l-8 1-47 4-29 1-38 18-9 4-70 8 95-81 11 2 20 5 22 5 18 1 24 1 20 1a13 13 0 0112 13c0 7-5 14-21 17z" fill="#ffb7b7"/><path d="M325 170s-7-2-9-9c-2-4-1-9 3-15l1 1c-3 6-4 10-3 14 2 5 9 7 9 7zM197 197l34-16v2l-33 16zM218 135l48-19v2l-41 16 35 6v2l-42-7z" opacity=".1"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 2.1 KiB  | 
							
								
								
									
										480
									
								
								src/components/contacts/AddContactModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										480
									
								
								src/components/contacts/AddContactModal.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,480 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { clickOutside } from "../base/outsideclick";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  import {
 | 
				
			||||||
 | 
					    GroupContactService,
 | 
				
			||||||
 | 
					    RunnerTeamService,
 | 
				
			||||||
 | 
					    RunnerOrganizationService,
 | 
				
			||||||
 | 
					  } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
					  import isEmail from "validator/es/lib/isEmail";
 | 
				
			||||||
 | 
					  import isMobilePhone from "validator/es/lib/isMobilePhone";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
					  export let modal_open;
 | 
				
			||||||
 | 
					  export let current_contacts;
 | 
				
			||||||
 | 
					  $: selected_team = [];
 | 
				
			||||||
 | 
					  let firstname_input;
 | 
				
			||||||
 | 
					  let lastname_input;
 | 
				
			||||||
 | 
					  let middlename_input;
 | 
				
			||||||
 | 
					  let phone_input;
 | 
				
			||||||
 | 
					  let email_input;
 | 
				
			||||||
 | 
					  let address_input1;
 | 
				
			||||||
 | 
					  let address_input2;
 | 
				
			||||||
 | 
					  let address_zipcode;
 | 
				
			||||||
 | 
					  let address_city;
 | 
				
			||||||
 | 
					  let teams = [];
 | 
				
			||||||
 | 
					  let orgs = [];
 | 
				
			||||||
 | 
					  RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
 | 
				
			||||||
 | 
					    teams = val;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
 | 
				
			||||||
 | 
					    orgs = val;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  function focus(el) {
 | 
				
			||||||
 | 
					    el.focus();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  $: middlename_input_value = "";
 | 
				
			||||||
 | 
					  $: phone_input_value = "";
 | 
				
			||||||
 | 
					  $: email_input_value = "";
 | 
				
			||||||
 | 
					  $: lastname_input_value = "";
 | 
				
			||||||
 | 
					  $: firstname_input_value = "";
 | 
				
			||||||
 | 
					  $: address_input1_value = "";
 | 
				
			||||||
 | 
					  $: address_input2_value = "";
 | 
				
			||||||
 | 
					  $: address_zipcode_value = "";
 | 
				
			||||||
 | 
					  $: address_city_value = "";
 | 
				
			||||||
 | 
					  $: processed_last_submit = true;
 | 
				
			||||||
 | 
					  $: address_checked = false;
 | 
				
			||||||
 | 
					  $: isPhoneValidOrEmpty =
 | 
				
			||||||
 | 
					    (phone_input_value.includes("+") &&
 | 
				
			||||||
 | 
					      isMobilePhone(
 | 
				
			||||||
 | 
					        phone_input_value
 | 
				
			||||||
 | 
					          .replaceAll("(", "")
 | 
				
			||||||
 | 
					          .replaceAll(")", "")
 | 
				
			||||||
 | 
					          .replaceAll("-", "")
 | 
				
			||||||
 | 
					          .replaceAll(" ", "")
 | 
				
			||||||
 | 
					      )) ||
 | 
				
			||||||
 | 
					    phone_input_value === "";
 | 
				
			||||||
 | 
					  $: isEmailValidOrEmpty =
 | 
				
			||||||
 | 
					    isEmail(email_input_value) || email_input_value === "";
 | 
				
			||||||
 | 
					  $: isLastnameValid = lastname_input_value.trim().length !== 0;
 | 
				
			||||||
 | 
					  $: isFirstnameValid = firstname_input_value.trim().length !== 0;
 | 
				
			||||||
 | 
					  $: isAddress1Valid = address_input1_value.trim().length !== 0;
 | 
				
			||||||
 | 
					  $: iszipcodevalid = address_zipcode_value.trim().length !== 0;
 | 
				
			||||||
 | 
					  $: iscityvalid = address_city_value.trim().length !== 0;
 | 
				
			||||||
 | 
					  $: createbtnenabled =
 | 
				
			||||||
 | 
					    isFirstnameValid &&
 | 
				
			||||||
 | 
					    isLastnameValid &&
 | 
				
			||||||
 | 
					    isEmailValidOrEmpty &&
 | 
				
			||||||
 | 
					    isPhoneValidOrEmpty &&
 | 
				
			||||||
 | 
					    ((isAddress1Valid && iszipcodevalid && iscityvalid) ||
 | 
				
			||||||
 | 
					      address_checked === false);
 | 
				
			||||||
 | 
					  (() => {
 | 
				
			||||||
 | 
					    document.onkeydown = (e) => {
 | 
				
			||||||
 | 
					      e = e || window.event;
 | 
				
			||||||
 | 
					      if (e.key === "Escape") {
 | 
				
			||||||
 | 
					        modal_open = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (e.keyCode === 13) {
 | 
				
			||||||
 | 
					        if (createbtnenabled === true) {
 | 
				
			||||||
 | 
					          createbtnenabled = false;
 | 
				
			||||||
 | 
					          submit();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					  function submit() {
 | 
				
			||||||
 | 
					    if (processed_last_submit === true) {
 | 
				
			||||||
 | 
					      processed_last_submit = false;
 | 
				
			||||||
 | 
					      toast.loading($_("contact-is-being-added"));
 | 
				
			||||||
 | 
					      let address = {};
 | 
				
			||||||
 | 
					      if (address_checked === true) {
 | 
				
			||||||
 | 
					        address = {
 | 
				
			||||||
 | 
					          address1: address_input1_value,
 | 
				
			||||||
 | 
					          address2: address_input2_value || "",
 | 
				
			||||||
 | 
					          postalcode: address_zipcode_value,
 | 
				
			||||||
 | 
					          city: address_city_value,
 | 
				
			||||||
 | 
					          country: "DE",
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      let postdata = {
 | 
				
			||||||
 | 
					        groups: selected_team,
 | 
				
			||||||
 | 
					        firstname: firstname_input_value,
 | 
				
			||||||
 | 
					        lastname: lastname_input_value,
 | 
				
			||||||
 | 
					        address,
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      if (middlename_input_value) {
 | 
				
			||||||
 | 
					        postdata.middlename = middlename_input_value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (phone_input_value) {
 | 
				
			||||||
 | 
					        postdata.phone = phone_input_value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (email_input_value) {
 | 
				
			||||||
 | 
					        postdata.email = email_input_value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      GroupContactService.groupContactControllerPost(postdata)
 | 
				
			||||||
 | 
					        .then((result) => {
 | 
				
			||||||
 | 
					          firstname_input_value = "";
 | 
				
			||||||
 | 
					          lastname_input_value = "";
 | 
				
			||||||
 | 
					          middlename_input_value = "";
 | 
				
			||||||
 | 
					          email_input_value = "";
 | 
				
			||||||
 | 
					          modal_open = false;
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					          toast.dismiss();
 | 
				
			||||||
 | 
					          toast.success($_("contact-added"));
 | 
				
			||||||
 | 
					          current_contacts.push(result);
 | 
				
			||||||
 | 
					          current_contacts = current_contacts;
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .catch((err) => {
 | 
				
			||||||
 | 
					          //
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .finally(() => {
 | 
				
			||||||
 | 
					          processed_last_submit = true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if modal_open}
 | 
				
			||||||
 | 
					  <div
 | 
				
			||||||
 | 
					    class="fixed z-10 inset-0 overflow-y-hidden"
 | 
				
			||||||
 | 
					    use:clickOutside
 | 
				
			||||||
 | 
					    on:click_outside={() => {
 | 
				
			||||||
 | 
					      modal_open = false;
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      class="flex items-end justify-center h-screen text-center sm:block p-0 lg:p-4"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          class="absolute inset-0 bg-gray-500 opacity-75"
 | 
				
			||||||
 | 
					          data-id="modal_backdrop"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <span
 | 
				
			||||||
 | 
					        class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
				
			||||||
 | 
					        aria-hidden="true">​</span
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        class="inline-block align-bottom text-left shadow-xl transform transition-all sm:align-middle w-full lg:w-auto min-w-auto lg:min-w-[35vw] relative z-10"
 | 
				
			||||||
 | 
					        role="dialog"
 | 
				
			||||||
 | 
					        aria-modal="true"
 | 
				
			||||||
 | 
					        aria-labelledby="modal-headline"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 rounded-t-xl">
 | 
				
			||||||
 | 
					          <div class="">
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <svg
 | 
				
			||||||
 | 
					                class="size-6 text-blue-600"
 | 
				
			||||||
 | 
					                fill="currentColor"
 | 
				
			||||||
 | 
					                xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					                viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                width="24"
 | 
				
			||||||
 | 
					                height="24"
 | 
				
			||||||
 | 
					                ><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
					                <path
 | 
				
			||||||
 | 
					                  d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm10 4h4v2h-4v-2zm-3-5h7v2h-7v-2zm2-5h5v2h-5V7z"
 | 
				
			||||||
 | 
					                /></svg
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="mt-3 sm:text-left max-h-[75vh] overflow-y-auto">
 | 
				
			||||||
 | 
					              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					                {$_("create-a-new-contact")}
 | 
				
			||||||
 | 
					              </h3>
 | 
				
			||||||
 | 
					              <div class="mb-6">
 | 
				
			||||||
 | 
					                <p class="text-sm text-gray-500">
 | 
				
			||||||
 | 
					                  {$_(
 | 
				
			||||||
 | 
					                    "please-provide-the-required-information-to-add-a-new-contact"
 | 
				
			||||||
 | 
					                  )}
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div class="grid grid-cols-6 gap-2 lg:gap-6 text-left">
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="firstname"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("first-name")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <input
 | 
				
			||||||
 | 
					                    use:focus
 | 
				
			||||||
 | 
					                    autocomplete="off"
 | 
				
			||||||
 | 
					                    placeholder={$_("first-name")}
 | 
				
			||||||
 | 
					                    class:border-red-500={!isFirstnameValid}
 | 
				
			||||||
 | 
					                    class:focus:border-red-500={!isFirstnameValid}
 | 
				
			||||||
 | 
					                    class:focus:ring-red-500={!isFirstnameValid}
 | 
				
			||||||
 | 
					                    bind:value={firstname_input_value}
 | 
				
			||||||
 | 
					                    bind:this={firstname_input}
 | 
				
			||||||
 | 
					                    type="text"
 | 
				
			||||||
 | 
					                    name="firstname"
 | 
				
			||||||
 | 
					                    class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                  {#if !isFirstnameValid}
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                      class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {$_("first-name-is-required")}
 | 
				
			||||||
 | 
					                    </span>
 | 
				
			||||||
 | 
					                  {/if}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="trackname"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("middle-name")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <input
 | 
				
			||||||
 | 
					                    autocomplete="off"
 | 
				
			||||||
 | 
					                    placeholder={$_("middle-name")}
 | 
				
			||||||
 | 
					                    bind:value={middlename_input_value}
 | 
				
			||||||
 | 
					                    bind:this={middlename_input}
 | 
				
			||||||
 | 
					                    type="text"
 | 
				
			||||||
 | 
					                    name="trackname"
 | 
				
			||||||
 | 
					                    class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="lastname"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("last-name")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <input
 | 
				
			||||||
 | 
					                    autocomplete="off"
 | 
				
			||||||
 | 
					                    placeholder={$_("last-name")}
 | 
				
			||||||
 | 
					                    class:border-red-500={!isLastnameValid}
 | 
				
			||||||
 | 
					                    class:focus:border-red-500={!isLastnameValid}
 | 
				
			||||||
 | 
					                    class:focus:ring-red-500={!isLastnameValid}
 | 
				
			||||||
 | 
					                    bind:value={lastname_input_value}
 | 
				
			||||||
 | 
					                    bind:this={lastname_input}
 | 
				
			||||||
 | 
					                    type="text"
 | 
				
			||||||
 | 
					                    name="lastname"
 | 
				
			||||||
 | 
					                    class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                  {#if !isLastnameValid}
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                      class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {$_("last-name-is-required")}
 | 
				
			||||||
 | 
					                    </span>
 | 
				
			||||||
 | 
					                  {/if}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="team"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("teams")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <select
 | 
				
			||||||
 | 
					                    name="team"
 | 
				
			||||||
 | 
					                    multiple
 | 
				
			||||||
 | 
					                    bind:value={selected_team}
 | 
				
			||||||
 | 
					                    class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                    {#each teams as team}
 | 
				
			||||||
 | 
					                      <option value={team.id}>
 | 
				
			||||||
 | 
					                        {team.parentGroup.name}
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                        {team.name}
 | 
				
			||||||
 | 
					                      </option>
 | 
				
			||||||
 | 
					                    {/each}
 | 
				
			||||||
 | 
					                    {#each orgs as org}
 | 
				
			||||||
 | 
					                      <option value={org.id}>{org.name}</option>
 | 
				
			||||||
 | 
					                    {/each}
 | 
				
			||||||
 | 
					                  </select>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="phone"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("phone")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <input
 | 
				
			||||||
 | 
					                    autocomplete="off"
 | 
				
			||||||
 | 
					                    placeholder={$_("phone")}
 | 
				
			||||||
 | 
					                    class:border-red-500={!isPhoneValidOrEmpty}
 | 
				
			||||||
 | 
					                    class:focus:border-red-500={!isPhoneValidOrEmpty}
 | 
				
			||||||
 | 
					                    class:focus:ring-red-500={!isPhoneValidOrEmpty}
 | 
				
			||||||
 | 
					                    bind:value={phone_input_value}
 | 
				
			||||||
 | 
					                    bind:this={phone_input}
 | 
				
			||||||
 | 
					                    type="tel"
 | 
				
			||||||
 | 
					                    name="phone"
 | 
				
			||||||
 | 
					                    class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                  {#if !isPhoneValidOrEmpty}
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                      class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {@html $_(
 | 
				
			||||||
 | 
					                        "the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number"
 | 
				
			||||||
 | 
					                      )}
 | 
				
			||||||
 | 
					                    </span>
 | 
				
			||||||
 | 
					                  {/if}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="col-span-6">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="email"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("e-mail-adress")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <input
 | 
				
			||||||
 | 
					                    autocomplete="off"
 | 
				
			||||||
 | 
					                    placeholder={$_("e-mail-adress")}
 | 
				
			||||||
 | 
					                    class:border-red-500={!isEmailValidOrEmpty}
 | 
				
			||||||
 | 
					                    class:focus:border-red-500={!isEmailValidOrEmpty}
 | 
				
			||||||
 | 
					                    class:focus:ring-red-500={!isEmailValidOrEmpty}
 | 
				
			||||||
 | 
					                    bind:value={email_input_value}
 | 
				
			||||||
 | 
					                    bind:this={email_input}
 | 
				
			||||||
 | 
					                    type="email"
 | 
				
			||||||
 | 
					                    name="email"
 | 
				
			||||||
 | 
					                    class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                  {#if !isEmailValidOrEmpty}
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                      class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {$_("valid-email-is-required")}
 | 
				
			||||||
 | 
					                    </span>
 | 
				
			||||||
 | 
					                  {/if}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="flex items-start">
 | 
				
			||||||
 | 
					                  <div class="flex items-center h-5">
 | 
				
			||||||
 | 
					                    <input
 | 
				
			||||||
 | 
					                      bind:checked={address_checked}
 | 
				
			||||||
 | 
					                      id="comments"
 | 
				
			||||||
 | 
					                      name="comments"
 | 
				
			||||||
 | 
					                      type="checkbox"
 | 
				
			||||||
 | 
					                      class="focus:ring-indigo-500 size-4 text-indigo-600 border-gray-300 rounded"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  <div class="ml-3 text-sm">
 | 
				
			||||||
 | 
					                    <label for="comments" class="font-semibold text-gray-700"
 | 
				
			||||||
 | 
					                      >{$_("address")}</label
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                {#if address_checked === true}
 | 
				
			||||||
 | 
					                  <div class="col-span-6">
 | 
				
			||||||
 | 
					                    <label
 | 
				
			||||||
 | 
					                      for="address1"
 | 
				
			||||||
 | 
					                      class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                      >{$_("address")}</label
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                    <input
 | 
				
			||||||
 | 
					                      autocomplete="off"
 | 
				
			||||||
 | 
					                      placeholder={$_("address")}
 | 
				
			||||||
 | 
					                      class:border-red-500={!isAddress1Valid}
 | 
				
			||||||
 | 
					                      class:focus:border-red-500={!isAddress1Valid}
 | 
				
			||||||
 | 
					                      class:focus:ring-red-500={!isAddress1Valid}
 | 
				
			||||||
 | 
					                      bind:value={address_input1_value}
 | 
				
			||||||
 | 
					                      bind:this={address_input1}
 | 
				
			||||||
 | 
					                      type="text"
 | 
				
			||||||
 | 
					                      name="address1"
 | 
				
			||||||
 | 
					                      class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    {#if !isAddress1Valid}
 | 
				
			||||||
 | 
					                      <span
 | 
				
			||||||
 | 
					                        class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        {$_("address-is-required")}
 | 
				
			||||||
 | 
					                      </span>
 | 
				
			||||||
 | 
					                    {/if}
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  <div class="col-span-6">
 | 
				
			||||||
 | 
					                    <label
 | 
				
			||||||
 | 
					                      for="address2"
 | 
				
			||||||
 | 
					                      class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                      >{$_("apartment-suite-etc")}</label
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                    <input
 | 
				
			||||||
 | 
					                      autocomplete="off"
 | 
				
			||||||
 | 
					                      placeholder={$_("apartment-suite-etc")}
 | 
				
			||||||
 | 
					                      bind:value={address_input2_value}
 | 
				
			||||||
 | 
					                      bind:this={address_input2}
 | 
				
			||||||
 | 
					                      type="text"
 | 
				
			||||||
 | 
					                      name="address2"
 | 
				
			||||||
 | 
					                      class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  <div class="col-span-6">
 | 
				
			||||||
 | 
					                    <label
 | 
				
			||||||
 | 
					                      for="zipcode"
 | 
				
			||||||
 | 
					                      class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                      >{$_("zip-postal-code")}</label
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                    <input
 | 
				
			||||||
 | 
					                      autocomplete="off"
 | 
				
			||||||
 | 
					                      placeholder={$_("zip-postal-code")}
 | 
				
			||||||
 | 
					                      class:border-red-500={!iszipcodevalid}
 | 
				
			||||||
 | 
					                      class:focus:border-red-500={!iszipcodevalid}
 | 
				
			||||||
 | 
					                      class:focus:ring-red-500={!iszipcodevalid}
 | 
				
			||||||
 | 
					                      bind:value={address_zipcode_value}
 | 
				
			||||||
 | 
					                      bind:this={address_zipcode}
 | 
				
			||||||
 | 
					                      type="text"
 | 
				
			||||||
 | 
					                      name="zipcode"
 | 
				
			||||||
 | 
					                      class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    {#if !iszipcodevalid}
 | 
				
			||||||
 | 
					                      <span
 | 
				
			||||||
 | 
					                        class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        {$_("valid-zipcode-postal-code-is-required")}
 | 
				
			||||||
 | 
					                      </span>
 | 
				
			||||||
 | 
					                    {/if}
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  <div class="col-span-6">
 | 
				
			||||||
 | 
					                    <label
 | 
				
			||||||
 | 
					                      for="city"
 | 
				
			||||||
 | 
					                      class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                      >{$_("city")}</label
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                    <input
 | 
				
			||||||
 | 
					                      autocomplete="off"
 | 
				
			||||||
 | 
					                      placeholder={$_("city")}
 | 
				
			||||||
 | 
					                      class:border-red-500={!iscityvalid}
 | 
				
			||||||
 | 
					                      class:focus:border-red-500={!iscityvalid}
 | 
				
			||||||
 | 
					                      class:focus:ring-red-500={!iscityvalid}
 | 
				
			||||||
 | 
					                      bind:value={address_city_value}
 | 
				
			||||||
 | 
					                      bind:this={address_city}
 | 
				
			||||||
 | 
					                      type="text"
 | 
				
			||||||
 | 
					                      name="city"
 | 
				
			||||||
 | 
					                      class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    {#if !iscityvalid}
 | 
				
			||||||
 | 
					                      <span
 | 
				
			||||||
 | 
					                        class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        {$_("valid-city-is-required")}
 | 
				
			||||||
 | 
					                      </span>
 | 
				
			||||||
 | 
					                    {/if}
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                {/if}
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="bg-gray-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10">
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            disabled={!createbtnenabled}
 | 
				
			||||||
 | 
					            class:opacity-50={!createbtnenabled}
 | 
				
			||||||
 | 
					            on:click={submit}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("create")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={() => {
 | 
				
			||||||
 | 
					              modal_open = false;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            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"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("cancel")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										399
									
								
								src/components/contacts/ContactDetail.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										399
									
								
								src/components/contacts/ContactDetail.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,399 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
						import store from "../../store";
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							GroupContactService,
 | 
				
			||||||
 | 
							RunnerTeamService,
 | 
				
			||||||
 | 
							RunnerOrganizationService,
 | 
				
			||||||
 | 
						} from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
						import PromiseError from "../base/PromiseError.svelte";
 | 
				
			||||||
 | 
						import isEmail from "validator/es/lib/isEmail";
 | 
				
			||||||
 | 
						import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
						let data_loaded = false;
 | 
				
			||||||
 | 
						let orgs = [];
 | 
				
			||||||
 | 
						let teams = [];
 | 
				
			||||||
 | 
						export let params;
 | 
				
			||||||
 | 
						$: delete_triggered = false;
 | 
				
			||||||
 | 
						$: original_data = {};
 | 
				
			||||||
 | 
						$: editable = {};
 | 
				
			||||||
 | 
						$: changes_performed = !(
 | 
				
			||||||
 | 
							JSON.stringify(original_data) === JSON.stringify(editable)
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						$: isEmailValid =
 | 
				
			||||||
 | 
							(editable.email || "") === "" ||
 | 
				
			||||||
 | 
							(editable.email && isEmail(editable.email || ""));
 | 
				
			||||||
 | 
						$: isFirstnameValid = editable.firstname !== "";
 | 
				
			||||||
 | 
						$: isLastnameValid = editable.lastname !== "";
 | 
				
			||||||
 | 
						$: save_enabled =
 | 
				
			||||||
 | 
							changes_performed &&
 | 
				
			||||||
 | 
							isFirstnameValid &&
 | 
				
			||||||
 | 
							isLastnameValid &&
 | 
				
			||||||
 | 
							isEmailValid &&
 | 
				
			||||||
 | 
							isPhoneValidOrEmpty &&
 | 
				
			||||||
 | 
							((isAddress1Valid && iszipcodevalid && iscityvalid) ||
 | 
				
			||||||
 | 
								editable.address_checked === false);
 | 
				
			||||||
 | 
						const promise = GroupContactService.groupContactControllerGetOne(
 | 
				
			||||||
 | 
							params.contact
 | 
				
			||||||
 | 
						).then((data) => {
 | 
				
			||||||
 | 
							data_loaded = true;
 | 
				
			||||||
 | 
							original_data = Object.assign(original_data, data);
 | 
				
			||||||
 | 
							editable = Object.assign(editable, original_data);
 | 
				
			||||||
 | 
							editable.groups = editable.groups.map((g) => g.id);
 | 
				
			||||||
 | 
							original_data.groups = original_data.groups.map((g) => g.id);
 | 
				
			||||||
 | 
							editable.address_checked = editable.address.address1 !== null;
 | 
				
			||||||
 | 
							original_data.address_checked = editable.address.address1 !== null;
 | 
				
			||||||
 | 
							if (editable.address_checked === false) {
 | 
				
			||||||
 | 
								editable.address = {
 | 
				
			||||||
 | 
									address1: "",
 | 
				
			||||||
 | 
									address2: "",
 | 
				
			||||||
 | 
									city: "",
 | 
				
			||||||
 | 
									postalcode: "",
 | 
				
			||||||
 | 
									country: "",
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
 | 
				
			||||||
 | 
							orgs = val;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
 | 
				
			||||||
 | 
							teams = val;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						$: isPhoneValidOrEmpty =
 | 
				
			||||||
 | 
							editable.phone?.includes("+") ||
 | 
				
			||||||
 | 
							editable.phone === "" ||
 | 
				
			||||||
 | 
							editable.phone === null;
 | 
				
			||||||
 | 
						$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
 | 
				
			||||||
 | 
						$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
 | 
				
			||||||
 | 
						$: iscityvalid = editable.address?.city?.trim().length !== 0;
 | 
				
			||||||
 | 
						function submit() {
 | 
				
			||||||
 | 
							if (data_loaded === true && save_enabled) {
 | 
				
			||||||
 | 
								toast.loading($_("contact-is-being-updated"));
 | 
				
			||||||
 | 
								editable.address.country = "DE";
 | 
				
			||||||
 | 
								if (editable.address_checked === false) {
 | 
				
			||||||
 | 
									editable.address = null;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (editable.email) editable.email = editable.email;
 | 
				
			||||||
 | 
								if (editable.phone) editable.phone = editable.phone;
 | 
				
			||||||
 | 
								if (editable.middlename) editable.middlename = editable.middlename;
 | 
				
			||||||
 | 
								GroupContactService.groupContactControllerPut(original_data.id, editable)
 | 
				
			||||||
 | 
									.then((resp) => {
 | 
				
			||||||
 | 
										Object.assign(original_data, editable);
 | 
				
			||||||
 | 
										original_data = original_data;
 | 
				
			||||||
 | 
										toast.dismiss();
 | 
				
			||||||
 | 
										toast.success($_("updated-contact"));
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									.catch((err) => {});
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						function deleteContact() {
 | 
				
			||||||
 | 
							GroupContactService.groupContactControllerRemove(original_data.id, true)
 | 
				
			||||||
 | 
								.then((resp) => {
 | 
				
			||||||
 | 
									location.replace("./");
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.catch((err) => {});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#await promise}
 | 
				
			||||||
 | 
						{$_("loading-contact-details")}
 | 
				
			||||||
 | 
					{:then}
 | 
				
			||||||
 | 
						<section class="container p-5 select-none">
 | 
				
			||||||
 | 
							<div class="flex flex-row mb-4">
 | 
				
			||||||
 | 
								<div class="w-full">
 | 
				
			||||||
 | 
									<nav class="w-full flex">
 | 
				
			||||||
 | 
										<ol class="list-none flex flex-row items-center justify-start">
 | 
				
			||||||
 | 
											<li class="flex items-center">
 | 
				
			||||||
 | 
												<a class="mr-2" href="./"
 | 
				
			||||||
 | 
													><svg
 | 
				
			||||||
 | 
														xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
														width="24"
 | 
				
			||||||
 | 
														height="24"
 | 
				
			||||||
 | 
														viewBox="0 0 24 24"
 | 
				
			||||||
 | 
														fill="none"
 | 
				
			||||||
 | 
														stroke="currentColor"
 | 
				
			||||||
 | 
														stroke-width="2"
 | 
				
			||||||
 | 
														stroke-linecap="round"
 | 
				
			||||||
 | 
														stroke-linejoin="round"
 | 
				
			||||||
 | 
														class="inline-block"
 | 
				
			||||||
 | 
														><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
													{$_("contacts")}</a
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
											</li>
 | 
				
			||||||
 | 
										</ol>
 | 
				
			||||||
 | 
									</nav>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="mb-4 text-3xl font-extrabold leading-tight">
 | 
				
			||||||
 | 
								{original_data.firstname}
 | 
				
			||||||
 | 
								{original_data.middlename || ""}
 | 
				
			||||||
 | 
								{original_data.lastname}
 | 
				
			||||||
 | 
								<div data-id="contact_actions_${editable.id}">
 | 
				
			||||||
 | 
									{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:DELETE")}
 | 
				
			||||||
 | 
										{#if delete_triggered}
 | 
				
			||||||
 | 
											<button
 | 
				
			||||||
 | 
												on:click={deleteContact}
 | 
				
			||||||
 | 
												class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm"
 | 
				
			||||||
 | 
												>{$_("confirm-deletion")}</button
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
											<button
 | 
				
			||||||
 | 
												on:click={() => {
 | 
				
			||||||
 | 
													delete_triggered = !delete_triggered;
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
												class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
 | 
				
			||||||
 | 
												>{$_("cancel")}</button
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
										{/if}
 | 
				
			||||||
 | 
										{#if !delete_triggered}
 | 
				
			||||||
 | 
											<button
 | 
				
			||||||
 | 
												on:click={() => {
 | 
				
			||||||
 | 
													delete_triggered = true;
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
												type="button"
 | 
				
			||||||
 | 
												class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm"
 | 
				
			||||||
 | 
												>{$_("delete-contact")}</button
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
										{/if}
 | 
				
			||||||
 | 
									{/if}
 | 
				
			||||||
 | 
									{#if !delete_triggered}
 | 
				
			||||||
 | 
										<button
 | 
				
			||||||
 | 
											disabled={!save_enabled}
 | 
				
			||||||
 | 
											class:opacity-50={!save_enabled}
 | 
				
			||||||
 | 
											type="button"
 | 
				
			||||||
 | 
											on:click={submit}
 | 
				
			||||||
 | 
											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"
 | 
				
			||||||
 | 
											>{$_("save-changes")}</button
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
									{/if}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<!--  -->
 | 
				
			||||||
 | 
							<div class="text-sm w-full mt-2">
 | 
				
			||||||
 | 
								<label for="firstname" class="font-semibold text-gray-700"
 | 
				
			||||||
 | 
									>{$_("first-name")}</label
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<input
 | 
				
			||||||
 | 
									autocomplete="off"
 | 
				
			||||||
 | 
									placeholder={$_("first-name")}
 | 
				
			||||||
 | 
									type="text"
 | 
				
			||||||
 | 
									class:border-red-500={!isFirstnameValid}
 | 
				
			||||||
 | 
									class:focus:border-red-500={!isFirstnameValid}
 | 
				
			||||||
 | 
									class:focus:ring-red-500={!isFirstnameValid}
 | 
				
			||||||
 | 
									bind:value={editable.firstname}
 | 
				
			||||||
 | 
									name="firstname"
 | 
				
			||||||
 | 
									class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								{#if !isFirstnameValid}
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{$_("first-name-is-required")}
 | 
				
			||||||
 | 
									</span>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="text-sm w-full mt-2">
 | 
				
			||||||
 | 
								<label for="middlename" class="font-semibold text-gray-700"
 | 
				
			||||||
 | 
									>{$_("middle-name")}</label
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<input
 | 
				
			||||||
 | 
									autocomplete="off"
 | 
				
			||||||
 | 
									placeholder={$_("middle-name")}
 | 
				
			||||||
 | 
									type="text"
 | 
				
			||||||
 | 
									bind:value={editable.middlename}
 | 
				
			||||||
 | 
									name="middlename"
 | 
				
			||||||
 | 
									class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="text-sm w-full mt-2">
 | 
				
			||||||
 | 
								<label for="lastname" class="font-semibold text-gray-700"
 | 
				
			||||||
 | 
									>{$_("last-name")}</label
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<input
 | 
				
			||||||
 | 
									autocomplete="off"
 | 
				
			||||||
 | 
									placeholder={$_("last-name")}
 | 
				
			||||||
 | 
									type="text"
 | 
				
			||||||
 | 
									bind:value={editable.lastname}
 | 
				
			||||||
 | 
									class:border-red-500={!isLastnameValid}
 | 
				
			||||||
 | 
									class:focus:border-red-500={!isLastnameValid}
 | 
				
			||||||
 | 
									class:focus:ring-red-500={!isLastnameValid}
 | 
				
			||||||
 | 
									name="lastname"
 | 
				
			||||||
 | 
									class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								{#if !isLastnameValid}
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{$_("last-name-is-required")}
 | 
				
			||||||
 | 
									</span>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="text-sm w-full mt-2">
 | 
				
			||||||
 | 
								<label for="email" class="font-semibold text-gray-700"
 | 
				
			||||||
 | 
									>{$_("e-mail-adress")}</label
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<input
 | 
				
			||||||
 | 
									autocomplete="off"
 | 
				
			||||||
 | 
									placeholder={$_("e-mail-adress")}
 | 
				
			||||||
 | 
									type="email"
 | 
				
			||||||
 | 
									bind:value={editable.email}
 | 
				
			||||||
 | 
									class:border-red-500={!isEmailValid}
 | 
				
			||||||
 | 
									class:focus:border-red-500={!isEmailValid}
 | 
				
			||||||
 | 
									class:focus:ring-red-500={!isEmailValid}
 | 
				
			||||||
 | 
									name="email"
 | 
				
			||||||
 | 
									class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								{#if !isEmailValid}
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{$_("valid-email-is-required")}
 | 
				
			||||||
 | 
									</span>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="text-sm w-full mt-2">
 | 
				
			||||||
 | 
								<label for="phone" class="font-semibold text-gray-700">{$_("phone")}</label>
 | 
				
			||||||
 | 
								<input
 | 
				
			||||||
 | 
									autocomplete="off"
 | 
				
			||||||
 | 
									placeholder={$_("phone")}
 | 
				
			||||||
 | 
									type="tel"
 | 
				
			||||||
 | 
									class:border-red-500={!isPhoneValidOrEmpty}
 | 
				
			||||||
 | 
									class:focus:border-red-500={!isPhoneValidOrEmpty}
 | 
				
			||||||
 | 
									class:focus:ring-red-500={!isPhoneValidOrEmpty}
 | 
				
			||||||
 | 
									bind:value={editable.phone}
 | 
				
			||||||
 | 
									name="phone"
 | 
				
			||||||
 | 
									class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								{#if !isPhoneValidOrEmpty}
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{$_("valid-international-phone-number-is-required")}
 | 
				
			||||||
 | 
									</span>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="text-sm w-full mt-2">
 | 
				
			||||||
 | 
								<span class="font-semibold text-gray-700">{$_("groups")}</span>
 | 
				
			||||||
 | 
								<select
 | 
				
			||||||
 | 
									bind:value={editable.groups}
 | 
				
			||||||
 | 
									name="team"
 | 
				
			||||||
 | 
									multiple
 | 
				
			||||||
 | 
									class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									{#each teams as team}
 | 
				
			||||||
 | 
										<option value={team.id}>
 | 
				
			||||||
 | 
											{team.parentGroup.name}
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
											{team.name}
 | 
				
			||||||
 | 
										</option>
 | 
				
			||||||
 | 
									{/each}
 | 
				
			||||||
 | 
									{#each orgs as org}
 | 
				
			||||||
 | 
										<option value={org.id}>{org.name}</option>
 | 
				
			||||||
 | 
									{/each}
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<!--  -->
 | 
				
			||||||
 | 
							<div class="flex items-start mt-2">
 | 
				
			||||||
 | 
								<div class="flex items-center h-5">
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										bind:checked={editable.address_checked}
 | 
				
			||||||
 | 
										id="comments"
 | 
				
			||||||
 | 
										name="comments"
 | 
				
			||||||
 | 
										type="checkbox"
 | 
				
			||||||
 | 
										class="focus:ring-indigo-500 size-4 text-indigo-600 border-gray-300 rounded"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div class="ml-3 text-sm">
 | 
				
			||||||
 | 
									<label for="comments" class="font-semibold text-gray-700"
 | 
				
			||||||
 | 
										>{$_("address")}</label
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							{#if editable.address_checked === true}
 | 
				
			||||||
 | 
								<div class="col-span-6">
 | 
				
			||||||
 | 
									<label for="address1" class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
										>{$_("address")}</label
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										autocomplete="off"
 | 
				
			||||||
 | 
										placeholder="Address"
 | 
				
			||||||
 | 
										class:border-red-500={!isAddress1Valid}
 | 
				
			||||||
 | 
										class:focus:border-red-500={!isAddress1Valid}
 | 
				
			||||||
 | 
										class:focus:ring-red-500={!isAddress1Valid}
 | 
				
			||||||
 | 
										bind:value={editable.address.address1}
 | 
				
			||||||
 | 
										type="text"
 | 
				
			||||||
 | 
										name="address1"
 | 
				
			||||||
 | 
										class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									{#if !isAddress1Valid}
 | 
				
			||||||
 | 
										<span
 | 
				
			||||||
 | 
											class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											{$_("address-is-required")}
 | 
				
			||||||
 | 
										</span>
 | 
				
			||||||
 | 
									{/if}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div class="col-span-6">
 | 
				
			||||||
 | 
									<label for="address2" class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
										>{$_("apartment-suite-etc")}</label
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										autocomplete="off"
 | 
				
			||||||
 | 
										placeholder={$_("apartment-suite-etc")}
 | 
				
			||||||
 | 
										bind:value={editable.address.address2}
 | 
				
			||||||
 | 
										type="text"
 | 
				
			||||||
 | 
										name="address2"
 | 
				
			||||||
 | 
										class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div class="col-span-6">
 | 
				
			||||||
 | 
									<label for="zipcode" class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
										>{$_("zip-postal-code")}</label
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										autocomplete="off"
 | 
				
			||||||
 | 
										placeholder={$_("zip-postal-code")}
 | 
				
			||||||
 | 
										class:border-red-500={!iszipcodevalid}
 | 
				
			||||||
 | 
										class:focus:border-red-500={!iszipcodevalid}
 | 
				
			||||||
 | 
										class:focus:ring-red-500={!iszipcodevalid}
 | 
				
			||||||
 | 
										bind:value={editable.address.postalcode}
 | 
				
			||||||
 | 
										type="text"
 | 
				
			||||||
 | 
										name="zipcode"
 | 
				
			||||||
 | 
										class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									{#if !iszipcodevalid}
 | 
				
			||||||
 | 
										<span
 | 
				
			||||||
 | 
											class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											{$_("valid-zipcode-postal-code-is-required")}
 | 
				
			||||||
 | 
										</span>
 | 
				
			||||||
 | 
									{/if}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div class="col-span-6">
 | 
				
			||||||
 | 
									<label for="city" class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
										>{$_("city")}</label
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										autocomplete="off"
 | 
				
			||||||
 | 
										placeholder={$_("city")}
 | 
				
			||||||
 | 
										class:border-red-500={!iscityvalid}
 | 
				
			||||||
 | 
										class:focus:border-red-500={!iscityvalid}
 | 
				
			||||||
 | 
										class:focus:ring-red-500={!iscityvalid}
 | 
				
			||||||
 | 
										bind:value={editable.address.city}
 | 
				
			||||||
 | 
										type="text"
 | 
				
			||||||
 | 
										name="city"
 | 
				
			||||||
 | 
										class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									{#if !iscityvalid}
 | 
				
			||||||
 | 
										<span
 | 
				
			||||||
 | 
											class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											{$_("valid-city-is-required")}
 | 
				
			||||||
 | 
										</span>
 | 
				
			||||||
 | 
									{/if}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							{/if}
 | 
				
			||||||
 | 
						</section>
 | 
				
			||||||
 | 
					{:catch error}
 | 
				
			||||||
 | 
						<PromiseError {error} />
 | 
				
			||||||
 | 
					{/await}
 | 
				
			||||||
							
								
								
									
										30
									
								
								src/components/contacts/Contacts.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/components/contacts/Contacts.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import store from "../../store";
 | 
				
			||||||
 | 
					  import AddContactModal from "./AddContactModal.svelte";
 | 
				
			||||||
 | 
					  import ContactsOverview from "./ContactsOverview.svelte";
 | 
				
			||||||
 | 
					  export let modal_open = false;
 | 
				
			||||||
 | 
					  let current_contacts = [];
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section class="container p-5">
 | 
				
			||||||
 | 
					  <h4 class="mb-1 text-3xl font-extrabold leading-tight">
 | 
				
			||||||
 | 
					    {$_("contacts")}
 | 
				
			||||||
 | 
					  </h4>
 | 
				
			||||||
 | 
					  {#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:CREATE")}
 | 
				
			||||||
 | 
					    <button
 | 
				
			||||||
 | 
					      on:click={() => {
 | 
				
			||||||
 | 
					        modal_open = true;
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      type="button"
 | 
				
			||||||
 | 
					      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {$_("create-a-new-contact")}
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  {/if}
 | 
				
			||||||
 | 
					  <ContactsOverview bind:current_contacts />
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:CREATE")}
 | 
				
			||||||
 | 
					  <AddContactModal bind:current_contacts bind:modal_open />
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										17
									
								
								src/components/contacts/ContactsEmptyState.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/components/contacts/ContactsEmptyState.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import AddContactModal from "./AddContactModal.svelte";
 | 
				
			||||||
 | 
					  import team_empty from "../teams/team_empty.svg";
 | 
				
			||||||
 | 
					  let modal_open = false;
 | 
				
			||||||
 | 
					  let current_contacts = [];
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="text-center items-center justify-center">
 | 
				
			||||||
 | 
					  <p class="mb-16 text-lg text-gray-500">
 | 
				
			||||||
 | 
					    <img class="w-full h-44" src={team_empty} alt="" />
 | 
				
			||||||
 | 
					    <span class="font-bold">{$_("there-are-no-contacts-added-yet")}</span><br />
 | 
				
			||||||
 | 
					    <span>{$_("add-your-first-contact")}</span>
 | 
				
			||||||
 | 
					  </p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<AddContactModal bind:modal_open bind:current_contacts />
 | 
				
			||||||
							
								
								
									
										198
									
								
								src/components/contacts/ContactsOverview.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								src/components/contacts/ContactsOverview.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,198 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
						import { GroupContactService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
						const promise = GroupContactService.groupContactControllerGetAll().then(
 | 
				
			||||||
 | 
							(result) => {
 | 
				
			||||||
 | 
								current_contacts = result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						import store from "../../store";
 | 
				
			||||||
 | 
						import ContactsEmptyState from "./ContactsEmptyState.svelte";
 | 
				
			||||||
 | 
						import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
						$: searchvalue = "";
 | 
				
			||||||
 | 
						$: active_deletes = [];
 | 
				
			||||||
 | 
						export let current_contacts = [];
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
 | 
				
			||||||
 | 
						{#await promise}
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
 | 
				
			||||||
 | 
								role="alert"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<p class="font-bold">{$_("contacts-are-being-loaded")}</p>
 | 
				
			||||||
 | 
								<p class="text-sm">{$_("this-might-take-a-moment")}</p>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						{:then}
 | 
				
			||||||
 | 
							{#if current_contacts.length === 0}
 | 
				
			||||||
 | 
								<ContactsEmptyState />
 | 
				
			||||||
 | 
							{:else}
 | 
				
			||||||
 | 
								<input
 | 
				
			||||||
 | 
									type="search"
 | 
				
			||||||
 | 
									bind:value={searchvalue}
 | 
				
			||||||
 | 
									placeholder={$_("datatable.search")}
 | 
				
			||||||
 | 
									aria-label={$_("datatable.search")}
 | 
				
			||||||
 | 
									class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<table class="divide-y divide-gray-200 w-full">
 | 
				
			||||||
 | 
										<thead class="bg-gray-50">
 | 
				
			||||||
 | 
											<tr class="odd:bg-white even:bg-gray-100">
 | 
				
			||||||
 | 
												<th
 | 
				
			||||||
 | 
													scope="col"
 | 
				
			||||||
 | 
													class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													{$_("name")}
 | 
				
			||||||
 | 
												</th>
 | 
				
			||||||
 | 
												<th
 | 
				
			||||||
 | 
													scope="col"
 | 
				
			||||||
 | 
													class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													{$_("groups")}
 | 
				
			||||||
 | 
												</th>
 | 
				
			||||||
 | 
												<th
 | 
				
			||||||
 | 
													scope="col"
 | 
				
			||||||
 | 
													class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													{$_("address")}
 | 
				
			||||||
 | 
												</th>
 | 
				
			||||||
 | 
												<th scope="col" class="relative px-6 py-3">
 | 
				
			||||||
 | 
													<span class="sr-only">{$_("action")}</span>
 | 
				
			||||||
 | 
												</th>
 | 
				
			||||||
 | 
											</tr>
 | 
				
			||||||
 | 
										</thead>
 | 
				
			||||||
 | 
										<tbody class="divide-y divide-gray-200">
 | 
				
			||||||
 | 
											{#each current_contacts as t}
 | 
				
			||||||
 | 
												{#if Object.values(t)
 | 
				
			||||||
 | 
													.toString()
 | 
				
			||||||
 | 
													.toLowerCase()
 | 
				
			||||||
 | 
													.includes(searchvalue)}
 | 
				
			||||||
 | 
													<tr
 | 
				
			||||||
 | 
														class="odd:bg-white even:bg-gray-100"
 | 
				
			||||||
 | 
														data-rowid="team_{t.id}"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														<td class="px-6 py-4 whitespace-nowrap">
 | 
				
			||||||
 | 
															<div class="flex items-center">
 | 
				
			||||||
 | 
																<div class="ml-4">
 | 
				
			||||||
 | 
																	<div class="text-sm font-medium text-gray-900">
 | 
				
			||||||
 | 
																		{t.firstname}
 | 
				
			||||||
 | 
																		{t.middlename || ""}
 | 
				
			||||||
 | 
																		{t.lastname}
 | 
				
			||||||
 | 
																	</div>
 | 
				
			||||||
 | 
																</div>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														</td>
 | 
				
			||||||
 | 
														<td class="px-6 py-4 whitespace-nowrap">
 | 
				
			||||||
 | 
															<div class="flex items-center">
 | 
				
			||||||
 | 
																<div
 | 
				
			||||||
 | 
																	class="text-sm font-medium text-gray-900 gap-0.5 flex flex-wrap"
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
																	{#if t.groups.length > 0}
 | 
				
			||||||
 | 
																		{#each t.groups as g}
 | 
				
			||||||
 | 
																			{#if g.responseType === "RUNNERORGANIZATION"}
 | 
				
			||||||
 | 
																				<a
 | 
				
			||||||
 | 
																					href="../orgs/{g.id}"
 | 
				
			||||||
 | 
																					class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
 | 
				
			||||||
 | 
																					>{g.name}</a
 | 
				
			||||||
 | 
																				>
 | 
				
			||||||
 | 
																			{:else}
 | 
				
			||||||
 | 
																				<a
 | 
				
			||||||
 | 
																					href="../teams/{g.id}"
 | 
				
			||||||
 | 
																					class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
 | 
				
			||||||
 | 
																					>{g.parentGroup.name}
 | 
				
			||||||
 | 
																					>
 | 
				
			||||||
 | 
																					{g.name}</a
 | 
				
			||||||
 | 
																				>
 | 
				
			||||||
 | 
																			{/if}
 | 
				
			||||||
 | 
																		{/each}
 | 
				
			||||||
 | 
																	{:else}
 | 
				
			||||||
 | 
																		{$_("contact-is-not-a-member-in-any-group")}
 | 
				
			||||||
 | 
																	{/if}
 | 
				
			||||||
 | 
																</div>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														</td>
 | 
				
			||||||
 | 
														<td class="px-6 py-4 whitespace-nowrap">
 | 
				
			||||||
 | 
															<div class="flex items-center">
 | 
				
			||||||
 | 
																<div class="ml-4">
 | 
				
			||||||
 | 
																	<div class="text-sm font-medium text-gray-900">
 | 
				
			||||||
 | 
																		{#if t.address.address1 !== null}
 | 
				
			||||||
 | 
																			{t.address.address1}<br />
 | 
				
			||||||
 | 
																			{t.address.address2 || ""}<br />
 | 
				
			||||||
 | 
																			{t.address.postalcode}
 | 
				
			||||||
 | 
																			{t.address.city}
 | 
				
			||||||
 | 
																			{t.address.country}
 | 
				
			||||||
 | 
																		{/if}
 | 
				
			||||||
 | 
																	</div>
 | 
				
			||||||
 | 
																</div>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														</td>
 | 
				
			||||||
 | 
														{#if active_deletes[t.id] === true}
 | 
				
			||||||
 | 
															<td
 | 
				
			||||||
 | 
																class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
																<button
 | 
				
			||||||
 | 
																	on:click={() => {
 | 
				
			||||||
 | 
																		active_deletes[t.id] = false;
 | 
				
			||||||
 | 
																	}}
 | 
				
			||||||
 | 
																	tabindex="0"
 | 
				
			||||||
 | 
																	class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
 | 
				
			||||||
 | 
																	>{$_("cancel-delete")}</button
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
																<button
 | 
				
			||||||
 | 
																	on:click={() => {
 | 
				
			||||||
 | 
																		toast.loading($_("deleting-contact"));
 | 
				
			||||||
 | 
																		GroupContactService.groupContactControllerRemove(
 | 
				
			||||||
 | 
																			t.id,
 | 
				
			||||||
 | 
																			false
 | 
				
			||||||
 | 
																		).then((resp) => {
 | 
				
			||||||
 | 
																			current_contacts = current_contacts.filter(
 | 
				
			||||||
 | 
																				(obj) => obj.id !== t.id
 | 
				
			||||||
 | 
																			);
 | 
				
			||||||
 | 
																			toast.dismiss();
 | 
				
			||||||
 | 
																			toast.success($_("contact-deleted"));
 | 
				
			||||||
 | 
																		});
 | 
				
			||||||
 | 
																	}}
 | 
				
			||||||
 | 
																	tabindex="0"
 | 
				
			||||||
 | 
																	class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
 | 
				
			||||||
 | 
																	>{$_("confirm-delete")}</button
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
															</td>
 | 
				
			||||||
 | 
														{:else}
 | 
				
			||||||
 | 
															<td
 | 
				
			||||||
 | 
																class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
																<a
 | 
				
			||||||
 | 
																	href="./{t.id}"
 | 
				
			||||||
 | 
																	class="text-indigo-600 hover:text-indigo-900"
 | 
				
			||||||
 | 
																	>{$_("details")}</a
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
																{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")}
 | 
				
			||||||
 | 
																	<button
 | 
				
			||||||
 | 
																		on:click={() => {
 | 
				
			||||||
 | 
																			active_deletes[t.id] = true;
 | 
				
			||||||
 | 
																		}}
 | 
				
			||||||
 | 
																		tabindex="0"
 | 
				
			||||||
 | 
																		class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
 | 
				
			||||||
 | 
																		>{$_("delete")}</button
 | 
				
			||||||
 | 
																	>
 | 
				
			||||||
 | 
																{/if}
 | 
				
			||||||
 | 
															</td>
 | 
				
			||||||
 | 
														{/if}
 | 
				
			||||||
 | 
													</tr>
 | 
				
			||||||
 | 
												{/if}
 | 
				
			||||||
 | 
											{/each}
 | 
				
			||||||
 | 
										</tbody>
 | 
				
			||||||
 | 
									</table>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							{/if}
 | 
				
			||||||
 | 
						{:catch error}
 | 
				
			||||||
 | 
							<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
 | 
				
			||||||
 | 
								<span class="inline-block align-middle mr-8">
 | 
				
			||||||
 | 
									<b>{$_("general_promise_error")}</b>
 | 
				
			||||||
 | 
									{error}
 | 
				
			||||||
 | 
								</span>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						{/await}
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										459
									
								
								src/components/dashboard/Dashboard.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										459
									
								
								src/components/dashboard/Dashboard.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,459 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
						import localForage from "localforage";
 | 
				
			||||||
 | 
						import store from "../../store";
 | 
				
			||||||
 | 
						import { router } from "tinro";
 | 
				
			||||||
 | 
						import NoComponentLoaded from "../base/NoComponentLoaded.svelte";
 | 
				
			||||||
 | 
						import { AuthService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
						import { Toaster } from "svelte-french-toast";
 | 
				
			||||||
 | 
						$: navOpen = false;
 | 
				
			||||||
 | 
						function logout() {
 | 
				
			||||||
 | 
							localForage.clear();
 | 
				
			||||||
 | 
							location.replace("/");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section class="min-h-screen bg-gray-50">
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							class:collapsed_navigation={!navOpen}
 | 
				
			||||||
 | 
							style="z-index:11;"
 | 
				
			||||||
 | 
							class="select-none fixed top-0 left-0 h-full pb-10 overflow-x-hidden overflow-y-auto transition origin-left transform border-r w-60 bg-gray-50"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<a href="/" class="flex items-center px-4 py-5">
 | 
				
			||||||
 | 
								<img src="/lfk-logo.png" alt="Logo" class="h-10" />
 | 
				
			||||||
 | 
								<h3 class="text-lg font-bold">LfK!Admin</h3>
 | 
				
			||||||
 | 
							</a>
 | 
				
			||||||
 | 
							<nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation">
 | 
				
			||||||
 | 
								<a
 | 
				
			||||||
 | 
									class:activenav={$router.path === "/"}
 | 
				
			||||||
 | 
									class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
									href="/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 20 20"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
									</svg>
 | 
				
			||||||
 | 
									<span>{$_("dashboard-title")}</span>
 | 
				
			||||||
 | 
								</a>
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET") && store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/cardassignment/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/cardassignment/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												fill-rule="evenodd"
 | 
				
			||||||
 | 
												d="M14.615 1.595a.75.75 0 0 1 .359.852L12.982 9.75h7.268a.75.75 0 0 1 .548 1.262l-10.5 11.25a.75.75 0 0 1-1.272-.71l1.992-7.302H3.75a.75.75 0 0 1-.548-1.262l10.5-11.25a.75.75 0 0 1 .913-.143Z"
 | 
				
			||||||
 | 
												clip-rule="evenodd"
 | 
				
			||||||
 | 
											/>
 | 
				
			||||||
 | 
										</svg>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<span>{$_('card_assignment_menu')}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/runners/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/runners/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("runners")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/teams/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/teams/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 640 512"
 | 
				
			||||||
 | 
											><path
 | 
				
			||||||
 | 
												fill="currentColor"
 | 
				
			||||||
 | 
												d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("teams")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/orgs/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/orgs/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												d="M17 19h2v-8h-6v8h2v-6h2v6zM3 19V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v5h2v10h1v2H2v-2h1zm4-8v2h2v-2H7zm0 4v2h2v-2H7zm0-8v2h2V7H7z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("orgs")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/donors/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/donors/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("donors")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/donations/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/donations/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("donations")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("TRACK:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path === "/tracks/"}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/tracks/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 640 512"
 | 
				
			||||||
 | 
											><path
 | 
				
			||||||
 | 
												fill="currentColor"
 | 
				
			||||||
 | 
												d="M635.7 167.2L556.1 31.7c-8.8-15-28.3-20.1-43.5-11.5l-69 39.1L503.3 161c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L416 75l-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L333.2 122 278 153.3 337.8 255c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-59.7-101.7-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-27.9-47.5-55.2 31.3 59.7 101.7c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L84.9 262.9l-69 39.1C.7 310.7-4.6 329.8 4.2 344.8l79.6 135.6c8.8 15 28.3 20.1 43.5 11.5L624.1 210c15.2-8.6 20.4-27.8 11.6-42.8z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("tracks")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path === "/cards/"}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/cards/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											<path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												fill="currentColor"
 | 
				
			||||||
 | 
												d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("cards")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/scans/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/scans/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												fill="currentColor"
 | 
				
			||||||
 | 
												d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>Scans</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/contacts/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/contacts/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm10 4h4v2h-4v-2zm-3-5h7v2h-7v-2zm2-5h5v2h-5V7z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("contacts")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/scanstations/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/scanstations/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												fill="currentColor"
 | 
				
			||||||
 | 
												d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("scanstations")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/statsclients/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/statsclients/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												fill="currentColor"
 | 
				
			||||||
 | 
												d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("statsclients")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("USER:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/users/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/users/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											viewBox="0 0 24 24"
 | 
				
			||||||
 | 
											><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
											<path
 | 
				
			||||||
 | 
												d="M12 14v8H4a8 8 0 018-8zm0-1a6 6 0 110-12 6 6 0 010 12zm2.6 5.81a3.51 3.51 0 010-1.62l-1-.57 1-1.74 1 .58a3.5 3.5 0 011.4-.82V13.5h2v1.15a3.5 3.5 0 011.4.8l1-.57 1 1.74-1 .57a3.51 3.51 0 010 1.62l1 .57-1 1.74-1-.58a3.5 3.5 0 01-1.4.82v1.14h-2v-1.15a3.5 3.5 0 01-1.4-.8l-1 .57-1-1.74 1-.57zM18 17a1 1 0 100 2 1 1 0 000-2z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("users")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:GET")}
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class:activenav={$router.path.includes("/groups/")}
 | 
				
			||||||
 | 
										class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
										href="/groups/"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<svg
 | 
				
			||||||
 | 
											class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											width="24"
 | 
				
			||||||
 | 
											height="24"
 | 
				
			||||||
 | 
											xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
											viewBox="0 0 640 512"
 | 
				
			||||||
 | 
											><path
 | 
				
			||||||
 | 
												fill="currentColor"
 | 
				
			||||||
 | 
												d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
 | 
				
			||||||
 | 
											/></svg
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
										<span>{$_("user-groups")}</span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								<a
 | 
				
			||||||
 | 
									class:activenav={$router.path === "/settings/"}
 | 
				
			||||||
 | 
									class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
									href="/settings/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 20 20"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											fill-rule="evenodd"
 | 
				
			||||||
 | 
											d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z"
 | 
				
			||||||
 | 
											clip-rule="evenodd"
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
									</svg>
 | 
				
			||||||
 | 
									<span>{$_("settings")}</span>
 | 
				
			||||||
 | 
								</a>
 | 
				
			||||||
 | 
								<a
 | 
				
			||||||
 | 
									class:activenav={$router.path === "/about/"}
 | 
				
			||||||
 | 
									class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
									href="/about/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										fill="none"
 | 
				
			||||||
 | 
										stroke="currentColor"
 | 
				
			||||||
 | 
										stroke-width="2"
 | 
				
			||||||
 | 
										stroke-linecap="round"
 | 
				
			||||||
 | 
										stroke-linejoin="round"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										><circle cx="12" cy="12" r="10" />
 | 
				
			||||||
 | 
										<path d="M12 16v-4M12 8h.01" /></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
									<span>{$_("about")}</span>
 | 
				
			||||||
 | 
								</a>
 | 
				
			||||||
 | 
								<button
 | 
				
			||||||
 | 
									tabindex="0"
 | 
				
			||||||
 | 
									class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
 | 
				
			||||||
 | 
									on:click={() => {
 | 
				
			||||||
 | 
										AuthService.authControllerLogout();
 | 
				
			||||||
 | 
										logout();
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22zm7-6v-3h-8v-2h8V8l5 4-5 4z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
									<span>{$_("logout")}</span>
 | 
				
			||||||
 | 
								</button>
 | 
				
			||||||
 | 
							</nav>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<div class="ml-0 transition md:ml-60">
 | 
				
			||||||
 | 
							<header
 | 
				
			||||||
 | 
								class="flex items-center w-full px-4 bg-white border-b h-14 md:hidden"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<button
 | 
				
			||||||
 | 
									on:click={() => {
 | 
				
			||||||
 | 
										navOpen = true;
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
									class="block btn btn-light md:hidden"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<span class="sr-only">Menu</span><svg
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										fill="none"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										stroke-width="1.5"
 | 
				
			||||||
 | 
										stroke="currentColor"
 | 
				
			||||||
 | 
										class="size-6"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											stroke-linecap="round"
 | 
				
			||||||
 | 
											stroke-linejoin="round"
 | 
				
			||||||
 | 
											d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
									</svg>
 | 
				
			||||||
 | 
								</button>
 | 
				
			||||||
 | 
								<span class="inline-block">
 | 
				
			||||||
 | 
									<img src="/lfk-logo.png" alt="Logo" class="h-8 inline-block" />
 | 
				
			||||||
 | 
									<span class="text-lg font-bold">LfK!Admin</span>
 | 
				
			||||||
 | 
								</span>
 | 
				
			||||||
 | 
							</header>
 | 
				
			||||||
 | 
							<Toaster position="top-right" />
 | 
				
			||||||
 | 
							<slot>
 | 
				
			||||||
 | 
								<NoComponentLoaded />
 | 
				
			||||||
 | 
							</slot>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						{#if navOpen === true}
 | 
				
			||||||
 | 
							<button
 | 
				
			||||||
 | 
								on:click={() => {
 | 
				
			||||||
 | 
									navOpen = false;
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								class:hidden={!navOpen}
 | 
				
			||||||
 | 
								class="fixed inset-0 z-10 w-screen h-screen bg-black bg-opacity-25 md:hidden"
 | 
				
			||||||
 | 
							/>
 | 
				
			||||||
 | 
						{/if}
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
						.collapsed_navigation {
 | 
				
			||||||
 | 
							transform: translateX(-100%);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						@media (min-width: 768px) {
 | 
				
			||||||
 | 
							.collapsed_navigation {
 | 
				
			||||||
 | 
								transform: translateX(0px);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										263
									
								
								src/components/dashboard/MainDashContent.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								src/components/dashboard/MainDashContent.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,263 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
						import { StatsService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
						import store from "../../store";
 | 
				
			||||||
 | 
						import StatCard from "./StatCard.svelte";
 | 
				
			||||||
 | 
						const stats_promise = StatsService.statsControllerGet();
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="p-2 md:p-5 overflow-x-hidden">
 | 
				
			||||||
 | 
						<h4 class="mb-1 text-3xl font-extrabold leading-tight">
 | 
				
			||||||
 | 
							{$_("dashboard-greeting")}
 | 
				
			||||||
 | 
							<span class="text-blue-500"
 | 
				
			||||||
 | 
								>{store.state.jwtinfo.userdetails.firstname}
 | 
				
			||||||
 | 
								{store.state.jwtinfo.userdetails.lastname}</span
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
						</h4>
 | 
				
			||||||
 | 
						{#await stats_promise}
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
 | 
				
			||||||
 | 
								role="alert"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<p class="font-bold">{$_("stats-are-being-loaded")}</p>
 | 
				
			||||||
 | 
								<p class="text-sm">{$_("this-might-take-a-moment")}</p>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						{:then stats}
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								class="grid gap-1 grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 sm:gap-4"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("runners")}
 | 
				
			||||||
 | 
									value={stats.total_runners}
 | 
				
			||||||
 | 
									href="/runners/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										><path d="M0 0h24v24H0z" fill="none" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("total-scans")}
 | 
				
			||||||
 | 
									value={stats.total_scans}
 | 
				
			||||||
 | 
									href="/scans/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											fill="currentColor"
 | 
				
			||||||
 | 
											d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("total-donors")}
 | 
				
			||||||
 | 
									value={stats.total_donors}
 | 
				
			||||||
 | 
									href="/donors/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("total-donation-count")}
 | 
				
			||||||
 | 
									value={stats.total_donations}
 | 
				
			||||||
 | 
									href="/donations/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("average-donation")}
 | 
				
			||||||
 | 
									value={`${parseFloat(stats.average_donation / 100).toLocaleString(
 | 
				
			||||||
 | 
										undefined,
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											minimumFractionDigits: 2,
 | 
				
			||||||
 | 
											maximumFractionDigits: 2,
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									)}`}
 | 
				
			||||||
 | 
									href="/donations/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										><path d="M0 0h24v24H0z" fill="none" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("total-donations")}
 | 
				
			||||||
 | 
									value={`${parseFloat(stats.total_donation / 100).toLocaleString(
 | 
				
			||||||
 | 
										undefined,
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											minimumFractionDigits: 2,
 | 
				
			||||||
 | 
											maximumFractionDigits: 2,
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									)}`}
 | 
				
			||||||
 | 
									href="/donations/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										><path d="M0 0h24v24H0z" fill="none" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("total-distance")}
 | 
				
			||||||
 | 
									value={`${stats.total_distance / 1000}km`}
 | 
				
			||||||
 | 
									href="/scans/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										><path d="M0 0h24v24H0z" fill="none" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("average-distance")}
 | 
				
			||||||
 | 
									value={`${parseFloat(stats.average_distance / 1000).toLocaleString(
 | 
				
			||||||
 | 
										undefined,
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											minimumFractionDigits: 2,
 | 
				
			||||||
 | 
											maximumFractionDigits: 2,
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									)}km`}
 | 
				
			||||||
 | 
									href="/scans/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										><path d="M0 0h24v24H0z" fill="none" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("count_teams")}
 | 
				
			||||||
 | 
									value={stats.total_teams}
 | 
				
			||||||
 | 
									href="/teams/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										stroke="currentColor"
 | 
				
			||||||
 | 
										fill="none"
 | 
				
			||||||
 | 
										stroke-width="2"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										stroke-linecap="round"
 | 
				
			||||||
 | 
										stroke-linejoin="round"
 | 
				
			||||||
 | 
										size="24"
 | 
				
			||||||
 | 
										class="stroke-current text-grey-500"
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
 | 
				
			||||||
 | 
										<circle cx="9" cy="7" r="4" />
 | 
				
			||||||
 | 
										<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
 | 
				
			||||||
 | 
										<path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("count_organizations")}
 | 
				
			||||||
 | 
									value={stats.total_orgs}
 | 
				
			||||||
 | 
									href="/orgs/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M17 11V3H7v4H3v14h8v-4h2v4h8V11h-4zM7 19H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm4 4H9v-2h2v2zm0-4H9V9h2v2zm0-4H9V5h2v2zm4 8h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm4 12h-2v-2h2v2zm0-4h-2v-2h2v2z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_("runner_via_selfservice")}
 | 
				
			||||||
 | 
									value={stats.runnersViaSelfservice}
 | 
				
			||||||
 | 
									href="/runners/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										><path d="M0 0h24v24H0z" fill="none" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
								<StatCard
 | 
				
			||||||
 | 
									title={$_('runners_via_kiosk')}
 | 
				
			||||||
 | 
									value={stats.runnersViaKiosk}
 | 
				
			||||||
 | 
									href="/runners/"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<svg
 | 
				
			||||||
 | 
										height="24"
 | 
				
			||||||
 | 
										width="24"
 | 
				
			||||||
 | 
										fill="currentColor"
 | 
				
			||||||
 | 
										xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
										viewBox="0 0 24 24"
 | 
				
			||||||
 | 
										><path d="M0 0h24v24H0z" fill="none" />
 | 
				
			||||||
 | 
										<path
 | 
				
			||||||
 | 
											d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z"
 | 
				
			||||||
 | 
										/></svg
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</StatCard>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						{:catch error}
 | 
				
			||||||
 | 
							<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
 | 
				
			||||||
 | 
								<span class="inline-block align-middle mr-8">
 | 
				
			||||||
 | 
									<b>{$_("general_promise_error")}</b>
 | 
				
			||||||
 | 
									{error}
 | 
				
			||||||
 | 
								</span>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						{/await}
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
							
								
								
									
										21
									
								
								src/components/dashboard/StatCard.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/components/dashboard/StatCard.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export let href = "#";
 | 
				
			||||||
 | 
					  export let title = "";
 | 
				
			||||||
 | 
					  export let value = "";
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a {href}>
 | 
				
			||||||
 | 
					  <div class="p-3 py-4 sm:p-4 rounded-lg bg-white border border-grey-100">
 | 
				
			||||||
 | 
					    <div class="flex flex-row items-center justify-between">
 | 
				
			||||||
 | 
					      <div class="flex flex-col">
 | 
				
			||||||
 | 
					        <div class="text-md sm:text-xs uppercase font-normal text-grey-500">
 | 
				
			||||||
 | 
					          {title}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="text-2xl sm:text-xl font-bold font-mono">{value}</div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <slot />
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</a>
 | 
				
			||||||
@@ -1,24 +0,0 @@
 | 
				
			|||||||
export function getlang(langkeys) {
 | 
					 | 
				
			||||||
	return {
 | 
					 | 
				
			||||||
		search: {
 | 
					 | 
				
			||||||
			placeholder: langkeys.search
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		sort: {
 | 
					 | 
				
			||||||
			sortAsc: langkeys.sort_column_ascending,
 | 
					 | 
				
			||||||
			sortDesc: langkeys.sort_column_descending
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		pagination: {
 | 
					 | 
				
			||||||
			previous: langkeys.previous,
 | 
					 | 
				
			||||||
			next: langkeys.next,
 | 
					 | 
				
			||||||
			navigate: (page, pages) => `${langkeys.page} ${page} ${langkeys.of} ${pages}`,
 | 
					 | 
				
			||||||
			page: (page) => `${langkeys.page} ${page}`,
 | 
					 | 
				
			||||||
			showing: langkeys.showing,
 | 
					 | 
				
			||||||
			of: langkeys.of,
 | 
					 | 
				
			||||||
			to: langkeys.to,
 | 
					 | 
				
			||||||
			results: langkeys.records
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		loading: langkeys.loading,
 | 
					 | 
				
			||||||
		noRecordsFound: langkeys.no_matching_records_found,
 | 
					 | 
				
			||||||
		error: langkeys.an_error_happened_while_fetching_the_data
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										384
									
								
								src/components/donations/AddDonationModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								src/components/donations/AddDonationModal.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,384 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
						import { clickOutside } from "../base/outsideclick";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							DonationService,
 | 
				
			||||||
 | 
							DonorService,
 | 
				
			||||||
 | 
							RunnerService,
 | 
				
			||||||
 | 
						} from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
						import Select from "svelte-select";
 | 
				
			||||||
 | 
						import { createEventDispatcher, onMount } from "svelte";
 | 
				
			||||||
 | 
						import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
						export let modal_open;
 | 
				
			||||||
 | 
						const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
						const getDonorLabel = (option) =>
 | 
				
			||||||
 | 
							option.firstname + " " + (option.middlename || "") + " " + option.lastname;
 | 
				
			||||||
 | 
						const filterDonors = (label, filterText, option) =>
 | 
				
			||||||
 | 
							label.toLowerCase().includes(filterText.toLowerCase()) ||
 | 
				
			||||||
 | 
							option.value.id.toString().startsWith(filterText.toLowerCase());
 | 
				
			||||||
 | 
						$: donor = 0;
 | 
				
			||||||
 | 
						$: runner = 0;
 | 
				
			||||||
 | 
						$: donors = [];
 | 
				
			||||||
 | 
						$: runners = [];
 | 
				
			||||||
 | 
						$: type = "distance";
 | 
				
			||||||
 | 
						$: is_paid = false;
 | 
				
			||||||
 | 
						$: amount_input = 0;
 | 
				
			||||||
 | 
						$: processed_last_submit = true;
 | 
				
			||||||
 | 
						$: is_amount_valid = amount_input > 0;
 | 
				
			||||||
 | 
						$: createbtnenabled = is_amount_valid;
 | 
				
			||||||
 | 
						(() => {
 | 
				
			||||||
 | 
							document.onkeydown = (e) => {
 | 
				
			||||||
 | 
								e = e || window.event;
 | 
				
			||||||
 | 
								if (e.key === "Escape") {
 | 
				
			||||||
 | 
									modal_open = false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (e.keyCode === 13) {
 | 
				
			||||||
 | 
									if (createbtnenabled === true) {
 | 
				
			||||||
 | 
										createbtnenabled = false;
 | 
				
			||||||
 | 
										submit();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						})();
 | 
				
			||||||
 | 
						function submit() {
 | 
				
			||||||
 | 
							if (processed_last_submit === true) {
 | 
				
			||||||
 | 
								let amount_cent = Math.floor(amount_input * 100);
 | 
				
			||||||
 | 
								processed_last_submit = false;
 | 
				
			||||||
 | 
								toast.loading($_("adding-donation"));
 | 
				
			||||||
 | 
								if (type === "fixed") {
 | 
				
			||||||
 | 
									let postdata = {
 | 
				
			||||||
 | 
										donor,
 | 
				
			||||||
 | 
										amount: amount_cent,
 | 
				
			||||||
 | 
										paidAmount: 0,
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
									if (is_paid) {
 | 
				
			||||||
 | 
										postdata.paidAmount = amount_cent;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									DonationService.donationControllerPostFixed(postdata)
 | 
				
			||||||
 | 
										.then((result) => {
 | 
				
			||||||
 | 
											donor = donors[0].id || 0;
 | 
				
			||||||
 | 
											runner = runners[0].id || 0;
 | 
				
			||||||
 | 
											amount_input = 0;
 | 
				
			||||||
 | 
											modal_open = false;
 | 
				
			||||||
 | 
											//
 | 
				
			||||||
 | 
											toast.dismiss();
 | 
				
			||||||
 | 
											toast.success($_("donation_added"));
 | 
				
			||||||
 | 
											dispatch("created", { donations: [result] });
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.catch((err) => {
 | 
				
			||||||
 | 
											//
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.finally(() => {
 | 
				
			||||||
 | 
											processed_last_submit = true;
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
								} else if (type === "anonymous") {
 | 
				
			||||||
 | 
									let postdata = {
 | 
				
			||||||
 | 
										amount: amount_cent,
 | 
				
			||||||
 | 
										paidAmount: 0,
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
									if (is_paid) {
 | 
				
			||||||
 | 
										postdata.paidAmount = amount_cent;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									DonationService.donationControllerPostFixed(postdata)
 | 
				
			||||||
 | 
										.then((result) => {
 | 
				
			||||||
 | 
											amount_input = 0;
 | 
				
			||||||
 | 
											modal_open = false;
 | 
				
			||||||
 | 
											//
 | 
				
			||||||
 | 
											toast.dismiss();
 | 
				
			||||||
 | 
											toast.success($_("donation_added"));
 | 
				
			||||||
 | 
											dispatch("created", { donations: [result] });
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.catch((err) => {
 | 
				
			||||||
 | 
											//
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.finally(() => {
 | 
				
			||||||
 | 
											processed_last_submit = true;
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
								} else if (type === "distance") {
 | 
				
			||||||
 | 
									let postdata = {
 | 
				
			||||||
 | 
										donor,
 | 
				
			||||||
 | 
										runner,
 | 
				
			||||||
 | 
										amountPerDistance: amount_cent,
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
									DonationService.donationControllerPostDistance(postdata)
 | 
				
			||||||
 | 
										.then((result) => {
 | 
				
			||||||
 | 
											donor = donors[0].id || 0;
 | 
				
			||||||
 | 
											runner = runners[0].id || 0;
 | 
				
			||||||
 | 
											amount_input = 0;
 | 
				
			||||||
 | 
											modal_open = false;
 | 
				
			||||||
 | 
											//
 | 
				
			||||||
 | 
											toast.dismiss();
 | 
				
			||||||
 | 
											toast.success($_("donation_added"));
 | 
				
			||||||
 | 
											dispatch("created", { donations: [result] });
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.catch((err) => {
 | 
				
			||||||
 | 
											//
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.finally(() => {
 | 
				
			||||||
 | 
											processed_last_submit = true;
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						onMount(async () => {
 | 
				
			||||||
 | 
							donors = (await DonorService.donorControllerGetAll()).map((r) => {
 | 
				
			||||||
 | 
								return { label: getDonorLabel(r), value: r };
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							runners = (await RunnerService.runnerControllerGetAll()).map((r) => {
 | 
				
			||||||
 | 
								return { label: getDonorLabel(r), value: r };
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if modal_open}
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							class="fixed z-10 inset-0 overflow-y-hidden"
 | 
				
			||||||
 | 
							use:clickOutside
 | 
				
			||||||
 | 
							on:click_outside={() => {
 | 
				
			||||||
 | 
								modal_open = false;
 | 
				
			||||||
 | 
							}}
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								class="flex items-end justify-center h-screen text-center sm:block p-0 lg:p-4"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										class="absolute inset-0 bg-neutral-500 opacity-75"
 | 
				
			||||||
 | 
										data-id="modal_backdrop"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<span
 | 
				
			||||||
 | 
									class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
				
			||||||
 | 
									aria-hidden="true">​</span
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									class="inline-block align-bottom text-left shadow-xl transform transition-all sm:align-middle w-full lg:w-auto min-w-auto lg:min-w-[35vw] relative z-10"
 | 
				
			||||||
 | 
									role="dialog"
 | 
				
			||||||
 | 
									aria-modal="true"
 | 
				
			||||||
 | 
									aria-labelledby="modal-headline"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 rounded-t-xl">
 | 
				
			||||||
 | 
										<div class="">
 | 
				
			||||||
 | 
											<div
 | 
				
			||||||
 | 
												class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												<svg
 | 
				
			||||||
 | 
													class="size-6 text-blue-600"
 | 
				
			||||||
 | 
													fill="currentColor"
 | 
				
			||||||
 | 
													xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
													viewBox="0 0 24 24"
 | 
				
			||||||
 | 
													width="24"
 | 
				
			||||||
 | 
													height="24"
 | 
				
			||||||
 | 
													><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
													<path
 | 
				
			||||||
 | 
														d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
 | 
				
			||||||
 | 
													/></svg
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div class="mt-3">
 | 
				
			||||||
 | 
					              <h3 class="text-xl leading-6 font-medium text-neutral-900">
 | 
				
			||||||
 | 
					                Sponsoring erstellen
 | 
				
			||||||
 | 
					              </h3>
 | 
				
			||||||
 | 
												<nav
 | 
				
			||||||
 | 
													class="relative z-0 flex border border-neutral-200 rounded-xl overflow-hidden mb-2"
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<button
 | 
				
			||||||
 | 
														on:click={() => {
 | 
				
			||||||
 | 
															type = "distance";
 | 
				
			||||||
 | 
														}}
 | 
				
			||||||
 | 
														type="button"
 | 
				
			||||||
 | 
														id="bar-with-underline-item-1"
 | 
				
			||||||
 | 
														class:donation_active_tab={type === "distance"}
 | 
				
			||||||
 | 
														class:donation_inactive_tab={type !== "distance"}
 | 
				
			||||||
 | 
														aria-selected={type === "distance"}
 | 
				
			||||||
 | 
														role="tab"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														{$_("spende_pro_km")}
 | 
				
			||||||
 | 
													</button>
 | 
				
			||||||
 | 
													<button
 | 
				
			||||||
 | 
														on:click={() => {
 | 
				
			||||||
 | 
															type = "fixed";
 | 
				
			||||||
 | 
														}}
 | 
				
			||||||
 | 
														type="button"
 | 
				
			||||||
 | 
														id="bar-with-underline-item-2"
 | 
				
			||||||
 | 
														class:donation_active_tab={type === "fixed"}
 | 
				
			||||||
 | 
														class:donation_inactive_tab={type !== "fixed"}
 | 
				
			||||||
 | 
														aria-selected={type === "fixed"}
 | 
				
			||||||
 | 
														role="tab"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														{$_("festbetrag")}
 | 
				
			||||||
 | 
													</button>
 | 
				
			||||||
 | 
													<button
 | 
				
			||||||
 | 
														on:click={() => {
 | 
				
			||||||
 | 
															type = "anonymous";
 | 
				
			||||||
 | 
														}}
 | 
				
			||||||
 | 
														type="button"
 | 
				
			||||||
 | 
														id="bar-with-underline-item-3"
 | 
				
			||||||
 | 
														class:donation_active_tab={type === "anonymous"}
 | 
				
			||||||
 | 
														class:donation_inactive_tab={type !== "anonymous"}
 | 
				
			||||||
 | 
														aria-selected={type === "anonymous"}
 | 
				
			||||||
 | 
														role="tab"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														{$_("anonyme_spende")}
 | 
				
			||||||
 | 
													</button>
 | 
				
			||||||
 | 
												</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												<div class="grid grid-cols-6 gap-2 lg:gap-6 text-left">
 | 
				
			||||||
 | 
													{#if type === "anonymous"}
 | 
				
			||||||
 | 
														<div class="col-span-6">
 | 
				
			||||||
 | 
															<label
 | 
				
			||||||
 | 
																for="donation_amount_eur"
 | 
				
			||||||
 | 
																class="block text-sm font-medium text-neutral-900"
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
																{$_("donation-amount")}</label
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
															<div class="mt-1 flex rounded-md shadow-sm">
 | 
				
			||||||
 | 
																<input
 | 
				
			||||||
 | 
																	autocomplete="off"
 | 
				
			||||||
 | 
																	class:border-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
																	class:focus:border-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
																	class:focus:ring-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
																	bind:value={amount_input}
 | 
				
			||||||
 | 
																	type="number"
 | 
				
			||||||
 | 
																	step="0.01"
 | 
				
			||||||
 | 
																	name="donation_amount_eur"
 | 
				
			||||||
 | 
																	class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 p-2"
 | 
				
			||||||
 | 
																	placeholder="2.00"
 | 
				
			||||||
 | 
																/>
 | 
				
			||||||
 | 
																<span
 | 
				
			||||||
 | 
																	class="inline-flex items-center px-3 rounded-r-md border border-neutral-300 bg-neutral-50 text-neutral-500 text-sm"
 | 
				
			||||||
 | 
																	>€</span
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
															{#if !is_amount_valid}
 | 
				
			||||||
 | 
																<span
 | 
				
			||||||
 | 
																	class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
																	{$_("donation-amount-must-be-greater-that-0-00eur")}
 | 
				
			||||||
 | 
																</span>
 | 
				
			||||||
 | 
															{/if}
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
													{:else}
 | 
				
			||||||
 | 
														<div class="col-span-6">
 | 
				
			||||||
 | 
															<label
 | 
				
			||||||
 | 
																for="donor"
 | 
				
			||||||
 | 
																class="block text-sm font-medium text-neutral-900"
 | 
				
			||||||
 | 
																>{$_("donor")}</label
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
															<Select
 | 
				
			||||||
 | 
																containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
																itemFilter={(label, filterText, option) =>
 | 
				
			||||||
 | 
																	filterDonors(label, filterText, option)}
 | 
				
			||||||
 | 
																items={donors}
 | 
				
			||||||
 | 
																showChevron={true}
 | 
				
			||||||
 | 
																placeholder={$_("search-for-donor-name-or-id")}
 | 
				
			||||||
 | 
																noOptionsMessage={$_("no-donors-found")}
 | 
				
			||||||
 | 
																on:select={(selectedValue) =>
 | 
				
			||||||
 | 
																	(donor = selectedValue.detail.value.id)}
 | 
				
			||||||
 | 
																on:clear={() => (donors = null)}
 | 
				
			||||||
 | 
															/>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														{#if type === "distance"}
 | 
				
			||||||
 | 
															<div class="col-span-6">
 | 
				
			||||||
 | 
																<label
 | 
				
			||||||
 | 
																	for="donor"
 | 
				
			||||||
 | 
																	class="block text-sm font-medium text-neutral-900"
 | 
				
			||||||
 | 
																	>{$_("runner")}</label
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
																<Select
 | 
				
			||||||
 | 
																	containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
																	itemFilter={(label, filterText, option) =>
 | 
				
			||||||
 | 
																		filterDonors(label, filterText, option)}
 | 
				
			||||||
 | 
																	items={runners}
 | 
				
			||||||
 | 
																	showChevron={true}
 | 
				
			||||||
 | 
																	placeholder={$_("search-for-runner-by-name-or-id")}
 | 
				
			||||||
 | 
																	noOptionsMessage={$_("no-runners-found")}
 | 
				
			||||||
 | 
																	on:select={(selectedValue) =>
 | 
				
			||||||
 | 
																		(runner = selectedValue.detail.value.id)}
 | 
				
			||||||
 | 
																	on:clear={() => (runner = null)}
 | 
				
			||||||
 | 
																/>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														{/if}
 | 
				
			||||||
 | 
														<div class="col-span-6">
 | 
				
			||||||
 | 
															<label
 | 
				
			||||||
 | 
																for="donation_amount_eur"
 | 
				
			||||||
 | 
																class="block text-sm font-medium text-neutral-900"
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
																{#if type === "fixed"}
 | 
				
			||||||
 | 
																	{$_("donation-amount")}
 | 
				
			||||||
 | 
																{:else}{$_("amount-per-kilometer")}{/if}</label
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
															<div class="mt-1 flex rounded-md shadow-sm">
 | 
				
			||||||
 | 
																<input
 | 
				
			||||||
 | 
																	autocomplete="off"
 | 
				
			||||||
 | 
																	class:border-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
																	class:focus:border-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
																	class:focus:ring-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
																	bind:value={amount_input}
 | 
				
			||||||
 | 
																	type="number"
 | 
				
			||||||
 | 
																	step="0.01"
 | 
				
			||||||
 | 
																	name="donation_amount_eur"
 | 
				
			||||||
 | 
																	class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 p-2"
 | 
				
			||||||
 | 
																	placeholder="2.00"
 | 
				
			||||||
 | 
																/>
 | 
				
			||||||
 | 
																<span
 | 
				
			||||||
 | 
																	class="inline-flex items-center px-3 rounded-r-md border border-neutral-300 bg-neutral-50 text-neutral-500 text-sm"
 | 
				
			||||||
 | 
																	>€</span
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
															{#if !is_amount_valid}
 | 
				
			||||||
 | 
																<span
 | 
				
			||||||
 | 
																	class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
																	{$_("donation-amount-must-be-greater-that-0-00eur")}
 | 
				
			||||||
 | 
																</span>
 | 
				
			||||||
 | 
															{/if}
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
													{/if}
 | 
				
			||||||
 | 
													{#if type === "fixed" || type === "anonymous"}
 | 
				
			||||||
 | 
														<div class="flex">
 | 
				
			||||||
 | 
															<input
 | 
				
			||||||
 | 
																bind:checked={is_paid}
 | 
				
			||||||
 | 
																type="checkbox"
 | 
				
			||||||
 | 
																class="shrink-0 mt-0.5 border-neutral-200 rounded-sm text-blue-600 focus:ring-blue-500 checked:border-blue-500 disabled:opacity-50 disabled:pointer-events-none"
 | 
				
			||||||
 | 
																id="hs-default-checkbox"
 | 
				
			||||||
 | 
															/>
 | 
				
			||||||
 | 
															<label
 | 
				
			||||||
 | 
																for="hs-default-checkbox"
 | 
				
			||||||
 | 
																class="text-base text-neutral-900 ms-2 font-medium"
 | 
				
			||||||
 | 
																>{$_("already-paid")}</label
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
													{/if}
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										class="bg-neutral-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<button
 | 
				
			||||||
 | 
											disabled={!createbtnenabled}
 | 
				
			||||||
 | 
											class:opacity-50={!createbtnenabled}
 | 
				
			||||||
 | 
											on:click={submit}
 | 
				
			||||||
 | 
											type="button"
 | 
				
			||||||
 | 
											class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											{$_("create")}
 | 
				
			||||||
 | 
										</button>
 | 
				
			||||||
 | 
										<button
 | 
				
			||||||
 | 
											on:click={() => {
 | 
				
			||||||
 | 
												modal_open = false;
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
											type="button"
 | 
				
			||||||
 | 
											class="w-full justify-center rounded-md border border-neutral-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-neutral-900 hover:bg-neutral-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 hidden lg:block"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											{$_("cancel")}
 | 
				
			||||||
 | 
										</button>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										205
									
								
								src/components/donations/AddDonationPaymentModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								src/components/donations/AddDonationPaymentModal.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,205 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { clickOutside } from "../base/outsideclick";
 | 
				
			||||||
 | 
					  import { DonationService } from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
					  import { createEventDispatcher } from "svelte";
 | 
				
			||||||
 | 
					  import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
					  export let payment_modal_open = false;
 | 
				
			||||||
 | 
					  export let original_data = {};
 | 
				
			||||||
 | 
					  export let paid_amount_input = 0;
 | 
				
			||||||
 | 
					  const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					  $: processed_last_submit = true;
 | 
				
			||||||
 | 
					  $: createbtnenabled =
 | 
				
			||||||
 | 
					    is_paid_amount_valid &&
 | 
				
			||||||
 | 
					    !(paid_amount_input * 100 == original_data.paidAmount);
 | 
				
			||||||
 | 
					  $: is_paid_amount_valid = paid_amount_input > 0;
 | 
				
			||||||
 | 
					  (() => {
 | 
				
			||||||
 | 
					    document.onkeydown = (e) => {
 | 
				
			||||||
 | 
					      e = e || window.event;
 | 
				
			||||||
 | 
					      if (e.key === "Escape") {
 | 
				
			||||||
 | 
					        payment_modal_open = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (e.keyCode === 13) {
 | 
				
			||||||
 | 
					        if (createbtnenabled === true) {
 | 
				
			||||||
 | 
					          createbtnenabled = false;
 | 
				
			||||||
 | 
					          submit();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					  function submit() {
 | 
				
			||||||
 | 
					    if (processed_last_submit === true) {
 | 
				
			||||||
 | 
					      processed_last_submit = false;
 | 
				
			||||||
 | 
					      toast.loading($_("updating-donation"));
 | 
				
			||||||
 | 
					      const editable = Object.assign({}, original_data);
 | 
				
			||||||
 | 
					      editable.donor = editable.donor.id;
 | 
				
			||||||
 | 
					      editable.paidAmount = Math.round(paid_amount_input * 100);
 | 
				
			||||||
 | 
					      if (editable.responseType == "DISTANCEDONATION" || editable.runner) {
 | 
				
			||||||
 | 
					        editable.runner = editable.runner.id;
 | 
				
			||||||
 | 
					        DonationService.donationControllerPutDistance(
 | 
				
			||||||
 | 
					          original_data.id,
 | 
				
			||||||
 | 
					          editable
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					          .then((result) => {
 | 
				
			||||||
 | 
					            payment_modal_open = false;
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					            toast.dismiss();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            toast.success($_("donation-updated"));
 | 
				
			||||||
 | 
					            dispatch("created", { donation: result });
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .catch((err) => {
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .finally(() => {
 | 
				
			||||||
 | 
					            processed_last_submit = true;
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        DonationService.donationControllerPutFixed(original_data.id, editable)
 | 
				
			||||||
 | 
					          .then((result) => {
 | 
				
			||||||
 | 
					            payment_modal_open = false;
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					            toast.dismiss();
 | 
				
			||||||
 | 
					            toast.success($_("donation-updated"));
 | 
				
			||||||
 | 
					            dispatch("created", { donation: result });
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .catch((err) => {
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .finally(() => {
 | 
				
			||||||
 | 
					            processed_last_submit = true;
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if payment_modal_open}
 | 
				
			||||||
 | 
					  <div
 | 
				
			||||||
 | 
					    class="fixed z-10 inset-0 overflow-y-hidden"
 | 
				
			||||||
 | 
					    use:clickOutside
 | 
				
			||||||
 | 
					    on:click_outside={() => {
 | 
				
			||||||
 | 
					      payment_modal_open = false;
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      class="flex items-end justify-center h-screen text-center sm:block p-0 lg:p-4"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          class="absolute inset-0 bg-gray-500 opacity-75"
 | 
				
			||||||
 | 
					          data-id="modal_backdrop"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <span
 | 
				
			||||||
 | 
					        class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
				
			||||||
 | 
					        aria-hidden="true">​</span
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        class="inline-block align-bottom text-left shadow-xl transform transition-all sm:align-middle w-full lg:w-auto min-w-auto lg:min-w-[35vw] relative z-10"
 | 
				
			||||||
 | 
					        role="dialog"
 | 
				
			||||||
 | 
					        aria-modal="true"
 | 
				
			||||||
 | 
					        aria-labelledby="modal-headline"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 rounded-t-xl">
 | 
				
			||||||
 | 
					          <div class="">
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <svg
 | 
				
			||||||
 | 
					                class="size-6 text-blue-600"
 | 
				
			||||||
 | 
					                fill="currentColor"
 | 
				
			||||||
 | 
					                xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					                viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                width="24"
 | 
				
			||||||
 | 
					                height="24"
 | 
				
			||||||
 | 
					                ><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
					                <path
 | 
				
			||||||
 | 
					                  fill="currentColor"
 | 
				
			||||||
 | 
					                  d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
 | 
				
			||||||
 | 
					                /></svg
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="mt-3 text-left">
 | 
				
			||||||
 | 
					              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					                {$_("enter-payment")}
 | 
				
			||||||
 | 
					              </h3>
 | 
				
			||||||
 | 
					              <div class="mb-6">
 | 
				
			||||||
 | 
					                <p class="text-sm text-gray-500">
 | 
				
			||||||
 | 
					                  {$_(
 | 
				
			||||||
 | 
					                    "you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount"
 | 
				
			||||||
 | 
					                  )}
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div class="grid grid-cols gap-2 lg:gap-6">
 | 
				
			||||||
 | 
					                <div class="w-full">
 | 
				
			||||||
 | 
					                  <label
 | 
				
			||||||
 | 
					                    for="token"
 | 
				
			||||||
 | 
					                    class="block text-sm font-medium text-gray-700"
 | 
				
			||||||
 | 
					                    >{$_("paid-amount")}</label
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <div
 | 
				
			||||||
 | 
					                    class="inline-flex border-gray-300 border rounded-l-md rounded-r-md bg-gray-50 text-gray-500 w-full"
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                    <input
 | 
				
			||||||
 | 
					                      autocomplete="off"
 | 
				
			||||||
 | 
					                      class:border-red-500={!is_paid_amount_valid}
 | 
				
			||||||
 | 
					                      class:focus:border-red-500={!is_paid_amount_valid}
 | 
				
			||||||
 | 
					                      class:focus:ring-red-500={!is_paid_amount_valid}
 | 
				
			||||||
 | 
					                      bind:value={paid_amount_input}
 | 
				
			||||||
 | 
					                      type="number"
 | 
				
			||||||
 | 
					                      step="0.01"
 | 
				
			||||||
 | 
					                      name="donation_amount_eur"
 | 
				
			||||||
 | 
					                      class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm p-2"
 | 
				
			||||||
 | 
					                      placeholder="2.00"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    <button
 | 
				
			||||||
 | 
					                      on:click={() => {
 | 
				
			||||||
 | 
					                        paid_amount_input = paid_amount_input = (
 | 
				
			||||||
 | 
					                          original_data.amount / 100
 | 
				
			||||||
 | 
					                        ).toFixed(2);
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
 | 
					                      class="inline-flex items-center p-r-2 text-indigo-300 hover:text-indigo-700 text-sm"
 | 
				
			||||||
 | 
					                      >MAX</button
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                      class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
 | 
				
			||||||
 | 
					                      >€</span
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  {#if !is_paid_amount_valid}
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                      class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {$_("payment-amount-must-be-greater-than-0-00eur")}
 | 
				
			||||||
 | 
					                    </span>
 | 
				
			||||||
 | 
					                  {/if}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="bg-gray-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10">
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            disabled={!createbtnenabled}
 | 
				
			||||||
 | 
					            class:opacity-50={!createbtnenabled}
 | 
				
			||||||
 | 
					            on:click={submit}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("save-changes")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={() => {
 | 
				
			||||||
 | 
					              payment_modal_open = false;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            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"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("cancel")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										117
									
								
								src/components/donations/DeleteDonationModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/components/donations/DeleteDonationModal.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import { clickOutside } from "../base/outsideclick";
 | 
				
			||||||
 | 
					  import { createEventDispatcher, onMount } from "svelte";
 | 
				
			||||||
 | 
					  export let modal_open;
 | 
				
			||||||
 | 
					  export let delete_donation = {
 | 
				
			||||||
 | 
					    id: 0,
 | 
				
			||||||
 | 
					    runner: {
 | 
				
			||||||
 | 
					      firstname: "",
 | 
				
			||||||
 | 
					      lastname: "",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    donor: {
 | 
				
			||||||
 | 
					      firstname: "",
 | 
				
			||||||
 | 
					      lastname: "",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					  onMount(() => {
 | 
				
			||||||
 | 
					    document.onkeydown = (e) => {
 | 
				
			||||||
 | 
					      e = e || window.event;
 | 
				
			||||||
 | 
					      if (e.key === "Escape") {
 | 
				
			||||||
 | 
					        modal_open = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (e.keyCode === 13) {
 | 
				
			||||||
 | 
					        if (createbtnenabled === true) {
 | 
				
			||||||
 | 
					          createbtnenabled = false;
 | 
				
			||||||
 | 
					          submit();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  async function submit() {
 | 
				
			||||||
 | 
					    dispatch("delete", { id: delete_donation.id });
 | 
				
			||||||
 | 
					    modal_open = false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if modal_open}
 | 
				
			||||||
 | 
					  <div
 | 
				
			||||||
 | 
					    class="fixed z-10 inset-0 overflow-y-hidden"
 | 
				
			||||||
 | 
					    use:clickOutside
 | 
				
			||||||
 | 
					    on:click_outside={() => {
 | 
				
			||||||
 | 
					      modal_open = false;
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      class="flex items-end justify-center h-screen text-center sm:block p-0 lg:p-4"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <div class="fixed inset-0 transition-opacity" aria-hidden="true">
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          class="absolute inset-0 bg-gray-500 opacity-75"
 | 
				
			||||||
 | 
					          data-id="modal_backdrop"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <span
 | 
				
			||||||
 | 
					        class="hidden sm:inline-block sm:align-middle sm:h-screen"
 | 
				
			||||||
 | 
					        aria-hidden="true">​</span
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        class="inline-block align-bottom text-left shadow-xl transform transition-all sm:align-middle w-full lg:w-auto min-w-auto lg:min-w-[35vw] relative z-10"
 | 
				
			||||||
 | 
					        role="dialog"
 | 
				
			||||||
 | 
					        aria-modal="true"
 | 
				
			||||||
 | 
					        aria-labelledby="modal-headline"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 rounded-t-xl">
 | 
				
			||||||
 | 
					          <div class="">
 | 
				
			||||||
 | 
					            <div
 | 
				
			||||||
 | 
					              class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <svg
 | 
				
			||||||
 | 
					                class="size-6 text-blue-600"
 | 
				
			||||||
 | 
					                fill="currentColor"
 | 
				
			||||||
 | 
					                xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					                viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                width="24"
 | 
				
			||||||
 | 
					                height="24"
 | 
				
			||||||
 | 
					                ><path fill="none" d="M0 0h24v24H0z" />
 | 
				
			||||||
 | 
					                <path
 | 
				
			||||||
 | 
					                  d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
 | 
				
			||||||
 | 
					                /></svg
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="mt-3 sm:text-left max-h-[75vh] overflow-y-auto">
 | 
				
			||||||
 | 
					              <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					                {$_("please-confirm-the-deletion-of-donation")}
 | 
				
			||||||
 | 
					              </h3>
 | 
				
			||||||
 | 
					              <div class="w-full">
 | 
				
			||||||
 | 
					                <span class="inline-block"
 | 
				
			||||||
 | 
					                  ><b>{$_("donor")}</b>: {delete_donation.donor.firstname}
 | 
				
			||||||
 | 
					                  {delete_donation.donor.lastname}</span
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="bg-gray-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10">
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={submit}
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-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"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("delete")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button
 | 
				
			||||||
 | 
					            on:click={() => {
 | 
				
			||||||
 | 
					              modal_open = false;
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            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"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {$_("cancel")}
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										352
									
								
								src/components/donations/DonationDetail.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								src/components/donations/DonationDetail.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,352 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
						import store from "../../store";
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							DonationService,
 | 
				
			||||||
 | 
							DonorService,
 | 
				
			||||||
 | 
							RunnerService,
 | 
				
			||||||
 | 
						} from "@odit/lfk-client-js";
 | 
				
			||||||
 | 
						import toast from "svelte-french-toast";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						import PromiseError from "../base/PromiseError.svelte";
 | 
				
			||||||
 | 
						import Select from "svelte-select";
 | 
				
			||||||
 | 
						let data_loaded = false;
 | 
				
			||||||
 | 
						export let params;
 | 
				
			||||||
 | 
						$: delete_triggered = false;
 | 
				
			||||||
 | 
						$: original_data = {};
 | 
				
			||||||
 | 
						$: editable = {};
 | 
				
			||||||
 | 
						$: donor = {};
 | 
				
			||||||
 | 
						$: runner = {};
 | 
				
			||||||
 | 
						$: current_donors = [];
 | 
				
			||||||
 | 
						$: current_runners = [];
 | 
				
			||||||
 | 
						$: amount_input = 0;
 | 
				
			||||||
 | 
						$: is_amount_valid = amount_input > 0;
 | 
				
			||||||
 | 
						$: paid_amount_input = 0;
 | 
				
			||||||
 | 
						$: is_paid_amount_valid = paid_amount_input > 0;
 | 
				
			||||||
 | 
						$: is_everything_set =
 | 
				
			||||||
 | 
							editable.donor != null &&
 | 
				
			||||||
 | 
							((original_data.responseType == "DISTANCEDONATION" &&
 | 
				
			||||||
 | 
								editable?.runner != null) ||
 | 
				
			||||||
 | 
								original_data.responseType !== "DISTANCEDONATION");
 | 
				
			||||||
 | 
						$: changes_performed =
 | 
				
			||||||
 | 
							!(JSON.stringify(original_data) === JSON.stringify(editable)) ||
 | 
				
			||||||
 | 
							(original_data.responseType == "DISTANCEDONATION" &&
 | 
				
			||||||
 | 
								!(Math.floor(amount_input * 100) === original_data.amountPerDistance)) ||
 | 
				
			||||||
 | 
							(original_data.responseType !== "DISTANCEDONATION" &&
 | 
				
			||||||
 | 
								!(Math.floor(amount_input * 100) === original_data.amount)) ||
 | 
				
			||||||
 | 
							!(Math.floor(paid_amount_input * 100) === original_data.paidAmount);
 | 
				
			||||||
 | 
						$: save_enabled = changes_performed && is_amount_valid && is_everything_set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const promise = DonationService.donationControllerGetOne(
 | 
				
			||||||
 | 
							params.donationid
 | 
				
			||||||
 | 
						).then((data) => {
 | 
				
			||||||
 | 
							data_loaded = true;
 | 
				
			||||||
 | 
							original_data = Object.assign({}, data);
 | 
				
			||||||
 | 
							editable = Object.assign({}, original_data);
 | 
				
			||||||
 | 
							paid_amount_input = data.paidAmount / 100;
 | 
				
			||||||
 | 
							if (data.responseType == "DISTANCEDONATION") {
 | 
				
			||||||
 | 
								amount_input = data.amountPerDistance / 100;
 | 
				
			||||||
 | 
								RunnerService.runnerControllerGetAll().then((val) => {
 | 
				
			||||||
 | 
									current_runners = val.map((r) => {
 | 
				
			||||||
 | 
										return { label: getDonorLabel(r), value: r };
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
									runner = current_runners.find((g) => g.value.id == editable.runner.id);
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								amount_input = data.amount / 100;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							DonorService.donorControllerGetAll().then((val) => {
 | 
				
			||||||
 | 
								current_donors = val.map((r) => {
 | 
				
			||||||
 | 
									return { label: getDonorLabel(r), value: r };
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								donor = current_donors.find((g) => g.value.id == editable.donor.id);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						const getDonorLabel = (option) =>
 | 
				
			||||||
 | 
							option.firstname + " " + (option.middlename || "") + " " + option.lastname;
 | 
				
			||||||
 | 
						const filterDonors = (label, filterText, option) =>
 | 
				
			||||||
 | 
							label.toLowerCase().includes(filterText.toLowerCase()) ||
 | 
				
			||||||
 | 
							option.value.id.toString().startsWith(filterText.toLowerCase());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function submit() {
 | 
				
			||||||
 | 
							if (data_loaded === true && save_enabled) {
 | 
				
			||||||
 | 
								toast($_("updating-donation"));
 | 
				
			||||||
 | 
								let postdata = {};
 | 
				
			||||||
 | 
								editable.paidAmount = paid_amount_input * 100;
 | 
				
			||||||
 | 
								if (original_data.responseType === "DISTANCEDONATION") {
 | 
				
			||||||
 | 
									editable.amountPerDistance = Math.floor(amount_input * 100);
 | 
				
			||||||
 | 
									postdata = Object.assign(postdata, editable);
 | 
				
			||||||
 | 
									postdata.runner = postdata.runner.id;
 | 
				
			||||||
 | 
									postdata.donor = postdata.donor.id;
 | 
				
			||||||
 | 
									DonationService.donationControllerPutDistance(
 | 
				
			||||||
 | 
										original_data.id,
 | 
				
			||||||
 | 
										postdata
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
										.then((resp) => {
 | 
				
			||||||
 | 
											Object.assign(original_data, editable);
 | 
				
			||||||
 | 
											original_data = original_data;
 | 
				
			||||||
 | 
											toast.success($_("donation-updated"));
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.catch((err) => {});
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									editable.amount = Math.floor(amount_input * 100);
 | 
				
			||||||
 | 
									postdata = Object.assign(postdata, editable);
 | 
				
			||||||
 | 
									postdata.donor = postdata.donor.id;
 | 
				
			||||||
 | 
									DonationService.donationControllerPutFixed(original_data.id, postdata)
 | 
				
			||||||
 | 
										.then((resp) => {
 | 
				
			||||||
 | 
											Object.assign(original_data, editable);
 | 
				
			||||||
 | 
											original_data = original_data;
 | 
				
			||||||
 | 
											toast.success($_("donation-updated"));
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.catch((err) => {});
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						function deleteDonation() {
 | 
				
			||||||
 | 
							DonationService.donationControllerRemove(original_data.id, false)
 | 
				
			||||||
 | 
								.then((resp) => {
 | 
				
			||||||
 | 
									toast.success($_("donation-deleted"));
 | 
				
			||||||
 | 
									location.replace("./");
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.catch((err) => {
 | 
				
			||||||
 | 
									modal_open = true;
 | 
				
			||||||
 | 
									delete_donor = original_data;
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#await promise}
 | 
				
			||||||
 | 
						{$_("loading-donation-details")}
 | 
				
			||||||
 | 
					{:then}
 | 
				
			||||||
 | 
						<section class="container p-5 select-none">
 | 
				
			||||||
 | 
							<div class="flex flex-row mb-4">
 | 
				
			||||||
 | 
								<div class="mt-2 w-full">
 | 
				
			||||||
 | 
									<nav class="w-full flex">
 | 
				
			||||||
 | 
										<ol class="list-none flex flex-row items-center justify-start">
 | 
				
			||||||
 | 
											<li class="flex items-center">
 | 
				
			||||||
 | 
												<a class="mr-2" href="./"
 | 
				
			||||||
 | 
													><svg
 | 
				
			||||||
 | 
														xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
														width="24"
 | 
				
			||||||
 | 
														height="24"
 | 
				
			||||||
 | 
														viewBox="0 0 24 24"
 | 
				
			||||||
 | 
														fill="none"
 | 
				
			||||||
 | 
														stroke="currentColor"
 | 
				
			||||||
 | 
														stroke-width="2"
 | 
				
			||||||
 | 
														stroke-linecap="round"
 | 
				
			||||||
 | 
														stroke-linejoin="round"
 | 
				
			||||||
 | 
														class="inline-block"
 | 
				
			||||||
 | 
														><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
													{$_("donations")}</a
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
											</li>
 | 
				
			||||||
 | 
										</ol>
 | 
				
			||||||
 | 
									</nav>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="mb-4 text-3xl font-extrabold leading-tight">
 | 
				
			||||||
 | 
								{original_data.donor.firstname}
 | 
				
			||||||
 | 
								{original_data.donor.middlename || ""}
 | 
				
			||||||
 | 
								{original_data.donor.lastname}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								{#if original_data.responseType == "DISTANCEDONATION"}
 | 
				
			||||||
 | 
									{original_data.runner.firstname}
 | 
				
			||||||
 | 
									{original_data.runner.middlename || ""}
 | 
				
			||||||
 | 
									{original_data.runner.lastname}
 | 
				
			||||||
 | 
								{:else}
 | 
				
			||||||
 | 
									{$_("fixed-donation")}:
 | 
				
			||||||
 | 
									{amount_input.toFixed(2).toLocaleString("de-DE", { valute: "EUR" })}€
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
								[#{original_data.id}]
 | 
				
			||||||
 | 
								<div data-id="donation_actions_${original_data.id}">
 | 
				
			||||||
 | 
									{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:DELETE")}
 | 
				
			||||||
 | 
										{#if delete_triggered}
 | 
				
			||||||
 | 
											<button
 | 
				
			||||||
 | 
												on:click={deleteDonation}
 | 
				
			||||||
 | 
												class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm"
 | 
				
			||||||
 | 
												>{$_("confirm-deletion")}</button
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
											<button
 | 
				
			||||||
 | 
												on:click={() => {
 | 
				
			||||||
 | 
													delete_triggered = !delete_triggered;
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
												class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
 | 
				
			||||||
 | 
												>{$_("cancel")}</button
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
										{/if}
 | 
				
			||||||
 | 
										{#if !delete_triggered}
 | 
				
			||||||
 | 
											<button
 | 
				
			||||||
 | 
												on:click={() => {
 | 
				
			||||||
 | 
													delete_triggered = true;
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
												type="button"
 | 
				
			||||||
 | 
												class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm"
 | 
				
			||||||
 | 
												>{$_("delete-donation")}</button
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
										{/if}
 | 
				
			||||||
 | 
									{/if}
 | 
				
			||||||
 | 
									{#if !delete_triggered}
 | 
				
			||||||
 | 
										<button
 | 
				
			||||||
 | 
											disabled={!save_enabled}
 | 
				
			||||||
 | 
											class:opacity-50={!save_enabled}
 | 
				
			||||||
 | 
											type="button"
 | 
				
			||||||
 | 
											on:click={submit}
 | 
				
			||||||
 | 
											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"
 | 
				
			||||||
 | 
											>{$_("save-changes")}</button
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
									{/if}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<!--  -->
 | 
				
			||||||
 | 
							<div>
 | 
				
			||||||
 | 
								<span class="font-semibold text-gray-700"
 | 
				
			||||||
 | 
									>{$_("total-donation-amount")}:</span
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<span
 | 
				
			||||||
 | 
									>{(editable.amount / 100)
 | 
				
			||||||
 | 
										.toFixed(2)
 | 
				
			||||||
 | 
										.toLocaleString("de-DE", { valute: "EUR" })}€</span
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								|
 | 
				
			||||||
 | 
								<span class="font-semibold text-gray-700">{$_("paid-amount")}:</span>
 | 
				
			||||||
 | 
								<span
 | 
				
			||||||
 | 
									>{(editable.paidAmount / 100)
 | 
				
			||||||
 | 
										.toFixed(2)
 | 
				
			||||||
 | 
										.toLocaleString("de-DE", { valute: "EUR" })}€</span
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								|
 | 
				
			||||||
 | 
								<span class="font-semibold text-gray-700">{$_("status")}:</span>
 | 
				
			||||||
 | 
								{#if editable.status == "PAID"}
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
 | 
				
			||||||
 | 
										>{$_("paid")}</span
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								{:else}
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-red-100 text-red-800"
 | 
				
			||||||
 | 
										>{$_("open")}</span
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<br />
 | 
				
			||||||
 | 
							<div class=" mt-2 w-full">
 | 
				
			||||||
 | 
								<label for="donor" class="block font-semibold text-gray-700"
 | 
				
			||||||
 | 
									>{$_("donor")}</label
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<Select
 | 
				
			||||||
 | 
									containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
									itemFilter={(label, filterText, option) =>
 | 
				
			||||||
 | 
										filterDonors(label, filterText, option)}
 | 
				
			||||||
 | 
									items={current_donors}
 | 
				
			||||||
 | 
									showChevron={true}
 | 
				
			||||||
 | 
									placeholder={$_("search-for-donor-name-or-id")}
 | 
				
			||||||
 | 
									noOptionsMessage={$_("no-donors-found")}
 | 
				
			||||||
 | 
									bind:selectedValue={donor}
 | 
				
			||||||
 | 
									on:select={(selectedValue) => {
 | 
				
			||||||
 | 
										editable.donor = selectedValue.detail.value;
 | 
				
			||||||
 | 
										editable.donor.donationAmount = original_data.donor.donationAmount;
 | 
				
			||||||
 | 
										editable.donor.paidDonationAmount =
 | 
				
			||||||
 | 
											original_data.donor.paidDonationAmount;
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
									on:clear={() => (editable.donor = null)}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							{#if original_data.responseType == "DISTANCEDONATION"}
 | 
				
			||||||
 | 
								<div class=" mt-2 w-full">
 | 
				
			||||||
 | 
									<label for="donor" class="block font-semibold text-gray-700"
 | 
				
			||||||
 | 
										>{$_("runner")}</label
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
									<Select
 | 
				
			||||||
 | 
										containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
 | 
				
			||||||
 | 
										itemFilter={(label, filterText, option) =>
 | 
				
			||||||
 | 
											filterDonors(label, filterText, option)}
 | 
				
			||||||
 | 
										items={current_runners}
 | 
				
			||||||
 | 
										showChevron={true}
 | 
				
			||||||
 | 
										placeholder={$_("search-for-runner-by-name-or-id")}
 | 
				
			||||||
 | 
										noOptionsMessage={$_("no-runners-found")}
 | 
				
			||||||
 | 
										bind:selectedValue={runner}
 | 
				
			||||||
 | 
										on:select={(selectedValue) =>
 | 
				
			||||||
 | 
											(editable.runner = selectedValue.detail.value)}
 | 
				
			||||||
 | 
										on:clear={() => (editable.runner = null)}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							{/if}
 | 
				
			||||||
 | 
							<div class=" mt-2 w-full">
 | 
				
			||||||
 | 
								<label for="lastname" class="font-semibold text-gray-700">
 | 
				
			||||||
 | 
									{#if original_data.responseType == "DISTANCEDONATION"}
 | 
				
			||||||
 | 
										{$_("amount-per-kilometer")}
 | 
				
			||||||
 | 
									{:else}{$_("donation-amount")}{/if}
 | 
				
			||||||
 | 
								</label>
 | 
				
			||||||
 | 
								<div class="mt-1 flex rounded-md shadow-sm">
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										autocomplete="off"
 | 
				
			||||||
 | 
										class:border-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
										class:focus:border-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
										class:focus:ring-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
										bind:value={amount_input}
 | 
				
			||||||
 | 
										type="number"
 | 
				
			||||||
 | 
										step="0.01"
 | 
				
			||||||
 | 
										name="donation_amount_eur"
 | 
				
			||||||
 | 
										class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 p-2"
 | 
				
			||||||
 | 
										placeholder="2.00"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500"
 | 
				
			||||||
 | 
										>€</span
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								{#if !is_amount_valid}
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{$_("donation-amount-must-be-greater-that-0-00eur")}
 | 
				
			||||||
 | 
									</span>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="mt-2 w-full">
 | 
				
			||||||
 | 
								<label for="token" class="block font-semibold text-gray-700"
 | 
				
			||||||
 | 
									>{$_("paid-amount")}</label
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									class="inline-flex border-gray-300 border rounded-l-md rounded-r-md bg-gray-50 text-gray-500 w-full"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										autocomplete="off"
 | 
				
			||||||
 | 
										class:border-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
										class:focus:border-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
										class:focus:ring-red-500={!is_amount_valid}
 | 
				
			||||||
 | 
										bind:value={paid_amount_input}
 | 
				
			||||||
 | 
										type="number"
 | 
				
			||||||
 | 
										step="0.01"
 | 
				
			||||||
 | 
										name="donation_amount_eur"
 | 
				
			||||||
 | 
										class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm p-2"
 | 
				
			||||||
 | 
										placeholder="2.00"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<button
 | 
				
			||||||
 | 
										on:click={() => {
 | 
				
			||||||
 | 
											paid_amount_input = paid_amount_input = (
 | 
				
			||||||
 | 
												original_data.amount / 100
 | 
				
			||||||
 | 
											).toFixed(2);
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
										class="inline-flex items-center p-r-2 text-indigo-300 hover:text-indigo-700 text-sm"
 | 
				
			||||||
 | 
										>MAX</button
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
 | 
				
			||||||
 | 
										>€</span
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								{#if !is_paid_amount_valid}
 | 
				
			||||||
 | 
									<span
 | 
				
			||||||
 | 
										class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{$_("payment-amount-must-be-greater-than-0-00eur")}
 | 
				
			||||||
 | 
									</span>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</section>
 | 
				
			||||||
 | 
					{:catch error}
 | 
				
			||||||
 | 
						<PromiseError {error} />
 | 
				
			||||||
 | 
					{/await}
 | 
				
			||||||
							
								
								
									
										21
									
								
								src/components/donations/DonationDonor.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/components/donations/DonationDonor.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
						export let donor;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if !donor || donor.firstname == 0}
 | 
				
			||||||
 | 
						<span
 | 
				
			||||||
 | 
							class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
 | 
				
			||||||
 | 
							>{$_('anonymer_sponsor')}</span
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
					{:else}
 | 
				
			||||||
 | 
						<div class="flex items-center">
 | 
				
			||||||
 | 
							<a
 | 
				
			||||||
 | 
								href="../donors/{donor.id}"
 | 
				
			||||||
 | 
								class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
 | 
				
			||||||
 | 
								>{donor.firstname}
 | 
				
			||||||
 | 
								{#if donor.middlename}{donor.middlename}{/if}
 | 
				
			||||||
 | 
								{donor.lastname}</a
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/components/donations/DonationRunner.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/components/donations/DonationRunner.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  export let runner;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if !runner || runner.firstname == 0}
 | 
				
			||||||
 | 
					  {$_("fixed-donation")}
 | 
				
			||||||
 | 
					{:else}
 | 
				
			||||||
 | 
					  <div class="text-sm font-medium text-gray-900">
 | 
				
			||||||
 | 
					    <a
 | 
				
			||||||
 | 
					      href="../runners/{runner.id}"
 | 
				
			||||||
 | 
					      class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
 | 
				
			||||||
 | 
					      >{runner.firstname}
 | 
				
			||||||
 | 
					      {#if runner.middlename}{runner.middlename}{/if}
 | 
				
			||||||
 | 
					      {runner.lastname}</a
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/components/donations/DonationStatus.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/components/donations/DonationStatus.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  export let status;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if status == "PAID"}
 | 
				
			||||||
 | 
					  <span
 | 
				
			||||||
 | 
					    class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
 | 
				
			||||||
 | 
					    >{$_("paid")}</span
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					{:else}
 | 
				
			||||||
 | 
					  <span
 | 
				
			||||||
 | 
					    class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-red-100 text-red-800"
 | 
				
			||||||
 | 
					    >{$_("open")}</span
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										21
									
								
								src/components/donations/DonationTableAction.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/components/donations/DonationTableAction.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import TableActions from "../shared/TableActions.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export let detailsLink;
 | 
				
			||||||
 | 
					  export let detailsAction;
 | 
				
			||||||
 | 
					  export let deleteEnabled;
 | 
				
			||||||
 | 
					  export let deleteAction;
 | 
				
			||||||
 | 
					  export let paymentAction;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<button
 | 
				
			||||||
 | 
					  on:click={paymentAction}
 | 
				
			||||||
 | 
					  class="text-[#025a21] hover:text-green-900 mr-4">{$_("enter-payment")}</button
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					<TableActions
 | 
				
			||||||
 | 
					  bind:detailsAction
 | 
				
			||||||
 | 
					  bind:detailsLink
 | 
				
			||||||
 | 
					  bind:deleteAction
 | 
				
			||||||
 | 
					  bind:deleteEnabled
 | 
				
			||||||
 | 
					/>
 | 
				
			||||||
							
								
								
									
										36
									
								
								src/components/donations/Donations.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/components/donations/Donations.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import store from "../../store";
 | 
				
			||||||
 | 
					  import AddDonationModal from "./AddDonationModal.svelte";
 | 
				
			||||||
 | 
					  import DonationsOverview from "./DonationsOverview.svelte";
 | 
				
			||||||
 | 
					  $: current_donations = [];
 | 
				
			||||||
 | 
					  export let modal_open = false;
 | 
				
			||||||
 | 
					  let addDonations;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section class="container p-5">
 | 
				
			||||||
 | 
					  <h4 class="mb-1 text-3xl font-extrabold leading-tight">
 | 
				
			||||||
 | 
					    {$_("donations")}
 | 
				
			||||||
 | 
					  </h4>
 | 
				
			||||||
 | 
					  {#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}
 | 
				
			||||||
 | 
					    <button
 | 
				
			||||||
 | 
					      on:click={() => {
 | 
				
			||||||
 | 
					        modal_open = true;
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      type="button"
 | 
				
			||||||
 | 
					      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {$_("add-donation")}
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  {/if}
 | 
				
			||||||
 | 
					  <DonationsOverview bind:current_donations bind:addDonations />
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}
 | 
				
			||||||
 | 
					  <AddDonationModal
 | 
				
			||||||
 | 
					    on:created={(event) => {
 | 
				
			||||||
 | 
					      addDonations(event.detail.donations);
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					    bind:modal_open
 | 
				
			||||||
 | 
					  />
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/components/donations/DonationsEmptyState.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/components/donations/DonationsEmptyState.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import { _ } from "svelte-i18n";
 | 
				
			||||||
 | 
					  import donations_empty from "./donations.svg";
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="text-center items-center justify-center">
 | 
				
			||||||
 | 
					  <p class="mb-16 text-lg text-gray-500">
 | 
				
			||||||
 | 
					    <img class="m-auto mt-2" style="height:15rem" src={donations_empty} alt="" />
 | 
				
			||||||
 | 
					    <span class="font-bold">{$_("there-are-no-donations-yet")}</span><br />
 | 
				
			||||||
 | 
					    <span>{$_("add-your-fist-donation")}</span>
 | 
				
			||||||
 | 
					  </p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user