Compare commits

...

173 Commits
0.4.1 ... main

Author SHA1 Message Date
00a0c99f70
Merge branch 'dev'
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 16:49:36 +01:00
4bcbc67436
refactor: drop sub-directory routing 2024-12-02 16:48:15 +01:00
595735ad00
🚀Bumped version to v1.0.1
All checks were successful
ci/woodpecker/tag/release Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 15:53:04 +01:00
7fcb6a9fc3
fix(container): Add dockeringore 2024-12-02 15:51:25 +01:00
2285ea5070
🚀Bumped version to v1.0.0
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 15:32:47 +01:00
4af5c4545b
refactor
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 13:16:45 +01:00
f296cbc1a0
i18n 2024-12-02 13:08:55 +01:00
4fcc38c374
updated profile page 2024-12-02 13:08:08 +01:00
90c085db28
footer update 2024-12-02 13:07:57 +01:00
1a3ab98412
improved style in registered view 2024-12-02 12:58:09 +01:00
048edfba89
i18n 2024-12-02 12:56:43 +01:00
0acda07eb5
add i18n ally snake case config 2024-12-02 12:42:00 +01:00
afffde8fa0
registration brand font + more translations 2024-12-02 12:34:42 +01:00
1eab535381
wip: general updates 2024-12-02 11:54:05 +01:00
196b386d6d
refactor: translations 2024-12-02 11:31:24 +01:00
548148e898
fix: translations 2024-12-02 11:29:05 +01:00
6376dcb5fe
feat(Footer): ref lfk 2024-12-02 11:25:11 +01:00
75b61d991b
feat(Home): improve ui 2024-12-02 11:24:04 +01:00
af9a168f58
feat: lfk font 2024-12-02 11:12:00 +01:00
f71b01c39a
chore(deps): node@23.3.0 2024-12-02 11:06:26 +01:00
3e289d83f9
feat(Home): improve background.jpg import
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 11:00:07 +01:00
ec6d252928
refactor: code cleanup 2024-12-02 10:55:06 +01:00
4a11fef0e0
chore(deps): update all
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 10:40:06 +01:00
b85c3958c2
chore: pnpm v9
Some checks are pending
ci/woodpecker/push/build Pipeline is running
2024-12-02 10:16:59 +01:00
780bc54604
refactor(ci): Make ready for new woodpecker
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-11-26 19:23:40 +01:00
cb2f8eeab1
chore: 2025 2024-11-21 10:49:46 +01:00
8fb39276af
chore: 2025 2024-11-21 10:48:22 +01:00
c36db2c18f
Pin pnpm
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2023-11-06 20:27:30 +01:00
decc80fcc1
Merge branch 'dev' of git.odit.services:lfk/selfservice into dev
Some checks failed
ci/woodpecker/push/build Pipeline failed
2023-11-06 20:25:28 +01:00
9a3d307dfa
feat(ci)!: Switch to woodpecker 2023-11-06 20:25:26 +01:00
240f44df60
🚀Bumped version to v0.11.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-07 15:17:49 +02:00
677e65f44a
chore(deps): pnpm@8.1.1 2023-04-07 15:17:27 +02:00
772eca64bb
fix(Footer): darkmode colors in lightmode
Some checks failed
continuous-integration/drone/push Build is failing
2023-04-07 15:15:26 +02:00
25d25401df
fix: registration code white bg
close #50
2023-04-07 15:13:44 +02:00
cac5103d52
switched drone to kaniko with cache
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-29 20:20:06 +02:00
6aca13f0cb
Pinned pnpm and lockfile 2023-03-29 20:17:33 +02:00
78fea1ea04
Switched dockerfile to pnpm with cache 2023-03-29 20:17:18 +02:00
fa51b31fe4
🚀Bumped version to v0.11.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-15 19:27:59 +01:00
b9624aa5ad
Added footer to every page 2023-03-15 19:27:40 +01:00
09e48e771f
Accept tos to accept privacy_policy 2023-03-15 19:22:35 +01:00
8364321a7c
🚀Bumped version to v0.11.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-18 17:27:22 +01:00
659fa77dca
Profile: add "---" if no data set
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-18 17:26:54 +01:00
10c9127256
🚀Bumped version to v0.11.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:24:42 +01:00
a3a1e89aa1
pnpm migration
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:24:25 +01:00
5587175534
🚀Bumped version to v0.10.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:19:08 +01:00
8e2b355466
updated nginx config for cache busting
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:18:57 +01:00
eccce0795b
text cleanups + footer
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:14:01 +01:00
54540be6e1
improved profile page padding + full width registration code for easier scanning
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:04:25 +01:00
3392a2e68e
🚀Bumped version to v0.9.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:52:50 +01:00
8928f841dc
wip: registration confirmation ui
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:52:38 +01:00
9ac14e8a5d
wip: error registration ui feedback
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:48:14 +01:00
4a5b9d2569
🚀Bumped version to v0.8.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:44:43 +01:00
123509d0a6
fix: registration code (broke in merge)
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:44:10 +01:00
51f8d0fb42
wip: fix registration code
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:41:42 +01:00
a1b600df1c
Merge branch 'dev'
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:54:34 +01:00
f4d1c7b053
🚀Bumped version to v0.8.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:51:54 +01:00
ab9b400fff
/profile/ dont instantly show mail format error
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:51:23 +01:00
ac75828309
/profile/ move from anchor tag to button
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:51:09 +01:00
c7f3a893af
/profile/ toast styles
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:50:54 +01:00
30fd7ead08
/profile/ autocomplete mail
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:50:40 +01:00
64e6ef8cec
/profile/ text cleanups
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:50:27 +01:00
c35f943957
move /registered/ to props
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:46:18 +01:00
292e44057a
🚀Bumped version to v0.8.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 15:54:17 +01:00
20fca6794d
Adjusted button text 2023-02-02 15:53:58 +01:00
8139d63715
Switched request login link api path to login (backend v13.0.0) 2023-02-02 15:52:33 +01:00
fe1bbc7816
Merge branch 'dev'
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 00:21:22 +01:00
7051909bf9
🚀Bumped version to v0.8.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 00:16:29 +01:00
f7a0682c33
Merge pull request 'dont autologin on register -> require mail link' (#47) from feature/46-dont-autologin-on-register-require-mail-link into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #47
2023-02-01 23:16:11 +00:00
c63adf557b
🚀Bumped version to v0.7.11
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 00:15:58 +01:00
077b33f031
Profile: improved mobile responsiveness/ design + toast clear
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 00:15:12 +01:00
52a6b3dc77
fix: registration code download button style
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 00:10:48 +01:00
eb20b547e7
add /registered/?mail route
ref #46
2023-02-02 00:08:14 +01:00
8b5e1cac13
🚀Bumped version to v0.7.10
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 17:50:46 +01:00
20c6a420e9
Merge branch 'dev' of git.odit.services:lfk/selfservice into dev
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 17:48:52 +01:00
53800b4fa3
Added download for registration code 2023-02-01 17:42:58 +01:00
debbd9219c
🚀Bumped version to v0.7.9
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 17:40:23 +01:00
9b261bf200
fix codeconfig.height
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 17:40:09 +01:00
713dd15312
drop jsbarcode
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 17:39:59 +01:00
64382880c4
Pinned version 2023-02-01 17:39:15 +01:00
9e06c46411
Configureable barcode format via bwp-js 2023-02-01 17:39:03 +01:00
8cfddb5029
migrate to bwip-js
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 17:36:22 +01:00
e5a01bcd76
🚀Bumped version to v0.7.8
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 14:50:04 +01:00
851190e6a7
add barcode to profile
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 14:48:06 +01:00
1603a097f7
certificate generation: success toast styling
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 14:47:38 +01:00
c2b615294e
🚀Bumped version to v0.7.7
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-31 13:47:39 +01:00
c64762831f
fix: registration w/o phone
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-31 13:47:32 +01:00
9b446abc1f
🚀Bumped version to v0.7.6
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-31 13:47:19 +01:00
5d974e562e
update release script
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-31 13:45:45 +01:00
a030f6b738
update texts of pdf generation status toasts
All checks were successful
continuous-integration/drone/push Build is passing
close #44
2023-01-31 13:45:28 +01:00
1249248a9d
🚀Bumped version to v0.7.5
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-30 18:19:53 +01:00
0bd6d543bf
update nginx base
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-30 18:18:26 +01:00
92d7bfd594
updated base node image
Some checks failed
continuous-integration/drone/push Build is failing
2023-01-30 18:16:25 +01:00
917cb6be34
fix: relativ links
Some checks failed
continuous-integration/drone/push Build is failing
2023-01-30 18:13:50 +01:00
d159cb59be
AGB link 2023-01-30 18:13:43 +01:00
9812d79d4d
2023
Some checks failed
continuous-integration/drone/push Build is failing
2023-01-30 18:12:50 +01:00
4663214ede 🚀Bumped version to v0.7.4
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-21 15:58:49 +02:00
9c9ceaa666 Updated dronefile
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-21 15:57:45 +02:00
602d80bd14 🚀Bumped version to v0.7.3
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-21 15:38:27 +02:00
45ee4ab812 Merge pull request 'Button fixes bugfix/42-button_links' (#43) from bugfix/42-button_links into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #43
2021-04-21 13:38:10 +00:00
020c310865 Fixed register button link
ref #42
2021-04-21 12:33:16 +02:00
1102d29c0e Removed useless register now button
ref #42
2021-04-21 12:31:46 +02:00
1a3af200dd 🚀Bumped version to v0.7.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-14 12:19:43 +02:00
71f419ffb4 Merge branch 'dev' of git.odit.services:lfk/selfservice into dev
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-14 12:18:09 +02:00
b74bea0340 Document generation hotfix 🐞 2021-04-14 12:18:02 +02:00
b0172c500b 🚀Bumped version to v0.7.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-13 18:08:19 +02:00
75b4dac0fe Merge pull request 'bugfix/31-env-js-linking-ci' (#41) from bugfix/31-env-js-linking-ci into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #41
close #31
2021-04-13 16:02:44 +00:00
51d058bf96 added 'yarn postbuild' script for fixing env.js in dist/index.html
ref #31
2021-04-13 17:58:43 +02:00
ad13bae068 dependency bump 2021-04-13 17:57:41 +02:00
152e74190d 🚀Bumped version to v0.7.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-06 21:28:02 +02:00
4c83e2e738 Merge pull request 'Donation list feature/39-donation_list' (#40) from feature/39-donation_list into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #40
2021-04-06 19:27:30 +00:00
cb1b9d330b Sorted translations 🌍
ref #39
2021-04-06 21:25:36 +02:00
3b4c11e4c0 Merge branch 'feature/39-donation_list' of git.odit.services:lfk/selfservice into feature/39-donation_list 2021-04-06 21:25:12 +02:00
89820d4450 Added total to bottom of page
ref #39
2021-04-06 21:25:10 +02:00
121022c843 added distance formatting
ref #39
2021-04-06 21:23:24 +02:00
d713fbef94 Added translations 🌍
ref #39
2021-04-06 17:27:18 +02:00
815a36f202 Now w/ formatted currency amount
ref #39
2021-04-06 17:20:41 +02:00
baa6da3dd0 Fixed spaces in name
ref #39
2021-04-06 17:18:09 +02:00
f141130db5 Added basic sponsoring table
ref #39
2021-04-06 17:14:22 +02:00
5a123b0cf8 Updated env description
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-06 17:03:05 +02:00
f5ae2145df 🚀Bumped version to v0.6.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-06 17:01:20 +02:00
96c0e56986 Fixed imprint/privacy default links
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-06 17:00:55 +02:00
bc1de2acdc 🚀Bumped version to v0.6.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-03 18:53:32 +02:00
5c558aa9ee Merge branch 'dev' of git.odit.services:lfk/selfservice into dev 2021-04-03 18:53:14 +02:00
145b49906b Revert "🚀Bumped version to v0.6.0"
This reverts commit 0a62e8f5d1929bfe9a53a9709a3031f06a2487c3.
2021-04-03 18:53:12 +02:00
0a62e8f5d1 🚀Bumped version to v0.6.0 2021-04-03 18:52:54 +02:00
53eeb6be3d Merge pull request 'Certificate download feature/19-runner_certficates' (#38) from feature/19-runner_certficates into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #38
2021-04-03 16:51:22 +00:00
a554a90e74 Merge branch 'dev' into feature/19-runner_certficates
# Conflicts:
#	index.html
2021-04-03 18:50:16 +02:00
c3b2b93d90 Reverted relative linking fix
ref #19
2021-04-03 18:48:53 +02:00
1a3c9edeb3 🚀Bumped version to v0.5.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-03 18:38:44 +02:00
7064a5bd82 Merge branch 'dev' into feature/19-runner_certficates 2021-04-03 16:28:18 +00:00
fd6bd88d42 Merge pull request 'Env linking bugfix bugfix/31-env_linking' (#37) from bugfix/31-env_linking into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #37
2021-04-03 16:27:56 +00:00
f0a7f35dec Renoved fixed data
ref #19
2021-04-03 18:11:57 +02:00
b938cfc49e Fixed blob handling
ref #19
2021-04-03 18:11:22 +02:00
f6334397dc first part of certificate generation with manual data
ref #19
2021-04-03 17:57:24 +02:00
544542ac1e Added building pipeline for current branch
All checks were successful
continuous-integration/drone/push Build is passing
ref #31
2021-04-03 15:26:07 +02:00
67c0dae537 Now manually linking env and main
ref #31
2021-04-03 15:24:52 +02:00
cd6a139daf Merge pull request 'feature/30-profile-forgot-link' (#35) from feature/30-profile-forgot-link into dev
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #35
close #30
2021-04-02 19:00:50 +00:00
ec44a8b63e Merge branch 'dev' into feature/30-profile-forgot-link
# Conflicts:
#	src/locales/en.json
#	src/views/Home.vue
2021-04-01 19:58:37 +02:00
676f0e8339 🚀Bumped version to v0.5.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-01 19:57:02 +02:00
27fd8f9a91 Revert "🚀Bumped version to v0.5.0"
This reverts commit b8c1b8c43b6d050d239d836bbb6ace2504fdcd21.
2021-04-01 19:56:52 +02:00
bc1c824d9f Merge branch 'dev' of git.odit.services:lfk/selfservice into dev 2021-04-01 19:56:30 +02:00
b8c1b8c43b 🚀Bumped version to v0.5.0 2021-04-01 19:56:09 +02:00
713db5e1e8 Removed useless code
ref #30
2021-04-01 19:55:23 +02:00
0795ea318d Fixed post url and body
ref #30
2021-04-01 19:55:01 +02:00
bd512e0651 Merge pull request 'Runner self deletion feature/21-user_deletion' (#36) from feature/21-user_deletion into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #36
2021-04-01 17:50:41 +00:00
cf0437c3a7 Sorted translations
ref #21
2021-04-01 19:42:51 +02:00
8a24505d64 Added translations
ref #21
2021-04-01 19:42:33 +02:00
175bb168ae Content i18n run 🌍
ref #21
2021-04-01 19:40:49 +02:00
9751c2e9fd Added error toast
ref #21
2021-04-01 19:37:21 +02:00
7440fc404e Updated toasts and removed useless code
ref #21
2021-04-01 19:36:40 +02:00
ba3dedb164 Added translations 🌍
ref #21
2021-04-01 19:35:54 +02:00
d710d4b68f Updated icons
ref #21
2021-04-01 19:35:42 +02:00
125fcdd8cf Merge branch 'feature/21-user_deletion' of git.odit.services:lfk/selfservice into feature/21-user_deletion 2021-04-01 19:31:29 +02:00
8773239244 Added confirmation for profile deletion
ref #21
2021-04-01 19:31:25 +02:00
85b0549a11 Added confirmation for profile deletion 2021-04-01 19:31:19 +02:00
fc04e71311 Implemented basic deletion
ref #21
2021-04-01 19:27:12 +02:00
619078cce8 Added data deletion button
ref #21
2021-04-01 19:25:09 +02:00
30f3a51ef8 add forgot view + action
ref #30
2021-04-01 19:22:23 +02:00
60dea511b9 🐞 fix home routes
ref #30
2021-04-01 19:07:14 +02:00
863568d7d0 basic ProfileNone layout
ref #30
2021-04-01 19:07:04 +02:00
7ae0081d69 Merge pull request 'sync - 0.4.5' (#34) from dev into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #34
2021-04-01 16:46:05 +00:00
555823954a Merge branch 'main' into dev
Some checks reported errors
continuous-integration/drone/push Build was killed
2021-04-01 16:45:25 +00:00
efcb7f5674 🚀Bumped version to v0.4.5
Some checks reported errors
continuous-integration/drone/push Build was killed
2021-04-01 18:40:10 +02:00
e796f6dcaf Merge pull request 'feature/32-registration-language' (#33) from feature/32-registration-language into dev
Some checks reported errors
continuous-integration/drone/push Build was killed
Reviewed-on: #33
close #32
2021-04-01 16:38:49 +00:00
52a082841d 🐞 fix /profile/ router on register
ref #32
2021-04-01 18:31:37 +02:00
e3f7497af5 pass browser locale to api/runners/register/
ref #32
2021-04-01 18:31:18 +02:00
9b62962758 🚀Bumped version to v0.4.4
Some checks reported errors
continuous-integration/drone/push Build was killed
2021-03-31 20:16:18 +02:00
84dc33bf14 🚑 hotfix - baseurl_selfservice -> baseurl 2021-03-31 20:14:58 +02:00
cad34d357b 🚀Bumped version to v0.4.3
Some checks reported errors
continuous-integration/drone/push Build was killed
2021-03-31 20:13:03 +02:00
2056ce1e62 🚑 hotfix - Profile api path 2021-03-31 20:11:40 +02:00
3b2c99c709 🚀Bumped version to v0.4.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-31 20:06:42 +02:00
f150821f0f 🚑 fix organization registration token 2021-03-31 20:06:20 +02:00
1c19657935 Merge pull request 'RELEASE 0.3.0' (#25) from dev into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #25
2021-03-30 16:20:04 +00:00
37 changed files with 6248 additions and 1176 deletions

187
.dockerignore Normal file
View File

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

View File

@ -1,109 +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: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

View File

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

33
.woodpecker/build.yml Normal file
View File

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

17
.woodpecker/release.yml Normal file
View File

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

View File

@ -2,9 +2,325 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [1.0.1](https://git.odit.services/lfk/selfservice/compare/1.0.0...1.0.1)
- fix(container): Add dockeringore [`7fcb6a9`](https://git.odit.services/lfk/selfservice/commit/7fcb6a9fc3f98772990790f6385200732f8bce7c)
### [1.0.0](https://git.odit.services/lfk/selfservice/compare/0.11.3...1.0.0)
> 2 December 2024
- chore(deps): update all [`4a11fef`](https://git.odit.services/lfk/selfservice/commit/4a11fef0e0ad0940535fd1d6a1a57a829dc2b50d)
- chore: pnpm v9 [`b85c395`](https://git.odit.services/lfk/selfservice/commit/b85c3958c288293bb98df2326f73dfad1684e3cb)
- wip: general updates [`1eab535`](https://git.odit.services/lfk/selfservice/commit/1eab5353810a0a351cfc72b493c5156f55a4c9d2)
- refactor [`4af5c45`](https://git.odit.services/lfk/selfservice/commit/4af5c4545bfaad21d71bcbf91d2cd8ea53847b62)
- fix: translations [`548148e`](https://git.odit.services/lfk/selfservice/commit/548148e8982d7d146182af9f2a69de87f0b3529e)
- refactor: translations [`196b386`](https://git.odit.services/lfk/selfservice/commit/196b386d6d57e91fbb4f46091a59ba04bb6e6984)
- feat(ci)!: Switch to woodpecker [`9a3d307`](https://git.odit.services/lfk/selfservice/commit/9a3d307dfae0851eb842ad3f1c34460bca13bff1)
- i18n [`048edfb`](https://git.odit.services/lfk/selfservice/commit/048edfba89a69efd3362dd8df8b89f8780f5f3fe)
- registration brand font + more translations [`afffde8`](https://git.odit.services/lfk/selfservice/commit/afffde8fa04df88d0a8bff05d0a28550414ce385)
- feat: lfk font [`af9a168`](https://git.odit.services/lfk/selfservice/commit/af9a168f587768d8b1af8990729e743481ba687d)
- updated profile page [`4fcc38c`](https://git.odit.services/lfk/selfservice/commit/4fcc38c374553b22f92a734903df1b7a032348fa)
- 🚀Bumped version to v1.0.0 [`2285ea5`](https://git.odit.services/lfk/selfservice/commit/2285ea507069cf362baa950e7337aec72a37d4e3)
- i18n [`f296cbc`](https://git.odit.services/lfk/selfservice/commit/f296cbc1a0c9035db6546c85781be71b152264d7)
- feat(Footer): ref lfk [`6376dcb`](https://git.odit.services/lfk/selfservice/commit/6376dcb5fe7e3b1e1e639e41bc1b682036d838a0)
- feat(Home): improve ui [`75b61d9`](https://git.odit.services/lfk/selfservice/commit/75b61d991bd483aaf00871c12c9268fc6e21435b)
- refactor(ci): Make ready for new woodpecker [`780bc54`](https://git.odit.services/lfk/selfservice/commit/780bc54604998abd275f3b7d50a3849002eb243d)
- refactor: code cleanup [`ec6d252`](https://git.odit.services/lfk/selfservice/commit/ec6d252928fb84248041a3675590b85293c96133)
- chore: 2025 [`cb2f8ee`](https://git.odit.services/lfk/selfservice/commit/cb2f8eeab1a7e260df938b8aa94fa31f8e1b5efe)
- footer update [`90c085d`](https://git.odit.services/lfk/selfservice/commit/90c085db28798bbcac24eb9700285221a9bcad92)
- improved style in registered view [`1a3ab98`](https://git.odit.services/lfk/selfservice/commit/1a3ab98412b82eeb1f0dea8ea642f5fc6435c09d)
- add i18n ally snake case config [`0acda07`](https://git.odit.services/lfk/selfservice/commit/0acda07eb53a85f7b2e87a3e26d90b7cdf1fe012)
- feat(Home): improve background.jpg import [`3e289d8`](https://git.odit.services/lfk/selfservice/commit/3e289d83f9db98641f0f7f732b622dab9955f3a1)
- chore(deps): node@23.3.0 [`f71b01c`](https://git.odit.services/lfk/selfservice/commit/f71b01c39a62ef4402004e2fbcfacb37bc92ea39)
- Pin pnpm [`c36db2c`](https://git.odit.services/lfk/selfservice/commit/c36db2c18fc5f7cfd7bf5d295f3faf3931df736b)
#### [0.11.3](https://git.odit.services/lfk/selfservice/compare/0.11.2...0.11.3)
> 7 April 2023
- fix: registration code white bg [`#50`](https://git.odit.services/lfk/selfservice/issues/50)
- Pinned pnpm and lockfile [`6aca13f`](https://git.odit.services/lfk/selfservice/commit/6aca13f0cb1bc8fa43f0f09c554cec0758acd7a1)
- switched drone to kaniko with cache [`cac5103`](https://git.odit.services/lfk/selfservice/commit/cac5103d52427e777e4c3624ebb253ad7bd393d6)
- Switched dockerfile to pnpm with cache [`78fea1e`](https://git.odit.services/lfk/selfservice/commit/78fea1ea045a7281fe0a2841fc4d5f1505dcb3cf)
- 🚀Bumped version to v0.11.3 [`240f44d`](https://git.odit.services/lfk/selfservice/commit/240f44df60184c492f6cff3d864c1f9f2563ff80)
- chore(deps): pnpm@8.1.1 [`677e65f`](https://git.odit.services/lfk/selfservice/commit/677e65f44ae4bcc6f9af4732d813f337da0c51d2)
- fix(Footer): darkmode colors in lightmode [`772eca6`](https://git.odit.services/lfk/selfservice/commit/772eca64bb38ce1cf1ea1b58859dd744588a88e1)
#### [0.11.2](https://git.odit.services/lfk/selfservice/compare/0.11.1...0.11.2)
> 15 March 2023
- Added footer to every page [`b9624aa`](https://git.odit.services/lfk/selfservice/commit/b9624aa5ad57002852c84081fc710c2e977251bd)
- 🚀Bumped version to v0.11.2 [`fa51b31`](https://git.odit.services/lfk/selfservice/commit/fa51b31fe41d41b3ec9becad07ddab4cf73be051)
- Accept tos to accept privacy_policy [`09e48e7`](https://git.odit.services/lfk/selfservice/commit/09e48e771f4c0db4a7dbb898b05b347f1aad2292)
#### [0.11.1](https://git.odit.services/lfk/selfservice/compare/0.11.0...0.11.1)
> 18 February 2023
- Profile: add "---" if no data set [`659fa77`](https://git.odit.services/lfk/selfservice/commit/659fa77dca3b527d896d752386e91a167a1b8f4f)
- 🚀Bumped version to v0.11.1 [`8364321`](https://git.odit.services/lfk/selfservice/commit/8364321a7cb6a0037ee0c5055b028c4cf883fb10)
#### [0.11.0](https://git.odit.services/lfk/selfservice/compare/0.10.0...0.11.0)
> 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)
> 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)
#### [0.7.1](https://git.odit.services/lfk/selfservice/compare/0.7.0...0.7.1)
> 13 April 2021
- Merge pull request 'bugfix/31-env-js-linking-ci' (#41) from bugfix/31-env-js-linking-ci into dev [`#31`](https://git.odit.services/lfk/selfservice/issues/31)
- ⏫ dependency bump [`ad13bae`](https://git.odit.services/lfk/selfservice/commit/ad13bae068416bed10d00e6887a05d580a836482)
- 🚀Bumped version to v0.7.1 [`b0172c5`](https://git.odit.services/lfk/selfservice/commit/b0172c500b0613209ac44e61023043065b3854b0)
- added 'yarn postbuild' script for fixing env.js in dist/index.html [`51d058b`](https://git.odit.services/lfk/selfservice/commit/51d058bf966c3dcb064562e6bf696a748d0cd148)
#### [0.7.0](https://git.odit.services/lfk/selfservice/compare/0.6.1...0.7.0)
> 6 April 2021
- 🚀Bumped version to v0.7.0 [`152e741`](https://git.odit.services/lfk/selfservice/commit/152e74190d13d30110d494a9062f868390ca19b3)
- Merge pull request 'Donation list feature/39-donation_list' (#40) from feature/39-donation_list into dev [`4c83e2e`](https://git.odit.services/lfk/selfservice/commit/4c83e2e738a075354383dca4d500808f761247d2)
- Added total to bottom of page [`89820d4`](https://git.odit.services/lfk/selfservice/commit/89820d44501793365248b8e778522cdc188afa70)
- Sorted translations 🌍 [`cb1b9d3`](https://git.odit.services/lfk/selfservice/commit/cb1b9d330b28f11cceed9691aee4ccee5246d346)
- Added basic sponsoring table [`f141130`](https://git.odit.services/lfk/selfservice/commit/f141130db5ede60a623747f4e324f66259e5bc75)
- Added translations 🌍 [`d713fbe`](https://git.odit.services/lfk/selfservice/commit/d713fbef94e75fbbc62254ea8f0ca50dc4e93d79)
- Now w/ formatted currency amount [`815a36f`](https://git.odit.services/lfk/selfservice/commit/815a36f20271f47f49c3814b001c3404d43113cd)
- Fixed spaces in name [`baa6da3`](https://git.odit.services/lfk/selfservice/commit/baa6da3dd06c493fccc61945b9bcbd9b2e79d910)
- Updated env description [`5a123b0`](https://git.odit.services/lfk/selfservice/commit/5a123b0cf89f49d450becbbc03b28c5bb6416b7c)
- added distance formatting [`121022c`](https://git.odit.services/lfk/selfservice/commit/121022c8434484a363a3f2ea68aba4d8ef7cad2d)
#### [0.6.1](https://git.odit.services/lfk/selfservice/compare/0.6.0...0.6.1)
> 6 April 2021
- 🚀Bumped version to v0.6.1 [`f5ae214`](https://git.odit.services/lfk/selfservice/commit/f5ae2145df07413329f60c229d9571fd1de2ca79)
- Fixed imprint/privacy default links [`96c0e56`](https://git.odit.services/lfk/selfservice/commit/96c0e5698697361e65c5aa80c9a0aada5c3d5f30)
#### [0.6.0](https://git.odit.services/lfk/selfservice/compare/0.5.1...0.6.0)
> 3 April 2021
- 🚀Bumped version to v0.6.0 [`bc1de2a`](https://git.odit.services/lfk/selfservice/commit/bc1de2acdcbf8f3319026887cb6b3d594fcd63dc)
- first part of certificate generation with manual data [`f633439`](https://git.odit.services/lfk/selfservice/commit/f6334397dc99cd38d31ef524bc26ba7d386b33dd)
- Renoved fixed data [`f0a7f35`](https://git.odit.services/lfk/selfservice/commit/f0a7f35dec07508a07d4c11abda297ad0bf91187)
- Revert "🚀Bumped version to v0.6.0" [`145b499`](https://git.odit.services/lfk/selfservice/commit/145b49906bdf2d75abf93e1779f188a691a3a909)
- 🚀Bumped version to v0.6.0 [`0a62e8f`](https://git.odit.services/lfk/selfservice/commit/0a62e8f5d1929bfe9a53a9709a3031f06a2487c3)
- Merge pull request 'Certificate download feature/19-runner_certficates' (#38) from feature/19-runner_certficates into dev [`53eeb6b`](https://git.odit.services/lfk/selfservice/commit/53eeb6be3ddf4735a11b6c4636c28b4d16aa58ee)
- Fixed blob handling [`b938cfc`](https://git.odit.services/lfk/selfservice/commit/b938cfc49e269e76761a752f8257ebbab88f6959)
- Reverted relative linking fix [`c3b2b93`](https://git.odit.services/lfk/selfservice/commit/c3b2b93d90102b4e31cfce15220acfc8fe48a7c5)
#### [0.5.1](https://git.odit.services/lfk/selfservice/compare/0.5.0...0.5.1)
> 3 April 2021
- Merge pull request 'feature/30-profile-forgot-link' (#35) from feature/30-profile-forgot-link into dev [`#30`](https://git.odit.services/lfk/selfservice/issues/30)
- 🚀Bumped version to v0.5.1 [`1a3c9ed`](https://git.odit.services/lfk/selfservice/commit/1a3c9edeb3987907ffe2223da8f3be079a1c80d2)
- Merge pull request 'Env linking bugfix bugfix/31-env_linking' (#37) from bugfix/31-env_linking into dev [`fd6bd88`](https://git.odit.services/lfk/selfservice/commit/fd6bd88d4238cca2a2755ab1bc51ff7870bef947)
- basic ProfileNone layout [`863568d`](https://git.odit.services/lfk/selfservice/commit/863568d7d0e132dd1b7d13a2cb1afe8db02c472c)
- add forgot view + action [`30f3a51`](https://git.odit.services/lfk/selfservice/commit/30f3a51ef82ad966225abc6fd95508af56106924)
- Added building pipeline for current branch [`544542a`](https://git.odit.services/lfk/selfservice/commit/544542ac1e9717506676c1495c2d530eca833d31)
- Removed useless code [`713db5e`](https://git.odit.services/lfk/selfservice/commit/713db5e1e8fed5f38b3a5d19cfe870eff16eeda1)
- Now manually linking env and main [`67c0dae`](https://git.odit.services/lfk/selfservice/commit/67c0dae537df5842e89c0ed040c0fef02df01b69)
- Fixed post url and body [`0795ea3`](https://git.odit.services/lfk/selfservice/commit/0795ea318d80b764eee89462ad87da86aa7ce0ae)
- 🐞 fix home routes [`60dea51`](https://git.odit.services/lfk/selfservice/commit/60dea511b9fbb6d206ee531618e788e686fa6b5a)
#### [0.5.0](https://git.odit.services/lfk/selfservice/compare/0.4.5...0.5.0)
> 1 April 2021
- 🚀Bumped version to v0.5.0 [`676f0e8`](https://git.odit.services/lfk/selfservice/commit/676f0e83393be823ccb612846650a9a98bf7f0b3)
- Revert "🚀Bumped version to v0.5.0" [`27fd8f9`](https://git.odit.services/lfk/selfservice/commit/27fd8f9a9106294ae6522f2fff42dfbf84f06f82)
- 🚀Bumped version to v0.5.0 [`b8c1b8c`](https://git.odit.services/lfk/selfservice/commit/b8c1b8c43b6d050d239d836bbb6ace2504fdcd21)
- Merge pull request 'Runner self deletion feature/21-user_deletion' (#36) from feature/21-user_deletion into dev [`bd512e0`](https://git.odit.services/lfk/selfservice/commit/bd512e0651363f1f2543136d354d9ada9990d83d)
- Sorted translations [`cf0437c`](https://git.odit.services/lfk/selfservice/commit/cf0437c3a738d42154ed1336d6020b88661b462f)
- Added translations 🌍 [`ba3dedb`](https://git.odit.services/lfk/selfservice/commit/ba3dedb1643e2d5f1c2ab92224a11c1c8a82ae71)
- Added confirmation for profile deletion [`8773239`](https://git.odit.services/lfk/selfservice/commit/8773239244c064a888a4ad1f66298f2811fcc2ae)
- Added confirmation for profile deletion [`85b0549`](https://git.odit.services/lfk/selfservice/commit/85b0549a11927758c579cd08bc8015ae00105a84)
- Updated icons [`d710d4b`](https://git.odit.services/lfk/selfservice/commit/d710d4b68ff0e9515eb4a0a4ea0def7b3552e599)
- Added data deletion button [`619078c`](https://git.odit.services/lfk/selfservice/commit/619078cce8281bef520b05bf3e735c26d0752375)
- Content i18n run 🌍 [`175bb16`](https://git.odit.services/lfk/selfservice/commit/175bb168ae134009c26072b76cd74948aecc189f)
- Implemented basic deletion [`fc04e71`](https://git.odit.services/lfk/selfservice/commit/fc04e713110df161c481cb9a3b64e78b30d4f79b)
- Added translations [`8a24505`](https://git.odit.services/lfk/selfservice/commit/8a24505d64832001d6a44800f61f7e0705892046)
- Updated toasts and removed useless code [`7440fc4`](https://git.odit.services/lfk/selfservice/commit/7440fc404ea2a8e68e7ce896e8369700069b2021)
- Added error toast [`9751c2e`](https://git.odit.services/lfk/selfservice/commit/9751c2e9fd99650efab4d5edce3909c907ea9391)
- Merge pull request 'RELEASE 0.3.0' (#25) from dev into main [`1c19657`](https://git.odit.services/lfk/selfservice/commit/1c196579356a70f9d761f7f69d79033157570076)
#### [0.4.5](https://git.odit.services/lfk/selfservice/compare/0.4.4...0.4.5)
> 1 April 2021
- Merge pull request 'feature/32-registration-language' (#33) from feature/32-registration-language into dev [`#32`](https://git.odit.services/lfk/selfservice/issues/32)
- 🚀Bumped version to v0.4.5 [`efcb7f5`](https://git.odit.services/lfk/selfservice/commit/efcb7f56745aa3f347eb98399ee1bcb68a157e9d)
- 🐞 fix /profile/ router on register [`52a0828`](https://git.odit.services/lfk/selfservice/commit/52a082841d47d1ed9c0997776a0784285a3f6ba7)
- pass browser locale to api/runners/register/ [`e3f7497`](https://git.odit.services/lfk/selfservice/commit/e3f7497af5860b2472b6cdfd33090b9d68b9fb49)
#### [0.4.4](https://git.odit.services/lfk/selfservice/compare/0.4.3...0.4.4)
> 31 March 2021
- 🚀Bumped version to v0.4.4 [`9b62962`](https://git.odit.services/lfk/selfservice/commit/9b62962758f8a73d669bca69b77f2c09a13c9e7a)
- 🚑 hotfix - baseurl_selfservice -> baseurl [`84dc33b`](https://git.odit.services/lfk/selfservice/commit/84dc33bf14ace839261aea02ffbcac5d627f8200)
#### [0.4.3](https://git.odit.services/lfk/selfservice/compare/0.4.2...0.4.3)
> 31 March 2021
- 🚀Bumped version to v0.4.3 [`cad34d3`](https://git.odit.services/lfk/selfservice/commit/cad34d357b9bd8501eed26b35b5324d2b4f756c3)
- 🚑 hotfix - Profile api path [`2056ce1`](https://git.odit.services/lfk/selfservice/commit/2056ce1e62a33e14bce5bdef5ea8cd38e039dc62)
#### [0.4.2](https://git.odit.services/lfk/selfservice/compare/0.4.1...0.4.2)
> 31 March 2021
- 🚀Bumped version to v0.4.2 [`3b2c99c`](https://git.odit.services/lfk/selfservice/commit/3b2c99c7090de03aab12415342136460ddd735ee)
- 🚑 fix organization registration token [`f150821`](https://git.odit.services/lfk/selfservice/commit/f150821f0f60e4798b02ebf50588da61ccb51279)
#### [0.4.1](https://git.odit.services/lfk/selfservice/compare/0.4.0...0.4.1) #### [0.4.1](https://git.odit.services/lfk/selfservice/compare/0.4.0...0.4.1)
> 31 March 2021
- Fixed registration routing [`2141f62`](https://git.odit.services/lfk/selfservice/commit/2141f62dca7ecb2be2579a7e79ffca513563c22a) - Fixed registration routing [`2141f62`](https://git.odit.services/lfk/selfservice/commit/2141f62dca7ecb2be2579a7e79ffca513563c22a)
- 🚀Bumped version to v0.4.1 [`5191ece`](https://git.odit.services/lfk/selfservice/commit/5191ecea1eb3ac66a3f0c2743d43ff5b505061b7)
#### [0.4.0](https://git.odit.services/lfk/selfservice/compare/0.3.1...0.4.0) #### [0.4.0](https://git.odit.services/lfk/selfservice/compare/0.3.1...0.4.0)

View File

@ -1,9 +1,15 @@
FROM node:15.9.0-alpine3.13 FROM node:23.3.0-alpine3.20 AS build
# FROM registry.odit.services/hub/library/node:23.3.0-alpine3.20 AS build
# ARG NPM_REGISTRY_URL=https://registry.npmjs.org
WORKDIR /app WORKDIR /app
COPY . . COPY . .
RUN yarn # RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@9
RUN yarn build RUN npm i -g pnpm@9
RUN pnpm i --frozen-lockfile
RUN pnpm build
RUN pnpm 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

View File

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

6
env_fix.js Normal file
View File

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

View File

@ -1,17 +1,17 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon-lfk.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lauf für Kaya! - Selfservice</title> <title>Lauf für Kaya! - Selfservice</title>
</head> </head>
<body class="dark:bg-gray-900 text-black dark:text-white p-0"> <body class="dark:bg-gray-900 text-black dark:text-white p-0">
<div id="app"></div> <div id="app"></div>
<script src="/env.js"></script> <script src="/env.js"></script>
<script defer type="module" src="/src/main.js"></script> <script defer type="module" src="/src/main.js"></script>
</body> </body>
</html> </html>

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;
} }
} }

View File

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

View File

@ -1,50 +1,50 @@
{ {
"name": "@odit/lfk-selfservice", "name": "@odit/lfk-selfservice",
"version": "0.4.1", "version": "1.0.1",
"scripts": { "type": "module",
"dev": "vite", "scripts": {
"build": "vite build", "dev": "vite",
"release": "release-it --only-version" "build": "vite build",
}, "release": "release-it",
"dependencies": { "postbuild": "node env_fix.js"
"marked": "2.0.1", },
"redaxios": "0.4.1", "dependencies": {
"toastify-js": "1.10.0", "@fontsource/athiti": "^5.1.0",
"validator": "13.5.2", "@tailwindcss/vite": "4.0.0-beta.4",
"vue-i18n": "9.0.0", "bwip-js": "4.5.1",
"vue-toastification": "2.0.0-rc.1", "marked": "15.0.3",
"vue": "3.0.9", "redaxios": "0.5.1",
"vue-router": "4.0.5" "tailwindcss": "4.0.0-beta.4",
}, "toastify-js": "1.12.0",
"devDependencies": { "validator": "13.12.0",
"@tailwindcss/jit": "0.1.18", "vue": "3.5.13",
"@tailwindcss/aspect-ratio": "0.2.0", "vue-i18n": "10.0.5",
"@tailwindcss/forms": "0.3.2", "vue-router": "4.5.0",
"@tailwindcss/line-clamp": "0.2.0", "vue-toastification": "2.0.0-rc.1"
"@tailwindcss/typography": "0.4.0", },
"@vitejs/plugin-vue": "1.2.1", "devDependencies": {
"@vue/compiler-sfc": "3.0.10", "@vitejs/plugin-vue": "5.2.1",
"autoprefixer": "10.2.5", "autoprefixer": "10.4.20",
"tailwindcss": "2.0.4", "release-it": "17.10.0",
"release-it": "14.5.0", "vite": "6.0.2",
"vite": "2.1.5" "vite-plugin-vue-devtools": "^7.6.7"
}, },
"release-it": { "release-it": {
"git": { "git": {
"commit": true, "commit": true,
"requireCleanWorkingDir": false, "requireCleanWorkingDir": false,
"commitMessage": "🚀Bumped version to v${version}", "commitMessage": "🚀Bumped version to v${version}",
"requireBranch": "dev", "requireBranch": "dev",
"push": false, "push": true,
"tag": true, "tag": true,
"tagName": null, "tagName": null,
"tagAnnotation": "v${version}" "tagAnnotation": "v${version}"
}, },
"npm": { "npm": {
"publish": false "publish": false
}, },
"hooks": { "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" "after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node order_i18n.js && git add src/locales"
} }
} }
} }

4228
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -3,10 +3,12 @@ const config = {
documentserver_key: '', documentserver_key: '',
// required, with trailing slash // required, with trailing slash
baseurl: '', baseurl: '',
// optional, will fallback to /selfservice/ // full url (including fqdn)
baseurl_selfservice: '/selfservice/', baseurl_documentserver: 'http://localhost:4010/documents',
// optional, will fallback to code128
code_format: 'ean13',
// optional, will fallback to /imprint // optional, will fallback to /imprint
url_imprint: '', url_imprint: '',
// optional, will fallback to /privacy // optional, will fallback to /privacy
url_privacy: '' url_privacy: '',
}; };

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

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

View File

@ -1,28 +1,16 @@
<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 text-center md:text-left">
Lauf für Kaya! Selfservice - Copyright © 2021 + proudly powered by Lauf für Kaya! Selfservice<br>Copyright © 2024<br>proudly powered by
<a <a class="underline" target="_blank" rel="noopener,noreferrer"
class="underline" href="https://odit.services?ref=lfk">ODIT.Services</a>
target="_blank"
rel="noopener,noreferrer"
href="https://odit.services"
>ODIT.Services</a>
</p> </p>
<span class="inline-flex sm:ml-auto sm:mt-0 mt-4 justify-center sm:justify-start"> <span class="inline-flex sm:ml-auto sm:mt-0 mt-4 justify-center sm:justify-start">
<a <a target="_blank" rel="noopener,noreferrer" :href="[[imprint_url]]" class="ml-3 text-gray-400 underline">{{
target="_blank" $t('imprint') }}</a>
rel="noopener,noreferrer" <a target="_blank" rel="noopener,noreferrer" :href="[[privacy_url]]" class="ml-3 text-gray-400 underline">{{
:href="[[imprint_url]]" $t('privacy_policy') }}</a>
class="ml-3 text-gray-400 underline"
>Impressum</a>
<a
target="_blank"
rel="noopener,noreferrer"
:href="[[privacy_url]]"
class="ml-3 text-gray-400 underline"
>Datenschutzerklärung</a>
</span> </span>
</div> </div>
</footer> </footer>
@ -31,8 +19,8 @@
export default { export default {
data() { data() {
return { return {
imprint_url: config.url_imprint || "/imprint/" imprint_url: config.url_imprint || "/imprint"
, privacy_url: config.url_privacy || "/privacy/" , privacy_url: config.url_privacy || "/privacy"
} }
}, },
} }

View File

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

View File

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

View File

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

View File

@ -1,41 +1,71 @@
{ {
"already_have_an_account": "Sie haben bereits einen Account?", "access_is_only_provided_via_your_email_link": "Der Zugang erfolgt über den Link, den Sie bei der Registrierung erhalten haben.",
"alle_daten_geloescht": "Alle Daten gelöscht!",
"already_registered": "bereits registriert...",
"amount_per_kilometer_in_eur": "Betrag pro Kilometer (in €)",
"apartment_suite_etc": "Addresszeile 2", "apartment_suite_etc": "Addresszeile 2",
"buergerlauf": "Bürgerlauf",
"cancel_keep_my_data": "Abbrechen, meine Daten behalten",
"configuration_error": "Konfigurationsfehler", "configuration_error": "Konfigurationsfehler",
"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 €)",
"delete_my_data": "Meine Daten löschen",
"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", "error-loading-privacy-policy": "Fehler beim Laden der Datenschutzerklärung",
"error_loading_imprint": "Fehler beim Laden des Impressums",
"error_requesting_the_login_link": "Fehler beim Anfordern des Login-Links...",
"i_accept": "Ich habe die ", "i_accept": "Ich habe die ",
"i_accept_end": "gelesen und akzeptiert.", "i_accept_end": "gelesen und akzeptiert.",
"if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance": "Wenn Sie der Systemadministrator sind, finden Sie Konfigurationsanweisungen in der offiziellen Produktdokumentation / README.", "if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance": "Wenn Sie der Systemadministrator sind, finden Sie Konfigurationsanweisungen in der offiziellen Produktdokumentation / README.",
"imprint": "Impressum", "imprint": "Impressum",
"invalid_input_phone_number_should_be_international_format": "ungültige Eingabe... Die Telefonnummer sollte ein internationales Format haben",
"lap_time": "Rundenzeit", "lap_time": "Rundenzeit",
"lap_times": "Rundenzeiten", "lap_times": "Rundenzeiten",
"login_link_gesendet_an_user_email_value": "Login-Link gesendet an ",
"login_link_is_requested": "Login-Link wird angefordert...",
"lost_your_registration_mail": "Brauchen Sie einen neuen Login-Link?",
"main_page_text": "Hier können Sie sich für den Lauf Für Kaya! registrieren oder ihr Läuferprofil verwalten.", "main_page_text": "Hier können Sie sich für den Lauf Für Kaya! registrieren oder ihr Läuferprofil verwalten.",
"mittelname": "Mittelname", "mittelname": "Mittelname",
"nachname": "Nachname", "nachname": "Nachname",
"no_laps_scans_were_recorded_yet": "Es wurden noch keine Runden / Scans aufgezeichnet ...", "no_laps_scans_were_recorded_yet": "Es wurden noch keine Runden / Scans aufgezeichnet ...",
"no_sponsorings_for_you_were_recorded_yet": "Es gibt noch keine Sponsorings für dich",
"not_registered_yet": "Noch nicht registriert?",
"organization": "Organisation",
"ort": "Ort", "ort": "Ort",
"phone_number": "Telefonnummer", "phone_number": "Telefonnummer (international formatiert)",
"please_provide_a_valid_zipcode": "Bitte geben Sie eine gültige Postleitzahl an...", "please_provide_a_valid_zipcode": "Bitte geben Sie eine gültige Postleitzahl an...",
"please_provide_valid_mail": "Bitte geben Sie eine gültige E-Mail Adresse an", "please_provide_valid_mail": "Bitte geben Sie eine gültige E-Mail Adresse an",
"plz": "PLZ", "plz": "PLZ",
"privacy_policy": "Datenschutzerklärung", "privacy_policy": "Datenschutzerklärung",
"profil_konnte_nicht_geladen_werden": "Profil konnte nicht geladen werden...",
"profil_konnte_nicht_geloescht_werden": "Profil konnte nicht gelöscht werden...",
"profil_wird_geloescht": "Profil wird gelöscht...",
"profile": "Profil", "profile": "Profil",
"provide_address": "Adresse angeben?", "provide_address": "Adresse angeben?",
"register": { "register": {
"register_now": "Jetzt für den Lauf für Kaya! 2021 registrieren." "register_now": "Jetzt für den Lauf für Kaya! 2025 registrieren."
}, },
"register_now": "Jetzt registrieren!", "register_now": "Jetzt registrieren!",
"register_now_small": "Jetzt registrieren",
"registration_running": "Registrierung läuft...",
"registrationcode": "Registrierungscode",
"registrieren": "Registrieren", "registrieren": "Registrieren",
"save_changes": "Änderungen speichern", "registriert": "Registriert",
"registrierungscode_generiert": "Registrierungscode generiert!",
"registrierungscode_wird_generiert": "Registrierungscode wird generiert...",
"resend_the_registration_mail": "Login-Link anfordern",
"sponsoring": "Sponsoring", "sponsoring": "Sponsoring",
"strasse": "Straße", "strasse": "Straße",
"the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help": "Das System ist nicht richtig konfiguriert. Bitte wenden Sie sich an den Systemadministrator, um Hilfe zu erhalten.", "the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help": "Das System ist nicht richtig konfiguriert. Bitte wenden Sie sich an den Systemadministrator, um Hilfe zu erhalten.",
"this_is_not_a_valid_international_phone_number": "Dies ist keine gültige internationale Telefonnummer", "this_is_not_a_valid_international_phone_number": "Dies ist keine gültige internationale Telefonnummer",
"tos": "AGBs", "total": "Gesamt",
"urkunde_generiert": "Urkunde generiert!",
"urkunde_konnte_nicht_generiert_werden": "Urkunde konnte nicht generiert werden...",
"urkunde_wird_generiert": "Urkunde wird generiert...",
"view_my_data": "Meine Läuferdaten einsehen", "view_my_data": "Meine Läuferdaten einsehen",
"vorname": "Vorname" "vorname": "Vorname"
} }

View File

@ -1,43 +1,71 @@
{ {
"already_have_an_account": "Already have an account?", "access_is_only_provided_via_your_email_link": "Access is only provided via the link you received upon registration.",
"alle_daten_geloescht": "all data deleted!",
"already_registered": "already registered...",
"amount_per_kilometer_in_eur": "Amount per kilometer (in €)",
"apartment_suite_etc": "Apartment, suite, etc.", "apartment_suite_etc": "Apartment, suite, etc.",
"buergerlauf": "Public Run",
"cancel_keep_my_data": "Cancel, keep my data",
"configuration_error": "Configuration error", "configuration_error": "Configuration error",
"confirm_delete_all_of_my_data": "Confirm, delete all of my data",
"confirm_personal_data": "I hereby confirm that the above information is complete and correct", "confirm_personal_data": "I hereby confirm that the above information is complete and correct",
"current_total_amount_in_eur": "Current total amount (in €)",
"delete_my_data": "Delete my data",
"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", "error-loading-privacy-policy": "Error loading Privacy Policy",
"error_loading_imprint": "Error loading Imprint",
"error_requesting_the_login_link": "Error requesting the login link...",
"i_accept": "I have read and accepted the ", "i_accept": "I have read and accepted the ",
"i_accept_end": "", "i_accept_end": "",
"if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance": "If you are the system administrator, please refer to the official product documentation/ README for configuration guidance.", "if_you_are_the_system_administrator_please_refer_to_the_official_product_documentation_readme_for_configuration_guidance": "If you are the system administrator, please refer to the official product documentation/ README for configuration guidance.",
"imprint": "Imprint", "imprint": "Imprint",
"invalid_input_phone_number_should_be_international_format": "invalid input... phone number should be international format",
"lap_time": "Lap time", "lap_time": "Lap time",
"lap_times": "Lap times", "lap_times": "Lap times",
"login_link_gesendet_an_user_email_value": "Login-Link sent to ",
"login_link_is_requested": "Login link is requested...",
"lost_your_registration_mail": "Lost your registration mail?",
"main_page_text": "Here you can register for the Lauf Für Kaya! or manage your runner profile.", "main_page_text": "Here you can register for the Lauf Für Kaya! or manage your runner profile.",
"mittelname": "Middlename", "mittelname": "Middlename",
"nachname": "Lastname", "nachname": "Lastname",
"no_laps_scans_were_recorded_yet": "No laps/ scans were recorded yet...", "no_laps_scans_were_recorded_yet": "No laps/ scans were recorded yet...",
"no_sponsorings_for_you_were_recorded_yet": "No sponsorings for you were recorded yet...",
"not_registered_yet": "Not registered yet?",
"organization": "Organization", "organization": "Organization",
"ort": "City", "ort": "City",
"phone_number": "Phone Number", "phone_number": "Phone Number (international format)",
"please_provide_a_valid_zipcode": "Please provide a valid zipcode...", "please_provide_a_valid_zipcode": "Please provide a valid zipcode...",
"please_provide_valid_mail": "Please provide a valid mail address.", "please_provide_valid_mail": "Please provide a valid mail address.",
"plz": "zipcode", "plz": "zipcode",
"privacy_policy": "Privacy Policy", "privacy_policy": "Privacy Policy",
"profil_konnte_nicht_geladen_werden": "could not load profile...",
"profil_konnte_nicht_geloescht_werden": "couold not delete profile...",
"profil_wird_geloescht": "deleting profile...",
"profile": "Profile", "profile": "Profile",
"provide_address": "Provide a postal address?", "provide_address": "Provide a postal address?",
"register": { "register": {
"register_now": "Register now for Lauf für Kaya! 2021." "register_now": "Register now for Lauf für Kaya! 2025."
}, },
"register_now": "Register now!", "register_now": "Register now!",
"register_now_small": "Register now",
"registration_running": "registration is running...",
"registrationcode": "Registration Code",
"registrieren": "Register Now", "registrieren": "Register Now",
"save_changes": "Save changes", "registriert": "Registered",
"registrierungscode_generiert": "created registration code!",
"registrierungscode_wird_generiert": "creating registration code...",
"resend_the_registration_mail": "Send me a login link",
"sponsoring": "Sponsoring", "sponsoring": "Sponsoring",
"strasse": "Street/ Block", "strasse": "Street/ Block",
"the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help": "The system is not properly configured. Please contact the system administrator for help.", "the_system_is_not_properly_configured_please_contact_the_system_administrator_for_help": "The system is not properly configured. Please contact the system administrator for help.",
"this_is_not_a_valid_international_phone_number": "This is not a valid international phone number", "this_is_not_a_valid_international_phone_number": "This is not a valid international phone number",
"tos": "Terms of Service", "total": "Total",
"urkunde_generiert": "created certificate",
"urkunde_konnte_nicht_generiert_werden": "could not create your certificate...",
"urkunde_wird_generiert": "creating certificate...",
"view_my_data": "View my data", "view_my_data": "View my data",
"vorname": "Firstname", "vorname": "Firstname"
"you_have_been_registered": "You have been registered!"
} }

View File

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

View File

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

View File

@ -1,3 +1 @@
@import 'tailwindcss/base'; @import "tailwindcss";
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

View File

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

View File

@ -2,22 +2,24 @@
<section class="container px-4 py-24 mx-auto"> <section class="container px-4 py-24 mx-auto">
<div class="simplecontent"> <div class="simplecontent">
<div class="mb-24 text-left md:text-center"> <div class="mb-24 text-left md:text-center">
<h1 <h1 class="mb-4 text-4xl font-bold leading-tight text-gray-900 dark:text-gray-50 md:text-5xl">{{ $t('imprint')
class="mb-4 text-4xl font-bold leading-tight text-gray-900 dark:text-gray-50 md:text-5xl" }}
>{{$t('imprint')}}</h1> </h1>
</div> </div>
<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() {
@ -29,7 +31,7 @@ export default {
try { try {
md = await fetch(`/imprint_en.md`); md = await fetch(`/imprint_en.md`);
} catch (error) { } catch (error) {
md = "Error loading Imprint"; md = t('error_loading_imprint');
} }
} }
this.content = marked(await md.text()); this.content = marked(await md.text());

View File

@ -2,19 +2,20 @@
<section class="container px-4 py-24 mx-auto"> <section class="container px-4 py-24 mx-auto">
<div class="simplecontent"> <div class="simplecontent">
<div class="mb-24 text-left md:text-center"> <div class="mb-24 text-left md:text-center">
<h1 <h1 class="mb-4 text-4xl font-bold leading-tight text-gray-900 dark:text-gray-50 md:text-5xl">{{
class="mb-4 text-4xl font-bold leading-tight text-gray-900 dark:text-gray-50 md:text-5xl" $t('privacy_policy') }}</h1>
>{{ $t('privacy_policy') }}</h1>
</div> </div>
<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: ""
@ -29,7 +30,7 @@ export default {
try { try {
md = await fetch(`/privacy_en.md`); md = await fetch(`/privacy_en.md`);
} catch (error) { } catch (error) {
md = "Error loading Privacy Policy"; md = t('error-loading-privacy-policy');
} }
} }
this.content = marked(await md.text()); this.content = marked(await md.text());

View File

@ -1,209 +1,638 @@
<template> <template>
<div class="min-h-screen w-full p-4"> <div class="min-h-screen w-full p-4">
<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="
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" flex flex-col
> md:pr-10 md:mb-0
<p mb-6
class="text-3xl font-bold whitespace-nowrap" pr-0
v-text="(state.firstname || '') + ' ' + (state.middlename || '') + ' ' + (state.lastname || '')" w-full
></p> md:w-auto md:text-left
<p class="text-md whitespace-nowrap">{{ state.group }}</p> text-center text-black
</div> dark:text-gray-200
<div class="inline-flex md:ml-auto md:mr-0 mx-auto items-center"> ">
<button <p class="text-4xl md:text-3xl font-bold whitespace-nowrap font-[Athiti]" v-text="(state.firstname || '') +
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" (state.middlename || '') +
> ' ' +
<svg (state.lastname || '')
xmlns="http://www.w3.org/2000/svg" "></p>
width="24" <p class="text-md whitespace-nowrap">{{ state.group }}</p>
height="24" </div>
viewBox="0 0 24 24" <div class="inline-flex md:ml-auto md:mr-0 mx-auto items-center">
fill="none" <div v-if="state.delete_active === false">
stroke="currentColor" <button type="button" class="
stroke-width="2" focus:border-black focus:ring-2 focus:ring-black
stroke-linecap="round" text-white text-base md:text-sm
stroke-linejoin="round" py-3.5
class="feather feather-download" px-5
style="display: inline;height: 1rem;vertical-align: sub;" md:py-2.5
> md:px-5
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> rounded-md
<polyline points="7 10 12 15 17 10" /> bg-blue-500
<line x1="12" y1="15" x2="12" y2="3" /> hover:bg-blue-600 hover:shadow-lg
</svg> w-full
{{ $t('download_certificate') }} md:w-auto
</button> mb-1
</div> md:mr-1
</div> " @click="get_registration">
</section> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
<div class="flex flex-wrap"> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
<div class="w-full p-4"> class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
<div class="flex flex-wrap flex-col w-full tabs"> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<div class="flex lg:flex-wrap flex-row lg:space-x-2"> <polyline points="7 10 12 15 17 10" />
<div class="flex-none"> <line x1="12" y1="15" x2="12" y2="3" />
<button </svg>
@click="() => { state.activetab = 'profile' }" {{ $t("download_registrationcode") }}
:class="{ 'tab-active border-b-2 font-medium border-blue-500': (state.activetab === 'profile') }" </button>
class="tab tab-underline py-4 px-6 block" <button type="button" class="
type="button" focus:border-black focus:ring-2 focus:ring-black
>{{ $t('profile') }}</button> text-white text-base md:text-sm
</div> py-3.5
<div class="flex-none"> px-5
<button md:py-2.5
@click="() => { state.activetab = 'laptimes' }" md:px-5
:class="{ 'tab-active border-b-2 font-medium border-blue-500': (state.activetab === 'laptimes') }" rounded-md
class="tab tab-underline py-4 px-6 block" bg-blue-500
type="button" hover:bg-blue-600 hover:shadow-lg
>{{ $t('lap_times') }}</button> w-full
</div> md:w-auto
<div class="flex-none"> mb-1
<button md:mr-1
@click="() => { state.activetab = 'sponsorings' }" " @click="get_certificate">
:class="{ 'tab-active border-b-2 font-medium border-blue-500': (state.activetab === 'sponsorings') }" <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
class="tab tab-underline py-4 px-6 block" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
type="button" class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
>{{ $t('sponsoring') }}</button> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
</div> <polyline points="7 10 12 15 17 10" />
</div> <line x1="12" y1="15" x2="12" y2="3" />
<div v-if="(state.activetab === 'profile')" class="tab-content block"> </svg>
<div class="py-4 w-full"> {{ $t("download_certificate") }}
<div class="flex flex-col"> </button>
<form class="form flex flex-wrap w-full"> <button type="button" class="
<div class="w-full"> focus:border-black focus:ring-2 focus:ring-black
<div class="form-element"> text-white text-base md:text-sm
<div class="text-lg">{{ $t('vorname') }}</div> py-3.5
<p px-5
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" md:py-2.5
v-text="state.firstname" md:px-5
/> rounded-md
</div> bg-red-600
<div class="form-element"> hover:bg-red-700 hover:shadow-lg
<div class="text-lg">{{ $t('mittelname') }}</div> w-full
<p md:w-auto
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" " @click="() => {
v-text="state.middlename" state.delete_active = true;
/> }
</div> ">
<div class="form-element"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
<div class="text-lg">{{ $t('nachname') }}</div> stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
<p class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
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" <path d="M0 0h24v24H0z" />
v-text="state.lastname" <path fill="currentColor"
/> d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z" />
</div> </svg>
<div class="form-element"> {{ $t("delete_my_data") }}
<div class="text-lg">{{ $t('e_mail_adress') }}</div> </button>
<p </div>
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" <div v-if="state.delete_active === true">
v-text="state.email" <button type="button" class="
/> focus:border-black focus:ring-2 focus:ring-black
</div> text-white text-base md:text-sm
<div class="form-element"> py-3.5
<div class="text-lg">{{ $t('phone_number') }}</div> px-5
<p md:py-2.5
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" md:px-5
v-text="state.phone" rounded-md
/> mb-1
</div> md:mb-auto
</div> w-full
</form> md:w-auto
</div> bg-blue-500
</div> hover:bg-blue-600 hover:shadow-lg
</div> " @click="() => {
<div v-if="(state.activetab === 'laptimes')" class="tab-content block"> state.delete_active = false;
<div class="py-4 w-full"> }
<section class="text-gray-400 dark:bg-gray-900 body-font"> ">
<div class="container mx-auto"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
<div class="lg:w-2/3 w-full mx-auto overflow-auto"> stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
<table class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
v-if="state.scans.length > 0" <path fill="none" d="M0 0h24v24H0z" />
class="table-auto w-full text-left whitespace-no-wrap" <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>
<thead {{ $t("cancel_keep_my_data") }}
class="text-black bg-gray-300 dark:text-white text-sm dark:bg-gray-800" </button>
> <button type="button" class="
<tr> focus:border-black focus:ring-2 focus:ring-black
<th text-white text-base md:text-sm
class="px-4 py-3 title-font tracking-wider font-medium" py-3.5
>{{ $t('distance') }}</th> px-5
<th md:py-2.5
class="px-4 py-3 title-font tracking-wider font-medium" md:px-5
>{{ $t('lap_time') }}</th> rounded-md
</tr> w-full
</thead> md:w-auto
<tbody class="text-gray-900 dark:text-gray-50"> bg-red-600
<tr v-for="s in state.scans" :key="s.id"> hover:bg-red-700 hover:shadow-lg
<td class="px-4 py-3"> md:ml-1
<span v-text="s.distance"></span>m " @click="delete_me">
</td> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
<td class="px-4 py-3" v-text="s.lapTime"></td> stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
</tr> class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
</tbody> <path d="M0 0h24v24H0z" />
</table> <path fill="currentColor"
<div v-else class="text-center font-bold text-black dark:text-white text-2xl"> 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" />
<img </svg>
src="../assets/empty_laps.svg" {{ $t("confirm_delete_all_of_my_data") }}
style="height:25rem; margin:0 auto;" </button>
:alt="[[$t('no_laps_scans_were_recorded_yet')]]" </div>
/> </div>
{{ $t('no_laps_scans_were_recorded_yet') }} </div>
</div> </section>
</div> <div class="flex flex-wrap">
</div> <div class="w-full">
</section> <div class="flex flex-wrap flex-col w-full tabs">
</div> <div class="flex lg:flex-wrap flex-row lg:space-x-2">
</div> <div class="flex-none">
<div v-if="(state.activetab === 'sponsorings')" class="tab-content block"> <button @click="() => {
<div class="py-4 w-full">coming soon...</div> state.activetab = 'profile';
</div> }
</div> " :class="{
</div> 'tab-active border-b-2 font-medium border-blue-500':
</div> state.activetab === 'profile',
</div> }" class="tab tab-underline py-4 px-6 block" type="button">
</template> {{ $t("profile") }}
</button>
<script setup> </div>
import { reactive } from "vue"; <div class="flex-none">
import { useToast } from "vue-toastification"; <button @click="() => {
import axios from "redaxios"; state.activetab = 'laptimes';
}
const state = reactive({ " :class="{
phone: "", 'tab-active border-b-2 font-medium border-blue-500':
email: "", state.activetab === 'laptimes',
firstname: "", }" class="tab tab-underline py-4 px-6 block" type="button">
middlename: "", {{ $t("lap_times") }}
lastname: "", </button>
scans: [], </div>
group: "", <div class="flex-none">
activetab: "profile", <button @click="() => {
}) state.activetab = 'sponsorings';
const toast = useToast(); }
const props = defineProps({ " :class="{
token: String 'tab-active border-b-2 font-medium border-blue-500':
}) state.activetab === 'sponsorings',
const accesstoken = atob(props.token); }" class="tab tab-underline py-4 px-6 block" type="button">
axios.get(`${config.baseurl_selfservice}/api/runners/me/${accesstoken}`) {{ $t("sponsoring") }}
.then(({ data }) => { </button>
state.phone = data.phone; </div>
state.email = data.email; </div>
state.firstname = data.firstname; <div v-if="state.activetab === 'profile'" class="tab-content block">
state.middlename = data.middlename; <div class="py-4 w-full">
state.lastname = data.lastname; <div class="flex flex-col">
state.group = data.group; <form class="form flex flex-wrap w-full">
}).catch((error) => { <div class="w-full">
toast.error("An error occured while loading your profile data"); <div class="form-element">
}) <div class="text-lg">{{ $t("registrationcode") }}</div>
axios.get(`${config.baseurl}api/runners/me/${accesstoken}/scans`) <img class="w-full md:w-auto mb-2 bg-white p-2" alt="Registrierungscode" :src="state.barcode" />
.then(({ data }) => { <div class="text-lg">{{ $t("vorname") }}</div>
data.map(function(s) { <p class="
s.lapTime = Math.floor(s.lapTime / 60) + 'min ' + (Math.floor(s.lapTime % 60) + "").padStart(2, "0") + "s" h-10
return s; w-full
}) dark:bg-gray-800
data.filter(s => s.valid === true); rounded
state.scans = data; text-base
}).catch((error) => { outline-none
toast.error("An error occured while loading your profile data"); 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 class="form-element">
<div class="text-lg">{{ $t("mittelname") }}</div>
<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
" v-text="state.middlename || '---'" />
</div>
<div class="form-element">
<div class="text-lg">{{ $t("nachname") }}</div>
<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
" v-text="state.lastname || '---'" />
</div>
<div class="form-element">
<div class="text-lg">{{ $t("e_mail_adress") }}</div>
<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
" v-text="state.email || '---'" />
</div>
<div class="form-element">
<div class="text-lg">{{ $t("phone_number") }}</div>
<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
" v-text="state.phone || '---'" />
</div>
</div>
</form>
</div>
</div>
</div>
<div v-if="state.activetab === 'laptimes'" class="tab-content block">
<div class="py-4 w-full">
<section class="text-gray-400 dark:bg-gray-900 body-font">
<div class="container mx-auto">
<div class="lg:w-2/3 w-full mx-auto overflow-auto">
<table v-if="state.scans.length > 0" class="table-auto w-full text-left whitespace-no-wrap">
<thead class="
text-black
bg-gray-300
dark:text-white
text-sm
dark:bg-gray-800
">
<tr>
<th class="
px-4
py-3
title-font
tracking-wider
font-medium
">
{{ $t("distance") }}
</th>
<th class="
px-4
py-3
title-font
tracking-wider
font-medium
">
{{ $t("lap_time") }}
</th>
</tr>
</thead>
<tbody class="text-gray-900 dark:text-gray-50">
<tr v-for="s in state.scans" :key="s.id">
<td class="px-4 py-3">
<span v-text="s.distance"></span>
</td>
<td class="px-4 py-3" v-text="s.lapTime"></td>
</tr>
</tbody>
</table>
<div v-else class="
text-center
font-bold
text-black
dark:text-white
text-2xl
">
<img src="../assets/empty_laps.svg" style="height: 25rem; margin: 0 auto"
:alt="[[$t('no_laps_scans_were_recorded_yet')]]" />
{{ $t("no_laps_scans_were_recorded_yet") }}
</div>
</div>
</div>
</section>
</div>
</div>
<div v-if="state.activetab === 'sponsorings'" class="tab-content block">
<div class="py-4 w-full">
<section class="text-gray-400 dark:bg-gray-900 body-font">
<div class="container mx-auto">
<div class="lg:w-2/3 w-full mx-auto overflow-auto">
<table v-if="state.sponsorings.length > 0" class="table-auto w-full text-left whitespace-no-wrap">
<thead class="
text-black
bg-gray-300
dark:text-white
text-sm
dark:bg-gray-800
">
<tr>
<th class="
px-4
py-3
title-font
tracking-wider
font-medium
">
Name
</th>
<th class="
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>
</thead>
<tbody class="text-gray-900 dark:text-gray-50">
<tr v-for="s in state.sponsorings" :key="s.id">
<td class="px-4 py-3">
<span v-text="s.donor.firstname"></span>
<span v-if="s.donor.middlename">
<span v-text="s.donor.middlename"></span>
</span>
<span v-text="s.donor.lastname"></span>
</td>
<td class="px-4 py-3">
<span v-text="(s.amountPerDistance / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })
"></span>
</td>
<td class="px-4 py-3">
<span v-text="(s.amount / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })
"></span>
</td>
</tr>
</tbody>
<tfoot class="text-gray-900 dark:text-gray-50">
<tr>
<td class="px-4 py-3">{{ $t("total") }}</td>
<td class="px-4 py-3">
<span v-text="(
state.sponsorings.reduce(function (
sum,
current
) {
return sum + current.amountPerDistance;
},
0) / 100
)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })
"></span>
</td>
<td class="px-4 py-3">
<span v-text="(
state.sponsorings.reduce(function (
sum,
current
) {
return sum + current.amount;
},
0) / 100
)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })
"></span>
</td>
</tr>
</tfoot>
</table>
<div v-else class="
text-center
font-bold
text-black
dark:text-white
text-2xl
">
<img src="../assets/empty_laps.svg" style="height: 25rem; margin: 0 auto" :alt="[
[$t('no_sponsorings_for_you_were_recorded_yet')],
]" />
{{ $t("no_sponsorings_for_you_were_recorded_yet") }}
</div>
</div>
</div>
</section>
</div>
</div>
</div>
</div>
</div>
<!-- -->
<Footer></Footer>
</div>
</template>
<script setup>
import { reactive } from "vue";
import { TYPE, useToast } from "vue-toastification";
import axios from "redaxios";
import { toCanvas } from "bwip-js";
import Footer from "@/components/Footer.vue";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
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;
}
toCanvas(canvas, codeconfig);
return canvas.toDataURL("image/png");
}
const state = reactive({
barcode: "",
phone: "",
email: "",
firstname: "",
middlename: "",
lastname: "",
scans: [],
sponsorings: [],
group: "",
activetab: "profile",
delete_active: false,
fullobject: {},
});
const toast = useToast();
const props = defineProps({
token: String,
});
const accesstoken = atob(props.token);
axios
.get(`${config.baseurl}api/runners/me/${accesstoken}`)
.then(({ data }) => {
state.phone = data.phone;
state.email = data.email;
state.firstname = data.firstname;
state.middlename = data.middlename;
state.lastname = data.lastname;
state.group = data.group;
state.sponsorings = data.distanceDonations;
state.fullobject = data;
state.barcode = textToBase64Barcode(data.id ?? "???");
})
.catch((error) => {
toast.clear();
toast.error(t('profil_konnte_nicht_geladen_werden'));
});
axios
.get(`${config.baseurl}api/runners/me/${accesstoken}/scans`)
.then(({ data }) => {
data.map(function (s) {
s.lapTime =
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;
});
data.filter((s) => s.valid === true);
state.scans = data;
})
.catch((error) => {
toast.error(t('profil_konnte_nicht_geladen_werden'));
});
function delete_me() {
toast.clear();
toast(t('profil_wird_geloescht'));
let url = `${config.baseurl}api/runners/me/${accesstoken}?force=true`;
axios
.delete(url)
.then(() => {
toast.clear();
toast(t('alle_daten_geloescht'));
location.replace(`/`);
})
.catch((error) => {
toast.clear();
toast.error(t('profil_konnte_nicht_geloescht_werden'));
});
}
function get_certificate() {
toast(t('urkunde_wird_generiert'));
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 postdata = Object.assign({}, state.fullobject);
postdata.group = {
name: postdata.group,
};
postdata = [postdata];
axios
.post(url, postdata, {
responseType: "blob",
})
.then((response) => {
console.log(response);
if (response.status !== 200) {
toast.error(t('urkunde_konnte_nicht_generiert_werden'));
} else {
var fileURL = window.URL.createObjectURL(
new Blob([response.data], { type: "application/pdf" })
);
var fileLink = document.createElement("a");
fileLink.href = fileURL;
fileLink.setAttribute("download", "Certificate.pdf");
document.body.appendChild(fileLink);
fileLink.click();
fileLink.remove();
toast.clear();
toast(t('urkunde_generiert'), { type: TYPE.SUCCESS });
}
})
.catch((err) => {
console.error(err);
toast.clear();
toast.error(t('urkunde_konnte_nicht_generiert_werden'));
});
}
function get_registration() {
toast.clear();
toast(t('registrierungscode_wird_generiert'));
var a = document.createElement("a");
a.href = state.barcode;
a.download = "LfK25_Registrierungscode.png";
a.click();
toast.clear();
toast(t('registrierungscode_generiert'), { type: TYPE.SUCCESS });
}
</script> </script>

View File

@ -1 +1,93 @@
<template>You have not provided a valid access key...</template> <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-lfk.png" alt />
<h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center font-[Athiti]">Lauf für Kaya! - {{
$t('profile')
}}</h1>
<p class="mx-auto leading-relaxed text-base text-center">
{{ $t('access_is_only_provided_via_your_email_link') }}
</p>
<div class="mt-6">
<div class="relative">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div>
</div>
<div class="relative flex justify-center text-sm">
<span class="px-2 bg-white dark:bg-gray-900">{{ $t('lost_your_registration_mail') }}</span>
</div>
</div>
<div class="mt-4">
<label for="email_address" class="block font-medium">
{{ $t('e_mail_adress') }}
<span class="font-bold">*</span>
</label>
<input v-model="user_email" name="email_address" id="email_address" autocomplete="email"
:placeholder="[[$t('e_mail_adress')]]" type="email"
:class="{ 'border-red-500': (!isEmail(user_email)), 'border-green-300': (isEmail(user_email)) }"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-2 bg-gray-50 text-gray-500 rounded-md p-2" />
<p v-if="!isEmail(user_email) && user_email !== ''" class="text-sm">{{
$t('please_provide_valid_mail')
}}</p>
</div>
<div class="mt-2">
<button :disabled="(!state.submit_enabled)"
:class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }"
@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">{{
$t('resend_the_registration_mail') }}</button>
</div>
</div>
<div class="mt-12">
<div class="relative">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div>
</div>
<div class="relative flex justify-center text-sm">
<span class="px-2 bg-white dark:bg-gray-900">{{ $t('not_registered_yet') }}</span>
</div>
</div>
<div class="mt-2">
<a href="/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">{{
$t('register_now_small') }}</a>
</div>
</div>
</div>
</div>
<Footer></Footer>
</template>
<script setup>
import { computed, ref, reactive } from "vue";
import axios from "redaxios";
import isEmail from 'validator/es/lib/isEmail';
import { TYPE, useToast } from "vue-toastification";
import Footer from "@/components/Footer.vue";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
let user_email = ref("");
//
const state = reactive({
org_name: "",
org_teams: [],
submit_enabled: computed(() => isEmail(user_email.value))
})
const toast = useToast();
function resendMail() {
if (isEmail(user_email.value)) {
toast(t('login_link_is_requested'));
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
axios.post(`${config.baseurl}api/runners/login?mail=${user_email.value}&locale=${browserlocale}`)
.then(({ data }) => {
console.log(data);
toast(t('login_link_gesendet_an_user_email_value') + user_email.value);
})
.catch((error) => {
console.log(error);
toast(t('error_requesting_the_login_link'), { type: TYPE.ERROR });
});
}
}
</script>

View File

@ -1,339 +1,454 @@
<template> <template>
<div class="min-h-screen flex items-center justify-center"> <div class="min-h-screen flex items-center justify-center" v-if="registrationState === 'registered'">
<div class="max-w-md w-full py-12 px-6"> <div class="max-w-md w-full py-12 px-6 font-[Athiti]">
<img class="mx-auto h-24 w-auto" src="/favicon.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt />
<h1 <h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center">
class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center" Lauf für Kaya! - {{ $t('registriert') }}
>Lauf für Kaya! - {{ $t('registrieren') }}</h1> </h1>
<p class="mx-auto leading-relaxed text-base text-center">{{ $t('register.register_now') }}</p> <p class="mx-auto leading-relaxed text-base text-center">
<p Bitte klicken Sie zum Fortfahren auf den Link, den wir an
v-if="state.org_name !== ''" <b class="font-bold">{{ userdetails.mail }}</b> geschickt haben.
class="mx-auto leading-relaxed text-base text-center" </p>
>{{ $t('organization') }}: {{ state.org_name }}</p> </div>
<p </div>
v-if="state.org_name !== '' && state.org_teams.length > 0" <div class="min-h-screen flex items-center justify-center" v-else>
class="mx-auto leading-relaxed text-base text-center" <div class="max-w-md w-full py-12 px-6 font-[Athiti]">
>Team:</p> <img class="mx-auto h-24 w-auto" src="/favicon-lfk.png" alt />
<select <h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center">
v-model="org_team" Lauf für Kaya! - {{ $t("registrieren") }}
v-if="state.org_name !== '' && state.org_teams.length > 0" </h1>
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" <p class="mx-auto leading-relaxed text-base text-center font-medium">
> {{ $t("register.register_now") }}
<option v-for="t in state.org_teams" :key="t.id" :value="t.id">{{ t.name }}</option> </p>
</select> <p v-if="state.org_name !== ''" class="mx-auto leading-relaxed text-base text-center font-medium">
<p {{ $t("organization") }}: {{ state.org_name }}
v-if="state.org_name === ''" </p>
class="mx-auto leading-relaxed text-base text-center" <p v-if="state.org_name !== '' && state.org_teams.length > 0"
>Bürgerlauf</p> class="mx-auto leading-relaxed text-base text-center">
<div class="mt-4"> Team:
<label for="first_name" class="block font-medium"> </p>
{{ $t('vorname') }} <select v-model="org_team" v-if="state.org_name !== '' && state.org_teams.length > 0" class="
<span class="font-bold">*</span> w-full
</label> border
<input bg-white
v-model="userdetails.firstname" rounded
name="firstname" px-3
id="first_name" py-2
autocomplete="off" outline-none
:placeholder="[[$t('vorname')]]" block
type="text" mt-1
:class="{ 'border-red-500': (!userdetails.firstname.trim()), 'border-green-300': (userdetails.firstname.trim()) }" 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="middle_name" class="block font-medium">{{ $t('mittelname') }}</label> dark:focus:shadow-outline-gray
<input ">
v-model="userdetails.middlename" <option v-for="t in state.org_teams" :key="t.id" :value="t.id">
name="middlename" {{ t.name }}
id="middle_name" </option>
autocomplete="off" </select>
:placeholder="[[$t('mittelname')]]" <p v-if="state.org_name === ''" class="mx-auto leading-relaxed text-base text-center">
type="text" {{ $t('buergerlauf') }}
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="last_name" class="block font-medium"> {{ $t("vorname") }}
{{ $t('nachname') }} <span class="font-bold">*</span>
<span class="font-bold">*</span> </label>
</label> <input v-model="userdetails.firstname" name="firstname" id="first_name" autocomplete="off"
<input :placeholder="[[$t('vorname')]]" type="text" :class="{
v-model="userdetails.lastname" 'border-red-500': !userdetails.firstname.trim(),
name="lastname" 'border-green-300': userdetails.firstname.trim(),
id="last_name" }" class="
autocomplete="off" dark:bg-gray-800
:placeholder="[[$t('nachname')]]" mt-1
type="text" block
:class="{ 'border-red-500': (!userdetails.lastname.trim()), 'border-green-300': (userdetails.lastname.trim()) }" w-full
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" shadow-sm
/> sm:text-sm
<!-- --> border-gray-300 border-2
<label for="email_address" class="block font-medium"> bg-gray-50
{{ $t('e_mail_adress') }} text-gray-500
<span class="font-bold">*</span> rounded-md
</label> p-2
<input " />
v-model="userdetails.mail" <!-- -->
name="email_address" <label for="middle_name" class="block font-medium">{{
id="email_address" $t("mittelname")
autocomplete="off" }}</label>
:placeholder="[[$t('e_mail_adress')]]" <input v-model="userdetails.middlename" name="middlename" id="middle_name" autocomplete="off"
type="email" :placeholder="[[$t('mittelname')]]" type="text" class="
:class="{ 'border-red-500': (!isEmail(userdetails.mail)), 'border-green-300': (isEmail(userdetails.mail)) }" dark:bg-gray-800
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" mt-1
/> block
<p v-if="!isEmail(userdetails.mail)" class="text-sm">{{ $t('please_provide_valid_mail') }}</p> w-full
<!-- --> shadow-sm
<label for="phone" class="select-none block font-medium">{{ $t('phone_number') }}</label> sm:text-sm
<input border-gray-300 border-2
v-model="userdetails.phone" bg-gray-50
name="phone" text-gray-500
id="phone" rounded-md
autocomplete="off" p-2
:placeholder="[[$t('phone_number')]]" " />
type="text" <!-- -->
:class="{ 'border-red-500': (!isMobilePhone(userdetails.phone) && userdetails.phone.trim()), 'border-green-300': (isMobilePhone(userdetails.phone) && userdetails.phone.trim()) }" <label for="last_name" class="block font-medium">
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" {{ $t("nachname") }}
/> <span class="font-bold">*</span>
<p </label>
v-if="(!isMobilePhone(userdetails.phone) && userdetails.phone.trim())" <input v-model="userdetails.lastname" name="lastname" id="last_name" autocomplete="off"
class="text-sm" :placeholder="[[$t('nachname')]]" type="text" :class="{
>{{ $t('this_is_not_a_valid_international_phone_number') }}</p> 'border-red-500': !userdetails.lastname.trim(),
<!-- --> 'border-green-300': userdetails.lastname.trim(),
<div class="grid grid-cols-6 mt-6"> }" class="
<div class="col-span-6"></div> dark:bg-gray-800
<div class="flex items-start col-span-6"> mt-1
<div class="flex items-center h-5"> block
<input w-full
v-model="provide_address" shadow-sm
id="address_activated" sm:text-sm
name="address_activated" border-gray-300 border-2
type="checkbox" bg-gray-50
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" text-gray-500
/> rounded-md
</div> p-2
<div class="ml-3 text-sm"> " />
<label <!-- -->
for="address_activated" <label for="email_address" class="block font-medium">
class="font-medium text-gray-400 select-none" {{ $t("e_mail_adress") }}
>{{ $t('provide_address') }}</label> <span class="font-bold">*</span>
</div> </label>
</div> <input v-model="userdetails.mail" name="email_address" id="email_address" autocomplete="off"
<div v-if="provide_address === true" class="col-span-6"> :placeholder="[[$t('e_mail_adress')]]" type="email" :class="{
<div class="col-span-6"> 'border-red-500': !isEmail(userdetails.mail),
<label for="street" class="block font-medium"> 'border-green-300': isEmail(userdetails.mail),
{{ $t('strasse') }} }" class="
<span class="font-bold">*</span> dark:bg-gray-800
</label> mt-1
<input block
v-model="userdetails.address.street" w-full
type="text" shadow-sm
name="street" sm:text-sm
:placeholder="[[$t('strasse')]]" border-2
id="street" bg-gray-50
autocomplete="street-address" text-gray-500
:class="{ 'border-red-500': (!userdetails.address.street.trim()), 'border-green-300': (userdetails.address.street.trim()) }" rounded-md
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-2
/> " />
</div> <p v-if="!isEmail(userdetails.mail)" class="text-sm">
<div class="col-span-6"> {{ $t("please_provide_valid_mail") }}
<label for="address2" class="block font-medium">{{ $t('apartment_suite_etc') }}</label> </p>
<input <!-- -->
v-model="userdetails.address.address2" <label for="phone" class="select-none block font-medium">{{
type="text" $t("phone_number")
name="address2" }}</label>
:placeholder="[[$t('apartment_suite_etc')]]" <input v-model="userdetails.phone" name="phone" id="phone" autocomplete="off"
id="address2" :placeholder="[[$t('phone_number')]]" type="text" :class="{
autocomplete="street-address" 'border-red-500':
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" !isMobilePhone(userdetails.phone) && userdetails.phone.trim(),
/> 'border-green-300':
</div> isMobilePhone(userdetails.phone) && userdetails.phone.trim(),
<div class="col-span-6 sm:col-span-6 lg:col-span-2"> }" class="
<label for="city" class="block font-medium"> dark:bg-gray-800
{{ $t('ort') }} mt-1
<span class="font-bold">*</span> block
</label> w-full
<input shadow-sm
v-model="userdetails.address.city" sm:text-sm
type="text" border-2
name="city" bg-gray-50
:placeholder="[[$t('ort')]]" text-gray-500
id="city" rounded-md
:class="{ 'border-red-500': (!userdetails.address.city.trim()), 'border-green-300': (userdetails.address.city.trim()) }" p-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" " />
/> <p v-if="!isMobilePhone(userdetails.phone) && userdetails.phone.trim()" class="text-sm">
</div> {{ $t("this_is_not_a_valid_international_phone_number") }}
<div class="col-span-6 sm:col-span-3 lg:col-span-2"> </p>
<label for="postal_code" class="block font-medium"> <!-- -->
{{ $t('plz') }} <div class="grid grid-cols-6 mt-6">
<span class="font-bold">*</span> <div class="col-span-6"></div>
</label> <div class="flex items-start col-span-6">
<input <div class="flex items-center h-5">
v-model="userdetails.address.zipcode" <input v-model="provide_address" id="address_activated" name="address_activated" type="checkbox"
type="text" class="h-4 w-4 text-indigo-600 border-gray-300 rounded" />
name="postal_code" </div>
:placeholder="[[$t('plz')]]" <div class="ml-3 text-sm">
id="postal_code" <label for="address_activated" class="font-medium text-gray-600 select-none">{{ $t("provide_address")
autocomplete="postal-code" }}</label>
:class="{ 'border-red-500': (!isPostalCode(userdetails.address.zipcode, 'DE')), 'border-green-300': (isPostalCode(userdetails.address.zipcode, 'DE')) }" </div>
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>
/> <div v-if="provide_address === true" class="col-span-6">
</div> <div class="col-span-6">
<p <label for="street" class="block font-medium">
v-if="!isPostalCode(userdetails.address.zipcode, 'DE')" {{ $t("strasse") }}
class="text-sm" <span class="font-bold">*</span>
>{{ $t('please_provide_a_valid_zipcode') }}</p> </label>
</div> <input v-model="userdetails.address.street" type="text" name="street" :placeholder="[[$t('strasse')]]"
</div> id="street" autocomplete="street-address" :class="{
<div class="flex items-start mt-6"> 'border-red-500': !userdetails.address.street.trim(),
<div class="flex items-center h-5"> 'border-green-300': userdetails.address.street.trim(),
<input }" class="
v-model="agb_accepted" dark:bg-gray-800
id="agb_accepted" mt-1
name="agb_accepted" block
type="checkbox" w-full
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" shadow-sm
/> sm:text-sm
</div> border-gray-300 border-2
<div class="ml-3 text-sm"> bg-gray-50
<label for="agb_accepted" class="font-medium text-gray-400 select-none"> text-gray-500
{{ $t('i_accept', { tos: $t('tos') }) }} rounded-md
<a p-2
target="_blank" " />
rel="noreferrer,noopener" </div>
href <div class="col-span-6">
class="underline" <label for="address2" class="block font-medium">{{
>{{ $t('tos') }}</a> $t("apartment_suite_etc")
{{ $t('i_accept_end') }} }}</label>
<span class="font-bold">*</span> <input v-model="userdetails.address.address2" type="text" name="address2"
</label> :placeholder="[[$t('apartment_suite_etc')]]" id="address2" autocomplete="street-address" class="
</div> dark:bg-gray-800
</div> mt-1
<div class="flex items-start mt-6"> block
<div class="flex items-center h-5"> w-full
<input shadow-sm
v-model="data_confirmed" sm:text-sm
id="data_confirmed" border-gray-300 border-2
name="data_confirmed" bg-gray-50
type="checkbox" text-gray-500
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" rounded-md
/> p-2
</div> " />
<div class="ml-3 text-sm"> </div>
<label for="data_confirmed" class="font-medium text-gray-400 select-none"> <div class="col-span-6 sm:col-span-6 lg:col-span-2">
{{ $t('confirm_personal_data') }} <label for="city" class="block font-medium">
<span class="font-bold">*</span> {{ $t("ort") }}
</label> <span class="font-bold">*</span>
</div> </label>
</div> <input v-model="userdetails.address.city" type="text" name="city" :placeholder="[[$t('ort')]]" id="city"
<div class="mt-6"> :class="{
<button 'border-red-500': !userdetails.address.city.trim(),
@click="login" 'border-green-300': userdetails.address.city.trim(),
:disabled="(!state.submit_enabled)" }" class="
:class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }" dark:bg-gray-800
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" mt-1
>{{ $t('registrieren') }}</button> block
</div> w-full
</div> shadow-sm
<div class="mt-6"> sm:text-sm
<div class="relative"> border-gray-300 border-2
<div class="absolute inset-0 flex items-center"> bg-gray-50
<div class="w-full border-t border-gray-300"></div> text-gray-500
</div> rounded-md
<div class="relative flex justify-center text-sm"> p-2
<span class="px-2 bg-white dark:bg-gray-900">{{ $t('already_have_an_account') }}</span> " />
</div> </div>
</div> <div class="col-span-6 sm:col-span-3 lg:col-span-2">
<div class="mt-6"> <label for="postal_code" class="block font-medium">
<a {{ $t("plz") }}
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 v-model="userdetails.address.zipcode" type="text" name="postal_code" :placeholder="[[$t('plz')]]"
</div> id="postal_code" autocomplete="postal-code" :class="{
</div> 'border-red-500': !isPostalCode(
</div> userdetails.address.zipcode,
</div> 'DE'
</template> ),
'border-green-300': isPostalCode(
<script setup> userdetails.address.zipcode,
import { computed, ref, reactive, defineProps } from "vue"; 'DE'
import axios from "redaxios"; ),
import isEmail from 'validator/es/lib/isEmail'; }" class="
import isMobilePhone from 'validator/es/lib/isMobilePhone'; dark:bg-gray-800
import isPostalCode from 'validator/es/lib/isPostalCode'; mt-1
import { useToast } from "vue-toastification"; block
// import { router } from '../router'; w-full
import { i18n } from '../language'; shadow-sm
sm:text-sm
const props = defineProps({ border-gray-300 border-2
token: String bg-gray-50
}) text-gray-500
if (props.token) { rounded-md
props.token = atob(props.token); p-2
axios.get(`${config.baseurl}api/organizations/selfservice/${props.token}`) " />
.then(({ data }) => { </div>
state.org_name = data.name; <p v-if="!isPostalCode(userdetails.address.zipcode, 'DE')" class="text-sm">
state.org_teams = data.teams; {{ $t("please_provide_a_valid_zipcode") }}
org_team.value = data.teams[0]?.id; </p>
}) </div>
.catch((error) => { </div>
console.log(error); <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" />
let userdetails = ref({ firstname: "", lastname: "", middlename: "", mail: "", phone: "", address: { street: "", address2: "", city: "", zipcode: "" } }); </div>
let provide_address = ref(false); <div class="ml-3 text-sm">
let agb_accepted = ref(false); <label for="agb_accepted" class="font-medium text-gray-600 select-none">
let data_confirmed = ref(false); {{ $t("i_accept", { tos: $t("privacy_policy") }) }}
let org_team = ref(""); <a target="_blank" rel="noreferrer,noopener" href="https://lauf-fuer-kaya.de/datenschutz/"
// class="underline">{{ $t("privacy_policy") }}</a>
const state = reactive({ {{ $t("i_accept_end") }}
org_name: "", <span class="font-bold">*</span>
org_teams: [], </label>
submit_enabled: computed(() => agb_accepted.value === true && data_confirmed.value === true && (isMobilePhone(userdetails.value.phone) || !userdetails.value.phone.trim()) && isEmail(userdetails.value.mail) </div>
&& userdetails.value.firstname </div>
&& 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")))) <div class="flex items-start mt-6">
}) <div class="flex items-center h-5">
const toast = useToast(); <input v-model="data_confirmed" id="data_confirmed" name="data_confirmed" type="checkbox"
function login() { class="h-4 w-4 text-indigo-600 border-gray-300 rounded" />
userdetails = userdetails.value; </div>
if (userdetails.phone === "" || isMobilePhone(userdetails.phone)) { <div class="ml-3 text-sm">
if (isEmail(userdetails.mail)) { <label for="data_confirmed" class="font-medium text-gray-600 select-none">
let postdata = { {{ $t("confirm_personal_data") }}
"email": userdetails.mail, <span class="font-bold">*</span>
"firstname": userdetails.firstname, </label>
"middlename": userdetails.middlename, </div>
"lastname": userdetails.lastname, </div>
"address": {} <div class="mt-6">
} <button @click="login" :disabled="!state.submit_enabled" :class="{
if (isMobilePhone(userdetails.phone)) { 'opacity-50': !state.submit_enabled,
postdata.phone = userdetails.phone; 'cursor-not-allowed': !state.submit_enabled,
} }" class="
if (provide_address.value === true) { text-white
postdata.address = { block
address1: userdetails.address.street, w-full
address2: userdetails.address.address2 || "", text-center
city: userdetails.address.city, py-2
postalcode: userdetails.address.zipcode, px-3
country: "DE", border-2 border-gray-300
} rounded-md
} p-1
if (state.org_name !== '' && state.org_teams.length > 0) { bg-blue-800
postdata.team = org_team.value; font-medium
} not-disabled:hover:border-gray-400
toast("registration in progress..."); not-disabled:hover:bg-blue-600
let url = `${config.baseurl}api/runners/register`; not-disabled:cursor-pointer
if (props.token) { not-disabled:focus:outline-none focus:border-gray-400
url = `${config.baseurl}api/runners/register/${props.token}` sm:text-sm
} ">
axios.post(url, postdata) {{ $t("registrieren") }}
.then(({ data }) => { </button>
const token = btoa(data.token); </div>
// router.push(`${config.baseurl_selfservice}/profile/${token}`); </div>
}) </div>
.catch((error) => { </div>
console.log(error); <Footer></Footer>
}); </template>
}
} <script setup>
} import { computed, ref, reactive } 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";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
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(t('registration_running'));
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(t('already_registered'), { type: TYPE.ERROR });
} else if (error.data.message === "Invalid body, check 'errors' property for more info.") {
error.data.errors.forEach(e => {
if (e.property === "phone") {
toast(t('invalid_input_phone_number_should_be_international_format'), { type: TYPE.ERROR });
}
});
}
});
}
}
}
</script> </script>

View File

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

View File

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