Compare commits

..

4 Commits
1.4.1 ... 1.4.2

Author SHA1 Message Date
68c2c681f2
chore(release): 1.4.2
All checks were successful
Build release images / build-container (push) Successful in 48s
2025-05-26 19:01:03 +02:00
480fe3e0e5
fix(profile): Format total distance 2025-05-26 18:58:43 +02:00
59cb42c336
feat(Profile/sponsoring): show note for on-day cash donations 2025-05-21 20:23:35 +02:00
2d761ccd6d
refactor(Profile): drop sponsor selfservice create from this branch 2025-05-21 20:19:05 +02:00
5 changed files with 290 additions and 359 deletions

View File

@ -2,8 +2,17 @@
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.4.2](https://git.odit.services/lfk/selfservice/compare/1.4.1...1.4.2)
- refactor(Profile): drop sponsor selfservice create from this branch [`2d761cc`](https://git.odit.services/lfk/selfservice/commit/2d761ccd6da7d9515fc0c2b65dc2ca0cff61e3bd)
- feat(Profile/sponsoring): show note for on-day cash donations [`59cb42c`](https://git.odit.services/lfk/selfservice/commit/59cb42c3364777f7b8aed1e90f48f5da015db118)
- fix(profile): Format total distance [`480fe3e`](https://git.odit.services/lfk/selfservice/commit/480fe3e0e568939507e5cc21c48e98634614d4e6)
#### [1.4.1](https://git.odit.services/lfk/selfservice/compare/1.4.0...1.4.1) #### [1.4.1](https://git.odit.services/lfk/selfservice/compare/1.4.0...1.4.1)
> 25 April 2025
- chore(release): 1.4.1 [`128c6ab`](https://git.odit.services/lfk/selfservice/commit/128c6abd737654087100cfca8e72af9b14dd770c)
- fix(laptimes): Filter out invalid scans [`094e731`](https://git.odit.services/lfk/selfservice/commit/094e7319476bc571949a70b6f4c27539616f3634) - fix(laptimes): Filter out invalid scans [`094e731`](https://git.odit.services/lfk/selfservice/commit/094e7319476bc571949a70b6f4c27539616f3634)
- fix(certificate): Provide selfservice url on certificate [`8d6f290`](https://git.odit.services/lfk/selfservice/commit/8d6f290fd5bad54094ba1228fa6d854ad77a561d) - fix(certificate): Provide selfservice url on certificate [`8d6f290`](https://git.odit.services/lfk/selfservice/commit/8d6f290fd5bad54094ba1228fa6d854ad77a561d)

View File

@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-selfservice", "name": "@odit/lfk-selfservice",
"version": "1.4.1", "version": "1.4.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@ -13,6 +13,7 @@
"current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)", "current_total_amount_in_eur": "Aktueller Gesamtbetrag (in €)",
"delete_my_data": "Meine Daten löschen", "delete_my_data": "Meine Daten löschen",
"distance": "Distanz", "distance": "Distanz",
"donation_on_event_day": "Am Lauftag kann Bargeld in unsere Spendenbox gespendet werden 💶",
"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",
@ -66,6 +67,7 @@
"registrierungscode_generiert": "Registrierungscode generiert!", "registrierungscode_generiert": "Registrierungscode generiert!",
"registrierungscode_wird_generiert": "Registrierungscode wird generiert...", "registrierungscode_wird_generiert": "Registrierungscode wird generiert...",
"resend_the_registration_mail": "Login-Link anfordern", "resend_the_registration_mail": "Login-Link anfordern",
"spenden_info": "Spenden-Info",
"sponsor_add_agree": "Mit dem Absenden bestätige ich, dass der Sponsor mit der Übermittlung seiner Daten einverstanden ist und ich dessen Berechtigung habe", "sponsor_add_agree": "Mit dem Absenden bestätige ich, dass der Sponsor mit der Übermittlung seiner Daten einverstanden ist und ich dessen Berechtigung habe",
"sponsoring": "Sponsoring", "sponsoring": "Sponsoring",
"sponsoring_pro_kilometer_in_eur": "Sponsoring pro Kilometer (in €)", "sponsoring_pro_kilometer_in_eur": "Sponsoring pro Kilometer (in €)",

View File

@ -13,6 +13,7 @@
"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",
"distance": "Distance", "distance": "Distance",
"donation_on_event_day": "On race day, cash can be donated to our donation box 💶",
"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",
@ -66,6 +67,7 @@
"registrierungscode_generiert": "created registration code!", "registrierungscode_generiert": "created registration code!",
"registrierungscode_wird_generiert": "creating 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",
"spenden_info": "info for donations",
"sponsor_add_agree": "By submitting, I confirm that the sponsor agrees to the transmission of his data and that I have his authorization", "sponsor_add_agree": "By submitting, I confirm that the sponsor agrees to the transmission of his data and that I have his authorization",
"sponsoring": "Sponsoring", "sponsoring": "Sponsoring",
"sponsoring_pro_kilometer_in_eur": "Sponsoring per Kilometer (in €)", "sponsoring_pro_kilometer_in_eur": "Sponsoring per Kilometer (in €)",

View File

@ -1,140 +1,122 @@
<template> <template>
<div class="w-full p-4 lg:px-48 xl:w-2/3 xl:mx-auto"> <div class="w-full p-4 lg:px-48 xl:w-2/3 xl:mx-auto">
<div class="md:pr-10 md:mb-0 mb-6 pr-0 w-full text-center text-black dark:text-gray-200"> <div class="md:pr-10 md:mb-0 mb-6 pr-0 w-full text-center text-black dark:text-gray-200">
<img src="/favicon-lfk.png" class="h-20 mx-auto" /> <img src="/favicon-lfk.png" class="h-20 mx-auto" />
<div v-if="loadstate === 'loaded'"> <div v-if="loadstate === 'loaded'">
<h1 class="text-3xl font-bold whitespace-nowrap" v-text="(state.firstname || '') + <h1 class="text-3xl font-bold whitespace-nowrap" v-text="(state.firstname || '') +
' ' + ' ' +
(state.middlename || '') + (state.middlename || '') +
' ' + ' ' +
(state.lastname || '') (state.lastname || '')
"></h1> "></h1>
<p v-if="state.group==='Citizen'" class="text-md whitespace-nowrap">Bürgerlauf<br>Start: 14:00 Uhr</p> <p v-if="state.group === 'Citizen'" class="text-md whitespace-nowrap">Bürgerlauf<br>Start: 14:00 Uhr</p>
<p v-else class="text-md whitespace-nowrap">Team: {{ state.group }}</p> <p v-else class="text-md whitespace-nowrap">Team: {{ state.group }}</p>
</div>
<h1 v-else class="text-3xl font-bold whitespace-nowrap">Daten werden geladen...</h1>
</div> </div>
<div v-if="loadstate === 'loaded'" class="flex flex-wrap"> <h1 v-else class="text-3xl font-bold whitespace-nowrap">Daten werden geladen...</h1>
<div class="w-full"> </div>
<div class=""> <div v-if="loadstate === 'loaded'" class="flex flex-wrap">
<div class="grid grid-cols-3 text-center gap-1"> <div class="w-full">
<button @click="() => { <div class="">
state.activetab = 'profile'; <div class="grid grid-cols-3 text-center gap-1">
} <button @click="() => {
" :class="{ state.activetab = 'profile';
'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white': }
state.activetab === 'profile', " :class="{
'bg-neutral-200': 'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white':
state.activetab !== 'profile', state.activetab === 'profile',
}" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button"> 'bg-neutral-200':
{{ $t("profile") }} state.activetab !== 'profile',
</button> }" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button">
<button @click="() => { {{ $t("profile") }}
state.activetab = 'laptimes'; </button>
} <button @click="() => {
" :class="{ state.activetab = 'laptimes';
'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white': }
state.activetab === 'laptimes', " :class="{
'bg-neutral-200': 'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white':
state.activetab !== 'laptimes', state.activetab === 'laptimes',
}" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button"> 'bg-neutral-200':
{{ $t("lap_times") }} state.activetab !== 'laptimes',
</button> }" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button">
<button @click="() => { {{ $t("lap_times") }}
state.activetab = 'sponsorings'; </button>
} <button @click="() => {
" :class="{ state.activetab = 'sponsorings';
'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white': }
state.activetab === 'sponsorings', " :class="{
'bg-neutral-200': 'tab-active font-medium bg-blue-600 hover:bg-blue-700 text-white':
state.activetab !== 'sponsorings', state.activetab === 'sponsorings',
}" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button"> 'bg-neutral-200':
{{ $t("sponsoring") }} state.activetab !== 'sponsorings',
</button> }" class="cursor-pointer rounded-md p-2 py-3 md:py-4 md:px-6 block" type="button">
</div> {{ $t("sponsoring") }}
<div v-if="state.activetab === 'profile'" class="tab-content block"> </button>
<div class="w-full mx-auto"> </div>
<div class="flex flex-col"> <div v-if="state.activetab === 'profile'" class="tab-content block">
<div class="flex flex-wrap w-full"> <div class="w-full mx-auto">
<div class="w-full"> <div class="flex flex-col">
<div v-if="state.delete_active === false"> <div class="flex flex-wrap w-full">
<button type="button" <div class="w-full">
class="mt-2 focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-blue-600 hover:bg-blue-700 hover:shadow-lg w-full md:w-auto cursor-pointer mb-1 md:mr-1" <div v-if="state.delete_active === false">
@click="get_certificate"> <button type="button"
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" class="mt-2 focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-blue-600 hover:bg-blue-700 hover:shadow-lg w-full md:w-auto cursor-pointer mb-1 md:mr-1"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" @click="get_certificate">
class="inline-block"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
<polyline points="7 10 12 15 17 10" /> class="inline-block">
<line x1="12" x2="12" y1="15" y2="3" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
</svg> <polyline points="7 10 12 15 17 10" />
{{ $t("download_certificate") }} <line x1="12" x2="12" y1="15" y2="3" />
</button> </svg>
{{ $t("download_certificate") }}
</button>
</div> </div>
<div> <div>
<div class="text-lg">{{ $t("registrationcode") }}</div> <div class="text-lg">{{ $t("registrationcode") }}</div>
<img class="w-full md:w-auto mb-2 bg-white p-2" alt="Registrierungscode" :src="state.barcode" /> <img class="w-full md:w-auto mb-2 bg-white p-2" alt="Registrierungscode" :src="state.barcode" />
<button type="button" <button type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-blue-600 hover:bg-blue-700 hover:shadow-lg w-full md:w-auto cursor-pointer mb-1 md:mr-1" class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-blue-600 hover:bg-blue-700 hover:shadow-lg w-full md:w-auto cursor-pointer mb-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" <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" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline-block"> class="inline-block">
<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" x2="12" y1="15" y2="3" /> <line x1="12" x2="12" y1="15" y2="3" />
</svg> </svg>
{{ $t("download_registrationcode") }} {{ $t("download_registrationcode") }}
</button> </button>
</div> </div>
<div class="mb-2"> <div class="mb-2">
<div class="text-lg">{{ $t("e_mail_adress") }}</div> <div class="text-lg">{{ $t("e_mail_adress") }}</div>
<p v-text="state.email || '---'" /> <p v-text="state.email || '---'" />
</div> </div>
<div class="mb-2"> <div class="mb-2">
<div class="text-lg">{{ $t("phone_number") }}</div> <div class="text-lg">{{ $t("phone_number") }}</div>
<p v-text="state.phone || '---'" /> <p v-text="state.phone || '---'" />
</div>
</div> </div>
</div> </div>
</div> </div>
<div v-if="state.delete_active === true"> </div>
<button type="button" <div v-if="state.delete_active === true">
class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md mb-1 md:mb-auto w-full md:w-auto cursor-pointer bg-blue-600 hover:bg-blue-700 hover:shadow-lg" <button type="button"
@click="() => { class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md mb-1 md:mb-auto w-full md:w-auto cursor-pointer bg-blue-600 hover:bg-blue-700 hover:shadow-lg"
state.delete_active = false;
}
">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline-block">
<circle cx="12" cy="12" r="10" />
<path d="m4.9 4.9 14.2 14.2" />
</svg>
{{ $t("cancel_keep_my_data") }}
</button>
<button type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md w-full md:w-auto cursor-pointer bg-red-600 hover:bg-red-700 hover:shadow-lg md:ml-1"
@click="delete_me">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline-block">
<path d="M3 6h18" />
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
<line x1="10" x2="10" y1="11" y2="17" />
<line x1="14" x2="14" y1="11" y2="17" />
</svg>
{{ $t("confirm_delete_all_of_my_data") }}
</button>
</div>
<button v-else type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-red-600 hover:bg-red-700 hover:shadow-lg w-full md:w-auto cursor-pointer"
@click="() => { @click="() => {
state.delete_active = true; state.delete_active = false;
} }
"> ">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline-block">
<circle cx="12" cy="12" r="10" />
<path d="m4.9 4.9 14.2 14.2" />
</svg>
{{ $t("cancel_keep_my_data") }}
</button>
<button type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md w-full md:w-auto cursor-pointer bg-red-600 hover:bg-red-700 hover:shadow-lg md:ml-1"
@click="delete_me">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" <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" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline-block"> class="inline-block">
@ -144,281 +126,246 @@
<line x1="10" x2="10" y1="11" y2="17" /> <line x1="10" x2="10" y1="11" y2="17" />
<line x1="14" x2="14" y1="11" y2="17" /> <line x1="14" x2="14" y1="11" y2="17" />
</svg> </svg>
{{ $t("delete_my_data") }} {{ $t("confirm_delete_all_of_my_data") }}
</button> </button>
</div> </div>
<button v-else type="button"
class="focus:border-black focus:ring-2 focus:ring-black text-white text-base font-medium md:text-sm py-3.5 px-5 md:py-2.5 md:px-5 rounded-md bg-red-600 hover:bg-red-700 hover:shadow-lg w-full md:w-auto cursor-pointer"
@click="() => {
state.delete_active = true;
}
">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="inline-block">
<path d="M3 6h18" />
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
<line x1="10" x2="10" y1="11" y2="17" />
<line x1="14" x2="14" y1="11" y2="17" />
</svg>
{{ $t("delete_my_data") }}
</button>
</div> </div>
</div> </div>
<div v-if="state.activetab === 'laptimes'" class="tab-content block"> </div>
<div class="py-4 w-full"> <div v-if="state.activetab === 'laptimes'" class="tab-content block">
<section class="dark:bg-gray-900 body-font"> <div class="py-4 w-full">
<div class="mx-auto"> <section class="dark:bg-gray-900 body-font">
<div class="w-full mx-auto"> <div class="mx-auto">
<div v-if="state.scans.length > 0"> <div class="w-full mx-auto">
<p class="mb-2"> <div v-if="state.scans.length > 0">
{{ $t('total_distance') }}: {{ getReadableDistanceForUI() }} <p class="mb-2">
</p> {{ $t('total_distance') }}: {{ getTotalReadableDistance() }}
</p>
<table class="table-auto w-full text-left whitespace-no-wrap"> <table class="table-auto w-full text-left whitespace-no-wrap">
<thead class=" <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 class=" <th 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 class=" <th 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>
</thead> </thead>
<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_readable"></span> <span v-text="s.distance_readable"></span>
</td> </td>
<td class="px-4 py-3" v-text="s.lapTime_readable"></td> <td class="px-4 py-3" v-text="s.lapTime_readable"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div v-else class=" <div v-else class="
text-center text-center
font-medium font-medium
text-black text-black
dark:text-white dark:text-white
text-xl text-xl
"> ">
<img src="../assets/empty_laps.svg" class="mx-auto h-56" <img src="../assets/empty_laps.svg" class="mx-auto h-56"
:alt="[[$t('no_laps_scans_were_recorded_yet')]]" /> :alt="[[$t('no_laps_scans_were_recorded_yet')]]" />
{{ $t("no_laps_scans_were_recorded_yet") }} {{ $t("no_laps_scans_were_recorded_yet") }}
</div>
</div> </div>
</div> </div>
</section>
</div>
</div>
<div v-if="state.activetab === 'sponsorings'" class="tab-content block">
<div v-if="mode === 'add_sponsoring'">
<h1 class="text-3xl">{{ $t('add_sponsoring') }}</h1>
<form>
<div class="mt-6 grid gap-4 lg:gap-6">
<!-- Grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 lg:gap-6">
<div>
<label for="sponsorvorname"
class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{
$t('vorname_des_sponsors') }}</label>
<input v-bind="newsponsor_vorname" type="text" name="sponsorvorname" id="sponsorvorname"
placeholder="Vorname des Sponsors"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
<div>
<label for="sponsornachname"
class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{
$t('nachname_des_sponsors') }}</label>
<input v-bind="newsponsor_nachname" type="text" name="sponsornachname" id="sponsornachname"
placeholder="Nachname des Sponsors"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 lg:gap-6">
<!-- End Grid -->
<div>
<label for="sponsortel" class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{
$t('telefonnummer_des_sponsors') }}</label>
<input v-bind="newsponsor_tel" type="tel" name="sponsortel" id="sponsortel" autocomplete="tel"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
<div>
<label for="sponsormail" class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{
$t('e_mail_des_sponsors') }}</label>
<input v-bind="newsponsor_mail" type="email" name="sponsormail" id="sponsormail"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
</div>
<div>
<label for="eurokilometer" class="block mb-2 text-sm text-gray-700 font-medium dark:text-white">{{
$t('sponsoring_pro_kilometer_in_eur') }}</label>
<input v-bind="newsponsor_value" type="number" name="eurokilometer" id="eurokilometer"
placeholder="z.B. 1€ ODER 0,50€"
class="py-2.5 sm:py-3 px-4 block w-full border-gray-200 rounded-lg border sm:text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600">
</div>
</div>
</form>
<!-- End Grid -->
<!-- Checkbox -->
<div class="mt-3 flex">
<div class="flex">
<input v-model="newsponsor_check" id="sponsor_agree" name="sponsor_agree" type="checkbox"
class="shrink-0 mt-1.5 border-gray-200 rounded-sm text-blue-600 focus:ring-blue-500 dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800">
</div>
<div class="ms-3">
<label for="sponsor_agree" class="text-sm text-gray-600 dark:text-neutral-400">{{
$t('sponsor_add_agree') }}</label>
</div>
</div> </div>
<!-- End Checkbox --> </section>
</div>
<button :disabled="!newsponsor_check" @click="addSponsoring" type="button" </div>
class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-teal-100 text-teal-800 hover:bg-teal-200 focus:outline-hidden focus:bg-teal-200 disabled:opacity-50 disabled:pointer-events-none dark:text-teal-500 dark:bg-teal-800/30 dark:hover:bg-teal-800/20 dark:focus:bg-teal-800/20 mt-2 cursor-pointer"> <div v-if="state.activetab === 'sponsorings'" class="tab-content block">
{{ $t('add_sponsoring') }} <div
</button> class="bg-white border border-gray-200 rounded-lg shadow-lg p-4 dark:bg-neutral-800 dark:border-neutral-700 mt-2 font-medium"
role="alert" tabindex="-1" aria-labelledby="hs-discovery-label">
<div class="flex">
<div class="shrink-0">
<svg class="shrink-0 size-4 text-blue-600 mt-1" 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">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 16v-4"></path>
<path d="M12 8h.01"></path>
</svg>
</div>
<div class="ms-3">
<h3 id="hs-discovery-label" class="text-gray-800 font-semibold dark:text-white">
{{ $t('spenden_info') }}
</h3>
<p class="mt-2 text-sm text-gray-700 dark:text-neutral-400">
{{ $t('donation_on_event_day') }}
</p>
</div>
</div> </div>
<div v-else> </div>
<div class="py-4 w-full"> <div class="py-4 w-full">
<section class="dark:bg-gray-900 body-font"> <section class="dark:bg-gray-900 body-font">
<div class="mx-auto"> <div class="mx-auto">
<div class="w-full mx-auto"> <div class="w-full mx-auto">
<table v-if="state.sponsorings.length > 0" class="table-auto w-full text-left whitespace-no-wrap"> <table v-if="state.sponsorings.length > 0" class="table-auto w-full text-left whitespace-no-wrap">
<thead class=" <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 class=" <th 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 class=" <th 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 class=" <th 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>
</thead> </thead>
<tbody class="text-gray-900 dark:text-gray-50"> <tbody class="text-gray-900 dark:text-gray-50">
<tr class="odd:bg-white even:bg-gray-100 dark:odd:bg-neutral-900 dark:even:bg-neutral-800" <tr class="odd:bg-white even:bg-gray-100 dark:odd:bg-neutral-900 dark:even:bg-neutral-800"
v-for="s in state.sponsorings" :key="s.id"> v-for="s in state.sponsorings" :key="s.id">
<td class="px-4 py-3"> <td class="px-4 py-3">
<span v-text="s.donor.firstname + ' '"></span> <span v-text="s.donor.firstname + ' '"></span>
<span v-if="s.donor.middlename"> <span v-if="s.donor.middlename">
<span v-text="s.donor.middlename"></span> <span v-text="s.donor.middlename"></span>
</span> </span>
<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 v-text="(s.amountPerDistance / 100) <span 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 v-text="(s.amount / 100) <span 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>
<tfoot class="text-black <tfoot class="text-black
bg-gray-300 bg-gray-300
border-t-2 border-t-2
border-t-current border-t-current
dark:text-white dark:text-white
text-sm text-sm
dark:bg-gray-800"> dark:bg-gray-800">
<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 v-text="( <span v-text="(
state.sponsorings.reduce(function ( state.sponsorings.reduce(function (
sum, sum,
current current
) { ) {
return sum + current.amountPerDistance; return sum + current.amountPerDistance;
}, },
0) / 100 0) / 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 v-text="( <span v-text="(
state.sponsorings.reduce(function ( state.sponsorings.reduce(function (
sum, sum,
current current
) { ) {
return sum + current.amount; return sum + current.amount;
}, },
0) / 100 0) / 100
) )
.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 v-else class=" <div v-else class="
text-center text-center
font-medium font-medium
text-black text-black
dark:text-white dark:text-white
text-xl text-xl
"> ">
<img src="../assets/empty_laps.svg" class="h-56 mx-auto" :alt="[ <img src="../assets/empty_laps.svg" class="h-56 mx-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>
<!-- <button
class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-teal-100 text-teal-800 hover:bg-teal-200 focus:outline-hidden focus:bg-teal-200 disabled:opacity-50 disabled:pointer-events-none dark:text-teal-500 dark:bg-teal-800/30 dark:hover:bg-teal-800/20 dark:focus:bg-teal-800/20 mt-2"
@click="mode = 'add_sponsoring'">{{ $t('add_sponsoring') }}</button> -->
</div>
</div> </div>
</section> </div>
</div> </div>
</div> </section>
</div> </div>
</div> </div>
</div> </div>
<!-- --> </div>
<Footer />
</div> </div>
<!-- -->
<Footer />
</template> </template>
<script setup> <script setup>
@ -431,22 +378,6 @@ import { useI18n } from 'vue-i18n';
import { TYPE, useToast } from "vue-toastification"; import { TYPE, useToast } from "vue-toastification";
const { t } = useI18n() const { t } = useI18n()
const loadstate = ref("loading") const loadstate = ref("loading")
const mode = ref("")
//
const newsponsor_check = ref(false)
const newsponsor_value = ref("")
const newsponsor_mail = ref("")
const newsponsor_tel = ref("")
const newsponsor_vorname = ref("")
const newsponsor_nachname = ref("")
function shareSponsorLink() {
navigator.share({
title: state.firstname,
text: "Am 23.05.2025 findet der Lauf für Kaya! statt 🏃‍♂️🏃‍♀️\nWerde mein Sponsor beim Lauf für Kaya! 2025 und unterstütze mich pro gelaufenem Kilometer: https://lauf-fuer-kaya.de",
// url: "https://lauf-fuer-kaya.de",
})
}
function textToBase64Barcode(text) { function textToBase64Barcode(text) {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
@ -489,8 +420,8 @@ const props = defineProps({
}); });
const accesstoken = props.token; const accesstoken = props.token;
function getReadableDistanceForUI() { function getTotalReadableDistance() {
return state.scans.reduce((accumulator, currentValue) => accumulator + currentValue.distance, 0) return getReadableDistance(state.scans.reduce((accumulator, currentValue) => accumulator + currentValue.distance, 0));
} }
function getReadableDistance(distance) { function getReadableDistance(distance) {
@ -542,19 +473,6 @@ runnerSelfServiceControllerGetScans({ path: { jwt: accesstoken } }).then(({ data
.catch((error) => { .catch((error) => {
toast.error(t('profil_konnte_nicht_geladen_werden')); toast.error(t('profil_konnte_nicht_geladen_werden'));
}); });
function addSponsoring() {
const postdata = {
"receiptNeeded": false,
"firstname": newsponsor_vorname.value,
"middlename": "",
"lastname": newsponsor_nachname.value,
"phone": newsponsor_tel.value,
"email": newsponsor_mail.value,
"address": {}
}
console.log(postdata);
// TODO: implement: donationControllerPostDistance({body:{}})
}
function delete_me() { function delete_me() {
toast.clear(); toast.clear();
toast(t('profil_wird_geloescht')); toast(t('profil_wird_geloescht'));