Compare commits
	
		
			16 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 51d9b35dc4 | |||
| 16dc789db5 | |||
| e4f9b1a605 | |||
| 3a8533a7ba | |||
| 5ac6fe30b5 | |||
| 14501d3828 | |||
| c78bdfa5e2 | |||
| b2ed2afd8a | |||
| 00d198895e | |||
| b5c079da9a | |||
| 93422b9779 | |||
| 6dcfd9a4fe | |||
| 6d1919974a | |||
| f27c716296 | |||
| 21395241de | |||
| 8d2cb13195 | 
							
								
								
									
										36
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -2,8 +2,44 @@ | |||||||
|  |  | ||||||
| All notable changes to this project will be documented in this file. Dates are displayed in UTC. | All notable changes to this project will be documented in this file. Dates are displayed in UTC. | ||||||
|  |  | ||||||
|  | #### [1.12.8](https://git.odit.services/lfk/frontend/compare/1.12.7...1.12.8) | ||||||
|  |  | ||||||
|  | - feat(dasboard): Added section headers to main nav [`3a8533a`](https://git.odit.services/lfk/frontend/commit/3a8533a7baef02f7bc9780ce37be1a350bd92270) | ||||||
|  | - fic(locales): Updated dashboard translations [`5ac6fe3`](https://git.odit.services/lfk/frontend/commit/5ac6fe30b5b9e34043c734d51d5da137fdf7ac38) | ||||||
|  | - feat(runners): Created_via filters can now be set via query params [`14501d3`](https://git.odit.services/lfk/frontend/commit/14501d3828dd0d48ba0baeeddf936ba275f7b9b7) | ||||||
|  | - refactor(tools): Move tools to tools route [`16dc789`](https://git.odit.services/lfk/frontend/commit/16dc789db5d9ea41774c77622a579cc0d9bd95f2) | ||||||
|  | - refactor(tools): Move tools into shared directory instead of the non-descript "general" [`e4f9b1a`](https://git.odit.services/lfk/frontend/commit/e4f9b1a60551d7955def4d068d534cf17b1ea640) | ||||||
|  |  | ||||||
|  | #### [1.12.7](https://git.odit.services/lfk/frontend/compare/1.12.6...1.12.7) | ||||||
|  |  | ||||||
|  | > 1 May 2025 | ||||||
|  |  | ||||||
|  | - chore(release): 1.12.7 [`c78bdfa`](https://git.odit.services/lfk/frontend/commit/c78bdfa5e24ada4909455064dd6b05cf34fc6df3) | ||||||
|  | - fix(deps): fresh lockfile [`b2ed2af`](https://git.odit.services/lfk/frontend/commit/b2ed2afd8a45a1a01ac6118b27941e3b4b3b611f) | ||||||
|  | - refactor(store): update refresh interval from 2min to 60min [`00d1988`](https://git.odit.services/lfk/frontend/commit/00d198895e15174b70a8d229974b4baa7d0ed8fc) | ||||||
|  |  | ||||||
|  | #### [1.12.6](https://git.odit.services/lfk/frontend/compare/1.12.5...1.12.6) | ||||||
|  |  | ||||||
|  | > 1 May 2025 | ||||||
|  |  | ||||||
|  | - feat(pdfs): Experimental generation of large runner card files [`93422b9`](https://git.odit.services/lfk/frontend/commit/93422b97799c5e45c89acadd34f33b1a11b04617) | ||||||
|  | - chore(release): 1.12.6 [`b5c079d`](https://git.odit.services/lfk/frontend/commit/b5c079da9a0545d146e9f3029a543e04c907add3) | ||||||
|  |  | ||||||
|  | #### [1.12.5](https://git.odit.services/lfk/frontend/compare/1.12.4...1.12.5) | ||||||
|  |  | ||||||
|  | > 1 May 2025 | ||||||
|  |  | ||||||
|  | - chore(release): 1.12.5 [`6dcfd9a`](https://git.odit.services/lfk/frontend/commit/6dcfd9a4fedd1e44894c9803482576bc650fb4db) | ||||||
|  | - fix(locales): Fixed translation [`2139524`](https://git.odit.services/lfk/frontend/commit/21395241de4de8f3a6b8404758d09c01d8a6f95f) | ||||||
|  | - feat(runners): Show total donations in runner detail [`f27c716`](https://git.odit.services/lfk/frontend/commit/f27c716296e228ecccbf500a21130f1bc47ea52d) | ||||||
|  | - chore(deps): Bump @odit/lfk-client-js to 1.2.7 [`6d19199`](https://git.odit.services/lfk/frontend/commit/6d1919974aacd74a265cf9ce0c9ed501028f0aa3) | ||||||
|  | - fix: Update release script to include --only-version flag [`8d2cb13`](https://git.odit.services/lfk/frontend/commit/8d2cb13195856f47022d414f3243e9a21457832b) | ||||||
|  |  | ||||||
| #### [1.12.4](https://git.odit.services/lfk/frontend/compare/1.12.3...1.12.4) | #### [1.12.4](https://git.odit.services/lfk/frontend/compare/1.12.3...1.12.4) | ||||||
|  |  | ||||||
|  | > 28 April 2025 | ||||||
|  |  | ||||||
|  | - chore(release): 1.12.4 [`e61e8b0`](https://git.odit.services/lfk/frontend/commit/e61e8b063af75539b7db93c5ca42965417019f29) | ||||||
| - fix: Disable ios auto zooming on inputs [`073c78d`](https://git.odit.services/lfk/frontend/commit/073c78d98afd1c2f08b190aeda942a634e9bb888) | - fix: Disable ios auto zooming on inputs [`073c78d`](https://git.odit.services/lfk/frontend/commit/073c78d98afd1c2f08b190aeda942a634e9bb888) | ||||||
|  |  | ||||||
| #### [1.12.3](https://git.odit.services/lfk/frontend/compare/1.12.2...1.12.3) | #### [1.12.3](https://git.odit.services/lfk/frontend/compare/1.12.2...1.12.3) | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
|  |  | ||||||
|   <body> |   <body> | ||||||
|     <span style="display: none; visibility: hidden" id="buildinfo" |     <span style="display: none; visibility: hidden" id="buildinfo" | ||||||
|       >RELEASE_INFO-1.12.4-RELEASE_INFO</span |       >RELEASE_INFO-1.12.8-RELEASE_INFO</span | ||||||
|     > |     > | ||||||
|     <noscript>You need to enable JavaScript to run this app.</noscript> |     <noscript>You need to enable JavaScript to run this app.</noscript> | ||||||
|     <script src="/env.js"></script> |     <script src="/env.js"></script> | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| { | { | ||||||
|   "name": "@odit/lfk-frontend", |   "name": "@odit/lfk-frontend", | ||||||
|   "version": "1.12.4", |   "version": "1.12.8", | ||||||
|   "type": "module", |   "type": "module", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "i18n-order": "node order.js", |     "i18n-order": "node order.js", | ||||||
|     "dev": "vite", |     "dev": "vite", | ||||||
|     "format": "prettier --write --plugin-search-dir=. .", |     "format": "prettier --write --plugin-search-dir=. .", | ||||||
|     "build": "vite build", |     "build": "vite build", | ||||||
|     "release": "release-it", |     "release": "release-it --only-version", | ||||||
|     "licenses:export": "license-exporter --json -o public" |     "licenses:export": "license-exporter --json -o public" | ||||||
|   }, |   }, | ||||||
|   "license": "CC-BY-NC-SA-4.0", |   "license": "CC-BY-NC-SA-4.0", | ||||||
| @@ -43,7 +43,7 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@bwip-js/browser": "^4.6.0", |     "@bwip-js/browser": "^4.6.0", | ||||||
|     "@fontsource/athiti": "^5.2.5", |     "@fontsource/athiti": "^5.2.5", | ||||||
|     "@odit/lfk-client-js": "1.2.5", |     "@odit/lfk-client-js": "1.2.7", | ||||||
|     "@paralleldrive/cuid2": "2.2.2", |     "@paralleldrive/cuid2": "2.2.2", | ||||||
|     "@tailwindcss/vite": "^4.1.4", |     "@tailwindcss/vite": "^4.1.4", | ||||||
|     "@tanstack/svelte-table": "8.9.1", |     "@tanstack/svelte-table": "8.9.1", | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @@ -15,8 +15,8 @@ importers: | |||||||
|         specifier: ^5.2.5 |         specifier: ^5.2.5 | ||||||
|         version: 5.2.5 |         version: 5.2.5 | ||||||
|       '@odit/lfk-client-js': |       '@odit/lfk-client-js': | ||||||
|         specifier: 1.2.5 |         specifier: 1.2.7 | ||||||
|         version: 1.2.5 |         version: 1.2.7 | ||||||
|       '@paralleldrive/cuid2': |       '@paralleldrive/cuid2': | ||||||
|         specifier: 2.2.2 |         specifier: 2.2.2 | ||||||
|         version: 2.2.2 |         version: 2.2.2 | ||||||
| @@ -491,8 +491,8 @@ packages: | |||||||
|   '@octokit/types@13.10.0': |   '@octokit/types@13.10.0': | ||||||
|     resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} |     resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} | ||||||
|  |  | ||||||
|   '@odit/lfk-client-js@1.2.5': |   '@odit/lfk-client-js@1.2.7': | ||||||
|     resolution: {integrity: sha512-a5vwqpjFXB5cVOCmjC/tZVi9OXJS8aMesNidSqwK2cwA/oC5yTJAqxKXGDhq9k/JLLipVGDJdaKMYmYVzRWkgA==} |     resolution: {integrity: sha512-sqbbTjGlalN32VPshXClR3qM0+TFgWCX9+2UCo7u/tABEIs7hsYTVXKSZ+fJNfAUCK6ZJiZV0ND6+Dcnk7s29A==} | ||||||
|  |  | ||||||
|   '@odit/license-exporter@0.2.0': |   '@odit/license-exporter@0.2.0': | ||||||
|     resolution: {integrity: sha512-RRyfQzDLoyLQlGSd8ThJQ3h0fiCe4tkmm935AUvSVQWP+p88FcnI4iaktKBJJVBnIpDhkv/7sDSA5dFc/QMM5w==} |     resolution: {integrity: sha512-RRyfQzDLoyLQlGSd8ThJQ3h0fiCe4tkmm935AUvSVQWP+p88FcnI4iaktKBJJVBnIpDhkv/7sDSA5dFc/QMM5w==} | ||||||
| @@ -2412,7 +2412,7 @@ snapshots: | |||||||
|     dependencies: |     dependencies: | ||||||
|       '@octokit/openapi-types': 24.2.0 |       '@octokit/openapi-types': 24.2.0 | ||||||
|  |  | ||||||
|   '@odit/lfk-client-js@1.2.5': {} |   '@odit/lfk-client-js@1.2.7': {} | ||||||
|  |  | ||||||
|   '@odit/license-exporter@0.2.0': |   '@odit/license-exporter@0.2.0': | ||||||
|     dependencies: |     dependencies: | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ | |||||||
|   import Settings from "./components/settings/Settings.svelte"; |   import Settings from "./components/settings/Settings.svelte"; | ||||||
|   import Transition from "./components/base/Transition.svelte"; |   import Transition from "./components/base/Transition.svelte"; | ||||||
|   import Orgs from "./components/orgs/Orgs.svelte"; |   import Orgs from "./components/orgs/Orgs.svelte"; | ||||||
|   import CardAssignment from "./components/general/CardAssignment.svelte"; |   import CardAssignment from "./components/tools/CardAssignment.svelte"; | ||||||
|   import Runners from "./components/runners/Runners.svelte"; |   import Runners from "./components/runners/Runners.svelte"; | ||||||
|   import Footer from "./components/general/Footer.svelte"; |   import Footer from "./components/general/Footer.svelte"; | ||||||
|   import TracksOverview from "./components/tracks/TracksOverview.svelte"; |   import TracksOverview from "./components/tracks/TracksOverview.svelte"; | ||||||
| @@ -70,7 +70,7 @@ | |||||||
|   import Cards from "./components/cards/Cards.svelte"; |   import Cards from "./components/cards/Cards.svelte"; | ||||||
|   import StatsClients from "./components/statsclients/StatsClients.svelte"; |   import StatsClients from "./components/statsclients/StatsClients.svelte"; | ||||||
|   import StatsClientDetail from "./components/statsclients/StatsClientDetail.svelte"; |   import StatsClientDetail from "./components/statsclients/StatsClientDetail.svelte"; | ||||||
|   import CardReplacement from "./components/general/CardReplacement.svelte"; |   import CardReplacement from "./components/tools/CardReplacement.svelte"; | ||||||
|   store.init(); |   store.init(); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| @@ -126,21 +126,19 @@ | |||||||
|           <Route path="/:trackid" let:params /> |           <Route path="/:trackid" let:params /> | ||||||
|         </Route> |         </Route> | ||||||
|         <Route path="/runners/*"> |         <Route path="/runners/*"> | ||||||
|           <Route path="/"> |           <Route path="/" let:meta> | ||||||
|             <Runners created_via="all" /> |             <Runners created_via={meta.query.created_via} /> | ||||||
|           </Route> |           </Route> | ||||||
|           <Route path="/:runnerid" let:params> |           <Route path="/:runnerid" let:params> | ||||||
|             <RunnerDetail {params} /> |             <RunnerDetail {params} /> | ||||||
|           </Route> |           </Route> | ||||||
|         </Route> |         </Route> | ||||||
|         <Route path="/cardassignment/*"> |         <Route path="/tools/*"> | ||||||
|           <Route path="/"> |           <Route path="/cardassignment/"> | ||||||
|             <CardAssignment /> |               <CardAssignment /> | ||||||
|           </Route> |           </Route> | ||||||
|         </Route> |           <Route path="/cardreplacement/"> | ||||||
|         <Route path="/cardreplacement/*"> |               <CardReplacement /> | ||||||
|           <Route path="/"> |  | ||||||
|             <CardReplacement /> |  | ||||||
|           </Route> |           </Route> | ||||||
|         </Route> |         </Route> | ||||||
|         <Route path="/teams/*"> |         <Route path="/teams/*"> | ||||||
|   | |||||||
| @@ -1,479 +1,488 @@ | |||||||
| <script> | <script> | ||||||
| 	import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
| 	import localForage from "localforage"; |   import localForage from "localforage"; | ||||||
| 	import store from "../../store"; |   import store from "../../store"; | ||||||
| 	import { router } from "tinro"; |   import { router } from "tinro"; | ||||||
| 	import NoComponentLoaded from "../base/NoComponentLoaded.svelte"; |   import NoComponentLoaded from "../base/NoComponentLoaded.svelte"; | ||||||
| 	import { AuthService } from "@odit/lfk-client-js"; |   import { AuthService } from "@odit/lfk-client-js"; | ||||||
| 	import { Toaster } from "svelte-french-toast"; |   import { Toaster } from "svelte-french-toast"; | ||||||
| 	$: navOpen = false; |   $: navOpen = false; | ||||||
| 	function logout() { |   function logout() { | ||||||
| 		localForage.clear(); |     localForage.clear(); | ||||||
| 		location.replace("/"); |     location.replace("/"); | ||||||
| 	} |   } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="min-h-screen bg-gray-50"> | <section class="min-h-screen bg-gray-50"> | ||||||
| 	<div |   <div | ||||||
| 		class:collapsed_navigation={!navOpen} |     class:collapsed_navigation={!navOpen} | ||||||
| 		style="z-index:11;" |     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" |     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"> |     <a href="/" class="flex items-center px-4 py-5"> | ||||||
| 			<img src="/lfk-logo.png" alt="Logo" class="h-10" /> |       <img src="/lfk-logo.png" alt="Logo" class="h-10" /> | ||||||
| 			<h3 class="text-lg font-bold">LfK!Admin</h3> |       <h3 class="text-lg font-bold">LfK!Admin</h3> | ||||||
| 		</a> |     </a> | ||||||
| 		<nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation"> |     <nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation"> | ||||||
| 			<a |       <a | ||||||
| 				class:activenav={$router.path === "/"} |         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" |         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="/" |         href="/" | ||||||
| 			> |       > | ||||||
| 				<svg |         <svg | ||||||
| 					class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 					xmlns="http://www.w3.org/2000/svg" |           xmlns="http://www.w3.org/2000/svg" | ||||||
| 					viewBox="0 0 20 20" |           viewBox="0 0 20 20" | ||||||
| 					fill="currentColor" |           fill="currentColor" | ||||||
| 				> |         > | ||||||
| 					<path |           <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" |             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> |         </svg> | ||||||
| 				<span>{$_("dashboard-title")}</span> |         <span>{$_("dashboard-title")}</span> | ||||||
| 			</a> |       </a> | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET") && store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")} |       <h2 class="px-4 py-2 text-xs font-semibold text-gray-600 uppercase"> | ||||||
| 				<a |         {$_("quick-tools")} | ||||||
| 					class:activenav={$router.path.includes("/cardassignment/")} |       </h2> | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET") && store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")} | ||||||
| 					href="/cardassignment/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/tools/cardassignment/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |           href="/tools/cardassignment/" | ||||||
| 						viewBox="0 0 24 24" |         > | ||||||
| 						fill="currentColor" |           <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 24 24" | ||||||
| 						<path |             fill="currentColor" | ||||||
| 							fill-rule="evenodd" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 							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" |             <path | ||||||
| 						/> |               fill-rule="evenodd" | ||||||
| 					</svg> |               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> |           <span>{$_("card_assignment_menu")}</span> | ||||||
| 				</a> |         </a> | ||||||
| 				<a |         <a | ||||||
| 					class:activenav={$router.path.includes("/cardreplacement/")} |           class:activenav={$router.path.includes("/tools/cardreplacement/")} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |           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="/cardreplacement/" |           href="/tools/cardreplacement/" | ||||||
| 				> |         > | ||||||
| 					<svg |           <svg | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 						viewBox="0 0 24 24" |             viewBox="0 0 24 24" | ||||||
| 						fill="currentColor" |             fill="currentColor" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 					> |           > | ||||||
| 						<path |             <path | ||||||
| 							fill-rule="evenodd" |               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" |               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" |               clip-rule="evenodd" | ||||||
| 						/> |             /> | ||||||
| 					</svg> |           </svg> | ||||||
|  |  | ||||||
| 					<span>{$_('card-replacement-menu')}</span> |           <span>{$_("card-replacement-menu")}</span> | ||||||
| 				</a> |         </a> | ||||||
| 				<a |         <h2 class="px-4 py-2 text-xs font-semibold text-gray-600 uppercase"> | ||||||
| 					class:activenav={$router.path.includes("/runners/")} |           {$_("management")} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |         </h2> | ||||||
| 					href="/runners/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/runners/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |           href="/runners/" | ||||||
| 						viewBox="0 0 24 24" |         > | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           <svg | ||||||
| 						fill="currentColor" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 						width="24" |             viewBox="0 0 24 24" | ||||||
| 						height="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             fill="currentColor" | ||||||
| 						<path |             width="24" | ||||||
| 							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" |             height="24" | ||||||
| 						/></svg |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 					> |             <path | ||||||
| 					<span>{$_("runners")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")} |           <span>{$_("runners")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/teams/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")} | ||||||
| 					href="/teams/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/teams/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/teams/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						width="24" |           <svg | ||||||
| 						height="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |             fill="currentColor" | ||||||
| 						viewBox="0 0 640 512" |             width="24" | ||||||
| 						><path |             height="24" | ||||||
| 							fill="currentColor" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 							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" |             viewBox="0 0 640 512" | ||||||
| 						/></svg |             ><path | ||||||
| 					> |               fill="currentColor" | ||||||
| 					<span>{$_("teams")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:GET")} |           <span>{$_("teams")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/orgs/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:GET")} | ||||||
| 					href="/orgs/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/orgs/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/orgs/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |           <svg | ||||||
| 						viewBox="0 0 24 24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						width="24" |             fill="currentColor" | ||||||
| 						height="24" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             viewBox="0 0 24 24" | ||||||
| 						<path |             width="24" | ||||||
| 							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" |             height="24" | ||||||
| 						/></svg |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 					> |             <path | ||||||
| 					<span>{$_("orgs")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")} |           <span>{$_("orgs")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/donors/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")} | ||||||
| 					href="/donors/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/donors/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/donors/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |           <svg | ||||||
| 						viewBox="0 0 24 24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						width="24" |             fill="currentColor" | ||||||
| 						height="24" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             viewBox="0 0 24 24" | ||||||
| 						<path |             width="24" | ||||||
| 							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" |             height="24" | ||||||
| 						/></svg |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 					> |             <path | ||||||
| 					<span>{$_("donors")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")} |           <span>{$_("donors")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/donations/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")} | ||||||
| 					href="/donations/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/donations/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/donations/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |           <svg | ||||||
| 						viewBox="0 0 24 24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						width="24" |             fill="currentColor" | ||||||
| 						height="24" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             viewBox="0 0 24 24" | ||||||
| 						<path |             width="24" | ||||||
| 							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" |             height="24" | ||||||
| 						/></svg |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 					> |             <path | ||||||
| 					<span>{$_("donations")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("TRACK:GET")} |           <span>{$_("donations")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path === "/tracks/"} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("TRACK:GET")} | ||||||
| 					href="/tracks/" |         <a | ||||||
| 				> |           class:activenav={$router.path === "/tracks/"} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/tracks/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						width="24" |           <svg | ||||||
| 						height="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |             fill="currentColor" | ||||||
| 						viewBox="0 0 640 512" |             width="24" | ||||||
| 						><path |             height="24" | ||||||
| 							fill="currentColor" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 							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" |             viewBox="0 0 640 512" | ||||||
| 						/></svg |             ><path | ||||||
| 					> |               fill="currentColor" | ||||||
| 					<span>{$_("tracks")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")} |           <span>{$_("tracks")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path === "/cards/"} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")} | ||||||
| 					href="/cards/" |         <a | ||||||
| 				> |           class:activenav={$router.path === "/cards/"} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/cards/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						width="24" |           <svg | ||||||
| 						height="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |             fill="currentColor" | ||||||
| 						viewBox="0 0 24 24" |             width="24" | ||||||
| 					> |             height="24" | ||||||
| 						<path fill="none" d="M0 0h24v24H0z" /> |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 						<path |             viewBox="0 0 24 24" | ||||||
| 							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" |             <path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 						/></svg |             <path | ||||||
| 					> |               fill="currentColor" | ||||||
| 					<span>{$_("cards")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")} |           <span>{$_("cards")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/scans/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")} | ||||||
| 					href="/scans/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/scans/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/scans/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						width="24" |           <svg | ||||||
| 						height="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |             fill="currentColor" | ||||||
| 						viewBox="0 0 24 24" |             width="24" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             height="24" | ||||||
| 						<path |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 							fill="currentColor" |             viewBox="0 0 24 24" | ||||||
| 							d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z" |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 						/></svg |             <path | ||||||
| 					> |               fill="currentColor" | ||||||
| 					<span>Scans</span> |               d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:GET")} |           <span>Scans</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/contacts/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:GET")} | ||||||
| 					href="/contacts/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/contacts/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						fill="currentColor" |           href="/contacts/" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |         > | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |           <svg | ||||||
| 						viewBox="0 0 24 24" |             fill="currentColor" | ||||||
| 						width="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						height="24" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             viewBox="0 0 24 24" | ||||||
| 						<path |             width="24" | ||||||
| 							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" |             height="24" | ||||||
| 						/></svg |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 					> |             <path | ||||||
| 					<span>{$_("contacts")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:GET")} |           <span>{$_("contacts")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/scanstations/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("STATION:GET")} | ||||||
| 					href="/scanstations/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/scanstations/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/scanstations/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						width="24" |           <svg | ||||||
| 						height="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						viewBox="0 0 24 24" |             fill="currentColor" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |             width="24" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             height="24" | ||||||
| 						<path |             viewBox="0 0 24 24" | ||||||
| 							fill="currentColor" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 							d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 						/></svg |             <path | ||||||
| 					> |               fill="currentColor" | ||||||
| 					<span>{$_("scanstations")}</span> |               d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:GET")} |           <span>{$_("scanstations")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/statsclients/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:GET")} | ||||||
| 					href="/statsclients/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/statsclients/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/statsclients/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						width="24" |           <svg | ||||||
| 						height="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						viewBox="0 0 24 24" |             fill="currentColor" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |             width="24" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             height="24" | ||||||
| 						<path |             viewBox="0 0 24 24" | ||||||
| 							fill="currentColor" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 							d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 						/></svg |             <path | ||||||
| 					> |               fill="currentColor" | ||||||
| 					<span>{$_("statsclients")}</span> |               d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("USER:GET")} |           <span>{$_("statsclients")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/users/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("USER:GET")} | ||||||
| 					href="/users/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/users/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |           href="/users/" | ||||||
| 						width="24" |         > | ||||||
| 						height="24" |           <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="currentColor" |             width="24" | ||||||
| 						viewBox="0 0 24 24" |             height="24" | ||||||
| 						><path fill="none" d="M0 0h24v24H0z" /> |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						<path |             fill="currentColor" | ||||||
| 							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" |             viewBox="0 0 24 24" | ||||||
| 						/></svg |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 					> |             <path | ||||||
| 					<span>{$_("users")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:GET")} |           <span>{$_("users")}</span> | ||||||
| 				<a |         </a> | ||||||
| 					class:activenav={$router.path.includes("/groups/")} |       {/if} | ||||||
| 					class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:GET")} | ||||||
| 					href="/groups/" |         <a | ||||||
| 				> |           class:activenav={$router.path.includes("/groups/")} | ||||||
| 					<svg |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 						class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |           href="/groups/" | ||||||
| 						fill="currentColor" |         > | ||||||
| 						width="24" |           <svg | ||||||
| 						height="24" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						xmlns="http://www.w3.org/2000/svg" |             fill="currentColor" | ||||||
| 						viewBox="0 0 640 512" |             width="24" | ||||||
| 						><path |             height="24" | ||||||
| 							fill="currentColor" |             xmlns="http://www.w3.org/2000/svg" | ||||||
| 							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" |             viewBox="0 0 640 512" | ||||||
| 						/></svg |             ><path | ||||||
| 					> |               fill="currentColor" | ||||||
| 					<span>{$_("user-groups")}</span> |               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" | ||||||
| 				</a> |             /></svg | ||||||
| 			{/if} |           > | ||||||
| 			<a |           <span>{$_("user-groups")}</span> | ||||||
| 				class:activenav={$router.path === "/settings/"} |         </a> | ||||||
| 				class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |       {/if} | ||||||
| 				href="/settings/" | 	  <h2 class="px-4 py-2 text-xs font-semibold text-gray-600 uppercase"> | ||||||
| 			> | 		  {$_("system")} | ||||||
| 				<svg |         </h2> | ||||||
| 					class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |       <a | ||||||
| 					xmlns="http://www.w3.org/2000/svg" |         class:activenav={$router.path === "/settings/"} | ||||||
| 					viewBox="0 0 20 20" |         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 					fill="currentColor" |         href="/settings/" | ||||||
| 				> |       > | ||||||
| 					<path |         <svg | ||||||
| 						fill-rule="evenodd" |           class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 						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" |           xmlns="http://www.w3.org/2000/svg" | ||||||
| 						clip-rule="evenodd" |           viewBox="0 0 20 20" | ||||||
| 					/> |           fill="currentColor" | ||||||
| 				</svg> |         > | ||||||
| 				<span>{$_("settings")}</span> |           <path | ||||||
| 			</a> |             fill-rule="evenodd" | ||||||
| 			<a |             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" | ||||||
| 				class:activenav={$router.path === "/about/"} |             clip-rule="evenodd" | ||||||
| 				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> | ||||||
| 			> |         <span>{$_("settings")}</span> | ||||||
| 				<svg |       </a> | ||||||
| 					class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |       <a | ||||||
| 					xmlns="http://www.w3.org/2000/svg" |         class:activenav={$router.path === "/about/"} | ||||||
| 					fill="none" |         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 					stroke="currentColor" |         href="/about/" | ||||||
| 					stroke-width="2" |       > | ||||||
| 					stroke-linecap="round" |         <svg | ||||||
| 					stroke-linejoin="round" |           class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 					viewBox="0 0 24 24" |           xmlns="http://www.w3.org/2000/svg" | ||||||
| 					><circle cx="12" cy="12" r="10" /> |           fill="none" | ||||||
| 					<path d="M12 16v-4M12 8h.01" /></svg |           stroke="currentColor" | ||||||
| 				> |           stroke-width="2" | ||||||
| 				<span>{$_("about")}</span> |           stroke-linecap="round" | ||||||
| 			</a> |           stroke-linejoin="round" | ||||||
| 			<button |           viewBox="0 0 24 24" | ||||||
| 				tabindex="0" |           ><circle cx="12" cy="12" r="10" /> | ||||||
| 				class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" |           <path d="M12 16v-4M12 8h.01" /></svg | ||||||
| 				on:click={() => { |         > | ||||||
| 					AuthService.authControllerLogout(); |         <span>{$_("about")}</span> | ||||||
| 					logout(); |       </a> | ||||||
| 				}} |       <button | ||||||
| 			> |         tabindex="0" | ||||||
| 				<svg |         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold" | ||||||
| 					class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" |         on:click={() => { | ||||||
| 					fill="currentColor" |           AuthService.authControllerLogout(); | ||||||
| 					width="24" |           logout(); | ||||||
| 					height="24" |         }} | ||||||
| 					xmlns="http://www.w3.org/2000/svg" |       > | ||||||
| 					viewBox="0 0 24 24" |         <svg | ||||||
| 					><path fill="none" d="M0 0h24v24H0z" /> |           class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
| 					<path |           fill="currentColor" | ||||||
| 						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" |           width="24" | ||||||
| 					/></svg |           height="24" | ||||||
| 				> |           xmlns="http://www.w3.org/2000/svg" | ||||||
| 				<span>{$_("logout")}</span> |           viewBox="0 0 24 24" | ||||||
| 			</button> |           ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
| 		</nav> |           <path | ||||||
| 	</div> |             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" | ||||||
| 	<div class="ml-0 transition md:ml-60"> |           /></svg | ||||||
| 		<header |         > | ||||||
| 			class="flex items-center w-full px-4 bg-white border-b h-14 md:hidden" |         <span>{$_("logout")}</span> | ||||||
| 		> |       </button> | ||||||
| 			<button |     </nav> | ||||||
| 				on:click={() => { |   </div> | ||||||
| 					navOpen = true; |   <div class="ml-0 transition md:ml-60"> | ||||||
| 				}} |     <header | ||||||
| 				class="block btn btn-light md:hidden" |       class="flex items-center w-full px-4 bg-white border-b h-14 md:hidden" | ||||||
| 			> |     > | ||||||
| 				<span class="sr-only">Menu</span><svg |       <button | ||||||
| 					xmlns="http://www.w3.org/2000/svg" |         on:click={() => { | ||||||
| 					fill="none" |           navOpen = true; | ||||||
| 					viewBox="0 0 24 24" |         }} | ||||||
| 					stroke-width="1.5" |         class="block btn btn-light md:hidden" | ||||||
| 					stroke="currentColor" |       > | ||||||
| 					class="size-6" |         <span class="sr-only">Menu</span><svg | ||||||
| 				> |           xmlns="http://www.w3.org/2000/svg" | ||||||
| 					<path |           fill="none" | ||||||
| 						stroke-linecap="round" |           viewBox="0 0 24 24" | ||||||
| 						stroke-linejoin="round" |           stroke-width="1.5" | ||||||
| 						d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" |           stroke="currentColor" | ||||||
| 					/> |           class="size-6" | ||||||
| 				</svg> |         > | ||||||
| 			</button> |           <path | ||||||
| 			<span class="inline-block"> |             stroke-linecap="round" | ||||||
| 				<img src="/lfk-logo.png" alt="Logo" class="h-8 inline-block" /> |             stroke-linejoin="round" | ||||||
| 				<span class="text-lg font-bold">LfK!Admin</span> |             d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" | ||||||
| 			</span> |           /> | ||||||
| 		</header> |         </svg> | ||||||
| 		<Toaster position="top-right" /> |       </button> | ||||||
| 		<slot> |       <span class="inline-block"> | ||||||
| 			<NoComponentLoaded /> |         <img src="/lfk-logo.png" alt="Logo" class="h-8 inline-block" /> | ||||||
| 		</slot> |         <span class="text-lg font-bold">LfK!Admin</span> | ||||||
| 	</div> |       </span> | ||||||
| 	{#if navOpen === true} |     </header> | ||||||
| 		<button |     <Toaster position="top-right" /> | ||||||
| 			on:click={() => { |     <slot> | ||||||
| 				navOpen = false; |       <NoComponentLoaded /> | ||||||
| 			}} |     </slot> | ||||||
| 			class:hidden={!navOpen} |   </div> | ||||||
| 			class="fixed inset-0 z-10 w-screen h-screen bg-black bg-opacity-25 md:hidden" |   {#if navOpen === true} | ||||||
| 		/> |     <button | ||||||
| 	{/if} |       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> | </section> | ||||||
|  |  | ||||||
| <style> | <style> | ||||||
| 	.collapsed_navigation { |   .collapsed_navigation { | ||||||
| 		transform: translateX(-100%); |     transform: translateX(-100%); | ||||||
| 	} |   } | ||||||
| 	@media (min-width: 768px) { |   @media (min-width: 768px) { | ||||||
| 		.collapsed_navigation { |     .collapsed_navigation { | ||||||
| 			transform: translateX(0px); |       transform: translateX(0px); | ||||||
| 		} |     } | ||||||
| 	} |   } | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -220,7 +220,7 @@ | |||||||
| 			<StatCard | 			<StatCard | ||||||
| 				title={$_("runner_via_selfservice")} | 				title={$_("runner_via_selfservice")} | ||||||
| 				value={stats.runnersViaSelfservice} | 				value={stats.runnersViaSelfservice} | ||||||
| 				href="/runners/" | 				href="/runners/?created_via=selfservice" | ||||||
| 			> | 			> | ||||||
| 				<svg | 				<svg | ||||||
| 					height="24" | 					height="24" | ||||||
| @@ -237,7 +237,7 @@ | |||||||
| 			<StatCard | 			<StatCard | ||||||
| 				title={$_('runners_via_kiosk')} | 				title={$_('runners_via_kiosk')} | ||||||
| 				value={stats.runnersViaKiosk} | 				value={stats.runnersViaKiosk} | ||||||
| 				href="/runners/" | 				href="/runners/?created_via=kiosk" | ||||||
| 			> | 			> | ||||||
| 				<svg | 				<svg | ||||||
| 					height="24" | 					height="24" | ||||||
|   | |||||||
| @@ -1,197 +1,256 @@ | |||||||
| <script> | <script> | ||||||
| 	import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
| 	import { |   import { | ||||||
| 		RunnerCardService, |     RunnerCardService, | ||||||
| 		RunnerOrganizationService, |     RunnerOrganizationService, | ||||||
| 		RunnerTeamService, |     RunnerTeamService, | ||||||
| 	} from "@odit/lfk-client-js"; |   } from "@odit/lfk-client-js"; | ||||||
| 	import toast from "svelte-french-toast"; |   import toast from "svelte-french-toast"; | ||||||
| 	import DocumentServer from "./DocumentServer.ts"; |   import DocumentServer from "./DocumentServer.ts"; | ||||||
|  |  | ||||||
| 	import { init } from "@paralleldrive/cuid2"; |   import { init } from "@paralleldrive/cuid2"; | ||||||
| 	const createId = init({ length: 10, fingerprint: "lfk-frontend" }); |   const createId = init({ length: 10, fingerprint: "lfk-frontend" }); | ||||||
| 	const documentServer = new DocumentServer( |   const documentServer = new DocumentServer( | ||||||
| 		config.baseurl_documentserver, |     config.baseurl_documentserver, | ||||||
| 		config.documentserver_key |     config.documentserver_key | ||||||
| 	); |   ); | ||||||
|  |  | ||||||
| 	export let cards_show = false; |   export let cards_show = false; | ||||||
| 	export let generate_cards = []; |   export let generate_cards = []; | ||||||
| 	export let generate_runners = []; |   export let generate_runners = []; | ||||||
| 	export let generate_orgs = []; |   export let generate_orgs = []; | ||||||
| 	export let generate_teams = []; |   export let generate_teams = []; | ||||||
|  |  | ||||||
| 	function download(blob, fileName) { |   function download(blob, fileName) { | ||||||
| 		const url = window.URL.createObjectURL(blob); |     const url = window.URL.createObjectURL(blob); | ||||||
| 		let a = document.createElement("a"); |     let a = document.createElement("a"); | ||||||
| 		a.href = url; |     a.href = url; | ||||||
| 		a.download = fileName; |     a.download = fileName; | ||||||
| 		document.body.appendChild(a); |     document.body.appendChild(a); | ||||||
| 		a.click(); |     a.click(); | ||||||
| 		a.remove(); |     a.remove(); | ||||||
| 		toast.dismiss(); |     toast.dismiss(); | ||||||
| 		toast.success($_("pdf-successfully-generated")); |     toast.success($_("pdf-successfully-generated")); | ||||||
| 	} |   } | ||||||
|  |  | ||||||
| 	function generateRunnerCards(locale) { |   function generateRunnerCards(locale, useCombined = false) { | ||||||
| 		if (generate_orgs.length > 0) { |     if (generate_orgs.length > 0) { | ||||||
| 			generateOrgCards(locale); | 		if(useCombined){ | ||||||
| 		} else if (generate_teams.length > 0) { | 			generateOrgCardsCombined(locale); | ||||||
| 			generateTeamCards(locale); |  | ||||||
| 		} else if (generate_runners.length > 0) { |  | ||||||
| 			generateRunnersCards(locale); |  | ||||||
| 		} else { | 		} else { | ||||||
| 			generateCards(locale); | 			generateOrgCards(locale) | ||||||
| 		} | 		} | ||||||
| 	} |     } else if (generate_teams.length > 0) { | ||||||
|  |       generateTeamCards(locale); | ||||||
|  |     } else if (generate_runners.length > 0) { | ||||||
|  |       generateRunnersCards(locale); | ||||||
|  |     } else { | ||||||
|  |       generateCards(locale); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
| 	function generateCards(locale) { |   function generateCards(locale) { | ||||||
| 		toast.loading($_("generating-pdf")); |     toast.loading($_("generating-pdf")); | ||||||
| 		documentServer |     documentServer | ||||||
| 			.generateCards(generate_cards, locale) |       .generateCards(generate_cards, locale) | ||||||
| 			.then((blob) => { |       .then((blob) => { | ||||||
| 				download(blob, `${$_("runnercards")}-${locale}-${createId()}.pdf`); |         download(blob, `${$_("runnercards")}-${locale}-${createId()}.pdf`); | ||||||
| 			}) |       }) | ||||||
| 			.catch((err) => { |       .catch((err) => { | ||||||
| 				console.error(err); |         console.error(err); | ||||||
| 			}); |       }); | ||||||
| 	} |   } | ||||||
|  |  | ||||||
| 	async function generateRunnersCards(locale) { |   async function generateRunnersCards(locale) { | ||||||
| 		toast.loading($_("generating-pdf")); |     toast.loading($_("generating-pdf")); | ||||||
| 		const current_cards = await RunnerCardService.runnerCardControllerGetAll(); |     const current_cards = await RunnerCardService.runnerCardControllerGetAll(); | ||||||
| 		let cards = []; |     let cards = []; | ||||||
| 		for (let runner of generate_runners) { |     for (let runner of generate_runners) { | ||||||
| 			let card = current_cards.find((c) => c.runner?.id == runner.id); |       let card = current_cards.find((c) => c.runner?.id == runner.id); | ||||||
| 			if (!card) { |       if (!card) { | ||||||
| 				card = await RunnerCardService.runnerCardControllerPost({ |         card = await RunnerCardService.runnerCardControllerPost({ | ||||||
| 					runner: runner.id, |           runner: runner.id, | ||||||
| 				}); |         }); | ||||||
| 			} |       } | ||||||
| 			cards.push(card); |       cards.push(card); | ||||||
| 		} |     } | ||||||
| 		documentServer |     documentServer | ||||||
| 			.generateCards(cards, locale) |       .generateCards(cards, locale) | ||||||
| 			.then((blob) => { |       .then((blob) => { | ||||||
| 				let fileName = `${$_("runnercards")}-${locale}-${createId()}.pdf`; |         let fileName = `${$_("runnercards")}-${locale}-${createId()}.pdf`; | ||||||
| 				if (generate_runners.length == 1) { |         if (generate_runners.length == 1) { | ||||||
| 					fileName = `${$_("runnercards")}_${generate_runners[0].firstname}_${ |           fileName = `${$_("runnercards")}_${generate_runners[0].firstname}_${ | ||||||
| 						generate_runners[0].lastname |             generate_runners[0].lastname | ||||||
| 					}-${locale}-${createId()}.pdf`; |           }-${locale}-${createId()}.pdf`; | ||||||
| 				} |         } | ||||||
| 				download(blob, fileName); |         download(blob, fileName); | ||||||
| 			}) |       }) | ||||||
| 			.catch((err) => {}); |       .catch((err) => {}); | ||||||
| 	} |   } | ||||||
|  |  | ||||||
| 	async function generateTeamCards(locale) { |   async function generateTeamCards(locale) { | ||||||
| 		toast.loading($_("generating-pdfs")); |     toast.loading($_("generating-pdfs")); | ||||||
| 		let count = 0; |     let count = 0; | ||||||
| 		const current_cards = await RunnerCardService.runnerCardControllerGetAll(); |     const current_cards = await RunnerCardService.runnerCardControllerGetAll(); | ||||||
| 		for (const t of generate_teams) { |     for (const t of generate_teams) { | ||||||
| 			const runners = await RunnerTeamService.runnerTeamControllerGetRunners( |       const runners = await RunnerTeamService.runnerTeamControllerGetRunners( | ||||||
| 				t.id |         t.id | ||||||
| 			); |       ); | ||||||
| 			let cards = []; |       let cards = []; | ||||||
| 			for (let runner of runners) { |       for (let runner of runners) { | ||||||
| 				let card = current_cards.find((c) => c.runner?.id == runner.id); |         let card = current_cards.find((c) => c.runner?.id == runner.id); | ||||||
| 				if (!card) { |         if (!card) { | ||||||
| 					card = await RunnerCardService.runnerCardControllerPost({ |           card = await RunnerCardService.runnerCardControllerPost({ | ||||||
| 						runner: runner.id, |             runner: runner.id, | ||||||
| 					}); |           }); | ||||||
| 				} |         } | ||||||
| 				cards.push(card); |         cards.push(card); | ||||||
| 			} |       } | ||||||
| 			documentServer |       documentServer | ||||||
| 				.generateCards(cards, locale) |         .generateCards(cards, locale) | ||||||
| 				.then((blob) => { |         .then((blob) => { | ||||||
| 					download( |           download( | ||||||
| 						blob, |             blob, | ||||||
| 						`${$_("runnercards")}_${t.name}-${locale}-${createId()}.pdf` |             `${$_("runnercards")}_${t.name}-${locale}-${createId()}.pdf` | ||||||
| 					); |           ); | ||||||
| 				}) |         }) | ||||||
| 				.catch((err) => {}); |         .catch((err) => {}); | ||||||
| 		} |     } | ||||||
| 	} |   } | ||||||
|  |  | ||||||
| 	async function generateOrgCards(locale) { |   async function generateOrgCards(locale) { | ||||||
| 		toast.loading($_("generating-pdfs")); |     toast.loading($_("generating-pdfs")); | ||||||
| 		const current_cards = await RunnerCardService.runnerCardControllerGetAll(); |     const current_cards = await RunnerCardService.runnerCardControllerGetAll(); | ||||||
| 		let count = 0; |     let count = 0; | ||||||
| 		let count_orgs = 0; |     let count_orgs = 0; | ||||||
| 		for (const o of generate_orgs) { |     for (const o of generate_orgs) { | ||||||
| 			count_orgs++; |       count_orgs++; | ||||||
| 			let count = 0; |       let count = 0; | ||||||
| 			let runners = |       let runners = | ||||||
| 				await RunnerOrganizationService.runnerOrganizationControllerGetRunners( |         await RunnerOrganizationService.runnerOrganizationControllerGetRunners( | ||||||
| 					o.id, |           o.id, | ||||||
| 					true |           true | ||||||
| 				); |         ); | ||||||
| 			let cards = []; |       let cards = []; | ||||||
| 			for (let runner of runners) { |       for (let runner of runners) { | ||||||
| 				let card = current_cards.find((c) => c.runner?.id == runner.id); |         let card = current_cards.find((c) => c.runner?.id == runner.id); | ||||||
| 				if (!card) { |         if (!card) { | ||||||
| 					card = await RunnerCardService.runnerCardControllerPost({ |           card = await RunnerCardService.runnerCardControllerPost({ | ||||||
| 						runner: runner.id, |             runner: runner.id, | ||||||
| 					}); |           }); | ||||||
| 				} |         } | ||||||
| 				cards.push(card); |         cards.push(card); | ||||||
| 			} |       } | ||||||
| 			await documentServer |       await documentServer | ||||||
| 				.generateCards(cards, locale) |         .generateCards(cards, locale) | ||||||
| 				.then((blob) => { |         .then((blob) => { | ||||||
| 					download( |           download( | ||||||
| 						blob, |             blob, | ||||||
| 						`${$_("runnercards")}_${o.name}_direct-${locale}-${createId()}.pdf` |             `${$_("runnercards")}_${o.name}_direct-${locale}-${createId()}.pdf` | ||||||
| 					); |           ); | ||||||
| 				}) |         }) | ||||||
| 				.catch((err) => {}); |         .catch((err) => {}); | ||||||
| 			for (const t of o.teams) { |       for (const t of o.teams) { | ||||||
| 				count++; |         count++; | ||||||
| 				let runners = await RunnerTeamService.runnerTeamControllerGetRunners( |         let runners = await RunnerTeamService.runnerTeamControllerGetRunners( | ||||||
| 					t.id |           t.id | ||||||
| 				); |         ); | ||||||
| 				let cards = []; |         let cards = []; | ||||||
| 				for (let runner of runners) { |         for (let runner of runners) { | ||||||
| 					let card = current_cards.find((c) => c.runner?.id == runner.id); |           let card = current_cards.find((c) => c.runner?.id == runner.id); | ||||||
| 					if (!card) { |           if (!card) { | ||||||
| 						card = await RunnerCardService.runnerCardControllerPost({ |             card = await RunnerCardService.runnerCardControllerPost({ | ||||||
| 							runner: runner.id, |               runner: runner.id, | ||||||
| 						}); |             }); | ||||||
| 					} |           } | ||||||
| 					cards.push(card); |           cards.push(card); | ||||||
| 				} |         } | ||||||
| 				await documentServer |         await documentServer | ||||||
| 					.generateCards(cards, locale) |           .generateCards(cards, locale) | ||||||
| 					.then((blob) => { |           .then((blob) => { | ||||||
| 						download( |             download( | ||||||
| 							blob, |               blob, | ||||||
| 							`${$_("runnercards")}_${o.name}_${ |               `${$_("runnercards")}_${o.name}_${ | ||||||
| 								t.name |                 t.name | ||||||
| 							}-${locale}-${createId()}.pdf` |               }-${locale}-${createId()}.pdf` | ||||||
| 						); |             ); | ||||||
| 					}) |           }) | ||||||
| 					.catch((err) => {}); |           .catch((err) => {}); | ||||||
| 			} |       } | ||||||
| 		} |     } | ||||||
| 	} |   } | ||||||
|  |   async function generateOrgCardsCombined(locale) { | ||||||
|  |     toast.loading($_("generating-pdfs")); | ||||||
|  |     const current_cards = await RunnerCardService.runnerCardControllerGetAll(); | ||||||
|  |     let count = 0; | ||||||
|  |     let count_orgs = 0; | ||||||
|  |     for (const o of generate_orgs) { | ||||||
|  |       count_orgs++; | ||||||
|  |       let cards = []; | ||||||
|  |       let count = 0; | ||||||
|  |       let runners = | ||||||
|  |         await RunnerOrganizationService.runnerOrganizationControllerGetRunners( | ||||||
|  |           o.id, | ||||||
|  |           true | ||||||
|  |         ); | ||||||
|  |       for (let runner of runners) { | ||||||
|  |         let card = current_cards.find((c) => c.runner?.id == runner.id); | ||||||
|  |         if (!card) { | ||||||
|  |           card = await RunnerCardService.runnerCardControllerPost({ | ||||||
|  |             runner: runner.id, | ||||||
|  |           }); | ||||||
|  |         } | ||||||
|  |         cards.push(card); | ||||||
|  |       } | ||||||
|  |       for (const t of o.teams) { | ||||||
|  |         count++; | ||||||
|  |         let runners = await RunnerTeamService.runnerTeamControllerGetRunners( | ||||||
|  |           t.id | ||||||
|  |         ); | ||||||
|  |         for (let runner of runners) { | ||||||
|  |           let card = current_cards.find((c) => c.runner?.id == runner.id); | ||||||
|  |           if (!card) { | ||||||
|  |             card = await RunnerCardService.runnerCardControllerPost({ | ||||||
|  |               runner: runner.id, | ||||||
|  |             }); | ||||||
|  |           } | ||||||
|  |           cards.push(card); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       await documentServer | ||||||
|  |         .generateCards(cards, locale) | ||||||
|  |         .then((blob) => { | ||||||
|  |           download( | ||||||
|  |             blob, | ||||||
|  |             `${$_("runnercards")}_${o.name}-${locale}-${createId()}.pdf` | ||||||
|  |           ); | ||||||
|  |         }) | ||||||
|  |         .catch((err) => {}); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| {#if cards_show} | {#if cards_show} | ||||||
| 	<button |   <button | ||||||
| 		on:click={() => { |     on:click={() => { | ||||||
| 			generateRunnerCards("de"); |       generateRunnerCards("de"); | ||||||
| 		}} |     }} | ||||||
| 		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" |     on:contextmenu|preventDefault={() => { | ||||||
| 	> |       generateRunnerCards("de", true); | ||||||
| 		{$_("generate-runnercards")}: DE |     }} | ||||||
| 	</button> |     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" | ||||||
| 	<button |   > | ||||||
| 		on:click={() => { |     {$_("generate-runnercards")}: DE | ||||||
| 			generateRunnerCards("en"); |   </button> | ||||||
| 		}} |   <button | ||||||
| 		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" |     on:click={() => { | ||||||
| 	> |       generateRunnerCards("en"); | ||||||
| 		{$_("generate-runnercards")}: EN |     }} | ||||||
| 	</button> | 	on:contextmenu|preventDefault={() => { | ||||||
|  |       generateRunnerCards("en", true); | ||||||
|  |     }} | ||||||
|  |     class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm mb-1 lg:mb-0" | ||||||
|  |   > | ||||||
|  |     {$_("generate-runnercards")}: EN | ||||||
|  |   </button> | ||||||
| {/if} | {/if} | ||||||
|   | |||||||
| @@ -289,6 +289,13 @@ | |||||||
| 			<br /> | 			<br /> | ||||||
| 			<span class="text-gray-700">{original_data.distance / 1000} km</span> | 			<span class="text-gray-700">{original_data.distance / 1000} km</span> | ||||||
| 		</div> | 		</div> | ||||||
|  | 		<div class="text-sm w-full mt-2"> | ||||||
|  | 			<span class="font-semibold text-gray-700">{$_("total-donation-amount")}</span> | ||||||
|  | 			<br /> | ||||||
|  | 			<span class="text-gray-700">{(editable.donationAmount / 100) | ||||||
|  | 					.toFixed(2) | ||||||
|  | 					.toLocaleString("de-DE", { valute: "EUR" })}€</span> | ||||||
|  | 		</div> | ||||||
| 		<div class="text-sm w-full mt-2"> | 		<div class="text-sm w-full mt-2"> | ||||||
| 			<span class="font-semibold text-gray-700">{$_("created_via")}</span> | 			<span class="font-semibold text-gray-700">{$_("created_via")}</span> | ||||||
| 			<br /> | 			<br /> | ||||||
|   | |||||||
| @@ -1,337 +1,342 @@ | |||||||
| <script> | <script> | ||||||
| 	import { |   import { | ||||||
| 		RunnerOrganizationService, |     RunnerOrganizationService, | ||||||
| 		RunnerService, |     RunnerService, | ||||||
| 		RunnerTeamService, |     RunnerTeamService, | ||||||
| 	} from "@odit/lfk-client-js"; |   } from "@odit/lfk-client-js"; | ||||||
| 	import { |   import { | ||||||
| 		createSvelteTable, |     createSvelteTable, | ||||||
| 		flexRender, |     flexRender, | ||||||
| 		getCoreRowModel, |     getCoreRowModel, | ||||||
| 		getFilteredRowModel, |     getFilteredRowModel, | ||||||
| 		getPaginationRowModel, |     getPaginationRowModel, | ||||||
| 		getSortedRowModel, |     getSortedRowModel, | ||||||
| 		renderComponent, |     renderComponent, | ||||||
| 	} from "@tanstack/svelte-table"; |   } from "@tanstack/svelte-table"; | ||||||
| 	import { onMount } from "svelte"; |   import { onMount } from "svelte"; | ||||||
| 	import { writable } from "svelte/store"; |   import { writable } from "svelte/store"; | ||||||
| 	import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte"; |   import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte"; | ||||||
| 	import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte"; |   import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte"; | ||||||
| 	import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte"; |   import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte"; | ||||||
| 	import InputElement from "../shared/InputElement.svelte"; |   import InputElement from "../shared/InputElement.svelte"; | ||||||
| 	import TableActions from "../shared/TableActions.svelte"; |   import TableActions from "../shared/TableActions.svelte"; | ||||||
| 	import { groupFilter } from "../shared/tablefilters"; |   import { groupFilter } from "../shared/tablefilters"; | ||||||
| 	import DeleteRunnerModal from "./DeleteRunnerModal.svelte"; |   import DeleteRunnerModal from "./DeleteRunnerModal.svelte"; | ||||||
| 	import TableBottom from "../shared/TableBottom.svelte"; |   import TableBottom from "../shared/TableBottom.svelte"; | ||||||
| 	import TableHeader from "../shared/TableHeader.svelte"; |   import TableHeader from "../shared/TableHeader.svelte"; | ||||||
|  |  | ||||||
| 	$: selectedRunners = |   $: selectedRunners = | ||||||
| 		$table?.getSelectedRowModel().rows.map((row) => row.original) || []; |     $table?.getSelectedRowModel().rows.map((row) => row.original) || []; | ||||||
| 	$: selected = |   $: selected = | ||||||
| 		$table?.getSelectedRowModel().rows.map((row) => row.index) || []; |     $table?.getSelectedRowModel().rows.map((row) => row.index) || []; | ||||||
|  |  | ||||||
| 	$: active_delete = undefined; |   $: active_delete = undefined; | ||||||
| 	let dataLoaded = false; |   let dataLoaded = false; | ||||||
| 	export let created_via = "all"; |   export let created_via = "all"; | ||||||
| 	export let current_runners = []; |   export let current_runners = []; | ||||||
| 	$: sponsoring_contracts_show = selected.length > 0; |   $: sponsoring_contracts_show = selected.length > 0; | ||||||
| 	$: cards_show = selected.length > 0; |   $: cards_show = selected.length > 0; | ||||||
| 	$: certificates_show = selected.length > 0; |   $: certificates_show = selected.length > 0; | ||||||
| 	$: teams = []; |   $: teams = []; | ||||||
| 	$: orgs = []; |   $: orgs = []; | ||||||
|  |  | ||||||
| 	export const addRunners = (runners) => { |   export const addRunners = (runners) => { | ||||||
| 		current_runners = current_runners.concat(...runners); |     current_runners = current_runners.concat(...runners); | ||||||
| 		options.update((options) => ({ |     options.update((options) => ({ | ||||||
| 			...options, |       ...options, | ||||||
| 			data: current_runners, |       data: current_runners, | ||||||
| 		})); |     })); | ||||||
| 	}; |   }; | ||||||
|  |  | ||||||
| 	//Section table |   //Section table | ||||||
| 	const columns = [ |   const columns = [ | ||||||
| 		{ |     { | ||||||
| 			accessorKey: "id", |       accessorKey: "id", | ||||||
| 			header: () => "id", |       header: () => "id", | ||||||
| 			filterFn: `equalsString`, |       filterFn: `equalsString`, | ||||||
| 		}, |     }, | ||||||
| 		{ |     { | ||||||
| 			accessorKey: "firstname", |       accessorKey: "firstname", | ||||||
| 			header: () => $_("first-name"), |       header: () => $_("first-name"), | ||||||
| 			filterFn: `includesString`, |       filterFn: `includesString`, | ||||||
| 		}, |     }, | ||||||
| 		{ |     { | ||||||
| 			accessorKey: "middlename", |       accessorKey: "middlename", | ||||||
| 			header: () => $_("middle-name"), |       header: () => $_("middle-name"), | ||||||
| 			cell: (info) => { |       cell: (info) => { | ||||||
| 				if (!info || !info.getValue()) { |         if (!info || !info.getValue()) { | ||||||
| 					return ""; |           return ""; | ||||||
| 				} |         } | ||||||
| 				return info.getValue(); |         return info.getValue(); | ||||||
| 			}, |       }, | ||||||
| 			filterFn: `includesString`, |       filterFn: `includesString`, | ||||||
| 		}, |     }, | ||||||
| 		{ |     { | ||||||
| 			accessorKey: "lastname", |       accessorKey: "lastname", | ||||||
| 			header: () => $_("last-name"), |       header: () => $_("last-name"), | ||||||
| 			filterFn: `includesString`, |       filterFn: `includesString`, | ||||||
| 		}, |     }, | ||||||
| 		{ |     { | ||||||
| 			accessorKey: "created_via", |       accessorKey: "created_via", | ||||||
| 			header: () => "created_via", |       header: () => "created_via", | ||||||
| 			filterFn: `includesString`, |       filterFn: `includesString`, | ||||||
| 		}, |     }, | ||||||
| 		{ |     { | ||||||
| 			accessorKey: "group", |       accessorKey: "group", | ||||||
| 			header: () => $_("group"), |       header: () => $_("group"), | ||||||
| 			cell: (info) => { |       cell: (info) => { | ||||||
| 				const group = info.getValue(); |         const group = info.getValue(); | ||||||
| 				if (group.responseType === "RUNNERORGANIZATION") { |         if (group.responseType === "RUNNERORGANIZATION") { | ||||||
| 					return group.name; |           return group.name; | ||||||
| 				} |         } | ||||||
| 				return `${group.parentGroup.name} > ${group.name}`; |         return `${group.parentGroup.name} > ${group.name}`; | ||||||
| 			}, |       }, | ||||||
| 			filterFn: `group`, |       filterFn: `group`, | ||||||
| 			sortingFn: (rowA, rowB, col) => { |       sortingFn: (rowA, rowB, col) => { | ||||||
| 				return rowA.original.group.name.localeCompare(rowB.original.group.name); |         return rowA.original.group.name.localeCompare(rowB.original.group.name); | ||||||
| 			}, |       }, | ||||||
| 		}, |     }, | ||||||
| 		{ |     { | ||||||
| 			accessorKey: "distance", |       accessorKey: "distance", | ||||||
| 			header: () => $_("distance"), |       header: () => $_("distance"), | ||||||
| 			sortingFn: (rowA, rowB, col) => { |       sortingFn: (rowA, rowB, col) => { | ||||||
| 				return rowA.original.distance > rowB.original.distance; |         return rowA.original.distance > rowB.original.distance; | ||||||
| 			}, |       }, | ||||||
| 			cell: (info) => { |       cell: (info) => { | ||||||
| 				if (info.getValue() < 1000) { |         if (info.getValue() < 1000) { | ||||||
| 					return `${info.getValue()} m`; |           return `${info.getValue()} m`; | ||||||
| 				} |         } | ||||||
| 				return `${(info.getValue() / 1000).toFixed(1)} km`; |         return `${(info.getValue() / 1000).toFixed(1)} km`; | ||||||
| 			}, |       }, | ||||||
| 			enableColumnFilter: false, |       enableColumnFilter: false, | ||||||
| 		}, |     }, | ||||||
| 		{ |     { | ||||||
| 			accessorKey: "actions", |       accessorKey: "actions", | ||||||
| 			header: () => $_("action"), |       header: () => $_("action"), | ||||||
| 			cell: (info) => { |       cell: (info) => { | ||||||
| 				return renderComponent(TableActions, { |         return renderComponent(TableActions, { | ||||||
| 					detailsLink: `/runners/${info.row.original.id}`, |           detailsLink: `/runners/${info.row.original.id}`, | ||||||
| 					deleteAction: () => { |           deleteAction: () => { | ||||||
| 						active_delete = |             active_delete = | ||||||
| 							current_runners[ |               current_runners[ | ||||||
| 								current_runners.findIndex((r) => r.id == info.row.original.id) |                 current_runners.findIndex((r) => r.id == info.row.original.id) | ||||||
| 							]; |               ]; | ||||||
| 					}, |           }, | ||||||
| 					deleteEnabled: |           deleteEnabled: | ||||||
| 						store.state.jwtinfo.userdetails.permissions.includes( |             store.state.jwtinfo.userdetails.permissions.includes( | ||||||
| 							"RUNNER:DELETE" |               "RUNNER:DELETE" | ||||||
| 						), |             ), | ||||||
| 				}); |         }); | ||||||
| 			}, |       }, | ||||||
| 			enableColumnFilter: false, |       enableColumnFilter: false, | ||||||
| 			enableSorting: false, |       enableSorting: false, | ||||||
| 		}, |     }, | ||||||
| 	]; |   ]; | ||||||
| 	const options = writable({ |   const options = writable({ | ||||||
| 		data: [], |     data: [], | ||||||
| 		columns: columns, |     columns: columns, | ||||||
| 		filterFns: { |     filterFns: { | ||||||
| 			group: groupFilter, |       group: groupFilter, | ||||||
| 		}, |     }, | ||||||
| 		initialState: { |     initialState: { | ||||||
| 			pagination: { |       pagination: { | ||||||
| 				pageSize: 50, |         pageSize: 50, | ||||||
| 			}, |       }, | ||||||
| 		}, |     }, | ||||||
| 		enableRowSelection: true, |     enableRowSelection: true, | ||||||
| 		getCoreRowModel: getCoreRowModel(), |     getCoreRowModel: getCoreRowModel(), | ||||||
| 		getFilteredRowModel: getFilteredRowModel(), |     getFilteredRowModel: getFilteredRowModel(), | ||||||
| 		getPaginationRowModel: getPaginationRowModel(), |     getPaginationRowModel: getPaginationRowModel(), | ||||||
| 		getSortedRowModel: getSortedRowModel(), |     getSortedRowModel: getSortedRowModel(), | ||||||
| 	}); |   }); | ||||||
| 	const table = createSvelteTable(options); |   const table = createSvelteTable(options); | ||||||
|  |  | ||||||
| 	async function deleteRunner(delete_runner_id) { |   async function deleteRunner(delete_runner_id) { | ||||||
| 		await RunnerService.runnerControllerRemove(delete_runner_id, true); |     await RunnerService.runnerControllerRemove(delete_runner_id, true); | ||||||
| 		current_runners = current_runners.filter((r) => r.id !== delete_runner_id); |     current_runners = current_runners.filter((r) => r.id !== delete_runner_id); | ||||||
| 		options.update((options) => ({ |     options.update((options) => ({ | ||||||
| 			...options, |       ...options, | ||||||
| 			data: current_runners, |       data: current_runners, | ||||||
| 		})); |     })); | ||||||
| 		toast.success($_("runner-deleted")); |     toast.success($_("runner-deleted")); | ||||||
| 	} |   } | ||||||
|  |  | ||||||
| 	onMount(async () => { |   onMount(async () => { | ||||||
| 		RunnerTeamService.runnerTeamControllerGetAll().then((val) => { |     RunnerTeamService.runnerTeamControllerGetAll().then((val) => { | ||||||
| 			teams = val; |       teams = val; | ||||||
| 		}); |     }); | ||||||
| 		RunnerOrganizationService.runnerOrganizationControllerGetAll().then( |     RunnerOrganizationService.runnerOrganizationControllerGetAll().then( | ||||||
| 			(val) => { |       (val) => { | ||||||
| 				orgs = val; |         orgs = val; | ||||||
| 			} |       } | ||||||
| 		); |     ); | ||||||
|  |  | ||||||
| 		let page = 0; |     let page = 0; | ||||||
| 		while (page >= 0) { |     while (page >= 0) { | ||||||
| 			const runners = await RunnerService.runnerControllerGetAll( |       const runners = await RunnerService.runnerControllerGetAll( | ||||||
| 				page, |         page, | ||||||
| 				500, |         500, | ||||||
| 				created_via |       ); | ||||||
| 			); |       if (runners.length == 0) { | ||||||
| 			if (runners.length == 0) { |         page = -2; | ||||||
| 				page = -2; |       } | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			current_runners = current_runners.concat(...runners); |       current_runners = current_runners.concat(...runners); | ||||||
| 			options.update((options) => ({ |       options.update((options) => ({ | ||||||
| 				...options, |         ...options, | ||||||
| 				data: current_runners, |         data: current_runners, | ||||||
| 			})); |       })); | ||||||
|  |  | ||||||
| 			dataLoaded = true; |       dataLoaded = true; | ||||||
| 			page++; |       page++; | ||||||
| 		} |     } | ||||||
| 	}); |   }); | ||||||
| 	import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
| 	import store from "../../store"; |   import store from "../../store"; | ||||||
| 	import AddRunnerModal from "./AddRunnerModal.svelte"; |   import AddRunnerModal from "./AddRunnerModal.svelte"; | ||||||
| 	import ImportRunnerModal from "./ImportRunnerModal.svelte"; |   import ImportRunnerModal from "./ImportRunnerModal.svelte"; | ||||||
| 	import toast from "svelte-french-toast"; |   import toast from "svelte-french-toast"; | ||||||
| 	$: current_runners = []; |   $: current_runners = []; | ||||||
| 	export let modal_open = false; |   export let modal_open = false; | ||||||
| 	export let import_modal_open = false; |   export let import_modal_open = false; | ||||||
|  |  | ||||||
|  |   if (created_via != "all") { | ||||||
|  |     $table.setColumnFilters([ | ||||||
|  |       { | ||||||
|  |         id: "created_via", | ||||||
|  |         value: created_via, | ||||||
|  |       }, | ||||||
|  |     ]); | ||||||
|  |   } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
| 	<h4 class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight"> | ||||||
| 		{$_("runners")} |     {$_("runners")} | ||||||
| 	</h4> |   </h4> | ||||||
| 	{#if created_via !== "all"} |   {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")} | ||||||
| 		<p>created_via={created_via}</p> |     <button | ||||||
| 	{/if} |       on:click={() => { | ||||||
| 	{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")} |         modal_open = true; | ||||||
| 		<button |       }} | ||||||
| 			on:click={() => { |       type="button" | ||||||
| 				modal_open = true; |       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" | ||||||
| 			}} |     > | ||||||
| 			type="button" |       {$_("laeufer-hinzufuegen")} | ||||||
| 			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" |     </button> | ||||||
| 		> |     <button | ||||||
| 			{$_("laeufer-hinzufuegen")} |       on:click={() => { | ||||||
| 		</button> |         import_modal_open = true; | ||||||
| 		<button |       }} | ||||||
| 			on:click={() => { |       type="button" | ||||||
| 				import_modal_open = true; |       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" | ||||||
| 			}} |     > | ||||||
| 			type="button" |       {$_("import-runners")} | ||||||
| 			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" |     </button> | ||||||
| 		> |   {/if} | ||||||
| 			{$_("import-runners")} |   <DeleteRunnerModal | ||||||
| 		</button> |     delete_runner={active_delete} | ||||||
| 	{/if} |     modal_open={active_delete != undefined} | ||||||
| 	<DeleteRunnerModal |     on:delete={(event) => { | ||||||
| 		delete_runner={active_delete} |       deleteRunner(event.detail.id); | ||||||
| 		modal_open={active_delete != undefined} |     }} | ||||||
| 		on:delete={(event) => { |   /> | ||||||
| 			deleteRunner(event.detail.id); |   {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")} | ||||||
| 		}} |     {#if !dataLoaded} | ||||||
| 	/> |       <div | ||||||
| 	{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")} |         class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" | ||||||
| 		{#if !dataLoaded} |         role="alert" | ||||||
| 			<div |       > | ||||||
| 				class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" |         <p class="font-bold">{$_("runners-are-being-loaded")}</p> | ||||||
| 				role="alert" |         <p class="text-sm">{$_("this-might-take-a-moment")}</p> | ||||||
| 			> |       </div> | ||||||
| 				<p class="font-bold">{$_("runners-are-being-loaded")}</p> |     {:else} | ||||||
| 				<p class="text-sm">{$_("this-might-take-a-moment")}</p> |       <GenerateSponsoringContracts | ||||||
| 			</div> |         bind:sponsoring_contracts_show | ||||||
| 		{:else} |         bind:generate_runners={selectedRunners} | ||||||
| 			<GenerateSponsoringContracts |       /> | ||||||
| 				bind:sponsoring_contracts_show |       <GenerateRunnerCards | ||||||
| 				bind:generate_runners={selectedRunners} |         bind:cards_show | ||||||
| 			/> |         bind:generate_runners={selectedRunners} | ||||||
| 			<GenerateRunnerCards |       /> | ||||||
| 				bind:cards_show |       <GenerateRunnerCertificates | ||||||
| 				bind:generate_runners={selectedRunners} |         bind:certificates_show | ||||||
| 			/> |         bind:generate_runners={selectedRunners} | ||||||
| 			<GenerateRunnerCertificates |       /> | ||||||
| 				bind:certificates_show |       <div class="overflow-x-auto"> | ||||||
| 				bind:generate_runners={selectedRunners} |         <table class="w-full"> | ||||||
| 			/> |           <thead class="border-b border-gray-400"> | ||||||
| 			<div class="overflow-x-auto"> |             {#each $table.getHeaderGroups() as headerGroup} | ||||||
| 				<table class="w-full"> |               <tr class="select-none"> | ||||||
| 					<thead class="border-b border-gray-400"> |                 <th class="inset-y-0 left-0 px-4 py-2 text-left w-px"> | ||||||
| 						{#each $table.getHeaderGroups() as headerGroup} |                   <InputElement | ||||||
| 							<tr class="select-none"> |                     type="checkbox" | ||||||
| 								<th class="inset-y-0 left-0 px-4 py-2 text-left w-px"> |                     checked={$table.getIsAllRowsSelected()} | ||||||
| 									<InputElement |                     indeterminate={$table.getIsSomeRowsSelected()} | ||||||
| 										type="checkbox" |                     on:change={() => $table.toggleAllRowsSelected()} | ||||||
| 										checked={$table.getIsAllRowsSelected()} |                   /> | ||||||
| 										indeterminate={$table.getIsSomeRowsSelected()} |                 </th> | ||||||
| 										on:change={() => $table.toggleAllRowsSelected()} |                 {#each headerGroup.headers as header} | ||||||
| 									/> |                   <TableHeader {header} /> | ||||||
| 								</th> |                 {/each} | ||||||
| 								{#each headerGroup.headers as header} |               </tr> | ||||||
| 									<TableHeader {header} /> |             {/each} | ||||||
| 								{/each} |           </thead> | ||||||
| 							</tr> |           <tbody> | ||||||
| 						{/each} |             {#each $table.getRowModel().rows as row} | ||||||
| 					</thead> |               <tr class="odd:bg-white even:bg-gray-100"> | ||||||
| 					<tbody> |                 <td class="inset-y-0 left-0 px-4 py-2 text-center w-px"> | ||||||
| 						{#each $table.getRowModel().rows as row} |                   <InputElement | ||||||
| 							<tr class="odd:bg-white even:bg-gray-100"> |                     type="checkbox" | ||||||
| 								<td class="inset-y-0 left-0 px-4 py-2 text-center w-px"> |                     checked={row.getIsSelected()} | ||||||
| 									<InputElement |                     on:change={() => row.toggleSelected()} | ||||||
| 										type="checkbox" |                   /> | ||||||
| 										checked={row.getIsSelected()} |                 </td> | ||||||
| 										on:change={() => row.toggleSelected()} |                 {#each row.getVisibleCells() as cell} | ||||||
| 									/> |                   <td> | ||||||
| 								</td> |                     <svelte:component | ||||||
| 								{#each row.getVisibleCells() as cell} |                       this={flexRender( | ||||||
| 									<td> |                         cell.column.columnDef.cell, | ||||||
| 										<svelte:component |                         cell.getContext() | ||||||
| 											this={flexRender( |                       )} | ||||||
| 												cell.column.columnDef.cell, |                     /> | ||||||
| 												cell.getContext() |                   </td> | ||||||
| 											)} |                 {/each} | ||||||
| 										/> |               </tr> | ||||||
| 									</td> |             {/each} | ||||||
| 								{/each} |           </tbody> | ||||||
| 							</tr> |         </table> | ||||||
| 						{/each} |       </div> | ||||||
| 					</tbody> |       <div class="h-2" /> | ||||||
| 				</table> |     {/if} | ||||||
| 			</div> |   {/if} | ||||||
| 			<div class="h-2" /> |   <TableBottom {table} {selected} /> | ||||||
| 		{/if} |  | ||||||
| 	{/if} |  | ||||||
| 	<TableBottom {table} {selected} /> |  | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
| {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")} | {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")} | ||||||
| 	<AddRunnerModal |   <AddRunnerModal | ||||||
| 		bind:modal_open |     bind:modal_open | ||||||
| 		on:created={(event) => { |     on:created={(event) => { | ||||||
| 			addRunners(event.detail.runners); |       addRunners(event.detail.runners); | ||||||
| 		}} |     }} | ||||||
| 	/> |   /> | ||||||
| 	<ImportRunnerModal |   <ImportRunnerModal | ||||||
| 		on:cancelDelete={(event) => { |     on:cancelDelete={(event) => { | ||||||
| 			import_modal_open = false; |       import_modal_open = false; | ||||||
| 		}} |     }} | ||||||
| 		passed_team={{}} |     passed_team={{}} | ||||||
| 		passed_orgs={[]} |     passed_orgs={[]} | ||||||
| 		passed_org={{}} |     passed_org={{}} | ||||||
| 		opened_from="RunnerOverview" |     opened_from="RunnerOverview" | ||||||
| 		bind:import_modal_open |     bind:import_modal_open | ||||||
| 		on:created={(event) => { |     on:created={(event) => { | ||||||
| 			addRunners(event.detail.runners); |       addRunners(event.detail.runners); | ||||||
| 		}} |     }} | ||||||
| 	/> |   /> | ||||||
| {/if} | {/if} | ||||||
|  |  | ||||||
| <style> | <style> | ||||||
| 	table tbody tr td:nth-child(2) { |   table tbody tr td:nth-child(2) { | ||||||
| 		font-family: monospace; |     font-family: monospace; | ||||||
| 	} |   } | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -296,6 +296,7 @@ | |||||||
|     "logout": "Abmelden", |     "logout": "Abmelden", | ||||||
|     "mail-validation-in-progress": "E-Mail Verifizierung läuft... ", |     "mail-validation-in-progress": "E-Mail Verifizierung läuft... ", | ||||||
|     "manage-admin-users": "Nutzer verwalten", |     "manage-admin-users": "Nutzer verwalten", | ||||||
|  |     "management": "Verwaltung", | ||||||
|     "middle-name": "Mittelname", |     "middle-name": "Mittelname", | ||||||
|     "minimum-lap-time-in-s": "Minimale Rundenzeit (in Sekunden)", |     "minimum-lap-time-in-s": "Minimale Rundenzeit (in Sekunden)", | ||||||
|     "minimum-lap-time-must-be-a-positive-number-or-0": "Die minimale Rundenzeit muss eine positive Zahl oder 0 sein", |     "minimum-lap-time-must-be-a-positive-number-or-0": "Die minimale Rundenzeit muss eine positive Zahl oder 0 sein", | ||||||
| @@ -375,6 +376,7 @@ | |||||||
|     "profile-deleted": "Profil gelöscht!", |     "profile-deleted": "Profil gelöscht!", | ||||||
|     "profile-picture": "Profilbild", |     "profile-picture": "Profilbild", | ||||||
|     "profile-updated": "Profil wurde aktualisiert!", |     "profile-updated": "Profil wurde aktualisiert!", | ||||||
|  |     "quick-tools": "Werkzeuge", | ||||||
|     "read-license": "Lizenz-Text lesen", |     "read-license": "Lizenz-Text lesen", | ||||||
|     "receipt-needed": "Spendenquittung benötigt", |     "receipt-needed": "Spendenquittung benötigt", | ||||||
|     "repo_link": "Link", |     "repo_link": "Link", | ||||||
| @@ -439,6 +441,7 @@ | |||||||
|     "status": "Status", |     "status": "Status", | ||||||
|     "stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können", |     "stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können", | ||||||
|     "successful-password-reset": "Passwort erfolgreich zurückgesetzt!", |     "successful-password-reset": "Passwort erfolgreich zurückgesetzt!", | ||||||
|  |     "system": "System", | ||||||
|     "team": "Team", |     "team": "Team", | ||||||
|     "team-added": "Team wurde erstellt", |     "team-added": "Team wurde erstellt", | ||||||
|     "team-deleted": "Team gelöscht", |     "team-deleted": "Team gelöscht", | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ | |||||||
|     "author": "Author", |     "author": "Author", | ||||||
|     "available-permissions": "available", |     "available-permissions": "available", | ||||||
|     "average-distance": "∅ distance", |     "average-distance": "∅ distance", | ||||||
|     "average-donation": "∅ donation", |     "average-donation": "∅ Donation", | ||||||
|     "barcode_scanner": "Scan via barcode scanner", |     "barcode_scanner": "Scan via barcode scanner", | ||||||
|     "by": "by", |     "by": "by", | ||||||
|     "cancel": "Cancel", |     "cancel": "Cancel", | ||||||
| @@ -375,6 +375,7 @@ | |||||||
|     "profile-deleted": "Profile deleted!", |     "profile-deleted": "Profile deleted!", | ||||||
|     "profile-picture": "Profile Picture", |     "profile-picture": "Profile Picture", | ||||||
|     "profile-updated": "Profile updated!", |     "profile-updated": "Profile updated!", | ||||||
|  |     "quick-tools": "Tools", | ||||||
|     "read-license": "Read License", |     "read-license": "Read License", | ||||||
|     "receipt-needed": "Receipt needed", |     "receipt-needed": "Receipt needed", | ||||||
|     "repo_link": "Link", |     "repo_link": "Link", | ||||||
| @@ -388,7 +389,7 @@ | |||||||
|     "runner-is-being-added": "Runner is being added...", |     "runner-is-being-added": "Runner is being added...", | ||||||
|     "runner-updated": "Runner updated!", |     "runner-updated": "Runner updated!", | ||||||
|     "runner_not_found": "Runner not found...", |     "runner_not_found": "Runner not found...", | ||||||
|     "runner_via_selfservice": "Runner via Selfservice", |     "runner_via_selfservice": "Runners via Selfservice", | ||||||
|     "runnercards": "Runnercards", |     "runnercards": "Runnercards", | ||||||
|     "runnerimport_verify_runners_org": "Please confirm these runners for import into the organization \"{org_name}\"", |     "runnerimport_verify_runners_org": "Please confirm these runners for import into the organization \"{org_name}\"", | ||||||
|     "runners": "Runners", |     "runners": "Runners", | ||||||
| @@ -439,6 +440,7 @@ | |||||||
|     "status": "Status", |     "status": "Status", | ||||||
|     "stuff-that-could-harm-your-profile": "Stuff that could harm your profile", |     "stuff-that-could-harm-your-profile": "Stuff that could harm your profile", | ||||||
|     "successful-password-reset": "Successful password reset!", |     "successful-password-reset": "Successful password reset!", | ||||||
|  |     "system": "System", | ||||||
|     "team": "Team", |     "team": "Team", | ||||||
|     "team-added": "Team added", |     "team-added": "Team added", | ||||||
|     "team-deleted": "Team deleted", |     "team-deleted": "Team deleted", | ||||||
| @@ -468,12 +470,12 @@ | |||||||
|     "timestamp": "timestamp", |     "timestamp": "timestamp", | ||||||
|     "token": "Token", |     "token": "Token", | ||||||
|     "total-distance": "total distance", |     "total-distance": "total distance", | ||||||
|     "total-donation-amount": "total donation amount", |     "total-donation-amount": "Total donations", | ||||||
|     "total-donation-count": "total donations (count)", |     "total-donation-count": "Donations (count)", | ||||||
|     "total-donations": "total donations", |     "total-donations": "Donations (amount)", | ||||||
|     "total-donors": "total donors", |     "total-donors": "Donors", | ||||||
|     "total-paid-amount": "Paid", |     "total-paid-amount": "Paid", | ||||||
|     "total-scans": "total scans", |     "total-scans": "Scans", | ||||||
|     "total_donation_amount_in_eur": "Total donation amount in €", |     "total_donation_amount_in_eur": "Total donation amount in €", | ||||||
|     "track": "Track", |     "track": "Track", | ||||||
|     "track-added": "Track added", |     "track-added": "Track added", | ||||||
|   | |||||||
| @@ -43,8 +43,8 @@ const store = () => { | |||||||
|         // |         // | ||||||
|         state.refreshInterval = setInterval(() => { |         state.refreshInterval = setInterval(() => { | ||||||
|           this.refreshAuth(); |           this.refreshAuth(); | ||||||
|           // 2min |           // 60min | ||||||
|         }, 2 * 60000); |         }, 60 * 60000); | ||||||
|         // |         // | ||||||
|         return state; |         return state; | ||||||
|       }); |       }); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user