Compare commits

...

22 Commits
0.6.1 ... 0.7.3

Author SHA1 Message Date
602d80bd14 🚀Bumped version to v0.7.3
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-21 15:38:27 +02:00
45ee4ab812 Merge pull request 'Button fixes bugfix/42-button_links' (#43) from bugfix/42-button_links into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #43
2021-04-21 13:38:10 +00:00
020c310865 Fixed register button link
ref #42
2021-04-21 12:33:16 +02:00
1102d29c0e Removed useless register now button
ref #42
2021-04-21 12:31:46 +02:00
1a3af200dd 🚀Bumped version to v0.7.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-14 12:19:43 +02:00
71f419ffb4 Merge branch 'dev' of git.odit.services:lfk/selfservice into dev
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-14 12:18:09 +02:00
b74bea0340 Document generation hotfix 🐞 2021-04-14 12:18:02 +02:00
b0172c500b 🚀Bumped version to v0.7.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-13 18:08:19 +02:00
75b4dac0fe Merge pull request 'bugfix/31-env-js-linking-ci' (#41) from bugfix/31-env-js-linking-ci into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #41
close #31
2021-04-13 16:02:44 +00:00
51d058bf96 added 'yarn postbuild' script for fixing env.js in dist/index.html
ref #31
2021-04-13 17:58:43 +02:00
ad13bae068 dependency bump 2021-04-13 17:57:41 +02:00
152e74190d 🚀Bumped version to v0.7.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-06 21:28:02 +02:00
4c83e2e738 Merge pull request 'Donation list feature/39-donation_list' (#40) from feature/39-donation_list into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #40
2021-04-06 19:27:30 +00:00
cb1b9d330b Sorted translations 🌍
ref #39
2021-04-06 21:25:36 +02:00
3b4c11e4c0 Merge branch 'feature/39-donation_list' of git.odit.services:lfk/selfservice into feature/39-donation_list 2021-04-06 21:25:12 +02:00
89820d4450 Added total to bottom of page
ref #39
2021-04-06 21:25:10 +02:00
121022c843 added distance formatting
ref #39
2021-04-06 21:23:24 +02:00
d713fbef94 Added translations 🌍
ref #39
2021-04-06 17:27:18 +02:00
815a36f202 Now w/ formatted currency amount
ref #39
2021-04-06 17:20:41 +02:00
baa6da3dd0 Fixed spaces in name
ref #39
2021-04-06 17:18:09 +02:00
f141130db5 Added basic sponsoring table
ref #39
2021-04-06 17:14:22 +02:00
5a123b0cf8 Updated env description
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-06 17:03:05 +02:00
10 changed files with 580 additions and 454 deletions

View File

@@ -2,8 +2,48 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [0.7.3](https://git.odit.services/lfk/selfservice/compare/0.7.2...0.7.3)
- Merge pull request 'Button fixes bugfix/42-button_links' (#43) from bugfix/42-button_links into dev [`45ee4ab`](https://git.odit.services/lfk/selfservice/commit/45ee4ab81260adf5b938d9f5359d256cce879acb)
- Removed useless register now button [`1102d29`](https://git.odit.services/lfk/selfservice/commit/1102d29c0e174b7a34fc4d3e6fe32d2dfb276765)
- Fixed register button link [`020c310`](https://git.odit.services/lfk/selfservice/commit/020c310865912b8f0752069e1c7e2adf71ab9835)
#### [0.7.2](https://git.odit.services/lfk/selfservice/compare/0.7.1...0.7.2)
> 14 April 2021
- 🚀Bumped version to v0.7.2 [`1a3af20`](https://git.odit.services/lfk/selfservice/commit/1a3af200dd41c8cc4271690ed72bef911901ce54)
- Document generation hotfix 🐞 [`b74bea0`](https://git.odit.services/lfk/selfservice/commit/b74bea03401c672ae774aaddc6da5beb67e2890e)
#### [0.7.1](https://git.odit.services/lfk/selfservice/compare/0.7.0...0.7.1)
> 13 April 2021
- Merge pull request 'bugfix/31-env-js-linking-ci' (#41) from bugfix/31-env-js-linking-ci into dev [`#31`](https://git.odit.services/lfk/selfservice/issues/31)
- ⏫ dependency bump [`ad13bae`](https://git.odit.services/lfk/selfservice/commit/ad13bae068416bed10d00e6887a05d580a836482)
- 🚀Bumped version to v0.7.1 [`b0172c5`](https://git.odit.services/lfk/selfservice/commit/b0172c500b0613209ac44e61023043065b3854b0)
- added 'yarn postbuild' script for fixing env.js in dist/index.html [`51d058b`](https://git.odit.services/lfk/selfservice/commit/51d058bf966c3dcb064562e6bf696a748d0cd148)
#### [0.7.0](https://git.odit.services/lfk/selfservice/compare/0.6.1...0.7.0)
> 6 April 2021
- 🚀Bumped version to v0.7.0 [`152e741`](https://git.odit.services/lfk/selfservice/commit/152e74190d13d30110d494a9062f868390ca19b3)
- Merge pull request 'Donation list feature/39-donation_list' (#40) from feature/39-donation_list into dev [`4c83e2e`](https://git.odit.services/lfk/selfservice/commit/4c83e2e738a075354383dca4d500808f761247d2)
- Added total to bottom of page [`89820d4`](https://git.odit.services/lfk/selfservice/commit/89820d44501793365248b8e778522cdc188afa70)
- Sorted translations 🌍 [`cb1b9d3`](https://git.odit.services/lfk/selfservice/commit/cb1b9d330b28f11cceed9691aee4ccee5246d346)
- Added basic sponsoring table [`f141130`](https://git.odit.services/lfk/selfservice/commit/f141130db5ede60a623747f4e324f66259e5bc75)
- Added translations 🌍 [`d713fbe`](https://git.odit.services/lfk/selfservice/commit/d713fbef94e75fbbc62254ea8f0ca50dc4e93d79)
- Now w/ formatted currency amount [`815a36f`](https://git.odit.services/lfk/selfservice/commit/815a36f20271f47f49c3814b001c3404d43113cd)
- Fixed spaces in name [`baa6da3`](https://git.odit.services/lfk/selfservice/commit/baa6da3dd06c493fccc61945b9bcbd9b2e79d910)
- Updated env description [`5a123b0`](https://git.odit.services/lfk/selfservice/commit/5a123b0cf89f49d450becbbc03b28c5bb6416b7c)
- added distance formatting [`121022c`](https://git.odit.services/lfk/selfservice/commit/121022c8434484a363a3f2ea68aba4d8ef7cad2d)
#### [0.6.1](https://git.odit.services/lfk/selfservice/compare/0.6.0...0.6.1) #### [0.6.1](https://git.odit.services/lfk/selfservice/compare/0.6.0...0.6.1)
> 6 April 2021
- 🚀Bumped version to v0.6.1 [`f5ae214`](https://git.odit.services/lfk/selfservice/commit/f5ae2145df07413329f60c229d9571fd1de2ca79)
- Fixed imprint/privacy default links [`96c0e56`](https://git.odit.services/lfk/selfservice/commit/96c0e5698697361e65c5aa80c9a0aada5c3d5f30) - Fixed imprint/privacy default links [`96c0e56`](https://git.odit.services/lfk/selfservice/commit/96c0e5698697361e65c5aa80c9a0aada5c3d5f30)
#### [0.6.0](https://git.odit.services/lfk/selfservice/compare/0.5.1...0.6.0) #### [0.6.0](https://git.odit.services/lfk/selfservice/compare/0.5.1...0.6.0)

View File

@@ -3,6 +3,7 @@ WORKDIR /app
COPY . . COPY . .
RUN yarn RUN yarn
RUN yarn build RUN yarn build
RUN yarn postbuild
# final image # final image
FROM fholzer/nginx-brotli:v1.19.1 FROM fholzer/nginx-brotli:v1.19.1
COPY --from=0 /app/dist /usr/share/nginx/html COPY --from=0 /app/dist /usr/share/nginx/html

6
env_fix.js Normal file
View File

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

View File

@@ -1,17 +1,18 @@
{ {
"name": "@odit/lfk-selfservice", "name": "@odit/lfk-selfservice",
"version": "0.6.1", "version": "0.7.3",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"release": "release-it --only-version" "release": "release-it --only-version",
"postbuild": "node env_fix.js"
}, },
"dependencies": { "dependencies": {
"marked": "2.0.1", "marked": "2.0.3",
"redaxios": "0.4.1", "redaxios": "0.4.1",
"toastify-js": "1.10.0", "toastify-js": "1.10.0",
"validator": "13.5.2", "validator": "13.5.2",
"vue-i18n": "9.0.0", "vue-i18n": "9.1.4",
"vue-toastification": "2.0.0-rc.1", "vue-toastification": "2.0.0-rc.1",
"vue": "3.0.9", "vue": "3.0.9",
"vue-router": "4.0.5" "vue-router": "4.0.5"
@@ -23,10 +24,10 @@
"@tailwindcss/line-clamp": "0.2.0", "@tailwindcss/line-clamp": "0.2.0",
"@tailwindcss/typography": "0.4.0", "@tailwindcss/typography": "0.4.0",
"@vitejs/plugin-vue": "1.2.1", "@vitejs/plugin-vue": "1.2.1",
"@vue/compiler-sfc": "3.0.10", "@vue/compiler-sfc": "3.0.11",
"autoprefixer": "10.2.5", "autoprefixer": "10.2.5",
"tailwindcss": "2.0.4", "tailwindcss": "2.1.1",
"release-it": "14.5.0", "release-it": "14.6.1",
"vite": "2.1.5" "vite": "2.1.5"
}, },
"release-it": { "release-it": {

View File

@@ -5,8 +5,10 @@ const config = {
baseurl: '', baseurl: '',
// optional, will fallback to /selfservice/ // optional, will fallback to /selfservice/
baseurl_selfservice: '/selfservice/', baseurl_selfservice: '/selfservice/',
// optional, will fallback to /imprint // full url (including fqdn)
baseurl_documentserver: 'http://localhost:4010/documents',
// optional, will fallback to baseurl_selfservice/imprint
url_imprint: '', url_imprint: '',
// optional, will fallback to /privacy // optional, will fallback to baseurl_selfservice/privacy
url_privacy: '' url_privacy: ''
}; };

View File

@@ -1,12 +1,14 @@
{ {
"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 nur über den Link, den Sie bei der Registrierung erhalten haben.",
"already_have_an_account": "Sie haben bereits einen Account?", "already_have_an_account": "Sie haben bereits einen Account?",
"amount_per_kilometer_in_eur": "Betrag pro Kilometer (in €)",
"apartment_suite_etc": "Addresszeile 2", "apartment_suite_etc": "Addresszeile 2",
"cancel_keep_my_data": "Abbrechen, meine Daten behalten", "cancel_keep_my_data": "Abbrechen, meine Daten behalten",
"configuration_error": "Konfigurationsfehler", "configuration_error": "Konfigurationsfehler",
"confirm_delete_all_of_my_data": "Bestätigung, meine gesamten Daten löschen", "confirm_delete_all_of_my_data": "Bestätigung, meine gesamten 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",
"delete-all-of-my-data": "Meine gesamten Daten löschen", "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...", "deletion_in_progress": "Daten werden gelöscht...",
"distance": "Distanz", "distance": "Distanz",
@@ -24,6 +26,7 @@
"mittelname": "Mittelname", "mittelname": "Mittelname",
"nachname": "Nachname", "nachname": "Nachname",
"no_laps_scans_were_recorded_yet": "Es wurden noch keine Runden / Scans aufgezeichnet ...", "no_laps_scans_were_recorded_yet": "Es wurden noch keine Runden / Scans aufgezeichnet ...",
"no_sponsorings_for_you_were_recorded_yet": "Es gibt noch keine Sponsorings für dich",
"not_registered_yet": "Noch nicht registriert?", "not_registered_yet": "Noch nicht registriert?",
"organization": "Organisation", "organization": "Organisation",
"ort": "Ort", "ort": "Ort",
@@ -47,6 +50,7 @@
"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", "tos": "AGBs",
"total": "Gesamt",
"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_been_registered": "Sie wurden registriert!",

View File

@@ -2,11 +2,13 @@
"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!", "all_data_deleted": "All Data deleted!",
"already_have_an_account": "Already have an account?", "already_have_an_account": "Already have an account?",
"amount_per_kilometer_in_eur": "Amount per kilometer (in €)",
"apartment_suite_etc": "Apartment, suite, etc.", "apartment_suite_etc": "Apartment, suite, etc.",
"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 €)",
"delete_my_data": "Delete my data", "delete_my_data": "Delete my data",
"deletion_in_progress": "Deletion in progress...", "deletion_in_progress": "Deletion in progress...",
"distance": "Distance", "distance": "Distance",
@@ -24,6 +26,7 @@
"mittelname": "Middlename", "mittelname": "Middlename",
"nachname": "Lastname", "nachname": "Lastname",
"no_laps_scans_were_recorded_yet": "No laps/ scans were recorded yet...", "no_laps_scans_were_recorded_yet": "No laps/ scans were recorded yet...",
"no_sponsorings_for_you_were_recorded_yet": "No sponsorings for you were recorded yet...",
"not_registered_yet": "Not registered yet?", "not_registered_yet": "Not registered yet?",
"organization": "Organization", "organization": "Organization",
"ort": "City", "ort": "City",
@@ -47,6 +50,7 @@
"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", "tos": "Terms of Service",
"total": "Total",
"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_been_registered": "You have been registered!",

View File

@@ -216,7 +216,7 @@
<tbody class="text-gray-900 dark:text-gray-50"> <tbody class="text-gray-900 dark:text-gray-50">
<tr v-for="s in state.scans" :key="s.id"> <tr v-for="s in state.scans" :key="s.id">
<td class="px-4 py-3"> <td class="px-4 py-3">
<span v-text="s.distance"></span>m <span v-text="s.distance"></span>
</td> </td>
<td class="px-4 py-3" v-text="s.lapTime"></td> <td class="px-4 py-3" v-text="s.lapTime"></td>
</tr> </tr>
@@ -236,7 +236,88 @@
</div> </div>
</div> </div>
<div v-if="(state.activetab === 'sponsorings')" class="tab-content block"> <div v-if="(state.activetab === 'sponsorings')" class="tab-content block">
<div class="py-4 w-full">coming soon...</div> <div class="py-4 w-full">
<section class="text-gray-400 dark:bg-gray-900 body-font">
<div class="container mx-auto">
<div class="lg:w-2/3 w-full mx-auto overflow-auto">
<table
v-if="state.sponsorings.length > 0"
class="table-auto w-full text-left whitespace-no-wrap"
>
<thead
class="text-black bg-gray-300 dark:text-white text-sm dark:bg-gray-800"
>
<tr>
<th class="px-4 py-3 title-font tracking-wider font-medium">Name</th>
<th
class="px-4 py-3 title-font tracking-wider font-medium"
>{{ $t('amount_per_kilometer_in_eur') }}</th>
<th
class="px-4 py-3 title-font tracking-wider font-medium"
>{{ $t('current_total_amount_in_eur') }}</th>
</tr>
</thead>
<tbody class="text-gray-900 dark:text-gray-50">
<tr v-for="s in state.sponsorings" :key="s.id">
<td class="px-4 py-3">
<span v-text="s.donor.firstname"></span>
<span v-if="s.donor.middlename">
<span v-text="s.donor.middlename"></span>
</span>
<span v-text="s.donor.lastname"></span>
</td>
<td class="px-4 py-3">
<span
v-text="(s.amountPerDistance / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })"
></span>€
</td>
<td class="px-4 py-3">
<span
v-text="(s.amount / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })"
></span>€
</td>
</tr>
</tbody>
<tfoot class="text-gray-900 dark:text-gray-50">
<tr>
<td class="px-4 py-3">{{ $t('total') }}</td>
<td class="px-4 py-3">
<span
v-text="(state.sponsorings.reduce(function(sum, current) {
return sum + current.amountPerDistance;
}, 0) / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })"
></span>€
</td>
<td class="px-4 py-3">
<span
v-text="(state.sponsorings.reduce(function(sum, current) {
return sum + current.amount;
}, 0) / 100)
.toFixed(2)
.toLocaleString('de-DE', { valute: 'EUR' })"
></span>€
</td>
</tr>
</tfoot>
</table>
<div v-else class="text-center font-bold text-black dark:text-white text-2xl">
<img
src="../assets/empty_laps.svg"
style="height:25rem; margin:0 auto;"
:alt="[[$t('no_sponsorings_for_you_were_recorded_yet')]]"
/>
{{ $t('no_sponsorings_for_you_were_recorded_yet') }}
</div>
</div>
</div>
</section>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -256,6 +337,7 @@ const state = reactive({
middlename: "", middlename: "",
lastname: "", lastname: "",
scans: [], scans: [],
sponsorings: [],
group: "", group: "",
activetab: "profile", activetab: "profile",
delete_active: false, delete_active: false,
@@ -274,6 +356,7 @@ axios.get(`${config.baseurl}api/runners/me/${accesstoken}`)
state.middlename = data.middlename; state.middlename = data.middlename;
state.lastname = data.lastname; state.lastname = data.lastname;
state.group = data.group; state.group = data.group;
state.sponsorings = data.distanceDonations;
state.fullobject = data; state.fullobject = data;
}).catch((error) => { }).catch((error) => {
toast.error("An error occured while loading your profile data"); toast.error("An error occured while loading your profile data");
@@ -282,6 +365,7 @@ axios.get(`${config.baseurl}api/runners/me/${accesstoken}/scans`)
.then(({ data }) => { .then(({ data }) => {
data.map(function(s) { data.map(function(s) {
s.lapTime = Math.floor(s.lapTime / 60) + 'min ' + (Math.floor(s.lapTime % 60) + "").padStart(2, "0") + "s" s.lapTime = Math.floor(s.lapTime / 60) + 'min ' + (Math.floor(s.lapTime % 60) + "").padStart(2, "0") + "s"
s.distance = Math.floor(s.distance / 1000) + 'km ' + (Math.floor(s.distance % 1000) + "").padStart(3, "0") + "m"
return s; return s;
}) })
data.filter(s => s.valid === true); data.filter(s => s.valid === true);
@@ -304,7 +388,7 @@ function delete_me() {
function get_certificate() { function get_certificate() {
toast("Generation in progress..."); toast("Generation in progress...");
const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2); const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
let url = `${config.baseurl}documents/certificates?locale=${browserlocale}&download=true&key=${config.documentserver_key}`; let url = `${config.baseurl_documentserver}certificates?locale=${browserlocale}&download=true&key=${config.documentserver_key}`;
let postdata = Object.assign({}, state.fullobject); let postdata = Object.assign({}, state.fullobject);
postdata.group = { postdata.group = {
name: postdata.group name: postdata.group
@@ -332,7 +416,7 @@ function get_certificate() {
}) })
.catch((err) => { .catch((err) => {
console.error(err); console.error(err);
toast.error("An error occured while deleting your profile data"); toast.error("An error occured while generating your certificate");
}); });
} }
</script> </script>

View File

@@ -1,104 +1,104 @@
<template> <template>
<div class="min-h-screen flex items-center justify-center"> <div class="min-h-screen flex items-center justify-center">
<div class="max-w-md w-full py-12 px-6"> <div class="max-w-md w-full py-12 px-6">
<img class="mx-auto h-24 w-auto" src="/favicon.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon.png" alt />
<h1 <h1
class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center" class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center"
>Lauf für Kaya! - {{ $t('profile') }}</h1> >Lauf für Kaya! - {{ $t('profile') }}</h1>
<p class="mx-auto leading-relaxed text-base text-center"> <p class="mx-auto leading-relaxed text-base text-center">
{{ $t('you_have_not_provided_a_valid_access_key') }} {{ $t('you_have_not_provided_a_valid_access_key') }}
<br /> <br />
{{ $t('access_is_only_provided_via_your_email_link') }} {{ $t('access_is_only_provided_via_your_email_link') }}
</p> </p>
<div class="mt-6"> <div class="mt-6">
<div class="relative"> <div class="relative">
<div class="absolute inset-0 flex items-center"> <div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div> <div class="w-full border-t border-gray-300"></div>
</div> </div>
<div class="relative flex justify-center text-sm"> <div class="relative flex justify-center text-sm">
<span <span
class="px-2 bg-white dark:bg-gray-900" class="px-2 bg-white dark:bg-gray-900"
>{{ $t('lost_your_registration_mail') }}</span> >{{ $t('lost_your_registration_mail') }}</span>
</div> </div>
</div> </div>
<div class="mt-4"> <div class="mt-4">
<label for="email_address" class="block font-medium"> <label for="email_address" class="block font-medium">
{{ $t('e_mail_adress') }} {{ $t('e_mail_adress') }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input
v-model="user_email" v-model="user_email"
name="email_address" name="email_address"
id="email_address" id="email_address"
autocomplete="off" autocomplete="off"
:placeholder="[[$t('e_mail_adress')]]" :placeholder="[[$t('e_mail_adress')]]"
type="email" type="email"
:class="{ 'border-red-500': (!isEmail(user_email)), 'border-green-300': (isEmail(user_email)) }" :class="{ 'border-red-500': (!isEmail(user_email)), 'border-green-300': (isEmail(user_email)) }"
class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-2 bg-gray-50 text-gray-500 rounded-md p-2" class="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-2 bg-gray-50 text-gray-500 rounded-md p-2"
/> />
<p <p
v-if="!isEmail(user_email)" v-if="!isEmail(user_email)"
class="text-sm" class="text-sm"
>{{ $t('please_provide_valid_mail') }}</p> >{{ $t('please_provide_valid_mail') }}</p>
</div> </div>
<div class="mt-2"> <div class="mt-2">
<a <a
:disabled="(!state.submit_enabled)" :disabled="(!state.submit_enabled)"
:class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }" :class="{ 'opacity-50': (!state.submit_enabled), 'cursor-not-allowed': (!state.submit_enabled) }"
@click="resendMail" @click="resendMail"
class="block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 dark:bg-gray-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm" class="block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 dark:bg-gray-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
>{{ $t('resend_the_registration_mail') }}</a> >{{ $t('resend_the_registration_mail') }}</a>
</div> </div>
</div> </div>
<div class="mt-12"> <div class="mt-12">
<div class="relative"> <div class="relative">
<div class="absolute inset-0 flex items-center"> <div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div> <div class="w-full border-t border-gray-300"></div>
</div> </div>
<div class="relative flex justify-center text-sm"> <div class="relative flex justify-center text-sm">
<span class="px-2 bg-white dark:bg-gray-900">{{ $t('not_registered_yet') }}</span> <span class="px-2 bg-white dark:bg-gray-900">{{ $t('not_registered_yet') }}</span>
</div> </div>
</div> </div>
<div class="mt-2"> <div class="mt-2">
<a <a
href="./register/" href="../register/"
class="text-white block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 bg-blue-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm" class="text-white block w-full text-center py-2 px-3 border-2 border-gray-300 rounded-md p-1 bg-blue-800 font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
>{{ $t('register_now_small') }}</a> >{{ $t('register_now_small') }}</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { computed, ref, reactive, defineProps } from "vue"; import { computed, ref, reactive, defineProps } 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 { useToast } from "vue-toastification"; import { useToast } from "vue-toastification";
let user_email = ref(""); let user_email = ref("");
// //
const state = reactive({ const state = reactive({
org_name: "", org_name: "",
org_teams: [], org_teams: [],
submit_enabled: computed(() => isEmail(user_email.value)) submit_enabled: computed(() => isEmail(user_email.value))
}) })
const toast = useToast(); const toast = useToast();
function resendMail() { function resendMail() {
if (isEmail(user_email.value)) { if (isEmail(user_email.value)) {
toast("sending password reset mail..."); toast("sending password reset mail...");
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/forgot?mail=${user_email.value}&locale=${browserlocale}`) axios.post(`${config.baseurl}api/runners/forgot?mail=${user_email.value}&locale=${browserlocale}`)
.then(({ data }) => { .then(({ data }) => {
console.log(data); console.log(data);
toast("sent password reset mail to " + user_email.value + "!"); toast("sent password reset mail to " + user_email.value + "!");
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
toast("user does not exist..."); toast("user does not exist...");
}); });
} }
} }
</script> </script>

View File

@@ -1,338 +1,322 @@
<template> <template>
<div class="min-h-screen flex items-center justify-center"> <div class="min-h-screen flex items-center justify-center">
<div class="max-w-md w-full py-12 px-6"> <div class="max-w-md w-full py-12 px-6">
<img class="mx-auto h-24 w-auto" src="/favicon.png" alt /> <img class="mx-auto h-24 w-auto" src="/favicon.png" alt />
<h1 <h1
class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center" class="sm:text-3xl text-2xl font-medium title-font mb-4 text-center"
>Lauf für Kaya! - {{ $t('registrieren') }}</h1> >Lauf für Kaya! - {{ $t('registrieren') }}</h1>
<p class="mx-auto leading-relaxed text-base text-center">{{ $t('register.register_now') }}</p> <p class="mx-auto leading-relaxed text-base text-center">{{ $t('register.register_now') }}</p>
<p <p
v-if="state.org_name !== ''" v-if="state.org_name !== ''"
class="mx-auto leading-relaxed text-base text-center" class="mx-auto leading-relaxed text-base text-center"
>{{ $t('organization') }}: {{ state.org_name }}</p> >{{ $t('organization') }}: {{ state.org_name }}</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:</p> >Team:</p>
<select <select
v-model="org_team" v-model="org_team"
v-if="state.org_name !== '' && state.org_teams.length > 0" 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> </select>
<p <p
v-if="state.org_name === ''" v-if="state.org_name === ''"
class="mx-auto leading-relaxed text-base text-center" class="mx-auto leading-relaxed text-base text-center"
>Bürgerlauf</p> >Bürgerlauf</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" v-model="userdetails.firstname"
name="firstname" name="firstname"
id="first_name" id="first_name"
autocomplete="off" autocomplete="off"
:placeholder="[[$t('vorname')]]" :placeholder="[[$t('vorname')]]"
type="text" type="text"
:class="{ 'border-red-500': (!userdetails.firstname.trim()), 'border-green-300': (userdetails.firstname.trim()) }" :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="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 <input
v-model="userdetails.middlename" v-model="userdetails.middlename"
name="middlename" name="middlename"
id="middle_name" id="middle_name"
autocomplete="off" autocomplete="off"
:placeholder="[[$t('mittelname')]]" :placeholder="[[$t('mittelname')]]"
type="text" 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"> <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" v-model="userdetails.lastname"
name="lastname" name="lastname"
id="last_name" id="last_name"
autocomplete="off" autocomplete="off"
:placeholder="[[$t('nachname')]]" :placeholder="[[$t('nachname')]]"
type="text" type="text"
:class="{ 'border-red-500': (!userdetails.lastname.trim()), 'border-green-300': (userdetails.lastname.trim()) }" :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="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"> <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" v-model="userdetails.mail"
name="email_address" name="email_address"
id="email_address" id="email_address"
autocomplete="off" autocomplete="off"
:placeholder="[[$t('e_mail_adress')]]" :placeholder="[[$t('e_mail_adress')]]"
type="email" type="email"
:class="{ 'border-red-500': (!isEmail(userdetails.mail)), 'border-green-300': (isEmail(userdetails.mail)) }" :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="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 <input
v-model="userdetails.phone" v-model="userdetails.phone"
name="phone" name="phone"
id="phone" id="phone"
autocomplete="off" autocomplete="off"
:placeholder="[[$t('phone_number')]]" :placeholder="[[$t('phone_number')]]"
type="text" type="text"
:class="{ 'border-red-500': (!isMobilePhone(userdetails.phone) && userdetails.phone.trim()), 'border-green-300': (isMobilePhone(userdetails.phone) && userdetails.phone.trim()) }" :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="dark:bg-gray-800 mt-1 block w-full shadow-sm sm:text-sm border-2 bg-gray-50 text-gray-500 rounded-md p-2"
/> />
<p <p
v-if="(!isMobilePhone(userdetails.phone) && userdetails.phone.trim())" v-if="(!isMobilePhone(userdetails.phone) && userdetails.phone.trim())"
class="text-sm" 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="grid grid-cols-6 mt-6">
<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" v-model="provide_address"
id="address_activated" id="address_activated"
name="address_activated" name="address_activated"
type="checkbox" type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" 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" for="address_activated"
class="font-medium text-gray-400 select-none" class="font-medium text-gray-400 select-none"
>{{ $t('provide_address') }}</label> >{{ $t('provide_address') }}</label>
</div> </div>
</div> </div>
<div v-if="provide_address === true" class="col-span-6"> <div v-if="provide_address === true" class="col-span-6">
<div class="col-span-6"> <div class="col-span-6">
<label for="street" class="block font-medium"> <label for="street" class="block font-medium">
{{ $t('strasse') }} {{ $t('strasse') }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
<input <input
v-model="userdetails.address.street" v-model="userdetails.address.street"
type="text" type="text"
name="street" name="street"
:placeholder="[[$t('strasse')]]" :placeholder="[[$t('strasse')]]"
id="street" id="street"
autocomplete="street-address" autocomplete="street-address"
:class="{ 'border-red-500': (!userdetails.address.street.trim()), 'border-green-300': (userdetails.address.street.trim()) }" :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="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>
<div class="col-span-6"> <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 <input
v-model="userdetails.address.address2" v-model="userdetails.address.address2"
type="text" type="text"
name="address2" name="address2"
:placeholder="[[$t('apartment_suite_etc')]]" :placeholder="[[$t('apartment_suite_etc')]]"
id="address2" id="address2"
autocomplete="street-address" 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>
<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" v-model="userdetails.address.city"
type="text" type="text"
name="city" name="city"
:placeholder="[[$t('ort')]]" :placeholder="[[$t('ort')]]"
id="city" id="city"
:class="{ 'border-red-500': (!userdetails.address.city.trim()), 'border-green-300': (userdetails.address.city.trim()) }" :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="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>
<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" v-model="userdetails.address.zipcode"
type="text" type="text"
name="postal_code" name="postal_code"
:placeholder="[[$t('plz')]]" :placeholder="[[$t('plz')]]"
id="postal_code" id="postal_code"
autocomplete="postal-code" autocomplete="postal-code"
:class="{ 'border-red-500': (!isPostalCode(userdetails.address.zipcode, 'DE')), 'border-green-300': (isPostalCode(userdetails.address.zipcode, 'DE')) }" :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="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>
<p <p
v-if="!isPostalCode(userdetails.address.zipcode, 'DE')" v-if="!isPostalCode(userdetails.address.zipcode, 'DE')"
class="text-sm" class="text-sm"
>{{ $t('please_provide_a_valid_zipcode') }}</p> >{{ $t('please_provide_a_valid_zipcode') }}</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" v-model="agb_accepted"
id="agb_accepted" id="agb_accepted"
name="agb_accepted" name="agb_accepted"
type="checkbox" type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" 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 for="agb_accepted" class="font-medium text-gray-400 select-none"> <label for="agb_accepted" class="font-medium text-gray-400 select-none">
{{ $t('i_accept', { tos: $t('tos') }) }} {{ $t('i_accept', { tos: $t('tos') }) }}
<a <a
target="_blank" target="_blank"
rel="noreferrer,noopener" rel="noreferrer,noopener"
href href
class="underline" class="underline"
>{{ $t('tos') }}</a> >{{ $t('tos') }}</a>
{{ $t('i_accept_end') }} {{ $t('i_accept_end') }}
<span class="font-bold">*</span> <span class="font-bold">*</span>
</label> </label>
</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="data_confirmed" v-model="data_confirmed"
id="data_confirmed" id="data_confirmed"
name="data_confirmed" name="data_confirmed"
type="checkbox" type="checkbox"
class="h-4 w-4 text-indigo-600 border-gray-300 rounded" 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 for="data_confirmed" class="font-medium text-gray-400 select-none"> <label 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" @click="login"
: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) }"
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('registrieren') }}</button> >{{ $t('registrieren') }}</button>
</div> </div>
</div> </div>
<div class="mt-6"> </div>
<div class="relative"> </div>
<div class="absolute inset-0 flex items-center"> </template>
<div class="w-full border-t border-gray-300"></div>
</div> <script setup>
<div class="relative flex justify-center text-sm"> import { computed, ref, reactive, defineProps } from "vue";
<span class="px-2 bg-white dark:bg-gray-900">{{ $t('already_have_an_account') }}</span> import axios from "redaxios";
</div> import isEmail from 'validator/es/lib/isEmail';
</div> import isMobilePhone from 'validator/es/lib/isMobilePhone';
<div class="mt-6"> import isPostalCode from 'validator/es/lib/isPostalCode';
<a import { useToast } from "vue-toastification";
href="./login"
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" const props = defineProps({
>{{ $t('go_to_login') }}</a> token: String
</div> })
</div> if (props.token) {
</div> axios.get(`${config.baseurl}api/organizations/selfservice/${props.token}`)
</div> .then(({ data }) => {
</template> state.org_name = data.name;
state.org_teams = data.teams;
<script setup> org_team.value = data.teams[0]?.id;
import { computed, ref, reactive, defineProps } from "vue"; })
import axios from "redaxios"; .catch((error) => {
import isEmail from 'validator/es/lib/isEmail'; console.log(error);
import isMobilePhone from 'validator/es/lib/isMobilePhone'; });
import isPostalCode from 'validator/es/lib/isPostalCode'; }
import { useToast } from "vue-toastification";
let userdetails = ref({ firstname: "", lastname: "", middlename: "", mail: "", phone: "", address: { street: "", address2: "", city: "", zipcode: "" } });
const props = defineProps({ let provide_address = ref(false);
token: String let agb_accepted = ref(false);
}) let data_confirmed = ref(false);
if (props.token) { let org_team = ref("");
axios.get(`${config.baseurl}api/organizations/selfservice/${props.token}`) //
.then(({ data }) => { const state = reactive({
state.org_name = data.name; org_name: "",
state.org_teams = data.teams; org_teams: [],
org_team.value = data.teams[0]?.id; 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
.catch((error) => { && 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"))))
console.log(error); })
}); const toast = useToast();
} function login() {
userdetails = userdetails.value;
let userdetails = ref({ firstname: "", lastname: "", middlename: "", mail: "", phone: "", address: { street: "", address2: "", city: "", zipcode: "" } }); if (userdetails.phone === "" || isMobilePhone(userdetails.phone)) {
let provide_address = ref(false); if (isEmail(userdetails.mail)) {
let agb_accepted = ref(false); let postdata = {
let data_confirmed = ref(false); "email": userdetails.mail,
let org_team = ref(""); "firstname": userdetails.firstname,
// "middlename": userdetails.middlename,
const state = reactive({ "lastname": userdetails.lastname,
org_name: "", "address": {}
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) if (isMobilePhone(userdetails.phone)) {
&& userdetails.value.firstname postdata.phone = userdetails.phone;
&& 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")))) }
}) if (provide_address.value === true) {
const toast = useToast(); postdata.address = {
function login() { address1: userdetails.address.street,
userdetails = userdetails.value; address2: userdetails.address.address2 || "",
if (userdetails.phone === "" || isMobilePhone(userdetails.phone)) { city: userdetails.address.city,
if (isEmail(userdetails.mail)) { postalcode: userdetails.address.zipcode,
let postdata = { country: "DE",
"email": userdetails.mail, }
"firstname": userdetails.firstname, }
"middlename": userdetails.middlename, if (state.org_name !== '' && state.org_teams.length > 0) {
"lastname": userdetails.lastname, postdata.team = org_team.value;
"address": {} }
} toast("registration in progress...");
if (isMobilePhone(userdetails.phone)) { const browserlocale = ((navigator.languages && navigator.languages[0]) || '').substr(0, 2);
postdata.phone = userdetails.phone; let url = `${config.baseurl}api/runners/register/?locale=${browserlocale}`;
} if (props.token) {
if (provide_address.value === true) { url = `${config.baseurl}api/runners/register/${props.token}/?locale=${browserlocale}`
postdata.address = { }
address1: userdetails.address.street, axios.post(url, postdata)
address2: userdetails.address.address2 || "", .then(({ data }) => {
city: userdetails.address.city, const token = btoa(data.token);
postalcode: userdetails.address.zipcode, // alert(token);
country: "DE", location.replace(`${config.baseurl_selfservice}profile/${token}`);
} })
} .catch((error) => {
if (state.org_name !== '' && state.org_teams.length > 0) { console.log(error);
postdata.team = org_team.value; });
} }
toast("registration in progress..."); }
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}`
}
axios.post(url, postdata)
.then(({ data }) => {
const token = btoa(data.token);
// alert(token);
location.replace(`${config.baseurl_selfservice}profile/${token}`);
})
.catch((error) => {
console.log(error);
});
}
}
}
</script> </script>