Compare commits

...

41 Commits
1.2.3 ... 1.4.2

Author SHA1 Message Date
68c2c681f2 chore(release): 1.4.2
All checks were successful
Build release images / build-container (push) Successful in 48s
2025-05-26 19:01:03 +02:00
480fe3e0e5 fix(profile): Format total distance 2025-05-26 18:58:43 +02:00
59cb42c336 feat(Profile/sponsoring): show note for on-day cash donations 2025-05-21 20:23:35 +02:00
2d761ccd6d refactor(Profile): drop sponsor selfservice create from this branch 2025-05-21 20:19:05 +02:00
128c6abd73 chore(release): 1.4.1
All checks were successful
Build release images / build-container (push) Successful in 49s
2025-04-25 15:41:19 +02:00
094e731947 fix(laptimes): Filter out invalid scans 2025-04-25 15:40:47 +02:00
8d6f290fd5 fix(certificate): Provide selfservice url on certificate 2025-04-25 15:38:31 +02:00
57600fad7f chore(release): 1.4.0
All checks were successful
Build release images / build-container (push) Successful in 45s
2025-03-28 22:36:34 +01:00
421dedcb8d ci: update release commit message 2025-03-28 22:36:21 +01:00
00c5181855 chore(deps): bump 2025-03-28 22:35:53 +01:00
6f5c5b4833 chore(deps): bump 2025-03-28 22:31:43 +01:00
347cfe0304 ci: only tagged for now 2025-03-28 22:30:26 +01:00
6afe3207fa feat(register): org/team as badge ui
All checks were successful
Build Latest image / build-container (push) Successful in 47s
2025-03-28 22:30:06 +01:00
4ccac8a0b8 feat: improved registration ui 2025-03-28 22:21:44 +01:00
3a9cd95830 🚀Bumped version to v1.3.1
All checks were successful
Build release images / build-container (push) Successful in 1m3s
Build Latest image / build-container (push) Successful in 1m14s
2025-03-28 19:00:04 +01:00
65dc27add1 feat: footer cleanup
Some checks failed
Build Latest image / build-container (push) Has been cancelled
2025-03-28 18:59:53 +01:00
c9e3b613e1 🚀Bumped version to v1.3.0
All checks were successful
Build release images / build-container (push) Successful in 51s
Build Latest image / build-container (push) Successful in 1m4s
2025-03-28 18:33:01 +01:00
f0c668c1c3 feat: only show international phone number thing if + is missing
All checks were successful
Build Latest image / build-container (push) Successful in 45s
2025-03-28 18:29:29 +01:00
e418d2a2b7 feat: improved Register UI
All checks were successful
Build Latest image / build-container (push) Successful in 45s
2025-03-28 17:47:12 +01:00
e14a6d6329 feat: improve phone number registration 2025-03-28 17:38:13 +01:00
e1a87eda4a 🚀Bumped version to v1.2.7
All checks were successful
Build Latest image / build-container (push) Successful in 1m3s
Build release images / build-container (push) Successful in 1m6s
2025-03-23 19:55:05 +01:00
0e557ef408 footer: cleanup imprint & privacy url
Some checks failed
Build Latest image / build-container (push) Has been cancelled
2025-03-23 19:54:47 +01:00
0af73525bc footer padding
All checks were successful
Build Latest image / build-container (push) Successful in 52s
2025-03-23 19:53:48 +01:00
422df7c3f8 fix: footer
Some checks failed
Build Latest image / build-container (push) Has been cancelled
2025-03-23 19:53:35 +01:00
bab145d78c chore: clean up .dockerignore by removing Gatsby references
All checks were successful
Build Latest image / build-container (push) Successful in 44s
2025-03-22 23:03:20 +01:00
a862593c53 refactor(ci): Switch to actions 2025-03-22 23:02:14 +01:00
63fc5ec747 🚀Bumped version to v1.2.6 2025-03-18 22:59:20 +01:00
c98a65d918 fix(profile): font sizes 2025-03-18 22:59:01 +01:00
b1ab04fa53 🚀Bumped version to v1.2.5 2025-03-18 21:32:48 +01:00
9af9c897f1 feat: improved icons 2025-03-18 21:32:32 +01:00
51b66eb85b feat: improved tabs 2025-03-18 21:29:13 +01:00
b3197dd3f9 feat: cleanup 2025-03-18 21:15:52 +01:00
50fbfe05f1 refactor: simplify imprint + privacy 2025-03-18 21:12:23 +01:00
0ff6df68d6 feat: cleanup 2025-03-18 21:06:39 +01:00
03532cc365 feat: profile cleanup 2025-03-18 21:05:13 +01:00
d50719c0da feat: profile cleanup 2025-03-18 20:58:42 +01:00
865058c8bb refactor: move to new lfk ts client 2025-03-18 00:05:04 +01:00
d503061604 register: drop middlename 2025-03-18 00:01:05 +01:00
d5eefbb5e2 fix(register): phone number verification 2025-03-18 00:00:51 +01:00
f1d552ce64 🚀Bumped version to v1.2.4 2025-03-17 22:35:58 +01:00
2939911c99 feat: loading screen 2025-03-17 22:35:12 +01:00
21 changed files with 890 additions and 1002 deletions

View File

@@ -85,8 +85,6 @@ out
.nuxt .nuxt
dist dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js # Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support # https://nextjs.org/blog/next-9-1#public-directory-support
# public # public

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/selfservice:${{ github.ref_name }}
platforms: linux/amd64,linux/arm64

View File

@@ -1,33 +0,0 @@
steps:
- name: build latest
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/selfservice
tags:
- latest
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/selfservice:dev
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
when:
branch: main
- name: build dev
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/selfservice
tags:
- dev
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/selfservice:dev
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
when:
branch: dev
when:
event: push

View File

@@ -1,17 +0,0 @@
steps:
- name: build tag
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/selfservice
tags:
- "${CI_COMMIT_TAG}"
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/selfservice:dev
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
when:
event:
- tag

View File

@@ -2,8 +2,93 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [1.4.2](https://git.odit.services/lfk/selfservice/compare/1.4.1...1.4.2)
- refactor(Profile): drop sponsor selfservice create from this branch [`2d761cc`](https://git.odit.services/lfk/selfservice/commit/2d761ccd6da7d9515fc0c2b65dc2ca0cff61e3bd)
- feat(Profile/sponsoring): show note for on-day cash donations [`59cb42c`](https://git.odit.services/lfk/selfservice/commit/59cb42c3364777f7b8aed1e90f48f5da015db118)
- fix(profile): Format total distance [`480fe3e`](https://git.odit.services/lfk/selfservice/commit/480fe3e0e568939507e5cc21c48e98634614d4e6)
#### [1.4.1](https://git.odit.services/lfk/selfservice/compare/1.4.0...1.4.1)
> 25 April 2025
- chore(release): 1.4.1 [`128c6ab`](https://git.odit.services/lfk/selfservice/commit/128c6abd737654087100cfca8e72af9b14dd770c)
- fix(laptimes): Filter out invalid scans [`094e731`](https://git.odit.services/lfk/selfservice/commit/094e7319476bc571949a70b6f4c27539616f3634)
- fix(certificate): Provide selfservice url on certificate [`8d6f290`](https://git.odit.services/lfk/selfservice/commit/8d6f290fd5bad54094ba1228fa6d854ad77a561d)
#### [1.4.0](https://git.odit.services/lfk/selfservice/compare/1.3.1...1.4.0)
> 28 March 2025
- chore(deps): bump [`00c5181`](https://git.odit.services/lfk/selfservice/commit/00c5181855433893681351b53b1204b56990c3b3)
- feat: improved registration ui [`4ccac8a`](https://git.odit.services/lfk/selfservice/commit/4ccac8a0b89396a9faf7066f096f6b9e66aa8894)
- ci: only tagged for now [`347cfe0`](https://git.odit.services/lfk/selfservice/commit/347cfe03046bd2ed46720c60b0a893fc57c6c646)
- feat(register): org/team as badge ui [`6afe320`](https://git.odit.services/lfk/selfservice/commit/6afe3207fa0db631b5f079cf815584f4b8f963b2)
- chore(release): 1.4.0 [`57600fa`](https://git.odit.services/lfk/selfservice/commit/57600fad7f3974a1ea8e8ffcb4bfbbd6ab77809a)
- ci: update release commit message [`421dedc`](https://git.odit.services/lfk/selfservice/commit/421dedcb8d6f03072c94786d1f543e0a85950e82)
- chore(deps): bump [`6f5c5b4`](https://git.odit.services/lfk/selfservice/commit/6f5c5b4833d963169003923e2cf011c41cc92393)
#### [1.3.1](https://git.odit.services/lfk/selfservice/compare/1.3.0...1.3.1)
> 28 March 2025
- feat: footer cleanup [`65dc27a`](https://git.odit.services/lfk/selfservice/commit/65dc27add1760c6ebe11f415c49238f82cdb5b48)
- 🚀Bumped version to v1.3.1 [`3a9cd95`](https://git.odit.services/lfk/selfservice/commit/3a9cd95830cc99685f78728f1b19502b523e5e7c)
#### [1.3.0](https://git.odit.services/lfk/selfservice/compare/1.2.7...1.3.0)
> 28 March 2025
- feat: improve phone number registration [`e14a6d6`](https://git.odit.services/lfk/selfservice/commit/e14a6d6329d547d3086abe59d00f0d054688b6f4)
- feat: improved Register UI [`e418d2a`](https://git.odit.services/lfk/selfservice/commit/e418d2a2b74553f614520ac8c0f0377d141daa8d)
- 🚀Bumped version to v1.3.0 [`c9e3b61`](https://git.odit.services/lfk/selfservice/commit/c9e3b613e1d08f6217ae58b8aa42a47749f0ac94)
- feat: only show international phone number thing if + is missing [`f0c668c`](https://git.odit.services/lfk/selfservice/commit/f0c668c1c3d1a5c27d78617e5ca34ca68603ce14)
#### [1.2.7](https://git.odit.services/lfk/selfservice/compare/1.2.6...1.2.7)
> 23 March 2025
- refactor(ci): Switch to actions [`a862593`](https://git.odit.services/lfk/selfservice/commit/a862593c5315043577699d1a6fd50854dd1bca00)
- 🚀Bumped version to v1.2.7 [`e1a87ed`](https://git.odit.services/lfk/selfservice/commit/e1a87eda4a0c9b9be47bcfe4ddb0e93696d037f4)
- footer: cleanup imprint & privacy url [`0e557ef`](https://git.odit.services/lfk/selfservice/commit/0e557ef4080e997b06adcbbadf3e82f12152281b)
- fix: footer [`422df7c`](https://git.odit.services/lfk/selfservice/commit/422df7c3f832dc29721e783dc4a86ee55e9d8ccc)
- footer padding [`0af7352`](https://git.odit.services/lfk/selfservice/commit/0af73525bc154ba730351d7a4970e9737edaa4db)
- chore: clean up .dockerignore by removing Gatsby references [`bab145d`](https://git.odit.services/lfk/selfservice/commit/bab145d78c16dd7c56136a274d051cf408935e3e)
#### [1.2.6](https://git.odit.services/lfk/selfservice/compare/1.2.5...1.2.6)
> 18 March 2025
- 🚀Bumped version to v1.2.6 [`63fc5ec`](https://git.odit.services/lfk/selfservice/commit/63fc5ec7474f65c743db9c281829fef31b623af6)
- fix(profile): font sizes [`c98a65d`](https://git.odit.services/lfk/selfservice/commit/c98a65d918e5d652ee98044b4d5333c7000e1c87)
#### [1.2.5](https://git.odit.services/lfk/selfservice/compare/1.2.4...1.2.5)
> 18 March 2025
- refactor: move to new lfk ts client [`865058c`](https://git.odit.services/lfk/selfservice/commit/865058c8bb7eec03278bf1f4a7b708429d0b5b20)
- feat: cleanup [`b3197dd`](https://git.odit.services/lfk/selfservice/commit/b3197dd3f95cd7d222f1ea168e9826f7ad7ef903)
- refactor: simplify imprint + privacy [`50fbfe0`](https://git.odit.services/lfk/selfservice/commit/50fbfe05f1ba830ea19f9e86b7a2fdce588f1a31)
- feat: improved tabs [`51b66eb`](https://git.odit.services/lfk/selfservice/commit/51b66eb85b3003996ac2414757ae62ee7ba80ce5)
- fix(register): phone number verification [`d5eefbb`](https://git.odit.services/lfk/selfservice/commit/d5eefbb5e22f4cc7b50e1f0c469779d3b7e310f5)
- feat: improved icons [`9af9c89`](https://git.odit.services/lfk/selfservice/commit/9af9c897f17b8a1be12f47dc271382629fc298ff)
- feat: profile cleanup [`d50719c`](https://git.odit.services/lfk/selfservice/commit/d50719c0dad4e3fbf008fb240edff80c4ea6ab4c)
- 🚀Bumped version to v1.2.5 [`b1ab04f`](https://git.odit.services/lfk/selfservice/commit/b1ab04fa53817178e016d7c2c387db12c0f6a987)
- register: drop middlename [`d503061`](https://git.odit.services/lfk/selfservice/commit/d5030616043fb9fa4eccc7894ee3ada92928d102)
- feat: profile cleanup [`03532cc`](https://git.odit.services/lfk/selfservice/commit/03532cc365e38d7313ff2e8571ae15975d8a53e5)
- feat: cleanup [`0ff6df6`](https://git.odit.services/lfk/selfservice/commit/0ff6df68d61404c7be7a1e9b88a354fb12ce0907)
#### [1.2.4](https://git.odit.services/lfk/selfservice/compare/1.2.3...1.2.4)
> 17 March 2025
- feat: loading screen [`2939911`](https://git.odit.services/lfk/selfservice/commit/2939911c993c3817d841d4cb4660aa940e478cc0)
- 🚀Bumped version to v1.2.4 [`f1d552c`](https://git.odit.services/lfk/selfservice/commit/f1d552ce64557b5da0dea91e114d3ebf2f8f0199)
#### [1.2.3](https://git.odit.services/lfk/selfservice/compare/1.2.2...1.2.3) #### [1.2.3](https://git.odit.services/lfk/selfservice/compare/1.2.2...1.2.3)
> 17 March 2025
- chore(deps): bump [`64bb2d1`](https://git.odit.services/lfk/selfservice/commit/64bb2d157daab257b6e0e7c4e6ed04f4b3772740) - chore(deps): bump [`64bb2d1`](https://git.odit.services/lfk/selfservice/commit/64bb2d157daab257b6e0e7c4e6ed04f4b3772740)
- feat: cleanup profile [`86ec22a`](https://git.odit.services/lfk/selfservice/commit/86ec22aa435d9138ae3cde6387ce7ead14f3c964) - feat: cleanup profile [`86ec22a`](https://git.odit.services/lfk/selfservice/commit/86ec22aa435d9138ae3cde6387ce7ead14f3c964)
- feat: improve profile [`846d10f`](https://git.odit.services/lfk/selfservice/commit/846d10f0b95dad460a068bdaf3ca489d96c0b723) - feat: improve profile [`846d10f`](https://git.odit.services/lfk/selfservice/commit/846d10f0b95dad460a068bdaf3ca489d96c0b723)
@@ -12,6 +97,7 @@ All notable changes to this project will be documented in this file. Dates are d
- i18n [`c94f9e5`](https://git.odit.services/lfk/selfservice/commit/c94f9e550e1cbe4626242423deb6d9ab994eea63) - i18n [`c94f9e5`](https://git.odit.services/lfk/selfservice/commit/c94f9e550e1cbe4626242423deb6d9ab994eea63)
- feat: wip: sponsoring add [`382757a`](https://git.odit.services/lfk/selfservice/commit/382757aa66cd79a6a8081ff4b21f6efe46a3ccfd) - feat: wip: sponsoring add [`382757a`](https://git.odit.services/lfk/selfservice/commit/382757aa66cd79a6a8081ff4b21f6efe46a3ccfd)
- feat: cleanup profile [`0366f95`](https://git.odit.services/lfk/selfservice/commit/0366f95951d1415b300b174699d93e4bf17f3e18) - feat: cleanup profile [`0366f95`](https://git.odit.services/lfk/selfservice/commit/0366f95951d1415b300b174699d93e4bf17f3e18)
- 🚀Bumped version to v1.2.3 [`e7b9c6e`](https://git.odit.services/lfk/selfservice/commit/e7b9c6e2036addd18e109e3ab040e69dee2f658d)
- shareSponsorLink function [`ccea9d6`](https://git.odit.services/lfk/selfservice/commit/ccea9d61975bfa54928d557735cd3ce79d671435) - shareSponsorLink function [`ccea9d6`](https://git.odit.services/lfk/selfservice/commit/ccea9d61975bfa54928d557735cd3ce79d671435)
- no selfservice sponsor add for now [`3641d2a`](https://git.odit.services/lfk/selfservice/commit/3641d2a78341b91a26a9d4cc31c40707096768b1) - no selfservice sponsor add for now [`3641d2a`](https://git.odit.services/lfk/selfservice/commit/3641d2a78341b91a26a9d4cc31c40707096768b1)
- feat: disable darkmode for now, also is better for visibility on day of run... [`0848209`](https://git.odit.services/lfk/selfservice/commit/0848209d49e4445881bf9536d87fe18ea2a6c924) - feat: disable darkmode for now, also is better for visibility on day of run... [`0848209`](https://git.odit.services/lfk/selfservice/commit/0848209d49e4445881bf9536d87fe18ea2a6c924)

View File

@@ -1,10 +1,9 @@
FROM node:23.4.0-alpine3.20 AS build FROM node:23.10.0-alpine3.21 AS build
# FROM registry.odit.services/hub/library/node:23.3.0-alpine3.20 AS build
# ARG NPM_REGISTRY_URL=https://registry.npmjs.org # ARG NPM_REGISTRY_URL=https://registry.npmjs.org
WORKDIR /app WORKDIR /app
COPY . . COPY . .
# RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@9 # RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@9
RUN npm i -g pnpm@9 RUN npm i -g pnpm@10.7
RUN pnpm i --frozen-lockfile RUN pnpm i --frozen-lockfile
RUN pnpm build RUN pnpm build

View File

@@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-selfservice", "name": "@odit/lfk-selfservice",
"version": "1.2.3", "version": "1.4.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -9,13 +9,14 @@
}, },
"dependencies": { "dependencies": {
"@fontsource/athiti": "5.2.5", "@fontsource/athiti": "5.2.5",
"@tailwindcss/vite": "4.0.14", "@odit/lfk-client": "^0.0.1",
"bwip-js": "4.5.2", "@tailwindcss/vite": "4.0.17",
"bwip-js": "4.5.3",
"marked": "15.0.7", "marked": "15.0.7",
"redaxios": "0.5.1", "redaxios": "0.5.1",
"tailwindcss": "4.0.14", "tailwindcss": "4.0.17",
"toastify-js": "1.12.0", "toastify-js": "1.12.0",
"validator": "13.12.0", "validator": "13.15.0",
"vue": "3.5.13", "vue": "3.5.13",
"vue-i18n": "10.0.5", "vue-i18n": "10.0.5",
"vue-router": "4.5.0", "vue-router": "4.5.0",
@@ -25,19 +26,19 @@
"@vitejs/plugin-vue": "5.2.3", "@vitejs/plugin-vue": "5.2.3",
"autoprefixer": "10.4.21", "autoprefixer": "10.4.21",
"release-it": "18.1.2", "release-it": "18.1.2",
"vite": "6.2.2", "vite": "6.2.3",
"vite-plugin-vue-devtools": "7.7.2" "vite-plugin-vue-devtools": "7.7.2"
}, },
"release-it": { "release-it": {
"git": { "git": {
"commit": true, "commit": true,
"requireCleanWorkingDir": false, "requireCleanWorkingDir": false,
"commitMessage": "🚀Bumped version to v${version}", "commitMessage": "chore(release): ${version}",
"requireBranch": "dev", "requireBranch": "dev",
"push": true, "push": true,
"tag": true, "tag": true,
"tagName": null, "tagName": "${version}",
"tagAnnotation": "v${version}" "tagAnnotation": "${version}"
}, },
"npm": { "npm": {
"publish": false "publish": false

401
pnpm-lock.yaml generated
View File

@@ -11,12 +11,15 @@ importers:
'@fontsource/athiti': '@fontsource/athiti':
specifier: 5.2.5 specifier: 5.2.5
version: 5.2.5 version: 5.2.5
'@odit/lfk-client':
specifier: ^0.0.1
version: 0.0.1
'@tailwindcss/vite': '@tailwindcss/vite':
specifier: 4.0.14 specifier: 4.0.17
version: 4.0.14(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)) version: 4.0.17(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))
bwip-js: bwip-js:
specifier: 4.5.2 specifier: 4.5.3
version: 4.5.2 version: 4.5.3
marked: marked:
specifier: 15.0.7 specifier: 15.0.7
version: 15.0.7 version: 15.0.7
@@ -24,14 +27,14 @@ importers:
specifier: 0.5.1 specifier: 0.5.1
version: 0.5.1 version: 0.5.1
tailwindcss: tailwindcss:
specifier: 4.0.14 specifier: 4.0.17
version: 4.0.14 version: 4.0.17
toastify-js: toastify-js:
specifier: 1.12.0 specifier: 1.12.0
version: 1.12.0 version: 1.12.0
validator: validator:
specifier: 13.12.0 specifier: 13.15.0
version: 13.12.0 version: 13.15.0
vue: vue:
specifier: 3.5.13 specifier: 3.5.13
version: 3.5.13 version: 3.5.13
@@ -47,7 +50,7 @@ importers:
devDependencies: devDependencies:
'@vitejs/plugin-vue': '@vitejs/plugin-vue':
specifier: 5.2.3 specifier: 5.2.3
version: 5.2.3(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13) version: 5.2.3(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13)
autoprefixer: autoprefixer:
specifier: 10.4.21 specifier: 10.4.21
version: 10.4.21(postcss@8.5.3) version: 10.4.21(postcss@8.5.3)
@@ -55,11 +58,11 @@ importers:
specifier: 18.1.2 specifier: 18.1.2
version: 18.1.2(@types/node@18.11.18) version: 18.1.2(@types/node@18.11.18)
vite: vite:
specifier: 6.2.2 specifier: 6.2.3
version: 6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1) version: 6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)
vite-plugin-vue-devtools: vite-plugin-vue-devtools:
specifier: 7.7.2 specifier: 7.7.2
version: 7.7.2(rollup@4.36.0)(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13) version: 7.7.2(rollup@4.37.0)(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13)
packages: packages:
@@ -368,6 +371,9 @@ packages:
'@fontsource/athiti@5.2.5': '@fontsource/athiti@5.2.5':
resolution: {integrity: sha512-vHoAKBBw+wI4y3bGOkiogOkgcoLH7+SWtNNo/nBQ1XfhvfRPX/91xGtclEdwqUlbOJTCkNzEecdKChJQ5MsDFg==} resolution: {integrity: sha512-vHoAKBBw+wI4y3bGOkiogOkgcoLH7+SWtNNo/nBQ1XfhvfRPX/91xGtclEdwqUlbOJTCkNzEecdKChJQ5MsDFg==}
'@hey-api/client-fetch@0.8.3':
resolution: {integrity: sha512-EBVa8wwUMyBSeQ32PtCz6u5bFQZIMAufvwCT1ZtpjqT3caJQEza4NokbGU50q1ZVrMsM5Ot6GuDNJOF3TMo26Q==}
'@iarna/toml@2.2.5': '@iarna/toml@2.2.5':
resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==}
@@ -586,6 +592,9 @@ packages:
'@octokit/types@13.8.0': '@octokit/types@13.8.0':
resolution: {integrity: sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==} resolution: {integrity: sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==}
'@odit/lfk-client@0.0.1':
resolution: {integrity: sha512-DD3ofUIl/Jv6pznJWYevKAbMWMY9GSecyJeNT06izKfko6jsMyOlZBwGnXrydeh8+Dh274/j/GoFA9rWqPxpbQ==}
'@pnpm/config.env-replace@1.1.0': '@pnpm/config.env-replace@1.1.0':
resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
engines: {node: '>=12.22.0'} engines: {node: '>=12.22.0'}
@@ -610,98 +619,103 @@ packages:
rollup: rollup:
optional: true optional: true
'@rollup/rollup-android-arm-eabi@4.36.0': '@rollup/rollup-android-arm-eabi@4.37.0':
resolution: {integrity: sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w==} resolution: {integrity: sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@rollup/rollup-android-arm64@4.36.0': '@rollup/rollup-android-arm64@4.37.0':
resolution: {integrity: sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg==} resolution: {integrity: sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@rollup/rollup-darwin-arm64@4.36.0': '@rollup/rollup-darwin-arm64@4.37.0':
resolution: {integrity: sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw==} resolution: {integrity: sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@rollup/rollup-darwin-x64@4.36.0': '@rollup/rollup-darwin-x64@4.37.0':
resolution: {integrity: sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA==} resolution: {integrity: sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@rollup/rollup-freebsd-arm64@4.36.0': '@rollup/rollup-freebsd-arm64@4.37.0':
resolution: {integrity: sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg==} resolution: {integrity: sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==}
cpu: [arm64] cpu: [arm64]
os: [freebsd] os: [freebsd]
'@rollup/rollup-freebsd-x64@4.36.0': '@rollup/rollup-freebsd-x64@4.37.0':
resolution: {integrity: sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ==} resolution: {integrity: sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@rollup/rollup-linux-arm-gnueabihf@4.36.0': '@rollup/rollup-linux-arm-gnueabihf@4.37.0':
resolution: {integrity: sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg==} resolution: {integrity: sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@rollup/rollup-linux-arm-musleabihf@4.36.0': '@rollup/rollup-linux-arm-musleabihf@4.37.0':
resolution: {integrity: sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg==} resolution: {integrity: sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@rollup/rollup-linux-arm64-gnu@4.36.0': '@rollup/rollup-linux-arm64-gnu@4.37.0':
resolution: {integrity: sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A==} resolution: {integrity: sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@rollup/rollup-linux-arm64-musl@4.36.0': '@rollup/rollup-linux-arm64-musl@4.37.0':
resolution: {integrity: sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw==} resolution: {integrity: sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@rollup/rollup-linux-loongarch64-gnu@4.36.0': '@rollup/rollup-linux-loongarch64-gnu@4.37.0':
resolution: {integrity: sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg==} resolution: {integrity: sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==}
cpu: [loong64] cpu: [loong64]
os: [linux] os: [linux]
'@rollup/rollup-linux-powerpc64le-gnu@4.36.0': '@rollup/rollup-linux-powerpc64le-gnu@4.37.0':
resolution: {integrity: sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg==} resolution: {integrity: sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
'@rollup/rollup-linux-riscv64-gnu@4.36.0': '@rollup/rollup-linux-riscv64-gnu@4.37.0':
resolution: {integrity: sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA==} resolution: {integrity: sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
'@rollup/rollup-linux-s390x-gnu@4.36.0': '@rollup/rollup-linux-riscv64-musl@4.37.0':
resolution: {integrity: sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag==} resolution: {integrity: sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==}
cpu: [riscv64]
os: [linux]
'@rollup/rollup-linux-s390x-gnu@4.37.0':
resolution: {integrity: sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
'@rollup/rollup-linux-x64-gnu@4.36.0': '@rollup/rollup-linux-x64-gnu@4.37.0':
resolution: {integrity: sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ==} resolution: {integrity: sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@rollup/rollup-linux-x64-musl@4.36.0': '@rollup/rollup-linux-x64-musl@4.37.0':
resolution: {integrity: sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ==} resolution: {integrity: sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@rollup/rollup-win32-arm64-msvc@4.36.0': '@rollup/rollup-win32-arm64-msvc@4.37.0':
resolution: {integrity: sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A==} resolution: {integrity: sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@rollup/rollup-win32-ia32-msvc@4.36.0': '@rollup/rollup-win32-ia32-msvc@4.37.0':
resolution: {integrity: sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ==} resolution: {integrity: sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@rollup/rollup-win32-x64-msvc@4.36.0': '@rollup/rollup-win32-x64-msvc@4.37.0':
resolution: {integrity: sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw==} resolution: {integrity: sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
@@ -716,81 +730,81 @@ packages:
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
'@tailwindcss/node@4.0.14': '@tailwindcss/node@4.0.17':
resolution: {integrity: sha512-Ux9NbFkKWYE4rfUFz6M5JFLs/GEYP6ysxT8uSyPn6aTbh2K3xDE1zz++eVK4Vwx799fzMF8CID9sdHn4j/Ab8w==} resolution: {integrity: sha512-LIdNwcqyY7578VpofXyqjH6f+3fP4nrz7FBLki5HpzqjYfXdF2m/eW18ZfoKePtDGg90Bvvfpov9d2gy5XVCbg==}
'@tailwindcss/oxide-android-arm64@4.0.14': '@tailwindcss/oxide-android-arm64@4.0.17':
resolution: {integrity: sha512-VBFKC2rFyfJ5J8lRwjy6ub3rgpY186kAcYgiUr8ArR8BAZzMruyeKJ6mlsD22Zp5ZLcPW/FXMasJiJBx0WsdQg==} resolution: {integrity: sha512-3RfO0ZK64WAhop+EbHeyxGThyDr/fYhxPzDbEQjD2+v7ZhKTb2svTWy+KK+J1PHATus2/CQGAGp7pHY/8M8ugg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@tailwindcss/oxide-darwin-arm64@4.0.14': '@tailwindcss/oxide-darwin-arm64@4.0.17':
resolution: {integrity: sha512-U3XOwLrefGr2YQZ9DXasDSNWGPZBCh8F62+AExBEDMLDfvLLgI/HDzY8Oq8p/JtqkAY38sWPOaNnRwEGKU5Zmg==} resolution: {integrity: sha512-e1uayxFQCCDuzTk9s8q7MC5jFN42IY7nzcr5n0Mw/AcUHwD6JaBkXnATkD924ZsHyPDvddnusIEvkgLd2CiREg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@tailwindcss/oxide-darwin-x64@4.0.14': '@tailwindcss/oxide-darwin-x64@4.0.17':
resolution: {integrity: sha512-V5AjFuc3ndWGnOi1d379UsODb0TzAS2DYIP/lwEbfvafUaD2aNZIcbwJtYu2DQqO2+s/XBvDVA+w4yUyaewRwg==} resolution: {integrity: sha512-d6z7HSdOKfXQ0HPlVx1jduUf/YtBuCCtEDIEFeBCzgRRtDsUuRtofPqxIVaSCUTOk5+OfRLonje6n9dF6AH8wQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@tailwindcss/oxide-freebsd-x64@4.0.14': '@tailwindcss/oxide-freebsd-x64@4.0.17':
resolution: {integrity: sha512-tXvtxbaZfcPfqBwW3f53lTcyH6EDT+1eT7yabwcfcxTs+8yTPqxsDUhrqe9MrnEzpNkd+R/QAjJapfd4tjWdLg==} resolution: {integrity: sha512-EjrVa6lx3wzXz3l5MsdOGtYIsRjgs5Mru6lDv4RuiXpguWeOb3UzGJ7vw7PEzcFadKNvNslEQqoAABeMezprxQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.14': '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.17':
resolution: {integrity: sha512-cSeLNWWqIWeSTmBntQvyY2/2gcLX8rkPFfDDTQVF8qbRcRMVPLxBvFVJyfSAYRNch6ZyVH2GI6dtgALOBDpdNA==} resolution: {integrity: sha512-65zXfCOdi8wuaY0Ye6qMR5LAXokHYtrGvo9t/NmxvSZtCCitXV/gzJ/WP5ksXPhff1SV5rov0S+ZIZU+/4eyCQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-arm64-gnu@4.0.14': '@tailwindcss/oxide-linux-arm64-gnu@4.0.17':
resolution: {integrity: sha512-bwDWLBalXFMDItcSXzFk6y7QKvj6oFlaY9vM+agTlwFL1n1OhDHYLZkSjaYsh6KCeG0VB0r7H8PUJVOM1LRZyg==} resolution: {integrity: sha512-+aaq6hJ8ioTdbJV5IA1WjWgLmun4T7eYLTvJIToiXLHy5JzUERRbIZjAcjgK9qXMwnvuu7rqpxzej+hGoEcG5g==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-arm64-musl@4.0.14': '@tailwindcss/oxide-linux-arm64-musl@4.0.17':
resolution: {integrity: sha512-gVkJdnR/L6iIcGYXx64HGJRmlme2FGr/aZH0W6u4A3RgPMAb+6ELRLi+UBiH83RXBm9vwCfkIC/q8T51h8vUJQ==} resolution: {integrity: sha512-/FhWgZCdUGAeYHYnZKekiOC0aXFiBIoNCA0bwzkICiMYS5Rtx2KxFfMUXQVnl4uZRblG5ypt5vpPhVaXgGk80w==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-x64-gnu@4.0.14': '@tailwindcss/oxide-linux-x64-gnu@4.0.17':
resolution: {integrity: sha512-EE+EQ+c6tTpzsg+LGO1uuusjXxYx0Q00JE5ubcIGfsogSKth8n8i2BcS2wYTQe4jXGs+BQs35l78BIPzgwLddw==} resolution: {integrity: sha512-gELJzOHK6GDoIpm/539Golvk+QWZjxQcbkKq9eB2kzNkOvrP0xc5UPgO9bIMNt1M48mO8ZeNenCMGt6tfkvVBg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-x64-musl@4.0.14': '@tailwindcss/oxide-linux-x64-musl@4.0.17':
resolution: {integrity: sha512-KCCOzo+L6XPT0oUp2Jwh233ETRQ/F6cwUnMnR0FvMUCbkDAzHbcyOgpfuAtRa5HD0WbTbH4pVD+S0pn1EhNfbw==} resolution: {integrity: sha512-68NwxcJrZn94IOW4TysMIbYv5AlM6So1luTlbYUDIGnKma1yTFGBRNEJ+SacJ3PZE2rgcTBNRHX1TB4EQ/XEHw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@tailwindcss/oxide-win32-arm64-msvc@4.0.14': '@tailwindcss/oxide-win32-arm64-msvc@4.0.17':
resolution: {integrity: sha512-AHObFiFL9lNYcm3tZSPqa/cHGpM5wOrNmM2uOMoKppp+0Hom5uuyRh0QkOp7jftsHZdrZUpmoz0Mp6vhh2XtUg==} resolution: {integrity: sha512-AkBO8efP2/7wkEXkNlXzRD4f/7WerqKHlc6PWb5v0jGbbm22DFBLbIM19IJQ3b+tNewQZa+WnPOaGm0SmwMNjw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@tailwindcss/oxide-win32-x64-msvc@4.0.14': '@tailwindcss/oxide-win32-x64-msvc@4.0.17':
resolution: {integrity: sha512-rNXXMDJfCJLw/ZaFTOLOHoGULxyXfh2iXTGiChFiYTSgKBKQHIGEpV0yn5N25WGzJJ+VBnRjHzlmDqRV+d//oQ==} resolution: {integrity: sha512-7/DTEvXcoWlqX0dAlcN0zlmcEu9xSermuo7VNGX9tJ3nYMdo735SHvbrHDln1+LYfF6NhJ3hjbpbjkMOAGmkDg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@tailwindcss/oxide@4.0.14': '@tailwindcss/oxide@4.0.17':
resolution: {integrity: sha512-M8VCNyO/NBi5vJ2cRcI9u8w7Si+i76a7o1vveoGtbbjpEYJZYiyc7f2VGps/DqawO56l3tImIbq2OT/533jcrA==} resolution: {integrity: sha512-B4OaUIRD2uVrULpAD1Yksx2+wNarQr2rQh65nXqaqbLY1jCd8fO+3KLh/+TH4Hzh2NTHQvgxVbPdUDOtLk7vAw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
'@tailwindcss/vite@4.0.14': '@tailwindcss/vite@4.0.17':
resolution: {integrity: sha512-y69ztPTRFy+13EPS/7dEFVl7q2Goh1pQueVO8IfGeyqSpcx/joNJXFk0lLhMgUbF0VFJotwRSb9ZY7Xoq3r26Q==} resolution: {integrity: sha512-HJbBYDlDVg5cvYZzECb6xwc1IDCEM3uJi3hEZp3BjZGCNGJcTsnCpan+z+VMW0zo6gR0U6O6ElqU1OoZ74Dhww==}
peerDependencies: peerDependencies:
vite: ^5.2.0 || ^6 vite: ^5.2.0 || ^6
@@ -952,8 +966,8 @@ packages:
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
bwip-js@4.5.2: bwip-js@4.5.3:
resolution: {integrity: sha512-RObBQLA1Ncy0cvpLoUGiX7PWupfRiRTemQXf+9wobBKjgHb6rXwO2f2YCAVJjVlCRoTRRiL18++ZF2946Ys4QA==} resolution: {integrity: sha512-RzODtC4xyl7mCyyfModA+EFyE4ZBlaMRAGX9LDGqjeskmIrzUqTyF++WxHr8ccX/9la4Ii5K9LCn60yv1lYwDA==}
hasBin: true hasBin: true
callsites@3.1.0: callsites@3.1.0:
@@ -1590,13 +1604,8 @@ packages:
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
engines: {node: ^18.17.0 || >=20.5.0} engines: {node: ^18.17.0 || >=20.5.0}
nanoid@3.3.10: nanoid@3.3.11:
resolution: {integrity: sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==} resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
nanoid@3.3.8:
resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true hasBin: true
@@ -1805,8 +1814,8 @@ packages:
rfdc@1.4.1: rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
rollup@4.36.0: rollup@4.37.0:
resolution: {integrity: sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q==} resolution: {integrity: sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true hasBin: true
@@ -1931,8 +1940,8 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
tailwindcss@4.0.14: tailwindcss@4.0.17:
resolution: {integrity: sha512-92YT2dpt671tFiHH/e1ok9D987N9fHD5VWoly1CdPD/Cd1HMglvZwP3nx2yTj2lbXDAHt8QssZkxTLCCTNL+xw==} resolution: {integrity: sha512-OErSiGzRa6rLiOvaipsDZvLMSpsBZ4ysB4f0VKGXUrjw2jfkJRd6kjRKV2+ZmTCNvwtvgdDam5D7w6WXsdLJZw==}
tapable@2.2.1: tapable@2.2.1:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
@@ -2001,8 +2010,8 @@ packages:
resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==} resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
validator@13.12.0: validator@13.15.0:
resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} resolution: {integrity: sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
vite-hot-client@0.2.4: vite-hot-client@0.2.4:
@@ -2031,8 +2040,8 @@ packages:
peerDependencies: peerDependencies:
vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0
vite@6.2.2: vite@6.2.3:
resolution: {integrity: sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==} resolution: {integrity: sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@@ -2433,6 +2442,8 @@ snapshots:
'@fontsource/athiti@5.2.5': {} '@fontsource/athiti@5.2.5': {}
'@hey-api/client-fetch@0.8.3': {}
'@iarna/toml@2.2.5': {} '@iarna/toml@2.2.5': {}
'@inquirer/checkbox@4.1.4(@types/node@18.11.18)': '@inquirer/checkbox@4.1.4(@types/node@18.11.18)':
@@ -2654,6 +2665,10 @@ snapshots:
dependencies: dependencies:
'@octokit/openapi-types': 23.0.1 '@octokit/openapi-types': 23.0.1
'@odit/lfk-client@0.0.1':
dependencies:
'@hey-api/client-fetch': 0.8.3
'@pnpm/config.env-replace@1.1.0': {} '@pnpm/config.env-replace@1.1.0': {}
'@pnpm/network.ca-file@1.0.2': '@pnpm/network.ca-file@1.0.2':
@@ -2668,69 +2683,72 @@ snapshots:
'@polka/url@1.0.0-next.28': {} '@polka/url@1.0.0-next.28': {}
'@rollup/pluginutils@5.1.4(rollup@4.36.0)': '@rollup/pluginutils@5.1.4(rollup@4.37.0)':
dependencies: dependencies:
'@types/estree': 1.0.6 '@types/estree': 1.0.6
estree-walker: 2.0.2 estree-walker: 2.0.2
picomatch: 4.0.2 picomatch: 4.0.2
optionalDependencies: optionalDependencies:
rollup: 4.36.0 rollup: 4.37.0
'@rollup/rollup-android-arm-eabi@4.36.0': '@rollup/rollup-android-arm-eabi@4.37.0':
optional: true optional: true
'@rollup/rollup-android-arm64@4.36.0': '@rollup/rollup-android-arm64@4.37.0':
optional: true optional: true
'@rollup/rollup-darwin-arm64@4.36.0': '@rollup/rollup-darwin-arm64@4.37.0':
optional: true optional: true
'@rollup/rollup-darwin-x64@4.36.0': '@rollup/rollup-darwin-x64@4.37.0':
optional: true optional: true
'@rollup/rollup-freebsd-arm64@4.36.0': '@rollup/rollup-freebsd-arm64@4.37.0':
optional: true optional: true
'@rollup/rollup-freebsd-x64@4.36.0': '@rollup/rollup-freebsd-x64@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.36.0': '@rollup/rollup-linux-arm-gnueabihf@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-arm-musleabihf@4.36.0': '@rollup/rollup-linux-arm-musleabihf@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-arm64-gnu@4.36.0': '@rollup/rollup-linux-arm64-gnu@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-arm64-musl@4.36.0': '@rollup/rollup-linux-arm64-musl@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-loongarch64-gnu@4.36.0': '@rollup/rollup-linux-loongarch64-gnu@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-powerpc64le-gnu@4.36.0': '@rollup/rollup-linux-powerpc64le-gnu@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-riscv64-gnu@4.36.0': '@rollup/rollup-linux-riscv64-gnu@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-s390x-gnu@4.36.0': '@rollup/rollup-linux-riscv64-musl@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-x64-gnu@4.36.0': '@rollup/rollup-linux-s390x-gnu@4.37.0':
optional: true optional: true
'@rollup/rollup-linux-x64-musl@4.36.0': '@rollup/rollup-linux-x64-gnu@4.37.0':
optional: true optional: true
'@rollup/rollup-win32-arm64-msvc@4.36.0': '@rollup/rollup-linux-x64-musl@4.37.0':
optional: true optional: true
'@rollup/rollup-win32-ia32-msvc@4.36.0': '@rollup/rollup-win32-arm64-msvc@4.37.0':
optional: true optional: true
'@rollup/rollup-win32-x64-msvc@4.36.0': '@rollup/rollup-win32-ia32-msvc@4.37.0':
optional: true
'@rollup/rollup-win32-x64-msvc@4.37.0':
optional: true optional: true
'@sec-ant/readable-stream@0.4.1': {} '@sec-ant/readable-stream@0.4.1': {}
@@ -2739,66 +2757,66 @@ snapshots:
'@sindresorhus/merge-streams@4.0.0': {} '@sindresorhus/merge-streams@4.0.0': {}
'@tailwindcss/node@4.0.14': '@tailwindcss/node@4.0.17':
dependencies: dependencies:
enhanced-resolve: 5.18.1 enhanced-resolve: 5.18.1
jiti: 2.4.2 jiti: 2.4.2
tailwindcss: 4.0.14 tailwindcss: 4.0.17
'@tailwindcss/oxide-android-arm64@4.0.14': '@tailwindcss/oxide-android-arm64@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-darwin-arm64@4.0.14': '@tailwindcss/oxide-darwin-arm64@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-darwin-x64@4.0.14': '@tailwindcss/oxide-darwin-x64@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-freebsd-x64@4.0.14': '@tailwindcss/oxide-freebsd-x64@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.14': '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.0.14': '@tailwindcss/oxide-linux-arm64-gnu@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.0.14': '@tailwindcss/oxide-linux-arm64-musl@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.0.14': '@tailwindcss/oxide-linux-x64-gnu@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-x64-musl@4.0.14': '@tailwindcss/oxide-linux-x64-musl@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.0.14': '@tailwindcss/oxide-win32-arm64-msvc@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.0.14': '@tailwindcss/oxide-win32-x64-msvc@4.0.17':
optional: true optional: true
'@tailwindcss/oxide@4.0.14': '@tailwindcss/oxide@4.0.17':
optionalDependencies: optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.0.14 '@tailwindcss/oxide-android-arm64': 4.0.17
'@tailwindcss/oxide-darwin-arm64': 4.0.14 '@tailwindcss/oxide-darwin-arm64': 4.0.17
'@tailwindcss/oxide-darwin-x64': 4.0.14 '@tailwindcss/oxide-darwin-x64': 4.0.17
'@tailwindcss/oxide-freebsd-x64': 4.0.14 '@tailwindcss/oxide-freebsd-x64': 4.0.17
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.14 '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.17
'@tailwindcss/oxide-linux-arm64-gnu': 4.0.14 '@tailwindcss/oxide-linux-arm64-gnu': 4.0.17
'@tailwindcss/oxide-linux-arm64-musl': 4.0.14 '@tailwindcss/oxide-linux-arm64-musl': 4.0.17
'@tailwindcss/oxide-linux-x64-gnu': 4.0.14 '@tailwindcss/oxide-linux-x64-gnu': 4.0.17
'@tailwindcss/oxide-linux-x64-musl': 4.0.14 '@tailwindcss/oxide-linux-x64-musl': 4.0.17
'@tailwindcss/oxide-win32-arm64-msvc': 4.0.14 '@tailwindcss/oxide-win32-arm64-msvc': 4.0.17
'@tailwindcss/oxide-win32-x64-msvc': 4.0.14 '@tailwindcss/oxide-win32-x64-msvc': 4.0.17
'@tailwindcss/vite@4.0.14(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))': '@tailwindcss/vite@4.0.17(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))':
dependencies: dependencies:
'@tailwindcss/node': 4.0.14 '@tailwindcss/node': 4.0.17
'@tailwindcss/oxide': 4.0.14 '@tailwindcss/oxide': 4.0.17
lightningcss: 1.29.2 lightningcss: 1.29.2
tailwindcss: 4.0.14 tailwindcss: 4.0.17
vite: 6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1) vite: 6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)
'@tootallnate/quickjs-emscripten@0.23.0': {} '@tootallnate/quickjs-emscripten@0.23.0': {}
@@ -2808,9 +2826,9 @@ snapshots:
'@types/parse-path@7.0.3': {} '@types/parse-path@7.0.3': {}
'@vitejs/plugin-vue@5.2.3(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13)': '@vitejs/plugin-vue@5.2.3(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13)':
dependencies: dependencies:
vite: 6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1) vite: 6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)
vue: 3.5.13 vue: 3.5.13
'@vue/babel-helper-vue-transform-on@1.4.0': {} '@vue/babel-helper-vue-transform-on@1.4.0': {}
@@ -2874,14 +2892,14 @@ snapshots:
'@vue/devtools-api@6.6.4': {} '@vue/devtools-api@6.6.4': {}
'@vue/devtools-core@7.7.2(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13)': '@vue/devtools-core@7.7.2(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13)':
dependencies: dependencies:
'@vue/devtools-kit': 7.7.2 '@vue/devtools-kit': 7.7.2
'@vue/devtools-shared': 7.7.2 '@vue/devtools-shared': 7.7.2
mitt: 3.0.1 mitt: 3.0.1
nanoid: 5.1.4 nanoid: 5.1.4
pathe: 2.0.3 pathe: 2.0.3
vite-hot-client: 0.2.4(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)) vite-hot-client: 0.2.4(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))
vue: 3.5.13 vue: 3.5.13
transitivePeerDependencies: transitivePeerDependencies:
- vite - vite
@@ -3008,7 +3026,7 @@ snapshots:
dependencies: dependencies:
run-applescript: 7.0.0 run-applescript: 7.0.0
bwip-js@4.5.2: {} bwip-js@4.5.3: {}
callsites@3.1.0: {} callsites@3.1.0: {}
@@ -3575,9 +3593,7 @@ snapshots:
mute-stream@2.0.0: {} mute-stream@2.0.0: {}
nanoid@3.3.10: {} nanoid@3.3.11: {}
nanoid@3.3.8: {}
nanoid@5.1.4: {} nanoid@5.1.4: {}
@@ -3709,13 +3725,13 @@ snapshots:
postcss@8.4.49: postcss@8.4.49:
dependencies: dependencies:
nanoid: 3.3.8 nanoid: 3.3.11
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.1 source-map-js: 1.2.1
postcss@8.5.3: postcss@8.5.3:
dependencies: dependencies:
nanoid: 3.3.10 nanoid: 3.3.11
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.1 source-map-js: 1.2.1
@@ -3820,29 +3836,30 @@ snapshots:
rfdc@1.4.1: {} rfdc@1.4.1: {}
rollup@4.36.0: rollup@4.37.0:
dependencies: dependencies:
'@types/estree': 1.0.6 '@types/estree': 1.0.6
optionalDependencies: optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.36.0 '@rollup/rollup-android-arm-eabi': 4.37.0
'@rollup/rollup-android-arm64': 4.36.0 '@rollup/rollup-android-arm64': 4.37.0
'@rollup/rollup-darwin-arm64': 4.36.0 '@rollup/rollup-darwin-arm64': 4.37.0
'@rollup/rollup-darwin-x64': 4.36.0 '@rollup/rollup-darwin-x64': 4.37.0
'@rollup/rollup-freebsd-arm64': 4.36.0 '@rollup/rollup-freebsd-arm64': 4.37.0
'@rollup/rollup-freebsd-x64': 4.36.0 '@rollup/rollup-freebsd-x64': 4.37.0
'@rollup/rollup-linux-arm-gnueabihf': 4.36.0 '@rollup/rollup-linux-arm-gnueabihf': 4.37.0
'@rollup/rollup-linux-arm-musleabihf': 4.36.0 '@rollup/rollup-linux-arm-musleabihf': 4.37.0
'@rollup/rollup-linux-arm64-gnu': 4.36.0 '@rollup/rollup-linux-arm64-gnu': 4.37.0
'@rollup/rollup-linux-arm64-musl': 4.36.0 '@rollup/rollup-linux-arm64-musl': 4.37.0
'@rollup/rollup-linux-loongarch64-gnu': 4.36.0 '@rollup/rollup-linux-loongarch64-gnu': 4.37.0
'@rollup/rollup-linux-powerpc64le-gnu': 4.36.0 '@rollup/rollup-linux-powerpc64le-gnu': 4.37.0
'@rollup/rollup-linux-riscv64-gnu': 4.36.0 '@rollup/rollup-linux-riscv64-gnu': 4.37.0
'@rollup/rollup-linux-s390x-gnu': 4.36.0 '@rollup/rollup-linux-riscv64-musl': 4.37.0
'@rollup/rollup-linux-x64-gnu': 4.36.0 '@rollup/rollup-linux-s390x-gnu': 4.37.0
'@rollup/rollup-linux-x64-musl': 4.36.0 '@rollup/rollup-linux-x64-gnu': 4.37.0
'@rollup/rollup-win32-arm64-msvc': 4.36.0 '@rollup/rollup-linux-x64-musl': 4.37.0
'@rollup/rollup-win32-ia32-msvc': 4.36.0 '@rollup/rollup-win32-arm64-msvc': 4.37.0
'@rollup/rollup-win32-x64-msvc': 4.36.0 '@rollup/rollup-win32-ia32-msvc': 4.37.0
'@rollup/rollup-win32-x64-msvc': 4.37.0
fsevents: 2.3.3 fsevents: 2.3.3
run-applescript@7.0.0: {} run-applescript@7.0.0: {}
@@ -3945,7 +3962,7 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {} supports-preserve-symlinks-flag@1.0.0: {}
tailwindcss@4.0.14: {} tailwindcss@4.0.17: {}
tapable@2.2.1: {} tapable@2.2.1: {}
@@ -4000,16 +4017,16 @@ snapshots:
url-join@5.0.0: {} url-join@5.0.0: {}
validator@13.12.0: {} validator@13.15.0: {}
vite-hot-client@0.2.4(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)): vite-hot-client@0.2.4(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)):
dependencies: dependencies:
vite: 6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1) vite: 6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)
vite-plugin-inspect@0.8.9(rollup@4.36.0)(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)): vite-plugin-inspect@0.8.9(rollup@4.37.0)(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)):
dependencies: dependencies:
'@antfu/utils': 0.7.10 '@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.1.4(rollup@4.36.0) '@rollup/pluginutils': 5.1.4(rollup@4.37.0)
debug: 4.4.0 debug: 4.4.0
error-stack-parser-es: 0.1.5 error-stack-parser-es: 0.1.5
fs-extra: 11.3.0 fs-extra: 11.3.0
@@ -4017,28 +4034,28 @@ snapshots:
perfect-debounce: 1.0.0 perfect-debounce: 1.0.0
picocolors: 1.1.1 picocolors: 1.1.1
sirv: 3.0.1 sirv: 3.0.1
vite: 6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1) vite: 6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
- supports-color - supports-color
vite-plugin-vue-devtools@7.7.2(rollup@4.36.0)(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13): vite-plugin-vue-devtools@7.7.2(rollup@4.37.0)(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13):
dependencies: dependencies:
'@vue/devtools-core': 7.7.2(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13) '@vue/devtools-core': 7.7.2(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))(vue@3.5.13)
'@vue/devtools-kit': 7.7.2 '@vue/devtools-kit': 7.7.2
'@vue/devtools-shared': 7.7.2 '@vue/devtools-shared': 7.7.2
execa: 9.5.2 execa: 9.5.2
sirv: 3.0.1 sirv: 3.0.1
vite: 6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1) vite: 6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)
vite-plugin-inspect: 0.8.9(rollup@4.36.0)(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)) vite-plugin-inspect: 0.8.9(rollup@4.37.0)(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))
vite-plugin-vue-inspector: 5.3.1(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)) vite-plugin-vue-inspector: 5.3.1(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1))
transitivePeerDependencies: transitivePeerDependencies:
- '@nuxt/kit' - '@nuxt/kit'
- rollup - rollup
- supports-color - supports-color
- vue - vue
vite-plugin-vue-inspector@5.3.1(vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)): vite-plugin-vue-inspector@5.3.1(vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)):
dependencies: dependencies:
'@babel/core': 7.26.10 '@babel/core': 7.26.10
'@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.10) '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.10)
@@ -4049,15 +4066,15 @@ snapshots:
'@vue/compiler-dom': 3.5.13 '@vue/compiler-dom': 3.5.13
kolorist: 1.8.0 kolorist: 1.8.0
magic-string: 0.30.17 magic-string: 0.30.17
vite: 6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1) vite: 6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
vite@6.2.2(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1): vite@6.2.3(@types/node@18.11.18)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.6.1):
dependencies: dependencies:
esbuild: 0.25.1 esbuild: 0.25.1
postcss: 8.5.3 postcss: 8.5.3
rollup: 4.36.0 rollup: 4.37.0
optionalDependencies: optionalDependencies:
'@types/node': 18.11.18 '@types/node': 18.11.18
fsevents: 2.3.3 fsevents: 2.3.3

View File

@@ -1,14 +1,14 @@
const config = { const config = {
// required // required
documentserver_key: '', documentserver_key: "",
// required, with trailing slash // required, with trailing slash
baseurl: '', baseurl: "",
// optional, full url, will fallback to https://lauf-fuer-kaya.de/impressum
url_imprint: "",
// optional, full url, will fallback to https://lauf-fuer-kaya.de/datenschutz
url_privacy: "",
// full url (including fqdn) // full url (including fqdn)
baseurl_documentserver: 'http://localhost:3000', baseurl_documentserver: "http://localhost:3000",
// optional, will fallback to code128 // optional, will fallback to code128
code_format: 'ean13', code_format: "ean13",
// optional, will fallback to /imprint
url_imprint: '',
// optional, will fallback to /privacy
url_privacy: '',
}; };

View File

@@ -1 +0,0 @@
TODO:

View File

@@ -1 +0,0 @@
TODO:

View File

@@ -1,26 +1,21 @@
<template> <template>
<footer> <footer>
<div class="container px-5 py-8 mx-auto flex items-center sm:flex-row flex-col"> <p class="text-sm sm:py-2 sm:mt-0 mt-4 text-center md:text-left">
<p class="text-sm sm:ml-4 sm:pl-4 sm:py-2 sm:mt-0 mt-4 text-center md:text-left"> Lauf für Kaya! Selfservice<br>Copyright © 2025<br>proudly powered by
Lauf für Kaya! Selfservice<br>Copyright © 2025<br>proudly powered by <a class="underline" target="_blank" rel="noopener,noreferrer"
<a class="underline" target="_blank" rel="noopener,noreferrer" href="https://odit.services?ref=lfk">ODIT.Services</a><br>
href="https://odit.services?ref=lfk">ODIT.Services</a> <a target="_blank" rel="noopener,noreferrer" :href="[[imprint_url]]" class="underline">{{
</p> $t('imprint') }}</a> <a target="_blank" rel="noopener,noreferrer" :href="[[privacy_url]]" class="underline">{{
<span class="inline-flex sm:ml-auto sm:mt-0 mt-4 justify-center sm:justify-start">
<a target="_blank" rel="noopener,noreferrer" :href="[[imprint_url]]" class="ml-3 underline">{{
$t('imprint') }}</a>
<a target="_blank" rel="noopener,noreferrer" :href="[[privacy_url]]" class="ml-3 underline">{{
$t('privacy_policy') }}</a> $t('privacy_policy') }}</a>
</span> </p>
</div>
</footer> </footer>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
imprint_url: config.url_imprint || "/imprint" imprint_url: config.url_imprint || "https://lauf-fuer-kaya.de/impressum"
, privacy_url: config.url_privacy || "/privacy" , privacy_url: config.url_privacy || "https://lauf-fuer-kaya.de/datenschutz"
} }
}, },
} }

View File

@@ -13,17 +13,21 @@
"current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)", "current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)",
"delete_my_data": "Meine Daten löschen", "delete_my_data": "Meine Daten löschen",
"distance": "Distanz", "distance": "Distanz",
"donation_on_event_day": "Am Lauftag kann Bargeld in unsere Spendenbox gespendet werden 💶",
"download_certificate": "Urkunde herunterladen", "download_certificate": "Urkunde herunterladen",
"download_registrationcode": "Registrierungscode herunterladen", "download_registrationcode": "Registrierungscode herunterladen",
"e_mail_adress": "E-Mail Adresse", "e_mail_adress": "E-Mail Adresse",
"e_mail_des_sponsors": "E-Mail des Sponsors", "e_mail_des_sponsors": "E-Mail des Sponsors",
"error-loading-privacy-policy": "Fehler beim Laden der Datenschutzerklärung",
"error_loading_imprint": "Fehler beim Laden des Impressums",
"error_requesting_the_login_link": "Fehler beim Anfordern des Login-Links...", "error_requesting_the_login_link": "Fehler beim Anfordern des Login-Links...",
"first_lap": "👏 erste Runde", "first_lap": "👏 erste Runde",
"geben_sie_ihre_handynummer_an": "Ihre Handynummer",
"hinweis": "Hinweis:",
"i_accept": "Ich habe die ", "i_accept": "Ich habe die ",
"i_accept_end": "gelesen und akzeptiert.", "i_accept_end": "gelesen und akzeptiert.",
"if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance": "Wenn Sie der Systemadministrator sind, finden Sie Konfigurationsanweisungen in der offiziellen Produktdokumentation / README.", "if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance": "Wenn Sie der Systemadministrator sind, finden Sie Konfigurationsanweisungen in der offiziellen Produktdokumentation / README.",
"ihr_nachname": "Ihr Nachname",
"ihr_vorname": "Ihr Vorname",
"ihre_e_mail_adresse": "Ihre E-Mail Adresse",
"imprint": "Impressum", "imprint": "Impressum",
"invalid_input_phone_number_should_be_international_format": "ungültige Eingabe... Die Telefonnummer sollte ein internationales Format haben", "invalid_input_phone_number_should_be_international_format": "ungültige Eingabe... Die Telefonnummer sollte ein internationales Format haben",
"lap_time": "Rundenzeit", "lap_time": "Rundenzeit",
@@ -40,7 +44,7 @@
"not_registered_yet": "Noch nicht registriert?", "not_registered_yet": "Noch nicht registriert?",
"organization": "Organisation", "organization": "Organisation",
"ort": "Ort", "ort": "Ort",
"phone_number": "Telefonnummer (international formatiert)", "phone_number": "Handynummer (optional)",
"please_provide_a_valid_zipcode": "Bitte geben Sie eine gültige Postleitzahl an...", "please_provide_a_valid_zipcode": "Bitte geben Sie eine gültige Postleitzahl an...",
"please_provide_valid_mail": "Bitte geben Sie eine gültige E-Mail Adresse an", "please_provide_valid_mail": "Bitte geben Sie eine gültige E-Mail Adresse an",
"plz": "PLZ", "plz": "PLZ",
@@ -51,10 +55,11 @@
"profile": "Profil", "profile": "Profil",
"provide_address": "Adresse angeben?", "provide_address": "Adresse angeben?",
"register": { "register": {
"register_now": "Jetzt für den Lauf für Kaya! 2025 registrieren." "register_now": "Jetzt für den LfK! 2025 registrieren."
}, },
"register_now": "Jetzt registrieren!", "register_now": "Jetzt registrieren!",
"register_now_small": "Jetzt registrieren", "register_now_small": "Jetzt registrieren",
"registration_local_phone_nr": "Handynummern ohne Vorwahl werden als deutsche Telefonnummer gewertet",
"registration_running": "Registrierung läuft...", "registration_running": "Registrierung läuft...",
"registrationcode": "Registrierungscode", "registrationcode": "Registrierungscode",
"registrieren": "Registrieren", "registrieren": "Registrieren",
@@ -62,6 +67,7 @@
"registrierungscode_generiert": "Registrierungscode generiert!", "registrierungscode_generiert": "Registrierungscode generiert!",
"registrierungscode_wird_generiert": "Registrierungscode wird generiert...", "registrierungscode_wird_generiert": "Registrierungscode wird generiert...",
"resend_the_registration_mail": "Login-Link anfordern", "resend_the_registration_mail": "Login-Link anfordern",
"spenden_info": "Spenden-Info",
"sponsor_add_agree": "Mit dem Absenden bestätige ich, dass der Sponsor mit der Übermittlung seiner Daten einverstanden ist und ich dessen Berechtigung habe", "sponsor_add_agree": "Mit dem Absenden bestätige ich, dass der Sponsor mit der Übermittlung seiner Daten einverstanden ist und ich dessen Berechtigung habe",
"sponsoring": "Sponsoring", "sponsoring": "Sponsoring",
"sponsoring_pro_kilometer_in_eur": "Sponsoring pro Kilometer (in €)", "sponsoring_pro_kilometer_in_eur": "Sponsoring pro Kilometer (in €)",

View File

@@ -13,17 +13,21 @@
"current_total_amount_in_eur": "Current total amount (in €)", "current_total_amount_in_eur": "Current total amount (in €)",
"delete_my_data": "Delete my data", "delete_my_data": "Delete my data",
"distance": "Distance", "distance": "Distance",
"donation_on_event_day": "On race day, cash can be donated to our donation box 💶",
"download_certificate": "Download certificate", "download_certificate": "Download certificate",
"download_registrationcode": "Download registrationcode", "download_registrationcode": "Download registrationcode",
"e_mail_adress": "mail address", "e_mail_adress": "mail address",
"e_mail_des_sponsors": "E-Mail of the Sponsor", "e_mail_des_sponsors": "E-Mail of the Sponsor",
"error-loading-privacy-policy": "Error loading Privacy Policy",
"error_loading_imprint": "Error loading Imprint",
"error_requesting_the_login_link": "Error requesting the login link...", "error_requesting_the_login_link": "Error requesting the login link...",
"first_lap": "👏 first lap", "first_lap": "👏 first lap",
"geben_sie_ihre_handynummer_an": "Your mobile number",
"hinweis": "Note:",
"i_accept": "I have read and accepted the ", "i_accept": "I have read and accepted the ",
"i_accept_end": "", "i_accept_end": "",
"if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance": "If you are the system administrator, please refer to the official product documentation/ README for configuration guidance.", "if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance": "If you are the system administrator, please refer to the official product documentation/ README for configuration guidance.",
"ihr_nachname": "Your last name",
"ihr_vorname": "Your first name",
"ihre_e_mail_adresse": "Your email address",
"imprint": "Imprint", "imprint": "Imprint",
"invalid_input_phone_number_should_be_international_format": "invalid input... phone number should be international format", "invalid_input_phone_number_should_be_international_format": "invalid input... phone number should be international format",
"lap_time": "Lap time", "lap_time": "Lap time",
@@ -40,7 +44,7 @@
"not_registered_yet": "Not registered yet?", "not_registered_yet": "Not registered yet?",
"organization": "Organization", "organization": "Organization",
"ort": "City", "ort": "City",
"phone_number": "Phone Number (international format)", "phone_number": "mobile number (optional)",
"please_provide_a_valid_zipcode": "Please provide a valid zipcode...", "please_provide_a_valid_zipcode": "Please provide a valid zipcode...",
"please_provide_valid_mail": "Please provide a valid mail address.", "please_provide_valid_mail": "Please provide a valid mail address.",
"plz": "zipcode", "plz": "zipcode",
@@ -51,10 +55,11 @@
"profile": "Profile", "profile": "Profile",
"provide_address": "Provide a postal address?", "provide_address": "Provide a postal address?",
"register": { "register": {
"register_now": "Register now for Lauf für Kaya! 2025." "register_now": "Register now for LfK! 2025."
}, },
"register_now": "Register now!", "register_now": "Register now!",
"register_now_small": "Register now", "register_now_small": "Register now",
"registration_local_phone_nr": "Mobile numbers without an area code are considered German phone numbers",
"registration_running": "registration is running...", "registration_running": "registration is running...",
"registrationcode": "Registration Code", "registrationcode": "Registration Code",
"registrieren": "Register Now", "registrieren": "Register Now",
@@ -62,6 +67,7 @@
"registrierungscode_generiert": "created registration code!", "registrierungscode_generiert": "created registration code!",
"registrierungscode_wird_generiert": "creating registration code...", "registrierungscode_wird_generiert": "creating registration code...",
"resend_the_registration_mail": "Send me a login link", "resend_the_registration_mail": "Send me a login link",
"spenden_info": "info for donations",
"sponsor_add_agree": "By submitting, I confirm that the sponsor agrees to the transmission of his data and that I have his authorization", "sponsor_add_agree": "By submitting, I confirm that the sponsor agrees to the transmission of his data and that I have his authorization",
"sponsoring": "Sponsoring", "sponsoring": "Sponsoring",
"sponsoring_pro_kilometer_in_eur": "Sponsoring per Kilometer (in €)", "sponsoring_pro_kilometer_in_eur": "Sponsoring per Kilometer (in €)",

View File

@@ -1,19 +1,13 @@
import Home from "./views/Home.vue"; import Home from "./views/Home.vue";
import Imprint from "./views/Imprint.vue";
import Privacy from "./views/Privacy.vue";
import Register from "./views/Register.vue"; import Register from "./views/Register.vue";
import Profile from "./views/Profile.vue"; import Profile from "./views/Profile.vue";
import ProfileNone from "./views/ProfileNone.vue"; import ProfileNone from "./views/ProfileNone.vue";
console.log(config); // console.log(config);
/** @type {import('vue-router').RouterOptions['routes']} */ /** @type {import('vue-router').RouterOptions['routes']} */
export const routes = [ export const routes = [
{ path: "/", component: Home }, { path: "/", component: Home },
{ path: "/imprint", component: Imprint },
{ path: "/imprint/", component: Imprint },
{ path: "/privacy", component: Privacy },
{ path: "/privacy/", component: Privacy },
{ path: "/register", component: Register }, { path: "/register", component: Register },
{ path: "/register/", component: Register }, { path: "/register/", component: Register },
{ path: "/register/:token", component: Register, props: true }, { path: "/register/:token", component: Register, props: true },

View File

@@ -1,13 +1,12 @@
<template> <template>
<div class="bg-cover bg-fixed m-0 h-screen text-white" <div class="bg-cover bg-fixed m-0 h-screen text-white"
v-bind:style='{ backgroundImage: "url(" + background_base64 + ")", }'> v-bind:style='{ backgroundImage: "url(" + background_base64 + ")", }'>
<section class="container px-4 py-24 mx-auto"> <section class="px-4 py-24 mx-auto">
<div class="w-full mx-auto text-center"> <div class="w-full mx-auto text-center">
<img src="/favicon-lfk.png" class="h-32 mx-auto" /> <img src="/favicon-lfk.png" class="h-32 mx-auto" />
<h1 <h1 class="mb-6 text-4xl font-extrabold leading-none tracking-normal md:text-6xl md:tracking-tight">
class="mb-6 text-4xl font-extrabold leading-none tracking-normal md:text-6xl md:tracking-tight font-[Athiti]">
Lauf Für Kaya!<br>2025</h1> Lauf Für Kaya!<br>2025</h1>
<h2 class="mb-6 text-xl font-bold leading-none tracking-normal md:text-3xl md:tracking-tight font-[Athiti]"> <h2 class="mb-6 text-xl font-bold leading-none tracking-normal md:text-3xl md:tracking-tight">
Selfservice Portal</h2> Selfservice Portal</h2>
<p class="px-0 mb-6 text-md lg:px-24 font-medium">{{ $t('main_page_text') }}</p> <p class="px-0 mb-6 text-md lg:px-24 font-medium">{{ $t('main_page_text') }}</p>
<a class="w-full block mx-auto md:w-3/4 px-6 py-3 border border-transparent text-base font-semibold rounded-md text-gray-900 bg-white shadow-sm hover:text-gray-600 focus:outline-none focus:text-gray-600 xl:text-lg xl:py-4" <a class="w-full block mx-auto md:w-3/4 px-6 py-3 border border-transparent text-base font-semibold rounded-md text-gray-900 bg-white shadow-sm hover:text-gray-600 focus:outline-none focus:text-gray-600 xl:text-lg xl:py-4"
@@ -18,7 +17,9 @@
</div> </div>
</section> </section>
</div> </div>
<Footer /> <div class="p-8">
<Footer />
</div>
</template> </template>
<script setup> <script setup>

View File

@@ -1,40 +0,0 @@
<template>
<section class="container px-4 py-24 mx-auto">
<div class="simplecontent">
<div class="mb-24 text-left md:text-center">
<h1 class="mb-4 text-4xl font-bold leading-tight text-gray-900 dark:text-gray-50 md:text-5xl">{{ $t('imprint')
}}
</h1>
</div>
<div class="mx-auto prose" v-html="content"></div>
</div>
</section>
<Footer></Footer>
</template>
<style src="../simple.css"></style>
<script>
import { marked } from "marked";
import Footer from "@/components/Footer.vue";
export default {
components: { Footer },
data() {
return {
content: "",
}
},
async beforeMount() {
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
let md = "";
try {
md = await fetch(`/imprint_${browserlocale}.md`);
} catch (error) {
try {
md = await fetch(`/imprint_en.md`);
} catch (error) {
md = t('error_loading_imprint');
}
}
this.content = marked(await md.text());
},
}
</script>

View File

@@ -1,39 +0,0 @@
<template>
<section class="container px-4 py-24 mx-auto">
<div class="simplecontent">
<div class="mb-24 text-left md:text-center">
<h1 class="mb-4 text-4xl font-bold leading-tight text-gray-900 dark:text-gray-50 md:text-5xl">{{
$t('privacy_policy') }}</h1>
</div>
<div class="mx-auto prose" v-html="content"></div>
</div>
</section>
<Footer></Footer>
</template>
<style src="../simple.css"></style>
<script>
import { marked } from "marked";
import Footer from "@/components/Footer.vue";
export default {
components: { Footer },
data() {
return {
content: ""
}
},
async beforeMount() {
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
let md = "";
try {
md = await fetch(`/privacy_${browserlocale}.md`);
} catch (error) {
try {
md = await fetch(`/privacy_en.md`);
} catch (error) {
md = t('error-loading-privacy-policy');
}
}
this.content = marked(await md.text());
},
}
</script>

View File

@@ -1,512 +1,383 @@
<template> <template>
<div class="min-h-screen w-full p-4"> <div class="w-full p-4 lg:px-48 xl:w-2/3 xl:mx-auto">
<div class=""> <div class="md:pr-10 md:mb-0 mb-6 pr-0 w-full text-center text-black dark:text-gray-200">
<div class=" <img src="/favicon-lfk.png" class="h-20 mx-auto" />
md:pr-10 md:mb-0 <div v-if="loadstate === 'loaded'">
mb-6 <h1 class="text-3xl font-bold whitespace-nowrap" v-text="(state.firstname || '') +
pr-0
w-full
text-center
text-black
dark:text-gray-200
">
<img src="/favicon-lfk.png" class="h-20 mx-auto" />
<h1 class="text-3xl font-bold whitespace-nowrap font-[Athiti]" v-text="(state.firstname || '') +
' ' + ' ' +
(state.middlename || '') + (state.middlename || '') +
' ' + ' ' +
(state.lastname || '') (state.lastname || '')
"></h1> "></h1>
<p class="text-md whitespace-nowrap">Team: {{ state.group }}</p> <p v-if="state.group === 'Citizen'" class="text-md whitespace-nowrap">Bürgerlauf<br>Start: 14:00 Uhr</p>
<p v-else class="text-md whitespace-nowrap">Team: {{ state.group }}</p>
</div> </div>
<div class="flex flex-wrap"> <h1 v-else class="text-3xl font-bold whitespace-nowrap">Daten werden geladen...</h1>
<div class="w-full"> </div>
<div class="flex flex-wrap flex-col w-full tabs"> <div v-if="loadstate === 'loaded'" class="flex flex-wrap">
<div class="flex lg:flex-wrap flex-row lg:space-x-2 justify-center"> <div class="w-full">
<div class="flex-none"> <div class="">
<button @click="() => { <div class="grid grid-cols-3 text-center gap-1">
state.activetab = 'profile'; <button @click="() => {
} state.activetab = 'profile';
" :class="{ }
'tab-active border-b-2 font-medium border-blue-500': " :class="{
state.activetab === 'profile', 'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white':
}" class="tab tab-underline cursor-pointer py-4 px-6 block" type="button"> state.activetab === 'profile',
{{ $t("profile") }} 'bg-neutral-200':
</button> state.activetab !== 'profile',
</div> }" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button">
<div class="flex-none"> {{ $t("profile") }}
<button @click="() => { </button>
state.activetab = 'laptimes'; <button @click="() => {
} state.activetab = 'laptimes';
" :class="{ }
'tab-active border-b-2 font-medium border-blue-500': " :class="{
state.activetab === 'laptimes', 'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white':
}" class="tab tab-underline cursor-pointer py-4 px-6 block" type="button"> state.activetab === 'laptimes',
{{ $t("lap_times") }} 'bg-neutral-200':
</button> state.activetab !== 'laptimes',
</div> }" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button">
<div class="flex-none"> {{ $t("lap_times") }}
<button @click="() => { </button>
state.activetab = 'sponsorings'; <button @click="() => {
} state.activetab = 'sponsorings';
" :class="{ }
'tab-active border-b-2 font-medium border-blue-500': " :class="{
state.activetab === 'sponsorings', 'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white':
}" class="tab tab-underline cursor-pointer py-4 px-6 block" type="button"> state.activetab === 'sponsorings',
{{ $t("sponsoring") }} 'bg-neutral-200':
</button> state.activetab !== 'sponsorings',
</div> }" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button">
</div> {{ $t("sponsoring") }}
<div v-if="state.activetab === 'profile'" class="tab-content block container"> </button>
<div class="lg:w-2/3 w-full mx-auto"> </div>
<div class="flex flex-col container"> <div v-if="state.activetab === 'profile'" class="tab-content block">
<div class="flex flex-wrap w-full"> <div class="w-full mx-auto">
<div class="w-full"> <div class="flex flex-col">
<div v-if="state.delete_active === false"> <div class="flex flex-wrap w-full">
<button type="button" class=" <div class="w-full">
mt-2 <div v-if="state.delete_active === false">
focus:border-black focus:ring-2 focus:ring-black <button type="button"
text-white text-base md:text-sm class="mt-2 focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-blue-600 hover:bg-blue-700 hover:shadow-lg w-full md:w-auto cursor-pointer mb-1 md:mr-1"
py-3.5 @click="get_certificate">
px-5 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
md:py-2.5 stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
md:px-5 class="inline-block">
rounded-md <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
bg-blue-500 <polyline points="7 10 12 15 17 10" />
hover:bg-blue-600 hover:shadow-lg <line x1="12" x2="12" y1="15" y2="3" />
w-full </svg>
md:w-auto {{ $t("download_certificate") }}
cursor-pointer </button>
mb-1
md:mr-1
" @click="get_certificate">
<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 h-4 align-sub">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" />
</svg>
{{ $t("download_certificate") }}
</button>
</div> </div>
<div> <div>
<div class="text-lg">{{ $t("registrationcode") }}</div> <div class="text-lg">{{ $t("registrationcode") }}</div>
<img class="w-full md:w-auto mb-2 bg-white p-2" alt="Registrierungscode" :src="state.barcode" /> <img class="w-full md:w-auto mb-2 bg-white p-2" alt="Registrierungscode" :src="state.barcode" />
<button type="button" class=" <button type="button"
focus:border-black focus:ring-2 focus:ring-black class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-blue-600 hover:bg-blue-700 hover:shadow-lg w-full md:w-auto cursor-pointer mb-1 md:mr-1"
text-white text-base md:text-sm @click="get_registration">
py-3.5 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
px-5 stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
md:py-2.5 class="inline-block">
md:px-5 <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
rounded-md <polyline points="7 10 12 15 17 10" />
bg-blue-500 <line x1="12" x2="12" y1="15" y2="3" />
hover:bg-blue-600 hover:shadow-lg </svg>
w-full {{ $t("download_registrationcode") }}
md:w-auto </button>
cursor-pointer </div>
mb-1 <div class="mb-2">
md:mr-1 <div class="text-lg">{{ $t("e_mail_adress") }}</div>
" @click="get_registration"> <p v-text="state.email || '---'" />
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" </div>
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" <div class="mb-2">
class="inline h-4 align-sub"> <div class="text-lg">{{ $t("phone_number") }}</div>
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> <p v-text="state.phone || '---'" />
<polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" />
</svg>
{{ $t("download_registrationcode") }}
</button>
</div>
<div class="mb-2">
<div class="text-lg">{{ $t("e_mail_adress") }}</div>
<p v-text="state.email || '---'" />
</div>
<div class="mb-2">
<div class="text-lg">{{ $t("phone_number") }}</div>
<p v-text="state.phone || '---'" />
</div>
</div> </div>
</div> </div>
</div> </div>
<div v-if="state.delete_active === true"> </div>
<button type="button" class=" <div v-if="state.delete_active === true">
focus:border-black focus:ring-2 focus:ring-black <button type="button"
text-white text-base md:text-sm class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md mb-1 md:mb-auto w-full md:w-auto cursor-pointer bg-blue-600 hover:bg-blue-700 hover:shadow-lg"
py-3.5 @click="() => {
px-5 state.delete_active = false;
md:py-2.5 }
md:px-5 ">
rounded-md
mb-1
md:mb-auto
w-full
md:w-auto
cursor-pointer
bg-blue-500
hover:bg-blue-600 hover:shadow-lg
" @click="() => {
state.delete_active = false;
}
">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline h-4 align-sub">
<path fill="none" d="M0 0h24v24H0z" />
<path fill="currentColor" d="M12 11l5-5 1 1-5 5 5 5-1 1-5-5-5 5-1-1 5-5-5-5 1-1z" />
</svg>
{{ $t("cancel_keep_my_data") }}
</button>
<button type="button" class="
focus:border-black focus:ring-2 focus:ring-black
text-white text-base md:text-sm
py-3.5
px-5
md:py-2.5
md:px-5
rounded-md
w-full
md:w-auto
cursor-pointer
bg-red-600
hover:bg-red-700 hover:shadow-lg
md:ml-1
" @click="delete_me">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline h-4 align-sub">
<path d="M0 0h24v24H0z" />
<path fill="currentColor"
d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z" />
</svg>
{{ $t("confirm_delete_all_of_my_data") }}
</button>
</div>
<button v-else type="button" class="
focus:border-black focus:ring-2 focus:ring-black
text-white text-base md:text-sm
py-3.5
px-5
md:py-2.5
md:px-5
rounded-md
bg-red-600
hover:bg-red-700 hover:shadow-lg
w-full
md:w-auto
cursor-pointer
" @click="() => {
state.delete_active = true;
}
">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline h-4 align-sub"> class="inline-block">
<path d="M0 0h24v24H0z" /> <circle cx="12" cy="12" r="10" />
<path fill="currentColor" <path d="m4.9 4.9 14.2 14.2" />
d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z" />
</svg> </svg>
{{ $t("delete_my_data") }} {{ $t("cancel_keep_my_data") }}
</button>
<button type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md w-full md:w-auto cursor-pointer bg-red-600 hover:bg-red-700 hover:shadow-lg md:ml-1"
@click="delete_me">
<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-block">
<path d="M3 6h18" />
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
<line x1="10" x2="10" y1="11" y2="17" />
<line x1="14" x2="14" y1="11" y2="17" />
</svg>
{{ $t("confirm_delete_all_of_my_data") }}
</button> </button>
</div> </div>
<button v-else type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-red-600 hover:bg-red-700 hover:shadow-lg w-full md:w-auto cursor-pointer"
@click="() => {
state.delete_active = true;
}
">
<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-block">
<path d="M3 6h18" />
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
<line x1="10" x2="10" y1="11" y2="17" />
<line x1="14" x2="14" y1="11" y2="17" />
</svg>
{{ $t("delete_my_data") }}
</button>
</div> </div>
</div> </div>
<div v-if="state.activetab === 'laptimes'" class="tab-content block"> </div>
<div class="py-4 w-full"> <div v-if="state.activetab === 'laptimes'" class="tab-content block">
<section class="dark:bg-gray-900 body-font"> <div class="py-4 w-full">
<div class="container mx-auto"> <section class="dark:bg-gray-900 body-font">
<div class="lg:w-2/3 w-full mx-auto"> <div class="mx-auto">
<div v-if="state.scans.length > 0"> <div class="w-full mx-auto">
<p class="mb-2"> <div v-if="state.scans.length > 0">
{{ $t('total_distance') }}: {{ getReadableDistanceForUI() }} <p class="mb-2">
</p> {{ $t('total_distance') }}: {{ getTotalReadableDistance() }}
</p>
<table class="table-auto w-full text-left whitespace-no-wrap"> <table class="table-auto w-full text-left whitespace-no-wrap">
<thead class=" <thead class="
text-black text-black
bg-gray-300 bg-gray-300
dark:text-white dark:text-white
text-sm text-sm
dark:bg-gray-800 dark:bg-gray-800
"> ">
<tr> <tr>
<th class=" <th class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
"> ">
{{ $t("distance") }} {{ $t("distance") }}
</th> </th>
<th class=" <th class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
"> ">
{{ $t("lap_time") }} {{ $t("lap_time") }}
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="text-gray-900 dark:text-gray-50"> <tbody class="text-gray-900 dark:text-gray-50">
<tr v-for="s in state.scans" :key="s.id"> <tr v-for="s in state.scans" :key="s.id">
<td class="px-4 py-3"> <td class="px-4 py-3">
<span v-text="s.distance_readable"></span> <span v-text="s.distance_readable"></span>
</td> </td>
<td class="px-4 py-3" v-text="s.lapTime_readable"></td> <td class="px-4 py-3" v-text="s.lapTime_readable"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div v-else class=" <div v-else class="
text-center text-center
font-bold font-medium
text-black text-black
dark:text-white dark:text-white
text-2xl text-xl
"> ">
<img src="../assets/empty_laps.svg" class="mx-auto h-64" <img src="../assets/empty_laps.svg" class="mx-auto h-56"
:alt="[[$t('no_laps_scans_were_recorded_yet')]]" /> :alt="[[$t('no_laps_scans_were_recorded_yet')]]" />
{{ $t("no_laps_scans_were_recorded_yet") }} {{ $t("no_laps_scans_were_recorded_yet") }}
</div>
</div> </div>
</div> </div>
</section>
</div>
</div>
<div v-if="state.activetab === 'sponsorings'" class="tab-content block">
<div v-if="mode === 'add_sponsoring'">
<h1 class="text-3xl">{{ $t('add_sponsoring') }}</h1>
<form>
<div class="mt-6 grid gap-4 lg:gap-6">
<!-- Grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 lg:gap-6">
<div>
<label for="sponsorvorname"
class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{ $t('vorname_des_sponsors') }}</label>
<input v-bind="newsponsor_vorname" type="text" name="sponsorvorname" id="sponsorvorname"
placeholder="Vorname des Sponsors"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
<div>
<label for="sponsornachname"
class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{ $t('nachname_des_sponsors') }}</label>
<input v-bind="newsponsor_nachname" type="text" name="sponsornachname" id="sponsornachname"
placeholder="Nachname des Sponsors"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 lg:gap-6">
<!-- End Grid -->
<div>
<label for="sponsortel"
class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{ $t('telefonnummer_des_sponsors') }}</label>
<input v-bind="newsponsor_tel" type="tel" name="sponsortel" id="sponsortel" autocomplete="tel"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
<div>
<label for="sponsormail"
class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{ $t('e_mail_des_sponsors') }}</label>
<input v-bind="newsponsor_mail" type="email" name="sponsormail" id="sponsormail"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
</div>
<div>
<label for="eurokilometer"
class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{ $t('sponsoring_pro_kilometer_in_eur') }}</label>
<input v-bind="newsponsor_value" type="number" name="eurokilometer" id="eurokilometer"
placeholder="z.B. 1€ ODER 0,50€"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
</div>
</form>
<!-- End Grid -->
<!-- Checkbox -->
<div class="mt-3 flex">
<div class="flex">
<input v-model="newsponsor_check" id="sponsor_agree" name="sponsor_agree" type="checkbox"
class="shrink-0 mt-1.5 border-gray-200 rounded-sm text-blue-600 focus:ring-blue-500 dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800">
</div>
<div class="ms-3">
<label for="sponsor_agree" class="text-sm text-gray-600 dark:text-neutral-400">{{ $t('sponsor_add_agree') }}</label>
</div>
</div> </div>
<!-- End Checkbox --> </section>
</div>
<button :disabled="!newsponsor_check" @click="addSponsoring" type="button" </div>
class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-teal-100 text-teal-800 hover:bg-teal-200 focus:outline-hidden focus:bg-teal-200 disabled:opacity-50 disabled:pointer-events-none dark:text-teal-500 dark:bg-teal-800/30 dark:hover:bg-teal-800/20 dark:focus:bg-teal-800/20 mt-2 cursor-pointer"> <div v-if="state.activetab === 'sponsorings'" class="tab-content block">
{{ $t('add_sponsoring') }} <div
</button> class="bg-white border border-gray-200 rounded-lg shadow-lg p-4 dark:bg-neutral-800 dark:border-neutral-700 mt-2 font-medium"
role="alert" tabindex="-1" aria-labelledby="hs-discovery-label">
<div class="flex">
<div class="shrink-0">
<svg class="shrink-0 size-4 text-blue-600 mt-1" 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">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 16v-4"></path>
<path d="M12 8h.01"></path>
</svg>
</div>
<div class="ms-3">
<h3 id="hs-discovery-label" class="text-gray-800 font-semibold dark:text-white">
{{ $t('spenden_info') }}
</h3>
<p class="mt-2 text-sm text-gray-700 dark:text-neutral-400">
{{ $t('donation_on_event_day') }}
</p>
</div>
</div> </div>
<div v-else> </div>
<div class="py-4 w-full"> <div class="py-4 w-full">
<section class="dark:bg-gray-900 body-font"> <section class="dark:bg-gray-900 body-font">
<div class="container mx-auto"> <div class="mx-auto">
<div class="lg:w-2/3 w-full mx-auto overflow-auto"> <div class="w-full mx-auto">
<table v-if="state.sponsorings.length > 0" class="table-auto w-full text-left whitespace-no-wrap"> <table v-if="state.sponsorings.length > 0" class="table-auto w-full text-left whitespace-no-wrap">
<thead class=" <thead class="
text-black text-black
bg-gray-300 bg-gray-300
dark:text-white dark:text-white
text-sm text-sm
dark:bg-gray-800 dark:bg-gray-800
"> ">
<tr> <tr>
<th class=" <th class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
"> ">
Name Name
</th> </th>
<th class=" <th class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
"> ">
{{ $t("amount_per_kilometer_in_eur") }} {{ $t("amount_per_kilometer_in_eur") }}
</th> </th>
<th class=" <th class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
"> ">
{{ $t("current_total_amount_in_eur") }} {{ $t("current_total_amount_in_eur") }}
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="text-gray-900 dark:text-gray-50"> <tbody class="text-gray-900 dark:text-gray-50">
<tr class="odd:bg-white even:bg-gray-100 dark:odd:bg-neutral-900 dark:even:bg-neutral-800" <tr class="odd:bg-white even:bg-gray-100 dark:odd:bg-neutral-900 dark:even:bg-neutral-800"
v-for="s in state.sponsorings" :key="s.id"> v-for="s in state.sponsorings" :key="s.id">
<td class="px-4 py-3"> <td class="px-4 py-3">
<span v-text="s.donor.firstname + ' '"></span> <span v-text="s.donor.firstname + ' '"></span>
<span v-if="s.donor.middlename"> <span v-if="s.donor.middlename">
<span v-text="s.donor.middlename"></span> <span v-text="s.donor.middlename"></span>
</span> </span>
<span v-text="s.donor.lastname"></span> <span v-text="s.donor.lastname"></span>
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span v-text="(s.amountPerDistance / 100) <span v-text="(s.amountPerDistance / 100)
.toFixed(2) .toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' }) .toLocaleString('de-DE', { valute: 'EUR' })
"></span>€ "></span>€
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span v-text="(s.amount / 100) <span v-text="(s.amount / 100)
.toFixed(2) .toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' }) .toLocaleString('de-DE', { valute: 'EUR' })
"></span>€ "></span>€
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tfoot class="text-black <tfoot class="text-black
bg-gray-300 bg-gray-300
border-t-2 border-t-2
border-t-current border-t-current
dark:text-white dark:text-white
text-sm text-sm
dark:bg-gray-800"> dark:bg-gray-800">
<tr> <tr>
<td class="px-4 py-3">{{ $t("total") }}</td> <td class="px-4 py-3">{{ $t("total") }}</td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span v-text="( <span v-text="(
state.sponsorings.reduce(function ( state.sponsorings.reduce(function (
sum, sum,
current current
) { ) {
return sum + current.amountPerDistance; return sum + current.amountPerDistance;
}, },
0) / 100 0) / 100
) )
.toFixed(2) .toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' }) .toLocaleString('de-DE', { valute: 'EUR' })
"></span>€ "></span>€
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span v-text="( <span v-text="(
state.sponsorings.reduce(function ( state.sponsorings.reduce(function (
sum, sum,
current current
) { ) {
return sum + current.amount; return sum + current.amount;
}, },
0) / 100 0) / 100
) )
.toFixed(2) .toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' }) .toLocaleString('de-DE', { valute: 'EUR' })
"></span>€ "></span>€
</td> </td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
<div v-else class=" <div v-else class="
text-center text-center
font-medium font-medium
text-black text-black
dark:text-white dark:text-white
text-xl text-xl
"> ">
<img src="../assets/empty_laps.svg" class="h-56 mx-auto" :alt="[ <img src="../assets/empty_laps.svg" class="h-56 mx-auto" :alt="[
[$t('no_sponsorings_for_you_were_recorded_yet')], [$t('no_sponsorings_for_you_were_recorded_yet')],
]" /> ]" />
{{ $t("no_sponsorings_for_you_were_recorded_yet") }} {{ $t("no_sponsorings_for_you_were_recorded_yet") }}
</div>
<!-- <button
class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-teal-100 text-teal-800 hover:bg-teal-200 focus:outline-hidden focus:bg-teal-200 disabled:opacity-50 disabled:pointer-events-none dark:text-teal-500 dark:bg-teal-800/30 dark:hover:bg-teal-800/20 dark:focus:bg-teal-800/20 mt-2"
@click="mode = 'add_sponsoring'">{{ $t('add_sponsoring') }}</button> -->
</div>
</div> </div>
</section> </div>
</div> </div>
</div> </section>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- -->
<Footer></Footer>
</div> </div>
<!-- -->
<Footer />
</template> </template>
<script setup> <script setup>
import { reactive, ref } from "vue";
import { TYPE, useToast } from "vue-toastification";
import axios from "redaxios";
import { toCanvas } from "bwip-js";
import Footer from "@/components/Footer.vue"; import Footer from "@/components/Footer.vue";
import { useI18n } from 'vue-i18n' import { runnerSelfServiceControllerGet, runnerSelfServiceControllerGetScans, runnerSelfServiceControllerRemove } from "@odit/lfk-client";
import { toCanvas } from "bwip-js";
import axios from "redaxios";
import { reactive, ref } from "vue";
import { useI18n } from 'vue-i18n';
import { TYPE, useToast } from "vue-toastification";
const { t } = useI18n() const { t } = useI18n()
const mode = ref("") const loadstate = ref("loading")
//
const newsponsor_check = ref(false)
const newsponsor_value = ref("")
const newsponsor_mail = ref("")
const newsponsor_tel = ref("")
const newsponsor_vorname = ref("")
const newsponsor_nachname = ref("")
function shareSponsorLink() {
navigator.share({
title: state.firstname,
text: "Am 23.05.2025 findet der Lauf für Kaya! statt 🏃‍♂️🏃‍♀️\nWerde mein Sponsor beim Lauf für Kaya! 2025 und unterstütze mich pro gelaufenem Kilometer: https://lauf-fuer-kaya.de",
// url: "https://lauf-fuer-kaya.de",
})
}
function textToBase64Barcode(text) { function textToBase64Barcode(text) {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
@@ -549,8 +420,8 @@ const props = defineProps({
}); });
const accesstoken = props.token; const accesstoken = props.token;
function getReadableDistanceForUI() { function getTotalReadableDistance() {
return state.scans.reduce((accumulator, currentValue) => accumulator + currentValue.distance, 0) return getReadableDistance(state.scans.reduce((accumulator, currentValue) => accumulator + currentValue.distance, 0));
} }
function getReadableDistance(distance) { function getReadableDistance(distance) {
@@ -563,78 +434,57 @@ function getReadableDistance(distance) {
return `${m} m` return `${m} m`
} }
axios runnerSelfServiceControllerGet({ path: { jwt: accesstoken } }).then(({ data }) => {
.get(`${config.baseurl}api/runners/me/${accesstoken}`) loadstate.value = "loaded"
.then(({ data }) => { state.phone = data.phone;
state.phone = data.phone; state.email = data.email;
state.email = data.email; state.firstname = data.firstname;
state.firstname = data.firstname; state.middlename = data.middlename;
state.middlename = data.middlename; state.lastname = data.lastname;
state.lastname = data.lastname; state.group = data.group;
state.group = data.group; state.sponsorings = data.distanceDonations;
state.sponsorings = data.distanceDonations; state.fullobject = data;
state.fullobject = data; state.barcode = textToBase64Barcode(data.id ?? "???");
state.barcode = textToBase64Barcode(data.id ?? "???"); })
})
.catch((error) => { .catch((error) => {
loadstate.value = "error"
toast.clear(); toast.clear();
toast.error(t('profil_konnte_nicht_geladen_werden')); toast.error(t('profil_konnte_nicht_geladen_werden'));
}); });
axios runnerSelfServiceControllerGetScans({ path: { jwt: accesstoken } }).then(({ data }) => {
.get(`${config.baseurl}api/runners/me/${accesstoken}/scans`) let counter = 0
.then(({ data }) => { data = data.filter((s) => s.valid === true);
let counter = 0 data.map(function (s) {
data.map(function (s) { if (counter === 0) {
if (counter === 0) { s.lapTime_readable = t('first_lap')
s.lapTime_readable = t('first_lap') } else {
} else { s.lapTime_readable =
s.lapTime_readable = Math.floor(s.lapTime / 60) +
Math.floor(s.lapTime / 60) + "min " +
"min " + (Math.floor(s.lapTime % 60) + "").padStart(2, "0") +
(Math.floor(s.lapTime % 60) + "").padStart(2, "0") + "s";
"s"; }
} s.distance_readable = getReadableDistance(s.distance);
s.distance_readable = getReadableDistance(s.distance); counter++;
counter++; return s;
return s; });
}); state.scans = data;
data.filter((s) => s.valid === true); })
state.scans = data;
})
.catch((error) => { .catch((error) => {
toast.error(t('profil_konnte_nicht_geladen_werden')); toast.error(t('profil_konnte_nicht_geladen_werden'));
}); });
function addSponsoring() {
const postdata = {
"receiptNeeded": false,
"firstname": newsponsor_vorname.value,
"middlename": "",
"lastname": newsponsor_nachname.value,
"phone": newsponsor_tel.value,
"email": newsponsor_mail.value,
"address": {}
}
console.log(postdata);
axios
.post(`${config.baseurl}api/donors`, postdata)
.then(({ data }) => {
console.log(data);
})
.catch((error) => {
//
});
}
function delete_me() { function delete_me() {
toast.clear(); toast.clear();
toast(t('profil_wird_geloescht')); toast(t('profil_wird_geloescht'));
let url = `${config.baseurl}api/runners/me/${accesstoken}?force=true`; runnerSelfServiceControllerRemove({
axios path: {
.delete(url) jwt: accesstoken
.then(() => { }, query: { force: true }
toast.clear(); }).then(() => {
toast(t('alle_daten_geloescht')); toast.clear();
location.replace(`/`); toast(t('alle_daten_geloescht'));
}) location.replace(`/`);
})
.catch((error) => { .catch((error) => {
toast.clear(); toast.clear();
toast.error(t('profil_konnte_nicht_geloescht_werden')); toast.error(t('profil_konnte_nicht_geloescht_werden'));
@@ -656,6 +506,7 @@ function get_certificate() {
last_name: state.lastname, last_name: state.lastname,
id: state.fullobject.id, id: state.fullobject.id,
distance: state.fullobject.distance, distance: state.fullobject.distance,
self_service_link: window.location.href,
group: { group: {
name: state.group, name: state.group,
id: state.fullobject.group.id || 0, id: state.fullobject.group.id || 0,
@@ -707,13 +558,13 @@ function get_certificate() {
}); });
} }
function get_registration() { function get_registration() {
toast.clear(); // toast.clear();
toast(t('registrierungscode_wird_generiert')); // toast(t('registrierungscode_wird_generiert'));
var a = document.createElement("a"); var a = document.createElement("a");
a.href = state.barcode; a.href = state.barcode;
a.download = "LfK25_Registrierungscode.png"; a.download = `LfK25_Registrierungscode_${state.firstname}_${state.lastname}.png`;
a.click(); a.click();
toast.clear(); // toast.clear();
toast(t('registrierungscode_generiert'), { type: TYPE.SUCCESS }); // toast(t('registrierungscode_generiert'), { type: TYPE.SUCCESS });
} }
</script> </script>

View File

@@ -2,9 +2,9 @@
<div class="min-h-screen flex items-center justify-center"> <div class="min-h-screen flex items-center justify-center">
<div class="max-w-md w-full py-12 px-6"> <div class="max-w-md w-full py-12 px-6">
<img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt />
<h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center font-[Athiti]">Lauf für Kaya! - {{ <h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center">Lauf für Kaya! - {{
$t('profile') $t('profile')
}}</h1> }}</h1>
<p class="mx-auto leading-relaxed text-base text-center"> <p class="mx-auto leading-relaxed text-base text-center">
{{ $t('access_is_only_provided_via_your_email_link') }} {{ $t('access_is_only_provided_via_your_email_link') }}
</p> </p>
@@ -28,7 +28,7 @@
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-2 bg-gray-50 text-gray-500 rounded-md p-2" /> class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-2 bg-gray-50 text-gray-500 rounded-md p-2" />
<p v-if="!isEmail(user_email) && user_email !== ''" class="text-sm">{{ <p v-if="!isEmail(user_email) && user_email !== ''" class="text-sm">{{
$t('please_provide_valid_mail') $t('please_provide_valid_mail')
}}</p> }}</p>
</div> </div>
<div class="mt-2"> <div class="mt-2">
<button :disabled="(!state.submit_enabled)" <button :disabled="(!state.submit_enabled)"
@@ -55,16 +55,16 @@
</div> </div>
</div> </div>
</div> </div>
<Footer></Footer> <Footer />
</template> </template>
<script setup> <script setup>
import { computed, ref, reactive } from "vue";
import axios from "redaxios";
import isEmail from 'validator/es/lib/isEmail';
import { TYPE, useToast } from "vue-toastification";
import Footer from "@/components/Footer.vue"; import Footer from "@/components/Footer.vue";
import { useI18n } from 'vue-i18n' import { runnerSelfServiceControllerRequestNewToken } from "@odit/lfk-client";
import isEmail from 'validator/es/lib/isEmail';
import { computed, reactive, ref } from "vue";
import { useI18n } from 'vue-i18n';
import { TYPE, useToast } from "vue-toastification";
const { t } = useI18n() const { t } = useI18n()
let user_email = ref(""); let user_email = ref("");
@@ -79,11 +79,10 @@ function resendMail() {
if (isEmail(user_email.value)) { if (isEmail(user_email.value)) {
toast(t('login_link_is_requested')); toast(t('login_link_is_requested'));
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2); const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
axios.post(`${config.baseurl}api/runners/login?mail=${user_email.value}&locale=${browserlocale}`) runnerSelfServiceControllerRequestNewToken({ query: { locale: browserlocale, mail: user_email.value } }).then(({ data }) => {
.then(({ data }) => { console.log(data);
console.log(data); toast(t('login_link_gesendet_an_user_email_value') + user_email.value);
toast(t('login_link_gesendet_an_user_email_value') + user_email.value); })
})
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
toast(t('error_requesting_the_login_link'), { type: TYPE.ERROR }); toast(t('error_requesting_the_login_link'), { type: TYPE.ERROR });

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="min-h-screen flex items-center justify-center" v-if="registrationState === 'registered'"> <div class="min-h-screen flex items-center justify-center" v-if="registrationState === 'registered'">
<div class="max-w-md w-full py-12 px-6 font-[Athiti]"> <div class="max-w-md w-full py-6 px-6">
<img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt />
<h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center"> <h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center">
Lauf für Kaya! - {{ $t('registriert') }} Lauf für Kaya! - {{ $t('registriert') }}
@@ -12,26 +12,26 @@
</div> </div>
</div> </div>
<div class="min-h-screen flex items-center justify-center" v-else> <div class="min-h-screen flex items-center justify-center" v-else>
<div class="max-w-md w-full py-12 px-6 font-[Athiti]"> <div class="max-w-md w-full py-6 px-6">
<img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt />
<h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center"> <h1 class="sm:text-3xl text-2xl font-semibold title-font text-center">
Lauf für Kaya! - {{ $t("registrieren") }} Lauf für Kaya!
</h1> </h1>
<p class="mx-auto leading-relaxed text-base text-center font-medium"> <p class="mx-auto leading-relaxed text-lg text-center font-medium mb-4">
{{ $t("register.register_now") }} {{ $t("register.register_now") }}
</p> </p>
<p v-if="state.org_name !== ''" class="mx-auto leading-relaxed text-base text-center font-medium"> <div v-if="state.org_name !== ''" class="w-full text-center">
{{ $t("organization") }}: {{ state.org_name }} <span
</p> class="inline-flex items-center gap-x-1.5 py-1.5 px-3 rounded-lg mx-auto font-medium bg-blue-100 text-blue-800 dark:bg-blue-800/30 dark:text-blue-500">{{ state.org_name }}</span>
<p v-if="state.org_name !== '' && state.org_teams.length > 0" </div>
class="mx-auto leading-relaxed text-base text-center"> <label v-if="state.org_name !== '' && state.org_teams.length > 0" for="select_team" class="block font-semibold mt-2">
Team: Team:
</p> </label>
<select v-model="org_team" v-if="state.org_name !== '' && state.org_teams.length > 0" class=" <select id="select_team" v-model="org_team" v-if="state.org_name !== '' && state.org_teams.length > 0" class="
w-full w-full
border border-2
bg-white bg-white
rounded rounded-md
px-3 px-3
py-2 py-2
outline-none outline-none
@@ -47,120 +47,123 @@
{{ t.name }} {{ t.name }}
</option> </option>
</select> </select>
<p v-if="state.org_name === ''" class="mx-auto leading-relaxed text-base text-center"> <div v-if="state.org_name === ''" class="w-full text-center">
{{ $t('buergerlauf') }} <span
</p> class="inline-flex items-center gap-x-1.5 py-1.5 px-3 rounded-lg mx-auto font-medium bg-blue-100 text-blue-800 dark:bg-blue-800/30 dark:text-blue-500">{{
$t('buergerlauf') }}</span>
</div>
<div class="mt-4"> <div class="mt-4">
<label for="first_name" class="block font-medium"> <label for="first_name" class="block font-semibold mt-2">
{{ $t("vorname") }} {{ $t("vorname") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input v-model="userdetails.firstname" name="firstname" id="first_name" autocomplete="off" <input v-model="userdetails.firstname" name="firstname" id="first_name" autocomplete="off"
:placeholder="[[$t('vorname')]]" type="text" :class="{ :placeholder="[[$t('ihr_vorname')]]" type="text" :class="{
'border-red-500': !userdetails.firstname.trim(), '': !userdetails.firstname.trim(),
'border-green-300': userdetails.firstname.trim(), 'border-green-300': userdetails.firstname.trim(),
}" class=" }" class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
sm:text-sm sm:text-sm
border-gray-300 border-2 border-2 placeholder:text-gray-800
bg-gray-50 bg-gray-50
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" /> " />
<!-- --> <!-- -->
<label for="middle_name" class="block font-medium">{{ <label for="last_name" class="block font-semibold mt-2">
$t("mittelname")
}}</label>
<input v-model="userdetails.middlename" name="middlename" id="middle_name" autocomplete="off"
:placeholder="[[$t('mittelname')]]" type="text" class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-gray-300 border-2
bg-gray-50
text-gray-500
rounded-md
p-2
" />
<!-- -->
<label for="last_name" class="block font-medium">
{{ $t("nachname") }} {{ $t("nachname") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input v-model="userdetails.lastname" name="lastname" id="last_name" autocomplete="off" <input v-model="userdetails.lastname" name="lastname" id="last_name" autocomplete="off"
:placeholder="[[$t('nachname')]]" type="text" :class="{ :placeholder="[[$t('ihr_nachname')]]" type="text" :class="{
'border-red-500': !userdetails.lastname.trim(), '': !userdetails.lastname.trim(),
'border-green-300': userdetails.lastname.trim(), 'border-green-300': userdetails.lastname.trim(),
}" class=" }" class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
sm:text-sm sm:text-sm
border-gray-300 border-2 border-2 placeholder:text-gray-800
bg-gray-50 bg-gray-50
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" /> " />
<!-- --> <!-- -->
<label for="email_address" class="block font-medium"> <label for="email_address" class="block font-semibold mt-2">
{{ $t("e_mail_adress") }} {{ $t("e_mail_adress") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input v-model="userdetails.mail" name="email_address" id="email_address" autocomplete="off" <input v-model="userdetails.mail" name="email_address" id="email_address" autocomplete="off"
:placeholder="[[$t('e_mail_adress')]]" type="email" :class="{ :placeholder="[[$t('ihre_e_mail_adresse')]]" type="email" :class="{
'border-red-500': !isEmail(userdetails.mail), '': !isEmail(userdetails.mail),
'border-green-300': isEmail(userdetails.mail), 'border-green-300': isEmail(userdetails.mail),
}" class=" }" class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
sm:text-sm sm:text-sm
border-2 border-2 placeholder:text-gray-800
bg-gray-50 bg-gray-50
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" /> " />
<p v-if="!isEmail(userdetails.mail)" class="text-sm"> <p v-if="userdetails.mail !== '' && !isEmail(userdetails.mail)" class="text-sm">
{{ $t("please_provide_valid_mail") }} {{ $t("please_provide_valid_mail") }}
</p> </p>
<!-- --> <!-- -->
<label for="phone" class="select-none block font-medium">{{ <label for="phone" class="block font-semibold mt-2">{{
$t("phone_number") $t("phone_number")
}}</label> }}</label>
<div v-if="userdetails.phone !== '' && !userdetails.phone.includes('+')"
class="bg-blue-100 border border-blue-200 text-black rounded-lg p-4 mb-1" role="alert" tabindex="-1"
aria-labelledby="hs-actions-label">
<div class="flex">
<div class="shrink-0">
<svg class="shrink-0 size-4 mt-1" 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">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 16v-4"></path>
<path d="M12 8h.01"></path>
</svg>
</div>
<div class="ms-3">
<h3 id="hs-actions-label" class="font-semibold">
{{ $t('hinweis') }}
</h3>
<div class="mt-2 text-sm text-gray-800 font-medium">
{{ $t('registration_local_phone_nr') }}
</div>
</div>
</div>
</div>
<input v-model="userdetails.phone" name="phone" id="phone" autocomplete="off" <input v-model="userdetails.phone" name="phone" id="phone" autocomplete="off"
:placeholder="[[$t('phone_number')]]" type="text" :class="{ :placeholder="[[$t('geben_sie_ihre_handynummer_an')]]" type="text" :class="{
'border-red-500': '':
!isMobilePhone(userdetails.phone) && userdetails.phone.trim(), userdetails.phone === '',
'border-green-300': 'border-red-300':
isMobilePhone(userdetails.phone) && userdetails.phone.trim(), !isPhoneOkay(),
}" class=" }" class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
sm:text-sm sm:text-sm
border-2 border-2 placeholder:text-gray-800
bg-gray-50 bg-gray-50
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" /> " />
<p v-if="!isMobilePhone(userdetails.phone) && userdetails.phone.trim()" class="text-sm"> <p v-if="!isPhoneOkay()" class="text-sm">
{{ $t("this_is_not_a_valid_international_phone_number") }} {{ $t("this_is_not_a_valid_international_phone_number") }}
</p> </p>
<!-- --> <!-- -->
@@ -173,12 +176,12 @@
</div> </div>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label for="address_activated" class="font-medium text-gray-600 select-none">{{ $t("provide_address") <label for="address_activated" class="font-medium text-gray-600 select-none">{{ $t("provide_address")
}}</label> }}</label>
</div> </div>
</div> </div>
<div v-if="provide_address === true" class="col-span-6"> <div v-if="provide_address === true" class="col-span-6">
<div class="col-span-6"> <div class="col-span-6">
<label for="street" class="block font-medium"> <label for="street" class="block font-semibold mt-2">
{{ $t("strasse") }} {{ $t("strasse") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
@@ -188,12 +191,11 @@
'border-green-300': userdetails.address.street.trim(), 'border-green-300': userdetails.address.street.trim(),
}" class=" }" class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
sm:text-sm sm:text-sm
border-gray-300 border-2 border-2 placeholder:text-gray-800
bg-gray-50 bg-gray-50
text-gray-500 text-gray-500
rounded-md rounded-md
@@ -201,18 +203,17 @@
" /> " />
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label for="address2" class="block font-medium">{{ <label for="address2" class="block font-semibold mt-2">{{
$t("apartment_suite_etc") $t("apartment_suite_etc")
}}</label> }}</label>
<input v-model="userdetails.address.address2" type="text" name="address2" <input v-model="userdetails.address.address2" type="text" name="address2"
:placeholder="[[$t('apartment_suite_etc')]]" id="address2" autocomplete="street-address" class=" :placeholder="[[$t('apartment_suite_etc')]]" id="address2" autocomplete="street-address" class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
sm:text-sm sm:text-sm
border-gray-300 border-2 border-2 placeholder:text-gray-800
bg-gray-50 bg-gray-50
text-gray-500 text-gray-500
rounded-md rounded-md
@@ -220,7 +221,7 @@
" /> " />
</div> </div>
<div class="col-span-6 sm:col-span-6 lg:col-span-2"> <div class="col-span-6 sm:col-span-6 lg:col-span-2">
<label for="city" class="block font-medium"> <label for="city" class="block font-semibold mt-2">
{{ $t("ort") }} {{ $t("ort") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
@@ -230,12 +231,11 @@
'border-green-300': userdetails.address.city.trim(), 'border-green-300': userdetails.address.city.trim(),
}" class=" }" class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
sm:text-sm sm:text-sm
border-gray-300 border-2 border-2 placeholder:text-gray-800
bg-gray-50 bg-gray-50
text-gray-500 text-gray-500
rounded-md rounded-md
@@ -243,7 +243,7 @@
" /> " />
</div> </div>
<div class="col-span-6 sm:col-span-3 lg:col-span-2"> <div class="col-span-6 sm:col-span-3 lg:col-span-2">
<label for="postal_code" class="block font-medium"> <label for="postal_code" class="block font-semibold mt-2">
{{ $t("plz") }} {{ $t("plz") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
@@ -259,12 +259,11 @@
), ),
}" class=" }" class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
sm:text-sm sm:text-sm
border-gray-300 border-2 border-2 placeholder:text-gray-800
bg-gray-50 bg-gray-50
text-gray-500 text-gray-500
rounded-md rounded-md
@@ -314,7 +313,7 @@
text-center text-center
py-2 py-2
px-3 px-3
border-2 border-gray-300 border-2 placeholder:text-gray-800 border-gray-300
rounded-md rounded-md
p-1 p-1
bg-blue-800 bg-blue-800
@@ -331,31 +330,30 @@
</div> </div>
</div> </div>
</div> </div>
<Footer></Footer> <div class="p-8">
<Footer />
</div>
</template> </template>
<script setup> <script setup>
import { computed, ref, reactive } from "vue"; import Footer from "@/components/Footer.vue";
import axios from "redaxios"; import { runnerSelfServiceControllerGetSelfserviceOrg, runnerSelfServiceControllerRegisterOrganizationRunner, runnerSelfServiceControllerRegisterRunner } from "@odit/lfk-client";
import isEmail from "validator/es/lib/isEmail"; import isEmail from "validator/es/lib/isEmail";
import isMobilePhone from "validator/es/lib/isMobilePhone"; import isMobilePhone from "validator/es/lib/isMobilePhone";
import isPostalCode from "validator/es/lib/isPostalCode"; import isPostalCode from "validator/es/lib/isPostalCode";
import { computed, reactive, ref } from "vue";
import { useI18n } from 'vue-i18n';
import { TYPE, useToast } from "vue-toastification"; import { TYPE, useToast } from "vue-toastification";
import Footer from "@/components/Footer.vue";
import { useI18n } from 'vue-i18n'
const { t } = useI18n() const { t } = useI18n()
const props = defineProps({ const props = defineProps({
token: String, token: String,
}); });
if (props.token) { if (props.token) {
axios runnerSelfServiceControllerGetSelfserviceOrg({ path: { token: props.token } }).then(({ data }) => {
.get(`${config.baseurl}api/organizations/selfservice/${props.token}`) state.org_name = data.name;
.then(({ data }) => { state.org_teams = data.teams;
state.org_name = data.name; org_team.value = data.teams[0]?.id;
state.org_teams = data.teams; })
org_team.value = data.teams[0]?.id;
})
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
}); });
@@ -369,6 +367,34 @@ let userdetails = ref({
phone: "", phone: "",
address: { street: "", address2: "", city: "", zipcode: "" }, address: { street: "", address2: "", city: "", zipcode: "" },
}); });
function formatPhoneNumber(phoneNumber, countryCode = "+49") {
// Remove all non-digit characters
const cleanedNumber = phoneNumber.replace(/\D/g, "");
// Check if the number starts with the country code
if (cleanedNumber.startsWith(countryCode.replace("+", ""))) {
return "+" + cleanedNumber; // already international
}
// Check if the number starts with 0
if (cleanedNumber.startsWith("0")) {
return countryCode + cleanedNumber.slice(1);
}
// If it doesn't start with 0 or the country code, assume it's a local number.
// In this case, prepend the country code.
return countryCode + cleanedNumber;
}
function isPhoneOkay() {
if (userdetails.value.phone === "") {
return true
}
const formattedNumber = formatPhoneNumber(userdetails.value.phone)
if (isMobilePhone(formattedNumber)) {
return true
}
return false
}
let provide_address = ref(false); let provide_address = ref(false);
let agb_accepted = ref(false); let agb_accepted = ref(false);
let data_confirmed = ref(false); let data_confirmed = ref(false);
@@ -382,8 +408,7 @@ const state = reactive({
() => () =>
agb_accepted.value === true && agb_accepted.value === true &&
data_confirmed.value === true && data_confirmed.value === true &&
(isMobilePhone(userdetails.value.phone) || isPhoneOkay() &&
!userdetails.value.phone.trim()) &&
isEmail(userdetails.value.mail) && isEmail(userdetails.value.mail) &&
userdetails.value.firstname && userdetails.value.firstname &&
userdetails.value.lastname && userdetails.value.lastname &&
@@ -396,25 +421,25 @@ const state = reactive({
}); });
const toast = useToast(); const toast = useToast();
function login() { function login() {
userdetails = userdetails.value; // userdetails = userdetails.value;
if (userdetails?.phone === "" || isMobilePhone(userdetails.phone)) { if (isPhoneOkay()) {
if (isEmail(userdetails.mail)) { if (isEmail(userdetails.value.mail)) {
let postdata = { let postdata = {
email: userdetails.mail, email: userdetails.value.mail,
firstname: userdetails.firstname, firstname: userdetails.value.firstname,
middlename: userdetails.middlename, middlename: userdetails.value.middlename,
lastname: userdetails.lastname, lastname: userdetails.value.lastname,
address: {}, address: {},
}; };
if (isMobilePhone(userdetails.phone)) { if (userdetails.value.phone !== "") {
postdata.phone = userdetails.phone; postdata.phone = formatPhoneNumber(userdetails.value.phone)
} }
if (provide_address.value === true) { if (provide_address.value === true) {
postdata.address = { postdata.address = {
address1: userdetails.address.street, address1: userdetails.value.address.street,
address2: userdetails.address.address2 || "", address2: userdetails.value.address.address2 || "",
city: userdetails.address.city, city: userdetails.value.address.city,
postalcode: userdetails.address.zipcode, postalcode: userdetails.value.address.zipcode,
country: "DE", country: "DE",
}; };
} }
@@ -426,28 +451,42 @@ function login() {
(navigator.languages && navigator.languages[0]) || (navigator.languages && navigator.languages[0]) ||
"" ""
).substr(0, 2); ).substr(0, 2);
let url = `${config.baseurl}api/runners/register/?locale=${browserlocale}`;
if (props.token) {
url = `${config.baseurl}api/runners/register/${props.token}/?locale=${browserlocale}`;
}
registrationState.value = "loading"; registrationState.value = "loading";
axios if (props.token) {
.post(url, postdata) runnerSelfServiceControllerRegisterOrganizationRunner({ path: { token: props.token }, body: postdata, query: { locale: browserlocale } })
.then(() => { .then(() => {
registrationState.value = "registered"; registrationState.value = "registered";
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
if (error.data.message === "E-Mail already registered") { if (error.data.message === "E-Mail already registered") {
toast(t('already_registered'), { type: TYPE.ERROR }); toast(t('already_registered'), { type: TYPE.ERROR });
} else if (error.data.message === "Invalid body, check 'errors' property for more info.") { } else if (error.data.message === "Invalid body, check 'errors' property for more info.") {
error.data.errors.forEach(e => { error.data.errors.forEach(e => {
if (e.property === "phone") { if (e.property === "phone") {
toast(t('invalid_input_phone_number_should_be_international_format'), { type: TYPE.ERROR }); toast(t('invalid_input_phone_number_should_be_international_format'), { type: TYPE.ERROR });
} }
}); });
} }
}); });
} else {
runnerSelfServiceControllerRegisterRunner({ body: postdata, query: { locale: browserlocale } })
.then(() => {
registrationState.value = "registered";
})
.catch((error) => {
console.log(error);
if (error.data.message === "E-Mail already registered") {
toast(t('already_registered'), { type: TYPE.ERROR });
} else if (error.data.message === "Invalid body, check 'errors' property for more info.") {
error.data.errors.forEach(e => {
if (e.property === "phone") {
toast(t('invalid_input_phone_number_should_be_international_format'), { type: TYPE.ERROR });
}
});
}
});
}
} }
} }
} }