Compare commits
36 Commits
16deab5308
...
1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
16d15f7242
|
|||
|
115767c656
|
|||
|
bb3c801908
|
|||
|
e512325115
|
|||
|
aa7d2dbe1b
|
|||
|
01cd8d4b78
|
|||
|
c7c1c6dc41
|
|||
|
bf8b351b64
|
|||
|
58830c5db3
|
|||
|
066e67c64f
|
|||
|
5f5b03a8a0
|
|||
|
cbfbd92d0e
|
|||
|
418fe7773f
|
|||
|
4b6e11d8d2
|
|||
|
0698038523
|
|||
|
297b88016b
|
|||
|
8959223016
|
|||
|
a3e437d966
|
|||
|
19c9fa339b
|
|||
|
8017f009e4
|
|||
|
482d6387fa
|
|||
|
ff36691ada
|
|||
|
8ec4fc0c83
|
|||
|
a07eb4ddf5
|
|||
|
ec6598feb1
|
|||
|
93872030ed
|
|||
|
a610c6abd1
|
|||
|
0a883ce7fb
|
|||
|
f2d8ab81e9
|
|||
|
c546a96c4d
|
|||
|
c82fdf3823
|
|||
|
a46a67793c
|
|||
|
898d3595a0
|
|||
|
3aa6f0473b
|
|||
|
22be68311b
|
|||
|
5d7a25e54f
|
123
CHANGELOG.md
Normal file
123
CHANGELOG.md
Normal file
@@ -0,0 +1,123 @@
|
||||
### Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
|
||||
|
||||
#### [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)
|
||||
- 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)
|
||||
|
||||
> 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)
|
||||
|
||||
#### [0.4.2](https://git.odit.services/lfk/kiosk/compare/0.4.1...0.4.2)
|
||||
|
||||
> 19 April 2023
|
||||
|
||||
- 🚀Bumped version to 0.4.2 [`a3e437d`](https://git.odit.services/lfk/kiosk/commit/a3e437d9665e9ee1836770618c10adbbd1c8f7d6)
|
||||
- fix(hrefs): Fixed relative locations [`19c9fa3`](https://git.odit.services/lfk/kiosk/commit/19c9fa339b3ddc4adef39d5783346bfd0db904af)
|
||||
|
||||
#### [0.4.1](https://git.odit.services/lfk/kiosk/compare/0.4.0...0.4.1)
|
||||
|
||||
> 19 April 2023
|
||||
|
||||
- 🚀Bumped version to 0.4.1 [`8017f00`](https://git.odit.services/lfk/kiosk/commit/8017f009e4ba452b22dd84b1f777f4e0b2f5e8b9)
|
||||
- fix(userstore): Prefix localstorage keys with `kiosk-` [`ff36691`](https://git.odit.services/lfk/kiosk/commit/ff36691ada802fc1560c430beb865246dff782ed)
|
||||
- Redirects/links relative [`482d638`](https://git.odit.services/lfk/kiosk/commit/482d6387fac83a05ebaaf762cde7a68818ecf31f)
|
||||
|
||||
#### [0.4.0](https://git.odit.services/lfk/kiosk/compare/0.3.0...0.4.0)
|
||||
|
||||
> 19 April 2023
|
||||
|
||||
- 🚀Bumped version to 0.4.0 [`8ec4fc0`](https://git.odit.services/lfk/kiosk/commit/8ec4fc0c835b4eb2fc634fba8d04d301d72fb3fd)
|
||||
- Merge pull request 'branding' (#1) from branding into main [`a07eb4d`](https://git.odit.services/lfk/kiosk/commit/a07eb4ddf52c31b391ea14d13c129282b5e344c3)
|
||||
- chore(deps): update all [`a610c6a`](https://git.odit.services/lfk/kiosk/commit/a610c6abd1887bf450294fff15db6eca7d99919c)
|
||||
- branding [`0a883ce`](https://git.odit.services/lfk/kiosk/commit/0a883ce7fbd3defccbe7be70ce6affcab281c9c5)
|
||||
- Lockfile [`9387203`](https://git.odit.services/lfk/kiosk/commit/93872030ed48a315d9721f253ff00568e1f42aee)
|
||||
|
||||
#### [0.3.0](https://git.odit.services/lfk/kiosk/compare/0.2.0...0.3.0)
|
||||
|
||||
> 19 April 2023
|
||||
|
||||
- feat(registration): drop privacy checkbox [privacy is linked on page] [`c546a96`](https://git.odit.services/lfk/kiosk/commit/c546a96c4d959b41181c34d6affccafdf84a221a)
|
||||
- 🚀Bumped version to 0.3.0 [`f2d8ab8`](https://git.odit.services/lfk/kiosk/commit/f2d8ab81e9ed87f8a9e0cae3010f27ed12c081cb)
|
||||
|
||||
#### [0.2.0](https://git.odit.services/lfk/kiosk/compare/0.1.0...0.2.0)
|
||||
|
||||
> 19 April 2023
|
||||
|
||||
- feat(registration): cleanup finished page [`898d359`](https://git.odit.services/lfk/kiosk/commit/898d3595a032c87615e1825d0023299b029fc19e)
|
||||
- 🚀Bumped version to 0.2.0 [`c82fdf3`](https://git.odit.services/lfk/kiosk/commit/c82fdf3823acf0ea49f0218ba57805e5d15fae97)
|
||||
|
||||
#### 0.1.0
|
||||
|
||||
> 19 April 2023
|
||||
|
||||
- 🚀Bumped version to 0.1.0 [`3aa6f04`](https://git.odit.services/lfk/kiosk/commit/3aa6f0473bd8767cbe33277643a5778d2b68a8ae)
|
||||
- Basic sveltekit project [`e0c0cbb`](https://git.odit.services/lfk/kiosk/commit/e0c0cbbbd8b2c4cb7db0a8ae3aa295083ae636d1)
|
||||
- Release config [`6b98ee9`](https://git.odit.services/lfk/kiosk/commit/6b98ee96341def78447317a39e1ff30f9db73a9d)
|
||||
- Added basic welcome page [`5ed21bb`](https://git.odit.services/lfk/kiosk/commit/5ed21bb13d30cc43bc16fd6357f2e92e031c3273)
|
||||
- Bump ts [`50764bc`](https://git.odit.services/lfk/kiosk/commit/50764bca472a441c2e84fc3273771303a94759ae)
|
||||
- Basic registration page [`09aee15`](https://git.odit.services/lfk/kiosk/commit/09aee15f60bec58ca3cc3b9ce392774a7ff77219)
|
||||
- Added basic drone docker build, build checks and typechecks [`eca9966`](https://git.odit.services/lfk/kiosk/commit/eca9966e29f5222189e0f10a6874e3c9e5f32b56)
|
||||
- Basic userstore [`88f3657`](https://git.odit.services/lfk/kiosk/commit/88f36575fb81c47b2e88f708890da77dcadde2e1)
|
||||
- Added login page with logic [`078e8dc`](https://git.odit.services/lfk/kiosk/commit/078e8dcb9af67ea874a7547c9303cb2a831a8486)
|
||||
- Added license exporter [`28b45f8`](https://git.odit.services/lfk/kiosk/commit/28b45f876877391d466a4a71e0772793bbe02137)
|
||||
- Added readme [`0bd83f8`](https://git.odit.services/lfk/kiosk/commit/0bd83f8000daeef993764aea29149036b1d80254)
|
||||
- Added runnerid as barcode [`5a81cb6`](https://git.odit.services/lfk/kiosk/commit/5a81cb64f59ca75264a38d09d54c19e506486e3a)
|
||||
- Registration feedback logic [`d3d0d17`](https://git.odit.services/lfk/kiosk/commit/d3d0d17b3a99ab8412df3111dc2d4c029fd04908)
|
||||
- Pin dependencies [`abff31a`](https://git.odit.services/lfk/kiosk/commit/abff31aaee4b6f6a07f4e1292e2b95d13b995fab)
|
||||
- Register results [`7cecbfe`](https://git.odit.services/lfk/kiosk/commit/7cecbfe80e60bc22cab9f4c0e8e2aa0b33899280)
|
||||
- Authed page login logic [`7879ca8`](https://git.odit.services/lfk/kiosk/commit/7879ca82fde600fdb9f314b6dd63a324eb308102)
|
||||
- Added dockerfile + compose [`e5535f1`](https://git.odit.services/lfk/kiosk/commit/e5535f18692d7afc3f2636283722e61aa0437c59)
|
||||
- Package project info [`2e355db`](https://git.odit.services/lfk/kiosk/commit/2e355dbb46404fe0eccd8409614ec7444933bcae)
|
||||
- Added bwip types [`1a0f52f`](https://git.odit.services/lfk/kiosk/commit/1a0f52f31f9bdd0fd78756e714f23433e16deb1e)
|
||||
- Fix in auth [`710cad3`](https://git.odit.services/lfk/kiosk/commit/710cad376eb865a0c82743a7213c3f4097027c23)
|
||||
- Switched to adapter static [`93bf436`](https://git.odit.services/lfk/kiosk/commit/93bf436e94ad492a1bc1acdaa8958ef9e79e3a73)
|
||||
- fix(a11y): input borders [`fffe290`](https://git.odit.services/lfk/kiosk/commit/fffe29036045ead825b54f44b38d824d09f039b8)
|
||||
- Added lfk client [`f927cc9`](https://git.odit.services/lfk/kiosk/commit/f927cc916b07e908c3bd18ee7d16d82cb41ca972)
|
||||
- Added license [`39fc381`](https://git.odit.services/lfk/kiosk/commit/39fc381343de6d2be4f8e5aa53c9d986f05a99bb)
|
||||
- Added login error [`8b086c5`](https://git.odit.services/lfk/kiosk/commit/8b086c5aa850f423b19a54499ae636937ff33387)
|
||||
- Updated typing [`d68e88e`](https://git.odit.services/lfk/kiosk/commit/d68e88ec9a890e418070f0698d5da6d7c75cc0c1)
|
||||
- Moved barcode height to main config [`3d110e8`](https://git.odit.services/lfk/kiosk/commit/3d110e8f48b9a3df8dba462e2ee71125e47aa875)
|
||||
- Open footer links in new tab [`c1400c0`](https://git.odit.services/lfk/kiosk/commit/c1400c0120a1b3b0e4358b3c6bb6ac38f4f01e35)
|
||||
- Moved config into call [`e25aaf3`](https://git.odit.services/lfk/kiosk/commit/e25aaf3e5e0c2ed52413b8289c7d5bdd5b8a54f1)
|
||||
- Added sample env [`f6dd25c`](https://git.odit.services/lfk/kiosk/commit/f6dd25c988a67b4d826410fea59473ca8d0b718f)
|
||||
- typo [`22be683`](https://git.odit.services/lfk/kiosk/commit/22be68311baaa3d866106603deb6c7ae3a8ab09b)
|
||||
- updated release hook [`5d7a25e`](https://git.odit.services/lfk/kiosk/commit/5d7a25e54ffe454ce4e61876acaae7b1a34df3eb)
|
||||
- pnpx -> npx [`16deab5`](https://git.odit.services/lfk/kiosk/commit/16deab5308b7245860d42b8f49aba0706595d95f)
|
||||
- release from main [`c0a39bd`](https://git.odit.services/lfk/kiosk/commit/c0a39bdabe9a597823fd28cee059b690bc7e34c3)
|
||||
- fix(registration): typo [`1c5e246`](https://git.odit.services/lfk/kiosk/commit/1c5e2460958919951968c8c20eb69929cfba81d5)
|
||||
- pinned dependency [`910fa38`](https://git.odit.services/lfk/kiosk/commit/910fa3867b32918e3791642526d414268049ed38)
|
||||
- Hide error on successfull signin [`f98a4fc`](https://git.odit.services/lfk/kiosk/commit/f98a4fc2b1a34343353fdc361ef08e92ea046ced)
|
||||
@@ -24,4 +24,9 @@ pnpm build
|
||||
```
|
||||
docker build .
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
## Kiosk Google Chrome
|
||||
```
|
||||
chrome https://run.lauf-fuer-kaya.de/kiosk/ -kiosk
|
||||
```
|
||||
10340
licenses.md
Normal file
10340
licenses.md
Normal file
File diff suppressed because it is too large
Load Diff
37
package.json
37
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@lfk/kiosk",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.0",
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"repository": "https://git.odit.services/lfk/kiosk",
|
||||
@@ -35,30 +35,31 @@
|
||||
"devDependencies": {
|
||||
"@odit/license-exporter": "0.0.12",
|
||||
"@sveltejs/adapter-static": "2.0.2",
|
||||
"@sveltejs/kit": "1.5.0",
|
||||
"@sveltejs/kit": "1.15.7",
|
||||
"@types/bwip-js": "^3.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.45.0",
|
||||
"@typescript-eslint/parser": "5.45.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.0",
|
||||
"@typescript-eslint/parser": "5.59.0",
|
||||
"auto-changelog": "2.4.0",
|
||||
"autoprefixer": "10.4.7",
|
||||
"eslint": "8.28.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"autoprefixer": "10.4.14",
|
||||
"eslint": "8.38.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-svelte3": "4.0.0",
|
||||
"postcss": "8.4.14",
|
||||
"postcss": "8.4.22",
|
||||
"postcss-load-config": "4.0.1",
|
||||
"prettier": "2.8.0",
|
||||
"prettier-plugin-svelte": "2.8.1",
|
||||
"prettier": "2.8.7",
|
||||
"prettier-plugin-svelte": "2.10.0",
|
||||
"release-it": "15.10.1",
|
||||
"svelte": "3.54.0",
|
||||
"svelte-check": "3.0.1",
|
||||
"svelte-preprocess": "4.10.7",
|
||||
"tailwindcss": "3.1.5",
|
||||
"tslib": "2.4.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.0"
|
||||
"vite": "4.2.2"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@fontsource/athiti": "^4.5.10",
|
||||
"@odit/lfk-client-js": "1.0.1",
|
||||
"bwip-js": "3.4.0"
|
||||
},
|
||||
@@ -77,7 +78,7 @@
|
||||
"publish": false
|
||||
},
|
||||
"hooks": {
|
||||
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && pnpm licenses:export && git add CHANGELOG.md 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": {
|
||||
@@ -86,4 +87,4 @@
|
||||
"engines": {
|
||||
"pnpm": "8"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
609
pnpm-lock.yaml
generated
609
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
|
||||
@@ -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';
|
||||
|
||||
type UserState = {
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
isLoggedIn: boolean;
|
||||
refreshInterval: NodeJS.Timer | undefined
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
isLoggedIn: boolean;
|
||||
refreshInterval: NodeJS.Timer | undefined;
|
||||
};
|
||||
|
||||
const userStore = () => {
|
||||
const state: UserState = {
|
||||
access_token: '',
|
||||
refresh_token: '',
|
||||
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('userdata', JSON.stringify(state));
|
||||
localStorage.setItem('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('access_token');
|
||||
if (!access_token) {
|
||||
throw new Error('Unauthorized');
|
||||
}
|
||||
|
||||
const storagedata = localStorage.getItem('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 state: UserState = {
|
||||
access_token: '',
|
||||
refresh_token: '',
|
||||
isLoggedIn: false,
|
||||
refreshInterval: undefined
|
||||
};
|
||||
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 };
|
||||
|
||||
@@ -2,14 +2,22 @@
|
||||
import { OpenAPI } from '@odit/lfk-client-js';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import '../app.postcss';
|
||||
import Footer from '../components/footer.svelte';
|
||||
import '@fontsource/athiti';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
OpenAPI.BASE = env.PUBLIC_BASE_URL || '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>
|
||||
|
||||
<div class="dark:bg-slate-900 flex flex-col h-screen">
|
||||
<main class="flex-grow">
|
||||
<slot />
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
@@ -1,41 +1,45 @@
|
||||
<!-- Hero -->
|
||||
<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 -->
|
||||
<script lang="ts">
|
||||
import { loginFromStorage, userState } from '$lib/userstore';
|
||||
import Register from './Register.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import Login from './Login.svelte';
|
||||
|
||||
<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>
|
||||
onMount(() => {
|
||||
loginFromStorage();
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="mt-8 grid gap-3 w-full sm:inline-flex sm:justify-center">
|
||||
<a
|
||||
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"
|
||||
href="/login"
|
||||
>
|
||||
Kiosk starten
|
||||
<svg class="w-3 h-3" width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||||
<path
|
||||
d="M5.27921 2L10.9257 7.64645C11.1209 7.84171 11.1209 8.15829 10.9257 8.35355L5.27921 14"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<!-- End Buttons -->
|
||||
</div>
|
||||
{#if $userState.isLoggedIn}
|
||||
<Register />
|
||||
{:else}
|
||||
<Login />
|
||||
{/if}
|
||||
<div class="fixed bottom-0 w-full text-center text-xl p-4 dark:text-white select-none">
|
||||
{#if $userState.isLoggedIn}
|
||||
<b class="font-bold">LfK!2023</b> powered by
|
||||
<b class="font-bold">ODIT.Services</b>
|
||||
{:else}
|
||||
<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
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
<!-- End Hero -->
|
||||
|
||||
120
src/routes/Login.svelte
Normal file
120
src/routes/Login.svelte
Normal file
@@ -0,0 +1,120 @@
|
||||
<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}
|
||||
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>
|
||||
</div>
|
||||
231
src/routes/Register.svelte
Normal file
231
src/routes/Register.svelte
Normal file
@@ -0,0 +1,231 @@
|
||||
<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 = '';
|
||||
$: doneButtonEnabled = false;
|
||||
$: showResult = false;
|
||||
|
||||
let response: ResponseRunner;
|
||||
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() {
|
||||
try {
|
||||
response = (await RunnerService.runnerControllerPost({
|
||||
firstname,
|
||||
lastname,
|
||||
group
|
||||
})) as ResponseRunner;
|
||||
showResult = true;
|
||||
setTimeout(() => {
|
||||
doneButtonEnabled = true;
|
||||
setTimeout(() => {
|
||||
focusDoneButton();
|
||||
}, 25);
|
||||
}, 7500);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
showResult = false;
|
||||
localStorage.clear();
|
||||
location.reload();
|
||||
}
|
||||
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,
|
||||
text: `${text}`,
|
||||
scale: 10,
|
||||
includetext: true,
|
||||
textxalign: 'center',
|
||||
backgroundcolor: 'ffffff',
|
||||
height: 10
|
||||
});
|
||||
return canvas.toDataURL('image/png');
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
focusFirstName();
|
||||
});
|
||||
</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="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="mt-5">
|
||||
<!-- Form -->
|
||||
{#if !showResult}
|
||||
<div class="text-center">
|
||||
<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>
|
||||
<form class="mt-4 text-lg" on:submit|preventDefault={register}>
|
||||
<div class="grid gap-y-4">
|
||||
<!-- Form Group -->
|
||||
<div>
|
||||
<label for="firstname" class="block text-lg font-bold mb-2 sr-only">Vorname</label>
|
||||
<div class="relative">
|
||||
<input
|
||||
on:keydown={(e) => {
|
||||
if (e.keyCode === 13) {
|
||||
document.getElementById('lastname')?.focus();
|
||||
}
|
||||
}}
|
||||
type="text"
|
||||
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"
|
||||
required
|
||||
placeholder="Vorname"
|
||||
bind:value={firstname}
|
||||
aria-describedby="firstname-error"
|
||||
/>
|
||||
<!-- <div
|
||||
class:hidden={firstname || firstname.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={firstname || firstname.length != 0}
|
||||
class="text-xs text-red-600 mt-2"
|
||||
id="firstname-error"
|
||||
>
|
||||
Bitte gebe deinen Vornamen ein
|
||||
</p> -->
|
||||
</div>
|
||||
<!-- End Form Group -->
|
||||
|
||||
<!-- Form Group -->
|
||||
<div>
|
||||
<label for="lastname" class="block text-lg font-bold mb-2 sr-only">Nachname</label>
|
||||
<div class="relative">
|
||||
<input
|
||||
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"
|
||||
required
|
||||
placeholder="Nachname"
|
||||
aria-describedby="lastname-error"
|
||||
bind:value={lastname}
|
||||
/>
|
||||
<!-- <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
|
||||
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"
|
||||
>Anmelden</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
<!-- End Form -->
|
||||
{:else}
|
||||
<div class="mb-2 text-center">
|
||||
<h3 class="text-4xl font-semibold dark:text-white">
|
||||
{response.firstname}
|
||||
{response.lastname}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="mb-2 text-center">
|
||||
<img
|
||||
class="w-full md:w-auto mb-2 mx-auto bg-white p-4"
|
||||
alt="runner id"
|
||||
src={textToBase64Barcode(response.id.toString(), false)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mx-auto text-center items-center">
|
||||
<button
|
||||
class:opacity-50={!doneButtonEnabled}
|
||||
disabled={!doneButtonEnabled}
|
||||
id="done"
|
||||
on:click={() => {
|
||||
doneButtonEnabled = 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"
|
||||
>Fertig</button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
BIN
src/routes/background.png
Normal file
BIN
src/routes/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@@ -1,94 +0,0 @@
|
||||
<script lang="ts">
|
||||
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);
|
||||
location.replace('/registration');
|
||||
} 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,25 +0,0 @@
|
||||
<script lang="ts">
|
||||
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();
|
||||
location.replace(`/login`);
|
||||
}
|
||||
});
|
||||
</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,218 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { RunnerService, type ResponseRunner } from '@odit/lfk-client-js';
|
||||
import bwipjs from 'bwip-js';
|
||||
|
||||
$: firstname = '';
|
||||
$: lastname = '';
|
||||
$: accepted = false;
|
||||
$: showResult = false;
|
||||
$: showError = false;
|
||||
|
||||
let response: ResponseRunner;
|
||||
const group = 1; //Default to Bürgerlauf
|
||||
|
||||
async function register() {
|
||||
try {
|
||||
response = (await RunnerService.runnerControllerPost({
|
||||
firstname,
|
||||
lastname,
|
||||
group
|
||||
})) as ResponseRunner;
|
||||
showError = false;
|
||||
showResult = true;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
showError = true;
|
||||
showResult = false;
|
||||
}
|
||||
firstname = '';
|
||||
lastname = '';
|
||||
accepted = false;
|
||||
}
|
||||
|
||||
function textToBase64Barcode(text: string, is_qrcode: boolean) {
|
||||
const canvas = document.createElement('canvas');
|
||||
let bcid = 'code128';
|
||||
if (is_qrcode) {
|
||||
bcid = 'qrcode';
|
||||
}
|
||||
bwipjs.toCanvas(canvas, {
|
||||
bcid,
|
||||
text: `${text}`,
|
||||
scale: 10,
|
||||
includetext: true,
|
||||
textxalign: 'center',
|
||||
backgroundcolor: 'ffffff',
|
||||
height: 10
|
||||
});
|
||||
return canvas.toDataURL('image/png');
|
||||
}
|
||||
</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">
|
||||
<h1 class="block text-2xl 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>
|
||||
|
||||
<div class="mt-5">
|
||||
<!-- Form -->
|
||||
{#if !showResult}
|
||||
<form on:submit|preventDefault={register}>
|
||||
<div class="grid gap-y-4">
|
||||
<!-- Form Group -->
|
||||
<div>
|
||||
<label for="firstname" class="block text-sm mb-2 dark:text-white">Vorname</label>
|
||||
<div class="relative">
|
||||
<input
|
||||
type="text"
|
||||
id="firstname"
|
||||
name="firstname"
|
||||
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
|
||||
bind:value={firstname}
|
||||
aria-describedby="firstname-error"
|
||||
/>
|
||||
<!-- <div
|
||||
class:hidden={firstname || firstname.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={firstname || firstname.length != 0}
|
||||
class="text-xs text-red-600 mt-2"
|
||||
id="firstname-error"
|
||||
>
|
||||
Bitte gebe deinen Vornamen ein
|
||||
</p> -->
|
||||
</div>
|
||||
<!-- End Form Group -->
|
||||
|
||||
<!-- Form Group -->
|
||||
<div>
|
||||
<label for="lastname" class="block text-sm mb-2 dark:text-white">Nachname</label>
|
||||
<div class="relative">
|
||||
<input
|
||||
type="lastname"
|
||||
id="lastname"
|
||||
name="lastname"
|
||||
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="lastname-error"
|
||||
bind:value={lastname}
|
||||
/>
|
||||
<!-- <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 -->
|
||||
|
||||
<!-- Checkbox -->
|
||||
<div
|
||||
class="flex items-center"
|
||||
on:click={() => {
|
||||
accepted = !accepted;
|
||||
}}
|
||||
on:keydown={() => {}}
|
||||
>
|
||||
<div class="flex">
|
||||
<input
|
||||
id="remember-me"
|
||||
name="remember-me"
|
||||
type="checkbox"
|
||||
bind:checked={accepted}
|
||||
class="shrink-0 mt-0.5 border-gray-200 rounded text-blue-600 pointer-events-none focus:ring-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800"
|
||||
/>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<label for="remember-me" class="text-sm dark:text-white"
|
||||
>Ich habe die <a
|
||||
class="text-blue-600 decoration-2 hover:underline font-medium"
|
||||
href="https://lauf-fuer-kaya.de/datenschutz">Datenschutzerklärung</a
|
||||
> gelesen und akzeptiert</label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Checkbox -->
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!firstname || !lastname || !accepted}
|
||||
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 text-sm dark:focus:ring-offset-gray-800"
|
||||
>Anmelden</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
<!-- End Form -->
|
||||
{:else}
|
||||
<div class="mb-2">
|
||||
<h3 class="text-xl font-semibold text-center dark:text-white">Läuferdaten</h3>
|
||||
<p class="text-lg dark:text-white">ID: {response.id}</p>
|
||||
<p class="text-lg dark:text-white">Vorname: {response.firstname}</p>
|
||||
<p class="text-lg dark:text-white">Nachname: {response.lastname}</p>
|
||||
</div>
|
||||
|
||||
<div class="mb-2 text-center">
|
||||
<h3 class="text-xl font-semibold dark:text-white">Läufercode</h3>
|
||||
<img
|
||||
class="w-full md:w-auto mb-2 mx-auto bg-white p-4"
|
||||
alt="Runnerid"
|
||||
src={textToBase64Barcode(response.id.toString(), false)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mx-auto text-center items-center">
|
||||
<button
|
||||
on:click={() => {
|
||||
showResult = false;
|
||||
}}
|
||||
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>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user