Compare commits

...

23 Commits

Author SHA1 Message Date
5587175534 🚀Bumped version to v0.10.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:19:08 +01:00
8e2b355466 updated nginx config for cache busting
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:18:57 +01:00
eccce0795b text cleanups + footer
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:14:01 +01:00
54540be6e1 improved profile page padding + full width registration code for easier scanning
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 17:04:25 +01:00
3392a2e68e 🚀Bumped version to v0.9.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:52:50 +01:00
8928f841dc wip: registration confirmation ui
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:52:38 +01:00
9ac14e8a5d wip: error registration ui feedback
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:48:14 +01:00
4a5b9d2569 🚀Bumped version to v0.8.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:44:43 +01:00
123509d0a6 fix: registration code (broke in merge)
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:44:10 +01:00
51f8d0fb42 wip: fix registration code
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 16:41:42 +01:00
f4d1c7b053 🚀Bumped version to v0.8.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:51:54 +01:00
ab9b400fff /profile/ dont instantly show mail format error
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:51:23 +01:00
ac75828309 /profile/ move from anchor tag to button
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:51:09 +01:00
c7f3a893af /profile/ toast styles
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:50:54 +01:00
30fd7ead08 /profile/ autocomplete mail
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:50:40 +01:00
64e6ef8cec /profile/ text cleanups
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:50:27 +01:00
c35f943957 move /registered/ to props
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-03 13:46:18 +01:00
292e44057a 🚀Bumped version to v0.8.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 15:54:17 +01:00
20fca6794d Adjusted button text 2023-02-02 15:53:58 +01:00
8139d63715 Switched request login link api path to login (backend v13.0.0) 2023-02-02 15:52:33 +01:00
7051909bf9 🚀Bumped version to v0.8.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-02 00:16:29 +01:00
f7a0682c33 Merge pull request 'dont autologin on register -> require mail link' (#47) from feature/46-dont-autologin-on-register-require-mail-link into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #47
2023-02-01 23:16:11 +00:00
eb20b547e7 add /registered/?mail route
ref #46
2023-02-02 00:08:14 +01:00
10 changed files with 514 additions and 130 deletions

View File

@@ -2,9 +2,62 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [0.10.0](https://git.odit.services/lfk/selfservice/compare/0.9.0...0.10.0)
- text cleanups + footer [`eccce07`](https://git.odit.services/lfk/selfservice/commit/eccce0795b6960aa3a2e9368de5ae4bdf80997d7)
- updated nginx config for cache busting [`8e2b355`](https://git.odit.services/lfk/selfservice/commit/8e2b355466e9a37510be8bf03311d6b28e1a0d9f)
- improved profile page padding + full width registration code for easier scanning [`54540be`](https://git.odit.services/lfk/selfservice/commit/54540be6e12ed85afc96061b8548cd4ec6700eec)
#### [0.9.0](https://git.odit.services/lfk/selfservice/compare/0.8.3...0.9.0)
> 3 February 2023
- wip: error registration ui feedback [`9ac14e8`](https://git.odit.services/lfk/selfservice/commit/9ac14e8a5d740fb4cd87645e69b2cfde73e4acc7)
- wip: registration confirmation ui [`8928f84`](https://git.odit.services/lfk/selfservice/commit/8928f841dcd370daf28416adbf1adbe16fa4d76f)
- 🚀Bumped version to v0.9.0 [`3392a2e`](https://git.odit.services/lfk/selfservice/commit/3392a2e68edb8fcf2aa6dd4b962abbf6ac27a414)
#### [0.8.3](https://git.odit.services/lfk/selfservice/compare/0.8.2...0.8.3)
> 3 February 2023
- fix: registration code (broke in merge) [`123509d`](https://git.odit.services/lfk/selfservice/commit/123509d0a6d15fe254e28f7a316bd6c260fe7bd2)
- 🚀Bumped version to v0.8.3 [`4a5b9d2`](https://git.odit.services/lfk/selfservice/commit/4a5b9d25698931158a602b2159b4e6c4fa129e8e)
- wip: fix registration code [`51f8d0f`](https://git.odit.services/lfk/selfservice/commit/51f8d0fb42d0dbba268799eb9385686d22fd2284)
#### [0.8.2](https://git.odit.services/lfk/selfservice/compare/0.8.1...0.8.2)
> 3 February 2023
- move /registered/ to props [`c35f943`](https://git.odit.services/lfk/selfservice/commit/c35f943957e5ba84361a437c1d945331248746d1)
- 🚀Bumped version to v0.8.2 [`f4d1c7b`](https://git.odit.services/lfk/selfservice/commit/f4d1c7b053d1e7210911772bde1b2d80a30ab225)
- /profile/ text cleanups [`64e6ef8`](https://git.odit.services/lfk/selfservice/commit/64e6ef8cec38a8193c4fb28c5f1b26ee0e4d5063)
- /profile/ move from anchor tag to button [`ac75828`](https://git.odit.services/lfk/selfservice/commit/ac75828309043532c6ab8aad63e0c40edf450459)
- /profile/ toast styles [`c7f3a89`](https://git.odit.services/lfk/selfservice/commit/c7f3a893af8705af12f2e7ae7e40197ca4c28666)
- /profile/ dont instantly show mail format error [`ab9b400`](https://git.odit.services/lfk/selfservice/commit/ab9b400fff1b421a41dd27479a81fb5e3740b9ef)
- /profile/ autocomplete mail [`30fd7ea`](https://git.odit.services/lfk/selfservice/commit/30fd7ead0833b0b3ab4e5509608aa92112151380)
#### [0.8.1](https://git.odit.services/lfk/selfservice/compare/0.8.0...0.8.1)
> 2 February 2023
- 🚀Bumped version to v0.8.1 [`292e440`](https://git.odit.services/lfk/selfservice/commit/292e44057aee9ef57a51aa9fa0372c3678b81de0)
- Adjusted button text [`20fca67`](https://git.odit.services/lfk/selfservice/commit/20fca6794dd7e0c714cd09c80a68b1d3592ab09c)
- Switched request login link api path to login (backend v13.0.0) [`8139d63`](https://git.odit.services/lfk/selfservice/commit/8139d637151c8c0184e4a98f151991b429d0a70c)
#### [0.8.0](https://git.odit.services/lfk/selfservice/compare/0.7.11...0.8.0)
> 2 February 2023
- 🚀Bumped version to v0.8.0 [`7051909`](https://git.odit.services/lfk/selfservice/commit/7051909bf960fb44b43e979ac4d304dff9ef2ec4)
- Merge pull request 'dont autologin on register -> require mail link' (#47) from feature/46-dont-autologin-on-register-require-mail-link into dev [`f7a0682`](https://git.odit.services/lfk/selfservice/commit/f7a0682c3392b8882be4a676882c8a49d55bd5fe)
- add /registered/?mail route [`eb20b54`](https://git.odit.services/lfk/selfservice/commit/eb20b547e79d352f3b7cd1b5ce7b7dbfcf8c19f7)
#### [0.7.11](https://git.odit.services/lfk/selfservice/compare/0.7.10...0.7.11)
> 2 February 2023
- Profile: improved mobile responsiveness/ design + toast clear [`077b33f`](https://git.odit.services/lfk/selfservice/commit/077b33f03180d0bd6c45becaaa63d3408c645deb)
- 🚀Bumped version to v0.7.11 [`c63adf5`](https://git.odit.services/lfk/selfservice/commit/c63adf557bcb29c8eccc05d5a83d476c75380d95)
- fix: registration code download button style [`52a6b3d`](https://git.odit.services/lfk/selfservice/commit/52a6b3dc776b806eaa8fee058a1c381ab63a8ea5)
#### [0.7.10](https://git.odit.services/lfk/selfservice/compare/0.7.9...0.7.10)

View File

@@ -7,15 +7,21 @@ http {
error_page 404 /index.html;
root /usr/share/nginx/html;
location / {
rewrite /register/(.*) /$1 break;
rewrite /profile/(.*) /$1 break;
rewrite /register/(.*) /$1 break;
rewrite /profile/(.*) /$1 break;
try_files $uri $uri/ /index.html;
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
location ~* \.(?:ico|css|gif|jpe?g|png)$ {
rewrite /register/(.*) /$1 break;
rewrite /profile/(.*) /$1 break;
rewrite /register/(.*) /$1 break;
rewrite /profile/(.*) /$1 break;
expires 1y;
add_header Pragma public;
@@ -35,24 +41,24 @@ http {
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types application/javascript
application/rss+xml
application/vnd.ms-fontobject
application/x-font
application/x-font-opentype
application/x-font-otf
application/x-font-truetype
application/x-font-ttf
application/x-javascript
application/xhtml+xml
application/xml
font/opentype
font/otf
font/ttf
image/svg+xml
image/x-icon
text/css
text/javascript
text/plain
text/xml;
application/rss+xml
application/vnd.ms-fontobject
application/x-font
application/x-font-opentype
application/x-font-otf
application/x-font-truetype
application/x-font-ttf
application/x-javascript
application/xhtml+xml
application/xml
font/opentype
font/otf
font/ttf
image/svg+xml
image/x-icon
text/css
text/javascript
text/plain
text/xml;
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@odit/lfk-selfservice",
"version": "0.7.11",
"version": "0.10.0",
"scripts": {
"dev": "vite",
"build": "vite build",

View File

@@ -13,5 +13,4 @@ const config = {
url_imprint: '',
// optional, will fallback to baseurl_selfservice/privacy
url_privacy: '',
codeformat: 'code39'
};

View File

@@ -1,11 +1,11 @@
{
"access_is_only_provided_via_your_email_link": "Der Zugang erfolgt nur über den Link, den Sie bei der Registrierung erhalten haben.",
"access_is_only_provided_via_your_email_link": "Der Zugang erfolgt über den Link, den Sie bei der Registrierung erhalten haben.",
"already_have_an_account": "Sie haben bereits einen Account?",
"amount_per_kilometer_in_eur": "Betrag pro Kilometer (in €)",
"apartment_suite_etc": "Addresszeile 2",
"cancel_keep_my_data": "Abbrechen, meine Daten behalten",
"configuration_error": "Konfigurationsfehler",
"confirm_delete_all_of_my_data": "Bestätigung, meine gesamten Daten löschen",
"confirm_delete_all_of_my_data": "Bestätigen, meine Daten löschen",
"confirm_personal_data": "Hiermit bestätige ich die Vollständigkeit und Richtigkeit der oben genannten Angaben",
"current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)",
"delete_all_of_my_data": "Meine gesamten Daten löschen",
@@ -22,7 +22,7 @@
"imprint": "Impressum",
"lap_time": "Rundenzeit",
"lap_times": "Rundenzeiten",
"lost_your_registration_mail": "Haben Sie Ihre Registrierungsmail verloren?",
"lost_your_registration_mail": "Brauchen Sie einen neuen Login-Link?",
"main_page_text": "Hier können Sie sich für den Lauf Für Kaya! registrieren oder ihr Läuferprofil verwalten.",
"mittelname": "Mittelname",
"nachname": "Nachname",
@@ -45,7 +45,7 @@
"register_now_small": "Jetzt registrieren",
"registrieren": "Registrieren",
"registrierungscode": "Registrierungscode",
"resend_the_registration_mail": "Registrierungsmail erneut versenden",
"resend_the_registration_mail": "Login-Link anfordern",
"save_changes": "Änderungen speichern",
"sponsoring": "Sponsoring",
"strasse": "Straße",

View File

@@ -44,7 +44,7 @@
"register_now": "Register now!",
"register_now_small": "Register now",
"registrieren": "Register Now",
"resend_the_registration_mail": "Resend the registration mail",
"resend_the_registration_mail": "Send me a login link",
"save_changes": "Save changes",
"sponsoring": "Sponsoring",
"strasse": "Street/ Block",

View File

@@ -150,6 +150,10 @@
py-2.5
px-5
rounded-md
mb-1
md:mb-auto
w-full
md:w-auto
bg-blue-500
hover:bg-blue-600 hover:shadow-lg
"
@@ -188,9 +192,11 @@
py-2.5
px-5
rounded-md
w-full
md:w-auto
bg-red-600
hover:bg-red-700 hover:shadow-lg
ml-1
md:ml-1
"
@click="delete_me"
>
@@ -220,7 +226,7 @@
</div>
</section>
<div class="flex flex-wrap">
<div class="w-full p-4">
<div class="w-full">
<div class="flex flex-wrap flex-col w-full tabs">
<div class="flex lg:flex-wrap flex-row lg:space-x-2">
<div class="flex-none">
@@ -282,7 +288,11 @@
<div class="w-full">
<div class="form-element">
<div class="text-lg">{{ $t("registrierungscode") }}</div>
<img alt="Registrierungscode" :src="state.barcode" />
<img
class="w-full md:w-auto mb-2"
alt="Registrierungscode"
:src="state.barcode"
/>
<div class="text-lg">{{ $t("vorname") }}</div>
<p
class="
@@ -628,6 +638,52 @@
</div>
</div>
</div>
<!-- -->
<footer
class="
p-4
bg-white
rounded-lg
shadow
md:flex md:items-center md:justify-between md:p-6
dark:bg-gray-800
"
>
<span class="text-sm text-gray-500 sm:text-center dark:text-gray-400"
><span class="font-bold">LfK! 2023</span> -
<a
class="underline"
href="https://odit.services/?ref=lfk"
target="_blank"
>powered by ODIT.Services</a
>
</span>
<ul
class="
flex flex-wrap
items-center
mt-3
text-sm text-gray-500
dark:text-gray-400
sm:mt-0
"
>
<li>
<a
href="https://lauf-fuer-kaya.de/impressum/"
class="mr-4 hover:underline md:mr-6"
>Impressum</a
>
</li>
<li>
<a
href="https://lauf-fuer-kaya.de/datenschutz/"
class="mr-4 hover:underline md:mr-6"
>Datenschutz</a
>
</li>
</ul>
</footer>
</div>
</template>
@@ -638,17 +694,23 @@ import axios from "redaxios";
import bwipjs from "bwip-js";
function textToBase64Barcode(text) {
var canvas = document.createElement("canvas");
bwipjs.toCanvas(canvas, {
bcid: config.codeformat || "code39",
text: text,
const canvas = document.createElement("canvas");
let codeconfig = {
bcid: config.code_format || "code39",
text: `${text}`,
scale: 3,
height: 10,
// width: 10,
includetext: true,
includetext: false,
textxalign: "center",
backgroundcolor: "ffffff",
});
};
if (
codeconfig.bcid === "code39" ||
codeconfig.bcid === "code128" ||
codeconfig.bcid === "ean13"
) {
codeconfig.height = 10;
}
bwipjs.toCanvas(canvas, codeconfig);
return canvas.toDataURL("image/png");
}
@@ -749,13 +811,13 @@ function get_certificate() {
} else {
var fileURL = window.URL.createObjectURL(
new Blob([response.data], { type: "application/pdf" })
);
);
var fileLink = document.createElement("a");
fileLink.href = fileURL;
fileLink.setAttribute("download", "Certificate.pdf");
document.body.appendChild(fileLink);
fileLink.click();
fileLink.remove();
toast.clear();

View File

@@ -6,8 +6,8 @@
class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center"
>Lauf für Kaya! - {{ $t('profile') }}</h1>
<p class="mx-auto leading-relaxed text-base text-center">
{{ $t('you_have_not_provided_a_valid_access_key') }}
<br />
<!-- {{ $t('you_have_not_provided_a_valid_access_key') }}
<br /> -->
{{ $t('access_is_only_provided_via_your_email_link') }}
</p>
<div class="mt-6">
@@ -30,24 +30,24 @@
v-model="user_email"
name="email_address"
id="email_address"
autocomplete="off"
autocomplete="email"
:placeholder="[[$t('e_mail_adress')]]"
type="email"
:class="{ 'border-red-500': (!isEmail(user_email)), 'border-green-300': (isEmail(user_email)) }"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-2 bg-gray-50 text-gray-500 rounded-md p-2"
/>
<p
v-if="!isEmail(user_email)"
v-if="!isEmail(user_email)&&user_email!==''"
class="text-sm"
>{{ $t('please_provide_valid_mail') }}</p>
</div>
<div class="mt-2">
<a
<button
:disabled="(!state.submit_enabled)"
:class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }"
@click="resendMail"
class="block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 dark:bg-gray-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
>{{ $t('resend_the_registration_mail') }}</a>
>{{ $t('resend_the_registration_mail') }}</button>
</div>
</div>
<div class="mt-12">
@@ -76,7 +76,7 @@ import axios from "redaxios";
import isEmail from 'validator/es/lib/isEmail';
import isMobilePhone from 'validator/es/lib/isMobilePhone';
import isPostalCode from 'validator/es/lib/isPostalCode';
import { useToast } from "vue-toastification";
import { TYPE, useToast } from "vue-toastification";
let user_email = ref("");
//
@@ -90,14 +90,14 @@ function resendMail() {
if (isEmail(user_email.value)) {
toast("Login-Link wird angefordert...");
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
axios.post(`${config.baseurl}api/runners/forgot?mail=${user_email.value}&locale=${browserlocale}`)
axios.post(`${config.baseurl}api/runners/login?mail=${user_email.value}&locale=${browserlocale}`)
.then(({ data }) => {
console.log(data);
toast("Login-Link gesendet an " + user_email.value + "!");
})
.catch((error) => {
console.log(error);
toast("Fehler beim Anfordern des Login-Links...");
toast("Fehler beim Anfordern des Login-Links...", { type: TYPE.ERROR });
});
}
}

View File

@@ -1,33 +1,73 @@
<template>
<div class="min-h-screen flex items-center justify-center">
<div
class="min-h-screen flex items-center justify-center"
v-if="registrationState === 'registered'"
>
<div class="max-w-md w-full py-12 px-6">
<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! - {{ $t('registrieren') }}</h1>
<p class="mx-auto leading-relaxed text-base text-center">{{ $t('register.register_now') }}</p>
<h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center">
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">{{ userdetails.mail }}</b> geschickt haben.
</p>
</div>
</div>
<div class="min-h-screen flex items-center justify-center" v-else>
<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! - {{ $t("registrieren") }}
</h1>
<p class="mx-auto leading-relaxed text-base text-center">
{{ $t("register.register_now") }}
</p>
<p
v-if="state.org_name !== ''"
class="mx-auto leading-relaxed text-base text-center"
>{{ $t('organization') }}: {{ state.org_name }}</p>
>
{{ $t("organization") }}: {{ state.org_name }}
</p>
<p
v-if="state.org_name !== '' && state.org_teams.length > 0"
class="mx-auto leading-relaxed text-base text-center"
>Team:</p>
>
Team:
</p>
<select
v-model="org_team"
v-if="state.org_name !== '' && state.org_teams.length > 0"
class="w-full border bg-white rounded px-3 py-2 outline-none block mt-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 form-select focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray"
class="
w-full
border
bg-white
rounded
px-3
py-2
outline-none
block
mt-1
text-sm
dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700
form-select
focus:border-purple-400 focus:outline-none focus:shadow-outline-purple
dark:focus:shadow-outline-gray
"
>
<option v-for="t in state.org_teams" :key="t.id" :value="t.id">{{ t.name }}</option>
<option v-for="t in state.org_teams" :key="t.id" :value="t.id">
{{ t.name }}
</option>
</select>
<p
v-if="state.org_name === ''"
class="mx-auto leading-relaxed text-base text-center"
>Bürgerlauf</p>
>
Bürgerlauf
</p>
<div class="mt-4">
<label for="first_name" class="block font-medium">
{{ $t('vorname') }}
{{ $t("vorname") }}
<span class="font-bold">*</span>
</label>
<input
@@ -37,11 +77,28 @@
autocomplete="off"
:placeholder="[[$t('vorname')]]"
type="text"
:class="{ 'border-red-500': (!userdetails.firstname.trim()), 'border-green-300': (userdetails.firstname.trim()) }"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-gray-300 border-2 bg-gray-50 text-gray-500 rounded-md p-2"
:class="{
'border-red-500': !userdetails.firstname.trim(),
'border-green-300': userdetails.firstname.trim(),
}"
class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-gray-300 border-2
bg-gray-50
text-gray-500
rounded-md
p-2
"
/>
<!-- -->
<label for="middle_name" class="block font-medium">{{ $t('mittelname') }}</label>
<label for="middle_name" class="block font-medium">{{
$t("mittelname")
}}</label>
<input
v-model="userdetails.middlename"
name="middlename"
@@ -49,11 +106,23 @@
autocomplete="off"
:placeholder="[[$t('mittelname')]]"
type="text"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-gray-300 border-2 bg-gray-50 text-gray-500 rounded-md p-2"
class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-gray-300 border-2
bg-gray-50
text-gray-500
rounded-md
p-2
"
/>
<!-- -->
<label for="last_name" class="block font-medium">
{{ $t('nachname') }}
{{ $t("nachname") }}
<span class="font-bold">*</span>
</label>
<input
@@ -63,12 +132,27 @@
autocomplete="off"
:placeholder="[[$t('nachname')]]"
type="text"
:class="{ 'border-red-500': (!userdetails.lastname.trim()), 'border-green-300': (userdetails.lastname.trim()) }"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-gray-300 border-2 bg-gray-50 text-gray-500 rounded-md p-2"
:class="{
'border-red-500': !userdetails.lastname.trim(),
'border-green-300': userdetails.lastname.trim(),
}"
class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-gray-300 border-2
bg-gray-50
text-gray-500
rounded-md
p-2
"
/>
<!-- -->
<label for="email_address" class="block font-medium">
{{ $t('e_mail_adress') }}
{{ $t("e_mail_adress") }}
<span class="font-bold">*</span>
</label>
<input
@@ -78,12 +162,31 @@
autocomplete="off"
:placeholder="[[$t('e_mail_adress')]]"
type="email"
:class="{ 'border-red-500': (!isEmail(userdetails.mail)), 'border-green-300': (isEmail(userdetails.mail)) }"
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="{
'border-red-500': !isEmail(userdetails.mail),
'border-green-300': isEmail(userdetails.mail),
}"
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(userdetails.mail)" class="text-sm">{{ $t('please_provide_valid_mail') }}</p>
<p v-if="!isEmail(userdetails.mail)" class="text-sm">
{{ $t("please_provide_valid_mail") }}
</p>
<!-- -->
<label for="phone" class="select-none block font-medium">{{ $t('phone_number') }}</label>
<label for="phone" class="select-none block font-medium">{{
$t("phone_number")
}}</label>
<input
v-model="userdetails.phone"
name="phone"
@@ -91,13 +194,32 @@
autocomplete="off"
:placeholder="[[$t('phone_number')]]"
type="text"
:class="{ 'border-red-500': (!isMobilePhone(userdetails.phone) && userdetails.phone.trim()), 'border-green-300': (isMobilePhone(userdetails.phone) && userdetails.phone.trim()) }"
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="{
'border-red-500':
!isMobilePhone(userdetails.phone) && userdetails.phone.trim(),
'border-green-300':
isMobilePhone(userdetails.phone) && userdetails.phone.trim(),
}"
class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-2
bg-gray-50
text-gray-500
rounded-md
p-2
"
/>
<p
v-if="(!isMobilePhone(userdetails.phone) && userdetails.phone.trim())"
v-if="!isMobilePhone(userdetails.phone) && userdetails.phone.trim()"
class="text-sm"
>{{ $t('this_is_not_a_valid_international_phone_number') }}</p>
>
{{ $t("this_is_not_a_valid_international_phone_number") }}
</p>
<!-- -->
<div class="grid grid-cols-6 mt-6">
<div class="col-span-6"></div>
@@ -115,13 +237,14 @@
<label
for="address_activated"
class="font-medium text-gray-400 select-none"
>{{ $t('provide_address') }}</label>
>{{ $t("provide_address") }}</label
>
</div>
</div>
<div v-if="provide_address === true" class="col-span-6">
<div class="col-span-6">
<label for="street" class="block font-medium">
{{ $t('strasse') }}
{{ $t("strasse") }}
<span class="font-bold">*</span>
</label>
<input
@@ -131,12 +254,29 @@
:placeholder="[[$t('strasse')]]"
id="street"
autocomplete="street-address"
:class="{ 'border-red-500': (!userdetails.address.street.trim()), 'border-green-300': (userdetails.address.street.trim()) }"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-gray-300 border-2 bg-gray-50 text-gray-500 rounded-md p-2"
:class="{
'border-red-500': !userdetails.address.street.trim(),
'border-green-300': userdetails.address.street.trim(),
}"
class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-gray-300 border-2
bg-gray-50
text-gray-500
rounded-md
p-2
"
/>
</div>
<div class="col-span-6">
<label for="address2" class="block font-medium">{{ $t('apartment_suite_etc') }}</label>
<label for="address2" class="block font-medium">{{
$t("apartment_suite_etc")
}}</label>
<input
v-model="userdetails.address.address2"
type="text"
@@ -144,12 +284,24 @@
:placeholder="[[$t('apartment_suite_etc')]]"
id="address2"
autocomplete="street-address"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-gray-300 border-2 bg-gray-50 text-gray-500 rounded-md p-2"
class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-gray-300 border-2
bg-gray-50
text-gray-500
rounded-md
p-2
"
/>
</div>
<div class="col-span-6 sm:col-span-6 lg:col-span-2">
<label for="city" class="block font-medium">
{{ $t('ort') }}
{{ $t("ort") }}
<span class="font-bold">*</span>
</label>
<input
@@ -158,13 +310,28 @@
name="city"
:placeholder="[[$t('ort')]]"
id="city"
:class="{ 'border-red-500': (!userdetails.address.city.trim()), 'border-green-300': (userdetails.address.city.trim()) }"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-gray-300 border-2 bg-gray-50 text-gray-500 rounded-md p-2"
:class="{
'border-red-500': !userdetails.address.city.trim(),
'border-green-300': userdetails.address.city.trim(),
}"
class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-gray-300 border-2
bg-gray-50
text-gray-500
rounded-md
p-2
"
/>
</div>
<div class="col-span-6 sm:col-span-3 lg:col-span-2">
<label for="postal_code" class="block font-medium">
{{ $t('plz') }}
{{ $t("plz") }}
<span class="font-bold">*</span>
</label>
<input
@@ -174,14 +341,37 @@
:placeholder="[[$t('plz')]]"
id="postal_code"
autocomplete="postal-code"
:class="{ 'border-red-500': (!isPostalCode(userdetails.address.zipcode, 'DE')), 'border-green-300': (isPostalCode(userdetails.address.zipcode, 'DE')) }"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-gray-300 border-2 bg-gray-50 text-gray-500 rounded-md p-2"
:class="{
'border-red-500': !isPostalCode(
userdetails.address.zipcode,
'DE'
),
'border-green-300': isPostalCode(
userdetails.address.zipcode,
'DE'
),
}"
class="
dark:bg-gray-800
mt-1
block
w-full
shadow-sm
sm:text-sm
border-gray-300 border-2
bg-gray-50
text-gray-500
rounded-md
p-2
"
/>
</div>
<p
v-if="!isPostalCode(userdetails.address.zipcode, 'DE')"
class="text-sm"
>{{ $t('please_provide_a_valid_zipcode') }}</p>
>
{{ $t("please_provide_a_valid_zipcode") }}
</p>
</div>
</div>
<div class="flex items-start mt-6">
@@ -195,15 +385,19 @@
/>
</div>
<div class="ml-3 text-sm">
<label for="agb_accepted" class="font-medium text-gray-400 select-none">
{{ $t('i_accept', { tos: $t('tos') }) }}
<label
for="agb_accepted"
class="font-medium text-gray-400 select-none"
>
{{ $t("i_accept", { tos: $t("tos") }) }}
<a
target="_blank"
rel="noreferrer,noopener"
href="https://lauf-fuer-kaya.de/datenschutz/"
class="underline"
>{{ $t('tos') }}</a>
{{ $t('i_accept_end') }}
>{{ $t("tos") }}</a
>
{{ $t("i_accept_end") }}
<span class="font-bold">*</span>
</label>
</div>
@@ -219,8 +413,11 @@
/>
</div>
<div class="ml-3 text-sm">
<label for="data_confirmed" class="font-medium text-gray-400 select-none">
{{ $t('confirm_personal_data') }}
<label
for="data_confirmed"
class="font-medium text-gray-400 select-none"
>
{{ $t("confirm_personal_data") }}
<span class="font-bold">*</span>
</label>
</div>
@@ -228,10 +425,30 @@
<div class="mt-6">
<button
@click="login"
:disabled="(!state.submit_enabled)"
:class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }"
class="text-white block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 bg-blue-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
>{{ $t('registrieren') }}</button>
:disabled="!state.submit_enabled"
:class="{
'opacity-50': !state.submit_enabled,
'cursor-not-allowed': !state.submit_enabled,
}"
class="
text-white
block
w-full
text-center
py-2
px-3
border-2 border-gray-300
rounded-md
p-1
bg-blue-800
font-medium
hover:border-gray-400
focus:outline-none focus:border-gray-400
sm:text-sm
"
>
{{ $t("registrieren") }}
</button>
</div>
</div>
</div>
@@ -241,16 +458,17 @@
<script setup>
import { computed, ref, reactive, defineProps } from "vue";
import axios from "redaxios";
import isEmail from 'validator/es/lib/isEmail';
import isMobilePhone from 'validator/es/lib/isMobilePhone';
import isPostalCode from 'validator/es/lib/isPostalCode';
import { useToast } from "vue-toastification";
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";
const props = defineProps({
token: String
})
token: String,
});
if (props.token) {
axios.get(`${config.baseurl}api/organizations/selfservice/${props.token}`)
axios
.get(`${config.baseurl}api/organizations/selfservice/${props.token}`)
.then(({ data }) => {
state.org_name = data.name;
state.org_teams = data.teams;
@@ -261,31 +479,51 @@ if (props.token) {
});
}
let userdetails = ref({ firstname: "", lastname: "", middlename: "", mail: "", phone: "", address: { street: "", address2: "", city: "", zipcode: "" } });
let userdetails = ref({
firstname: "",
lastname: "",
middlename: "",
mail: "",
phone: "",
address: { street: "", address2: "", city: "", zipcode: "" },
});
let provide_address = ref(false);
let agb_accepted = ref(false);
let data_confirmed = ref(false);
let org_team = ref("");
//
let registrationState = ref("pending");
//
const state = reactive({
org_name: "",
org_teams: [],
submit_enabled: computed(() => agb_accepted.value === true && data_confirmed.value === true && (isMobilePhone(userdetails.value.phone) || !userdetails.value.phone.trim()) && isEmail(userdetails.value.mail)
&& userdetails.value.firstname
&& userdetails.value.lastname && (provide_address.value === false || provide_address.value === true && (userdetails.value.address.street.trim() && userdetails.value.address.city.trim() && isPostalCode(userdetails.value.address.zipcode, "DE"))))
})
submit_enabled: computed(
() =>
agb_accepted.value === true &&
data_confirmed.value === true &&
(isMobilePhone(userdetails.value.phone) ||
!userdetails.value.phone.trim()) &&
isEmail(userdetails.value.mail) &&
userdetails.value.firstname &&
userdetails.value.lastname &&
(provide_address.value === false ||
(provide_address.value === true &&
userdetails.value.address.street.trim() &&
userdetails.value.address.city.trim() &&
isPostalCode(userdetails.value.address.zipcode, "DE")))
),
});
const toast = useToast();
function login() {
userdetails = userdetails.value;
if (userdetails?.phone === "" || isMobilePhone(userdetails.phone)) {
if (isEmail(userdetails.mail)) {
let postdata = {
"email": userdetails.mail,
"firstname": userdetails.firstname,
"middlename": userdetails.middlename,
"lastname": userdetails.lastname,
"address": {}
}
email: userdetails.mail,
firstname: userdetails.firstname,
middlename: userdetails.middlename,
lastname: userdetails.lastname,
address: {},
};
if (isMobilePhone(userdetails.phone)) {
postdata.phone = userdetails.phone;
}
@@ -296,25 +534,31 @@ function login() {
city: userdetails.address.city,
postalcode: userdetails.address.zipcode,
country: "DE",
}
};
}
if (state.org_name !== '' && state.org_teams.length > 0) {
if (state.org_name !== "" && state.org_teams.length > 0) {
postdata.team = org_team.value;
}
toast("Registrierung läuft...");
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
const browserlocale = (
(navigator.languages && navigator.languages[0]) ||
""
).substr(0, 2);
let url = `${config.baseurl}api/runners/register/?locale=${browserlocale}`;
if (props.token) {
url = `${config.baseurl}api/runners/register/${props.token}/?locale=${browserlocale}`
url = `${config.baseurl}api/runners/register/${props.token}/?locale=${browserlocale}`;
}
axios.post(url, postdata)
.then(({ data }) => {
const token = btoa(data.token);
// alert(token);
location.replace(`${config.baseurl_selfservice}profile/${token}`);
registrationState.value = "loading";
axios
.post(url, postdata)
.then(() => {
registrationState.value = "registered";
})
.catch((error) => {
console.log(error);
if (error.data.message === "E-Mail already registered") {
toast("bereits registriert...", { type: TYPE.ERROR });
}
});
}
}

20
src/views/Registered.vue Normal file
View File

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