Compare commits
	
		
			28 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						528b025e55
	
				 | 
					
					
						|||
| 
						
						
							
						
						368e97c6bb
	
				 | 
					
					
						|||
| 
						
						
							
						
						6acd8bb634
	
				 | 
					
					
						|||
| 
						
						
							
						
						6dcdba6568
	
				 | 
					
					
						|||
| 
						
						
							
						
						525c096f7a
	
				 | 
					
					
						|||
| 
						
						
							
						
						0de50822cd
	
				 | 
					
					
						|||
| 
						
						
							
						
						0177c50651
	
				 | 
					
					
						|||
| 
						
						
							
						
						f7575f46e4
	
				 | 
					
					
						|||
| 
						
						
							
						
						a8d90d4882
	
				 | 
					
					
						|||
| 
						
						
							
						
						a2ffa5055e
	
				 | 
					
					
						|||
| 
						
						
							
						
						b969932582
	
				 | 
					
					
						|||
| 
						
						
							
						
						72ace57cb3
	
				 | 
					
					
						|||
| 
						
						
							
						
						16f9228390
	
				 | 
					
					
						|||
| 
						
						
							
						
						16d15f7242
	
				 | 
					
					
						|||
| 
						
						
							
						
						115767c656
	
				 | 
					
					
						|||
| 
						
						
							
						
						bb3c801908
	
				 | 
					
					
						|||
| 
						
						
							
						
						e512325115
	
				 | 
					
					
						|||
| 
						
						
							
						
						aa7d2dbe1b
	
				 | 
					
					
						|||
| 
						
						
							
						
						01cd8d4b78
	
				 | 
					
					
						|||
| 
						
						
							
						
						c7c1c6dc41
	
				 | 
					
					
						|||
| 
						
						
							
						
						bf8b351b64
	
				 | 
					
					
						|||
| 
						
						
							
						
						58830c5db3
	
				 | 
					
					
						|||
| 
						
						
							
						
						066e67c64f
	
				 | 
					
					
						|||
| 
						
						
							
						
						5f5b03a8a0
	
				 | 
					
					
						|||
| 
						
						
							
						
						cbfbd92d0e
	
				 | 
					
					
						|||
| 
						
						
							
						
						418fe7773f
	
				 | 
					
					
						|||
| 
						
						
							
						
						4b6e11d8d2
	
				 | 
					
					
						|||
| 
						
						
							
						
						0698038523
	
				 | 
					
					
						
							
								
								
									
										131
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								.drone.yml
									
									
									
									
									
								
							@@ -1,131 +0,0 @@
 | 
				
			|||||||
---
 | 
					 | 
				
			||||||
kind: secret
 | 
					 | 
				
			||||||
name: docker_username
 | 
					 | 
				
			||||||
get:
 | 
					 | 
				
			||||||
  path: odit-registry-builder
 | 
					 | 
				
			||||||
  name: username
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
kind: secret
 | 
					 | 
				
			||||||
name: docker_password
 | 
					 | 
				
			||||||
get:
 | 
					 | 
				
			||||||
  path: odit-registry-builder
 | 
					 | 
				
			||||||
  name: password
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
kind: secret
 | 
					 | 
				
			||||||
name: npm_url
 | 
					 | 
				
			||||||
get:
 | 
					 | 
				
			||||||
  path: odit-npm-cache
 | 
					 | 
				
			||||||
  name: url
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
kind: pipeline
 | 
					 | 
				
			||||||
type: kubernetes
 | 
					 | 
				
			||||||
name: build:latest
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
steps:
 | 
					 | 
				
			||||||
  - name: docker release
 | 
					 | 
				
			||||||
    image: registry.odit.services/library/drone-kaniko
 | 
					 | 
				
			||||||
    depends_on: [clone]
 | 
					 | 
				
			||||||
    settings:
 | 
					 | 
				
			||||||
      username:
 | 
					 | 
				
			||||||
        from_secret: docker_username
 | 
					 | 
				
			||||||
      password:
 | 
					 | 
				
			||||||
        from_secret: docker_password
 | 
					 | 
				
			||||||
      build_args:
 | 
					 | 
				
			||||||
        - NPM_REGISTRY_URL:
 | 
					 | 
				
			||||||
          from_secret: npm_url
 | 
					 | 
				
			||||||
      repo: lfk/kiosk
 | 
					 | 
				
			||||||
      tags:
 | 
					 | 
				
			||||||
        - latest
 | 
					 | 
				
			||||||
      cache: true
 | 
					 | 
				
			||||||
      registry: registry.odit.services
 | 
					 | 
				
			||||||
trigger:
 | 
					 | 
				
			||||||
  branch:
 | 
					 | 
				
			||||||
    - main
 | 
					 | 
				
			||||||
  event:
 | 
					 | 
				
			||||||
    - push
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
kind: pipeline
 | 
					 | 
				
			||||||
type: kubernetes
 | 
					 | 
				
			||||||
name: build:dev
 | 
					 | 
				
			||||||
steps:
 | 
					 | 
				
			||||||
  - name: docker edge
 | 
					 | 
				
			||||||
    image: registry.odit.services/library/drone-kaniko
 | 
					 | 
				
			||||||
    depends_on: [clone]
 | 
					 | 
				
			||||||
    settings:
 | 
					 | 
				
			||||||
      username:
 | 
					 | 
				
			||||||
        from_secret: docker_username
 | 
					 | 
				
			||||||
      password:
 | 
					 | 
				
			||||||
        from_secret: docker_password
 | 
					 | 
				
			||||||
      build_args:
 | 
					 | 
				
			||||||
        - NPM_REGISTRY_URL:
 | 
					 | 
				
			||||||
          from_secret: npm_url
 | 
					 | 
				
			||||||
      repo: lfk/kiosk
 | 
					 | 
				
			||||||
      tags:
 | 
					 | 
				
			||||||
        - edge
 | 
					 | 
				
			||||||
      cache: true
 | 
					 | 
				
			||||||
      registry: registry.odit.services
 | 
					 | 
				
			||||||
trigger:
 | 
					 | 
				
			||||||
  branch:
 | 
					 | 
				
			||||||
    - dev
 | 
					 | 
				
			||||||
  event:
 | 
					 | 
				
			||||||
    - push
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
kind: pipeline
 | 
					 | 
				
			||||||
type: kubernetes
 | 
					 | 
				
			||||||
name: build:tag
 | 
					 | 
				
			||||||
steps:
 | 
					 | 
				
			||||||
  - name: docker release
 | 
					 | 
				
			||||||
    image: registry.odit.services/library/drone-kaniko
 | 
					 | 
				
			||||||
    depends_on: [clone]
 | 
					 | 
				
			||||||
    settings:
 | 
					 | 
				
			||||||
      username:
 | 
					 | 
				
			||||||
        from_secret: docker_username
 | 
					 | 
				
			||||||
      password:
 | 
					 | 
				
			||||||
        from_secret: docker_password
 | 
					 | 
				
			||||||
      build_args:
 | 
					 | 
				
			||||||
        - NPM_REGISTRY_URL:
 | 
					 | 
				
			||||||
          from_secret: npm_url
 | 
					 | 
				
			||||||
      repo: lfk/kiosk
 | 
					 | 
				
			||||||
      tags:
 | 
					 | 
				
			||||||
        - "${DRONE_TAG}"
 | 
					 | 
				
			||||||
      cache: true
 | 
					 | 
				
			||||||
      registry: registry.odit.services
 | 
					 | 
				
			||||||
trigger:
 | 
					 | 
				
			||||||
  event:
 | 
					 | 
				
			||||||
    - tag
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
kind: pipeline
 | 
					 | 
				
			||||||
type: kubernetes
 | 
					 | 
				
			||||||
name: check:pr
 | 
					 | 
				
			||||||
steps:
 | 
					 | 
				
			||||||
  - name: type checks
 | 
					 | 
				
			||||||
    depends_on:
 | 
					 | 
				
			||||||
      - "clone"
 | 
					 | 
				
			||||||
    image: registry.odit.services/hub/library/node:19.9.0-alpine3.16
 | 
					 | 
				
			||||||
    commands:
 | 
					 | 
				
			||||||
      - npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
 | 
					 | 
				
			||||||
      - pnpm i
 | 
					 | 
				
			||||||
      - pnpm check
 | 
					 | 
				
			||||||
    environment:
 | 
					 | 
				
			||||||
      NPM_REGISTRY_URL:
 | 
					 | 
				
			||||||
        from_secret: npm_url
 | 
					 | 
				
			||||||
  - name: build check
 | 
					 | 
				
			||||||
    depends_on:
 | 
					 | 
				
			||||||
      - "clone"
 | 
					 | 
				
			||||||
    image: registry.odit.services/hub/library/node:19.9.0-alpine3.16
 | 
					 | 
				
			||||||
    commands:
 | 
					 | 
				
			||||||
      - npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
 | 
					 | 
				
			||||||
      - pnpm i
 | 
					 | 
				
			||||||
      - pnpm build
 | 
					 | 
				
			||||||
    environment:
 | 
					 | 
				
			||||||
      NPM_REGISTRY_URL:
 | 
					 | 
				
			||||||
        from_secret: npm_url
 | 
					 | 
				
			||||||
trigger:
 | 
					 | 
				
			||||||
  event:
 | 
					 | 
				
			||||||
    - pull_request
 | 
					 | 
				
			||||||
							
								
								
									
										27
									
								
								.gitea/workflows/dev.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.gitea/workflows/dev.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					name: Build latest image
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  push:
 | 
				
			||||||
 | 
					    branches:
 | 
				
			||||||
 | 
					      - main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  build-container:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v4
 | 
				
			||||||
 | 
					      - name: Login to registry
 | 
				
			||||||
 | 
					        uses: docker/login-action@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          registry: registry.odit.services
 | 
				
			||||||
 | 
					          username: ${{ vars.REGISTRY_USERNAME }}
 | 
				
			||||||
 | 
					          password: ${{ secrets.REGISTRY_PASSWORD }}
 | 
				
			||||||
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
 | 
					        uses: docker/setup-buildx-action@v3
 | 
				
			||||||
 | 
					      - name: Build and push
 | 
				
			||||||
 | 
					        uses: docker/build-push-action@v6
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          push: true
 | 
				
			||||||
 | 
					          tags: |
 | 
				
			||||||
 | 
					            ${{ vars.REGISTRY }}/lfk/kiosk:latest
 | 
				
			||||||
 | 
					          platforms: linux/amd64,linux/arm64
 | 
				
			||||||
							
								
								
									
										27
									
								
								.gitea/workflows/release.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.gitea/workflows/release.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					name: Build release images
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  push:
 | 
				
			||||||
 | 
					    tags:
 | 
				
			||||||
 | 
					      - "*.*.*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  build-container:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v4
 | 
				
			||||||
 | 
					      - name: Login to registry
 | 
				
			||||||
 | 
					        uses: docker/login-action@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          registry: registry.odit.services
 | 
				
			||||||
 | 
					          username: ${{ vars.REGISTRY_USERNAME }}
 | 
				
			||||||
 | 
					          password: ${{ secrets.REGISTRY_PASSWORD }}
 | 
				
			||||||
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
 | 
					        uses: docker/setup-buildx-action@v3
 | 
				
			||||||
 | 
					      - name: Build and push
 | 
				
			||||||
 | 
					        uses: docker/build-push-action@v6
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          push: true
 | 
				
			||||||
 | 
					          tags: |
 | 
				
			||||||
 | 
					            ${{ vars.REGISTRY }}/lfk/kiosk:${{ github.ref_name }}
 | 
				
			||||||
 | 
					          platforms: linux/amd64,linux/arm64
 | 
				
			||||||
							
								
								
									
										61
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -2,8 +2,69 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
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.1.2](https://git.odit.services/lfk/kiosk/compare/1.1.1...1.1.2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- fix: build [`368e97c`](https://git.odit.services/lfk/kiosk/commit/368e97c6bba238b605532aa9c598ace5f2bac592)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [1.1.1](https://git.odit.services/lfk/kiosk/compare/1.1.0...1.1.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 2 April 2025
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- refactor(ci): Switch to actions [`0177c50`](https://git.odit.services/lfk/kiosk/commit/0177c506516c5e21b4f73e1086b587ab2f1d8f50)
 | 
				
			||||||
 | 
					- feat: improved registration [`6dcdba6`](https://git.odit.services/lfk/kiosk/commit/6dcdba6568def337dcd1e4e6db5c75df09c1f938)
 | 
				
			||||||
 | 
					- 🚀Bumped version to 1.1.1 [`6acd8bb`](https://git.odit.services/lfk/kiosk/commit/6acd8bb6340f0d874e8ab8b9e1a93a5fd05fd3b6)
 | 
				
			||||||
 | 
					- feat: disable chrome autocomplete [`525c096`](https://git.odit.services/lfk/kiosk/commit/525c096f7a757105947da62e8dac75a24e0aa757)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [1.1.0](https://git.odit.services/lfk/kiosk/compare/1.0.0...1.1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 16 December 2024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- chore(deps): bump all [`b969932`](https://git.odit.services/lfk/kiosk/commit/b9699325828dd9b3ed51997d7a72f43449f000cf)
 | 
				
			||||||
 | 
					- 🚀Bumped version to 1.1.0 [`f7575f4`](https://git.odit.services/lfk/kiosk/commit/f7575f46e4197da893c002299f8e7fdefc5cb026)
 | 
				
			||||||
 | 
					- feat(ci)!: Switch to woodpecker [`16f9228`](https://git.odit.services/lfk/kiosk/commit/16f92283904bc3a2825ebb0fb0c7f130ffa8f057)
 | 
				
			||||||
 | 
					- feat: email [`a8d90d4`](https://git.odit.services/lfk/kiosk/commit/a8d90d48829fa708d1cdc5029d1e1ac2f28b1e4c)
 | 
				
			||||||
 | 
					- 2025 [`a2ffa50`](https://git.odit.services/lfk/kiosk/commit/a2ffa5055e58445bbbc6f932495eb8c4952fec99)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### [1.0.0](https://git.odit.services/lfk/kiosk/compare/0.6.0...1.0.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 19 April 2023
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- feat: footer [`115767c`](https://git.odit.services/lfk/kiosk/commit/115767c656381336257c23ee30a130e7e9c60144)
 | 
				
			||||||
 | 
					- refactor: drop footer [`e512325`](https://git.odit.services/lfk/kiosk/commit/e5123251155f58e83f36c091b671acc73167ce68)
 | 
				
			||||||
 | 
					- 🚀Bumped version to 1.0.0 [`16d15f7`](https://git.odit.services/lfk/kiosk/commit/16d15f7242c738724121797cea1bd2868253fc6f)
 | 
				
			||||||
 | 
					- feat: prevent F1 + F5 [`bb3c801`](https://git.odit.services/lfk/kiosk/commit/bb3c80190834be6d43f50cdb6eeb09ac75868259)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [0.6.0](https://git.odit.services/lfk/kiosk/compare/0.5.0...0.6.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 19 April 2023
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- feat!: move to single route application for kiosk mode [`bf8b351`](https://git.odit.services/lfk/kiosk/commit/bf8b351b644174a2dd39d38208a03a067de387be)
 | 
				
			||||||
 | 
					- refactor!: cleanup userdata localstorage + components [`c7c1c6d`](https://git.odit.services/lfk/kiosk/commit/c7c1c6dc41afc6ca3e66b507fd1ff50185f4e1be)
 | 
				
			||||||
 | 
					- 🚀Bumped version to 0.6.0 [`aa7d2db`](https://git.odit.services/lfk/kiosk/commit/aa7d2dbe1b67b33a59093bc53aa944cb6473ef03)
 | 
				
			||||||
 | 
					- add chrome kiosk command to readme [`01cd8d4`](https://git.odit.services/lfk/kiosk/commit/01cd8d4b78b3898d2f74f2b27cdad9e9745c1e33)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [0.5.0](https://git.odit.services/lfk/kiosk/compare/0.4.4...0.5.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 19 April 2023
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- feat(registration): autofocus input fields + done button [`cbfbd92`](https://git.odit.services/lfk/kiosk/commit/cbfbd92d0e4f9735a2192125f267f651ed36c9b1)
 | 
				
			||||||
 | 
					- 🚀Bumped version to 0.5.0 [`58830c5`](https://git.odit.services/lfk/kiosk/commit/58830c5db3d9903d590f535a4099ad93a8ff6519)
 | 
				
			||||||
 | 
					- feat(registration): disabled done button for 7.5s [`5f5b03a`](https://git.odit.services/lfk/kiosk/commit/5f5b03a8a086799543cf675ccc3a973b781d1987)
 | 
				
			||||||
 | 
					- feat(registration): support next input element with ENTER key [`066e67c`](https://git.odit.services/lfk/kiosk/commit/066e67c64f48b00673f2de7727acb230c94c3c13)
 | 
				
			||||||
 | 
					- feat(registration): disable text select [`418fe77`](https://git.odit.services/lfk/kiosk/commit/418fe7773fbc981186909a1f7c262c3c1fa1ece2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### [0.4.4](https://git.odit.services/lfk/kiosk/compare/0.4.3...0.4.4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 19 April 2023
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 🚀Bumped version to 0.4.4 [`4b6e11d`](https://git.odit.services/lfk/kiosk/commit/4b6e11d8d271c638b3c2e4cd3dc887680023dd5e)
 | 
				
			||||||
 | 
					- fix(registration): Added missing dark styling [`0698038`](https://git.odit.services/lfk/kiosk/commit/06980385230e32dffe1083ceb4f88e86a9197aef)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### [0.4.3](https://git.odit.services/lfk/kiosk/compare/0.4.2...0.4.3)
 | 
					#### [0.4.3](https://git.odit.services/lfk/kiosk/compare/0.4.2...0.4.3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 19 April 2023
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 🚀Bumped version to 0.4.3 [`297b880`](https://git.odit.services/lfk/kiosk/commit/297b88016bce1619d55bd6dc05f993f59f86382a)
 | 
				
			||||||
- fix(href): replaced location.replace with goto [`8959223`](https://git.odit.services/lfk/kiosk/commit/8959223016b2bbe8ebae79f55a489cc0503b3c78)
 | 
					- fix(href): replaced location.replace with goto [`8959223`](https://git.odit.services/lfk/kiosk/commit/8959223016b2bbe8ebae79f55a489cc0503b3c78)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### [0.4.2](https://git.odit.services/lfk/kiosk/compare/0.4.1...0.4.2)
 | 
					#### [0.4.2](https://git.odit.services/lfk/kiosk/compare/0.4.1...0.4.2)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
FROM registry.odit.services/hub/library/node:19.9.0-alpine3.16 AS build
 | 
					FROM registry.odit.services/hub/library/node:23.10.0-alpine3.21 AS build
 | 
				
			||||||
ARG NPM_REGISTRY_URL=registry.npmjs.org
 | 
					# ARG NPM_REGISTRY_URL=registry.npmjs.org
 | 
				
			||||||
WORKDIR /app
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY package.json *.config.cjs *.config.js *.config.ts tsconfig.json .npmrc ./
 | 
					COPY package.json *.config.cjs *.config.js *.config.ts tsconfig.json .npmrc ./
 | 
				
			||||||
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
 | 
					RUN npm i -g pnpm@10.7
 | 
				
			||||||
RUN pnpm i
 | 
					RUN pnpm i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY src ./src
 | 
					COPY src ./src
 | 
				
			||||||
@@ -11,5 +11,5 @@ COPY static ./static
 | 
				
			|||||||
RUN pnpm build
 | 
					RUN pnpm build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# final image
 | 
					# final image
 | 
				
			||||||
FROM registry.odit.services/library/nginx-brotli:3.15 as final
 | 
					FROM registry.odit.services/library/nginx-brotli:3.15 AS final
 | 
				
			||||||
COPY --from=build /app/build /usr/share/nginx/html
 | 
					COPY --from=build /app/build /usr/share/nginx/html
 | 
				
			||||||
@@ -24,4 +24,9 @@ pnpm build
 | 
				
			|||||||
```
 | 
					```
 | 
				
			||||||
docker build .
 | 
					docker build .
 | 
				
			||||||
docker-compose up
 | 
					docker-compose up
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Kiosk Google Chrome
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					chrome https://run.lauf-fuer-kaya.de/kiosk/ -kiosk
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
							
								
								
									
										5358
									
								
								licenses.md
									
									
									
									
									
								
							
							
						
						
									
										5358
									
								
								licenses.md
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										65
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								package.json
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	"name": "@lfk/kiosk",
 | 
						"name": "@lfk/kiosk",
 | 
				
			||||||
	"version": "0.4.3",
 | 
						"version": "1.1.2",
 | 
				
			||||||
	"private": false,
 | 
						"private": false,
 | 
				
			||||||
	"license": "MIT",
 | 
						"license": "MIT",
 | 
				
			||||||
	"repository": "https://git.odit.services/lfk/kiosk",
 | 
						"repository": "https://git.odit.services/lfk/kiosk",
 | 
				
			||||||
@@ -33,45 +33,46 @@
 | 
				
			|||||||
		"license:export": "license-exporter --markdown && git stage licenses.md"
 | 
							"license:export": "license-exporter --markdown && git stage licenses.md"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"devDependencies": {
 | 
						"devDependencies": {
 | 
				
			||||||
		"@odit/license-exporter": "0.0.12",
 | 
							"@odit/license-exporter": "0.2.0",
 | 
				
			||||||
		"@sveltejs/adapter-static": "2.0.2",
 | 
							"@philippdormann/release-it": "^1.0.0",
 | 
				
			||||||
		"@sveltejs/kit": "1.15.7",
 | 
							"@sveltejs/adapter-static": "3.0.6",
 | 
				
			||||||
		"@types/bwip-js": "^3.2.0",
 | 
							"@sveltejs/kit": "2.12.0",
 | 
				
			||||||
		"@typescript-eslint/eslint-plugin": "5.59.0",
 | 
							"@sveltejs/vite-plugin-svelte": "^5.0.2",
 | 
				
			||||||
		"@typescript-eslint/parser": "5.59.0",
 | 
							"@types/bwip-js": "^3.2.3",
 | 
				
			||||||
		"auto-changelog": "2.4.0",
 | 
							"@typescript-eslint/eslint-plugin": "8.18.0",
 | 
				
			||||||
		"autoprefixer": "10.4.14",
 | 
							"@typescript-eslint/parser": "8.18.0",
 | 
				
			||||||
		"eslint": "8.38.0",
 | 
							"auto-changelog": "2.5.0",
 | 
				
			||||||
		"eslint-config-prettier": "8.8.0",
 | 
							"autoprefixer": "10.4.20",
 | 
				
			||||||
		"eslint-plugin-svelte3": "4.0.0",
 | 
							"eslint": "9.17.0",
 | 
				
			||||||
		"postcss": "8.4.22",
 | 
							"eslint-config-prettier": "9.1.0",
 | 
				
			||||||
		"postcss-load-config": "4.0.1",
 | 
							"postcss": "8.4.49",
 | 
				
			||||||
		"prettier": "2.8.7",
 | 
							"postcss-load-config": "6.0.1",
 | 
				
			||||||
		"prettier-plugin-svelte": "2.10.0",
 | 
							"prettier": "3.4.2",
 | 
				
			||||||
		"release-it": "15.10.1",
 | 
							"prettier-plugin-svelte": "3.3.2",
 | 
				
			||||||
		"svelte": "3.58.0",
 | 
							"svelte": "5.14.0",
 | 
				
			||||||
		"svelte-check": "3.2.0",
 | 
							"svelte-check": "4.1.1",
 | 
				
			||||||
		"svelte-preprocess": "5.0.3",
 | 
							"svelte-preprocess": "6.0.3",
 | 
				
			||||||
		"tailwindcss": "3.3.1",
 | 
							"tailwindcss": "3.4.16",
 | 
				
			||||||
		"tslib": "2.5.0",
 | 
							"tslib": "2.8.1",
 | 
				
			||||||
		"typescript": "5.0.4",
 | 
							"typescript": "5.7.2",
 | 
				
			||||||
		"vite": "4.2.2"
 | 
							"vite": "6.0.3"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"type": "module",
 | 
						"type": "module",
 | 
				
			||||||
	"dependencies": {
 | 
						"dependencies": {
 | 
				
			||||||
		"@fontsource/athiti": "^4.5.10",
 | 
							"@fontsource/athiti": "^5.1.0",
 | 
				
			||||||
		"@odit/lfk-client-js": "1.0.1",
 | 
							"@odit/lfk-client-js": "1.1.3",
 | 
				
			||||||
		"bwip-js": "3.4.0"
 | 
							"bwip-js": "4.5.1",
 | 
				
			||||||
 | 
							"eslint-plugin-svelte": "^2.46.1"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"release-it": {
 | 
						"release-it": {
 | 
				
			||||||
		"git": {
 | 
							"git": {
 | 
				
			||||||
			"commit": true,
 | 
								"commit": true,
 | 
				
			||||||
			"requireCleanWorkingDir": false,
 | 
								"requireCleanWorkingDir": false,
 | 
				
			||||||
			"commitMessage": "🚀Bumped version to ${version}",
 | 
								"commitMessage": "chore(release): ${version}",
 | 
				
			||||||
			"requireBranch": "main",
 | 
								"requireBranch": "main",
 | 
				
			||||||
			"push": true,
 | 
								"push": true,
 | 
				
			||||||
			"tag": true,
 | 
								"tag": true,
 | 
				
			||||||
			"tagName": null,
 | 
								"tagName": "${version}",
 | 
				
			||||||
			"tagAnnotation": "${version}"
 | 
								"tagAnnotation": "${version}"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"npm": {
 | 
							"npm": {
 | 
				
			||||||
@@ -80,11 +81,5 @@
 | 
				
			|||||||
		"hooks": {
 | 
							"hooks": {
 | 
				
			||||||
			"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && npm run license:export && git add CHANGELOG.md && git add licenses.md"
 | 
								"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && npm run license:export && git add CHANGELOG.md && git add licenses.md"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"volta": {
 | 
					 | 
				
			||||||
		"node": "19.9.0"
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"engines": {
 | 
					 | 
				
			||||||
		"pnpm": "8"
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6927
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6927
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,49 +0,0 @@
 | 
				
			|||||||
<footer class="mt-auto w-full max-w-[85rem] py-10 px-4 sm:px-6 lg:px-8 mx-auto">
 | 
					 | 
				
			||||||
	<!-- Grid -->
 | 
					 | 
				
			||||||
	<div class="text-center">
 | 
					 | 
				
			||||||
		<div>
 | 
					 | 
				
			||||||
			<a
 | 
					 | 
				
			||||||
				class="flex-none text-xl font-semibold text-black dark:text-white"
 | 
					 | 
				
			||||||
				href="/"
 | 
					 | 
				
			||||||
				aria-label="Brand">LfK Kiosk</a
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<!-- End Col -->
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		<div class="mt-3">
 | 
					 | 
				
			||||||
			<p class="text-gray-500">
 | 
					 | 
				
			||||||
				Powered by <a
 | 
					 | 
				
			||||||
					class="font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-500 dark:hover:text-blue-400"
 | 
					 | 
				
			||||||
					target="_blank"
 | 
					 | 
				
			||||||
					rel="noreferrer"
 | 
					 | 
				
			||||||
					href="https://odit.services/?ref=lfks">ODIT.Services</a
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</p>
 | 
					 | 
				
			||||||
			<p class="text-gray-500">© {new Date().getFullYear()} ODIT.Services</p>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		<div class="mt-3 space-x-2">
 | 
					 | 
				
			||||||
			<a
 | 
					 | 
				
			||||||
				class="inline-flex justify-center items-center text-center text-gray-500 hover:bg-gray-100 rounded-full focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2 focus:ring-offset-white transition dark:text-gray-500 dark:hover:text-gray-200 dark:hover:bg-gray-800"
 | 
					 | 
				
			||||||
				target="_blank"
 | 
					 | 
				
			||||||
				rel="noreferrer"
 | 
					 | 
				
			||||||
				href="https://lauf-fuer-kaya.de/impressum"
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				Impressum
 | 
					 | 
				
			||||||
			</a>
 | 
					 | 
				
			||||||
			<p
 | 
					 | 
				
			||||||
				class="inline-flex justify-center items-center text-center text-gray-500 hover:bg-gray-100 rounded-full focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2 focus:ring-offset-white transition dark:text-gray-500 dark:hover:text-gray-200 dark:hover:bg-gray-800"
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				|
 | 
					 | 
				
			||||||
			</p>
 | 
					 | 
				
			||||||
			<a
 | 
					 | 
				
			||||||
				class="inline-flex justify-center items-center text-center text-gray-500 hover:bg-gray-100 rounded-full focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2 focus:ring-offset-white transition dark:text-gray-500 dark:hover:text-gray-200 dark:hover:bg-gray-800"
 | 
					 | 
				
			||||||
				target="_blank"
 | 
					 | 
				
			||||||
				rel="noreferrer"
 | 
					 | 
				
			||||||
				href="https://lauf-fuer-kaya.de/datenschutz"
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				Datenschutz
 | 
					 | 
				
			||||||
			</a>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</footer>
 | 
					 | 
				
			||||||
@@ -2,93 +2,69 @@ import { AuthService, OpenAPI, type ResponseAuth } from '@odit/lfk-client-js';
 | 
				
			|||||||
import { writable } from 'svelte/store';
 | 
					import { writable } from 'svelte/store';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UserState = {
 | 
					type UserState = {
 | 
				
			||||||
    access_token: string;
 | 
						access_token: string;
 | 
				
			||||||
    refresh_token: string;
 | 
						refresh_token: string;
 | 
				
			||||||
    isLoggedIn: boolean;
 | 
						isLoggedIn: boolean;
 | 
				
			||||||
    refreshInterval: NodeJS.Timer | undefined
 | 
						refreshInterval: NodeJS.Timer | undefined;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					const state: UserState = {
 | 
				
			||||||
const userStore = () => {
 | 
						access_token: '',
 | 
				
			||||||
    const state: UserState = {
 | 
						refresh_token: '',
 | 
				
			||||||
        access_token: '',
 | 
						isLoggedIn: false,
 | 
				
			||||||
        refresh_token: '',
 | 
						refreshInterval: undefined
 | 
				
			||||||
        isLoggedIn: false,
 | 
					 | 
				
			||||||
        refreshInterval: undefined
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const { subscribe, set, update } = writable(state);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const methods = {
 | 
					 | 
				
			||||||
        async login(resAuth: ResponseAuth) {
 | 
					 | 
				
			||||||
            update((state: UserState) => {
 | 
					 | 
				
			||||||
                if (!resAuth) {
 | 
					 | 
				
			||||||
                    return state;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                state.access_token = resAuth.access_token;
 | 
					 | 
				
			||||||
                state.refresh_token = resAuth.refresh_token;
 | 
					 | 
				
			||||||
                state.isLoggedIn = true;
 | 
					 | 
				
			||||||
                state.refreshInterval = setInterval(() => {
 | 
					 | 
				
			||||||
                    this.refreshAuth();
 | 
					 | 
				
			||||||
                }, 2 * 60000)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                localStorage.setItem('kiosk-userdata', JSON.stringify(state));
 | 
					 | 
				
			||||||
                localStorage.setItem('kiosk-access_token', state.access_token);
 | 
					 | 
				
			||||||
                OpenAPI.TOKEN = resAuth.access_token;
 | 
					 | 
				
			||||||
                return state;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        async refreshAuth() {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                const authRes = await AuthService.authControllerRefresh({ token: state.refresh_token }) as ResponseAuth;
 | 
					 | 
				
			||||||
                OpenAPI.TOKEN = authRes.access_token;
 | 
					 | 
				
			||||||
            } catch {
 | 
					 | 
				
			||||||
                this.logout();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        async loginFromStorage() {
 | 
					 | 
				
			||||||
            console.log('loginFromStorage');
 | 
					 | 
				
			||||||
            const access_token = localStorage.getItem('kiosk-access_token');
 | 
					 | 
				
			||||||
            if (!access_token) {
 | 
					 | 
				
			||||||
                throw new Error('Unauthorized');
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const storagedata = localStorage.getItem('kiosk-userdata');
 | 
					 | 
				
			||||||
            const userdata = JSON.parse(storagedata || '{}') as UserState;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            update((state: UserState) => {
 | 
					 | 
				
			||||||
                state.access_token = access_token;
 | 
					 | 
				
			||||||
                state.refresh_token = userdata.refresh_token;
 | 
					 | 
				
			||||||
                state.isLoggedIn = true;
 | 
					 | 
				
			||||||
                state.refreshInterval = setInterval(() => {
 | 
					 | 
				
			||||||
                    this.refreshAuth();
 | 
					 | 
				
			||||||
                }, 2 * 60000);
 | 
					 | 
				
			||||||
                OpenAPI.TOKEN = userdata.access_token;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                return state;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            await this.refreshAuth();
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        async logout() {
 | 
					 | 
				
			||||||
            update((state: UserState) => {
 | 
					 | 
				
			||||||
                state.isLoggedIn = false;
 | 
					 | 
				
			||||||
                state.access_token = '';
 | 
					 | 
				
			||||||
                state.refresh_token = '';
 | 
					 | 
				
			||||||
                state.refreshInterval = undefined;
 | 
					 | 
				
			||||||
                localStorage.clear();
 | 
					 | 
				
			||||||
                return state;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
        subscribe,
 | 
					 | 
				
			||||||
        set,
 | 
					 | 
				
			||||||
        update,
 | 
					 | 
				
			||||||
        state,
 | 
					 | 
				
			||||||
        ...methods
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					const userState = writable(state);
 | 
				
			||||||
 | 
					async function auth_login(resAuth: ResponseAuth) {
 | 
				
			||||||
 | 
						if (!resAuth) {
 | 
				
			||||||
 | 
							return state;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default userStore();
 | 
						state.access_token = resAuth.access_token;
 | 
				
			||||||
 | 
						state.refresh_token = resAuth.refresh_token;
 | 
				
			||||||
 | 
						state.isLoggedIn = true;
 | 
				
			||||||
 | 
						state.refreshInterval = setInterval(() => {
 | 
				
			||||||
 | 
							refreshAuth();
 | 
				
			||||||
 | 
						}, 2 * 60000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						localStorage.setItem('kiosk-userdata', JSON.stringify(state));
 | 
				
			||||||
 | 
						OpenAPI.TOKEN = resAuth.access_token;
 | 
				
			||||||
 | 
						userState.set(state);
 | 
				
			||||||
 | 
						return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					async function refreshAuth() {
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							const authRes = (await AuthService.authControllerRefresh({
 | 
				
			||||||
 | 
								token: state.refresh_token
 | 
				
			||||||
 | 
							})) as ResponseAuth;
 | 
				
			||||||
 | 
							OpenAPI.TOKEN = authRes.access_token;
 | 
				
			||||||
 | 
						} catch {
 | 
				
			||||||
 | 
							logout();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					async function loginFromStorage() {
 | 
				
			||||||
 | 
						const storagedata = localStorage.getItem('kiosk-userdata');
 | 
				
			||||||
 | 
						const userdata = JSON.parse(storagedata || '{}') as UserState;
 | 
				
			||||||
 | 
						if (!userdata.access_token) {
 | 
				
			||||||
 | 
							throw new Error('Unauthorized');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state.access_token = userdata.access_token;
 | 
				
			||||||
 | 
						state.refresh_token = userdata.refresh_token;
 | 
				
			||||||
 | 
						state.isLoggedIn = true;
 | 
				
			||||||
 | 
						state.refreshInterval = setInterval(() => {
 | 
				
			||||||
 | 
							refreshAuth();
 | 
				
			||||||
 | 
						}, 2 * 60000);
 | 
				
			||||||
 | 
						OpenAPI.TOKEN = userdata.access_token;
 | 
				
			||||||
 | 
						userState.set(state);
 | 
				
			||||||
 | 
						return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					async function logout() {
 | 
				
			||||||
 | 
						state.isLoggedIn = false;
 | 
				
			||||||
 | 
						state.access_token = '';
 | 
				
			||||||
 | 
						state.refresh_token = '';
 | 
				
			||||||
 | 
						state.refreshInterval = undefined;
 | 
				
			||||||
 | 
						localStorage.clear();
 | 
				
			||||||
 | 
						return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { auth_login, logout, loginFromStorage, refreshAuth, userState };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,18 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
	import { OpenAPI } from '@odit/lfk-client-js';
 | 
						import { OpenAPI } from '@odit/lfk-client-js';
 | 
				
			||||||
	import { env } from '$env/dynamic/public';
 | 
					 | 
				
			||||||
	import '../app.postcss';
 | 
						import '../app.postcss';
 | 
				
			||||||
	import "@fontsource/athiti"
 | 
						import '@fontsource/athiti';
 | 
				
			||||||
	import Footer from '../components/footer.svelte';
 | 
						import { onMount } from 'svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	OpenAPI.BASE = env.PUBLIC_BASE_URL || 'https://run.lauf-fuer-kaya.de';
 | 
						OpenAPI.BASE = 'https://run.lauf-fuer-kaya.de';
 | 
				
			||||||
 | 
						onMount(() => {
 | 
				
			||||||
 | 
							window.addEventListener('keydown', (e) => {
 | 
				
			||||||
 | 
								// F1
 | 
				
			||||||
 | 
								if (e.keyCode === 112) e.preventDefault();
 | 
				
			||||||
 | 
								// F5
 | 
				
			||||||
 | 
								if (e.keyCode === 116) e.preventDefault();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="dark:bg-slate-900 flex flex-col h-screen">
 | 
					<div class="dark:bg-slate-900 flex flex-col h-screen">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,41 +1,45 @@
 | 
				
			|||||||
<!-- Hero -->
 | 
					<script lang="ts">
 | 
				
			||||||
<div
 | 
						import { loginFromStorage, userState } from '$lib/userstore';
 | 
				
			||||||
	class="relative overflow-hidden before:absolute before:top-0 before:left-1/2 before:bg-[url('/assets/polygon.svg')] before:bg-no-repeat before:bg-top before:bg-cover before:w-full before:h-full before:-z-[1] before:transform before:-translate-x-1/2 dark:before:bg-[url('/assets/polygon-dark.svg')]"
 | 
						import Register from './Register.svelte';
 | 
				
			||||||
>
 | 
						import { onMount } from 'svelte';
 | 
				
			||||||
	<div class="max-w-[85rem] mx-auto px-4 sm:px-6 lg:px-8 pt-24 pb-10">
 | 
						import Login from './Login.svelte';
 | 
				
			||||||
		<!-- Title -->
 | 
					 | 
				
			||||||
		<div class="mt-5 max-w-2xl text-center mx-auto">
 | 
					 | 
				
			||||||
			<h1 class="block font-bold text-gray-800 text-4xl md:text-5xl lg:text-6xl dark:text-gray-200">
 | 
					 | 
				
			||||||
				LfK! Selfservice
 | 
					 | 
				
			||||||
				<span class="bg-clip-text bg-gradient-to-tl from-blue-600 to-violet-600 text-transparent"
 | 
					 | 
				
			||||||
					>Kiosk</span
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</h1>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<!-- End Title -->
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="mt-5 max-w-3xl text-center mx-auto">
 | 
						onMount(() => {
 | 
				
			||||||
			<p class="text-lg text-gray-600 dark:text-gray-400">Für die Anmeldung vor Ort</p>
 | 
							loginFromStorage();
 | 
				
			||||||
		</div>
 | 
						});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<!-- Buttons -->
 | 
					{#if $userState.isLoggedIn}
 | 
				
			||||||
		<div class="mt-8 grid gap-3 w-full sm:inline-flex sm:justify-center">
 | 
						<Register />
 | 
				
			||||||
			<a
 | 
					{:else}
 | 
				
			||||||
				class="inline-flex justify-center items-center gap-x-3 text-center bg-gradient-to-tl from-blue-600 to-violet-600 hover:from-violet-600 hover:to-blue-600 border border-transparent text-white text-sm font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2 focus:ring-offset-white py-3 px-4 dark:focus:ring-offset-gray-800"
 | 
						<Login />
 | 
				
			||||||
				href="./login"
 | 
					{/if}
 | 
				
			||||||
			>
 | 
					<div class="fixed bottom-0 w-full text-center text-xl p-4 dark:text-white select-none">
 | 
				
			||||||
				Kiosk starten
 | 
						{#if $userState.isLoggedIn}
 | 
				
			||||||
				<svg class="w-3 h-3" width="16" height="16" viewBox="0 0 16 16" fill="none">
 | 
							<b class="font-bold">LfK!2025</b> powered by
 | 
				
			||||||
					<path
 | 
							<b class="font-bold">ODIT.Services</b>
 | 
				
			||||||
						d="M5.27921 2L10.9257 7.64645C11.1209 7.84171 11.1209 8.15829 10.9257 8.35355L5.27921 14"
 | 
						{:else}
 | 
				
			||||||
						stroke="currentColor"
 | 
							<a
 | 
				
			||||||
						stroke-width="2"
 | 
								rel="noopener noreferrer"
 | 
				
			||||||
						stroke-linecap="round"
 | 
								target="_blank"
 | 
				
			||||||
					/>
 | 
								href="https://lauf-fuer-kaya.de/datenschutz/"
 | 
				
			||||||
				</svg>
 | 
								class="underline">Datenschutzerklärung</a
 | 
				
			||||||
			</a>
 | 
							>
 | 
				
			||||||
		</div>
 | 
							|
 | 
				
			||||||
		<!-- End Buttons -->
 | 
							<a
 | 
				
			||||||
	</div>
 | 
								rel="noopener noreferrer"
 | 
				
			||||||
 | 
								target="_blank"
 | 
				
			||||||
 | 
								href="https://lauf-fuer-kaya.de/impressum/"
 | 
				
			||||||
 | 
								class="underline">Impressum</a
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
							<br />
 | 
				
			||||||
 | 
							<br />
 | 
				
			||||||
 | 
							<b class="font-bold">LfK!2025</b> powered by
 | 
				
			||||||
 | 
							<a
 | 
				
			||||||
 | 
								rel="noopener noreferrer"
 | 
				
			||||||
 | 
								target="_blank"
 | 
				
			||||||
 | 
								href="https://odit.services?ref=lfk"
 | 
				
			||||||
 | 
								class="underline">ODIT.Services</a
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
						{/if}
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<!-- End Hero -->
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										122
									
								
								src/routes/Login.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/routes/Login.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						import { auth_login, loginFromStorage } from '$lib/userstore';
 | 
				
			||||||
 | 
						import { AuthService } from '@odit/lfk-client-js';
 | 
				
			||||||
 | 
						import { onMount } from 'svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$: username = '';
 | 
				
			||||||
 | 
						$: password = '';
 | 
				
			||||||
 | 
						$: loginError = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						onMount(() => {
 | 
				
			||||||
 | 
							loginFromStorage();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						async function login() {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								const auth = (await AuthService.authControllerLogin({
 | 
				
			||||||
 | 
									username,
 | 
				
			||||||
 | 
									password
 | 
				
			||||||
 | 
								})) as import('@odit/lfk-client-js').ResponseAuth;
 | 
				
			||||||
 | 
								loginError = false;
 | 
				
			||||||
 | 
								auth_login(auth);
 | 
				
			||||||
 | 
							} catch (error) {
 | 
				
			||||||
 | 
								loginError = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--  -->
 | 
				
			||||||
 | 
					<div
 | 
				
			||||||
 | 
						class="relative overflow-hidden before:absolute before:top-0 before:left-1/2 before:bg-[url('/assets/polygon.svg')] before:bg-no-repeat before:bg-top before:bg-cover before:w-full before:h-full before:-z-[1] before:transform before:-translate-x-1/2 dark:before:bg-[url('/assets/polygon-dark.svg')]"
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
						<div class="max-w-[85rem] mx-auto px-4 sm:px-6 lg:px-8 pt-24 pb-10">
 | 
				
			||||||
 | 
							<!-- Title -->
 | 
				
			||||||
 | 
							<div class="mt-5 max-w-2xl text-center mx-auto">
 | 
				
			||||||
 | 
								<h1 class="block font-bold text-gray-800 text-4xl md:text-5xl lg:text-6xl dark:text-gray-200">
 | 
				
			||||||
 | 
									LfK! Selfservice
 | 
				
			||||||
 | 
									<span class="bg-clip-text bg-gradient-to-tl from-blue-600 to-violet-600 text-transparent"
 | 
				
			||||||
 | 
										>Kiosk</span
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
								</h1>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<!-- End Title -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div class="mt-5 max-w-3xl text-center mx-auto">
 | 
				
			||||||
 | 
								<p class="text-lg text-gray-600 dark:text-gray-400">Für die Anmeldung vor Ort</p>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="w-full max-w-md mx-auto p-6">
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									class="mt-7 bg-white border border-gray-200 rounded-xl shadow-sm dark:bg-gray-800 dark:border-gray-700"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div class="p-4 sm:p-7">
 | 
				
			||||||
 | 
										<div class="text-center mb-8">
 | 
				
			||||||
 | 
											<h1 class="block text-2xl font-bold text-gray-800 dark:text-white">Anmeldung</h1>
 | 
				
			||||||
 | 
											<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">
 | 
				
			||||||
 | 
												Hierfür wird ein LfK Läufersystem Account benötigt
 | 
				
			||||||
 | 
											</p>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										{#if loginError}
 | 
				
			||||||
 | 
											<div
 | 
				
			||||||
 | 
												class="bg-red-500 text-sm text-white text-center font-semibold rounded-md shadow-lg mb-8"
 | 
				
			||||||
 | 
												role="alert"
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												<div class="p-4">Falscher Nutzername oder falsches Passwort</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<!-- Form -->
 | 
				
			||||||
 | 
										<form on:submit|preventDefault={login}>
 | 
				
			||||||
 | 
											<div class="grid gap-y-4">
 | 
				
			||||||
 | 
												<!-- Form Group -->
 | 
				
			||||||
 | 
												<div>
 | 
				
			||||||
 | 
													<label for="username" class="block text-sm mb-2 dark:text-white">Benutzername</label
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
													<div class="relative">
 | 
				
			||||||
 | 
														<input
 | 
				
			||||||
 | 
															bind:value={username}
 | 
				
			||||||
 | 
															autocomplete="one-time-code"
 | 
				
			||||||
 | 
															type="username"
 | 
				
			||||||
 | 
															id="username"
 | 
				
			||||||
 | 
															name="username"
 | 
				
			||||||
 | 
															class="py-3 px-4 block w-full border-gray-200 rounded-md text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 border"
 | 
				
			||||||
 | 
															required
 | 
				
			||||||
 | 
															aria-describedby="username-error"
 | 
				
			||||||
 | 
														/>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<!-- End Form Group -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												<!-- Form Group -->
 | 
				
			||||||
 | 
												<div>
 | 
				
			||||||
 | 
													<div class="flex justify-between items-center">
 | 
				
			||||||
 | 
														<label for="password" class="block text-sm mb-2 dark:text-white">Passwort</label>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
													<div class="relative">
 | 
				
			||||||
 | 
														<input
 | 
				
			||||||
 | 
															bind:value={password}
 | 
				
			||||||
 | 
															autocomplete="one-time-code"
 | 
				
			||||||
 | 
															type="password"
 | 
				
			||||||
 | 
															id="password"
 | 
				
			||||||
 | 
															name="password"
 | 
				
			||||||
 | 
															class="py-3 px-4 block w-full border-gray-200 rounded-md text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 border"
 | 
				
			||||||
 | 
															required
 | 
				
			||||||
 | 
															aria-describedby="password-error"
 | 
				
			||||||
 | 
														/>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<!-- End Form Group -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												<button
 | 
				
			||||||
 | 
													type="submit"
 | 
				
			||||||
 | 
													class="py-3 px-4 inline-flex justify-center items-center gap-2 rounded-md border border-transparent font-semibold bg-blue-500 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all text-sm dark:focus:ring-offset-gray-800"
 | 
				
			||||||
 | 
													>Anmelden</button
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</form>
 | 
				
			||||||
 | 
										<!-- End Form -->
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
@@ -2,28 +2,54 @@
 | 
				
			|||||||
	import { RunnerService, type ResponseRunner } from '@odit/lfk-client-js';
 | 
						import { RunnerService, type ResponseRunner } from '@odit/lfk-client-js';
 | 
				
			||||||
	import bwipjs from 'bwip-js';
 | 
						import bwipjs from 'bwip-js';
 | 
				
			||||||
	import lfkbackground from './background.png';
 | 
						import lfkbackground from './background.png';
 | 
				
			||||||
 | 
						import { onMount } from 'svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$: firstname = '';
 | 
						$: firstname = '';
 | 
				
			||||||
	$: lastname = '';
 | 
						$: lastname = '';
 | 
				
			||||||
 | 
						$: email = '';
 | 
				
			||||||
 | 
						$: doneButtonEnabled = false;
 | 
				
			||||||
	$: showResult = false;
 | 
						$: showResult = false;
 | 
				
			||||||
	$: showError = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let response: ResponseRunner;
 | 
						let response: ResponseRunner;
 | 
				
			||||||
	const group = 1; //Default to Bürgerlauf
 | 
						const group = 1; //Default to Bürgerlauf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function focusFirstName() {
 | 
				
			||||||
 | 
							setTimeout(() => {
 | 
				
			||||||
 | 
								document.getElementById('firstname')?.focus();
 | 
				
			||||||
 | 
							}, 50);
 | 
				
			||||||
 | 
							setTimeout(() => {
 | 
				
			||||||
 | 
								document.getElementById('firstname')?.focus();
 | 
				
			||||||
 | 
							}, 100);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						function focusDoneButton() {
 | 
				
			||||||
 | 
							setTimeout(() => {
 | 
				
			||||||
 | 
								document.getElementById('done')?.focus();
 | 
				
			||||||
 | 
							}, 50);
 | 
				
			||||||
 | 
							setTimeout(() => {
 | 
				
			||||||
 | 
								document.getElementById('done')?.focus();
 | 
				
			||||||
 | 
							}, 100);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	async function register() {
 | 
						async function register() {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			response = (await RunnerService.runnerControllerPost({
 | 
								response = (await RunnerService.runnerControllerPost({
 | 
				
			||||||
				firstname,
 | 
									firstname,
 | 
				
			||||||
				lastname,
 | 
									lastname,
 | 
				
			||||||
 | 
									email,
 | 
				
			||||||
				group
 | 
									group
 | 
				
			||||||
			})) as ResponseRunner;
 | 
								})) as ResponseRunner;
 | 
				
			||||||
			showError = false;
 | 
					 | 
				
			||||||
			showResult = true;
 | 
								showResult = true;
 | 
				
			||||||
 | 
								setTimeout(() => {
 | 
				
			||||||
 | 
									doneButtonEnabled = true;
 | 
				
			||||||
 | 
									setTimeout(() => {
 | 
				
			||||||
 | 
										focusDoneButton();
 | 
				
			||||||
 | 
									}, 25);
 | 
				
			||||||
 | 
								}, 7500);
 | 
				
			||||||
		} catch (error) {
 | 
							} catch (error) {
 | 
				
			||||||
			console.log(error);
 | 
								console.log(error);
 | 
				
			||||||
			showError = true;
 | 
					 | 
				
			||||||
			showResult = false;
 | 
								showResult = false;
 | 
				
			||||||
 | 
								localStorage.clear();
 | 
				
			||||||
 | 
								location.reload();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		firstname = '';
 | 
							firstname = '';
 | 
				
			||||||
		lastname = '';
 | 
							lastname = '';
 | 
				
			||||||
@@ -46,22 +72,26 @@
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
		return canvas.toDataURL('image/png');
 | 
							return canvas.toDataURL('image/png');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						onMount(() => {
 | 
				
			||||||
 | 
							focusFirstName();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div
 | 
					<div
 | 
				
			||||||
	class="dark:bg-slate-900 bg-gray-100 flex h-full items-center py-16"
 | 
						class="dark:bg-slate-900 bg-gray-100 flex h-full items-center py-16 select-none"
 | 
				
			||||||
	style="background: url({lfkbackground});background-position: center center!important;background-size: contain!important;background-repeat: no-repeat!important;"
 | 
						style="background: url({lfkbackground});background-position: center center!important;background-size: contain!important;background-repeat: no-repeat!important;"
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
	<div class="w-full max-w-md mx-auto p-6">
 | 
						<div class="w-full max-w-md mx-auto p-6">
 | 
				
			||||||
		<!-- <div
 | 
							<!-- <div
 | 
				
			||||||
			class="mt-7 bg-white border border-gray-200 rounded-xl shadow-sm dark:bg-gray-800 dark:border-gray-700"
 | 
								class="mt-7 bg-white border border-gray-200 rounded-xl shadow-sm dark:bg-gray-800 dark:border-gray-200"
 | 
				
			||||||
		> -->
 | 
							> -->
 | 
				
			||||||
		<div class="p-4 sm:p-7">
 | 
							<div class="p-4 sm:p-7">
 | 
				
			||||||
			<div class="mt-5">
 | 
								<div class="mt-5">
 | 
				
			||||||
				<!-- Form -->
 | 
									<!-- Form -->
 | 
				
			||||||
				{#if !showResult}
 | 
									{#if !showResult}
 | 
				
			||||||
					<div class="text-center">
 | 
										<div class="text-center">
 | 
				
			||||||
						<h1 class="block text-7xl font-bold text-gray-800 dark:text-white">LfK!2023</h1>
 | 
											<h1 class="block text-7xl font-bold text-gray-800 dark:text-white">LfK!2025</h1>
 | 
				
			||||||
						<h1 class="block text-4xl font-bold text-gray-800 dark:text-white">Registrierung</h1>
 | 
											<h1 class="block text-4xl font-bold text-gray-800 dark:text-white">Registrierung</h1>
 | 
				
			||||||
						<!-- <p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Melde dich für den LfK an</p> -->
 | 
											<!-- <p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Melde dich für den LfK an</p> -->
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
@@ -72,10 +102,19 @@
 | 
				
			|||||||
								<label for="firstname" class="block text-lg font-bold mb-2 sr-only">Vorname</label>
 | 
													<label for="firstname" class="block text-lg font-bold mb-2 sr-only">Vorname</label>
 | 
				
			||||||
								<div class="relative">
 | 
													<div class="relative">
 | 
				
			||||||
									<input
 | 
														<input
 | 
				
			||||||
 | 
															on:keydown={(e) => {
 | 
				
			||||||
 | 
																if (e.keyCode === 13) {
 | 
				
			||||||
 | 
																	document.getElementById('lastname')?.focus();
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
																if (e.keyCode === 40) {
 | 
				
			||||||
 | 
																	document.getElementById('lastname')?.focus();
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
															}}
 | 
				
			||||||
										type="text"
 | 
															type="text"
 | 
				
			||||||
 | 
															autocomplete="one-time-code"
 | 
				
			||||||
										id="firstname"
 | 
															id="firstname"
 | 
				
			||||||
										name="firstname"
 | 
															name="firstname"
 | 
				
			||||||
										class="py-3 px-4 block w-full border-gray-200 rounded-md focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 border"
 | 
															class="placeholder:text-black dark:placeholder:text-white py-3 px-4 block w-full border-gray-500 rounded-md focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-200 dark:text-gray-400 border"
 | 
				
			||||||
										required
 | 
															required
 | 
				
			||||||
										placeholder="Vorname"
 | 
															placeholder="Vorname"
 | 
				
			||||||
										bind:value={firstname}
 | 
															bind:value={firstname}
 | 
				
			||||||
@@ -114,10 +153,23 @@
 | 
				
			|||||||
								<label for="lastname" class="block text-lg font-bold mb-2 sr-only">Nachname</label>
 | 
													<label for="lastname" class="block text-lg font-bold mb-2 sr-only">Nachname</label>
 | 
				
			||||||
								<div class="relative">
 | 
													<div class="relative">
 | 
				
			||||||
									<input
 | 
														<input
 | 
				
			||||||
 | 
															on:keydown={(e) => {
 | 
				
			||||||
 | 
																console.log(e.keyCode);
 | 
				
			||||||
 | 
																if (e.keyCode === 13) {
 | 
				
			||||||
 | 
																	document.getElementById('email')?.focus();
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
																if (e.keyCode === 38) {
 | 
				
			||||||
 | 
																	document.getElementById('firstname')?.focus();
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
																if (e.keyCode === 40) {
 | 
				
			||||||
 | 
																	document.getElementById('email')?.focus();
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
															}}
 | 
				
			||||||
 | 
															autocomplete="one-time-code"
 | 
				
			||||||
										type="lastname"
 | 
															type="lastname"
 | 
				
			||||||
										id="lastname"
 | 
															id="lastname"
 | 
				
			||||||
										name="lastname"
 | 
															name="lastname"
 | 
				
			||||||
										class="py-3 px-4 block w-full border-gray-200 rounded-md focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 border"
 | 
															class="placeholder:text-black dark:placeholder:text-white py-3 px-4 block w-full border-gray-500 rounded-md focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-200 dark:text-gray-400 border"
 | 
				
			||||||
										required
 | 
															required
 | 
				
			||||||
										placeholder="Nachname"
 | 
															placeholder="Nachname"
 | 
				
			||||||
										aria-describedby="lastname-error"
 | 
															aria-describedby="lastname-error"
 | 
				
			||||||
@@ -151,10 +203,67 @@
 | 
				
			|||||||
							</div>
 | 
												</div>
 | 
				
			||||||
							<!-- End Form Group -->
 | 
												<!-- End Form Group -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												<!-- Form Group -->
 | 
				
			||||||
 | 
												<div>
 | 
				
			||||||
 | 
													<label for="email" class="block text-lg font-bold mb-2 sr-only"
 | 
				
			||||||
 | 
														>E-Mail (optional)</label
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
													<div class="relative">
 | 
				
			||||||
 | 
														<input
 | 
				
			||||||
 | 
															on:keydown={(e) => {
 | 
				
			||||||
 | 
																console.log(e.keyCode);
 | 
				
			||||||
 | 
																if (e.keyCode === 13) {
 | 
				
			||||||
 | 
																	document.getElementById('submit')?.focus();
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
																if (e.keyCode === 38) {
 | 
				
			||||||
 | 
																	document.getElementById('lastname')?.focus();
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
																if (e.keyCode === 40) {
 | 
				
			||||||
 | 
																	document.getElementById('submit')?.focus();
 | 
				
			||||||
 | 
																}
 | 
				
			||||||
 | 
															}}
 | 
				
			||||||
 | 
															autocomplete="one-time-code"
 | 
				
			||||||
 | 
															type="email"
 | 
				
			||||||
 | 
															id="email"
 | 
				
			||||||
 | 
															name="email"
 | 
				
			||||||
 | 
															class="placeholder:text-black dark:placeholder:text-white py-3 px-4 block w-full border-gray-500 rounded-md focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-200 dark:text-gray-400 border"
 | 
				
			||||||
 | 
															placeholder="E-Mail (optional)"
 | 
				
			||||||
 | 
															aria-describedby="lastname-error"
 | 
				
			||||||
 | 
															bind:value={email}
 | 
				
			||||||
 | 
														/>
 | 
				
			||||||
 | 
														<!-- <div
 | 
				
			||||||
 | 
																class:hidden={lastname || lastname.length != 0}
 | 
				
			||||||
 | 
																class="absolute inset-y-0 right-0 flex items-center pointer-events-none pr-3"
 | 
				
			||||||
 | 
															>
 | 
				
			||||||
 | 
																<svg
 | 
				
			||||||
 | 
																	class="h-5 w-5 text-red-500"
 | 
				
			||||||
 | 
																	width="16"
 | 
				
			||||||
 | 
																	height="16"
 | 
				
			||||||
 | 
																	fill="currentColor"
 | 
				
			||||||
 | 
																	viewBox="0 0 16 16"
 | 
				
			||||||
 | 
																	aria-hidden="true"
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
																	<path
 | 
				
			||||||
 | 
																		d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"
 | 
				
			||||||
 | 
																	/>
 | 
				
			||||||
 | 
																</svg>
 | 
				
			||||||
 | 
															</div> -->
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
													<!-- <p
 | 
				
			||||||
 | 
															class:hidden={lastname || lastname.length != 0}
 | 
				
			||||||
 | 
															class="text-xs text-red-600 mt-2"
 | 
				
			||||||
 | 
															id="lastname-error"
 | 
				
			||||||
 | 
														>
 | 
				
			||||||
 | 
															Bitte gebe deinen Nachnamen ein
 | 
				
			||||||
 | 
														</p> -->
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<!-- End Form Group -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							<button
 | 
												<button
 | 
				
			||||||
 | 
													id="submit"
 | 
				
			||||||
								type="submit"
 | 
													type="submit"
 | 
				
			||||||
								disabled={!firstname || !lastname}
 | 
													disabled={!firstname || !lastname}
 | 
				
			||||||
								class="py-3 px-4 inline-flex justify-center items-center gap-2 rounded-md border border-transparent font-semibold disabled:opacity-70 bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all  dark:focus:ring-offset-gray-800"
 | 
													class="py-3 px-4 inline-flex justify-center items-center gap-2 rounded-md border border-transparent font-semibold disabled:opacity-70 bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all dark:focus:ring-offset-gray-800"
 | 
				
			||||||
								>Anmelden</button
 | 
													>Anmelden</button
 | 
				
			||||||
							>
 | 
												>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
@@ -178,8 +287,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					<div class="mx-auto text-center items-center">
 | 
										<div class="mx-auto text-center items-center">
 | 
				
			||||||
						<button
 | 
											<button
 | 
				
			||||||
 | 
												class:opacity-50={!doneButtonEnabled}
 | 
				
			||||||
 | 
												disabled={!doneButtonEnabled}
 | 
				
			||||||
 | 
												id="done"
 | 
				
			||||||
							on:click={() => {
 | 
												on:click={() => {
 | 
				
			||||||
 | 
													doneButtonEnabled = false;
 | 
				
			||||||
								showResult = false;
 | 
													showResult = false;
 | 
				
			||||||
 | 
													focusFirstName();
 | 
				
			||||||
							}}
 | 
												}}
 | 
				
			||||||
							class="w-full py-3 px-4 inline-flex justify-center items-center gap-2 rounded-md border border-transparent font-semibold bg-blue-500 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all text-sm dark:focus:ring-offset-gray-800"
 | 
												class="w-full py-3 px-4 inline-flex justify-center items-center gap-2 rounded-md border border-transparent font-semibold bg-blue-500 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all text-sm dark:focus:ring-offset-gray-800"
 | 
				
			||||||
							>Fertig</button
 | 
												>Fertig</button
 | 
				
			||||||
@@ -191,27 +305,3 @@
 | 
				
			|||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<div class="fixed bottom-0 w-full text-center text-xl p-4">
 | 
					 | 
				
			||||||
	<a
 | 
					 | 
				
			||||||
		rel="noopener noreferrer"
 | 
					 | 
				
			||||||
		target="_blank"
 | 
					 | 
				
			||||||
		href="https://lauf-fuer-kaya.de/datenschutz/"
 | 
					 | 
				
			||||||
		class="underline">Datenschutzerklärung</a
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
	|
 | 
					 | 
				
			||||||
	<a
 | 
					 | 
				
			||||||
		rel="noopener noreferrer"
 | 
					 | 
				
			||||||
		target="_blank"
 | 
					 | 
				
			||||||
		href="https://lauf-fuer-kaya.de/impressum/"
 | 
					 | 
				
			||||||
		class="underline">Impressum</a
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
	<br />
 | 
					 | 
				
			||||||
	<br />
 | 
					 | 
				
			||||||
	<b class="font-bold">LfK!2023</b> powered by
 | 
					 | 
				
			||||||
	<a
 | 
					 | 
				
			||||||
		rel="noopener noreferrer"
 | 
					 | 
				
			||||||
		target="_blank"
 | 
					 | 
				
			||||||
		href="https://odit.services?ref=lfk"
 | 
					 | 
				
			||||||
		class="underline">ODIT.Services</a
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB  | 
@@ -1,95 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
					 | 
				
			||||||
	import userstore from '$lib/userstore';
 | 
					 | 
				
			||||||
	import { AuthService } from '@odit/lfk-client-js';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	$: username = '';
 | 
					 | 
				
			||||||
	$: password = '';
 | 
					 | 
				
			||||||
	$: loginError = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	async function login() {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			const auth = (await AuthService.authControllerLogin({
 | 
					 | 
				
			||||||
				username,
 | 
					 | 
				
			||||||
				password
 | 
					 | 
				
			||||||
			})) as import('@odit/lfk-client-js').ResponseAuth;
 | 
					 | 
				
			||||||
            loginError=false;
 | 
					 | 
				
			||||||
			await userstore.login(auth);
 | 
					 | 
				
			||||||
			goto('./registration', {replaceState: true})
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			console.log(error);
 | 
					 | 
				
			||||||
			loginError = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="dark:bg-slate-900 bg-gray-100 flex h-full items-center py-16">
 | 
					 | 
				
			||||||
	<div class="w-full max-w-md mx-auto p-6">
 | 
					 | 
				
			||||||
		<div
 | 
					 | 
				
			||||||
			class="mt-7 bg-white border border-gray-200 rounded-xl shadow-sm dark:bg-gray-800 dark:border-gray-700"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<div class="p-4 sm:p-7">
 | 
					 | 
				
			||||||
				<div class="text-center mb-8">
 | 
					 | 
				
			||||||
					<h1 class="block text-2xl font-bold text-gray-800 dark:text-white">Anmeldung</h1>
 | 
					 | 
				
			||||||
					<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">
 | 
					 | 
				
			||||||
						Hierfür wird ein LfK Läufersystem Account benötigt
 | 
					 | 
				
			||||||
					</p>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{#if loginError}
 | 
					 | 
				
			||||||
					<div class="bg-red-500 text-sm text-white text-center font-semibold rounded-md shadow-lg mb-8" role="alert">
 | 
					 | 
				
			||||||
						<div class="p-4">Falscher Nutzername oder falsches Passwort</div>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				{/if}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				<!-- Form -->
 | 
					 | 
				
			||||||
				<form on:submit|preventDefault={login}>
 | 
					 | 
				
			||||||
					<div class="grid gap-y-4">
 | 
					 | 
				
			||||||
						<!-- Form Group -->
 | 
					 | 
				
			||||||
						<div>
 | 
					 | 
				
			||||||
							<label for="username" class="block text-sm mb-2 dark:text-white">Benutzername</label>
 | 
					 | 
				
			||||||
							<div class="relative">
 | 
					 | 
				
			||||||
								<input
 | 
					 | 
				
			||||||
									bind:value={username}
 | 
					 | 
				
			||||||
									type="username"
 | 
					 | 
				
			||||||
									id="username"
 | 
					 | 
				
			||||||
									name="username"
 | 
					 | 
				
			||||||
									class="py-3 px-4 block w-full border-gray-200 rounded-md text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 border"
 | 
					 | 
				
			||||||
									required
 | 
					 | 
				
			||||||
									aria-describedby="username-error"
 | 
					 | 
				
			||||||
								/>
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
						<!-- End Form Group -->
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						<!-- Form Group -->
 | 
					 | 
				
			||||||
						<div>
 | 
					 | 
				
			||||||
							<div class="flex justify-between items-center">
 | 
					 | 
				
			||||||
								<label for="password" class="block text-sm mb-2 dark:text-white">Passwort</label>
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
							<div class="relative">
 | 
					 | 
				
			||||||
								<input
 | 
					 | 
				
			||||||
									bind:value={password}
 | 
					 | 
				
			||||||
									type="password"
 | 
					 | 
				
			||||||
									id="password"
 | 
					 | 
				
			||||||
									name="password"
 | 
					 | 
				
			||||||
									class="py-3 px-4 block w-full border-gray-200 rounded-md text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 border"
 | 
					 | 
				
			||||||
									required
 | 
					 | 
				
			||||||
									aria-describedby="password-error"
 | 
					 | 
				
			||||||
								/>
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
						<!-- End Form Group -->
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						<button
 | 
					 | 
				
			||||||
							type="submit"
 | 
					 | 
				
			||||||
							class="py-3 px-4 inline-flex justify-center items-center gap-2 rounded-md border border-transparent font-semibold bg-blue-500 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all text-sm dark:focus:ring-offset-gray-800"
 | 
					 | 
				
			||||||
							>Anmelden</button
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</form>
 | 
					 | 
				
			||||||
				<!-- End Form -->
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
					 | 
				
			||||||
	import userstore from '$lib/userstore';
 | 
					 | 
				
			||||||
	import { onMount } from 'svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	$: loginRendered = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	onMount(async () => {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			await userstore.loginFromStorage();
 | 
					 | 
				
			||||||
			loginRendered = true;
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			console.log(error);
 | 
					 | 
				
			||||||
			userstore.logout();
 | 
					 | 
				
			||||||
			goto('./login', {replaceState: true})
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if loginRendered}
 | 
					 | 
				
			||||||
	<slot />
 | 
					 | 
				
			||||||
{:else}
 | 
					 | 
				
			||||||
	<div class="mx-auto mt-20">
 | 
					 | 
				
			||||||
        <h1 class="block text-center text-2xl font-bold text-gray-800 dark:text-white">Lade Anmeldedaten...</h1>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,13 +1,11 @@
 | 
				
			|||||||
import preprocess from 'svelte-preprocess';
 | 
					import preprocess from 'svelte-preprocess';
 | 
				
			||||||
import adapter from '@sveltejs/adapter-static';
 | 
					import adapter from '@sveltejs/adapter-static';
 | 
				
			||||||
import { vitePreprocess } from '@sveltejs/kit/vite';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @type {import('@sveltejs/kit').Config} */
 | 
					/** @type {import('@sveltejs/kit').Config} */
 | 
				
			||||||
const config = {
 | 
					const config = {
 | 
				
			||||||
	// Consult https://kit.svelte.dev/docs/integrations#preprocessors
 | 
						// Consult https://kit.svelte.dev/docs/integrations#preprocessors
 | 
				
			||||||
	// for more information about preprocessors
 | 
						// for more information about preprocessors
 | 
				
			||||||
	preprocess: [
 | 
						preprocess: [
 | 
				
			||||||
		vitePreprocess(),
 | 
					 | 
				
			||||||
		preprocess({
 | 
							preprocess({
 | 
				
			||||||
			postcss: true
 | 
								postcss: true
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user