Compare commits

...
71 Commits
Author SHA1 Message Date
niggl decc80fcc1 Merge branch 'dev' of git.odit.services:lfk/selfservice into dev
ci/woodpecker/push/build Pipeline failed
2023-11-06 20:25:28 +01:00
niggl 9a3d307dfa feat(ci)!: Switch to woodpecker 2023-11-06 20:25:26 +01:00
philipp 240f44df60 🚀Bumped version to v0.11.3
continuous-integration/drone/push Build is passing
2023-04-07 15:17:49 +02:00
philipp 677e65f44a chore(deps): pnpm@8.1.1 2023-04-07 15:17:27 +02:00
philipp 772eca64bb fix(Footer): darkmode colors in lightmode
continuous-integration/drone/push Build is failing
2023-04-07 15:15:26 +02:00
philipp 25d25401df fix: registration code white bg
close #50
2023-04-07 15:13:44 +02:00
niggl cac5103d52 switched drone to kaniko with cache
continuous-integration/drone/push Build is passing
2023-03-29 20:20:06 +02:00
niggl 6aca13f0cb Pinned pnpm and lockfile 2023-03-29 20:17:33 +02:00
niggl 78fea1ea04 Switched dockerfile to pnpm with cache 2023-03-29 20:17:18 +02:00
niggl fa51b31fe4 🚀Bumped version to v0.11.2
continuous-integration/drone/push Build is passing
2023-03-15 19:27:59 +01:00
niggl b9624aa5ad Added footer to every page 2023-03-15 19:27:40 +01:00
niggl 09e48e771f Accept tos to accept privacy_policy 2023-03-15 19:22:35 +01:00
philipp 8364321a7c 🚀Bumped version to v0.11.1
continuous-integration/drone/push Build is passing
2023-02-18 17:27:22 +01:00
philipp 659fa77dca Profile: add "---" if no data set
continuous-integration/drone/push Build is passing
2023-02-18 17:26:54 +01:00
philipp 10c9127256 🚀Bumped version to v0.11.0
continuous-integration/drone/push Build is passing
2023-02-03 17:24:42 +01:00
philipp a3a1e89aa1 pnpm migration
continuous-integration/drone/push Build is passing
2023-02-03 17:24:25 +01:00
philipp 5587175534 🚀Bumped version to v0.10.0
continuous-integration/drone/push Build is passing
2023-02-03 17:19:08 +01:00
philipp 8e2b355466 updated nginx config for cache busting
continuous-integration/drone/push Build is passing
2023-02-03 17:18:57 +01:00
philipp eccce0795b text cleanups + footer
continuous-integration/drone/push Build is passing
2023-02-03 17:14:01 +01:00
philipp 54540be6e1 improved profile page padding + full width registration code for easier scanning
continuous-integration/drone/push Build is passing
2023-02-03 17:04:25 +01:00
philipp 3392a2e68e 🚀Bumped version to v0.9.0
continuous-integration/drone/push Build is passing
2023-02-03 16:52:50 +01:00
philipp 8928f841dc wip: registration confirmation ui
continuous-integration/drone/push Build is passing
2023-02-03 16:52:38 +01:00
philipp 9ac14e8a5d wip: error registration ui feedback
continuous-integration/drone/push Build is passing
2023-02-03 16:48:14 +01:00
philipp 4a5b9d2569 🚀Bumped version to v0.8.3
continuous-integration/drone/push Build is passing
2023-02-03 16:44:43 +01:00
philipp 123509d0a6 fix: registration code (broke in merge)
continuous-integration/drone/push Build is passing
2023-02-03 16:44:10 +01:00
philipp 51f8d0fb42 wip: fix registration code
continuous-integration/drone/push Build is passing
2023-02-03 16:41:42 +01:00
philipp f4d1c7b053 🚀Bumped version to v0.8.2
continuous-integration/drone/push Build is passing
2023-02-03 13:51:54 +01:00
philipp ab9b400fff /profile/ dont instantly show mail format error
continuous-integration/drone/push Build is passing
2023-02-03 13:51:23 +01:00
philipp ac75828309 /profile/ move from anchor tag to button
continuous-integration/drone/push Build is passing
2023-02-03 13:51:09 +01:00
philipp c7f3a893af /profile/ toast styles
continuous-integration/drone/push Build is passing
2023-02-03 13:50:54 +01:00
philipp 30fd7ead08 /profile/ autocomplete mail
continuous-integration/drone/push Build is passing
2023-02-03 13:50:40 +01:00
philipp 64e6ef8cec /profile/ text cleanups
continuous-integration/drone/push Build is passing
2023-02-03 13:50:27 +01:00
philipp c35f943957 move /registered/ to props
continuous-integration/drone/push Build is passing
2023-02-03 13:46:18 +01:00
niggl 292e44057a 🚀Bumped version to v0.8.1
continuous-integration/drone/push Build is passing
2023-02-02 15:54:17 +01:00
niggl 20fca6794d Adjusted button text 2023-02-02 15:53:58 +01:00
niggl 8139d63715 Switched request login link api path to login (backend v13.0.0) 2023-02-02 15:52:33 +01:00
philipp 7051909bf9 🚀Bumped version to v0.8.0
continuous-integration/drone/push Build is passing
2023-02-02 00:16:29 +01:00
philipp f7a0682c33 Merge pull request 'dont autologin on register -> require mail link' (#47) from feature/46-dont-autologin-on-register-require-mail-link into dev
continuous-integration/drone/push Build is passing
Reviewed-on: #47
2023-02-01 23:16:11 +00:00
philipp c63adf557b 🚀Bumped version to v0.7.11
continuous-integration/drone/push Build is passing
2023-02-02 00:15:58 +01:00
philipp 077b33f031 Profile: improved mobile responsiveness/ design + toast clear
continuous-integration/drone/push Build is passing
2023-02-02 00:15:12 +01:00
philipp 52a6b3dc77 fix: registration code download button style
continuous-integration/drone/push Build is passing
2023-02-02 00:10:48 +01:00
philipp eb20b547e7 add /registered/?mail route
ref #46
2023-02-02 00:08:14 +01:00
niggl 8b5e1cac13 🚀Bumped version to v0.7.10
continuous-integration/drone/push Build is passing
2023-02-01 17:50:46 +01:00
niggl 20c6a420e9 Merge branch 'dev' of git.odit.services:lfk/selfservice into dev
continuous-integration/drone/push Build is passing
2023-02-01 17:48:52 +01:00
niggl 53800b4fa3 Added download for registration code 2023-02-01 17:42:58 +01:00
philipp debbd9219c 🚀Bumped version to v0.7.9
continuous-integration/drone/push Build is passing
2023-02-01 17:40:23 +01:00
philipp 9b261bf200 fix codeconfig.height
continuous-integration/drone/push Build is passing
2023-02-01 17:40:09 +01:00
philipp 713dd15312 drop jsbarcode
continuous-integration/drone/push Build is passing
2023-02-01 17:39:59 +01:00
niggl 64382880c4 Pinned version 2023-02-01 17:39:15 +01:00
niggl 9e06c46411 Configureable barcode format via bwp-js 2023-02-01 17:39:03 +01:00
philipp 8cfddb5029 migrate to bwip-js
continuous-integration/drone/push Build is passing
2023-02-01 17:36:22 +01:00
philipp e5a01bcd76 🚀Bumped version to v0.7.8
continuous-integration/drone/push Build is passing
2023-02-01 14:50:04 +01:00
philipp 851190e6a7 add barcode to profile
continuous-integration/drone/push Build is passing
2023-02-01 14:48:06 +01:00
philipp 1603a097f7 certificate generation: success toast styling
continuous-integration/drone/push Build is passing
2023-02-01 14:47:38 +01:00
philipp c2b615294e 🚀Bumped version to v0.7.7
continuous-integration/drone/push Build is passing
2023-01-31 13:47:39 +01:00
philipp c64762831f fix: registration w/o phone
continuous-integration/drone/push Build is passing
2023-01-31 13:47:32 +01:00
philipp 9b446abc1f 🚀Bumped version to v0.7.6
continuous-integration/drone/push Build is passing
2023-01-31 13:47:19 +01:00
philipp 5d974e562e update release script
continuous-integration/drone/push Build is passing
2023-01-31 13:45:45 +01:00
philipp a030f6b738 update texts of pdf generation status toasts
continuous-integration/drone/push Build is passing
close #44
2023-01-31 13:45:28 +01:00
philipp 1249248a9d 🚀Bumped version to v0.7.5
continuous-integration/drone/push Build is passing
2023-01-30 18:19:53 +01:00
philipp 0bd6d543bf update nginx base
continuous-integration/drone/push Build is passing
2023-01-30 18:18:26 +01:00
philipp 92d7bfd594 updated base node image
continuous-integration/drone/push Build is failing
2023-01-30 18:16:25 +01:00
philipp 917cb6be34 fix: relativ links
continuous-integration/drone/push Build is failing
2023-01-30 18:13:50 +01:00
philipp d159cb59be AGB link 2023-01-30 18:13:43 +01:00
philipp 9812d79d4d 2023
continuous-integration/drone/push Build is failing
2023-01-30 18:12:50 +01:00
niggl 4663214ede 🚀Bumped version to v0.7.4
continuous-integration/drone/push Build is passing
2021-04-21 15:58:49 +02:00
niggl 9c9ceaa666 Updated dronefile
continuous-integration/drone/push Build is passing
2021-04-21 15:57:45 +02:00
niggl 602d80bd14 🚀Bumped version to v0.7.3
continuous-integration/drone/push Build is passing
2021-04-21 15:38:27 +02:00
niggl 45ee4ab812 Merge pull request 'Button fixes bugfix/42-button_links' (#43) from bugfix/42-button_links into dev
continuous-integration/drone/push Build is passing
Reviewed-on: #43
2021-04-21 13:38:10 +00:00
niggl 020c310865 Fixed register button link
ref #42
2021-04-21 12:33:16 +02:00
niggl 1102d29c0e Removed useless register now button
ref #42
2021-04-21 12:31:46 +02:00
21 changed files with 4683 additions and 795 deletions
-134
View File
@@ -1,134 +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: run full license export
# depends_on: ["clone"]
# image: node:alpine
# commands:
# - yarn
# - yarn licenses:export
# - name: push new licenses file to repo
# depends_on: ["run full license export"]
# image: appleboy/drone-git-push
# settings:
# branch: dev
# commit: true
# commit_message: new license file version [CI SKIP]
# author_email: bot@odit.services
# remote: git@git.odit.services:lfk/selfservice.git
# ssh_key:
# from_secret: git_ssh
- 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
+39
View File
@@ -0,0 +1,39 @@
steps:
- name: build latest
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/selfservice
tags:
- latest
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/selfservice:latest
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
when:
branch: main
- name: build dev
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/selfservice
tags:
- dev
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/selfservice:dev
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
when:
branch: dev
when:
event: push
+20
View File
@@ -0,0 +1,20 @@
steps:
- name: build tag
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/selfservice
tags:
- "${CI_COMMIT_TAG}"
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/selfservice:latest
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
when:
event: tag
+163
View File
@@ -2,8 +2,171 @@
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.
#### [0.11.3](https://git.odit.services/lfk/selfservice/compare/0.11.2...0.11.3)
- 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)
- 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)
> 3 February 2023
- 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)
> 3 February 2023
- text cleanups + footer [`eccce07`](https://git.odit.services/lfk/selfservice/commit/eccce0795b6960aa3a2e9368de5ae4bdf80997d7)
- updated nginx config for cache busting [`8e2b355`](https://git.odit.services/lfk/selfservice/commit/8e2b355466e9a37510be8bf03311d6b28e1a0d9f)
- improved profile page padding + full width registration code for easier scanning [`54540be`](https://git.odit.services/lfk/selfservice/commit/54540be6e12ed85afc96061b8548cd4ec6700eec)
- 🚀Bumped version to v0.10.0 [`5587175`](https://git.odit.services/lfk/selfservice/commit/5587175534188e05ab43d0eed9745484e01edb63)
#### [0.9.0](https://git.odit.services/lfk/selfservice/compare/0.8.3...0.9.0)
> 3 February 2023
- wip: error registration ui feedback [`9ac14e8`](https://git.odit.services/lfk/selfservice/commit/9ac14e8a5d740fb4cd87645e69b2cfde73e4acc7)
- wip: registration confirmation ui [`8928f84`](https://git.odit.services/lfk/selfservice/commit/8928f841dcd370daf28416adbf1adbe16fa4d76f)
- 🚀Bumped version to v0.9.0 [`3392a2e`](https://git.odit.services/lfk/selfservice/commit/3392a2e68edb8fcf2aa6dd4b962abbf6ac27a414)
#### [0.8.3](https://git.odit.services/lfk/selfservice/compare/0.8.2...0.8.3)
> 3 February 2023
- fix: registration code (broke in merge) [`123509d`](https://git.odit.services/lfk/selfservice/commit/123509d0a6d15fe254e28f7a316bd6c260fe7bd2)
- 🚀Bumped version to v0.8.3 [`4a5b9d2`](https://git.odit.services/lfk/selfservice/commit/4a5b9d25698931158a602b2159b4e6c4fa129e8e)
- wip: fix registration code [`51f8d0f`](https://git.odit.services/lfk/selfservice/commit/51f8d0fb42d0dbba268799eb9385686d22fd2284)
#### [0.8.2](https://git.odit.services/lfk/selfservice/compare/0.8.1...0.8.2)
> 3 February 2023
- move /registered/ to props [`c35f943`](https://git.odit.services/lfk/selfservice/commit/c35f943957e5ba84361a437c1d945331248746d1)
- 🚀Bumped version to v0.8.2 [`f4d1c7b`](https://git.odit.services/lfk/selfservice/commit/f4d1c7b053d1e7210911772bde1b2d80a30ab225)
- /profile/ text cleanups [`64e6ef8`](https://git.odit.services/lfk/selfservice/commit/64e6ef8cec38a8193c4fb28c5f1b26ee0e4d5063)
- /profile/ move from anchor tag to button [`ac75828`](https://git.odit.services/lfk/selfservice/commit/ac75828309043532c6ab8aad63e0c40edf450459)
- /profile/ toast styles [`c7f3a89`](https://git.odit.services/lfk/selfservice/commit/c7f3a893af8705af12f2e7ae7e40197ca4c28666)
- /profile/ dont instantly show mail format error [`ab9b400`](https://git.odit.services/lfk/selfservice/commit/ab9b400fff1b421a41dd27479a81fb5e3740b9ef)
- /profile/ autocomplete mail [`30fd7ea`](https://git.odit.services/lfk/selfservice/commit/30fd7ead0833b0b3ab4e5509608aa92112151380)
#### [0.8.1](https://git.odit.services/lfk/selfservice/compare/0.8.0...0.8.1)
> 2 February 2023
- 🚀Bumped version to v0.8.1 [`292e440`](https://git.odit.services/lfk/selfservice/commit/292e44057aee9ef57a51aa9fa0372c3678b81de0)
- Adjusted button text [`20fca67`](https://git.odit.services/lfk/selfservice/commit/20fca6794dd7e0c714cd09c80a68b1d3592ab09c)
- Switched request login link api path to login (backend v13.0.0) [`8139d63`](https://git.odit.services/lfk/selfservice/commit/8139d637151c8c0184e4a98f151991b429d0a70c)
#### [0.8.0](https://git.odit.services/lfk/selfservice/compare/0.7.11...0.8.0)
> 2 February 2023
- 🚀Bumped version to v0.8.0 [`7051909`](https://git.odit.services/lfk/selfservice/commit/7051909bf960fb44b43e979ac4d304dff9ef2ec4)
- Merge pull request 'dont autologin on register -> require mail link' (#47) from feature/46-dont-autologin-on-register-require-mail-link into dev [`f7a0682`](https://git.odit.services/lfk/selfservice/commit/f7a0682c3392b8882be4a676882c8a49d55bd5fe)
- add /registered/?mail route [`eb20b54`](https://git.odit.services/lfk/selfservice/commit/eb20b547e79d352f3b7cd1b5ce7b7dbfcf8c19f7)
#### [0.7.11](https://git.odit.services/lfk/selfservice/compare/0.7.10...0.7.11)
> 2 February 2023
- Profile: improved mobile responsiveness/ design + toast clear [`077b33f`](https://git.odit.services/lfk/selfservice/commit/077b33f03180d0bd6c45becaaa63d3408c645deb)
- 🚀Bumped version to v0.7.11 [`c63adf5`](https://git.odit.services/lfk/selfservice/commit/c63adf557bcb29c8eccc05d5a83d476c75380d95)
- fix: registration code download button style [`52a6b3d`](https://git.odit.services/lfk/selfservice/commit/52a6b3dc776b806eaa8fee058a1c381ab63a8ea5)
#### [0.7.10](https://git.odit.services/lfk/selfservice/compare/0.7.9...0.7.10)
> 1 February 2023
- Configureable barcode format via bwp-js [`9e06c46`](https://git.odit.services/lfk/selfservice/commit/9e06c464118c5b5d0cd78c8b8379523bf3bfdbd4)
- Added download for registration code [`53800b4`](https://git.odit.services/lfk/selfservice/commit/53800b4fa355bb972e51e71b5b1f98772deed114)
- 🚀Bumped version to v0.7.10 [`8b5e1ca`](https://git.odit.services/lfk/selfservice/commit/8b5e1cac1353373b13cf9d570deb7cadcd437247)
- Pinned version [`6438288`](https://git.odit.services/lfk/selfservice/commit/64382880c40ba5c1e3c9004ce7fc65099849cd44)
#### [0.7.9](https://git.odit.services/lfk/selfservice/compare/0.7.8...0.7.9)
> 1 February 2023
- migrate to bwip-js [`8cfddb5`](https://git.odit.services/lfk/selfservice/commit/8cfddb502964be7edf45cdc524344ea2f7f20142)
- fix codeconfig.height [`9b261bf`](https://git.odit.services/lfk/selfservice/commit/9b261bf20023561a7c9691dff33c9a6d2b5c0cac)
- 🚀Bumped version to v0.7.9 [`debbd92`](https://git.odit.services/lfk/selfservice/commit/debbd9219cb53dbd48cf0cb7bee329b765ce4647)
- drop jsbarcode [`713dd15`](https://git.odit.services/lfk/selfservice/commit/713dd153126851e8cf1045bf5ba3ca702a39c738)
#### [0.7.8](https://git.odit.services/lfk/selfservice/compare/0.7.7...0.7.8)
> 1 February 2023
- add barcode to profile [`851190e`](https://git.odit.services/lfk/selfservice/commit/851190e6a7f8b9cccbf05e60f9b50b96c196959c)
- 🚀Bumped version to v0.7.8 [`e5a01bc`](https://git.odit.services/lfk/selfservice/commit/e5a01bcd7629164655cacd10dd1f014260c67c4b)
- certificate generation: success toast styling [`1603a09`](https://git.odit.services/lfk/selfservice/commit/1603a097f71ed85c901baf8da04cb06b86474649)
#### [0.7.7](https://git.odit.services/lfk/selfservice/compare/0.7.6...0.7.7)
> 31 January 2023
- 🚀Bumped version to v0.7.7 [`c2b6152`](https://git.odit.services/lfk/selfservice/commit/c2b615294e605db37695b13cec1158f535986911)
- fix: registration w/o phone [`c647628`](https://git.odit.services/lfk/selfservice/commit/c64762831f1e6dffc9cbc3f531e23435b455a5a9)
#### [0.7.6](https://git.odit.services/lfk/selfservice/compare/0.7.5...0.7.6)
> 31 January 2023
- update texts of pdf generation status toasts [`#44`](https://git.odit.services/lfk/selfservice/issues/44)
- 🚀Bumped version to v0.7.6 [`9b446ab`](https://git.odit.services/lfk/selfservice/commit/9b446abc1fa231bb1f5a78c545400c617eaa4af5)
- update release script [`5d974e5`](https://git.odit.services/lfk/selfservice/commit/5d974e562ed1ed5aeac579afe000c2dca945ff71)
#### [0.7.5](https://git.odit.services/lfk/selfservice/compare/0.7.4...0.7.5)
> 30 January 2023
- fix: relativ links [`917cb6b`](https://git.odit.services/lfk/selfservice/commit/917cb6be340844bcc2318bf73cec37c3c831fd5d)
- 🚀Bumped version to v0.7.5 [`1249248`](https://git.odit.services/lfk/selfservice/commit/1249248a9d3e0d72665bca6871a651f2491a4039)
- 2023 [`9812d79`](https://git.odit.services/lfk/selfservice/commit/9812d79d4de820ce791f69634c5861f4f04ad7f1)
- update nginx base [`0bd6d54`](https://git.odit.services/lfk/selfservice/commit/0bd6d543bf60b7a333b96d5d319269d4bf50db96)
- updated base node image [`92d7bfd`](https://git.odit.services/lfk/selfservice/commit/92d7bfd59407273f86809b53ffc9f67fb8ba0ec7)
- AGB link [`d159cb5`](https://git.odit.services/lfk/selfservice/commit/d159cb59be35f963abc89c42732ba6110d27830c)
#### [0.7.4](https://git.odit.services/lfk/selfservice/compare/0.7.3...0.7.4)
> 21 April 2021
- Updated dronefile [`9c9ceaa`](https://git.odit.services/lfk/selfservice/commit/9c9ceaa6664f6ea21a536a12f04e552156e81da4)
- 🚀Bumped version to v0.7.4 [`4663214`](https://git.odit.services/lfk/selfservice/commit/4663214ede3880386b5389885e32c953571290e6)
#### [0.7.3](https://git.odit.services/lfk/selfservice/compare/0.7.2...0.7.3)
> 21 April 2021
- 🚀Bumped version to v0.7.3 [`602d80b`](https://git.odit.services/lfk/selfservice/commit/602d80bd14c4bd00a24b746be1e74d9e41af0445)
- Merge pull request 'Button fixes bugfix/42-button_links' (#43) from bugfix/42-button_links into dev [`45ee4ab`](https://git.odit.services/lfk/selfservice/commit/45ee4ab81260adf5b938d9f5359d256cce879acb)
- Removed useless register now button [`1102d29`](https://git.odit.services/lfk/selfservice/commit/1102d29c0e174b7a34fc4d3e6fe32d2dfb276765)
- Fixed register button link [`020c310`](https://git.odit.services/lfk/selfservice/commit/020c310865912b8f0752069e1c7e2adf71ab9835)
#### [0.7.2](https://git.odit.services/lfk/selfservice/compare/0.7.1...0.7.2) #### [0.7.2](https://git.odit.services/lfk/selfservice/compare/0.7.1...0.7.2)
> 14 April 2021
- 🚀Bumped version to v0.7.2 [`1a3af20`](https://git.odit.services/lfk/selfservice/commit/1a3af200dd41c8cc4271690ed72bef911901ce54)
- Document generation hotfix 🐞 [`b74bea0`](https://git.odit.services/lfk/selfservice/commit/b74bea03401c672ae774aaddc6da5beb67e2890e) - Document generation hotfix 🐞 [`b74bea0`](https://git.odit.services/lfk/selfservice/commit/b74bea03401c672ae774aaddc6da5beb67e2890e)
#### [0.7.1](https://git.odit.services/lfk/selfservice/compare/0.7.0...0.7.1) #### [0.7.1](https://git.odit.services/lfk/selfservice/compare/0.7.0...0.7.1)
+8 -6
View File
@@ -1,10 +1,12 @@
FROM node:15.9.0-alpine3.13 FROM registry.odit.services/hub/library/node:19.5.0-alpine3.17 as build
ARG NPM_REGISTRY_URL=https://registry.npmjs.org
WORKDIR /app WORKDIR /app
COPY . . COPY . .
RUN yarn RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
RUN yarn build RUN pnpm i && pnpm build && pnpm postbuild
RUN yarn postbuild
# final image # final image
FROM fholzer/nginx-brotli:v1.19.1 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
+29 -23
View File
@@ -7,15 +7,21 @@ http {
error_page 404 /index.html; error_page 404 /index.html;
root /usr/share/nginx/html; root /usr/share/nginx/html;
location / { location / {
rewrite /register/(.*) /$1 break; rewrite /register/(.*) /$1 break;
rewrite /profile/(.*) /$1 break; rewrite /profile/(.*) /$1 break;
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
} }
location ~* \.(?:ico|css|gif|jpe?g|png)$ { location ~* \.(?:ico|css|gif|jpe?g|png)$ {
rewrite /register/(.*) /$1 break; rewrite /register/(.*) /$1 break;
rewrite /profile/(.*) /$1 break; rewrite /profile/(.*) /$1 break;
expires 1y; expires 1y;
add_header Pragma public; add_header Pragma public;
@@ -35,24 +41,24 @@ http {
gzip_buffers 16 8k; gzip_buffers 16 8k;
gzip_http_version 1.1; gzip_http_version 1.1;
gzip_types application/javascript gzip_types application/javascript
application/rss+xml application/rss+xml
application/vnd.ms-fontobject application/vnd.ms-fontobject
application/x-font application/x-font
application/x-font-opentype application/x-font-opentype
application/x-font-otf application/x-font-otf
application/x-font-truetype application/x-font-truetype
application/x-font-ttf application/x-font-ttf
application/x-javascript application/x-javascript
application/xhtml+xml application/xhtml+xml
application/xml application/xml
font/opentype font/opentype
font/otf font/otf
font/ttf font/ttf
image/svg+xml image/svg+xml
image/x-icon image/x-icon
text/css text/css
text/javascript text/javascript
text/plain text/plain
text/xml; text/xml;
} }
} }
+55 -51
View File
@@ -1,51 +1,55 @@
{ {
"name": "@odit/lfk-selfservice", "name": "@odit/lfk-selfservice",
"version": "0.7.2", "version": "0.11.3",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"release": "release-it --only-version", "release": "release-it",
"postbuild": "node env_fix.js" "postbuild": "node env_fix.js"
}, },
"dependencies": { "engines": {
"marked": "2.0.3", "pnpm": "8.1.1"
"redaxios": "0.4.1", },
"toastify-js": "1.10.0", "dependencies": {
"validator": "13.5.2", "bwip-js": "3.2.2",
"vue-i18n": "9.1.4", "marked": "2.0.3",
"vue-toastification": "2.0.0-rc.1", "redaxios": "0.4.1",
"vue": "3.0.9", "toastify-js": "1.10.0",
"vue-router": "4.0.5" "validator": "13.5.2",
}, "vue-i18n": "9.1.4",
"devDependencies": { "vue-toastification": "2.0.0-rc.1",
"@tailwindcss/jit": "0.1.18", "vue": "3.0.9",
"@tailwindcss/aspect-ratio": "0.2.0", "vue-router": "4.0.5"
"@tailwindcss/forms": "0.3.2", },
"@tailwindcss/line-clamp": "0.2.0", "devDependencies": {
"@tailwindcss/typography": "0.4.0", "@tailwindcss/jit": "0.1.18",
"@vitejs/plugin-vue": "1.2.1", "@tailwindcss/aspect-ratio": "0.2.0",
"@vue/compiler-sfc": "3.0.11", "@tailwindcss/forms": "0.3.2",
"autoprefixer": "10.2.5", "@tailwindcss/line-clamp": "0.2.0",
"tailwindcss": "2.1.1", "@tailwindcss/typography": "0.4.0",
"release-it": "14.6.1", "@vitejs/plugin-vue": "1.2.1",
"vite": "2.1.5" "@vue/compiler-sfc": "3.0.11",
}, "autoprefixer": "10.2.5",
"release-it": { "tailwindcss": "2.1.1",
"git": { "release-it": "14.6.1",
"commit": true, "vite": "2.1.5"
"requireCleanWorkingDir": false, },
"commitMessage": "🚀Bumped version to v${version}", "release-it": {
"requireBranch": "dev", "git": {
"push": false, "commit": true,
"tag": true, "requireCleanWorkingDir": false,
"tagName": null, "commitMessage": "🚀Bumped version to v${version}",
"tagAnnotation": "v${version}" "requireBranch": "dev",
}, "push": true,
"npm": { "tag": true,
"publish": false "tagName": null,
}, "tagAnnotation": "v${version}"
"hooks": { },
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node order_i18n.js && git add src/locales" "npm": {
} "publish": false
} },
} "hooks": {
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node order_i18n.js && git add src/locales"
}
}
}
+3145
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -7,8 +7,10 @@ const config = {
baseurl_selfservice: '/selfservice/', baseurl_selfservice: '/selfservice/',
// full url (including fqdn) // full url (including fqdn)
baseurl_documentserver: 'http://localhost:4010/documents', baseurl_documentserver: 'http://localhost:4010/documents',
// optional, will fallback to code128
code_format: 'ean13',
// optional, will fallback to baseurl_selfservice/imprint // optional, will fallback to baseurl_selfservice/imprint
url_imprint: '', url_imprint: '',
// optional, will fallback to baseurl_selfservice/privacy // optional, will fallback to baseurl_selfservice/privacy
url_privacy: '' url_privacy: '',
}; };
+2 -2
View File
@@ -1,8 +1,8 @@
<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"> <div class="container px-5 py-8 mx-auto flex items-center sm:flex-row flex-col">
<p class="text-sm text-gray-400 sm:ml-4 sm:pl-4 sm:py-2 sm:mt-0 mt-4"> <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 - Copyright © 2021 + proudly powered by Lauf für Kaya! Selfservice - Copyright © 2023 + proudly powered by
<a <a
class="underline" class="underline"
target="_blank" target="_blank"
+3 -3
View File
@@ -29,7 +29,7 @@
placeholder="Passwort" placeholder="Passwort"
/> />
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm"> <div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm">
<a href="./reset" class="text-gray-900 underline">Passwort vergessen?</a> <a href="/selfservice/reset" class="text-gray-900 underline">Passwort vergessen?</a>
</div> </div>
</div> </div>
</div> </div>
@@ -80,7 +80,7 @@
</div> </div>
<div class="mt-6"> <div class="mt-6">
<a <a
href="./register" 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" 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> >Account erstellen</a>
</div> </div>
@@ -101,7 +101,7 @@ function login() {
axios.get("").then((res) => { axios.get("").then((res) => {
loading.value = false; loading.value = false;
Toastify({ Toastify({
text: "This is a toast", text: "Login läuft...",
duration: 3000, duration: 3000,
}).showToast(); }).showToast();
}); });
+3 -3
View File
@@ -29,7 +29,7 @@
placeholder="Passwort" placeholder="Passwort"
/> />
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm"> <div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm">
<a href="./reset" class="text-gray-900 underline">Passwort vergessen?</a> <a href="/selfservice/reset" class="text-gray-900 underline">Passwort vergessen?</a>
</div> </div>
</div> </div>
</div> </div>
@@ -80,7 +80,7 @@
</div> </div>
<div class="mt-6"> <div class="mt-6">
<a <a
href="./register" 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" 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> >Account erstellen</a>
</div> </div>
@@ -101,7 +101,7 @@ function login() {
axios.get("").then((res) => { axios.get("").then((res) => {
loading.value = false; loading.value = false;
Toastify({ Toastify({
text: "This is a toast", text: "Login läuft...",
duration: 3000, duration: 3000,
}).showToast(); }).showToast();
}); });
+7 -5
View File
@@ -1,11 +1,11 @@
{ {
"access_is_only_provided_via_your_email_link": "Der Zugang erfolgt nur ü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?", "already_have_an_account": "Sie haben bereits einen Account?",
"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",
"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ätigung, meine gesamten 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_all_of_my_data": "Meine gesamten Daten löschen",
@@ -13,6 +13,7 @@
"deletion_in_progress": "Daten werden gelöscht...", "deletion_in_progress": "Daten werden gelöscht...",
"distance": "Distanz", "distance": "Distanz",
"download_certificate": "Urkunde herunterladen", "download_certificate": "Urkunde herunterladen",
"download_registrationcode": "Registrierungscode herunterladen",
"e_mail_adress": "E-Mail Adresse", "e_mail_adress": "E-Mail Adresse",
"go_to_login": "Zum Login", "go_to_login": "Zum Login",
"i_accept": "Ich habe die ", "i_accept": "Ich habe die ",
@@ -21,7 +22,7 @@
"imprint": "Impressum", "imprint": "Impressum",
"lap_time": "Rundenzeit", "lap_time": "Rundenzeit",
"lap_times": "Rundenzeiten", "lap_times": "Rundenzeiten",
"lost_your_registration_mail": "Haben Sie Ihre Registrierungsmail verloren?", "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",
@@ -38,12 +39,13 @@
"profile": "Profil", "profile": "Profil",
"provide_address": "Adresse angeben?", "provide_address": "Adresse angeben?",
"register": { "register": {
"register_now": "Jetzt für den Lauf für Kaya! 2021 registrieren." "register_now": "Jetzt für den Lauf für Kaya! 2023 registrieren."
}, },
"register_now": "Jetzt registrieren!", "register_now": "Jetzt registrieren!",
"register_now_small": "Jetzt registrieren", "register_now_small": "Jetzt registrieren",
"registrieren": "Registrieren", "registrieren": "Registrieren",
"resend_the_registration_mail": "Registrierungsmail erneut versenden", "registrierungscode": "Registrierungscode",
"resend_the_registration_mail": "Login-Link anfordern",
"save_changes": "Änderungen speichern", "save_changes": "Änderungen speichern",
"sponsoring": "Sponsoring", "sponsoring": "Sponsoring",
"strasse": "Straße", "strasse": "Straße",
+3 -2
View File
@@ -13,6 +13,7 @@
"deletion_in_progress": "Deletion in progress...", "deletion_in_progress": "Deletion in progress...",
"distance": "Distance", "distance": "Distance",
"download_certificate": "Download certificate", "download_certificate": "Download certificate",
"download_registrationcode": "Download registrationcode",
"e_mail_adress": "mail address", "e_mail_adress": "mail address",
"go_to_login": "Go To Login", "go_to_login": "Go To Login",
"i_accept": "I have read and accepted the ", "i_accept": "I have read and accepted the ",
@@ -38,12 +39,12 @@
"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! 2021." "register_now": "Register now for Lauf für Kaya! 2023."
}, },
"register_now": "Register now!", "register_now": "Register now!",
"register_now_small": "Register now", "register_now_small": "Register now",
"registrieren": "Register Now", "registrieren": "Register Now",
"resend_the_registration_mail": "Resend the registration mail", "resend_the_registration_mail": "Send me a login link",
"save_changes": "Save changes", "save_changes": "Save changes",
"sponsoring": "Sponsoring", "sponsoring": "Sponsoring",
"strasse": "Street/ Block", "strasse": "Street/ Block",
+2 -2
View File
@@ -11,10 +11,10 @@
<div class="mt-6 sm:flex place-content-center"> <div class="mt-6 sm:flex place-content-center">
<a <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" 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"
href="./register/" href="/selfservice/register/"
>{{ $t('register_now') }}</a> >{{ $t('register_now') }}</a>
<a <a
href="./profile/" 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" 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> >{{ $t('view_my_data') }}</a>
</div> </div>
+4 -1
View File
@@ -9,15 +9,18 @@
<div class="mx-auto prose" v-html="content"></div> <div class="mx-auto prose" v-html="content"></div>
</div> </div>
</section> </section>
<Footer></Footer>
</template> </template>
<style src="../simple.css"> <style src="../simple.css">
</style> </style>
<script> <script>
import marked from "marked"; import marked from "marked";
import Footer from "@/components/Footer.vue";
export default { export default {
components: {Footer},
data() { data() {
return { return {
content: "" content: "",
} }
}, },
async beforeMount() { async beforeMount() {
+3
View File
@@ -9,12 +9,15 @@
<div class="mx-auto prose" v-html="content"></div> <div class="mx-auto prose" v-html="content"></div>
</div> </div>
</section> </section>
<Footer></Footer>
</template> </template>
<style src="../simple.css"> <style src="../simple.css">
</style> </style>
<script> <script>
import marked from "marked"; import marked from "marked";
import Footer from "@/components/Footer.vue";
export default { export default {
components: {Footer},
data() { data() {
return { return {
content: "" content: ""
+500 -122
View File
@@ -3,19 +3,82 @@
<section class="text-white body-font"> <section class="text-white body-font">
<div class="container mx-auto flex items-center md:flex-row flex-col"> <div class="container mx-auto flex items-center md:flex-row flex-col">
<div <div
class="flex flex-col md:pr-10 md:mb-0 mb-6 pr-0 w-full md:w-auto md:text-left text-center text-black dark:text-gray-200" class="
flex flex-col
md:pr-10 md:mb-0
mb-6
pr-0
w-full
md:w-auto md:text-left
text-center text-black
dark:text-gray-200
"
> >
<p <p
class="text-3xl font-bold whitespace-nowrap" class="text-3xl font-bold whitespace-nowrap"
v-text="(state.firstname || '') + ' ' + (state.middlename || '') + ' ' + (state.lastname || '')" v-text="
(state.firstname || '') +
' ' +
(state.middlename || '') +
' ' +
(state.lastname || '')
"
></p> ></p>
<p class="text-md whitespace-nowrap">{{ state.group }}</p> <p class="text-md whitespace-nowrap">{{ state.group }}</p>
</div> </div>
<div class="inline-flex md:ml-auto md:mr-0 mx-auto items-center"> <div class="inline-flex md:ml-auto md:mr-0 mx-auto items-center">
<div v-if="(state.delete_active === false)"> <div v-if="state.delete_active === false">
<button <button
type="button" type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-sm py-2.5 px-5 rounded-md bg-blue-500 hover:bg-blue-600 hover:shadow-lg" class="
focus:border-black focus:ring-2 focus:ring-black
text-white text-sm
py-2.5
px-5
rounded-md
bg-blue-500
hover:bg-blue-600 hover:shadow-lg
w-full
md:w-auto
mb-1
md:mr-1
"
@click="get_registration"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-download"
style="display: inline; height: 1rem; vertical-align: sub"
>
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" />
</svg>
{{ $t("download_registrationcode") }}
</button>
<button
type="button"
class="
focus:border-black focus:ring-2 focus:ring-black
text-white text-sm
py-2.5
px-5
rounded-md
bg-blue-500
hover:bg-blue-600 hover:shadow-lg
w-full
md:w-auto
mb-1
md:mr-1
"
@click="get_certificate" @click="get_certificate"
> >
<svg <svg
@@ -29,18 +92,32 @@
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" stroke-linejoin="round"
class="feather feather-download" class="feather feather-download"
style="display: inline;height: 1rem;vertical-align: sub;" style="display: inline; height: 1rem; vertical-align: sub"
> >
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="7 10 12 15 17 10" /> <polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" /> <line x1="12" y1="15" x2="12" y2="3" />
</svg> </svg>
{{ $t('download_certificate') }} {{ $t("download_certificate") }}
</button> </button>
<button <button
type="button" type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-sm py-2.5 px-5 rounded-md bg-red-600 hover:bg-red-700 hover:shadow-lg ml-1" class="
@click="() => { state.delete_active = true }" focus:border-black focus:ring-2 focus:ring-black
text-white text-sm
py-2.5
px-5
rounded-md
bg-red-600
hover:bg-red-700 hover:shadow-lg
w-full
md:w-auto
"
@click="
() => {
state.delete_active = true;
}
"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -53,7 +130,7 @@
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" stroke-linejoin="round"
class="feather feather-download" class="feather feather-download"
style="display: inline;height: 1rem;vertical-align: sub;" style="display: inline; height: 1rem; vertical-align: sub"
> >
<path d="M0 0h24v24H0z" /> <path d="M0 0h24v24H0z" />
<path <path
@@ -61,14 +138,30 @@
d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z" d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z"
/> />
</svg> </svg>
{{ $t('delete_my_data') }} {{ $t("delete_my_data") }}
</button> </button>
</div> </div>
<div v-if="(state.delete_active === true)"> <div v-if="state.delete_active === true">
<button <button
type="button" type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-sm py-2.5 px-5 rounded-md bg-blue-500 hover:bg-blue-600 hover:shadow-lg" class="
@click="() => { state.delete_active = false }" focus:border-black focus:ring-2 focus:ring-black
text-white text-sm
py-2.5
px-5
rounded-md
mb-1
md:mb-auto
w-full
md:w-auto
bg-blue-500
hover:bg-blue-600 hover:shadow-lg
"
@click="
() => {
state.delete_active = false;
}
"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -81,16 +174,30 @@
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" stroke-linejoin="round"
class="feather feather-download" class="feather feather-download"
style="display: inline;height: 1rem;vertical-align: sub;" style="display: inline; height: 1rem; vertical-align: sub"
> >
<path fill="none" d="M0 0h24v24H0z" /> <path fill="none" d="M0 0h24v24H0z" />
<path fill="currentColor" d="M12 11l5-5 1 1-5 5 5 5-1 1-5-5-5 5-1-1 5-5-5-5 1-1z" /> <path
fill="currentColor"
d="M12 11l5-5 1 1-5 5 5 5-1 1-5-5-5 5-1-1 5-5-5-5 1-1z"
/>
</svg> </svg>
{{ $t('cancel_keep_my_data') }} {{ $t("cancel_keep_my_data") }}
</button> </button>
<button <button
type="button" type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-sm py-2.5 px-5 rounded-md bg-red-600 hover:bg-red-700 hover:shadow-lg ml-1" class="
focus:border-black focus:ring-2 focus:ring-black
text-white text-sm
py-2.5
px-5
rounded-md
w-full
md:w-auto
bg-red-600
hover:bg-red-700 hover:shadow-lg
md:ml-1
"
@click="delete_me" @click="delete_me"
> >
<svg <svg
@@ -104,7 +211,7 @@
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" stroke-linejoin="round"
class="feather feather-download" class="feather feather-download"
style="display: inline;height: 1rem;vertical-align: sub;" style="display: inline; height: 1rem; vertical-align: sub"
> >
<path d="M0 0h24v24H0z" /> <path d="M0 0h24v24H0z" />
<path <path
@@ -112,79 +219,187 @@
d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z" d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z"
/> />
</svg> </svg>
{{ $t('confirm_delete_all_of_my_data') }} {{ $t("confirm_delete_all_of_my_data") }}
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<div class="flex flex-wrap"> <div class="flex flex-wrap">
<div class="w-full p-4"> <div class="w-full">
<div class="flex flex-wrap flex-col w-full tabs"> <div class="flex flex-wrap flex-col w-full tabs">
<div class="flex lg:flex-wrap flex-row lg:space-x-2"> <div class="flex lg:flex-wrap flex-row lg:space-x-2">
<div class="flex-none"> <div class="flex-none">
<button <button
@click="() => { state.activetab = 'profile' }" @click="
:class="{ 'tab-active border-b-2 font-medium border-blue-500': (state.activetab === 'profile') }" () => {
state.activetab = 'profile';
}
"
:class="{
'tab-active border-b-2 font-medium border-blue-500':
state.activetab === 'profile',
}"
class="tab tab-underline py-4 px-6 block" class="tab tab-underline py-4 px-6 block"
type="button" type="button"
>{{ $t('profile') }}</button> >
{{ $t("profile") }}
</button>
</div> </div>
<div class="flex-none"> <div class="flex-none">
<button <button
@click="() => { state.activetab = 'laptimes' }" @click="
:class="{ 'tab-active border-b-2 font-medium border-blue-500': (state.activetab === 'laptimes') }" () => {
state.activetab = 'laptimes';
}
"
:class="{
'tab-active border-b-2 font-medium border-blue-500':
state.activetab === 'laptimes',
}"
class="tab tab-underline py-4 px-6 block" class="tab tab-underline py-4 px-6 block"
type="button" type="button"
>{{ $t('lap_times') }}</button> >
{{ $t("lap_times") }}
</button>
</div> </div>
<div class="flex-none"> <div class="flex-none">
<button <button
@click="() => { state.activetab = 'sponsorings' }" @click="
:class="{ 'tab-active border-b-2 font-medium border-blue-500': (state.activetab === 'sponsorings') }" () => {
state.activetab = 'sponsorings';
}
"
:class="{
'tab-active border-b-2 font-medium border-blue-500':
state.activetab === 'sponsorings',
}"
class="tab tab-underline py-4 px-6 block" class="tab tab-underline py-4 px-6 block"
type="button" type="button"
>{{ $t('sponsoring') }}</button> >
{{ $t("sponsoring") }}
</button>
</div> </div>
</div> </div>
<div v-if="(state.activetab === 'profile')" class="tab-content block"> <div v-if="state.activetab === 'profile'" class="tab-content block">
<div class="py-4 w-full"> <div class="py-4 w-full">
<div class="flex flex-col"> <div class="flex flex-col">
<form class="form flex flex-wrap w-full"> <form class="form flex flex-wrap w-full">
<div class="w-full"> <div class="w-full">
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t('vorname') }}</div> <div class="text-lg">{{ $t("registrierungscode") }}</div>
<img
class="w-full md:w-auto mb-2 bg-white p-2"
alt="Registrierungscode"
:src="state.barcode"
/>
<div class="text-lg">{{ $t("vorname") }}</div>
<p <p
class="h-10 w-full dark:bg-gray-800 rounded text-base outline-none dark:text-gray-100 text-gray-600 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" class="
v-text="state.firstname" h-10
w-full
dark:bg-gray-800
rounded
text-base
outline-none
dark:text-gray-100
text-gray-600
py-1
px-3
leading-8
transition-colors
duration-200
ease-in-out
"
v-text="state.firstname || '---'"
/> />
</div> </div>
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t('mittelname') }}</div> <div class="text-lg">{{ $t("mittelname") }}</div>
<p <p
class="h-10 w-full dark:bg-gray-800 rounded text-base outline-none dark:text-gray-100 text-gray-600 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" class="
v-text="state.middlename" h-10
w-full
dark:bg-gray-800
rounded
text-base
outline-none
dark:text-gray-100
text-gray-600
py-1
px-3
leading-8
transition-colors
duration-200
ease-in-out
"
v-text="state.middlename || '---'"
/> />
</div> </div>
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t('nachname') }}</div> <div class="text-lg">{{ $t("nachname") }}</div>
<p <p
class="h-10 w-full dark:bg-gray-800 rounded text-base outline-none dark:text-gray-100 text-gray-600 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" class="
v-text="state.lastname" h-10
w-full
dark:bg-gray-800
rounded
text-base
outline-none
dark:text-gray-100
text-gray-600
py-1
px-3
leading-8
transition-colors
duration-200
ease-in-out
"
v-text="state.lastname || '---'"
/> />
</div> </div>
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t('e_mail_adress') }}</div> <div class="text-lg">{{ $t("e_mail_adress") }}</div>
<p <p
class="h-10 w-full dark:bg-gray-800 rounded text-base outline-none dark:text-gray-100 text-gray-600 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" class="
v-text="state.email" h-10
w-full
dark:bg-gray-800
rounded
text-base
outline-none
dark:text-gray-100
text-gray-600
py-1
px-3
leading-8
transition-colors
duration-200
ease-in-out
"
v-text="state.email || '---'"
/> />
</div> </div>
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t('phone_number') }}</div> <div class="text-lg">{{ $t("phone_number") }}</div>
<p <p
class="h-10 w-full dark:bg-gray-800 rounded text-base outline-none dark:text-gray-100 text-gray-600 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" class="
v-text="state.phone" h-10
w-full
dark:bg-gray-800
rounded
text-base
outline-none
dark:text-gray-100
text-gray-600
py-1
px-3
leading-8
transition-colors
duration-200
ease-in-out
"
v-text="state.phone || '---'"
/> />
</div> </div>
</div> </div>
@@ -192,7 +407,7 @@
</div> </div>
</div> </div>
</div> </div>
<div v-if="(state.activetab === 'laptimes')" class="tab-content block"> <div v-if="state.activetab === 'laptimes'" class="tab-content block">
<div class="py-4 w-full"> <div class="py-4 w-full">
<section class="text-gray-400 dark:bg-gray-900 body-font"> <section class="text-gray-400 dark:bg-gray-900 body-font">
<div class="container mx-auto"> <div class="container mx-auto">
@@ -202,15 +417,37 @@
class="table-auto w-full text-left whitespace-no-wrap" class="table-auto w-full text-left whitespace-no-wrap"
> >
<thead <thead
class="text-black bg-gray-300 dark:text-white text-sm dark:bg-gray-800" class="
text-black
bg-gray-300
dark:text-white
text-sm
dark:bg-gray-800
"
> >
<tr> <tr>
<th <th
class="px-4 py-3 title-font tracking-wider font-medium" class="
>{{ $t('distance') }}</th> px-4
py-3
title-font
tracking-wider
font-medium
"
>
{{ $t("distance") }}
</th>
<th <th
class="px-4 py-3 title-font tracking-wider font-medium" class="
>{{ $t('lap_time') }}</th> px-4
py-3
title-font
tracking-wider
font-medium
"
>
{{ $t("lap_time") }}
</th>
</tr> </tr>
</thead> </thead>
<tbody class="text-gray-900 dark:text-gray-50"> <tbody class="text-gray-900 dark:text-gray-50">
@@ -222,20 +459,32 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div v-else class="text-center font-bold text-black dark:text-white text-2xl"> <div
v-else
class="
text-center
font-bold
text-black
dark:text-white
text-2xl
"
>
<img <img
src="../assets/empty_laps.svg" src="../assets/empty_laps.svg"
style="height:25rem; margin:0 auto;" style="height: 25rem; margin: 0 auto"
:alt="[[$t('no_laps_scans_were_recorded_yet')]]" :alt="[[$t('no_laps_scans_were_recorded_yet')]]"
/> />
{{ $t('no_laps_scans_were_recorded_yet') }} {{ $t("no_laps_scans_were_recorded_yet") }}
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</div> </div>
</div> </div>
<div v-if="(state.activetab === 'sponsorings')" class="tab-content block"> <div
v-if="state.activetab === 'sponsorings'"
class="tab-content block"
>
<div class="py-4 w-full"> <div class="py-4 w-full">
<section class="text-gray-400 dark:bg-gray-900 body-font"> <section class="text-gray-400 dark:bg-gray-900 body-font">
<div class="container mx-auto"> <div class="container mx-auto">
@@ -245,16 +494,48 @@
class="table-auto w-full text-left whitespace-no-wrap" class="table-auto w-full text-left whitespace-no-wrap"
> >
<thead <thead
class="text-black bg-gray-300 dark:text-white text-sm dark:bg-gray-800" class="
text-black
bg-gray-300
dark:text-white
text-sm
dark:bg-gray-800
"
> >
<tr> <tr>
<th class="px-4 py-3 title-font tracking-wider font-medium">Name</th>
<th <th
class="px-4 py-3 title-font tracking-wider font-medium" class="
>{{ $t('amount_per_kilometer_in_eur') }}</th> px-4
py-3
title-font
tracking-wider
font-medium
"
>
Name
</th>
<th <th
class="px-4 py-3 title-font tracking-wider font-medium" class="
>{{ $t('current_total_amount_in_eur') }}</th> px-4
py-3
title-font
tracking-wider
font-medium
"
>
{{ $t("amount_per_kilometer_in_eur") }}
</th>
<th
class="
px-4
py-3
title-font
tracking-wider
font-medium
"
>
{{ $t("current_total_amount_in_eur") }}
</th>
</tr> </tr>
</thead> </thead>
<tbody class="text-gray-900 dark:text-gray-50"> <tbody class="text-gray-900 dark:text-gray-50">
@@ -268,51 +549,86 @@
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span <span
v-text="(s.amountPerDistance / 100) v-text="
.toFixed(2) (s.amountPerDistance / 100)
.toLocaleString('de-DE', { valute: 'EUR' })" .toFixed(2)
></span>€ .toLocaleString('de-DE', { valute: 'EUR' })
"
></span
>€
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span <span
v-text="(s.amount / 100) v-text="
.toFixed(2) (s.amount / 100)
.toLocaleString('de-DE', { valute: 'EUR' })" .toFixed(2)
></span>€ .toLocaleString('de-DE', { valute: 'EUR' })
"
></span
>€
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tfoot class="text-gray-900 dark:text-gray-50"> <tfoot class="text-gray-900 dark:text-gray-50">
<tr> <tr>
<td class="px-4 py-3">{{ $t('total') }}</td> <td class="px-4 py-3">{{ $t("total") }}</td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span <span
v-text="(state.sponsorings.reduce(function(sum, current) { v-text="
return sum + current.amountPerDistance; (
}, 0) / 100) state.sponsorings.reduce(function (
.toFixed(2) sum,
.toLocaleString('de-DE', { valute: 'EUR' })" current
></span>€ ) {
return sum + current.amountPerDistance;
},
0) / 100
)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })
"
></span
>€
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span <span
v-text="(state.sponsorings.reduce(function(sum, current) { v-text="
return sum + current.amount; (
}, 0) / 100) state.sponsorings.reduce(function (
.toFixed(2) sum,
.toLocaleString('de-DE', { valute: 'EUR' })" current
></span>€ ) {
return sum + current.amount;
},
0) / 100
)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })
"
></span
>€
</td> </td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
<div v-else class="text-center font-bold text-black dark:text-white text-2xl"> <div
v-else
class="
text-center
font-bold
text-black
dark:text-white
text-2xl
"
>
<img <img
src="../assets/empty_laps.svg" src="../assets/empty_laps.svg"
style="height:25rem; margin:0 auto;" style="height: 25rem; margin: 0 auto"
:alt="[[$t('no_sponsorings_for_you_were_recorded_yet')]]" :alt="[
[$t('no_sponsorings_for_you_were_recorded_yet')],
]"
/> />
{{ $t('no_sponsorings_for_you_were_recorded_yet') }} {{ $t("no_sponsorings_for_you_were_recorded_yet") }}
</div> </div>
</div> </div>
</div> </div>
@@ -322,15 +638,41 @@
</div> </div>
</div> </div>
</div> </div>
<!-- -->
<Footer></Footer>
</div> </div>
</template> </template>
<script setup> <script setup>
import { reactive } from "vue"; import { reactive } from "vue";
import { useToast } from "vue-toastification"; import { TYPE, useToast } from "vue-toastification";
import axios from "redaxios"; import axios from "redaxios";
import bwipjs from "bwip-js";
import Footer from "@/components/Footer.vue";
function textToBase64Barcode(text) {
const canvas = document.createElement("canvas");
let codeconfig = {
bcid: config.code_format || "code39",
text: `${text}`,
scale: 3,
includetext: false,
textxalign: "center",
backgroundcolor: "ffffff",
};
if (
codeconfig.bcid === "code39" ||
codeconfig.bcid === "code128" ||
codeconfig.bcid === "ean13"
) {
codeconfig.height = 10;
}
bwipjs.toCanvas(canvas, codeconfig);
return canvas.toDataURL("image/png");
}
const state = reactive({ const state = reactive({
barcode: "",
phone: "", phone: "",
email: "", email: "",
firstname: "", firstname: "",
@@ -341,14 +683,15 @@ const state = reactive({
group: "", group: "",
activetab: "profile", activetab: "profile",
delete_active: false, delete_active: false,
fullobject: {} fullobject: {},
}) });
const toast = useToast(); const toast = useToast();
const props = defineProps({ const props = defineProps({
token: String token: String,
}) });
const accesstoken = atob(props.token); const accesstoken = atob(props.token);
axios.get(`${config.baseurl}api/runners/me/${accesstoken}`) axios
.get(`${config.baseurl}api/runners/me/${accesstoken}`)
.then(({ data }) => { .then(({ data }) => {
state.phone = data.phone; state.phone = data.phone;
state.email = data.email; state.email = data.email;
@@ -358,65 +701,100 @@ axios.get(`${config.baseurl}api/runners/me/${accesstoken}`)
state.group = data.group; state.group = data.group;
state.sponsorings = data.distanceDonations; state.sponsorings = data.distanceDonations;
state.fullobject = data; state.fullobject = data;
}).catch((error) => { state.barcode = textToBase64Barcode(data.id ?? "???");
toast.error("An error occured while loading your profile data");
}) })
axios.get(`${config.baseurl}api/runners/me/${accesstoken}/scans`) .catch((error) => {
toast.clear();
toast.error("Profil konnte nicht geladen werden...");
});
axios
.get(`${config.baseurl}api/runners/me/${accesstoken}/scans`)
.then(({ data }) => { .then(({ data }) => {
data.map(function(s) { data.map(function (s) {
s.lapTime = Math.floor(s.lapTime / 60) + 'min ' + (Math.floor(s.lapTime % 60) + "").padStart(2, "0") + "s" s.lapTime =
s.distance = Math.floor(s.distance / 1000) + 'km ' + (Math.floor(s.distance % 1000) + "").padStart(3, "0") + "m" Math.floor(s.lapTime / 60) +
"min " +
(Math.floor(s.lapTime % 60) + "").padStart(2, "0") +
"s";
s.distance =
Math.floor(s.distance / 1000) +
"km " +
(Math.floor(s.distance % 1000) + "").padStart(3, "0") +
"m";
return s; return s;
}) });
data.filter(s => s.valid === true); data.filter((s) => s.valid === true);
state.scans = data; state.scans = data;
}).catch((error) => {
toast.error("An error occured while loading your profile data");
}) })
.catch((error) => {
toast.error("Profil konnte nicht geladen werden...");
});
function delete_me() { function delete_me() {
toast("Deletion in progress..."); toast.clear();
let url = `${config.baseurl}api/runners/me/${accesstoken}?force=true` toast("Profil wird gelöscht...");
axios.delete(url) let url = `${config.baseurl}api/runners/me/${accesstoken}?force=true`;
axios
.delete(url)
.then(() => { .then(() => {
toast("All Data deleted!"); toast.clear();
toast("Alle Daten gelöscht!");
location.replace(`${config.baseurl_selfservice}`); location.replace(`${config.baseurl_selfservice}`);
}) })
.catch((error) => { .catch((error) => {
toast.error("An error occured while deleting your profile data"); toast.clear();
toast.error("Profil konnte nicht gelöscht werden...");
}); });
} }
function get_certificate() { function get_certificate() {
toast("Generation in progress..."); toast("Urkunde wird generiert...");
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2); const browserlocale = (
(navigator.languages && navigator.languages[0]) ||
""
).substr(0, 2);
let url = `${config.baseurl_documentserver}certificates?locale=${browserlocale}&download=true&key=${config.documentserver_key}`; let url = `${config.baseurl_documentserver}certificates?locale=${browserlocale}&download=true&key=${config.documentserver_key}`;
let postdata = Object.assign({}, state.fullobject); let postdata = Object.assign({}, state.fullobject);
postdata.group = { postdata.group = {
name: postdata.group name: postdata.group,
} };
postdata = [postdata] postdata = [postdata];
axios.post(url, postdata, { axios
responseType: "blob" .post(url, postdata, {
}) responseType: "blob",
})
.then((response) => { .then((response) => {
console.log(response) console.log(response);
if (response.status != "200") { if (response.status != "200") {
toast.error("An error occured while generateing your certificate!"); toast.error("Urkunde konnte nicht generiert werden...");
} else { } else {
var fileURL = window.URL.createObjectURL(new Blob([response.data], { type: 'application/pdf' })); var fileURL = window.URL.createObjectURL(
var fileLink = document.createElement('a'); new Blob([response.data], { type: "application/pdf" })
);
var fileLink = document.createElement("a");
fileLink.href = fileURL; fileLink.href = fileURL;
fileLink.setAttribute('download', 'Certificate.pdf'); fileLink.setAttribute("download", "Certificate.pdf");
document.body.appendChild(fileLink); document.body.appendChild(fileLink);
fileLink.click(); fileLink.click();
fileLink.remove(); fileLink.remove();
toast("Document generated!"); toast.clear();
toast("Urkunde generiert!", { type: TYPE.SUCCESS });
} }
}) })
.catch((err) => { .catch((err) => {
console.error(err); console.error(err);
toast.error("An error occured while generating your certificate"); toast.clear();
toast.error("Urkunde konnte nicht generiert werden...");
}); });
} }
function get_registration() {
toast.clear();
toast("Registrierungscode wird generiert...");
var a = document.createElement("a");
a.href = state.barcode;
a.download = "LfK23_Registrierungscode.png";
a.click();
toast.clear();
toast("Registrierungscode generiert!", { type: TYPE.SUCCESS });
}
</script> </script>
+105 -103
View File
@@ -1,104 +1,106 @@
<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.png" alt />
<h1 <h1
class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center" class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center"
>Lauf für Kaya! - {{ $t('profile') }}</h1> >Lauf für Kaya! - {{ $t('profile') }}</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') }} <!-- {{ $t('you_have_not_provided_a_valid_access_key') }}
<br /> <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">
<div class="relative"> <div class="relative">
<div class="absolute inset-0 flex items-center"> <div class="absolute inset-0 flex items-center">
<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" class="px-2 bg-white dark:bg-gray-900"
>{{ $t('lost_your_registration_mail') }}</span> >{{ $t('lost_your_registration_mail') }}</span>
</div> </div>
</div> </div>
<div class="mt-4"> <div class="mt-4">
<label for="email_address" class="block font-medium"> <label for="email_address" class="block font-medium">
{{ $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" v-model="user_email"
name="email_address" name="email_address"
id="email_address" id="email_address"
autocomplete="off" autocomplete="email"
:placeholder="[[$t('e_mail_adress')]]" :placeholder="[[$t('e_mail_adress')]]"
type="email" 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 <p
v-if="!isEmail(user_email)" v-if="!isEmail(user_email)&&user_email!==''"
class="text-sm" class="text-sm"
>{{ $t('please_provide_valid_mail') }}</p> >{{ $t('please_provide_valid_mail') }}</p>
</div> </div>
<div class="mt-2"> <div class="mt-2">
<a <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') }}</a> >{{ $t('resend_the_registration_mail') }}</button>
</div> </div>
</div> </div>
<div class="mt-12"> <div class="mt-12">
<div class="relative"> <div class="relative">
<div class="absolute inset-0 flex items-center"> <div class="absolute inset-0 flex items-center">
<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 class="px-2 bg-white dark:bg-gray-900">{{ $t('not_registered_yet') }}</span> <span class="px-2 bg-white dark:bg-gray-900">{{ $t('not_registered_yet') }}</span>
</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>
</template> <Footer></Footer>
</template>
<script setup>
import { computed, ref, reactive, defineProps } from "vue"; <script setup>
import axios from "redaxios"; import { computed, ref, reactive, defineProps } from "vue";
import isEmail from 'validator/es/lib/isEmail'; import axios from "redaxios";
import isMobilePhone from 'validator/es/lib/isMobilePhone'; import isEmail from 'validator/es/lib/isEmail';
import isPostalCode from 'validator/es/lib/isPostalCode'; import isMobilePhone from 'validator/es/lib/isMobilePhone';
import { useToast } from "vue-toastification"; import isPostalCode from 'validator/es/lib/isPostalCode';
import { TYPE, useToast } from "vue-toastification";
let user_email = ref(""); import Footer from "@/components/Footer.vue";
//
const state = reactive({ let user_email = ref("");
org_name: "", //
org_teams: [], const state = reactive({
submit_enabled: computed(() => isEmail(user_email.value)) org_name: "",
}) org_teams: [],
const toast = useToast(); submit_enabled: computed(() => isEmail(user_email.value))
function resendMail() { })
if (isEmail(user_email.value)) { const toast = useToast();
toast("sending password reset mail..."); function resendMail() {
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2); if (isEmail(user_email.value)) {
axios.post(`${config.baseurl}api/runners/forgot?mail=${user_email.value}&locale=${browserlocale}`) toast("Login-Link wird angefordert...");
.then(({ data }) => { const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
console.log(data); axios.post(`${config.baseurl}api/runners/login?mail=${user_email.value}&locale=${browserlocale}`)
toast("sent password reset mail to " + user_email.value + "!"); .then(({ data }) => {
}) console.log(data);
.catch((error) => { toast("Login-Link gesendet an " + user_email.value + "!");
console.log(error); })
toast("user does not exist..."); .catch((error) => {
}); console.log(error);
} toast("Fehler beim Anfordern des Login-Links...", { type: TYPE.ERROR });
} });
}
}
</script> </script>
+567 -337
View File
@@ -1,338 +1,568 @@
<template> <template>
<div class="min-h-screen flex items-center justify-center"> <div
<div class="max-w-md w-full py-12 px-6"> class="min-h-screen flex items-center justify-center"
<img class="mx-auto h-24 w-auto" src="/favicon.png" alt /> v-if="registrationState === 'registered'"
<h1 >
class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center" <div class="max-w-md w-full py-12 px-6">
>Lauf für Kaya! - {{ $t('registrieren') }}</h1> <img class="mx-auto h-24 w-auto" src="/favicon.png" alt />
<p class="mx-auto leading-relaxed text-base text-center">{{ $t('register.register_now') }}</p> <h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center">
<p Lauf für Kaya! - Registriert
v-if="state.org_name !== ''" </h1>
class="mx-auto leading-relaxed text-base text-center" <p class="mx-auto leading-relaxed text-base text-center">
>{{ $t('organization') }}: {{ state.org_name }}</p> Bitte klicken Sie zum Fortfahren auf den Link, den wir an
<p <b class="font-bold">{{ userdetails.mail }}</b> geschickt haben.
v-if="state.org_name !== '' && state.org_teams.length > 0" </p>
class="mx-auto leading-relaxed text-base text-center" </div>
>Team:</p> </div>
<select <div class="min-h-screen flex items-center justify-center" v-else>
v-model="org_team" <div class="max-w-md w-full py-12 px-6">
v-if="state.org_name !== '' && state.org_teams.length > 0" <img class="mx-auto h-24 w-auto" src="/favicon.png" alt />
class="w-full border bg-white rounded px-3 py-2 outline-none block mt-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 form-select focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray" <h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center">
> Lauf für Kaya! - {{ $t("registrieren") }}
<option v-for="t in state.org_teams" :key="t.id" :value="t.id">{{ t.name }}</option> </h1>
</select> <p class="mx-auto leading-relaxed text-base text-center">
<p {{ $t("register.register_now") }}
v-if="state.org_name === ''" </p>
class="mx-auto leading-relaxed text-base text-center" <p
>Bürgerlauf</p> v-if="state.org_name !== ''"
<div class="mt-4"> class="mx-auto leading-relaxed text-base text-center"
<label for="first_name" class="block font-medium"> >
{{ $t('vorname') }} {{ $t("organization") }}: {{ state.org_name }}
<span class="font-bold">*</span> </p>
</label> <p
<input v-if="state.org_name !== '' && state.org_teams.length > 0"
v-model="userdetails.firstname" class="mx-auto leading-relaxed text-base text-center"
name="firstname" >
id="first_name" Team:
autocomplete="off" </p>
:placeholder="[[$t('vorname')]]" <select
type="text" v-model="org_team"
:class="{ 'border-red-500': (!userdetails.firstname.trim()), 'border-green-300': (userdetails.firstname.trim()) }" v-if="state.org_name !== '' && state.org_teams.length > 0"
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" class="
/> w-full
<!-- --> border
<label for="middle_name" class="block font-medium">{{ $t('mittelname') }}</label> bg-white
<input rounded
v-model="userdetails.middlename" px-3
name="middlename" py-2
id="middle_name" outline-none
autocomplete="off" block
:placeholder="[[$t('mittelname')]]" mt-1
type="text" text-sm
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" dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700
/> form-select
<!-- --> focus:border-purple-400 focus:outline-none focus:shadow-outline-purple
<label for="last_name" class="block font-medium"> dark:focus:shadow-outline-gray
{{ $t('nachname') }} "
<span class="font-bold">*</span> >
</label> <option v-for="t in state.org_teams" :key="t.id" :value="t.id">
<input {{ t.name }}
v-model="userdetails.lastname" </option>
name="lastname" </select>
id="last_name" <p
autocomplete="off" v-if="state.org_name === ''"
:placeholder="[[$t('nachname')]]" class="mx-auto leading-relaxed text-base text-center"
type="text" >
:class="{ 'border-red-500': (!userdetails.lastname.trim()), 'border-green-300': (userdetails.lastname.trim()) }" Bürgerlauf
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" </p>
/> <div class="mt-4">
<!-- --> <label for="first_name" class="block font-medium">
<label for="email_address" class="block font-medium"> {{ $t("vorname") }}
{{ $t('e_mail_adress') }} <span class="font-bold">*</span>
<span class="font-bold">*</span> </label>
</label> <input
<input v-model="userdetails.firstname"
v-model="userdetails.mail" name="firstname"
name="email_address" id="first_name"
id="email_address" autocomplete="off"
autocomplete="off" :placeholder="[[$t('vorname')]]"
:placeholder="[[$t('e_mail_adress')]]" type="text"
type="email" :class="{
:class="{ 'border-red-500': (!isEmail(userdetails.mail)), 'border-green-300': (isEmail(userdetails.mail)) }" 'border-red-500': !userdetails.firstname.trim(),
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" 'border-green-300': userdetails.firstname.trim(),
/> }"
<p v-if="!isEmail(userdetails.mail)" class="text-sm">{{ $t('please_provide_valid_mail') }}</p> class="
<!-- --> dark:bg-gray-800
<label for="phone" class="select-none block font-medium">{{ $t('phone_number') }}</label> mt-1
<input block
v-model="userdetails.phone" w-full
name="phone" shadow-sm
id="phone" sm:text-sm
autocomplete="off" border-gray-300 border-2
:placeholder="[[$t('phone_number')]]" bg-gray-50
type="text" text-gray-500
:class="{ 'border-red-500': (!isMobilePhone(userdetails.phone) && userdetails.phone.trim()), 'border-green-300': (isMobilePhone(userdetails.phone) && userdetails.phone.trim()) }" rounded-md
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-2
/> "
<p />
v-if="(!isMobilePhone(userdetails.phone) && userdetails.phone.trim())" <!-- -->
class="text-sm" <label for="middle_name" class="block font-medium">{{
>{{ $t('this_is_not_a_valid_international_phone_number') }}</p> $t("mittelname")
<!-- --> }}</label>
<div class="grid grid-cols-6 mt-6"> <input
<div class="col-span-6"></div> v-model="userdetails.middlename"
<div class="flex items-start col-span-6"> name="middlename"
<div class="flex items-center h-5"> id="middle_name"
<input autocomplete="off"
v-model="provide_address" :placeholder="[[$t('mittelname')]]"
id="address_activated" type="text"
name="address_activated" class="
type="checkbox" dark:bg-gray-800
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" mt-1
/> block
</div> w-full
<div class="ml-3 text-sm"> shadow-sm
<label sm:text-sm
for="address_activated" border-gray-300 border-2
class="font-medium text-gray-400 select-none" bg-gray-50
>{{ $t('provide_address') }}</label> text-gray-500
</div> rounded-md
</div> p-2
<div v-if="provide_address === true" class="col-span-6"> "
<div class="col-span-6"> />
<label for="street" class="block font-medium"> <!-- -->
{{ $t('strasse') }} <label for="last_name" class="block font-medium">
<span class="font-bold">*</span> {{ $t("nachname") }}
</label> <span class="font-bold">*</span>
<input </label>
v-model="userdetails.address.street" <input
type="text" v-model="userdetails.lastname"
name="street" name="lastname"
:placeholder="[[$t('strasse')]]" id="last_name"
id="street" autocomplete="off"
autocomplete="street-address" :placeholder="[[$t('nachname')]]"
:class="{ 'border-red-500': (!userdetails.address.street.trim()), 'border-green-300': (userdetails.address.street.trim()) }" 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" :class="{
/> 'border-red-500': !userdetails.lastname.trim(),
</div> 'border-green-300': userdetails.lastname.trim(),
<div class="col-span-6"> }"
<label for="address2" class="block font-medium">{{ $t('apartment_suite_etc') }}</label> class="
<input dark:bg-gray-800
v-model="userdetails.address.address2" mt-1
type="text" block
name="address2" w-full
:placeholder="[[$t('apartment_suite_etc')]]" shadow-sm
id="address2" sm:text-sm
autocomplete="street-address" border-gray-300 border-2
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" bg-gray-50
/> text-gray-500
</div> rounded-md
<div class="col-span-6 sm:col-span-6 lg:col-span-2"> p-2
<label for="city" class="block font-medium"> "
{{ $t('ort') }} />
<span class="font-bold">*</span> <!-- -->
</label> <label for="email_address" class="block font-medium">
<input {{ $t("e_mail_adress") }}
v-model="userdetails.address.city" <span class="font-bold">*</span>
type="text" </label>
name="city" <input
:placeholder="[[$t('ort')]]" v-model="userdetails.mail"
id="city" name="email_address"
:class="{ 'border-red-500': (!userdetails.address.city.trim()), 'border-green-300': (userdetails.address.city.trim()) }" id="email_address"
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" autocomplete="off"
/> :placeholder="[[$t('e_mail_adress')]]"
</div> type="email"
<div class="col-span-6 sm:col-span-3 lg:col-span-2"> :class="{
<label for="postal_code" class="block font-medium"> 'border-red-500': !isEmail(userdetails.mail),
{{ $t('plz') }} 'border-green-300': isEmail(userdetails.mail),
<span class="font-bold">*</span> }"
</label> class="
<input dark:bg-gray-800
v-model="userdetails.address.zipcode" mt-1
type="text" block
name="postal_code" w-full
:placeholder="[[$t('plz')]]" shadow-sm
id="postal_code" sm:text-sm
autocomplete="postal-code" border-2
:class="{ 'border-red-500': (!isPostalCode(userdetails.address.zipcode, 'DE')), 'border-green-300': (isPostalCode(userdetails.address.zipcode, 'DE')) }" bg-gray-50
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" text-gray-500
/> rounded-md
</div> p-2
<p "
v-if="!isPostalCode(userdetails.address.zipcode, 'DE')" />
class="text-sm" <p v-if="!isEmail(userdetails.mail)" class="text-sm">
>{{ $t('please_provide_a_valid_zipcode') }}</p> {{ $t("please_provide_valid_mail") }}
</div> </p>
</div> <!-- -->
<div class="flex items-start mt-6"> <label for="phone" class="select-none block font-medium">{{
<div class="flex items-center h-5"> $t("phone_number")
<input }}</label>
v-model="agb_accepted" <input
id="agb_accepted" v-model="userdetails.phone"
name="agb_accepted" name="phone"
type="checkbox" id="phone"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" autocomplete="off"
/> :placeholder="[[$t('phone_number')]]"
</div> type="text"
<div class="ml-3 text-sm"> :class="{
<label for="agb_accepted" class="font-medium text-gray-400 select-none"> 'border-red-500':
{{ $t('i_accept', { tos: $t('tos') }) }} !isMobilePhone(userdetails.phone) && userdetails.phone.trim(),
<a 'border-green-300':
target="_blank" isMobilePhone(userdetails.phone) && userdetails.phone.trim(),
rel="noreferrer,noopener" }"
href class="
class="underline" dark:bg-gray-800
>{{ $t('tos') }}</a> mt-1
{{ $t('i_accept_end') }} block
<span class="font-bold">*</span> w-full
</label> shadow-sm
</div> sm:text-sm
</div> border-2
<div class="flex items-start mt-6"> bg-gray-50
<div class="flex items-center h-5"> text-gray-500
<input rounded-md
v-model="data_confirmed" p-2
id="data_confirmed" "
name="data_confirmed" />
type="checkbox" <p
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" v-if="!isMobilePhone(userdetails.phone) && userdetails.phone.trim()"
/> class="text-sm"
</div> >
<div class="ml-3 text-sm"> {{ $t("this_is_not_a_valid_international_phone_number") }}
<label for="data_confirmed" class="font-medium text-gray-400 select-none"> </p>
{{ $t('confirm_personal_data') }} <!-- -->
<span class="font-bold">*</span> <div class="grid grid-cols-6 mt-6">
</label> <div class="col-span-6"></div>
</div> <div class="flex items-start col-span-6">
</div> <div class="flex items-center h-5">
<div class="mt-6"> <input
<button v-model="provide_address"
@click="login" id="address_activated"
:disabled="(!state.submit_enabled)" name="address_activated"
:class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }" type="checkbox"
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="h-4 w-4 text-indigo-600 border-gray-300 rounded"
>{{ $t('registrieren') }}</button> />
</div> </div>
</div> <div class="ml-3 text-sm">
<div class="mt-6"> <label
<div class="relative"> for="address_activated"
<div class="absolute inset-0 flex items-center"> class="font-medium text-gray-400 select-none"
<div class="w-full border-t border-gray-300"></div> >{{ $t("provide_address") }}</label
</div> >
<div class="relative flex justify-center text-sm"> </div>
<span class="px-2 bg-white dark:bg-gray-900">{{ $t('already_have_an_account') }}</span> </div>
</div> <div v-if="provide_address === true" class="col-span-6">
</div> <div class="col-span-6">
<div class="mt-6"> <label for="street" class="block font-medium">
<a {{ $t("strasse") }}
href="./login" <span class="font-bold">*</span>
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" </label>
>{{ $t('go_to_login') }}</a> <input
</div> v-model="userdetails.address.street"
</div> type="text"
</div> name="street"
</div> :placeholder="[[$t('strasse')]]"
</template> id="street"
autocomplete="street-address"
<script setup> :class="{
import { computed, ref, reactive, defineProps } from "vue"; 'border-red-500': !userdetails.address.street.trim(),
import axios from "redaxios"; 'border-green-300': userdetails.address.street.trim(),
import isEmail from 'validator/es/lib/isEmail'; }"
import isMobilePhone from 'validator/es/lib/isMobilePhone'; class="
import isPostalCode from 'validator/es/lib/isPostalCode'; dark:bg-gray-800
import { useToast } from "vue-toastification"; mt-1
block
const props = defineProps({ w-full
token: String shadow-sm
}) sm:text-sm
if (props.token) { border-gray-300 border-2
axios.get(`${config.baseurl}api/organizations/selfservice/${props.token}`) bg-gray-50
.then(({ data }) => { text-gray-500
state.org_name = data.name; rounded-md
state.org_teams = data.teams; p-2
org_team.value = data.teams[0]?.id; "
}) />
.catch((error) => { </div>
console.log(error); <div class="col-span-6">
}); <label for="address2" class="block font-medium">{{
} $t("apartment_suite_etc")
}}</label>
let userdetails = ref({ firstname: "", lastname: "", middlename: "", mail: "", phone: "", address: { street: "", address2: "", city: "", zipcode: "" } }); <input
let provide_address = ref(false); v-model="userdetails.address.address2"
let agb_accepted = ref(false); type="text"
let data_confirmed = ref(false); name="address2"
let org_team = ref(""); :placeholder="[[$t('apartment_suite_etc')]]"
// id="address2"
const state = reactive({ autocomplete="street-address"
org_name: "", class="
org_teams: [], dark:bg-gray-800
submit_enabled: computed(() => agb_accepted.value === true && data_confirmed.value === true && (isMobilePhone(userdetails.value.phone) || !userdetails.value.phone.trim()) && isEmail(userdetails.value.mail) mt-1
&& userdetails.value.firstname block
&& userdetails.value.lastname && (provide_address.value === false || provide_address.value === true && (userdetails.value.address.street.trim() && userdetails.value.address.city.trim() && isPostalCode(userdetails.value.address.zipcode, "DE")))) w-full
}) shadow-sm
const toast = useToast(); sm:text-sm
function login() { border-gray-300 border-2
userdetails = userdetails.value; bg-gray-50
if (userdetails.phone === "" || isMobilePhone(userdetails.phone)) { text-gray-500
if (isEmail(userdetails.mail)) { rounded-md
let postdata = { p-2
"email": userdetails.mail, "
"firstname": userdetails.firstname, />
"middlename": userdetails.middlename, </div>
"lastname": userdetails.lastname, <div class="col-span-6 sm:col-span-6 lg:col-span-2">
"address": {} <label for="city" class="block font-medium">
} {{ $t("ort") }}
if (isMobilePhone(userdetails.phone)) { <span class="font-bold">*</span>
postdata.phone = userdetails.phone; </label>
} <input
if (provide_address.value === true) { v-model="userdetails.address.city"
postdata.address = { type="text"
address1: userdetails.address.street, name="city"
address2: userdetails.address.address2 || "", :placeholder="[[$t('ort')]]"
city: userdetails.address.city, id="city"
postalcode: userdetails.address.zipcode, :class="{
country: "DE", 'border-red-500': !userdetails.address.city.trim(),
} 'border-green-300': userdetails.address.city.trim(),
} }"
if (state.org_name !== '' && state.org_teams.length > 0) { class="
postdata.team = org_team.value; dark:bg-gray-800
} mt-1
toast("registration in progress..."); block
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2); w-full
let url = `${config.baseurl}api/runners/register/?locale=${browserlocale}`; shadow-sm
if (props.token) { sm:text-sm
url = `${config.baseurl}api/runners/register/${props.token}/?locale=${browserlocale}` border-gray-300 border-2
} bg-gray-50
axios.post(url, postdata) text-gray-500
.then(({ data }) => { rounded-md
const token = btoa(data.token); p-2
// alert(token); "
location.replace(`${config.baseurl_selfservice}profile/${token}`); />
}) </div>
.catch((error) => { <div class="col-span-6 sm:col-span-3 lg:col-span-2">
console.log(error); <label for="postal_code" class="block font-medium">
}); {{ $t("plz") }}
} <span class="font-bold">*</span>
} </label>
} <input
v-model="userdetails.address.zipcode"
type="text"
name="postal_code"
:placeholder="[[$t('plz')]]"
id="postal_code"
autocomplete="postal-code"
:class="{
'border-red-500': !isPostalCode(
userdetails.address.zipcode,
'DE'
),
'border-green-300': isPostalCode(
userdetails.address.zipcode,
'DE'
),
}"
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
"
/>
</div>
<p
v-if="!isPostalCode(userdetails.address.zipcode, 'DE')"
class="text-sm"
>
{{ $t("please_provide_a_valid_zipcode") }}
</p>
</div>
</div>
<div class="flex items-start mt-6">
<div class="flex items-center h-5">
<input
v-model="agb_accepted"
id="agb_accepted"
name="agb_accepted"
type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div>
<div class="ml-3 text-sm">
<label
for="agb_accepted"
class="font-medium text-gray-400 select-none"
>
{{ $t("i_accept", { tos: $t("privacy_policy") }) }}
<a
target="_blank"
rel="noreferrer,noopener"
href="https://lauf-fuer-kaya.de/datenschutz/"
class="underline"
>{{ $t("privacy_policy") }}</a
>
{{ $t("i_accept_end") }}
<span class="font-bold">*</span>
</label>
</div>
</div>
<div class="flex items-start mt-6">
<div class="flex items-center h-5">
<input
v-model="data_confirmed"
id="data_confirmed"
name="data_confirmed"
type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div>
<div class="ml-3 text-sm">
<label
for="data_confirmed"
class="font-medium text-gray-400 select-none"
>
{{ $t("confirm_personal_data") }}
<span class="font-bold">*</span>
</label>
</div>
</div>
<div class="mt-6">
<button
@click="login"
:disabled="!state.submit_enabled"
:class="{
'opacity-50': !state.submit_enabled,
'cursor-not-allowed': !state.submit_enabled,
}"
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("registrieren") }}
</button>
</div>
</div>
</div>
</div>
<Footer></Footer>
</template>
<script setup>
import { computed, ref, reactive, defineProps } from "vue";
import axios from "redaxios";
import isEmail from "validator/es/lib/isEmail";
import isMobilePhone from "validator/es/lib/isMobilePhone";
import isPostalCode from "validator/es/lib/isPostalCode";
import { TYPE, useToast } from "vue-toastification";
import Footer from "@/components/Footer.vue";
const props = defineProps({
token: String,
});
if (props.token) {
axios
.get(`${config.baseurl}api/organizations/selfservice/${props.token}`)
.then(({ data }) => {
state.org_name = data.name;
state.org_teams = data.teams;
org_team.value = data.teams[0]?.id;
})
.catch((error) => {
console.log(error);
});
}
let userdetails = ref({
firstname: "",
lastname: "",
middlename: "",
mail: "",
phone: "",
address: { street: "", address2: "", city: "", zipcode: "" },
});
let provide_address = ref(false);
let agb_accepted = ref(false);
let data_confirmed = ref(false);
let org_team = ref("");
let registrationState = ref("pending");
//
const state = reactive({
org_name: "",
org_teams: [],
submit_enabled: computed(
() =>
agb_accepted.value === true &&
data_confirmed.value === true &&
(isMobilePhone(userdetails.value.phone) ||
!userdetails.value.phone.trim()) &&
isEmail(userdetails.value.mail) &&
userdetails.value.firstname &&
userdetails.value.lastname &&
(provide_address.value === false ||
(provide_address.value === true &&
userdetails.value.address.street.trim() &&
userdetails.value.address.city.trim() &&
isPostalCode(userdetails.value.address.zipcode, "DE")))
),
});
const toast = useToast();
function login() {
userdetails = userdetails.value;
if (userdetails?.phone === "" || isMobilePhone(userdetails.phone)) {
if (isEmail(userdetails.mail)) {
let postdata = {
email: userdetails.mail,
firstname: userdetails.firstname,
middlename: userdetails.middlename,
lastname: userdetails.lastname,
address: {},
};
if (isMobilePhone(userdetails.phone)) {
postdata.phone = userdetails.phone;
}
if (provide_address.value === true) {
postdata.address = {
address1: userdetails.address.street,
address2: userdetails.address.address2 || "",
city: userdetails.address.city,
postalcode: userdetails.address.zipcode,
country: "DE",
};
}
if (state.org_name !== "" && state.org_teams.length > 0) {
postdata.team = org_team.value;
}
toast("Registrierung läuft...");
const browserlocale = (
(navigator.languages && navigator.languages[0]) ||
""
).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";
axios
.post(url, postdata)
.then(() => {
registrationState.value = "registered";
})
.catch((error) => {
console.log(error);
if (error.data.message === "E-Mail already registered") {
toast("bereits registriert...", { type: TYPE.ERROR });
}
});
}
}
}
</script> </script>
+22
View File
@@ -0,0 +1,22 @@
<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>
<Footer></Footer>
</template>
<script setup>
import Footer from "@/components/Footer.vue";
const props = defineProps({
mail: String,
});
</script>