Compare commits

..

No commits in common. "main" and "1.0.0" have entirely different histories.
main ... 1.0.0

20 changed files with 11710 additions and 4903 deletions

131
.drone.yml Normal file
View File

@ -0,0 +1,131 @@
---
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

View File

@ -1,27 +0,0 @@
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

@ -1,27 +0,0 @@
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

@ -2,117 +2,10 @@
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)
### [1.0.0](https://git.odit.services/lfk/kiosk/compare/0.6.0...1.0.0)
> 19 April 2023
#### [1.0.0](https://git.odit.services/lfk/kiosk/compare/0.6.0...1.0.0)
- 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)

View File

@ -1,9 +1,9 @@
FROM registry.odit.services/hub/library/node:23.10.0-alpine3.21 AS build
# ARG NPM_REGISTRY_URL=registry.npmjs.org
FROM registry.odit.services/hub/library/node:19.9.0-alpine3.16 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 i -g pnpm@10.7
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
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,38 +1,32 @@
# @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 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
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
## 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.2.6",
"version": "1.0.0",
"private": false,
"license": "MIT",
"repository": "https://git.odit.services/lfk/kiosk",
@ -33,44 +33,45 @@
"license:export": "license-exporter --markdown && git stage licenses.md"
},
"devDependencies": {
"@odit/license-exporter": "0.2.0",
"@philippdormann/release-it": "^1.0.0",
"@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.29.0",
"@typescript-eslint/parser": "8.29.0",
"auto-changelog": "2.5.0",
"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",
"tslib": "2.8.1",
"typescript": "5.8.3",
"vite": "6.2.5"
"@odit/license-exporter": "0.0.12",
"@sveltejs/adapter-static": "2.0.2",
"@sveltejs/kit": "1.15.7",
"@types/bwip-js": "^3.2.0",
"@typescript-eslint/eslint-plugin": "5.59.0",
"@typescript-eslint/parser": "5.59.0",
"auto-changelog": "2.4.0",
"autoprefixer": "10.4.14",
"eslint": "8.38.0",
"eslint-config-prettier": "8.8.0",
"eslint-plugin-svelte3": "4.0.0",
"postcss": "8.4.22",
"postcss-load-config": "4.0.1",
"prettier": "2.8.7",
"prettier-plugin-svelte": "2.10.0",
"release-it": "15.10.1",
"svelte": "3.58.0",
"svelte-check": "3.2.0",
"svelte-preprocess": "5.0.3",
"tailwindcss": "3.3.1",
"tslib": "2.5.0",
"typescript": "5.0.4",
"vite": "4.2.2"
},
"type": "module",
"dependencies": {
"@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"
"@fontsource/athiti": "^4.5.10",
"@odit/lfk-client-js": "1.0.1",
"bwip-js": "3.4.0"
},
"release-it": {
"git": {
"commit": true,
"requireCleanWorkingDir": false,
"commitMessage": "chore(release): ${version}",
"commitMessage": "🚀Bumped version to ${version}",
"requireBranch": "main",
"push": true,
"tag": true,
"tagName": "${version}",
"tagName": null,
"tagAnnotation": "${version}"
},
"npm": {
@ -79,5 +80,11 @@
"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"
}
},
"volta": {
"node": "19.9.0"
},
"engines": {
"pnpm": "8"
}
}

7154
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

13
postcss.config.cjs Normal file
View File

@ -0,0 +1,13 @@
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;

View File

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

View File

@ -5,6 +5,11 @@
<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>

4
src/app.postcss Normal file
View File

@ -0,0 +1,4 @@
/* 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 = 'https://run.lauf-fuer-kaya.de';
OpenAPI.BASE = env.PUBLIC_BASE_URL || 'https://run.lauf-fuer-kaya.de';
onMount(() => {
window.addEventListener('keydown', (e) => {
// F1
@ -14,25 +14,10 @@
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="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;"
>
<div class="dark:bg-slate-900 flex flex-col h-screen">
<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,29 +4,20 @@
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 bind:printEnabled />
<Register />
{:else}
<Login />
{/if}
<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">
<div class="fixed bottom-0 w-full text-center text-xl p-4 dark:text-white select-none">
{#if $userState.isLoggedIn}
<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>
<b class="font-bold">LfK!2023</b> powered by
<b class="font-bold">ODIT.Services</b>
{:else}
<a
rel="noopener noreferrer"
@ -42,7 +33,8 @@
class="underline">Impressum</a
>
<br />
<b class="font-bold">LfK!2025</b> powered by
<br />
<b class="font-bold">LfK!2023</b> powered by
<a
rel="noopener noreferrer"
target="_blank"

View File

@ -26,84 +26,95 @@
</script>
<!-- -->
<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>
<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">
<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 -->
{#if loginError}
<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="bg-red-500 text-white text-center font-semibold rounded-md shadow-lg mb-8 mt-4"
role="alert"
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">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 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 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>
<!-- 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>
</div>

View File

@ -1,16 +1,14 @@
<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 = '';
$: lastname = '';
$: email = '';
$: doneButtonEnabled = false;
$: showResult = false;
export let printEnabled = false;
let response: ResponseRunner;
const group = 1; //Default to Bürgerlauf
@ -33,25 +31,12 @@
async function register() {
try {
let emailToSend = null;
if (email !== '') {
if (email.includes('@')) {
emailToSend = email;
}
}
response = (await RunnerService.runnerControllerPost({
firstname,
lastname,
email: emailToSend,
group,
created_via: 'kiosk'
group
})) as ResponseRunner;
showResult = true;
if (printEnabled) {
setTimeout(() => {
window.print();
}, 200);
}
setTimeout(() => {
doneButtonEnabled = true;
setTimeout(() => {
@ -64,33 +49,25 @@
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) {
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
});
bcid = 'qrcode';
}
bwipjs.toCanvas(canvas, {
bcid,
text: `${text}`,
scale: 10,
includetext: true,
textxalign: 'center',
backgroundcolor: 'ffffff',
height: 10
});
return canvas.toDataURL('image/png');
}
@ -99,17 +76,20 @@
});
</script>
<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="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="mt-7 bg-white border border-gray-200 rounded-xl shadow-sm dark:bg-gray-800 dark:border-gray-200"
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 print:p-0 print:sm:p-0">
<div class="mt-5 print:mt-0">
<div class="p-4 sm:p-7">
<div class="mt-5">
<!-- Form -->
{#if !showResult}
<div class="text-center">
<h1 class="block text-7xl font-bold text-gray-800 dark:text-white">LfK!2025</h1>
<h1 class="block text-7xl font-bold text-gray-800 dark:text-white">LfK!2023</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> -->
</div>
@ -122,18 +102,13 @@
<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="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"
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
placeholder="Vorname"
bind:value={firstname}
@ -172,23 +147,10 @@
<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="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"
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
placeholder="Nachname"
aria-describedby="lastname-error"
@ -222,134 +184,32 @@
</div>
<!-- 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) => {
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="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}
/>
<!-- <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 -->
<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 cursor-pointer"
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
>
</div>
</form>
<!-- End Form -->
{:else}
<div class="mb-2 text-center print:mb-0">
<h3 class="text-4xl font-semibold dark:text-white print:text-2xl/tight">
<div class="mb-2 text-center">
<h3 class="text-4xl font-semibold dark:text-white">
{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 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>
<div class="mb-2 text-center">
<img
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)}
class="w-full md:w-auto mb-2 mx-auto bg-white p-4"
alt="runner id"
src={textToBase64Barcode(response.id.toString(), false)}
/>
<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 print:hidden">
<div class="mx-auto text-center items-center">
<button
class:opacity-50={!doneButtonEnabled}
disabled={!doneButtonEnabled}
@ -359,7 +219,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 cursor-pointer"
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
>
</div>

View File

@ -1,11 +1,13 @@
import preprocess from 'svelte-preprocess';
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: [
vitePreprocess(),
preprocess({
postcss: true
})

11
tailwind.config.cjs Normal file
View File

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

View File

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