Compare commits

...

98 Commits

Author SHA1 Message Date
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
e7b9c6e203 🚀Bumped version to v1.2.3 2025-03-17 22:22:39 +01:00
3641d2a783 no selfservice sponsor add for now 2025-03-17 22:21:17 +01:00
ccea9d6197 shareSponsorLink function 2025-03-17 22:20:54 +01:00
c94f9e550e i18n 2025-03-17 22:15:00 +01:00
0848209d49 feat: disable darkmode for now, also is better for visibility on day of run... 2025-03-17 22:06:51 +01:00
1202f2ebca feat: profile cleanup 2025-03-17 22:06:32 +01:00
4714b81465 wip 2025-03-17 22:00:31 +01:00
7f2e6b9160 cleanup 2025-03-17 21:54:06 +01:00
0366f95951 feat: cleanup profile 2025-03-17 21:52:44 +01:00
382757aa66 feat: wip: sponsoring add 2025-03-17 21:43:47 +01:00
34e63cf690 feat: improve profile 2025-03-17 21:32:02 +01:00
846d10f0b9 feat: improve profile 2025-03-17 21:29:13 +01:00
86ec22aa43 feat: cleanup profile 2025-03-17 21:16:57 +01:00
f6f46f41bf feat(footer): 2024 2025-03-17 20:32:32 +01:00
64bb2d157d chore(deps): bump 2025-03-17 20:32:23 +01:00
c8ceae5cf0 🚀Bumped version to v1.2.2
Some checks failed
ci/woodpecker/push/build Pipeline failed
ci/woodpecker/tag/release Pipeline was successful
2024-12-16 17:10:39 +01:00
1d7cd601ee feat(profile): add cursor pointer
Some checks failed
ci/woodpecker/push/build Pipeline failed
2024-12-16 17:10:27 +01:00
9ddb188ef6 🚀Bumped version to v1.2.1
All checks were successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/release Pipeline was successful
2024-12-16 17:03:30 +01:00
4996b8c526 Merge branch 'dev' of https://git.odit.services/lfk/selfservice into dev 2024-12-16 17:03:06 +01:00
7d2a29c0d8 🚀Bumped version to v1.2.0
All checks were successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/release Pipeline was successful
2024-12-16 16:56:10 +01:00
721892c315 refacor(documents): Switch to new document-server 2024-12-16 16:55:26 +01:00
d5641312ca feat(profile): updated tab alignment 2024-12-16 16:55:16 +01:00
c34a8a7fcc refactor(profile): replace styles with tailwindcss 2024-12-16 16:55:01 +01:00
55abb9ed22 feat(profile): show total distance 2024-12-16 16:54:06 +01:00
1d55445c1b 🚀Bumped version to v1.1.2
Some checks failed
ci/woodpecker/push/build Pipeline failed
ci/woodpecker/tag/release Pipeline was successful
2024-12-11 23:08:38 +01:00
762454a086 fix(profile): migrate to code128 2024-12-11 23:08:27 +01:00
25c2a170bc chore(deps): bump all 2024-12-11 22:45:30 +01:00
b21ad636ad refactor: drop postbuild step 2024-12-11 22:45:20 +01:00
4771bf1359 🚀Bumped version to v1.1.1
All checks were successful
ci/woodpecker/tag/release Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
2024-12-11 22:43:36 +01:00
dbe707b062 fix(profile): passed id is a jwt 2024-12-11 22:43:02 +01:00
dee1b7a6ea 🚀Bumped version to v1.1.0
All checks were successful
ci/woodpecker/tag/release Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 16:50:31 +01:00
4bcbc67436 refactor: drop sub-directory routing 2024-12-02 16:48:15 +01:00
595735ad00 🚀Bumped version to v1.0.1
All checks were successful
ci/woodpecker/tag/release Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 15:53:04 +01:00
7fcb6a9fc3 fix(container): Add dockeringore 2024-12-02 15:51:25 +01:00
2285ea5070 🚀Bumped version to v1.0.0
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 15:32:47 +01:00
4af5c4545b refactor
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 13:16:45 +01:00
f296cbc1a0 i18n 2024-12-02 13:08:55 +01:00
4fcc38c374 updated profile page 2024-12-02 13:08:08 +01:00
90c085db28 footer update 2024-12-02 13:07:57 +01:00
1a3ab98412 improved style in registered view 2024-12-02 12:58:09 +01:00
048edfba89 i18n 2024-12-02 12:56:43 +01:00
0acda07eb5 add i18n ally snake case config 2024-12-02 12:42:00 +01:00
afffde8fa0 registration brand font + more translations 2024-12-02 12:34:42 +01:00
1eab535381 wip: general updates 2024-12-02 11:54:05 +01:00
196b386d6d refactor: translations 2024-12-02 11:31:24 +01:00
548148e898 fix: translations 2024-12-02 11:29:05 +01:00
6376dcb5fe feat(Footer): ref lfk 2024-12-02 11:25:11 +01:00
75b61d991b feat(Home): improve ui 2024-12-02 11:24:04 +01:00
af9a168f58 feat: lfk font 2024-12-02 11:12:00 +01:00
f71b01c39a chore(deps): node@23.3.0 2024-12-02 11:06:26 +01:00
3e289d83f9 feat(Home): improve background.jpg import
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 11:00:07 +01:00
ec6d252928 refactor: code cleanup 2024-12-02 10:55:06 +01:00
4a11fef0e0 chore(deps): update all
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 10:40:06 +01:00
b85c3958c2 chore: pnpm v9
Some checks are pending
ci/woodpecker/push/build Pipeline is running
2024-12-02 10:16:59 +01:00
780bc54604 refactor(ci): Make ready for new woodpecker
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-11-26 19:23:40 +01:00
cb2f8eeab1 chore: 2025 2024-11-21 10:49:46 +01:00
c36db2c18f Pin pnpm
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2023-11-06 20:27:30 +01:00
decc80fcc1 Merge branch 'dev' of git.odit.services:lfk/selfservice into dev
Some checks failed
ci/woodpecker/push/build Pipeline failed
2023-11-06 20:25:28 +01:00
9a3d307dfa feat(ci)!: Switch to woodpecker 2023-11-06 20:25:26 +01:00
240f44df60 🚀Bumped version to v0.11.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-07 15:17:49 +02:00
677e65f44a chore(deps): pnpm@8.1.1 2023-04-07 15:17:27 +02:00
772eca64bb fix(Footer): darkmode colors in lightmode
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-07 15:15:26 +02:00
25d25401df fix: registration code white bg
close #50
2023-04-07 15:13:44 +02:00
cac5103d52 switched drone to kaniko with cache
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-29 20:20:06 +02:00
6aca13f0cb Pinned pnpm and lockfile 2023-03-29 20:17:33 +02:00
78fea1ea04 Switched dockerfile to pnpm with cache 2023-03-29 20:17:18 +02:00
fa51b31fe4 🚀Bumped version to v0.11.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-15 19:27:59 +01:00
b9624aa5ad Added footer to every page 2023-03-15 19:27:40 +01:00
09e48e771f Accept tos to accept privacy_policy 2023-03-15 19:22:35 +01:00
8364321a7c 🚀Bumped version to v0.11.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-18 17:27:22 +01:00
659fa77dca Profile: add "---" if no data set
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-18 17:26:54 +01:00
41 changed files with 5006 additions and 4306 deletions

185
.dockerignore Normal file
View File

@@ -0,0 +1,185 @@
# ---> Node
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# 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
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# ---> Windows
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# ---> macOS
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# ---> Vue
# gitignore template for Vue.js projects
#
# Recommended template: Node.gitignore
# TODO: where does this rule come from?
docs/_book
# TODO: where does this rule come from?
test/
/package-lock.json
/yarn.lock
/public/env.js

View File

@@ -1,117 +0,0 @@
---
kind: secret
name: docker_username
get:
path: odit-registry-builder
name: username
---
kind: secret
name: docker_password
get:
path: odit-registry-builder
name: password
---
kind: secret
name: git_ssh
get:
path: odit-git-bot
name: sshkey
---
kind: pipeline
type: kubernetes
name: build:dev
steps:
- name: build dev
image: plugins/docker
depends_on: [clone]
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: registry.odit.services/lfk/selfservice
tags:
- dev
registry: registry.odit.services
mtu: 1000
trigger:
branch:
- dev
event:
- push
---
kind: pipeline
type: kubernetes
name: build:testing
steps:
- name: build testing
image: plugins/docker
depends_on: [clone]
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: registry.odit.services/lfk/selfservice
tags:
- testing
registry: registry.odit.services
mtu: 1000
trigger:
branch:
- bugfix/31-env_linking
event:
- push
---
kind: pipeline
type: kubernetes
name: build:latest
steps:
- name: build latest
image: plugins/docker
depends_on: [clone]
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: registry.odit.services/lfk/selfservice
tags:
- latest
registry: registry.odit.services
mtu: 1000
trigger:
branch:
- main
event:
- push
---
kind: pipeline
type: kubernetes
name: build:tags
steps:
- name: build $DRONE_TAG
image: plugins/docker
depends_on: [clone]
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: registry.odit.services/lfk/selfservice
tags:
- '${DRONE_TAG}'
registry: registry.odit.services
mtu: 1000
trigger:
event:
- tag

27
.gitea/workflows/dev.yaml Normal file
View File

@@ -0,0 +1,27 @@
name: Build Latest image
on:
push:
branches:
- dev
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:dev
platforms: linux/amd64,linux/arm64

View File

@@ -0,0 +1,27 @@
name: Build Latest image
on:
push:
branches:
- main
jobs:
build-container:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to registry
uses: docker/login-action@v3
with:
registry: registry.odit.services
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: |
${{ vars.REGISTRY }}/lfk/selfservice:latest
platforms: linux/amd64,linux/arm64

View File

@@ -0,0 +1,27 @@
name: Build release images
on:
push:
tags:
- "*.*.*"
jobs:
build-container:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to registry
uses: docker/login-action@v3
with:
registry: registry.odit.services
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: |
${{ vars.REGISTRY }}/lfk/selfservice:${{ github.ref_name }}
platforms: linux/amd64,linux/arm64

View File

@@ -2,5 +2,9 @@
"i18n-ally.localesPaths": [ "i18n-ally.localesPaths": [
"src/locales" "src/locales"
], ],
"i18n-ally.keystyle": "nested" "i18n-ally.keystyle": "nested",
"i18n-ally.extract.keygenStyle": "snake_case",
"i18n-ally.enabledFrameworks": [
"vue"
]
} }

View File

@@ -2,9 +2,195 @@
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.3.1](https://git.odit.services/lfk/selfservice/compare/1.3.0...1.3.1)
- feat: footer cleanup [`65dc27a`](https://git.odit.services/lfk/selfservice/commit/65dc27add1760c6ebe11f415c49238f82cdb5b48)
#### [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)
> 17 March 2025
- 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: improve profile [`846d10f`](https://git.odit.services/lfk/selfservice/commit/846d10f0b95dad460a068bdaf3ca489d96c0b723)
- feat: profile cleanup [`1202f2e`](https://git.odit.services/lfk/selfservice/commit/1202f2ebca5fbc0baea145dda6f99668d8c47e92)
- feat: improve profile [`34e63cf`](https://git.odit.services/lfk/selfservice/commit/34e63cf690431da973a969376b493d8b34f5c7c0)
- i18n [`c94f9e5`](https://git.odit.services/lfk/selfservice/commit/c94f9e550e1cbe4626242423deb6d9ab994eea63)
- 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)
- 🚀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)
- 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)
- wip [`4714b81`](https://git.odit.services/lfk/selfservice/commit/4714b814650d4138d8522dd57b5ee59a8c96a0ac)
- feat(footer): 2024 [`f6f46f4`](https://git.odit.services/lfk/selfservice/commit/f6f46f41bf2c6fcf75dbd79a28f6dd14114445e3)
- cleanup [`7f2e6b9`](https://git.odit.services/lfk/selfservice/commit/7f2e6b916076874cfb2e787ae174320b50d2d7e0)
#### [1.2.2](https://git.odit.services/lfk/selfservice/compare/1.2.1...1.2.2)
> 16 December 2024
- feat(profile): add cursor pointer [`1d7cd60`](https://git.odit.services/lfk/selfservice/commit/1d7cd601ee027dd7df0405079e208d03078210bb)
- 🚀Bumped version to v1.2.2 [`c8ceae5`](https://git.odit.services/lfk/selfservice/commit/c8ceae5cf016341af1bc903fb219e544bb2f0d58)
#### [1.2.1](https://git.odit.services/lfk/selfservice/compare/1.2.0...1.2.1)
> 16 December 2024
- feat(profile): show total distance [`55abb9e`](https://git.odit.services/lfk/selfservice/commit/55abb9ed22e4c66c05536897ba33b12915eea226)
- refactor(profile): replace styles with tailwindcss [`c34a8a7`](https://git.odit.services/lfk/selfservice/commit/c34a8a7fcc77a0fa27280365ebf2382fbffc1e61)
- 🚀Bumped version to v1.2.1 [`9ddb188`](https://git.odit.services/lfk/selfservice/commit/9ddb188ef659742018f00d786e030f80a0d9bbc5)
- feat(profile): updated tab alignment [`d564131`](https://git.odit.services/lfk/selfservice/commit/d5641312ca0b35a5c5ab9b7b19ed3a40971ac4fd)
#### [1.2.0](https://git.odit.services/lfk/selfservice/compare/1.1.2...1.2.0)
> 16 December 2024
- refacor(documents): Switch to new document-server [`721892c`](https://git.odit.services/lfk/selfservice/commit/721892c315de9c2c1158d0f728dc2ef387a5d8c2)
- 🚀Bumped version to v1.2.0 [`7d2a29c`](https://git.odit.services/lfk/selfservice/commit/7d2a29c0d834fbe783e59308af89bb8fb46a8015)
#### [1.1.2](https://git.odit.services/lfk/selfservice/compare/1.1.1...1.1.2)
> 11 December 2024
- chore(deps): bump all [`25c2a17`](https://git.odit.services/lfk/selfservice/commit/25c2a170bc9cde66498ae3d7f966201f2b28b679)
- 🚀Bumped version to v1.1.2 [`1d55445`](https://git.odit.services/lfk/selfservice/commit/1d55445c1b67ec2e1be73172d8e451f038451f59)
- refactor: drop postbuild step [`b21ad63`](https://git.odit.services/lfk/selfservice/commit/b21ad636ad69886878d5bd0f441f4187e4f22a5c)
- fix(profile): migrate to code128 [`762454a`](https://git.odit.services/lfk/selfservice/commit/762454a08674303881063337ddf86da564b191f1)
#### [1.1.1](https://git.odit.services/lfk/selfservice/compare/1.1.0...1.1.1)
> 11 December 2024
- 🚀Bumped version to v1.1.1 [`4771bf1`](https://git.odit.services/lfk/selfservice/commit/4771bf135986f90f344757083236539b9d590e83)
- fix(profile): passed id is a jwt [`dbe707b`](https://git.odit.services/lfk/selfservice/commit/dbe707b062ced048428b8c1f62a0ab047ab0051b)
#### [1.1.0](https://git.odit.services/lfk/selfservice/compare/1.0.1...1.1.0)
> 2 December 2024
- refactor: drop sub-directory routing [`4bcbc67`](https://git.odit.services/lfk/selfservice/commit/4bcbc67436e6c0b0905e3ef2613894854d659091)
- 🚀Bumped version to v1.1.0 [`dee1b7a`](https://git.odit.services/lfk/selfservice/commit/dee1b7a6eab11689bae8914e74bea7cb364475e2)
#### [1.0.1](https://git.odit.services/lfk/selfservice/compare/1.0.0...1.0.1)
> 2 December 2024
- fix(container): Add dockeringore [`7fcb6a9`](https://git.odit.services/lfk/selfservice/commit/7fcb6a9fc3f98772990790f6385200732f8bce7c)
- 🚀Bumped version to v1.0.1 [`595735a`](https://git.odit.services/lfk/selfservice/commit/595735ad003b849521e6e5f2b24da4880f768dff)
### [1.0.0](https://git.odit.services/lfk/selfservice/compare/0.11.3...1.0.0)
> 2 December 2024
- chore(deps): update all [`4a11fef`](https://git.odit.services/lfk/selfservice/commit/4a11fef0e0ad0940535fd1d6a1a57a829dc2b50d)
- chore: pnpm v9 [`b85c395`](https://git.odit.services/lfk/selfservice/commit/b85c3958c288293bb98df2326f73dfad1684e3cb)
- wip: general updates [`1eab535`](https://git.odit.services/lfk/selfservice/commit/1eab5353810a0a351cfc72b493c5156f55a4c9d2)
- refactor [`4af5c45`](https://git.odit.services/lfk/selfservice/commit/4af5c4545bfaad21d71bcbf91d2cd8ea53847b62)
- fix: translations [`548148e`](https://git.odit.services/lfk/selfservice/commit/548148e8982d7d146182af9f2a69de87f0b3529e)
- refactor: translations [`196b386`](https://git.odit.services/lfk/selfservice/commit/196b386d6d57e91fbb4f46091a59ba04bb6e6984)
- feat(ci)!: Switch to woodpecker [`9a3d307`](https://git.odit.services/lfk/selfservice/commit/9a3d307dfae0851eb842ad3f1c34460bca13bff1)
- i18n [`048edfb`](https://git.odit.services/lfk/selfservice/commit/048edfba89a69efd3362dd8df8b89f8780f5f3fe)
- registration brand font + more translations [`afffde8`](https://git.odit.services/lfk/selfservice/commit/afffde8fa04df88d0a8bff05d0a28550414ce385)
- feat: lfk font [`af9a168`](https://git.odit.services/lfk/selfservice/commit/af9a168f587768d8b1af8990729e743481ba687d)
- updated profile page [`4fcc38c`](https://git.odit.services/lfk/selfservice/commit/4fcc38c374553b22f92a734903df1b7a032348fa)
- 🚀Bumped version to v1.0.0 [`2285ea5`](https://git.odit.services/lfk/selfservice/commit/2285ea507069cf362baa950e7337aec72a37d4e3)
- i18n [`f296cbc`](https://git.odit.services/lfk/selfservice/commit/f296cbc1a0c9035db6546c85781be71b152264d7)
- feat(Footer): ref lfk [`6376dcb`](https://git.odit.services/lfk/selfservice/commit/6376dcb5fe7e3b1e1e639e41bc1b682036d838a0)
- feat(Home): improve ui [`75b61d9`](https://git.odit.services/lfk/selfservice/commit/75b61d991bd483aaf00871c12c9268fc6e21435b)
- refactor(ci): Make ready for new woodpecker [`780bc54`](https://git.odit.services/lfk/selfservice/commit/780bc54604998abd275f3b7d50a3849002eb243d)
- refactor: code cleanup [`ec6d252`](https://git.odit.services/lfk/selfservice/commit/ec6d252928fb84248041a3675590b85293c96133)
- chore: 2025 [`cb2f8ee`](https://git.odit.services/lfk/selfservice/commit/cb2f8eeab1a7e260df938b8aa94fa31f8e1b5efe)
- footer update [`90c085d`](https://git.odit.services/lfk/selfservice/commit/90c085db28798bbcac24eb9700285221a9bcad92)
- improved style in registered view [`1a3ab98`](https://git.odit.services/lfk/selfservice/commit/1a3ab98412b82eeb1f0dea8ea642f5fc6435c09d)
- add i18n ally snake case config [`0acda07`](https://git.odit.services/lfk/selfservice/commit/0acda07eb53a85f7b2e87a3e26d90b7cdf1fe012)
- feat(Home): improve background.jpg import [`3e289d8`](https://git.odit.services/lfk/selfservice/commit/3e289d83f9db98641f0f7f732b622dab9955f3a1)
- chore(deps): node@23.3.0 [`f71b01c`](https://git.odit.services/lfk/selfservice/commit/f71b01c39a62ef4402004e2fbcfacb37bc92ea39)
- Pin pnpm [`c36db2c`](https://git.odit.services/lfk/selfservice/commit/c36db2c18fc5f7cfd7bf5d295f3faf3931df736b)
#### [0.11.3](https://git.odit.services/lfk/selfservice/compare/0.11.2...0.11.3)
> 7 April 2023
- fix: registration code white bg [`#50`](https://git.odit.services/lfk/selfservice/issues/50)
- Pinned pnpm and lockfile [`6aca13f`](https://git.odit.services/lfk/selfservice/commit/6aca13f0cb1bc8fa43f0f09c554cec0758acd7a1)
- switched drone to kaniko with cache [`cac5103`](https://git.odit.services/lfk/selfservice/commit/cac5103d52427e777e4c3624ebb253ad7bd393d6)
- Switched dockerfile to pnpm with cache [`78fea1e`](https://git.odit.services/lfk/selfservice/commit/78fea1ea045a7281fe0a2841fc4d5f1505dcb3cf)
- 🚀Bumped version to v0.11.3 [`240f44d`](https://git.odit.services/lfk/selfservice/commit/240f44df60184c492f6cff3d864c1f9f2563ff80)
- chore(deps): pnpm@8.1.1 [`677e65f`](https://git.odit.services/lfk/selfservice/commit/677e65f44ae4bcc6f9af4732d813f337da0c51d2)
- fix(Footer): darkmode colors in lightmode [`772eca6`](https://git.odit.services/lfk/selfservice/commit/772eca64bb38ce1cf1ea1b58859dd744588a88e1)
#### [0.11.2](https://git.odit.services/lfk/selfservice/compare/0.11.1...0.11.2)
> 15 March 2023
- Added footer to every page [`b9624aa`](https://git.odit.services/lfk/selfservice/commit/b9624aa5ad57002852c84081fc710c2e977251bd)
- 🚀Bumped version to v0.11.2 [`fa51b31`](https://git.odit.services/lfk/selfservice/commit/fa51b31fe41d41b3ec9becad07ddab4cf73be051)
- Accept tos to accept privacy_policy [`09e48e7`](https://git.odit.services/lfk/selfservice/commit/09e48e771f4c0db4a7dbb898b05b347f1aad2292)
#### [0.11.1](https://git.odit.services/lfk/selfservice/compare/0.11.0...0.11.1)
> 18 February 2023
- Profile: add "---" if no data set [`659fa77`](https://git.odit.services/lfk/selfservice/commit/659fa77dca3b527d896d752386e91a167a1b8f4f)
- 🚀Bumped version to v0.11.1 [`8364321`](https://git.odit.services/lfk/selfservice/commit/8364321a7cb6a0037ee0c5055b028c4cf883fb10)
#### [0.11.0](https://git.odit.services/lfk/selfservice/compare/0.10.0...0.11.0) #### [0.11.0](https://git.odit.services/lfk/selfservice/compare/0.10.0...0.11.0)
> 3 February 2023
- pnpm migration [`a3a1e89`](https://git.odit.services/lfk/selfservice/commit/a3a1e89aa14798e1d180697f91809e282a229f23) - pnpm migration [`a3a1e89`](https://git.odit.services/lfk/selfservice/commit/a3a1e89aa14798e1d180697f91809e282a229f23)
- 🚀Bumped version to v0.11.0 [`10c9127`](https://git.odit.services/lfk/selfservice/commit/10c9127256edf2cbad1dc6690d5f4e87c32f6396)
#### [0.10.0](https://git.odit.services/lfk/selfservice/compare/0.9.0...0.10.0) #### [0.10.0](https://git.odit.services/lfk/selfservice/compare/0.9.0...0.10.0)

View File

@@ -1,11 +1,14 @@
FROM registry.odit.services/hub/library/node:19.5.0-alpine3.17 FROM node:23.4.0-alpine3.20 AS build
# FROM registry.odit.services/hub/library/node:23.3.0-alpine3.20 AS build
# ARG NPM_REGISTRY_URL=https://registry.npmjs.org
WORKDIR /app WORKDIR /app
RUN npm i -g pnpm@7
COPY . . COPY . .
# RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@9
RUN npm i -g pnpm@9
RUN pnpm i --frozen-lockfile RUN pnpm i --frozen-lockfile
RUN pnpm build RUN pnpm build
RUN pnpm postbuild
# final image # final image
FROM registry.odit.services/library/nginx-brotli:3.15 FROM registry.odit.services/library/nginx-brotli:3.15 AS final
COPY --from=0 /app/dist /usr/share/nginx/html COPY --from=build /app/dist /usr/share/nginx/html
COPY ./nginx.conf /etc/nginx/nginx.conf COPY ./nginx.conf /etc/nginx/nginx.conf

View File

@@ -2,29 +2,8 @@
runner selfservice portal runner selfservice portal
## ⚡ Development
### Requirements
- Node.js v14.16.0 or newer
- yarn package manager >= v1.22.10 < 2
### Recommended Extensions
- will be automatically recommended via `./vscode/extensions.json`
- we also provide a config for i18n-ally in the `./vscode/` folder
### Fastest Dev Environment
- You can install the [Remote - Containers](https://github.com/Microsoft/vscode-remote-release) extension and use all recommended extensions and editor settings via the provided `./devcontainer/` config
### Manual Dev Environment
```
yarn && yarn dev --open
```
## 🔨 Environment config ## 🔨 Environment config
- copy the `/public/env.sample.js` file to `/public/env.js` - copy the `/public/env.sample.js` file to `/public/env.js`
- set the required environment variables - set the required environment variables
- `documentserver_key`: url to the [document server](https://git.odit.services/lfk/document-server) instance - `documentserver_key`: url to the [document server](https://git.odit.services/lfk/document-server) instance
- `baseurl`: url to the main lfk instance - WITH TRAILING SLASH - `baseurl`: url to the main lfk instance - WITH TRAILING SLASH
- see [@lfk/deployment](https://git.odit.services/lfk/deployment) for a complete deployment guide
- `baseurl_selfservice`: location of the selfservice instance - WITH TRAILING SLASH
- e.g. path: `/selfservice/`
- e.g. url: `https://example.com/selfservice/`

View File

@@ -1,6 +0,0 @@
const fs = require('fs');
if (fs.existsSync('./dist/index.html')) {
const content = fs.readFileSync('./dist/index.html', { encoding: 'utf8' });
const newcontent = content.replace(`"/env.js"`, `"./env.js"`);
fs.writeFileSync('./dist/index.html', newcontent);
}

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon-lfk.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lauf für Kaya! - Selfservice</title> <title>Lauf für Kaya! - Selfservice</title>
</head> </head>

View File

@@ -1,16 +1,18 @@
const fs = require('fs'); import { readdirSync, readFileSync, writeFileSync } from "node:fs";
// get all language files // get all language files
const files = fs.readdirSync('./src/locales/'); const files = readdirSync("./src/locales/");
files.forEach((f) => { files.forEach((f) => {
// read file as object // read file as object
const unordered = JSON.parse(fs.readFileSync(`src/locales/${f}`)); const unordered = JSON.parse(readFileSync(`src/locales/${f}`));
// order object by keys alpabetically A-Z // order object by keys alpabetically A-Z
const ordered = Object.keys(unordered).sort().reduce((obj, key) => { const ordered = Object.keys(unordered)
obj[key] = unordered[key]; .sort()
return obj; .reduce((obj, key) => {
}, {}); obj[key] = unordered[key];
return obj;
}, {});
// format output as json for commit diff compatibility // format output as json for commit diff compatibility
const out = JSON.stringify(ordered, 0, 4); const out = JSON.stringify(ordered, 0, 4);
// write output file // write output file
fs.writeFileSync(`src/locales/${f}`, out); writeFileSync(`src/locales/${f}`, out);
}); });

View File

@@ -1,35 +1,33 @@
{ {
"name": "@odit/lfk-selfservice", "name": "@odit/lfk-selfservice",
"version": "0.11.0", "version": "1.3.1",
"type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"release": "release-it", "release": "release-it"
"postbuild": "node env_fix.js"
}, },
"dependencies": { "dependencies": {
"bwip-js": "3.2.2", "@fontsource/athiti": "5.2.5",
"marked": "2.0.3", "@odit/lfk-client": "^0.0.1",
"redaxios": "0.4.1", "@tailwindcss/vite": "4.0.14",
"toastify-js": "1.10.0", "bwip-js": "4.5.2",
"validator": "13.5.2", "marked": "15.0.7",
"vue-i18n": "9.1.4", "redaxios": "0.5.1",
"vue-toastification": "2.0.0-rc.1", "tailwindcss": "4.0.14",
"vue": "3.0.9", "toastify-js": "1.12.0",
"vue-router": "4.0.5" "validator": "13.12.0",
"vue": "3.5.13",
"vue-i18n": "10.0.5",
"vue-router": "4.5.0",
"vue-toastification": "2.0.0-rc.1"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/jit": "0.1.18", "@vitejs/plugin-vue": "5.2.3",
"@tailwindcss/aspect-ratio": "0.2.0", "autoprefixer": "10.4.21",
"@tailwindcss/forms": "0.3.2", "release-it": "18.1.2",
"@tailwindcss/line-clamp": "0.2.0", "vite": "6.2.2",
"@tailwindcss/typography": "0.4.0", "vite-plugin-vue-devtools": "7.7.2"
"@vitejs/plugin-vue": "1.2.1",
"@vue/compiler-sfc": "3.0.11",
"autoprefixer": "10.2.5",
"tailwindcss": "2.1.1",
"release-it": "14.6.1",
"vite": "2.1.5"
}, },
"release-it": { "release-it": {
"git": { "git": {

6292
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
module.exports = {
plugins: {
'@tailwindcss/jit': {},
autoprefixer: {},
},
}

View File

@@ -1,16 +1,14 @@
const config = { const config = {
// required // required
documentserver_key: '', documentserver_key: "",
// required, with trailing slash // required, with trailing slash
baseurl: '', baseurl: "",
// optional, will fallback to /selfservice/ // optional, full url, will fallback to https://lauf-fuer-kaya.de/impressum
baseurl_selfservice: '/selfservice/', 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:4010/documents', 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 baseurl_selfservice/imprint
url_imprint: '',
// optional, will fallback to baseurl_selfservice/privacy
url_privacy: '',
}; };

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

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

View File

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

View File

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -1,29 +0,0 @@
<template>
<section class="container px-4 py-32 mx-auto">
<div class="w-full mx-auto lg:w-1/3">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="h-20 feather feather-alert-triangle"
viewBox="0 0 24 24"
>
<path
d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0zM12 9v4M12 17h.01"
/>
</svg>
<p
class="mt-5 mb-3 text-xl font-bold text-black dark:text-gray-50 md:text-2xl"
>{{ $t('configuration_error') }}</p>
<p class="mb-3 text-base font-medium text-gray-700 dark:text-gray-400">
{{ $t('the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help') }}
<br />
<br />
{{ $t('if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance') }}
</p>
</div>
</section>
</template>

View File

@@ -1,38 +1,21 @@
<template> <template>
<footer class="text-gray-400 bg-gray-900 body-font"> <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 text-gray-400 sm:ml-4 sm:pl-4 sm:py-2 sm:mt-0 mt-4"> Lauf für Kaya! Selfservice<br>Copyright © 2025<br>proudly powered by
Lauf für Kaya! Selfservice - Copyright © 2023 + proudly powered by <a class="underline" target="_blank" rel="noopener,noreferrer"
<a href="https://odit.services?ref=lfk">ODIT.Services</a><br>
class="underline" <a target="_blank" rel="noopener,noreferrer" :href="[[imprint_url]]" class="underline">{{
target="_blank" $t('imprint') }}</a> <a target="_blank" rel="noopener,noreferrer" :href="[[privacy_url]]" class="underline">{{
rel="noopener,noreferrer" $t('privacy_policy') }}</a>
href="https://odit.services" </p>
>ODIT.Services</a>
</p>
<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 text-gray-400 underline"
>Impressum</a>
<a
target="_blank"
rel="noopener,noreferrer"
:href="[[privacy_url]]"
class="ml-3 text-gray-400 underline"
>Datenschutzerklärung</a>
</span>
</div>
</footer> </footer>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
imprint_url: config.url_imprint || config.baseurl_selfservice + "imprint" imprint_url: config.url_imprint || "https://lauf-fuer-kaya.de/impressum"
, privacy_url: config.url_privacy || config.baseurl_selfservice + "privacy" , privacy_url: config.url_privacy || "https://lauf-fuer-kaya.de/datenschutz"
} }
}, },
} }

View File

@@ -1,30 +0,0 @@
<template>
<h1>{{ msg }}</h1>
<p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Vite Documentation</a> |
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a>
</p>
<button @click="state.count++">count is: {{ state.count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test hot module replacement.
</p>
</template>
<script setup>
import { defineProps, reactive } from 'vue'
defineProps({
msg: String
})
const state = reactive({ count: 0 })
</script>
<style scoped>
a {
color: #42b983;
}
</style>

View File

@@ -1,109 +0,0 @@
<template>
<div class="min-h-screen flex items-center justify-center">
<div class="max-w-md w-full py-12 px-6">
<img class="mx-auto h-24 w-auto" src="/favicon.png" alt="" />
<h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center">Lauf für Kaya! - Registrieren</h1>
<p
class="mx-auto leading-relaxed text-base text-center"
>Bitte anmelden...</p>
<div class="mt-5">
<div class="rounded-md shadow-sm">
<div>
<input
aria-label="E-Mail Adresse"
name="email"
type="email"
required
class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border text-gray-900 rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
placeholder="E-Mail Adresse"
v-model="mail"
/>
</div>
<div class="-mt-px relative">
<input
aria-label="Passwort"
name="password"
type="password"
required
class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border text-gray-900 rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
placeholder="Passwort"
/>
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm">
<a href="/selfservice/reset" class="text-gray-900 underline">Passwort vergessen?</a>
</div>
</div>
</div>
<div class="mt-5">
<button
v-if="loading === false"
@click="login"
type="submit"
class="relative block w-full py-2 px-3 border border-transparent rounded-md font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm text-white"
>
<span class="absolute left-0 inset-y pl-3">
<svg class="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path
fill-rule="evenodd"
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
clip-rule="evenodd"
/>
</svg>
</span>
Log in
</button>
<button
v-if="loading === true"
type="submit"
class="relative block w-full py-2 px-3 border border-transparent rounded-md font-semibold bg-yellow-500 sm:text-sm text-black"
>
<span class="absolute left-0 inset-y pl-3">
<svg class="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path
fill-rule="evenodd"
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
clip-rule="evenodd"
/>
</svg>
</span>
Logging in...
</button>
</div>
</div>
<div class="mt-6">
<div class="relative">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div>
</div>
<div class="relative flex justify-center text-sm">
<span class="px-2 bg-white dark:bg-gray-900">Sie haben noch keinen Account?</span>
</div>
</div>
<div class="mt-6">
<a
href="/selfservice/register"
class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
>Account erstellen</a>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import axios from "redaxios";
import Toastify from "toastify-js";
let mail = ref("");
let loading = ref(false);
function login() {
loading.value = true;
axios.get("").then((res) => {
loading.value = false;
Toastify({
text: "Login läuft...",
duration: 3000,
}).showToast();
});
}
</script>

View File

@@ -1,109 +0,0 @@
<template>
<div class="min-h-screen flex items-center justify-center">
<div class="max-w-md w-full py-12 px-6">
<!-- <img class="mx-auto h-8 w-auto" src="/img/tailwindui-logo.svg" alt="" /> -->
<h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center">Login</h1>
<p
class="mx-auto leading-relaxed text-base text-center"
>Bitte anmelden...</p>
<div class="mt-5">
<div class="rounded-md shadow-sm">
<div>
<input
aria-label="E-Mail Adresse"
name="email"
type="email"
required
class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border text-gray-900 rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
placeholder="E-Mail Adresse"
v-model="mail"
/>
</div>
<div class="-mt-px relative">
<input
aria-label="Passwort"
name="password"
type="password"
required
class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border text-gray-900 rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
placeholder="Passwort"
/>
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm">
<a href="/selfservice/reset" class="text-gray-900 underline">Passwort vergessen?</a>
</div>
</div>
</div>
<div class="mt-5">
<button
v-if="loading === false"
@click="login"
type="submit"
class="relative block w-full py-2 px-3 border border-transparent rounded-md font-semibold bg-gray-800 hover:bg-gray-700 focus:bg-gray-900 focus:outline-none focus:shadow-outline sm:text-sm text-white"
>
<span class="absolute left-0 inset-y pl-3">
<svg class="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path
fill-rule="evenodd"
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
clip-rule="evenodd"
/>
</svg>
</span>
Log in
</button>
<button
v-if="loading === true"
type="submit"
class="relative block w-full py-2 px-3 border border-transparent rounded-md font-semibold bg-yellow-500 sm:text-sm text-black"
>
<span class="absolute left-0 inset-y pl-3">
<svg class="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path
fill-rule="evenodd"
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
clip-rule="evenodd"
/>
</svg>
</span>
Logging in...
</button>
</div>
</div>
<div class="mt-6">
<div class="relative">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div>
</div>
<div class="relative flex justify-center text-sm">
<span class="px-2 bg-white dark:bg-gray-900">Sie haben noch keinen Account?</span>
</div>
</div>
<div class="mt-6">
<a
href="/selfservice/register"
class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
>Account erstellen</a>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import axios from "redaxios";
import Toastify from "toastify-js";
let mail = ref("");
let loading = ref(false);
function login() {
loading.value = true;
axios.get("").then((res) => {
loading.value = false;
Toastify({
text: "Login läuft...",
duration: 3000,
}).showToast();
});
}
</script>

View File

@@ -1,32 +1,40 @@
{ {
"access_is_only_provided_via_your_email_link": "Der Zugang erfolgt über den Link, den Sie bei der Registrierung erhalten haben.", "access_is_only_provided_via_your_email_link": "Der Zugang erfolgt über den Link, den Sie bei der Registrierung erhalten haben.",
"already_have_an_account": "Sie haben bereits einen Account?", "add_sponsoring": "Sponsoring hinzufügen",
"alle_daten_geloescht": "Alle Daten gelöscht!",
"already_registered": "bereits registriert...",
"amount_per_kilometer_in_eur": "Betrag pro Kilometer (in €)", "amount_per_kilometer_in_eur": "Betrag pro Kilometer (in €)",
"apartment_suite_etc": "Addresszeile 2", "apartment_suite_etc": "Addresszeile 2",
"buergerlauf": "Bürgerlauf",
"cancel_keep_my_data": "Abbrechen, meine Daten behalten", "cancel_keep_my_data": "Abbrechen, meine Daten behalten",
"configuration_error": "Konfigurationsfehler", "configuration_error": "Konfigurationsfehler",
"confirm_delete_all_of_my_data": "Bestätigen, meine Daten löschen", "confirm_delete_all_of_my_data": "Bestätigen, meine Daten löschen",
"confirm_personal_data": "Hiermit bestätige ich die Vollständigkeit und Richtigkeit der oben genannten Angaben", "confirm_personal_data": "Hiermit bestätige ich die Vollständigkeit und Richtigkeit der oben genannten Angaben",
"current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)", "current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)",
"delete_all_of_my_data": "Meine gesamten Daten löschen",
"delete_my_data": "Meine Daten löschen", "delete_my_data": "Meine Daten löschen",
"deletion_in_progress": "Daten werden gelöscht...",
"distance": "Distanz", "distance": "Distanz",
"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",
"go_to_login": "Zum Login", "e_mail_des_sponsors": "E-Mail des Sponsors",
"error_requesting_the_login_link": "Fehler beim Anfordern des Login-Links...",
"first_lap": "👏 erste Runde",
"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.",
"imprint": "Impressum", "imprint": "Impressum",
"invalid_input_phone_number_should_be_international_format": "ungültige Eingabe... Die Telefonnummer sollte ein internationales Format haben",
"lap_time": "Rundenzeit", "lap_time": "Rundenzeit",
"lap_times": "Rundenzeiten", "lap_times": "Rundenzeiten",
"login_link_gesendet_an_user_email_value": "Login-Link gesendet an ",
"login_link_is_requested": "Login-Link wird angefordert...",
"lost_your_registration_mail": "Brauchen Sie einen neuen Login-Link?", "lost_your_registration_mail": "Brauchen Sie einen neuen Login-Link?",
"main_page_text": "Hier können Sie sich für den Lauf Für Kaya! registrieren oder ihr Läuferprofil verwalten.", "main_page_text": "Hier können Sie sich für den Lauf Für Kaya! registrieren oder ihr Läuferprofil verwalten.",
"mittelname": "Mittelname", "mittelname": "Mittelname",
"nachname": "Nachname", "nachname": "Nachname",
"no_laps_scans_were_recorded_yet": "Es wurden noch keine Runden / Scans aufgezeichnet ...", "nachname_des_sponsors": "Nachname des Sponsors",
"no_laps_scans_were_recorded_yet": "Noch keine Runden aufgezeichnet ...",
"no_sponsorings_for_you_were_recorded_yet": "Es gibt noch keine Sponsorings für dich", "no_sponsorings_for_you_were_recorded_yet": "Es gibt noch keine Sponsorings für dich",
"not_registered_yet": "Noch nicht registriert?", "not_registered_yet": "Noch nicht registriert?",
"organization": "Organisation", "organization": "Organisation",
@@ -36,25 +44,38 @@
"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",
"privacy_policy": "Datenschutzerklärung", "privacy_policy": "Datenschutzerklärung",
"profil_konnte_nicht_geladen_werden": "Profil konnte nicht geladen werden...",
"profil_konnte_nicht_geloescht_werden": "Profil konnte nicht gelöscht werden...",
"profil_wird_geloescht": "Profil wird gelöscht...",
"profile": "Profil", "profile": "Profil",
"provide_address": "Adresse angeben?", "provide_address": "Adresse angeben?",
"register": { "register": {
"register_now": "Jetzt für den Lauf für Kaya! 2023 registrieren." "register_now": "Jetzt für den Lauf für Kaya! 2025 registrieren."
}, },
"register_now": "Jetzt registrieren!", "register_now": "Jetzt registrieren!",
"register_now_small": "Jetzt registrieren", "register_now_small": "Jetzt registrieren",
"registration_local_phone_nr": "Wenn Sie eine Telefonnummer ohne Vorwahl angeben, wird Sie als deutsche Telefonnummer gewertet",
"registration_running": "Registrierung läuft...",
"registrationcode": "Registrierungscode",
"registrieren": "Registrieren", "registrieren": "Registrieren",
"registrierungscode": "Registrierungscode", "registriert": "Registriert",
"registrierungscode_generiert": "Registrierungscode generiert!",
"registrierungscode_wird_generiert": "Registrierungscode wird generiert...",
"resend_the_registration_mail": "Login-Link anfordern", "resend_the_registration_mail": "Login-Link anfordern",
"save_changes": "Änderungen speichern", "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 €)",
"strasse": "Straße", "strasse": "Straße",
"telefonnummer_des_sponsors": "Telefonnummer des Sponsors",
"the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help": "Das System ist nicht richtig konfiguriert. Bitte wenden Sie sich an den Systemadministrator, um Hilfe zu erhalten.", "the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help": "Das System ist nicht richtig konfiguriert. Bitte wenden Sie sich an den Systemadministrator, um Hilfe zu erhalten.",
"this_is_not_a_valid_international_phone_number": "Dies ist keine gültige internationale Telefonnummer", "this_is_not_a_valid_international_phone_number": "Dies ist keine gültige internationale Telefonnummer",
"tos": "AGBs",
"total": "Gesamt", "total": "Gesamt",
"total_distance": "Gesamt-Distanz",
"urkunde_generiert": "Urkunde generiert!",
"urkunde_konnte_nicht_generiert_werden": "Urkunde konnte nicht generiert werden...",
"urkunde_wird_generiert": "Urkunde wird generiert...",
"view_my_data": "Meine Läuferdaten einsehen", "view_my_data": "Meine Läuferdaten einsehen",
"vorname": "Vorname", "vorname": "Vorname",
"you_have_been_registered": "Sie wurden registriert!", "vorname_des_sponsors": "Vorname des Sponsors",
"you_have_not_provided_a_valid_access_key": "Sie haben keinen gültigen Zugangsschlüssel angegeben..." "z_b_1eur_oder_0_50eur": "z.B. 1€ ODER 0,50€"
} }

View File

@@ -1,31 +1,39 @@
{ {
"access_is_only_provided_via_your_email_link": "Access is only provided via the link you received upon registration.", "access_is_only_provided_via_your_email_link": "Access is only provided via the link you received upon registration.",
"all_data_deleted": "All Data deleted!", "add_sponsoring": "New Sponsoring",
"already_have_an_account": "Already have an account?", "alle_daten_geloescht": "all data deleted!",
"already_registered": "already registered...",
"amount_per_kilometer_in_eur": "Amount per kilometer (in €)", "amount_per_kilometer_in_eur": "Amount per kilometer (in €)",
"apartment_suite_etc": "Apartment, suite, etc.", "apartment_suite_etc": "Apartment, suite, etc.",
"buergerlauf": "Public Run",
"cancel_keep_my_data": "Cancel, keep my data", "cancel_keep_my_data": "Cancel, keep my data",
"configuration_error": "Configuration error", "configuration_error": "Configuration error",
"confirm_delete_all_of_my_data": "Confirm, delete all of my data", "confirm_delete_all_of_my_data": "Confirm, delete all of my data",
"confirm_personal_data": "I hereby confirm that the above information is complete and correct", "confirm_personal_data": "I hereby confirm that the above information is complete and correct",
"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",
"deletion_in_progress": "Deletion in progress...",
"distance": "Distance", "distance": "Distance",
"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",
"go_to_login": "Go To Login", "e_mail_des_sponsors": "E-Mail of the Sponsor",
"error_requesting_the_login_link": "Error requesting the login link...",
"first_lap": "👏 first lap",
"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.",
"imprint": "Imprint", "imprint": "Imprint",
"invalid_input_phone_number_should_be_international_format": "invalid input... phone number should be international format",
"lap_time": "Lap time", "lap_time": "Lap time",
"lap_times": "Lap times", "lap_times": "Lap times",
"login_link_gesendet_an_user_email_value": "Login-Link sent to ",
"login_link_is_requested": "Login link is requested...",
"lost_your_registration_mail": "Lost your registration mail?", "lost_your_registration_mail": "Lost your registration mail?",
"main_page_text": "Here you can register for the Lauf Für Kaya! or manage your runner profile.", "main_page_text": "Here you can register for the Lauf Für Kaya! or manage your runner profile.",
"mittelname": "Middlename", "mittelname": "Middlename",
"nachname": "Lastname", "nachname": "Lastname",
"nachname_des_sponsors": "last name of the sponsor",
"no_laps_scans_were_recorded_yet": "No laps/ scans were recorded yet...", "no_laps_scans_were_recorded_yet": "No laps/ scans were recorded yet...",
"no_sponsorings_for_you_were_recorded_yet": "No sponsorings for you were recorded yet...", "no_sponsorings_for_you_were_recorded_yet": "No sponsorings for you were recorded yet...",
"not_registered_yet": "Not registered yet?", "not_registered_yet": "Not registered yet?",
@@ -36,24 +44,38 @@
"please_provide_valid_mail": "Please provide a valid mail address.", "please_provide_valid_mail": "Please provide a valid mail address.",
"plz": "zipcode", "plz": "zipcode",
"privacy_policy": "Privacy Policy", "privacy_policy": "Privacy Policy",
"profil_konnte_nicht_geladen_werden": "could not load profile...",
"profil_konnte_nicht_geloescht_werden": "couold not delete profile...",
"profil_wird_geloescht": "deleting profile...",
"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! 2023." "register_now": "Register now for Lauf für Kaya! 2025."
}, },
"register_now": "Register now!", "register_now": "Register now!",
"register_now_small": "Register now", "register_now_small": "Register now",
"registration_local_phone_nr": "If you enter a phone number without an country code, it will be treated as a German phone number",
"registration_running": "registration is running...",
"registrationcode": "Registration Code",
"registrieren": "Register Now", "registrieren": "Register Now",
"registriert": "Registered",
"registrierungscode_generiert": "created 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",
"save_changes": "Save changes", "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 €)",
"strasse": "Street/ Block", "strasse": "Street/ Block",
"telefonnummer_des_sponsors": "Sponsor's phone number",
"the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help": "The system is not properly configured. Please contact the system administrator for help.", "the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help": "The system is not properly configured. Please contact the system administrator for help.",
"this_is_not_a_valid_international_phone_number": "This is not a valid international phone number", "this_is_not_a_valid_international_phone_number": "This is not a valid international phone number",
"tos": "Terms of Service",
"total": "Total", "total": "Total",
"total_distance": "total distance",
"urkunde_generiert": "created certificate",
"urkunde_konnte_nicht_generiert_werden": "could not create your certificate...",
"urkunde_wird_generiert": "creating certificate...",
"view_my_data": "View my data", "view_my_data": "View my data",
"vorname": "Firstname", "vorname": "Firstname",
"you_have_been_registered": "You have been registered!", "vorname_des_sponsors": "Sponsor's first name",
"you_have_not_provided_a_valid_access_key": "You have not provided a valid access key..." "z_b_1eur_oder_0_50eur": "e.g. €1 OR €0.50"
} }

View File

@@ -2,6 +2,14 @@ import { createApp } from 'vue';
import './tailwind.css'; import './tailwind.css';
import 'toastify-js/src/toastify.css'; import 'toastify-js/src/toastify.css';
import 'vue-toastification/dist/index.css'; import 'vue-toastification/dist/index.css';
// import '@fontsource/athiti';
import '@fontsource/athiti/200.css';
import '@fontsource/athiti/300.css';
import '@fontsource/athiti/400.css';
import '@fontsource/athiti/500.css';
import '@fontsource/athiti/600.css';
import '@fontsource/athiti/700.css';
//
import App from './App.vue'; import App from './App.vue';
import { routes } from './routes.js'; import { routes } from './routes.js';
import { createRouter, createWebHistory } from 'vue-router'; import { createRouter, createWebHistory } from 'vue-router';

View File

@@ -1,24 +1,17 @@
// import EnvError from './components/EnvError.vue'; import Home from "./views/Home.vue";
import Home from './views/Home.vue'; import Register from "./views/Register.vue";
import Imprint from './views/Imprint.vue'; import Profile from "./views/Profile.vue";
import Privacy from './views/Privacy.vue'; import ProfileNone from "./views/ProfileNone.vue";
import Register from './views/Register.vue';
import Profile from './views/Profile.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: config.baseurl_selfservice + '', component: Home }, { path: "/", component: Home },
{ path: config.baseurl_selfservice + 'imprint', component: Imprint }, { path: "/register", component: Register },
{ path: config.baseurl_selfservice + 'imprint/', component: Imprint }, { path: "/register/", component: Register },
{ path: config.baseurl_selfservice + 'privacy', component: Privacy }, { path: "/register/:token", component: Register, props: true },
{ path: config.baseurl_selfservice + 'privacy/', component: Privacy }, { path: "/profile", component: Profile },
{ path: config.baseurl_selfservice + 'register', component: Register }, { path: "/profile/", component: ProfileNone },
{ path: config.baseurl_selfservice + 'register/', component: Register }, { path: "/profile/:token", component: Profile, props: true },
{ path: config.baseurl_selfservice + 'register/:token', component: Register, props: true },
{ path: config.baseurl_selfservice + 'profile', component: Profile },
{ path: config.baseurl_selfservice + 'profile/', component: ProfileNone },
{ path: config.baseurl_selfservice + 'profile/:token', component: Profile, props: true }
]; ];

View File

@@ -1,3 +1,8 @@
@import 'tailwindcss/base'; @import "tailwindcss";
@import 'tailwindcss/components'; @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
@import 'tailwindcss/utilities';
* {
font-family: Athiti;
}

View File

@@ -1,30 +1,28 @@
<template> <template>
<div class="bg-cover bg-fixed m-0 h-screen" style="background-image: url('./background.jpg');"> <div class="bg-cover bg-fixed m-0 h-screen text-white"
<section class="container px-4 py-24 mx-auto"> v-bind:style='{ backgroundImage: "url(" + background_base64 + ")", }'>
<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.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 text-white md:text-6xl md:tracking-tight" Lauf Für Kaya!<br>2025</h1>
>Lauf Für Kaya!</h1> <h2 class="mb-6 text-xl font-bold leading-none tracking-normal md:text-3xl md:tracking-tight">
<p class="px-0 mb-6 text-lg text-gray-100 md:text-xl lg:px-24">Selfservice Portal</p> Selfservice Portal</h2>
<p class="px-0 mb-6 text-md text-gray-100 lg:px-24">{{ $t('main_page_text') }}</p> <p class="px-0 mb-6 text-md lg:px-24 font-medium">{{ $t('main_page_text') }}</p>
<div class="mt-6 sm:flex place-content-center"> <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 href="/register/">{{ $t('register_now') }}</a>
class="w-full sm:w-auto inline-flex 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 transition ease-in-out duration-150 xl:text-lg xl:py-4" <a href="/profile/"
href="/selfservice/register/" class="md:mt-4 mt-2 w-full block mx-auto md:w-3/4 px-6 py-3 text-base font-semibold rounded-md bg-gray-800 shadow-sm hover:bg-gray-700 focus:outline-none focus:bg-gray-700 xl:text-lg xl:py-4 border border-gray-400">{{
>{{ $t('register_now') }}</a> $t('view_my_data') }}</a>
<a
href="/selfservice/profile/"
class="mt-4 sm:ml-4 sm:mt-0 w-full sm:w-auto inline-flex px-6 py-3 border border-transparent text-base font-semibold rounded-md text-white bg-gray-800 shadow-sm hover:bg-gray-700 focus:outline-none focus:bg-gray-700 transition ease-in-out duration-150 xl:text-lg xl:py-4"
>{{ $t('view_my_data') }}</a>
</div>
</div> </div>
</section> </section>
</div> </div>
<Footer /> <div class="p-8">
<Footer />
</div>
</template> </template>
<script setup> <script setup>
import background_base64 from "../assets/background.jpg?inline";
import Footer from "@/components/Footer.vue"; import Footer from "@/components/Footer.vue";
console.log(config);
</script> </script>

View File

@@ -1,38 +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>
</template>
<style src="../simple.css">
</style>
<script>
import marked from "marked";
export default {
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 = "Error loading Imprint";
}
}
this.content = marked(await md.text());
},
}
</script>

View File

@@ -1,38 +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>
</template>
<style src="../simple.css">
</style>
<script>
import marked from "marked";
export default {
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 = "Error loading Privacy Policy";
}
}
this.content = marked(await md.text());
},
}
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,11 @@
<template> <template>
<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.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt />
<h1 <h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center">Lauf für Kaya! - {{
class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center" $t('profile')
>Lauf für Kaya! - {{ $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('you_have_not_provided_a_valid_access_key') }}
<br /> -->
{{ $t('access_is_only_provided_via_your_email_link') }} {{ $t('access_is_only_provided_via_your_email_link') }}
</p> </p>
<div class="mt-6"> <div class="mt-6">
@@ -16,9 +14,7 @@
<div class="w-full border-t border-gray-300"></div> <div class="w-full border-t border-gray-300"></div>
</div> </div>
<div class="relative flex justify-center text-sm"> <div class="relative flex justify-center text-sm">
<span <span class="px-2 bg-white dark:bg-gray-900">{{ $t('lost_your_registration_mail') }}</span>
class="px-2 bg-white dark:bg-gray-900"
>{{ $t('lost_your_registration_mail') }}</span>
</div> </div>
</div> </div>
<div class="mt-4"> <div class="mt-4">
@@ -26,28 +22,20 @@
{{ $t('e_mail_adress') }} {{ $t('e_mail_adress') }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input v-model="user_email" name="email_address" id="email_address" autocomplete="email"
v-model="user_email" :placeholder="[[$t('e_mail_adress')]]" type="email"
name="email_address"
id="email_address"
autocomplete="email"
:placeholder="[[$t('e_mail_adress')]]"
type="email"
:class="{ 'border-red-500': (!isEmail(user_email)), 'border-green-300': (isEmail(user_email)) }" :class="{ 'border-red-500': (!isEmail(user_email)), 'border-green-300': (isEmail(user_email)) }"
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 $t('please_provide_valid_mail')
v-if="!isEmail(user_email)&&user_email!==''" }}</p>
class="text-sm"
>{{ $t('please_provide_valid_mail') }}</p>
</div> </div>
<div class="mt-2"> <div class="mt-2">
<button <button :disabled="(!state.submit_enabled)"
:disabled="(!state.submit_enabled)"
:class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }" :class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }"
@click="resendMail" @click="resendMail"
class="block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 dark:bg-gray-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm" class="block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 dark:bg-gray-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm">{{
>{{ $t('resend_the_registration_mail') }}</button> $t('resend_the_registration_mail') }}</button>
</div> </div>
</div> </div>
<div class="mt-12"> <div class="mt-12">
@@ -60,23 +48,24 @@
</div> </div>
</div> </div>
<div class="mt-2"> <div class="mt-2">
<a <a href="/register/"
href="/selfservice/register/" class="text-white block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 bg-blue-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm">{{
class="text-white block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 bg-blue-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm" $t('register_now_small') }}</a>
>{{ $t('register_now_small') }}</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<Footer />
</template> </template>
<script setup> <script setup>
import { computed, ref, reactive, defineProps } from "vue"; import Footer from "@/components/Footer.vue";
import axios from "redaxios"; import { runnerSelfServiceControllerRequestNewToken } 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 { computed, reactive, ref } from "vue";
import isPostalCode from 'validator/es/lib/isPostalCode'; import { useI18n } from 'vue-i18n';
import { TYPE, useToast } from "vue-toastification"; import { TYPE, useToast } from "vue-toastification";
const { t } = useI18n()
let user_email = ref(""); let user_email = ref("");
// //
@@ -88,16 +77,15 @@ const state = reactive({
const toast = useToast(); const toast = useToast();
function resendMail() { function resendMail() {
if (isEmail(user_email.value)) { if (isEmail(user_email.value)) {
toast("Login-Link wird angefordert..."); 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("Login-Link gesendet an " + user_email.value + "!"); })
})
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
toast("Fehler beim Anfordern des Login-Links...", { type: TYPE.ERROR }); toast(t('error_requesting_the_login_link'), { type: TYPE.ERROR });
}); });
} }
} }

View File

@@ -1,12 +1,9 @@
<template> <template>
<div <div class="min-h-screen flex items-center justify-center" v-if="registrationState === 'registered'">
class="min-h-screen flex items-center justify-center"
v-if="registrationState === 'registered'"
>
<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.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt />
<h1 class="sm:text-3xl text-2xl font-medium 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! - Registriert Lauf für Kaya! - {{ $t('registriert') }}
</h1> </h1>
<p class="mx-auto leading-relaxed text-base text-center"> <p class="mx-auto leading-relaxed text-base text-center">
Bitte klicken Sie zum Fortfahren auf den Link, den wir an Bitte klicken Sie zum Fortfahren auf den Link, den wir an
@@ -16,29 +13,21 @@
</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"> <div class="max-w-md w-full py-12 px-6">
<img class="mx-auto h-24 w-auto" src="/favicon.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt />
<h1 class="sm:text-3xl text-2xl font-medium 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("registrieren") }} Lauf für Kaya! - {{ $t("registrieren") }}
</h1> </h1>
<p class="mx-auto leading-relaxed text-base text-center"> <p class="mx-auto leading-relaxed text-base text-center font-medium">
{{ $t("register.register_now") }} {{ $t("register.register_now") }}
</p> </p>
<p <p v-if="state.org_name !== ''" class="mx-auto leading-relaxed text-base text-center font-medium">
v-if="state.org_name !== ''"
class="mx-auto leading-relaxed text-base text-center"
>
{{ $t("organization") }}: {{ state.org_name }} {{ $t("organization") }}: {{ state.org_name }}
</p> </p>
<p <p v-if="state.org_name !== '' && state.org_teams.length > 0"
v-if="state.org_name !== '' && state.org_teams.length > 0" class="mx-auto leading-relaxed text-base text-center">
class="mx-auto leading-relaxed text-base text-center"
>
Team: Team:
</p> </p>
<select <select v-model="org_team" v-if="state.org_name !== '' && state.org_teams.length > 0" class="
v-model="org_team"
v-if="state.org_name !== '' && state.org_teams.length > 0"
class="
w-full w-full
border border
bg-white bg-white
@@ -53,37 +42,25 @@
form-select form-select
focus:border-purple-400 focus:outline-none focus:shadow-outline-purple focus:border-purple-400 focus:outline-none focus:shadow-outline-purple
dark:focus:shadow-outline-gray dark:focus:shadow-outline-gray
" ">
>
<option v-for="t in state.org_teams" :key="t.id" :value="t.id"> <option v-for="t in state.org_teams" :key="t.id" :value="t.id">
{{ t.name }} {{ t.name }}
</option> </option>
</select> </select>
<p <p v-if="state.org_name === ''" class="mx-auto leading-relaxed text-base text-center">
v-if="state.org_name === ''" {{ $t('buergerlauf') }}
class="mx-auto leading-relaxed text-base text-center"
>
Bürgerlauf
</p> </p>
<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 <input v-model="userdetails.firstname" name="firstname" id="first_name" autocomplete="off"
v-model="userdetails.firstname" :placeholder="[[$t('vorname')]]" type="text" :class="{
name="firstname"
id="first_name"
autocomplete="off"
:placeholder="[[$t('vorname')]]"
type="text"
:class="{
'border-red-500': !userdetails.firstname.trim(), 'border-red-500': !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
@@ -93,52 +70,18 @@
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 <input v-model="userdetails.lastname" name="lastname" id="last_name" autocomplete="off"
v-model="userdetails.lastname" :placeholder="[[$t('nachname')]]" type="text" :class="{
name="lastname"
id="last_name"
autocomplete="off"
:placeholder="[[$t('nachname')]]"
type="text"
:class="{
'border-red-500': !userdetails.lastname.trim(), 'border-red-500': !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
@@ -148,27 +91,18 @@
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 <input v-model="userdetails.mail" name="email_address" id="email_address" autocomplete="off"
v-model="userdetails.mail" :placeholder="[[$t('e_mail_adress')]]" type="email" :class="{
name="email_address"
id="email_address"
autocomplete="off"
:placeholder="[[$t('e_mail_adress')]]"
type="email"
:class="{
'border-red-500': !isEmail(userdetails.mail), 'border-red-500': !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
@@ -178,31 +112,45 @@
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="!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>
<input <div v-if="userdetails.phone !== '' && !userdetails.phone.includes('+')"
v-model="userdetails.phone" class="bg-blue-100 border border-blue-200 text-black rounded-lg p-4 mb-1" role="alert" tabindex="-1"
name="phone" aria-labelledby="hs-actions-label">
id="phone" <div class="flex">
autocomplete="off" <div class="shrink-0">
:placeholder="[[$t('phone_number')]]" <svg class="shrink-0 size-4 mt-1" xmlns="http://www.w3.org/2000/svg" width="24" height="24"
type="text" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
:class="{ 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"
:placeholder="[[$t('phone_number')]]" type="text" :class="{
'border-red-500': 'border-red-500':
!isMobilePhone(userdetails.phone) && userdetails.phone.trim(), !isPhoneOkay(userdetails.phone),
'border-green-300': 'border-green-300':
isMobilePhone(userdetails.phone) && userdetails.phone.trim(), isPhoneOkay(userdetails.phone),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
@@ -212,12 +160,8 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/> <p v-if="!isPhoneOkay(userdetails.phone)" class="text-sm">
<p
v-if="!isMobilePhone(userdetails.phone) && userdetails.phone.trim()"
class="text-sm"
>
{{ $t("this_is_not_a_valid_international_phone_number") }} {{ $t("this_is_not_a_valid_international_phone_number") }}
</p> </p>
<!-- --> <!-- -->
@@ -225,42 +169,26 @@
<div class="col-span-6"></div> <div class="col-span-6"></div>
<div class="flex items-start col-span-6"> <div class="flex items-start col-span-6">
<div class="flex items-center h-5"> <div class="flex items-center h-5">
<input <input v-model="provide_address" id="address_activated" name="address_activated" type="checkbox"
v-model="provide_address" class="h-4 w-4 text-indigo-600 border-gray-300 rounded" />
id="address_activated"
name="address_activated"
type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div> </div>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label <label for="address_activated" class="font-medium text-gray-600 select-none">{{ $t("provide_address")
for="address_activated" }}</label>
class="font-medium text-gray-400 select-none"
>{{ $t("provide_address") }}</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>
<input <input v-model="userdetails.address.street" type="text" name="street" :placeholder="[[$t('strasse')]]"
v-model="userdetails.address.street" id="street" autocomplete="street-address" :class="{
type="text"
name="street"
:placeholder="[[$t('strasse')]]"
id="street"
autocomplete="street-address"
:class="{
'border-red-500': !userdetails.address.street.trim(), 'border-red-500': !userdetails.address.street.trim(),
'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
@@ -270,23 +198,15 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
</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 <input v-model="userdetails.address.address2" type="text" name="address2"
v-model="userdetails.address.address2" :placeholder="[[$t('apartment_suite_etc')]]" id="address2" autocomplete="street-address" class="
type="text"
name="address2"
: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
@@ -296,27 +216,19 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
</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>
<input <input v-model="userdetails.address.city" type="text" name="city" :placeholder="[[$t('ort')]]" id="city"
v-model="userdetails.address.city"
type="text"
name="city"
:placeholder="[[$t('ort')]]"
id="city"
:class="{ :class="{
'border-red-500': !userdetails.address.city.trim(), 'border-red-500': !userdetails.address.city.trim(),
'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
@@ -326,22 +238,15 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
</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>
<input <input v-model="userdetails.address.zipcode" type="text" name="postal_code" :placeholder="[[$t('plz')]]"
v-model="userdetails.address.zipcode" id="postal_code" autocomplete="postal-code" :class="{
type="text"
name="postal_code"
:placeholder="[[$t('plz')]]"
id="postal_code"
autocomplete="postal-code"
:class="{
'border-red-500': !isPostalCode( 'border-red-500': !isPostalCode(
userdetails.address.zipcode, userdetails.address.zipcode,
'DE' 'DE'
@@ -350,10 +255,8 @@
userdetails.address.zipcode, userdetails.address.zipcode,
'DE' 'DE'
), ),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1
block block
w-full w-full
shadow-sm shadow-sm
@@ -363,40 +266,23 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
</div> </div>
<p <p v-if="!isPostalCode(userdetails.address.zipcode, 'DE')" class="text-sm">
v-if="!isPostalCode(userdetails.address.zipcode, 'DE')"
class="text-sm"
>
{{ $t("please_provide_a_valid_zipcode") }} {{ $t("please_provide_a_valid_zipcode") }}
</p> </p>
</div> </div>
</div> </div>
<div class="flex items-start mt-6"> <div class="flex items-start mt-6">
<div class="flex items-center h-5"> <div class="flex items-center h-5">
<input <input v-model="agb_accepted" id="agb_accepted" name="agb_accepted" type="checkbox"
v-model="agb_accepted" class="h-4 w-4 text-indigo-600 border-gray-300 rounded" />
id="agb_accepted"
name="agb_accepted"
type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div> </div>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label <label for="agb_accepted" class="font-medium text-gray-600 select-none">
for="agb_accepted" {{ $t("i_accept", { tos: $t("privacy_policy") }) }}
class="font-medium text-gray-400 select-none" <a target="_blank" rel="noreferrer,noopener" href="https://lauf-fuer-kaya.de/datenschutz/"
> class="underline">{{ $t("privacy_policy") }}</a>
{{ $t("i_accept", { tos: $t("tos") }) }}
<a
target="_blank"
rel="noreferrer,noopener"
href="https://lauf-fuer-kaya.de/datenschutz/"
class="underline"
>{{ $t("tos") }}</a
>
{{ $t("i_accept_end") }} {{ $t("i_accept_end") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
@@ -404,33 +290,21 @@
</div> </div>
<div class="flex items-start mt-6"> <div class="flex items-start mt-6">
<div class="flex items-center h-5"> <div class="flex items-center h-5">
<input <input v-model="data_confirmed" id="data_confirmed" name="data_confirmed" type="checkbox"
v-model="data_confirmed" class="h-4 w-4 text-indigo-600 border-gray-300 rounded" />
id="data_confirmed"
name="data_confirmed"
type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div> </div>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label <label for="data_confirmed" class="font-medium text-gray-600 select-none">
for="data_confirmed"
class="font-medium text-gray-400 select-none"
>
{{ $t("confirm_personal_data") }} {{ $t("confirm_personal_data") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
</div> </div>
</div> </div>
<div class="mt-6"> <div class="mt-6">
<button <button @click="login" :disabled="!state.submit_enabled" :class="{
@click="login" 'opacity-50': !state.submit_enabled,
:disabled="!state.submit_enabled" 'cursor-not-allowed': !state.submit_enabled,
:class="{ }" class="
'opacity-50': !state.submit_enabled,
'cursor-not-allowed': !state.submit_enabled,
}"
class="
text-white text-white
block block
w-full w-full
@@ -442,38 +316,42 @@
p-1 p-1
bg-blue-800 bg-blue-800
font-medium font-medium
hover:border-gray-400 not-disabled:hover:border-gray-400
focus:outline-none focus:border-gray-400 not-disabled:hover:bg-blue-600
not-disabled:cursor-pointer
not-disabled:focus:outline-none focus:border-gray-400
sm:text-sm sm:text-sm
" ">
>
{{ $t("registrieren") }} {{ $t("registrieren") }}
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="p-8">
<Footer />
</div>
</template> </template>
<script setup> <script setup>
import { computed, ref, reactive, defineProps } 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";
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);
}); });
@@ -487,6 +365,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);
@@ -500,8 +406,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 &&
@@ -514,52 +419,72 @@ 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",
}; };
} }
if (state.org_name !== "" && state.org_teams.length > 0) { if (state.org_name !== "" && state.org_teams.length > 0) {
postdata.team = org_team.value; postdata.team = org_team.value;
} }
toast("Registrierung läuft..."); toast(t('registration_running'));
const browserlocale = ( const browserlocale = (
(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("bereits registriert...", { type: TYPE.ERROR }); 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 });
}
});
}
});
} 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 });
}
});
}
});
}
} }
} }
} }

View File

@@ -1,20 +0,0 @@
<template>
<div class="min-h-screen flex items-center justify-center">
<div class="max-w-md w-full py-12 px-6">
<img class="mx-auto h-24 w-auto" src="/favicon.png" alt />
<h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center">
Lauf für Kaya! - Registriert
</h1>
<p class="mx-auto leading-relaxed text-base text-center">
Bitte klicken Sie zum Fortfahren auf den Link, den wir an
<b class="font-bold">{{ $props.mail }}</b> geschickt haben.
</p>
</div>
</div>
</template>
<script setup>
const props = defineProps({
mail: String,
});
</script>

View File

@@ -1,11 +0,0 @@
module.exports = {
purge: [ './index.html', './src/**/*.{vue,js,ts,jsx,tsx}' ],
darkMode: 'media', // or 'media' or 'class'
theme: {
extend: {}
},
variants: {
extend: {}
},
plugins: []
};

View File

@@ -1,13 +1,15 @@
import { defineConfig } from 'vite'; import { fileURLToPath, URL } from "node:url";
import vue from '@vitejs/plugin-vue';
import path from 'path'; import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import tailwindcss from "@tailwindcss/vite";
import vueDevTools from "vite-plugin-vue-devtools";
export default defineConfig({ export default defineConfig({
plugins: [ vue() ], plugins: [vue(), vueDevTools(), tailwindcss()],
base: './',
resolve: { resolve: {
alias: { alias: {
'@': path.resolve(__dirname, '/src') "@": fileURLToPath(new URL("./src", import.meta.url)),
} },
} },
}); });