Compare commits

..

25 Commits

Author SHA1 Message Date
2285ea5070
🚀Bumped version to v1.0.0
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 15:32:47 +01:00
4af5c4545b
refactor
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 13:16:45 +01:00
f296cbc1a0
i18n 2024-12-02 13:08:55 +01:00
4fcc38c374
updated profile page 2024-12-02 13:08:08 +01:00
90c085db28
footer update 2024-12-02 13:07:57 +01:00
1a3ab98412
improved style in registered view 2024-12-02 12:58:09 +01:00
048edfba89
i18n 2024-12-02 12:56:43 +01:00
0acda07eb5
add i18n ally snake case config 2024-12-02 12:42:00 +01:00
afffde8fa0
registration brand font + more translations 2024-12-02 12:34:42 +01:00
1eab535381
wip: general updates 2024-12-02 11:54:05 +01:00
196b386d6d
refactor: translations 2024-12-02 11:31:24 +01:00
548148e898
fix: translations 2024-12-02 11:29:05 +01:00
6376dcb5fe
feat(Footer): ref lfk 2024-12-02 11:25:11 +01:00
75b61d991b
feat(Home): improve ui 2024-12-02 11:24:04 +01:00
af9a168f58
feat: lfk font 2024-12-02 11:12:00 +01:00
f71b01c39a
chore(deps): node@23.3.0 2024-12-02 11:06:26 +01:00
3e289d83f9
feat(Home): improve background.jpg import
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 11:00:07 +01:00
ec6d252928
refactor: code cleanup 2024-12-02 10:55:06 +01:00
4a11fef0e0
chore(deps): update all
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-02 10:40:06 +01:00
b85c3958c2
chore: pnpm v9
Some checks are pending
ci/woodpecker/push/build Pipeline is running
2024-12-02 10:16:59 +01:00
780bc54604
refactor(ci): Make ready for new woodpecker
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-11-26 19:23:40 +01:00
cb2f8eeab1
chore: 2025 2024-11-21 10:49:46 +01:00
c36db2c18f
Pin pnpm
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2023-11-06 20:27:30 +01:00
decc80fcc1
Merge branch 'dev' of git.odit.services:lfk/selfservice into dev
Some checks failed
ci/woodpecker/push/build Pipeline failed
2023-11-06 20:25:28 +01:00
9a3d307dfa
feat(ci)!: Switch to woodpecker 2023-11-06 20:25:26 +01:00
33 changed files with 4172 additions and 3687 deletions

View File

@ -1,101 +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: npm_url
get:
path: odit-npm-cache
name: url
---
kind: pipeline
type: kubernetes
name: build:dev
steps:
- name: docker dev
image: registry.odit.services/library/drone-kaniko
depends_on: [clone]
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
build_args:
- NPM_REGISTRY_URL:
from_secret: npm_url
repo: lfk/selfservice
tags:
- dev
cache: true
registry: registry.odit.services
trigger:
branch:
- dev
event:
- push
---
kind: pipeline
type: kubernetes
name: build:latest
steps:
- name: docker latest
image: registry.odit.services/library/drone-kaniko
depends_on: [clone]
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
build_args:
- NPM_REGISTRY_URL:
from_secret: npm_url
repo: lfk/selfservice
tags:
- latest
cache: true
registry: registry.odit.services
trigger:
branch:
- main
event:
- push
---
kind: pipeline
type: kubernetes
name: build:tags
steps:
- name: docker release
image: registry.odit.services/library/drone-kaniko
depends_on: [clone]
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
build_args:
- NPM_REGISTRY_URL:
from_secret: npm_url
repo: lfk/selfservice
tags:
- "${DRONE_TAG}"
cache: true
registry: registry.odit.services
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,12 +2,41 @@
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.0](https://git.odit.services/lfk/selfservice/compare/0.11.3...1.0.0)
- 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)
- 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) #### [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) - 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) - 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 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) - 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) - 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) - fix(Footer): darkmode colors in lightmode [`772eca6`](https://git.odit.services/lfk/selfservice/commit/772eca64bb38ce1cf1ea1b58859dd744588a88e1)

View File

@ -1,12 +1,15 @@
FROM registry.odit.services/hub/library/node:19.5.0-alpine3.17 as build FROM node:23.3.0-alpine3.20 AS build
ARG NPM_REGISTRY_URL=https://registry.npmjs.org # 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 npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8 # RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@9
RUN pnpm i && pnpm build && pnpm postbuild RUN npm i -g pnpm@9
RUN pnpm i --frozen-lockfile
RUN pnpm build
RUN pnpm postbuild
# final image # final image
FROM registry.odit.services/library/nginx-brotli:3.15 as final FROM registry.odit.services/library/nginx-brotli:3.15 AS final
COPY --from=build /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,23 +2,6 @@
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

View File

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

View File

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

View File

@ -1,16 +1,18 @@
const fs = require('fs'); import { readdirSync, readFileSync, writeFileSync } from "node:fs";
// get all language files // get all language files
const files = fs.readdirSync('./src/locales/'); const files = readdirSync("./src/locales/");
files.forEach((f) => { files.forEach((f) => {
// read file as object // read file as object
const unordered = JSON.parse(fs.readFileSync(`src/locales/${f}`)); const unordered = JSON.parse(readFileSync(`src/locales/${f}`));
// order object by keys alpabetically A-Z // order object by keys alpabetically A-Z
const ordered = Object.keys(unordered).sort().reduce((obj, key) => { const ordered = Object.keys(unordered)
.sort()
.reduce((obj, key) => {
obj[key] = unordered[key]; obj[key] = unordered[key];
return obj; 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,38 +1,33 @@
{ {
"name": "@odit/lfk-selfservice", "name": "@odit/lfk-selfservice",
"version": "0.11.3", "version": "1.0.0",
"type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"release": "release-it", "release": "release-it",
"postbuild": "node env_fix.js" "postbuild": "node env_fix.js"
}, },
"engines": {
"pnpm": "8.1.1"
},
"dependencies": { "dependencies": {
"bwip-js": "3.2.2", "@fontsource/athiti": "^5.1.0",
"marked": "2.0.3", "@tailwindcss/vite": "4.0.0-beta.4",
"redaxios": "0.4.1", "bwip-js": "4.5.1",
"toastify-js": "1.10.0", "marked": "15.0.3",
"validator": "13.5.2", "redaxios": "0.5.1",
"vue-i18n": "9.1.4", "tailwindcss": "4.0.0-beta.4",
"vue-toastification": "2.0.0-rc.1", "toastify-js": "1.12.0",
"vue": "3.0.9", "validator": "13.12.0",
"vue-router": "4.0.5" "vue": "3.5.13",
"vue-i18n": "10.0.5",
"vue-router": "4.5.0",
"vue-toastification": "2.0.0-rc.1"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/jit": "0.1.18", "@vitejs/plugin-vue": "5.2.1",
"@tailwindcss/aspect-ratio": "0.2.0", "autoprefixer": "10.4.20",
"@tailwindcss/forms": "0.3.2", "release-it": "17.10.0",
"@tailwindcss/line-clamp": "0.2.0", "vite": "6.0.2",
"@tailwindcss/typography": "0.4.0", "vite-plugin-vue-devtools": "^7.6.7"
"@vitejs/plugin-vue": "1.2.1",
"@vue/compiler-sfc": "3.0.11",
"autoprefixer": "10.2.5",
"tailwindcss": "2.1.1",
"release-it": "14.6.1",
"vite": "2.1.5"
}, },
"release-it": { "release-it": {
"git": { "git": {

6233
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

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

View File

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,28 +1,16 @@
<template> <template>
<footer> <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 © 2023 + 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>

View File

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

View File

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

View File

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

View File

@ -1,27 +1,32 @@
{ {
"access_is_only_provided_via_your_email_link": "Der Zugang erfolgt über den Link, den Sie bei der Registrierung erhalten haben.", "access_is_only_provided_via_your_email_link": "Der Zugang erfolgt über den Link, den Sie bei der Registrierung erhalten haben.",
"already_have_an_account": "Sie haben bereits einen Account?", "alle_daten_geloescht": "Alle Daten gelöscht!",
"already_registered": "bereits registriert...",
"amount_per_kilometer_in_eur": "Betrag pro Kilometer (in €)", "amount_per_kilometer_in_eur": "Betrag pro Kilometer (in €)",
"apartment_suite_etc": "Addresszeile 2", "apartment_suite_etc": "Addresszeile 2",
"buergerlauf": "Bürgerlauf",
"cancel_keep_my_data": "Abbrechen, meine Daten behalten", "cancel_keep_my_data": "Abbrechen, meine Daten behalten",
"configuration_error": "Konfigurationsfehler", "configuration_error": "Konfigurationsfehler",
"confirm_delete_all_of_my_data": "Bestätigen, meine Daten löschen", "confirm_delete_all_of_my_data": "Bestätigen, meine Daten löschen",
"confirm_personal_data": "Hiermit bestätige ich die Vollständigkeit und Richtigkeit der oben genannten Angaben", "confirm_personal_data": "Hiermit bestätige ich die Vollständigkeit und Richtigkeit der oben genannten Angaben",
"current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)", "current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)",
"delete_all_of_my_data": "Meine gesamten Daten löschen",
"delete_my_data": "Meine Daten löschen", "delete_my_data": "Meine Daten löschen",
"deletion_in_progress": "Daten werden gelöscht...",
"distance": "Distanz", "distance": "Distanz",
"download_certificate": "Urkunde herunterladen", "download_certificate": "Urkunde herunterladen",
"download_registrationcode": "Registrierungscode herunterladen", "download_registrationcode": "Registrierungscode herunterladen",
"e_mail_adress": "E-Mail Adresse", "e_mail_adress": "E-Mail Adresse",
"go_to_login": "Zum Login", "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?", "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",
@ -31,30 +36,36 @@
"not_registered_yet": "Noch nicht registriert?", "not_registered_yet": "Noch nicht registriert?",
"organization": "Organisation", "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! 2023 registrieren." "register_now": "Jetzt für den Lauf für Kaya! 2025 registrieren."
}, },
"register_now": "Jetzt registrieren!", "register_now": "Jetzt registrieren!",
"register_now_small": "Jetzt registrieren", "register_now_small": "Jetzt registrieren",
"registration_running": "Registrierung läuft...",
"registrationcode": "Registrierungscode",
"registrieren": "Registrieren", "registrieren": "Registrieren",
"registrierungscode": "Registrierungscode", "registriert": "Registriert",
"registrierungscode_generiert": "Registrierungscode generiert!",
"registrierungscode_wird_generiert": "Registrierungscode wird generiert...",
"resend_the_registration_mail": "Login-Link anfordern", "resend_the_registration_mail": "Login-Link anfordern",
"save_changes": "Änderungen speichern",
"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", "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"
"you_have_been_registered": "Sie wurden registriert!",
"you_have_not_provided_a_valid_access_key": "Sie haben keinen gültigen Zugangsschlüssel angegeben..."
} }

View File

@ -1,27 +1,32 @@
{ {
"access_is_only_provided_via_your_email_link": "Access is only provided via the link you received upon registration.", "access_is_only_provided_via_your_email_link": "Access is only provided via the link you received upon registration.",
"all_data_deleted": "All Data deleted!", "alle_daten_geloescht": "all data deleted!",
"already_have_an_account": "Already have an account?", "already_registered": "already registered...",
"amount_per_kilometer_in_eur": "Amount per kilometer (in €)", "amount_per_kilometer_in_eur": "Amount per kilometer (in €)",
"apartment_suite_etc": "Apartment, suite, etc.", "apartment_suite_etc": "Apartment, suite, etc.",
"buergerlauf": "Public Run",
"cancel_keep_my_data": "Cancel, keep my data", "cancel_keep_my_data": "Cancel, keep my data",
"configuration_error": "Configuration error", "configuration_error": "Configuration error",
"confirm_delete_all_of_my_data": "Confirm, delete all of my data", "confirm_delete_all_of_my_data": "Confirm, delete all of my data",
"confirm_personal_data": "I hereby confirm that the above information is complete and correct", "confirm_personal_data": "I hereby confirm that the above information is complete and correct",
"current_total_amount_in_eur": "Current total amount (in €)", "current_total_amount_in_eur": "Current total amount (in €)",
"delete_my_data": "Delete my data", "delete_my_data": "Delete my data",
"deletion_in_progress": "Deletion in progress...",
"distance": "Distance", "distance": "Distance",
"download_certificate": "Download certificate", "download_certificate": "Download certificate",
"download_registrationcode": "Download registrationcode", "download_registrationcode": "Download registrationcode",
"e_mail_adress": "mail address", "e_mail_adress": "mail address",
"go_to_login": "Go To Login", "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?", "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",
@ -31,29 +36,36 @@
"not_registered_yet": "Not registered 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! 2023." "register_now": "Register now for Lauf für Kaya! 2025."
}, },
"register_now": "Register now!", "register_now": "Register now!",
"register_now_small": "Register now", "register_now_small": "Register now",
"registration_running": "registration is running...",
"registrationcode": "Registration Code",
"registrieren": "Register Now", "registrieren": "Register Now",
"registriert": "Registered",
"registrierungscode_generiert": "created registration code!",
"registrierungscode_wird_generiert": "creating registration code...",
"resend_the_registration_mail": "Send me a login link", "resend_the_registration_mail": "Send me a login link",
"save_changes": "Save changes",
"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", "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!",
"you_have_not_provided_a_valid_access_key": "You have not provided a valid access key..."
} }

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,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="/selfservice/register/">{{ $t('register_now') }}</a>
href="/selfservice/register/" <a href="/selfservice/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="/selfservice/profile/"
class="mt-4 sm:ml-4 sm:mt-0 w-full sm:w-auto inline-flex px-6 py-3 border border-transparent text-base font-semibold rounded-md text-white bg-gray-800 shadow-sm hover:bg-gray-700 focus:outline-none focus:bg-gray-700 transition ease-in-out duration-150 xl:text-lg xl:py-4"
>{{ $t('view_my_data') }}</a>
</div>
</div> </div>
</section> </section>
</div> </div>
@ -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,21 @@
<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> <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"; import Footer from "@/components/Footer.vue";
export default { export default {
components: {Footer}, components: { Footer },
data() { data() {
return { return {
content: "", content: "",
@ -32,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,22 +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> <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"; import Footer from "@/components/Footer.vue";
export default { export default {
components: {Footer}, components: { Footer },
data() { data() {
return { return {
content: "" content: ""
@ -32,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

@ -2,8 +2,7 @@
<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 flex flex-col
md:pr-10 md:mb-0 md:pr-10 md:mb-0
mb-6 mb-6
@ -12,29 +11,24 @@
md:w-auto md:text-left md:w-auto md:text-left
text-center text-black text-center text-black
dark:text-gray-200 dark:text-gray-200
" ">
> <p class="text-4xl md:text-3xl font-bold whitespace-nowrap font-[Athiti]" v-text="(state.firstname || '') +
<p
class="text-3xl font-bold whitespace-nowrap"
v-text="
(state.firstname || '') +
' ' + ' ' +
(state.middlename || '') + (state.middlename || '') +
' ' + ' ' +
(state.lastname || '') (state.lastname || '')
" "></p>
></p>
<p class="text-md whitespace-nowrap">{{ state.group }}</p> <p class="text-md whitespace-nowrap">{{ state.group }}</p>
</div> </div>
<div class="inline-flex md:ml-auto md:mr-0 mx-auto items-center"> <div class="inline-flex md:ml-auto md:mr-0 mx-auto items-center">
<div v-if="state.delete_active === false"> <div v-if="state.delete_active === false">
<button <button type="button" class="
type="button"
class="
focus:border-black focus:ring-2 focus:ring-black focus:border-black focus:ring-2 focus:ring-black
text-white text-sm text-white text-base md:text-sm
py-2.5 py-3.5
px-5 px-5
md:py-2.5
md:px-5
rounded-md rounded-md
bg-blue-500 bg-blue-500
hover:bg-blue-600 hover:shadow-lg hover:bg-blue-600 hover:shadow-lg
@ -42,35 +36,23 @@
md:w-auto md:w-auto
mb-1 mb-1
md:mr-1 md:mr-1
" " @click="get_registration">
@click="get_registration" <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
<svg class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-download"
style="display: inline; height: 1rem; vertical-align: sub"
>
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="7 10 12 15 17 10" /> <polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" /> <line x1="12" y1="15" x2="12" y2="3" />
</svg> </svg>
{{ $t("download_registrationcode") }} {{ $t("download_registrationcode") }}
</button> </button>
<button <button type="button" class="
type="button"
class="
focus:border-black focus:ring-2 focus:ring-black focus:border-black focus:ring-2 focus:ring-black
text-white text-sm text-white text-base md:text-sm
py-2.5 py-3.5
px-5 px-5
md:py-2.5
md:px-5
rounded-md rounded-md
bg-blue-500 bg-blue-500
hover:bg-blue-600 hover:shadow-lg hover:bg-blue-600 hover:shadow-lg
@ -78,77 +60,50 @@
md:w-auto md:w-auto
mb-1 mb-1
md:mr-1 md:mr-1
" " @click="get_certificate">
@click="get_certificate" <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
<svg class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-download"
style="display: inline; height: 1rem; vertical-align: sub"
>
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="7 10 12 15 17 10" /> <polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" /> <line x1="12" y1="15" x2="12" y2="3" />
</svg> </svg>
{{ $t("download_certificate") }} {{ $t("download_certificate") }}
</button> </button>
<button <button type="button" class="
type="button"
class="
focus:border-black focus:ring-2 focus:ring-black focus:border-black focus:ring-2 focus:ring-black
text-white text-sm text-white text-base md:text-sm
py-2.5 py-3.5
px-5 px-5
md:py-2.5
md:px-5
rounded-md rounded-md
bg-red-600 bg-red-600
hover:bg-red-700 hover:shadow-lg hover:bg-red-700 hover:shadow-lg
w-full w-full
md:w-auto md:w-auto
" " @click="() => {
@click="
() => {
state.delete_active = true; state.delete_active = true;
} }
" ">
> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
<svg stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
xmlns="http://www.w3.org/2000/svg" class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="none"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-download"
style="display: inline; height: 1rem; vertical-align: sub"
>
<path d="M0 0h24v24H0z" /> <path d="M0 0h24v24H0z" />
<path <path fill="currentColor"
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" />
d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z"
/>
</svg> </svg>
{{ $t("delete_my_data") }} {{ $t("delete_my_data") }}
</button> </button>
</div> </div>
<div v-if="state.delete_active === true"> <div v-if="state.delete_active === true">
<button <button type="button" class="
type="button"
class="
focus:border-black focus:ring-2 focus:ring-black focus:border-black focus:ring-2 focus:ring-black
text-white text-sm text-white text-base md:text-sm
py-2.5 py-3.5
px-5 px-5
md:py-2.5
md:px-5
rounded-md rounded-md
mb-1 mb-1
md:mb-auto md:mb-auto
@ -156,68 +111,38 @@
md:w-auto md:w-auto
bg-blue-500 bg-blue-500
hover:bg-blue-600 hover:shadow-lg hover:bg-blue-600 hover:shadow-lg
" " @click="() => {
@click="
() => {
state.delete_active = false; state.delete_active = false;
} }
" ">
> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
<svg stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
xmlns="http://www.w3.org/2000/svg" class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="none"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-download"
style="display: inline; height: 1rem; vertical-align: sub"
>
<path fill="none" d="M0 0h24v24H0z" /> <path fill="none" d="M0 0h24v24H0z" />
<path <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" />
fill="currentColor"
d="M12 11l5-5 1 1-5 5 5 5-1 1-5-5-5 5-1-1 5-5-5-5 1-1z"
/>
</svg> </svg>
{{ $t("cancel_keep_my_data") }} {{ $t("cancel_keep_my_data") }}
</button> </button>
<button <button type="button" class="
type="button"
class="
focus:border-black focus:ring-2 focus:ring-black focus:border-black focus:ring-2 focus:ring-black
text-white text-sm text-white text-base md:text-sm
py-2.5 py-3.5
px-5 px-5
md:py-2.5
md:px-5
rounded-md rounded-md
w-full w-full
md:w-auto md:w-auto
bg-red-600 bg-red-600
hover:bg-red-700 hover:shadow-lg hover:bg-red-700 hover:shadow-lg
md:ml-1 md:ml-1
" " @click="delete_me">
@click="delete_me" <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
> stroke="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
<svg class="feather feather-download" style="display: inline; height: 1rem; vertical-align: sub">
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="none"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-download"
style="display: inline; height: 1rem; vertical-align: sub"
>
<path d="M0 0h24v24H0z" /> <path d="M0 0h24v24H0z" />
<path <path fill="currentColor"
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" />
d="M17 6h5v2h-2v13a1 1 0 01-1 1H5a1 1 0 01-1-1V8H2V6h5V3a1 1 0 011-1h8a1 1 0 011 1v3zm1 2H6v12h12V8zm-5 6l2 2-1 1-2-2-2 2-1-1 2-2-2-2 1-1 2 2 2-2 1 1-2 2zM9 4v2h6V4H9z"
/>
</svg> </svg>
{{ $t("confirm_delete_all_of_my_data") }} {{ $t("confirm_delete_all_of_my_data") }}
</button> </button>
@ -230,53 +155,35 @@
<div class="flex flex-wrap flex-col w-full tabs"> <div class="flex flex-wrap flex-col w-full tabs">
<div class="flex lg:flex-wrap flex-row lg:space-x-2"> <div class="flex lg:flex-wrap flex-row lg:space-x-2">
<div class="flex-none"> <div class="flex-none">
<button <button @click="() => {
@click="
() => {
state.activetab = 'profile'; state.activetab = 'profile';
} }
" " :class="{
:class="{
'tab-active border-b-2 font-medium border-blue-500': 'tab-active border-b-2 font-medium border-blue-500':
state.activetab === 'profile', state.activetab === 'profile',
}" }" class="tab tab-underline py-4 px-6 block" type="button">
class="tab tab-underline py-4 px-6 block"
type="button"
>
{{ $t("profile") }} {{ $t("profile") }}
</button> </button>
</div> </div>
<div class="flex-none"> <div class="flex-none">
<button <button @click="() => {
@click="
() => {
state.activetab = 'laptimes'; state.activetab = 'laptimes';
} }
" " :class="{
:class="{
'tab-active border-b-2 font-medium border-blue-500': 'tab-active border-b-2 font-medium border-blue-500':
state.activetab === 'laptimes', state.activetab === 'laptimes',
}" }" class="tab tab-underline py-4 px-6 block" type="button">
class="tab tab-underline py-4 px-6 block"
type="button"
>
{{ $t("lap_times") }} {{ $t("lap_times") }}
</button> </button>
</div> </div>
<div class="flex-none"> <div class="flex-none">
<button <button @click="() => {
@click="
() => {
state.activetab = 'sponsorings'; state.activetab = 'sponsorings';
} }
" " :class="{
:class="{
'tab-active border-b-2 font-medium border-blue-500': 'tab-active border-b-2 font-medium border-blue-500':
state.activetab === 'sponsorings', state.activetab === 'sponsorings',
}" }" class="tab tab-underline py-4 px-6 block" type="button">
class="tab tab-underline py-4 px-6 block"
type="button"
>
{{ $t("sponsoring") }} {{ $t("sponsoring") }}
</button> </button>
</div> </div>
@ -287,15 +194,10 @@
<form class="form flex flex-wrap w-full"> <form class="form flex flex-wrap w-full">
<div class="w-full"> <div class="w-full">
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t("registrierungscode") }}</div> <div class="text-lg">{{ $t("registrationcode") }}</div>
<img <img class="w-full md:w-auto mb-2 bg-white p-2" alt="Registrierungscode" :src="state.barcode" />
class="w-full md:w-auto mb-2 bg-white p-2"
alt="Registrierungscode"
:src="state.barcode"
/>
<div class="text-lg">{{ $t("vorname") }}</div> <div class="text-lg">{{ $t("vorname") }}</div>
<p <p class="
class="
h-10 h-10
w-full w-full
dark:bg-gray-800 dark:bg-gray-800
@ -310,14 +212,11 @@
transition-colors transition-colors
duration-200 duration-200
ease-in-out ease-in-out
" " v-text="state.firstname || '---'" />
v-text="state.firstname || '---'"
/>
</div> </div>
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t("mittelname") }}</div> <div class="text-lg">{{ $t("mittelname") }}</div>
<p <p class="
class="
h-10 h-10
w-full w-full
dark:bg-gray-800 dark:bg-gray-800
@ -332,14 +231,11 @@
transition-colors transition-colors
duration-200 duration-200
ease-in-out ease-in-out
" " v-text="state.middlename || '---'" />
v-text="state.middlename || '---'"
/>
</div> </div>
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t("nachname") }}</div> <div class="text-lg">{{ $t("nachname") }}</div>
<p <p class="
class="
h-10 h-10
w-full w-full
dark:bg-gray-800 dark:bg-gray-800
@ -354,14 +250,11 @@
transition-colors transition-colors
duration-200 duration-200
ease-in-out ease-in-out
" " v-text="state.lastname || '---'" />
v-text="state.lastname || '---'"
/>
</div> </div>
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t("e_mail_adress") }}</div> <div class="text-lg">{{ $t("e_mail_adress") }}</div>
<p <p class="
class="
h-10 h-10
w-full w-full
dark:bg-gray-800 dark:bg-gray-800
@ -376,14 +269,11 @@
transition-colors transition-colors
duration-200 duration-200
ease-in-out ease-in-out
" " v-text="state.email || '---'" />
v-text="state.email || '---'"
/>
</div> </div>
<div class="form-element"> <div class="form-element">
<div class="text-lg">{{ $t("phone_number") }}</div> <div class="text-lg">{{ $t("phone_number") }}</div>
<p <p class="
class="
h-10 h-10
w-full w-full
dark:bg-gray-800 dark:bg-gray-800
@ -398,9 +288,7 @@
transition-colors transition-colors
duration-200 duration-200
ease-in-out ease-in-out
" " v-text="state.phone || '---'" />
v-text="state.phone || '---'"
/>
</div> </div>
</div> </div>
</form> </form>
@ -412,40 +300,31 @@
<section class="text-gray-400 dark:bg-gray-900 body-font"> <section class="text-gray-400 dark:bg-gray-900 body-font">
<div class="container mx-auto"> <div class="container mx-auto">
<div class="lg:w-2/3 w-full mx-auto overflow-auto"> <div class="lg:w-2/3 w-full mx-auto overflow-auto">
<table <table v-if="state.scans.length > 0" class="table-auto w-full text-left whitespace-no-wrap">
v-if="state.scans.length > 0" <thead class="
class="table-auto w-full text-left whitespace-no-wrap"
>
<thead
class="
text-black text-black
bg-gray-300 bg-gray-300
dark:text-white dark:text-white
text-sm text-sm
dark:bg-gray-800 dark:bg-gray-800
" ">
>
<tr> <tr>
<th <th class="
class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
" ">
>
{{ $t("distance") }} {{ $t("distance") }}
</th> </th>
<th <th class="
class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
" ">
>
{{ $t("lap_time") }} {{ $t("lap_time") }}
</th> </th>
</tr> </tr>
@ -459,21 +338,15 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div <div v-else class="
v-else
class="
text-center text-center
font-bold font-bold
text-black text-black
dark:text-white dark:text-white
text-2xl text-2xl
" ">
> <img src="../assets/empty_laps.svg" style="height: 25rem; margin: 0 auto"
<img :alt="[[$t('no_laps_scans_were_recorded_yet')]]" />
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") }} {{ $t("no_laps_scans_were_recorded_yet") }}
</div> </div>
</div> </div>
@ -481,59 +354,45 @@
</section> </section>
</div> </div>
</div> </div>
<div <div v-if="state.activetab === 'sponsorings'" class="tab-content block">
v-if="state.activetab === 'sponsorings'"
class="tab-content block"
>
<div class="py-4 w-full"> <div class="py-4 w-full">
<section class="text-gray-400 dark:bg-gray-900 body-font"> <section class="text-gray-400 dark:bg-gray-900 body-font">
<div class="container mx-auto"> <div class="container mx-auto">
<div class="lg:w-2/3 w-full mx-auto overflow-auto"> <div class="lg:w-2/3 w-full mx-auto overflow-auto">
<table <table v-if="state.sponsorings.length > 0" class="table-auto w-full text-left whitespace-no-wrap">
v-if="state.sponsorings.length > 0" <thead class="
class="table-auto w-full text-left whitespace-no-wrap"
>
<thead
class="
text-black text-black
bg-gray-300 bg-gray-300
dark:text-white dark:text-white
text-sm text-sm
dark:bg-gray-800 dark:bg-gray-800
" ">
>
<tr> <tr>
<th <th class="
class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
" ">
>
Name Name
</th> </th>
<th <th class="
class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
" ">
>
{{ $t("amount_per_kilometer_in_eur") }} {{ $t("amount_per_kilometer_in_eur") }}
</th> </th>
<th <th class="
class="
px-4 px-4
py-3 py-3
title-font title-font
tracking-wider tracking-wider
font-medium font-medium
" ">
>
{{ $t("current_total_amount_in_eur") }} {{ $t("current_total_amount_in_eur") }}
</th> </th>
</tr> </tr>
@ -548,24 +407,16 @@
<span v-text="s.donor.lastname"></span> <span v-text="s.donor.lastname"></span>
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span <span v-text="(s.amountPerDistance / 100)
v-text="
(s.amountPerDistance / 100)
.toFixed(2) .toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' }) .toLocaleString('de-DE', { valute: 'EUR' })
" "></span>
></span
>
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span <span v-text="(s.amount / 100)
v-text="
(s.amount / 100)
.toFixed(2) .toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' }) .toLocaleString('de-DE', { valute: 'EUR' })
" "></span>
></span
>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -573,9 +424,7 @@
<tr> <tr>
<td class="px-4 py-3">{{ $t("total") }}</td> <td class="px-4 py-3">{{ $t("total") }}</td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span <span v-text="(
v-text="
(
state.sponsorings.reduce(function ( state.sponsorings.reduce(function (
sum, sum,
current current
@ -586,14 +435,10 @@
) )
.toFixed(2) .toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' }) .toLocaleString('de-DE', { valute: 'EUR' })
" "></span>
></span
>
</td> </td>
<td class="px-4 py-3"> <td class="px-4 py-3">
<span <span v-text="(
v-text="
(
state.sponsorings.reduce(function ( state.sponsorings.reduce(function (
sum, sum,
current current
@ -604,30 +449,21 @@
) )
.toFixed(2) .toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' }) .toLocaleString('de-DE', { valute: 'EUR' })
" "></span>
></span
>
</td> </td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
<div <div v-else class="
v-else
class="
text-center text-center
font-bold font-bold
text-black text-black
dark:text-white dark:text-white
text-2xl text-2xl
" ">
> <img src="../assets/empty_laps.svg" style="height: 25rem; margin: 0 auto" :alt="[
<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')],
]" ]" />
/>
{{ $t("no_sponsorings_for_you_were_recorded_yet") }} {{ $t("no_sponsorings_for_you_were_recorded_yet") }}
</div> </div>
</div> </div>
@ -647,8 +483,10 @@
import { reactive } from "vue"; import { reactive } from "vue";
import { TYPE, useToast } from "vue-toastification"; import { TYPE, useToast } from "vue-toastification";
import axios from "redaxios"; import axios from "redaxios";
import bwipjs from "bwip-js"; import { toCanvas } from "bwip-js";
import Footer from "@/components/Footer.vue"; import Footer from "@/components/Footer.vue";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
function textToBase64Barcode(text) { function textToBase64Barcode(text) {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
@ -667,7 +505,7 @@ function textToBase64Barcode(text) {
) { ) {
codeconfig.height = 10; codeconfig.height = 10;
} }
bwipjs.toCanvas(canvas, codeconfig); toCanvas(canvas, codeconfig);
return canvas.toDataURL("image/png"); return canvas.toDataURL("image/png");
} }
@ -705,7 +543,7 @@ axios
}) })
.catch((error) => { .catch((error) => {
toast.clear(); toast.clear();
toast.error("Profil konnte nicht geladen werden..."); toast.error(t('profil_konnte_nicht_geladen_werden'));
}); });
axios axios
.get(`${config.baseurl}api/runners/me/${accesstoken}/scans`) .get(`${config.baseurl}api/runners/me/${accesstoken}/scans`)
@ -727,26 +565,26 @@ axios
state.scans = data; state.scans = data;
}) })
.catch((error) => { .catch((error) => {
toast.error("Profil konnte nicht geladen werden..."); toast.error(t('profil_konnte_nicht_geladen_werden'));
}); });
function delete_me() { function delete_me() {
toast.clear(); toast.clear();
toast("Profil wird gelöscht..."); toast(t('profil_wird_geloescht'));
let url = `${config.baseurl}api/runners/me/${accesstoken}?force=true`; let url = `${config.baseurl}api/runners/me/${accesstoken}?force=true`;
axios axios
.delete(url) .delete(url)
.then(() => { .then(() => {
toast.clear(); toast.clear();
toast("Alle Daten gelöscht!"); toast(t('alle_daten_geloescht'));
location.replace(`${config.baseurl_selfservice}`); location.replace(`${config.baseurl_selfservice}`);
}) })
.catch((error) => { .catch((error) => {
toast.clear(); toast.clear();
toast.error("Profil konnte nicht gelöscht werden..."); toast.error(t('profil_konnte_nicht_geloescht_werden'));
}); });
} }
function get_certificate() { function get_certificate() {
toast("Urkunde wird generiert..."); toast(t('urkunde_wird_generiert'));
const browserlocale = ( const browserlocale = (
(navigator.languages && navigator.languages[0]) || (navigator.languages && navigator.languages[0]) ||
"" ""
@ -763,8 +601,8 @@ function get_certificate() {
}) })
.then((response) => { .then((response) => {
console.log(response); console.log(response);
if (response.status != "200") { if (response.status !== 200) {
toast.error("Urkunde konnte nicht generiert werden..."); toast.error(t('urkunde_konnte_nicht_generiert_werden'));
} else { } else {
var fileURL = window.URL.createObjectURL( var fileURL = window.URL.createObjectURL(
new Blob([response.data], { type: "application/pdf" }) new Blob([response.data], { type: "application/pdf" })
@ -778,23 +616,23 @@ function get_certificate() {
fileLink.click(); fileLink.click();
fileLink.remove(); fileLink.remove();
toast.clear(); toast.clear();
toast("Urkunde generiert!", { type: TYPE.SUCCESS }); toast(t('urkunde_generiert'), { type: TYPE.SUCCESS });
} }
}) })
.catch((err) => { .catch((err) => {
console.error(err); console.error(err);
toast.clear(); toast.clear();
toast.error("Urkunde konnte nicht generiert werden..."); toast.error(t('urkunde_konnte_nicht_generiert_werden'));
}); });
} }
function get_registration() { function get_registration() {
toast.clear(); toast.clear();
toast("Registrierungscode wird generiert..."); toast(t('registrierungscode_wird_generiert'));
var a = document.createElement("a"); var a = document.createElement("a");
a.href = state.barcode; a.href = state.barcode;
a.download = "LfK23_Registrierungscode.png"; a.download = "LfK25_Registrierungscode.png";
a.click(); a.click();
toast.clear(); toast.clear();
toast("Registrierungscode generiert!", { type: TYPE.SUCCESS }); toast(t('registrierungscode_generiert'), { type: TYPE.SUCCESS });
} }
</script> </script>

View File

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

View File

@ -1,12 +1,9 @@
<template> <template>
<div <div class="min-h-screen flex items-center justify-center" v-if="registrationState === 'registered'">
class="min-h-screen flex items-center justify-center" <div class="max-w-md w-full py-12 px-6 font-[Athiti]">
v-if="registrationState === 'registered'" <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">
<div class="max-w-md w-full py-12 px-6"> Lauf für Kaya! - {{ $t('registriert') }}
<img class="mx-auto h-24 w-auto" src="/favicon.png" alt />
<h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center">
Lauf für Kaya! - Registriert
</h1> </h1>
<p class="mx-auto leading-relaxed text-base text-center"> <p class="mx-auto leading-relaxed text-base text-center">
Bitte klicken Sie zum Fortfahren auf den Link, den wir an Bitte klicken Sie zum Fortfahren auf den Link, den wir an
@ -15,30 +12,22 @@
</div> </div>
</div> </div>
<div class="min-h-screen flex items-center justify-center" v-else> <div class="min-h-screen flex items-center justify-center" v-else>
<div class="max-w-md w-full py-12 px-6"> <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 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center"> <h1 class="sm:text-3xl text-2xl font-semibold title-font mb-4 text-center">
Lauf für Kaya! - {{ $t("registrieren") }} Lauf für Kaya! - {{ $t("registrieren") }}
</h1> </h1>
<p class="mx-auto leading-relaxed text-base text-center"> <p class="mx-auto leading-relaxed text-base text-center font-medium">
{{ $t("register.register_now") }} {{ $t("register.register_now") }}
</p> </p>
<p <p v-if="state.org_name !== ''" class="mx-auto leading-relaxed text-base text-center font-medium">
v-if="state.org_name !== ''"
class="mx-auto leading-relaxed text-base text-center"
>
{{ $t("organization") }}: {{ state.org_name }} {{ $t("organization") }}: {{ state.org_name }}
</p> </p>
<p <p v-if="state.org_name !== '' && state.org_teams.length > 0"
v-if="state.org_name !== '' && state.org_teams.length > 0" class="mx-auto leading-relaxed text-base text-center">
class="mx-auto leading-relaxed text-base text-center"
>
Team: Team:
</p> </p>
<select <select v-model="org_team" v-if="state.org_name !== '' && state.org_teams.length > 0" class="
v-model="org_team"
v-if="state.org_name !== '' && state.org_teams.length > 0"
class="
w-full w-full
border border
bg-white bg-white
@ -53,35 +42,24 @@
form-select form-select
focus:border-purple-400 focus:outline-none focus:shadow-outline-purple focus:border-purple-400 focus:outline-none focus:shadow-outline-purple
dark:focus:shadow-outline-gray dark:focus:shadow-outline-gray
" ">
>
<option v-for="t in state.org_teams" :key="t.id" :value="t.id"> <option v-for="t in state.org_teams" :key="t.id" :value="t.id">
{{ t.name }} {{ t.name }}
</option> </option>
</select> </select>
<p <p v-if="state.org_name === ''" class="mx-auto leading-relaxed text-base text-center">
v-if="state.org_name === ''" {{ $t('buergerlauf') }}
class="mx-auto leading-relaxed text-base text-center"
>
Bürgerlauf
</p> </p>
<div class="mt-4"> <div class="mt-4">
<label for="first_name" class="block font-medium"> <label for="first_name" class="block font-medium">
{{ $t("vorname") }} {{ $t("vorname") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input v-model="userdetails.firstname" name="firstname" id="first_name" autocomplete="off"
v-model="userdetails.firstname" :placeholder="[[$t('vorname')]]" type="text" :class="{
name="firstname"
id="first_name"
autocomplete="off"
:placeholder="[[$t('vorname')]]"
type="text"
:class="{
'border-red-500': !userdetails.firstname.trim(), 'border-red-500': !userdetails.firstname.trim(),
'border-green-300': userdetails.firstname.trim(), 'border-green-300': userdetails.firstname.trim(),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -93,20 +71,13 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
<!-- --> <!-- -->
<label for="middle_name" class="block font-medium">{{ <label for="middle_name" class="block font-medium">{{
$t("mittelname") $t("mittelname")
}}</label> }}</label>
<input <input v-model="userdetails.middlename" name="middlename" id="middle_name" autocomplete="off"
v-model="userdetails.middlename" :placeholder="[[$t('mittelname')]]" type="text" class="
name="middlename"
id="middle_name"
autocomplete="off"
:placeholder="[[$t('mittelname')]]"
type="text"
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -118,25 +89,17 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
<!-- --> <!-- -->
<label for="last_name" class="block font-medium"> <label for="last_name" class="block font-medium">
{{ $t("nachname") }} {{ $t("nachname") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input v-model="userdetails.lastname" name="lastname" id="last_name" autocomplete="off"
v-model="userdetails.lastname" :placeholder="[[$t('nachname')]]" type="text" :class="{
name="lastname"
id="last_name"
autocomplete="off"
:placeholder="[[$t('nachname')]]"
type="text"
:class="{
'border-red-500': !userdetails.lastname.trim(), 'border-red-500': !userdetails.lastname.trim(),
'border-green-300': userdetails.lastname.trim(), 'border-green-300': userdetails.lastname.trim(),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -148,25 +111,17 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
<!-- --> <!-- -->
<label for="email_address" class="block font-medium"> <label for="email_address" class="block font-medium">
{{ $t("e_mail_adress") }} {{ $t("e_mail_adress") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input v-model="userdetails.mail" name="email_address" id="email_address" autocomplete="off"
v-model="userdetails.mail" :placeholder="[[$t('e_mail_adress')]]" type="email" :class="{
name="email_address"
id="email_address"
autocomplete="off"
:placeholder="[[$t('e_mail_adress')]]"
type="email"
:class="{
'border-red-500': !isEmail(userdetails.mail), 'border-red-500': !isEmail(userdetails.mail),
'border-green-300': isEmail(userdetails.mail), 'border-green-300': isEmail(userdetails.mail),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -178,8 +133,7 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
<p v-if="!isEmail(userdetails.mail)" class="text-sm"> <p v-if="!isEmail(userdetails.mail)" class="text-sm">
{{ $t("please_provide_valid_mail") }} {{ $t("please_provide_valid_mail") }}
</p> </p>
@ -187,20 +141,13 @@
<label for="phone" class="select-none block font-medium">{{ <label for="phone" class="select-none block font-medium">{{
$t("phone_number") $t("phone_number")
}}</label> }}</label>
<input <input v-model="userdetails.phone" name="phone" id="phone" autocomplete="off"
v-model="userdetails.phone" :placeholder="[[$t('phone_number')]]" type="text" :class="{
name="phone"
id="phone"
autocomplete="off"
:placeholder="[[$t('phone_number')]]"
type="text"
:class="{
'border-red-500': 'border-red-500':
!isMobilePhone(userdetails.phone) && userdetails.phone.trim(), !isMobilePhone(userdetails.phone) && userdetails.phone.trim(),
'border-green-300': 'border-green-300':
isMobilePhone(userdetails.phone) && userdetails.phone.trim(), isMobilePhone(userdetails.phone) && userdetails.phone.trim(),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -212,12 +159,8 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/> <p v-if="!isMobilePhone(userdetails.phone) && userdetails.phone.trim()" class="text-sm">
<p
v-if="!isMobilePhone(userdetails.phone) && userdetails.phone.trim()"
class="text-sm"
>
{{ $t("this_is_not_a_valid_international_phone_number") }} {{ $t("this_is_not_a_valid_international_phone_number") }}
</p> </p>
<!-- --> <!-- -->
@ -225,20 +168,12 @@
<div class="col-span-6"></div> <div class="col-span-6"></div>
<div class="flex items-start col-span-6"> <div class="flex items-start col-span-6">
<div class="flex items-center h-5"> <div class="flex items-center h-5">
<input <input v-model="provide_address" id="address_activated" name="address_activated" type="checkbox"
v-model="provide_address" class="h-4 w-4 text-indigo-600 border-gray-300 rounded" />
id="address_activated"
name="address_activated"
type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div> </div>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label <label for="address_activated" class="font-medium text-gray-600 select-none">{{ $t("provide_address")
for="address_activated" }}</label>
class="font-medium text-gray-400 select-none"
>{{ $t("provide_address") }}</label
>
</div> </div>
</div> </div>
<div v-if="provide_address === true" class="col-span-6"> <div v-if="provide_address === true" class="col-span-6">
@ -247,18 +182,11 @@
{{ $t("strasse") }} {{ $t("strasse") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input v-model="userdetails.address.street" type="text" name="street" :placeholder="[[$t('strasse')]]"
v-model="userdetails.address.street" id="street" autocomplete="street-address" :class="{
type="text"
name="street"
:placeholder="[[$t('strasse')]]"
id="street"
autocomplete="street-address"
:class="{
'border-red-500': !userdetails.address.street.trim(), 'border-red-500': !userdetails.address.street.trim(),
'border-green-300': userdetails.address.street.trim(), 'border-green-300': userdetails.address.street.trim(),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -270,21 +198,14 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label for="address2" class="block font-medium">{{ <label for="address2" class="block font-medium">{{
$t("apartment_suite_etc") $t("apartment_suite_etc")
}}</label> }}</label>
<input <input v-model="userdetails.address.address2" type="text" name="address2"
v-model="userdetails.address.address2" :placeholder="[[$t('apartment_suite_etc')]]" id="address2" autocomplete="street-address" class="
type="text"
name="address2"
:placeholder="[[$t('apartment_suite_etc')]]"
id="address2"
autocomplete="street-address"
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -296,25 +217,18 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
</div> </div>
<div class="col-span-6 sm:col-span-6 lg:col-span-2"> <div class="col-span-6 sm:col-span-6 lg:col-span-2">
<label for="city" class="block font-medium"> <label for="city" class="block font-medium">
{{ $t("ort") }} {{ $t("ort") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input v-model="userdetails.address.city" type="text" name="city" :placeholder="[[$t('ort')]]" id="city"
v-model="userdetails.address.city"
type="text"
name="city"
:placeholder="[[$t('ort')]]"
id="city"
:class="{ :class="{
'border-red-500': !userdetails.address.city.trim(), 'border-red-500': !userdetails.address.city.trim(),
'border-green-300': userdetails.address.city.trim(), 'border-green-300': userdetails.address.city.trim(),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -326,22 +240,15 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
</div> </div>
<div class="col-span-6 sm:col-span-3 lg:col-span-2"> <div class="col-span-6 sm:col-span-3 lg:col-span-2">
<label for="postal_code" class="block font-medium"> <label for="postal_code" class="block font-medium">
{{ $t("plz") }} {{ $t("plz") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input v-model="userdetails.address.zipcode" type="text" name="postal_code" :placeholder="[[$t('plz')]]"
v-model="userdetails.address.zipcode" id="postal_code" autocomplete="postal-code" :class="{
type="text"
name="postal_code"
:placeholder="[[$t('plz')]]"
id="postal_code"
autocomplete="postal-code"
:class="{
'border-red-500': !isPostalCode( 'border-red-500': !isPostalCode(
userdetails.address.zipcode, userdetails.address.zipcode,
'DE' 'DE'
@ -350,8 +257,7 @@
userdetails.address.zipcode, userdetails.address.zipcode,
'DE' 'DE'
), ),
}" }" class="
class="
dark:bg-gray-800 dark:bg-gray-800
mt-1 mt-1
block block
@ -363,40 +269,23 @@
text-gray-500 text-gray-500
rounded-md rounded-md
p-2 p-2
" " />
/>
</div> </div>
<p <p v-if="!isPostalCode(userdetails.address.zipcode, 'DE')" class="text-sm">
v-if="!isPostalCode(userdetails.address.zipcode, 'DE')"
class="text-sm"
>
{{ $t("please_provide_a_valid_zipcode") }} {{ $t("please_provide_a_valid_zipcode") }}
</p> </p>
</div> </div>
</div> </div>
<div class="flex items-start mt-6"> <div class="flex items-start mt-6">
<div class="flex items-center h-5"> <div class="flex items-center h-5">
<input <input v-model="agb_accepted" id="agb_accepted" name="agb_accepted" type="checkbox"
v-model="agb_accepted" class="h-4 w-4 text-indigo-600 border-gray-300 rounded" />
id="agb_accepted"
name="agb_accepted"
type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div> </div>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label <label for="agb_accepted" class="font-medium text-gray-600 select-none">
for="agb_accepted"
class="font-medium text-gray-400 select-none"
>
{{ $t("i_accept", { tos: $t("privacy_policy") }) }} {{ $t("i_accept", { tos: $t("privacy_policy") }) }}
<a <a target="_blank" rel="noreferrer,noopener" href="https://lauf-fuer-kaya.de/datenschutz/"
target="_blank" class="underline">{{ $t("privacy_policy") }}</a>
rel="noreferrer,noopener"
href="https://lauf-fuer-kaya.de/datenschutz/"
class="underline"
>{{ $t("privacy_policy") }}</a
>
{{ $t("i_accept_end") }} {{ $t("i_accept_end") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
@ -404,33 +293,21 @@
</div> </div>
<div class="flex items-start mt-6"> <div class="flex items-start mt-6">
<div class="flex items-center h-5"> <div class="flex items-center h-5">
<input <input v-model="data_confirmed" id="data_confirmed" name="data_confirmed" type="checkbox"
v-model="data_confirmed" class="h-4 w-4 text-indigo-600 border-gray-300 rounded" />
id="data_confirmed"
name="data_confirmed"
type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div> </div>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label <label for="data_confirmed" class="font-medium text-gray-600 select-none">
for="data_confirmed"
class="font-medium text-gray-400 select-none"
>
{{ $t("confirm_personal_data") }} {{ $t("confirm_personal_data") }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
</div> </div>
</div> </div>
<div class="mt-6"> <div class="mt-6">
<button <button @click="login" :disabled="!state.submit_enabled" :class="{
@click="login"
:disabled="!state.submit_enabled"
:class="{
'opacity-50': !state.submit_enabled, 'opacity-50': !state.submit_enabled,
'cursor-not-allowed': !state.submit_enabled, 'cursor-not-allowed': !state.submit_enabled,
}" }" class="
class="
text-white text-white
block block
w-full w-full
@ -442,11 +319,12 @@
p-1 p-1
bg-blue-800 bg-blue-800
font-medium font-medium
hover:border-gray-400 not-disabled:hover:border-gray-400
focus:outline-none focus:border-gray-400 not-disabled:hover:bg-blue-600
not-disabled:cursor-pointer
not-disabled:focus:outline-none focus:border-gray-400
sm:text-sm sm:text-sm
" ">
>
{{ $t("registrieren") }} {{ $t("registrieren") }}
</button> </button>
</div> </div>
@ -457,13 +335,15 @@
</template> </template>
<script setup> <script setup>
import { computed, ref, reactive, defineProps } from "vue"; import { computed, ref, reactive } from "vue";
import axios from "redaxios"; import axios from "redaxios";
import isEmail from "validator/es/lib/isEmail"; import isEmail from "validator/es/lib/isEmail";
import isMobilePhone from "validator/es/lib/isMobilePhone"; import isMobilePhone from "validator/es/lib/isMobilePhone";
import isPostalCode from "validator/es/lib/isPostalCode"; import isPostalCode from "validator/es/lib/isPostalCode";
import { TYPE, useToast } from "vue-toastification"; import { TYPE, useToast } from "vue-toastification";
import Footer from "@/components/Footer.vue"; import Footer from "@/components/Footer.vue";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const props = defineProps({ const props = defineProps({
token: String, token: String,
@ -541,7 +421,7 @@ function login() {
if (state.org_name !== "" && state.org_teams.length > 0) { if (state.org_name !== "" && state.org_teams.length > 0) {
postdata.team = org_team.value; postdata.team = org_team.value;
} }
toast("Registrierung läuft..."); toast(t('registration_running'));
const browserlocale = ( const browserlocale = (
(navigator.languages && navigator.languages[0]) || (navigator.languages && navigator.languages[0]) ||
"" ""
@ -559,7 +439,13 @@ function login() {
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
if (error.data.message === "E-Mail already registered") { if (error.data.message === "E-Mail already registered") {
toast("bereits registriert...", { type: TYPE.ERROR }); toast(t('already_registered'), { type: TYPE.ERROR });
} else if (error.data.message === "Invalid body, check 'errors' property for more info.") {
error.data.errors.forEach(e => {
if (e.property === "phone") {
toast(t('invalid_input_phone_number_should_be_international_format'), { type: TYPE.ERROR });
}
});
} }
}); });
} }

View File

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

View File

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

View File

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