Compare commits

...

8 Commits

Author SHA1 Message Date
8c56aa3c46
Merge branch 'dev' into feature/anonyme-spende 2025-04-28 10:57:14 +02:00
f642849dbb
wip 2025-04-28 10:56:45 +02:00
7ac92ae6ca
wip 2025-04-28 10:45:47 +02:00
95af9f9914
i18n 2025-04-28 10:44:02 +02:00
1004aee16c
implement DonationDonor 2025-04-28 10:40:23 +02:00
0baf2fc460
wip 2025-04-28 10:38:27 +02:00
09b59175ee
wip 2025-04-28 10:35:45 +02:00
a21f61f3f3
wip 2025-04-28 10:24:07 +02:00
5 changed files with 405 additions and 344 deletions

View File

@ -21,7 +21,7 @@
$: runner = 0; $: runner = 0;
$: donors = []; $: donors = [];
$: runners = []; $: runners = [];
$: is_fixed = false; $: type = "distance";
$: is_paid = false; $: is_paid = false;
$: amount_input = 0; $: amount_input = 0;
$: processed_last_submit = true; $: processed_last_submit = true;
@ -46,7 +46,7 @@
let amount_cent = Math.floor(amount_input * 100); let amount_cent = Math.floor(amount_input * 100);
processed_last_submit = false; processed_last_submit = false;
toast.loading($_("adding-donation")); toast.loading($_("adding-donation"));
if (is_fixed) { if (type === "fixed") {
let postdata = { let postdata = {
donor, donor,
amount: amount_cent, amount: amount_cent,
@ -72,7 +72,30 @@
.finally(() => { .finally(() => {
processed_last_submit = true; processed_last_submit = true;
}); });
} else { } else if (type === "anonymous") {
let postdata = {
amount: amount_cent,
paidAmount: 0,
};
if (is_paid) {
postdata.paidAmount = amount_cent;
}
DonationService.donationControllerPostFixed(postdata)
.then((result) => {
amount_input = 0;
modal_open = false;
//
toast.dismiss();
toast.success($_("donation_added"));
dispatch("created", { donations: [result] });
})
.catch((err) => {
//
})
.finally(() => {
processed_last_submit = true;
});
} else if (type === "distance") {
let postdata = { let postdata = {
donor, donor,
runner, runner,
@ -100,16 +123,12 @@
} }
onMount(async () => { onMount(async () => {
donors = (await DonorService.donorControllerGetAll()).map( donors = (await DonorService.donorControllerGetAll()).map((r) => {
(r) => {
return { label: getDonorLabel(r), value: r }; return { label: getDonorLabel(r), value: r };
} });
); runners = (await RunnerService.runnerControllerGetAll()).map((r) => {
runners = (await RunnerService.runnerControllerGetAll()).map(
(r) => {
return { label: getDonorLabel(r), value: r }; return { label: getDonorLabel(r), value: r };
} });
);
}); });
</script> </script>
@ -126,7 +145,7 @@
> >
<div class="fixed inset-0 transition-opacity" aria-hidden="true"> <div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div <div
class="absolute inset-0 bg-gray-500 opacity-75" class="absolute inset-0 bg-neutral-500 opacity-75"
data-id="modal_backdrop" data-id="modal_backdrop"
/> />
</div> </div>
@ -146,7 +165,7 @@
class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10" class="flex-shrink-0 flex items-center justify-center size-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
> >
<svg <svg
class="h-6 w-6 text-blue-600" class="size-6 text-blue-600"
fill="currentColor" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@ -159,40 +178,97 @@
> >
</div> </div>
<div class="mt-3"> <div class="mt-3">
<h3 class="text-lg leading-6 font-medium text-gray-900"> <h3 class="text-xl leading-6 font-medium text-neutral-900">
{#if is_fixed} Sponsoring erstellen
{$_("create-a-new-fixed-donation")}
{:else}{$_("create-a-new-distance-donation")}{/if}
</h3> </h3>
<label class="content-center align-middle object-center"> <nav
<span class="text-base" class:text-gray-300={is_fixed} class="relative z-0 flex border border-neutral-200 rounded-xl overflow-hidden mb-2"
>{$_("distance-donation")}</span
> >
<input <button
class="toggle relative w-10 h-5 transition-all duration-200 ease-in-out bg-gray-400 rounded-full shadow-inner outline-none appearance-none align-middle" on:click={() => {
type="checkbox" type = "distance";
bind:checked={is_fixed} }}
/> type="button"
<span class="ml-2 text-base" class:text-gray-300={!is_fixed} id="bar-with-underline-item-1"
>{$_("fixed-donation")}</span class:donation_active_tab={type === "distance"}
class:donation_inactive_tab={type !== "distance"}
aria-selected={type === "distance"}
role="tab"
> >
</label> {$_("spende_pro_km")}
<div class="mb-6"> </button>
<p class="text-sm text-gray-500"> <button
{$_( on:click={() => {
"please-provide-the-nessecary-information-to-create-a-new-donation" type = "fixed";
)} }}
</p> type="button"
</div> id="bar-with-underline-item-2"
class:donation_active_tab={type === "fixed"}
class:donation_inactive_tab={type !== "fixed"}
aria-selected={type === "fixed"}
role="tab"
>
{$_("festbetrag")}
</button>
<button
on:click={() => {
type = "anonymous";
}}
type="button"
id="bar-with-underline-item-3"
class:donation_active_tab={type === "anonymous"}
class:donation_inactive_tab={type !== "anonymous"}
aria-selected={type === "anonymous"}
role="tab"
>
{$_("anonyme_spende")}
</button>
</nav>
<div class="grid grid-cols-6 gap-2 lg:gap-6 text-left"> <div class="grid grid-cols-6 gap-2 lg:gap-6 text-left">
{#if type === "anonymous"}
<div class="col-span-6">
<label
for="donation_amount_eur"
class="block text-sm font-medium text-neutral-900"
>
{$_("donation-amount")}</label
>
<div class="mt-1 flex rounded-md shadow-sm">
<input
autocomplete="off"
class:border-red-500={!is_amount_valid}
class:focus:border-red-500={!is_amount_valid}
class:focus:ring-red-500={!is_amount_valid}
bind:value={amount_input}
type="number"
step="0.01"
name="donation_amount_eur"
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 p-2"
placeholder="2.00"
/>
<span
class="inline-flex items-center px-3 rounded-r-md border border-neutral-300 bg-neutral-50 text-neutral-500 text-sm"
>€</span
>
</div>
{#if !is_amount_valid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
>
{$_("donation-amount-must-be-greater-that-0-00eur")}
</span>
{/if}
</div>
{:else}
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="donor" for="donor"
class="block text-sm font-medium text-gray-700" class="block text-sm font-medium text-neutral-900"
>{$_("donor")}</label >{$_("donor")}</label
> >
<Select <Select
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 rounded-md p-2"
itemFilter={(label, filterText, option) => itemFilter={(label, filterText, option) =>
filterDonors(label, filterText, option)} filterDonors(label, filterText, option)}
items={donors} items={donors}
@ -204,15 +280,15 @@
on:clear={() => (donors = null)} on:clear={() => (donors = null)}
/> />
</div> </div>
{#if !is_fixed} {#if type === "distance"}
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="donor" for="donor"
class="block text-sm font-medium text-gray-700" class="block text-sm font-medium text-neutral-900"
>{$_("runner")}</label >{$_("runner")}</label
> >
<Select <Select
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 rounded-md p-2"
itemFilter={(label, filterText, option) => itemFilter={(label, filterText, option) =>
filterDonors(label, filterText, option)} filterDonors(label, filterText, option)}
items={runners} items={runners}
@ -228,11 +304,11 @@
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="donation_amount_eur" for="donation_amount_eur"
class="block text-sm font-medium text-gray-700" class="block text-sm font-medium text-neutral-900"
> >
{#if !is_fixed} {#if type === "fixed"}
{$_("amount-per-kilometer")} {$_("donation-amount")}
{:else}{$_("donation-amount")}{/if}</label {:else}{$_("amount-per-kilometer")}{/if}</label
> >
<div class="mt-1 flex rounded-md shadow-sm"> <div class="mt-1 flex rounded-md shadow-sm">
<input <input
@ -244,11 +320,11 @@
type="number" type="number"
step="0.01" step="0.01"
name="donation_amount_eur" name="donation_amount_eur"
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2" class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-neutral-300 border bg-neutral-50 text-neutral-800 p-2"
placeholder="2.00" placeholder="2.00"
/> />
<span <span
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm" class="inline-flex items-center px-3 rounded-r-md border border-neutral-300 bg-neutral-50 text-neutral-500 text-sm"
>€</span >€</span
> >
</div> </div>
@ -260,36 +336,29 @@
</span> </span>
{/if} {/if}
</div> </div>
{#if is_fixed} {/if}
<div class="col-span-6"> {#if type === "fixed" || type === "anonymous"}
<div class="flex">
<input
bind:checked={is_paid}
type="checkbox"
class="shrink-0 mt-0.5 border-neutral-200 rounded-sm text-blue-600 focus:ring-blue-500 checked:border-blue-500 disabled:opacity-50 disabled:pointer-events-none"
id="hs-default-checkbox"
/>
<label <label
for="paid" for="hs-default-checkbox"
class="block text-sm font-medium text-gray-700" class="text-base text-neutral-900 ms-2 font-medium"
>{$_("already-paid")}</label >{$_("already-paid")}</label
> >
<p class="text-gray-500">
<input
id="paid"
bind:checked={is_paid}
name="paid"
type="checkbox"
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
<span class="align-text-bottom">
{#if is_paid}
{$_("paid")}
{:else}
{$_("open")}
{/if}
</span>
</p>
</div> </div>
{/if} {/if}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="bg-gray-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10"> <div
class="bg-neutral-50 px-4 lg:py-3 sm:px-6 grid gap-2 lg:rounded-b-xl pt-3 pb-10"
>
<button <button
disabled={!createbtnenabled} disabled={!createbtnenabled}
class:opacity-50={!createbtnenabled} class:opacity-50={!createbtnenabled}
@ -304,7 +373,7 @@
modal_open = false; modal_open = false;
}} }}
type="button" type="button"
class="w-full justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 hidden lg:block" class="w-full justify-center rounded-md border border-neutral-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-neutral-900 hover:bg-neutral-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 hidden lg:block"
> >
{$_("cancel")} {$_("cancel")}
</button> </button>
@ -313,28 +382,3 @@
</div> </div>
</div> </div>
{/if} {/if}
<style>
.toggle:before {
content: "";
position: absolute;
width: 1.25rem;
height: 1.25rem;
border-radius: 50%;
top: 0;
left: 0;
transform: scale(1.1);
box-shadow: 0 0.125rem 0.5rem rgba(0, 0, 0, 0.2);
background-color: white;
transition: 0.2s ease-in-out;
}
.toggle:checked {
/* @apply: bg-indigo-400; */
background-color: #7f9cf5;
}
.toggle:checked:before {
left: 1.25rem;
}
</style>

View File

@ -4,7 +4,10 @@
</script> </script>
{#if !donor || donor.firstname == 0} {#if !donor || donor.firstname == 0}
{$_("donor-has-no-associated-donations")} <span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
>{$_('anonymer_sponsor')}</span
>
{:else} {:else}
<div class="flex items-center"> <div class="flex items-center">
<a <a

View File

@ -41,6 +41,8 @@
"already-paid": "Bereits bezahlt", "already-paid": "Bereits bezahlt",
"amount": "Anzahl", "amount": "Anzahl",
"amount-per-kilometer": "Betrag pro Kilometer", "amount-per-kilometer": "Betrag pro Kilometer",
"anonyme_spende": "Anonyme Spende",
"anonymer_sponsor": "👻 Anonymer Sponsor",
"apartment-suite-etc": "Apartment, Wohnung, etc.", "apartment-suite-etc": "Apartment, Wohnung, etc.",
"api-endpoint": "API-Endpunkt", "api-endpoint": "API-Endpunkt",
"application_name": "Lauf für Kaya! - Admin", "application_name": "Lauf für Kaya! - Admin",
@ -224,6 +226,7 @@
"error_on_login": "😢Fehler beim Login", "error_on_login": "😢Fehler beim Login",
"everything-concerning-your-profile": "Alles zu deinem Profil", "everything-concerning-your-profile": "Alles zu deinem Profil",
"faq": "FAQ", "faq": "FAQ",
"festbetrag": "Festbetrag",
"filename_sponsoringquittungsliste": "SponsoringQuittungsListe", "filename_sponsoringquittungsliste": "SponsoringQuittungsListe",
"filter-by-organization-team": "Filtern nach Organisation / Team", "filter-by-organization-team": "Filtern nach Organisation / Team",
"first-name": "Vorname", "first-name": "Vorname",
@ -418,6 +421,7 @@
"settings": "Einstellungen", "settings": "Einstellungen",
"settings-for-your-profile": "Die Einstellungen deines Accounts", "settings-for-your-profile": "Die Einstellungen deines Accounts",
"something-about-the-group": "Infos zur Gruppe", "something-about-the-group": "Infos zur Gruppe",
"spende_pro_km": "Spende pro km",
"sponsoring-quittungs-liste_herunterladen": "Sponsoring-Quittungs-Liste herunterladen", "sponsoring-quittungs-liste_herunterladen": "Sponsoring-Quittungs-Liste herunterladen",
"sponsorings": "Sponsoringerklaerungen", "sponsorings": "Sponsoringerklaerungen",
"station-deleted": "Scannerstation gelöscht", "station-deleted": "Scannerstation gelöscht",

View File

@ -41,6 +41,8 @@
"already-paid": "Already paid", "already-paid": "Already paid",
"amount": "Amount", "amount": "Amount",
"amount-per-kilometer": "Amount per kilometer", "amount-per-kilometer": "Amount per kilometer",
"anonyme_spende": "Anonymous Donation",
"anonymer_sponsor": "👻 Anonymous Donor",
"apartment-suite-etc": "Apartment, suite, etc.", "apartment-suite-etc": "Apartment, suite, etc.",
"api-endpoint": "API-Endpoint", "api-endpoint": "API-Endpoint",
"application_name": "Lauf für Kaya! - Admin", "application_name": "Lauf für Kaya! - Admin",
@ -224,6 +226,7 @@
"error_on_login": "Error on login", "error_on_login": "Error on login",
"everything-concerning-your-profile": "Everything concerning your profile", "everything-concerning-your-profile": "Everything concerning your profile",
"faq": "FAQ", "faq": "FAQ",
"festbetrag": "Fixed Donation",
"filename_sponsoringquittungsliste": "DonorReceiptList", "filename_sponsoringquittungsliste": "DonorReceiptList",
"filter-by-organization-team": "Filter by Organization/ Team", "filter-by-organization-team": "Filter by Organization/ Team",
"first-name": "First name", "first-name": "First name",
@ -418,6 +421,7 @@
"settings": "Settings", "settings": "Settings",
"settings-for-your-profile": "Settings for your profile", "settings-for-your-profile": "Settings for your profile",
"something-about-the-group": "Something about the group...", "something-about-the-group": "Something about the group...",
"spende_pro_km": "donation per km",
"sponsoring-quittungs-liste_herunterladen": "Download donor receipt list", "sponsoring-quittungs-liste_herunterladen": "Download donor receipt list",
"sponsorings": "Sponsorings", "sponsorings": "Sponsorings",
"station-deleted": "station deleted", "station-deleted": "station deleted",

View File

@ -25,3 +25,9 @@
#html5-qrcode-button-camera-stop { #html5-qrcode-button-camera-stop {
@apply px-2 inline-flex text-lg leading-5 font-semibold rounded-md border border-current bg-red-100 text-red-800 mb-2 cursor-pointer; @apply px-2 inline-flex text-lg leading-5 font-semibold rounded-md border border-current bg-red-100 text-red-800 mb-2 cursor-pointer;
} }
.donation_inactive_tab {
@apply min-w-0 flex-1 bg-white first:border-s-0 border-s border-b-2 border-neutral-200 py-4 px-4 text-neutral-800 hover:text-neutral-700 text-sm font-medium text-center overflow-hidden hover:bg-neutral-200 cursor-pointer focus:z-10 focus:outline-hidden focus:bg-neutral-200 disabled:opacity-50 disabled:pointer-events-none;
}
.donation_active_tab {
@apply min-w-0 flex-1 bg-blue-400 text-white first:border-s-0 border-s border-b-2 border-neutral-200 py-4 px-4 text-sm font-medium text-center overflow-hidden cursor-pointer focus:outline-hidden;
}