Compare commits

...

38 Commits
1.1.0 ... main

Author SHA1 Message Date
ab422cb019
chore(release): 1.2.6
All checks were successful
Build latest image / build-container (push) Successful in 1m4s
Build release images / build-container (push) Successful in 1m1s
2025-05-23 10:47:34 +02:00
b7e3e59e7a
fix(register): clear email
All checks were successful
Build latest image / build-container (push) Successful in 47s
2025-05-23 10:46:34 +02:00
509685497e
chore(release): 1.2.5
Some checks failed
Build latest image / build-container (push) Failing after 6s
Build release images / build-container (push) Successful in 45s
2025-04-25 13:50:59 +02:00
016a86e188
fix: Disable selection 2025-04-25 13:50:43 +02:00
ca98acd5bc
fix(print): Disable edge image search 2025-04-25 13:48:08 +02:00
a96551cdd0
refactor(print): Adjusted size of elements when printed to avoid wasting paper 2025-04-25 13:41:45 +02:00
6f144d42af
style: Refactor footer content for print visibility
All checks were successful
Build latest image / build-container (push) Successful in 45s
2025-04-25 13:32:49 +02:00
408bd00288
chore(release): 1.2.4
All checks were successful
Build latest image / build-container (push) Successful in 1m1s
Build release images / build-container (push) Successful in 1m1s
2025-04-25 13:19:15 +02:00
5646fedd4e
style(print): Adjust print styles for improved readability 2025-04-25 13:19:01 +02:00
962307317f
chore(release): 1.2.3
All checks were successful
Build release images / build-container (push) Successful in 59s
Build latest image / build-container (push) Successful in 1m1s
2025-04-25 13:00:30 +02:00
5d440d0a0c
feat(print): Updated content of prints 2025-04-25 12:57:49 +02:00
54114a6547
fix: Hide print enabled debug message 2025-04-25 12:54:19 +02:00
8a08e19e00
chore(release): 1.2.2
All checks were successful
Build release images / build-container (push) Successful in 1m11s
Build latest image / build-container (push) Successful in 1m14s
2025-04-14 17:38:27 +02:00
642434b9fd
feat(register): Enable/disable print via query params
All checks were successful
Build latest image / build-container (push) Successful in 48s
2025-04-12 18:02:36 +02:00
b0feae1719
chore(release): 1.2.1
All checks were successful
Build latest image / build-container (push) Successful in 1m7s
Build release images / build-container (push) Successful in 1m8s
2025-04-08 21:12:57 +02:00
cd8b98c624
feat(register): Implement created_via 2025-04-08 21:11:33 +02:00
be4b8df02b
chore:(deps): Bump client 2025-04-08 21:11:06 +02:00
d3d0b356ac
chore(release): 1.2.0
All checks were successful
Build latest image / build-container (push) Successful in 1m11s
Build release images / build-container (push) Successful in 1m9s
2025-04-08 20:58:14 +02:00
3fdd8c80d8
fix: Updated styling
Some checks failed
Build latest image / build-container (push) Has been cancelled
2025-04-08 20:57:43 +02:00
3e3846f1cb
feat: Full printing support 2025-04-08 20:56:16 +02:00
ed7242cc2a
refactor(register): Switch to showing qr code
All checks were successful
Build latest image / build-container (push) Successful in 45s
2025-04-08 20:22:11 +02:00
6152500652
chore: Bump js lib 2025-04-08 20:14:12 +02:00
6ecaae1b8d
style(docs): Linting
All checks were successful
Build latest image / build-container (push) Successful in 44s
2025-04-07 15:16:45 +02:00
5f97c9d8da
refactor(svelte): Threw out workspace config 2025-04-07 15:11:21 +02:00
e32c2f3069
chore(release): 1.1.5
All checks were successful
Build latest image / build-container (push) Successful in 1m28s
Build release images / build-container (push) Successful in 44s
2025-04-07 15:01:23 +02:00
83826f966b
feat: clock widget, general cleanups 2025-04-07 15:01:06 +02:00
1665fd67ae
chore(deps): bump 2025-04-07 14:32:05 +02:00
7516d3579f
chore(release): 1.1.4
All checks were successful
Build release images / build-container (push) Successful in 50s
Build latest image / build-container (push) Successful in 56s
2025-04-02 23:47:01 +02:00
2c503f9b03
feat: improve registration flow
Some checks failed
Build latest image / build-container (push) Has been cancelled
2025-04-02 23:46:48 +02:00
6a0b014d55
chore(release): 1.1.3
All checks were successful
Build release images / build-container (push) Successful in 1m0s
Build latest image / build-container (push) Successful in 1m3s
2025-04-02 22:36:00 +02:00
b7f792c6f9
fix: registration without email
Some checks failed
Build latest image / build-container (push) Has been cancelled
2025-04-02 22:35:50 +02:00
528b025e55
chore(release): 1.1.2
All checks were successful
Build release images / build-container (push) Successful in 55s
Build latest image / build-container (push) Successful in 57s
2025-04-02 22:27:01 +02:00
368e97c6bb
fix: build
Some checks failed
Build latest image / build-container (push) Has been cancelled
2025-04-02 22:26:52 +02:00
6acd8bb634
🚀Bumped version to 1.1.1
Some checks failed
Build latest image / build-container (push) Failing after 19s
Build release images / build-container (push) Failing after 18s
2025-04-02 22:19:59 +02:00
6dcdba6568
feat: improved registration 2025-04-02 22:19:34 +02:00
525c096f7a
feat: disable chrome autocomplete 2025-04-02 22:19:12 +02:00
0de50822cd
Merge branch 'main' of git.odit.services:lfk/kiosk
Some checks failed
Build latest image / build-container (push) Failing after 18s
2025-03-22 23:10:31 +01:00
0177c50651
refactor(ci): Switch to actions 2025-03-22 23:08:06 +01:00
20 changed files with 1932 additions and 6368 deletions

27
.gitea/workflows/dev.yaml Normal file
View 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

View 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

View File

@ -1,40 +0,0 @@
steps:
- name: build edge
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/kiosk
tags:
- edge
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/kiosk:edge
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
when:
branch: dev
- name: build latest
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/kiosk
tags:
- latest
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
when:
branch: main
when:
event:
- push

View File

@ -1,22 +0,0 @@
steps:
- name: type checks
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
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
- name: build check
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
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
when:
event:
- pull_request

View File

@ -2,9 +2,106 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [1.2.6](https://git.odit.services/lfk/kiosk/compare/1.2.5...1.2.6)
- fix(register): clear email [`b7e3e59`](https://git.odit.services/lfk/kiosk/commit/b7e3e59e7a948dae76786094743ff5aa679b9a0a)
#### [1.2.5](https://git.odit.services/lfk/kiosk/compare/1.2.4...1.2.5)
> 25 April 2025
- refactor(print): Adjusted size of elements when printed to avoid wasting paper [`a96551c`](https://git.odit.services/lfk/kiosk/commit/a96551cdd0c2e4285d74a064f9c352f1343e4b77)
- chore(release): 1.2.5 [`5096854`](https://git.odit.services/lfk/kiosk/commit/509685497e2200f35fbd3d52a8dd7fc62988f246)
- style: Refactor footer content for print visibility [`6f144d4`](https://git.odit.services/lfk/kiosk/commit/6f144d42afedd38722d73fde350ea924db2341ba)
- fix: Disable selection [`016a86e`](https://git.odit.services/lfk/kiosk/commit/016a86e188c12e98113dd43a97dc0c25ea88e0d6)
- fix(print): Disable edge image search [`ca98acd`](https://git.odit.services/lfk/kiosk/commit/ca98acd5bc2e0082398748b0e3a9bb35b2adeb3c)
#### [1.2.4](https://git.odit.services/lfk/kiosk/compare/1.2.3...1.2.4)
> 25 April 2025
- style(print): Adjust print styles for improved readability [`5646fed`](https://git.odit.services/lfk/kiosk/commit/5646fedd4e71b9fa25a5a80d03199f7897cda21c)
- chore(release): 1.2.4 [`408bd00`](https://git.odit.services/lfk/kiosk/commit/408bd0028887cc27ee49aa0991ad1356f18d840a)
#### [1.2.3](https://git.odit.services/lfk/kiosk/compare/1.2.2...1.2.3)
> 25 April 2025
- feat(print): Updated content of prints [`5d440d0`](https://git.odit.services/lfk/kiosk/commit/5d440d0a0cba2f8f1470351ef740cfe957a0af47)
- chore(release): 1.2.3 [`9623073`](https://git.odit.services/lfk/kiosk/commit/962307317fbb83543b65e1bb36b266a888b732e0)
- fix: Hide print enabled debug message [`54114a6`](https://git.odit.services/lfk/kiosk/commit/54114a654733a9454a57a327bbf3f6dd1bf611f2)
#### [1.2.2](https://git.odit.services/lfk/kiosk/compare/1.2.1...1.2.2)
> 14 April 2025
- feat(register): Enable/disable print via query params [`642434b`](https://git.odit.services/lfk/kiosk/commit/642434b9fd4ecf985b160d4d87edad0e8bc106c6)
- chore(release): 1.2.2 [`8a08e19`](https://git.odit.services/lfk/kiosk/commit/8a08e19e00658fb145bb7fff7553ca33d6424b21)
#### [1.2.1](https://git.odit.services/lfk/kiosk/compare/1.2.0...1.2.1)
> 8 April 2025
- chore:(deps): Bump client [`be4b8df`](https://git.odit.services/lfk/kiosk/commit/be4b8df02bed33b4755cdf81b8a843239b32bcc1)
- chore(release): 1.2.1 [`b0feae1`](https://git.odit.services/lfk/kiosk/commit/b0feae1719c993eb351f1c36c35eedd8a5ffd7ea)
- feat(register): Implement created_via [`cd8b98c`](https://git.odit.services/lfk/kiosk/commit/cd8b98c6249b84cb6d2c4f7eb1d403c1837bc151)
#### [1.2.0](https://git.odit.services/lfk/kiosk/compare/1.1.5...1.2.0)
> 8 April 2025
- refactor(svelte): Threw out workspace config [`5f97c9d`](https://git.odit.services/lfk/kiosk/commit/5f97c9d8da1a9002875d8fe35606c078c62c1d0a)
- feat: Full printing support [`3e3846f`](https://git.odit.services/lfk/kiosk/commit/3e3846f1cb1fe281edce7c6ce3485f54ddbed3e2)
- refactor(register): Switch to showing qr code [`ed7242c`](https://git.odit.services/lfk/kiosk/commit/ed7242cc2a6e1af22de8950a53b64e94459a2aee)
- style(docs): Linting [`6ecaae1`](https://git.odit.services/lfk/kiosk/commit/6ecaae1b8dcce099b82cd257a22bd1d579d79ba2)
- chore(release): 1.2.0 [`d3d0b35`](https://git.odit.services/lfk/kiosk/commit/d3d0b356ac6d0e6d0fa40a7390799d57a3e50f7a)
- chore: Bump js lib [`6152500`](https://git.odit.services/lfk/kiosk/commit/61525006526ab5e237b0caf24a474618fc238372)
- fix: Updated styling [`3fdd8c8`](https://git.odit.services/lfk/kiosk/commit/3fdd8c80d8d72bdc899739896fa379ff7a7b620d)
#### [1.1.5](https://git.odit.services/lfk/kiosk/compare/1.1.4...1.1.5)
> 7 April 2025
- chore(release): 1.1.5 [`e32c2f3`](https://git.odit.services/lfk/kiosk/commit/e32c2f3069e03584f3829a96e3fea94f98bf419b)
- chore(deps): bump [`1665fd6`](https://git.odit.services/lfk/kiosk/commit/1665fd67ae7153ece759edbe3e74262eb207a2f6)
- feat: clock widget, general cleanups [`83826f9`](https://git.odit.services/lfk/kiosk/commit/83826f966bb0de2402889d6574c6db7730831119)
#### [1.1.4](https://git.odit.services/lfk/kiosk/compare/1.1.3...1.1.4)
> 2 April 2025
- feat: improve registration flow [`2c503f9`](https://git.odit.services/lfk/kiosk/commit/2c503f9b0333b668730c4eb11deb5184ee49f295)
- chore(release): 1.1.4 [`7516d35`](https://git.odit.services/lfk/kiosk/commit/7516d3579f31166f172cd5f5bcf071366d9c59ec)
#### [1.1.3](https://git.odit.services/lfk/kiosk/compare/1.1.2...1.1.3)
> 2 April 2025
- chore(release): 1.1.3 [`6a0b014`](https://git.odit.services/lfk/kiosk/commit/6a0b014d55b129eef17d70bb9a86203a272d3ad3)
- fix: registration without email [`b7f792c`](https://git.odit.services/lfk/kiosk/commit/b7f792c6f99249acd0c8c1154800c4442ad5a8b0)
#### [1.1.2](https://git.odit.services/lfk/kiosk/compare/1.1.1...1.1.2)
> 2 April 2025
- fix: build [`368e97c`](https://git.odit.services/lfk/kiosk/commit/368e97c6bba238b605532aa9c598ace5f2bac592)
- chore(release): 1.1.2 [`528b025`](https://git.odit.services/lfk/kiosk/commit/528b025e55ce6d4ab0dec32803d201d057725dac)
#### [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)

View File

@ -1,9 +1,9 @@
FROM registry.odit.services/hub/library/node:19.9.0-alpine3.16 AS build
ARG NPM_REGISTRY_URL=registry.npmjs.org
FROM registry.odit.services/hub/library/node:23.10.0-alpine3.21 AS build
# ARG NPM_REGISTRY_URL=registry.npmjs.org
WORKDIR /app
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
COPY src ./src
@ -11,5 +11,5 @@ COPY static ./static
RUN pnpm build
# 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

View File

@ -1,32 +1,38 @@
# @lfk/kiosk
## Overview 👀
This is a simple kiosk style register form for the LfK runnersystem.
The basic idea is:
1. Create a runnersystem user with only `RUNNER:CREATE` permissions.
2. Login with this user under `/login`
3. Runners can register via their firstnam and lastname
4. The kiosk creates the runner via the backend and shows their id, firstname, lastname and a barcode containing their id
3. Runners can register via their firstname and lastname
4. The kiosk creates the runner via the backend and shows their id, firstname, lastname and a barcode containing their id along
## Development 🛠️
```
```shell
pnpm i
pnpm dev --open
```
## Build 🚀
```
```shell
pnpm i
pnpm build
```
## Docker 🐳
```
```shell
docker build .
docker-compose up
```
## Kiosk Google Chrome
```
``` shell
chrome https://run.lauf-fuer-kaya.de/kiosk/ -kiosk
```
```

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "@lfk/kiosk",
"version": "1.1.0",
"version": "1.2.6",
"private": false,
"license": "MIT",
"repository": "https://git.odit.services/lfk/kiosk",
@ -35,44 +35,42 @@
"devDependencies": {
"@odit/license-exporter": "0.2.0",
"@philippdormann/release-it": "^1.0.0",
"@sveltejs/adapter-static": "3.0.6",
"@sveltejs/kit": "2.12.0",
"@sveltejs/vite-plugin-svelte": "^5.0.2",
"@sveltejs/adapter-static": "3.0.8",
"@sveltejs/kit": "2.20.4",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@types/bwip-js": "^3.2.3",
"@typescript-eslint/eslint-plugin": "8.18.0",
"@typescript-eslint/parser": "8.18.0",
"@typescript-eslint/eslint-plugin": "8.29.0",
"@typescript-eslint/parser": "8.29.0",
"auto-changelog": "2.5.0",
"autoprefixer": "10.4.20",
"eslint": "9.17.0",
"eslint-config-prettier": "9.1.0",
"postcss": "8.4.49",
"postcss-load-config": "6.0.1",
"prettier": "3.4.2",
"prettier-plugin-svelte": "3.3.2",
"svelte": "5.14.0",
"svelte-check": "4.1.1",
"eslint": "9.24.0",
"eslint-config-prettier": "10.1.1",
"prettier": "3.5.3",
"prettier-plugin-svelte": "3.3.3",
"svelte": "5.25.7",
"svelte-check": "4.1.5",
"svelte-preprocess": "6.0.3",
"tailwindcss": "3.4.16",
"tslib": "2.8.1",
"typescript": "5.7.2",
"vite": "6.0.3"
"typescript": "5.8.3",
"vite": "6.2.5"
},
"type": "module",
"dependencies": {
"@fontsource/athiti": "^5.1.0",
"@odit/lfk-client-js": "1.1.3",
"bwip-js": "4.5.1",
"eslint-plugin-svelte": "^2.46.1"
"@fontsource/athiti": "^5.2.5",
"@odit/lfk-client-js": "1.2.2",
"@tailwindcss/vite": "^4.1.3",
"bwip-js": "4.5.3",
"eslint-plugin-svelte": "^3.5.1",
"tailwindcss": "^4.1.3"
},
"release-it": {
"git": {
"commit": true,
"requireCleanWorkingDir": false,
"commitMessage": "🚀Bumped version to ${version}",
"commitMessage": "chore(release): ${version}",
"requireBranch": "main",
"push": true,
"tag": true,
"tagName": null,
"tagName": "${version}",
"tagAnnotation": "${version}"
},
"npm": {

2081
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
const tailwindcss = require('tailwindcss');
const autoprefixer = require('autoprefixer');
const config = {
plugins: [
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(),
//But others, like autoprefixer, need to run after,
autoprefixer
]
};
module.exports = config;

4
src/app.css Normal file
View File

@ -0,0 +1,4 @@
@import 'tailwindcss';
* {
font-family: 'Athiti', sans-serif;
}

View File

@ -5,11 +5,6 @@
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
<style>
body {
font-family: 'Athiti', sans-serif;
}
</style>
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>

View File

@ -1,4 +0,0 @@
/* Write your global styles here, in PostCSS syntax */
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -1,11 +1,11 @@
<script>
import { OpenAPI } from '@odit/lfk-client-js';
import { env } from '$env/dynamic/public';
import '../app.postcss';
import '@fontsource/athiti';
import '../app.css';
import { onMount } from 'svelte';
import lfkbackground from './background.png';
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
@ -14,10 +14,25 @@
if (e.keyCode === 116) e.preventDefault();
});
});
let time = new Date();
$: hours = (time.getHours() + '').padStart(2, '0');
$: minutes = (time.getMinutes() + '').padStart(2, '0');
$: seconds = (time.getSeconds() + '').padStart(2, '0');
setInterval(() => {
time = new Date();
}, 500);
</script>
<div class="dark:bg-slate-900 flex flex-col h-screen">
<div
class="text-neutral-800 flex flex-col h-screen print:h-full select-none"
style="background: url({lfkbackground});background-position: center center!important;background-size: contain!important;background-repeat: no-repeat!important;"
>
<main class="flex-grow">
<div
class="text-6xl font-semibold text-right text-gray-900 font-mono top-2 w-full fixed pr-4 xl:top-6 xl:pr-8 print:hidden"
>
{hours}:{minutes}:{seconds}
</div>
<slot />
</main>
</div>

View File

@ -4,20 +4,29 @@
import { onMount } from 'svelte';
import Login from './Login.svelte';
$: printEnabled = false;
onMount(() => {
const params = new URLSearchParams(window.location.search);
if (params.get('print') === 'true') {
printEnabled = true;
}
loginFromStorage();
});
</script>
{#if $userState.isLoggedIn}
<Register />
<Register bind:printEnabled />
{:else}
<Login />
{/if}
<div class="fixed bottom-0 w-full text-center text-xl p-4 dark:text-white select-none">
<div class="fixed bottom-0 w-full text-center text-xl p-4 dark:text-white select-none print:absolute print:bottom-auto print:text-sm">
{#if $userState.isLoggedIn}
<b class="font-bold">LfK!2025</b> powered by
<b class="font-bold">ODIT.Services</b>
<span class="print:hidden">
<b class="font-bold">LfK!2025</b> powered by
<b class="font-bold">ODIT.Services</b>
</span>
<b class="font-bold hidden print:block"> LfK!2025 powered by ODIT.Services</b>
{:else}
<a
rel="noopener noreferrer"
@ -33,7 +42,6 @@
class="underline">Impressum</a
>
<br />
<br />
<b class="font-bold">LfK!2025</b> powered by
<a
rel="noopener noreferrer"

View File

@ -26,95 +26,84 @@
</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">
<div class="relative overflow-hidden">
<div class="max-w-md mx-auto px-4 sm:px-6 lg:px-8 pt-24 pb-10">
<div class="text-center">
<h1 class="block text-7xl font-bold">LfK!Kiosk</h1>
<h1 class="block text-4xl font-bold">Login</h1>
<!-- <p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Melde dich für den LfK an</p> -->
</div>
<!-- Title -->
<div class="mt-5 max-w-2xl text-center mx-auto">
<!-- <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>
</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">
{#if loginError}
<div
class="mt-7 bg-white border border-gray-200 rounded-xl shadow-sm dark:bg-gray-800 dark:border-gray-700"
class="bg-red-500 text-white text-center font-semibold rounded-md shadow-lg mb-8 mt-4"
role="alert"
>
<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 class="p-4">Falscher Nutzername oder falsches Passwort</div>
</div>
</div>
{/if}
<!-- Form -->
<form on:submit|preventDefault={login}>
<div class="grid gap-y-4">
<!-- Form Group -->
<div>
<label for="username" class="block font-semibold">Benutzername</label>
<div class="relative">
<input
autofocus
bind:value={username}
autocomplete="one-time-code"
type="username"
id="username"
name="username"
placeholder="Benutzername"
class="placeholder:text-neutral-800 py-3 px-4 block w-full rounded-md focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 border bg-white"
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 font-semibold">Passwort</label>
</div>
<div class="relative">
<input
bind:value={password}
autocomplete="one-time-code"
type="password"
id="password"
name="password"
placeholder="Passwort"
class="placeholder:text-neutral-800 py-3 px-4 block w-full rounded-md focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 border bg-white"
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 dark:focus:ring-offset-gray-800"
>Anmelden</button
>
</div>
</form>
<!-- End Form -->
</div>
</div>

View File

@ -1,7 +1,6 @@
<script lang="ts">
import { RunnerService, type ResponseRunner } from '@odit/lfk-client-js';
import bwipjs from 'bwip-js';
import lfkbackground from './background.png';
import { onMount } from 'svelte';
$: firstname = '';
@ -10,6 +9,8 @@
$: doneButtonEnabled = false;
$: showResult = false;
export let printEnabled = false;
let response: ResponseRunner;
const group = 1; //Default to Bürgerlauf
@ -32,13 +33,25 @@
async function register() {
try {
let emailToSend = null;
if (email !== '') {
if (email.includes('@')) {
emailToSend = email;
}
}
response = (await RunnerService.runnerControllerPost({
firstname,
lastname,
email,
group
email: emailToSend,
group,
created_via: 'kiosk'
})) as ResponseRunner;
showResult = true;
if (printEnabled) {
setTimeout(() => {
window.print();
}, 200);
}
setTimeout(() => {
doneButtonEnabled = true;
setTimeout(() => {
@ -51,25 +64,33 @@
localStorage.clear();
location.reload();
}
email = '';
firstname = '';
lastname = '';
}
function textToBase64Barcode(text: string, is_qrcode: boolean) {
const canvas = document.createElement('canvas');
let bcid = 'code128';
if (is_qrcode) {
bcid = 'qrcode';
bwipjs.toCanvas(canvas, {
bcid: 'qrcode',
text: `${text}`,
scale: 10,
includetext: false,
textxalign: 'center',
backgroundcolor: 'ffffff'
});
} else {
bwipjs.toCanvas(canvas, {
bcid: 'code128',
text: `${text}`,
scale: 10,
includetext: true,
textxalign: 'center',
backgroundcolor: 'ffffff',
height: 10
});
}
bwipjs.toCanvas(canvas, {
bcid,
text: `${text}`,
scale: 10,
includetext: true,
textxalign: 'center',
backgroundcolor: 'ffffff',
height: 10
});
return canvas.toDataURL('image/png');
}
@ -78,16 +99,13 @@
});
</script>
<div
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;"
>
<div class="w-full max-w-md mx-auto p-6">
<div class="flex h-full items-center py-16 print:py-0 print:items-baseline">
<div class="w-full max-w-md mx-auto p-6 print:p-0">
<!-- <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="mt-5">
<div class="p-4 sm:p-7 print:p-0 print:sm:p-0">
<div class="mt-5 print:mt-0">
<!-- Form -->
{#if !showResult}
<div class="text-center">
@ -104,13 +122,18 @@
<input
on:keydown={(e) => {
if (e.keyCode === 13) {
e.preventDefault();
document.getElementById('lastname')?.focus();
}
if (e.keyCode === 40) {
document.getElementById('lastname')?.focus();
}
}}
type="text"
autocomplete="one-time-code"
id="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="font-semibold placeholder:font-normal placeholder:text-black dark:placeholder:text-gray-200 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-white border bg-white"
required
placeholder="Vorname"
bind:value={firstname}
@ -149,10 +172,23 @@
<label for="lastname" class="block text-lg font-bold mb-2 sr-only">Nachname</label>
<div class="relative">
<input
on:keydown={(e) => {
if (e.keyCode === 13) {
e.preventDefault();
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"
id="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="font-semibold placeholder:font-normal placeholder:text-black dark:placeholder:text-gray-200 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-white border bg-white"
required
placeholder="Nachname"
aria-describedby="lastname-error"
@ -188,14 +224,28 @@
<!-- Form Group -->
<div>
<label for="email" class="block text-lg font-bold mb-2 sr-only">E-Mail (optional)</label>
<label for="email" class="block text-lg font-bold mb-2 sr-only"
>E-Mail (optional)</label
>
<div class="relative">
<input
on:keydown={(e) => {
if (e.keyCode === 13) {
e.preventDefault();
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="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"
required
class="font-semibold placeholder:font-normal placeholder:text-black dark:placeholder:text-gray-200 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-white border bg-white"
placeholder="E-Mail (optional)"
aria-describedby="lastname-error"
bind:value={email}
@ -227,33 +277,79 @@
</p> -->
</div>
<!-- End Form Group -->
<p
class="bg-white text-gray-800 dark:bg-gray-800 dark:text-gray-400 rounded border p-3"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="inline"
><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path
d="M12 8h.01"
/></svg
>
Mit der Registrierung akzeptieren Sie die AGBs sowie die Datenschutzerklärung des Lauf
für Kaya! 2025 sowie der ODIT.Services GmbH.
</p>
<button
on:keydown={(e) => {
if (e.keyCode === 38) {
document.getElementById('email')?.focus();
}
}}
id="submit"
type="submit"
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 cursor-pointer"
>Anmelden</button
>
</div>
</form>
<!-- End Form -->
{:else}
<div class="mb-2 text-center">
<h3 class="text-4xl font-semibold dark:text-white">
<div class="mb-2 text-center print:mb-0">
<h3 class="text-4xl font-semibold dark:text-white print:text-2xl/tight">
{response.firstname}
{response.lastname}
</h3>
<h4 class="font-semibold dark:text-white hidden print:block print:text-lg/tight">
{response.id}
</h4>
</div>
<div class="mb-2 text-center">
<div class="mb-2 text-center print:mb-0">
<h3 class="text-xl font-semibold dark:text-white print:hidden">
Scanne diesen QR-Code, um zu unserem Selfservice zu gelangen. Hier findest du deine
Rundenzeiten, Spenden und Urkunden.
</h3>
<h3 class="text-base/tight font-semibold dark:text-white hidden print:block">
Zeige diesen QR-Code am Infozelt vor, um deine Läuferkarte zu erhalten.
</h3>
<img
class="w-full md:w-auto mb-2 mx-auto bg-white p-4"
alt="runner id"
src={textToBase64Barcode(response.id.toString(), false)}
class="w-full md:w-auto mb-2 mx-auto bg-white p-4 print:w-3/5 print:p-0 pointer-events-none"
alt="runner selfservice"
src={textToBase64Barcode(response.selfserviceLink.toString(), true)}
/>
<h3 class="text-base/tight font-semibold dark:text-white hidden print:block">
Scanne diesen QR-Code, um zu unserem Selfservice zu gelangen. Hier findest du deine
Rundenzeiten, Spenden und Urkunden.
</h3>
{#if printEnabled}
<h3 class="text-xl font-semibold dark:text-white print:hidden">
Bitte nehm den Bon mit und zeige ihn am Infozelt vor, um deine Läuferkarte zu erhalten.
Auf dem Bon findest auch nochmal den QR-Code.
</h3>
{/if}
</div>
<div class="mx-auto text-center items-center">
<div class="mx-auto text-center items-center print:hidden">
<button
class:opacity-50={!doneButtonEnabled}
disabled={!doneButtonEnabled}
@ -263,7 +359,7 @@
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 cursor-pointer"
>Fertig</button
>
</div>
@ -272,4 +368,4 @@
<!-- </div> -->
</div>
</div>
</div>
</div>

View File

@ -1,11 +0,0 @@
const config = {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: []
};
module.exports = config;

View File

@ -1,6 +1,9 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [sveltekit()]
});
plugins: [
tailwindcss(),
sveltekit(),
],
});