This commit is contained in:
Philipp Dormann 2025-03-20 21:51:00 +01:00
parent e82350df4a
commit 1bc53146b9
Signed by: philipp
GPG Key ID: 3BB9ADD52DCA4314
4 changed files with 800 additions and 797 deletions

View File

@ -145,7 +145,6 @@
{original_data.middlename || ""} {original_data.middlename || ""}
{original_data.lastname} {original_data.lastname}
<div data-id="donor_actions_${editable.id}"> <div data-id="donor_actions_${editable.id}">
<p class="text-base">Aktionen</p>
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:DELETE")} {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:DELETE")}
{#if delete_triggered} {#if delete_triggered}
<button <button
@ -226,8 +225,8 @@
{/each} {/each}
{:else}{$_("donor-has-no-associated-donations")}{/if} {:else}{$_("donor-has-no-associated-donations")}{/if}
</div> </div>
<div class=" w-full"> <div class="mt-2 w-full">
<label for="firstname" class="font-medium text-gray-700" <label for="firstname" class="font-semibold text-gray-700"
>{$_("first-name")}</label >{$_("first-name")}</label
> >
<input <input
@ -239,7 +238,7 @@
class:focus:ring-red-500={!isFirstnameValid} class:focus:ring-red-500={!isFirstnameValid}
bind:value={editable.firstname} bind:value={editable.firstname}
name="firstname" name="firstname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !isFirstnameValid} {#if !isFirstnameValid}
<span <span
@ -249,8 +248,8 @@
</span> </span>
{/if} {/if}
</div> </div>
<div class=" w-full"> <div class="mt-2 w-full">
<label for="middlename" class="font-medium text-gray-700" <label for="middlename" class="font-semibold text-gray-700"
>{$_("middle-name")}</label >{$_("middle-name")}</label
> >
<input <input
@ -259,11 +258,11 @@
type="text" type="text"
bind:value={editable.middlename} bind:value={editable.middlename}
name="middlename" name="middlename"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
</div> </div>
<div class=" w-full"> <div class="mt-2 w-full">
<label for="lastname" class="font-medium text-gray-700" <label for="lastname" class="font-semibold text-gray-700"
>{$_("last-name")}</label >{$_("last-name")}</label
> >
<input <input
@ -275,7 +274,7 @@
class:focus:border-red-500={!isLastnameValid} class:focus:border-red-500={!isLastnameValid}
class:focus:ring-red-500={!isLastnameValid} class:focus:ring-red-500={!isLastnameValid}
name="lastname" name="lastname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !isLastnameValid} {#if !isLastnameValid}
<span <span
@ -285,8 +284,8 @@
</span> </span>
{/if} {/if}
</div> </div>
<div class=" w-full"> <div class="mt-2 w-full">
<label for="email" class="font-medium text-gray-700" <label for="email" class="font-semibold text-gray-700"
>{$_("e-mail-adress")}</label >{$_("e-mail-adress")}</label
> >
<input <input
@ -298,7 +297,7 @@
class:focus:border-red-500={!isEmailValid} class:focus:border-red-500={!isEmailValid}
class:focus:ring-red-500={!isEmailValid} class:focus:ring-red-500={!isEmailValid}
name="email" name="email"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !isEmailValid} {#if !isEmailValid}
<span <span
@ -308,8 +307,8 @@
</span> </span>
{/if} {/if}
</div> </div>
<div class=" w-full"> <div class="mt-2 w-full">
<label for="phone" class="font-medium text-gray-700">{$_("phone")}</label> <label for="phone" class="font-semibold text-gray-700">{$_("phone")}</label>
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_("phone")} placeholder={$_("phone")}
@ -319,7 +318,7 @@
class:focus:ring-red-500={!isPhoneValidOrEmpty} class:focus:ring-red-500={!isPhoneValidOrEmpty}
bind:value={editable.phone} bind:value={editable.phone}
name="phone" name="phone"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !isPhoneValidOrEmpty} {#if !isPhoneValidOrEmpty}
<span <span
@ -340,7 +339,7 @@
/> />
</div> </div>
<div class="ml-3"> <div class="ml-3">
<label for="comments" class="font-medium text-gray-700" <label for="comments" class="font-semibold text-gray-700"
>{$_("receipt-needed")}</label >{$_("receipt-needed")}</label
> >
</div> </div>
@ -359,7 +358,7 @@
bind:value={editable.address.address1} bind:value={editable.address.address1}
type="text" type="text"
name="address1" name="address1"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !isAddress1Valid} {#if !isAddress1Valid}
<span <span
@ -379,7 +378,7 @@
bind:value={editable.address.address2} bind:value={editable.address.address2}
type="text" type="text"
name="address2" name="address2"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
@ -395,7 +394,7 @@
bind:value={editable.address.postalcode} bind:value={editable.address.postalcode}
type="text" type="text"
name="zipcode" name="zipcode"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !iszipcodevalid} {#if !iszipcodevalid}
<span <span
@ -418,7 +417,7 @@
bind:value={editable.address.city} bind:value={editable.address.city}
type="text" type="text"
name="city" name="city"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !iscityvalid} {#if !iscityvalid}
<span <span

View File

@ -1,488 +1,490 @@
<script> <script>
import { import {
GroupContactService, GroupContactService,
RunnerOrganizationService, RunnerOrganizationService,
} from "@odit/lfk-client-js"; } from "@odit/lfk-client-js";
import { getLocaleFromNavigator, _ } from "svelte-i18n"; import { getLocaleFromNavigator, _ } from "svelte-i18n";
import toast from 'svelte-french-toast' import toast from "svelte-french-toast";
import store from "../../store"; import store from "../../store";
import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte"; import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte";
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte"; import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
import PromiseError from "../base/PromiseError.svelte"; import PromiseError from "../base/PromiseError.svelte";
import Select from "svelte-select"; import Select from "svelte-select";
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte"; import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte"; import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte"; import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
import { tick } from "svelte"; import { tick } from "svelte";
$: delete_triggered = false; $: delete_triggered = false;
$: address_valid_or_none = $: address_valid_or_none =
(isAddress1Valid && iszipcodevalid && iscityvalid) || (isAddress1Valid && iszipcodevalid && iscityvalid) ||
editable.address_checked === false; editable.address_checked === false;
$: save_enabled = data_changed && address_valid_or_none; $: save_enabled = data_changed && address_valid_or_none;
let original = ""; let original = "";
let original_object = {}; let original_object = {};
let contacts = []; let contacts = [];
let valueCopy = null; let valueCopy = null;
let areaDom; let areaDom;
let copied = false; let copied = false;
export let params; export let params;
$: editable = {}; $: editable = {};
$: contact = {}; $: contact = {};
$: data_loaded = false; $: data_loaded = false;
$: data_changed = !(JSON.stringify(editable) === original); $: data_changed = !(JSON.stringify(editable) === original);
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0; $: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0; $: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
$: iscityvalid = editable.address?.city?.trim().length !== 0; $: iscityvalid = editable.address?.city?.trim().length !== 0;
$: sponsoring_contracts_show = true; $: sponsoring_contracts_show = true;
$: cards_show = true; $: cards_show = true;
$: certificates_show = true; $: certificates_show = true;
$: generate_orgs = [original_object]; $: generate_orgs = [original_object];
$: registrationLink = `${config.baseurl_selfservice}/register/${editable.registrationKey}`; $: registrationLink = `${config.baseurl_selfservice}/register/${editable.registrationKey}`;
const getContactLabel = (option) => const getContactLabel = (option) =>
option.firstname + " " + (option.middlename || "") + " " + option.lastname; option.firstname + " " + (option.middlename || "") + " " + option.lastname;
const promise = RunnerOrganizationService.runnerOrganizationControllerGetOne( const promise = RunnerOrganizationService.runnerOrganizationControllerGetOne(
params.orgid params.orgid
).then((value) => { ).then((value) => {
data_loaded = true; data_loaded = true;
value.address_checked = value.address.address1 !== null; value.address_checked = value.address.address1 !== null;
if (value.address_checked === false) { if (value.address_checked === false) {
value.address = { value.address = {
address1: "", address1: "",
address2: "", address2: "",
city: "", city: "",
postalcode: "", postalcode: "",
country: "", country: "",
}; };
} }
editable = Object.assign(editable, value); editable = Object.assign(editable, value);
editable = editable; editable = editable;
original_object = Object.assign(editable, value); original_object = Object.assign(editable, value);
original = JSON.stringify(value); original = JSON.stringify(value);
GroupContactService.groupContactControllerGetAll().then((val) => { GroupContactService.groupContactControllerGetAll().then((val) => {
contacts = val.map((r) => { contacts = val.map((r) => {
return { label: getContactLabel(r), value: r }; return { label: getContactLabel(r), value: r };
}); });
if (editable.contact) { if (editable.contact) {
contact = contacts.find((g) => g.value.id == editable.contact.id); contact = contacts.find((g) => g.value.id == editable.contact.id);
} else { } else {
contact = null; contact = null;
} }
}); });
}); });
let modal_open = false; let modal_open = false;
let delete_org = {}; let delete_org = {};
function deleteOrganization() { function deleteOrganization() {
RunnerOrganizationService.runnerOrganizationControllerRemove( RunnerOrganizationService.runnerOrganizationControllerRemove(
original_object.id, original_object.id,
false false
) )
.then((resp) => { .then((resp) => {
toast($_("organization-deleted")); toast($_("organization-deleted"));
location.replace("./"); location.replace("./");
}) })
.catch((err) => { .catch((err) => {
modal_open = true; modal_open = true;
delete_org = original_object; delete_org = original_object;
}); });
} }
function submit() { function submit() {
if (data_loaded === true && save_enabled) { if (data_loaded === true && save_enabled) {
toast($_("updating-organization")); toast($_("updating-organization"));
let postdata = Object.assign({}, editable); let postdata = Object.assign({}, editable);
if (postdata.address_checked === false) { if (postdata.address_checked === false) {
postdata.address = null; postdata.address = null;
} }
postdata.contact = postdata.contact?.id; postdata.contact = postdata.contact?.id;
RunnerOrganizationService.runnerOrganizationControllerPut( RunnerOrganizationService.runnerOrganizationControllerPut(
original_object.id, original_object.id,
postdata postdata
) )
.then((resp) => { .then((resp) => {
editable.registrationKey = resp.registrationKey; editable.registrationKey = resp.registrationKey;
original_object = Object.assign({}, editable); original_object = Object.assign({}, editable);
original = JSON.stringify(original_object); original = JSON.stringify(original_object);
toast.success($_("updated-organization")); toast.success($_("updated-organization"));
}) })
.catch((err) => {}); .catch((err) => {});
} else { } else {
} }
} }
async function copy() { async function copy() {
if (!editable.registrationKey) { if (!editable.registrationKey) {
toast.error($_("you-have-to-save-your-changes-to-generate-a-link")); toast.error($_("you-have-to-save-your-changes-to-generate-a-link"));
return; return;
} }
valueCopy = registrationLink; valueCopy = registrationLink;
await tick(); await tick();
areaDom.focus(); areaDom.focus();
areaDom.select(); areaDom.select();
try { try {
const successful = document.execCommand("copy"); const successful = document.execCommand("copy");
if (!successful) { if (!successful) {
throw new Error(); throw new Error();
} }
toast($_("copied-link-to-clipboard")); toast($_("copied-link-to-clipboard"));
copied = true; copied = true;
} catch (err) { } catch (err) {
toast.error($_("error-whyile-copying-to-clipboard")); toast.error($_("error-whyile-copying-to-clipboard"));
} }
// we can notifi by event or storage about copy status // we can notifi by event or storage about copy status
valueCopy = null; valueCopy = null;
} }
export let import_modal_open = false; export let import_modal_open = false;
</script> </script>
{#if valueCopy != null}<textarea bind:this={areaDom}>{valueCopy}</textarea>{/if} {#if valueCopy != null}<textarea bind:this={areaDom}>{valueCopy}</textarea>{/if}
<ImportRunnerModal <ImportRunnerModal
on:cancelDelete={(event) => { on:cancelDelete={(event) => {
import_modal_open = false; import_modal_open = false;
}} }}
current_runners={[]} current_runners={[]}
passed_team={{}} passed_team={{}}
passed_orgs={[]} passed_orgs={[]}
passed_org={editable} passed_org={editable}
opened_from="OrgDetail" opened_from="OrgDetail"
bind:import_modal_open bind:import_modal_open
/> />
<ConfirmOrgDeletion bind:modal_open bind:delete_org /> <ConfirmOrgDeletion bind:modal_open bind:delete_org />
{#if data_loaded} {#if data_loaded}
<section class="container p-5"> <section class="container p-5">
<div class="mb-8 text-3xl font-extrabold leading-tight"> <div class="flex flex-row mb-4">
{original_object.name} <div class="w-full">
<span data-id="org_actions_${editable.id}"> <nav class="w-full flex">
<GenerateSponsoringContracts <ol class="list-none flex flex-row items-center justify-start">
bind:sponsoring_contracts_show <li class="mr-2 flex items-center">
bind:generate_orgs <svg
/> stroke="currentColor"
<GenerateRunnerCards bind:cards_show bind:generate_orgs /> fill="none"
<GenerateRunnerCertificates bind:certificates_show bind:generate_orgs /> stroke-width="2"
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")} viewBox="0 0 24 24"
<button stroke-linecap="round"
on:click={() => { stroke-linejoin="round"
import_modal_open = true; class="h-3 w-3 stroke-current"
}} height="1em"
type="button" width="1em"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm" xmlns="http://www.w3.org/2000/svg"
> ><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
{$_("import-runners")} <polyline points="9 22 9 12 15 12 15 22" /></svg
</button> >
{/if} </li>
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")} <li class="flex items-center">
{#if delete_triggered} <a class="mr-2" href="/">{$_("home")}</a><svg
<button stroke="currentColor"
on:click={deleteOrganization} fill="none"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm" stroke-width="2"
>{$_("confirm-delete")}</button viewBox="0 0 24 24"
> stroke-linecap="round"
<button stroke-linejoin="round"
on:click={() => { class="h-3 w-3 mr-2 stroke-current"
delete_triggered = !delete_triggered; height="1em"
}} width="1em"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm" xmlns="http://www.w3.org/2000/svg"
>{$_("cancel")}</button ><line x1="5" y1="12" x2="19" y2="12" />
> <polyline points="12 5 19 12 12 19" /></svg
{/if} >
{#if !delete_triggered} </li>
<button <li class="mr-2 flex items-center">
on:click={() => { <svg
delete_triggered = true; xmlns="http://www.w3.org/2000/svg"
}} viewBox="0 0 24 24"
type="button" width="24"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm" height="24"
>{$_("delete-organization")}</button ><path fill="none" d="M0 0h24v24H0z" />
> <path
{/if} d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z"
{/if} /></svg
{#if !delete_triggered} >
<button </li>
on:click={submit} <li class="flex items-center">
disabled={!save_enabled} <a class="mr-2" href="./">{$_("organizations")}</a><svg
class:opacity-50={!save_enabled} stroke="currentColor"
type="button" fill="none"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm" stroke-width="2"
>{$_("save-changes")}</button viewBox="0 0 24 24"
> stroke-linecap="round"
{/if} stroke-linejoin="round"
</span> class="h-3 w-3 mr-2 stroke-current"
</div> height="1em"
<div class="flex flex-row mb-4"> width="1em"
<div class="w-full"> xmlns="http://www.w3.org/2000/svg"
<nav class="w-full flex"> ><line x1="5" y1="12" x2="19" y2="12" />
<ol class="list-none flex flex-row items-center justify-start"> <polyline points="12 5 19 12 12 19" /></svg
<li class="mr-2 flex items-center"> >
<svg </li>
stroke="currentColor" <li class="flex items-center">
fill="none" <span class="mr-2">Org-Details #{params.orgid}</span>
stroke-width="2" </li>
viewBox="0 0 24 24" </ol>
stroke-linecap="round" </nav>
stroke-linejoin="round" </div>
class="h-3 w-3 stroke-current" </div>
height="1em" <div class="mb-8 text-3xl font-extrabold leading-tight">
width="1em" {original_object.name}
xmlns="http://www.w3.org/2000/svg" <span data-id="org_actions_${editable.id}">
><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" /> <GenerateSponsoringContracts
<polyline points="9 22 9 12 15 12 15 22" /></svg bind:sponsoring_contracts_show
> bind:generate_orgs
</li> />
<li class="flex items-center"> <GenerateRunnerCards bind:cards_show bind:generate_orgs />
<a class="mr-2" href="/">{$_("home")}</a><svg <GenerateRunnerCertificates bind:certificates_show bind:generate_orgs />
stroke="currentColor" {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
fill="none" <button
stroke-width="2" on:click={() => {
viewBox="0 0 24 24" import_modal_open = true;
stroke-linecap="round" }}
stroke-linejoin="round" type="button"
class="h-3 w-3 mr-2 stroke-current" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm"
height="1em" >
width="1em" {$_("import-runners")}
xmlns="http://www.w3.org/2000/svg" </button>
><line x1="5" y1="12" x2="19" y2="12" /> {/if}
<polyline points="12 5 19 12 12 19" /></svg {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
> {#if delete_triggered}
</li> <button
<li class="mr-2 flex items-center"> on:click={deleteOrganization}
<svg class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm"
xmlns="http://www.w3.org/2000/svg" >{$_("confirm-delete")}</button
viewBox="0 0 24 24" >
width="24" <button
height="24" on:click={() => {
><path fill="none" d="M0 0h24v24H0z" /> delete_triggered = !delete_triggered;
<path }}
d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z" class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
/></svg >{$_("cancel")}</button
> >
</li> {/if}
<li class="flex items-center"> {#if !delete_triggered}
<a class="mr-2" href="./">{$_("organizations")}</a><svg <button
stroke="currentColor" on:click={() => {
fill="none" delete_triggered = true;
stroke-width="2" }}
viewBox="0 0 24 24" type="button"
stroke-linecap="round" class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm"
stroke-linejoin="round" >{$_("delete-organization")}</button
class="h-3 w-3 mr-2 stroke-current" >
height="1em" {/if}
width="1em" {/if}
xmlns="http://www.w3.org/2000/svg" {#if !delete_triggered}
><line x1="5" y1="12" x2="19" y2="12" /> <button
<polyline points="12 5 19 12 12 19" /></svg on:click={submit}
> disabled={!save_enabled}
</li> class:opacity-50={!save_enabled}
<li class="flex items-center"> type="button"
<span class="mr-2">Org-Details #{params.orgid}</span> class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm"
</li> >{$_("save-changes")}</button
</ol> >
</nav> {/if}
</div> </span>
</div> </div>
<div class="text-sm w-full"> <div class="text-sm w-full">
<label for="name" class="font-medium text-gray-700">{$_("name")}</label> <label for="name" class="font-medium text-gray-700">{$_("name")}</label>
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_("name")} placeholder={$_("name")}
type="text" type="text"
bind:value={editable.name} bind:value={editable.name}
name="name" name="name"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
</div> </div>
<div class="text-sm w-full"> <div class="text-sm w-full">
<label for="contact" class="font-medium text-gray-700" <label for="contact" class="font-medium text-gray-700"
>{$_("contact")}</label >{$_("contact")}</label
> >
<Select <Select
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md 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 rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
itemFilter={(label, filterText, option) => itemFilter={(label, filterText, option) =>
label.toLowerCase().includes(filterText.toLowerCase()) || label.toLowerCase().includes(filterText.toLowerCase()) ||
option.value.id.toString().startsWith(filterText.toLowerCase())} option.value.id.toString().startsWith(filterText.toLowerCase())}
items={contacts} items={contacts}
showChevron={true} showChevron={true}
placeholder={$_("no-contact-selected")} placeholder={$_("no-contact-selected")}
noOptionsMessage={$_("no-contact-found")} noOptionsMessage={$_("no-contact-found")}
bind:selectedValue={contact} bind:selectedValue={contact}
on:select={(selectedValue) => on:select={(selectedValue) =>
(editable.contact = selectedValue.detail.value)} (editable.contact = selectedValue.detail.value)}
on:clear={() => (editable.contact = null)} on:clear={() => (editable.contact = null)}
/> />
</div> </div>
<div> <div>
<div class="flex items-start mt-2"> <div class="flex items-start mt-2">
<div class="flex items-center h-5"> <div class="flex items-center h-5">
<input <input
bind:checked={editable.registrationEnabled} bind:checked={editable.registrationEnabled}
id="toggle_selfservice_feature" id="toggle_selfservice_feature"
name="toggle_selfservice_feature" name="toggle_selfservice_feature"
type="checkbox" type="checkbox"
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" class="focus:ring-indigo-500 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="toggle_selfservice_feature" for="toggle_selfservice_feature"
class="font-medium text-gray-700" class="font-medium text-gray-700"
>{$_("selfservice-registration")}</label >{$_("selfservice-registration")}</label
> >
</div> </div>
</div> </div>
<div> <div>
{#if editable.registrationEnabled} {#if editable.registrationEnabled}
<div class="text-sm w-full"> <div class="text-sm w-full">
<button on:click={copy} class="inline-flex w-full"> <button on:click={copy} class="inline-flex w-full">
<p <p
name="token" name="token"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
> >
{#if editable.registrationKey} {#if editable.registrationKey}
{registrationLink} {registrationLink}
{:else} {:else}
{$_("you-have-to-save-your-changes-to-generate-a-link")} {$_("you-have-to-save-your-changes-to-generate-a-link")}
{/if} {/if}
</p> </p>
<div <div
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer" class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" viewBox="0 0 24 24"
width="24" width="24"
height="24" height="24"
><path fill="none" d="M0 0h24v24H0z" /> ><path fill="none" d="M0 0h24v24H0z" />
<path <path
fill="currentColor" fill="currentColor"
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z" d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"
/></svg /></svg
> >
</div> </div>
</button> </button>
{#if editable.registrationKey} {#if editable.registrationKey}
<p class="text-gray-500 text-xs"> <p class="text-gray-500 text-xs">
{$_("click-to-copy-the-link-into-your-clipboard")} {$_("click-to-copy-the-link-into-your-clipboard")}
</p> </p>
{/if} {/if}
</div> </div>
{/if} {/if}
<!-- --> <!-- -->
<div> <div>
<div class="flex items-start mt-2"> <div class="flex items-start mt-2">
<div class="flex items-center h-5"> <div class="flex items-center h-5">
<input <input
bind:checked={editable.address_checked} bind:checked={editable.address_checked}
id="toggle_address_checkbox" id="toggle_address_checkbox"
name="toggle_address_checkbox" name="toggle_address_checkbox"
type="checkbox" type="checkbox"
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" class="focus:ring-indigo-500 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="toggle_address_checkbox" for="toggle_address_checkbox"
class="font-medium text-gray-700">{$_("address")}</label class="font-medium text-gray-700">{$_("address")}</label
> >
</div> </div>
</div> </div>
</div> </div>
{#if editable.address_checked === true} {#if editable.address_checked === true}
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="address1" for="address1"
class="block text-sm font-medium text-gray-700" class="block text-sm font-medium text-gray-700"
>{$_("address")}</label >{$_("address")}</label
> >
<input <input
autocomplete="off" autocomplete="off"
placeholder="Address" placeholder="Address"
class:border-red-500={!isAddress1Valid} class:border-red-500={!isAddress1Valid}
class:focus:border-red-500={!isAddress1Valid} class:focus:border-red-500={!isAddress1Valid}
class:focus:ring-red-500={!isAddress1Valid} class:focus:ring-red-500={!isAddress1Valid}
bind:value={editable.address.address1} bind:value={editable.address.address1}
type="text" type="text"
name="address1" name="address1"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !isAddress1Valid} {#if !isAddress1Valid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1" class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
> >
{$_("address-is-required")} {$_("address-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="address2" for="address2"
class="block text-sm font-medium text-gray-700" class="block text-sm font-medium text-gray-700"
>{$_("apartment-suite-etc")}</label >{$_("apartment-suite-etc")}</label
> >
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_("apartment-suite-etc")} placeholder={$_("apartment-suite-etc")}
bind:value={editable.address.address2} bind:value={editable.address.address2}
type="text" type="text"
name="address2" name="address2"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label for="zipcode" class="block text-sm font-medium text-gray-700" <label for="zipcode" class="block text-sm font-medium text-gray-700"
>{$_("zip-postal-code")}</label >{$_("zip-postal-code")}</label
> >
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_("zip-postal-code")} placeholder={$_("zip-postal-code")}
class:border-red-500={!iszipcodevalid} class:border-red-500={!iszipcodevalid}
class:focus:border-red-500={!iszipcodevalid} class:focus:border-red-500={!iszipcodevalid}
class:focus:ring-red-500={!iszipcodevalid} class:focus:ring-red-500={!iszipcodevalid}
bind:value={editable.address.postalcode} bind:value={editable.address.postalcode}
type="text" type="text"
name="zipcode" name="zipcode"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !iszipcodevalid} {#if !iszipcodevalid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1" class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
> >
{$_("valid-zipcode-postal-code-is-required")} {$_("valid-zipcode-postal-code-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label for="city" class="block text-sm font-medium text-gray-700" <label for="city" class="block text-sm font-medium text-gray-700"
>{$_("city")}</label >{$_("city")}</label
> >
<input <input
autocomplete="off" autocomplete="off"
placeholder={$_("city")} placeholder={$_("city")}
class:border-red-500={!iscityvalid} class:border-red-500={!iscityvalid}
class:focus:border-red-500={!iscityvalid} class:focus:border-red-500={!iscityvalid}
class:focus:ring-red-500={!iscityvalid} class:focus:ring-red-500={!iscityvalid}
bind:value={editable.address.city} bind:value={editable.address.city}
type="text" type="text"
name="city" name="city"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
/> />
{#if !iscityvalid} {#if !iscityvalid}
<span <span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1" class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
> >
{$_("valid-city-is-required")} {$_("valid-city-is-required")}
</span> </span>
{/if} {/if}
</div> </div>
{/if} {/if}
<div class="text-sm w-full"> <div class="text-sm w-full">
<span class="font-medium text-gray-700">{$_("distance")}</span> <span class="font-medium text-gray-700">{$_("distance")}</span>
<br /> <br />
<span class="text-gray-700">{(original_object.total_distance / 1000).toFixed(2)} km</span> <span class="text-gray-700"
</div> >{(original_object.total_distance / 1000).toFixed(2)} km</span
</div> >
</div> </div>
</section> </div>
</div>
</section>
{:else} {:else}
{#await promise} {#await promise}
{$_("organization-detail-is-being-loaded")} {$_("organization-detail-is-being-loaded")}
{:catch error} {:catch error}
<PromiseError /> <PromiseError />
{/await} {/await}
{/if} {/if}

View File

@ -159,7 +159,6 @@
bind:generate_runners bind:generate_runners
/> />
<div> <div>
<p class="text-base">Aktionen</p>
{#if delete_triggered} {#if delete_triggered}
<button <button
on:click={deleteRunner} on:click={deleteRunner}

View File

@ -1,308 +1,311 @@
<script> <script>
import { import {
GroupContactService, GroupContactService,
RunnerOrganizationService, RunnerOrganizationService,
RunnerTeamService, RunnerTeamService,
} from "@odit/lfk-client-js"; } from "@odit/lfk-client-js";
import { getLocaleFromNavigator, _ } from "svelte-i18n"; import { getLocaleFromNavigator, _ } from "svelte-i18n";
import toast from 'svelte-french-toast' import toast from "svelte-french-toast";
import store from "../../store"; import store from "../../store";
import Select from "svelte-select"; import Select from "svelte-select";
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte"; import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
import PromiseError from "../base/PromiseError.svelte"; import PromiseError from "../base/PromiseError.svelte";
import ConfirmTeamDeletion from "./ConfirmTeamDeletion.svelte"; import ConfirmTeamDeletion from "./ConfirmTeamDeletion.svelte";
import Teams from "./Teams.svelte"; import Teams from "./Teams.svelte";
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte"; import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte"; import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte"; import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
let [teamdata, original, delete_team, orgs, contacts, modal_open] = [ let [teamdata, original, delete_team, orgs, contacts, modal_open] = [
{}, {},
{}, {},
{}, {},
[], [],
[], [],
false, false,
]; ];
export let params; export let params;
export let import_modal_open = false; export let import_modal_open = false;
$: delete_triggered = false; $: delete_triggered = false;
$: save_enabled = data_changed && teamdata.parentGroup != null; $: save_enabled = data_changed && teamdata.parentGroup != null;
$: data_loaded = false; $: data_loaded = false;
$: data_changed = !(JSON.stringify(teamdata) === JSON.stringify(original)); $: data_changed = !(JSON.stringify(teamdata) === JSON.stringify(original));
$: sponsoring_contracts_show = true; $: sponsoring_contracts_show = true;
$: cards_show = true; $: cards_show = true;
$: certificates_show = true; $: certificates_show = true;
$: generate_teams = [original]; $: generate_teams = [original];
$: group = {}; $: group = {};
$: contact = {}; $: contact = {};
// //
const getContactLabel = (option) => const getContactLabel = (option) =>
option.firstname + " " + (option.middlename || "") + " " + option.lastname; option.firstname + " " + (option.middlename || "") + " " + option.lastname;
const promise = RunnerTeamService.runnerTeamControllerGetOne( const promise = RunnerTeamService.runnerTeamControllerGetOne(
params.teamid params.teamid
).then((value) => { ).then((value) => {
data_loaded = true; data_loaded = true;
teamdata = Object.assign(teamdata, value); teamdata = Object.assign(teamdata, value);
original = Object.assign(original, value); original = Object.assign(original, value);
RunnerOrganizationService.runnerOrganizationControllerGetAll().then( RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
(val) => { (val) => {
orgs = val.map((r) => { orgs = val.map((r) => {
delete r.contact; delete r.contact;
r.teams = []; r.teams = [];
return { label: r.name, value: r }; return { label: r.name, value: r };
}); });
group = orgs.find((g) => g.value.id == teamdata.parentGroup.id); group = orgs.find((g) => g.value.id == teamdata.parentGroup.id);
} }
); );
GroupContactService.groupContactControllerGetAll().then((val) => { GroupContactService.groupContactControllerGetAll().then((val) => {
contacts = val.map((r) => { contacts = val.map((r) => {
return { label: getContactLabel(r), value: r }; return { label: getContactLabel(r), value: r };
}); });
if (teamdata.contact) { if (teamdata.contact) {
contact = contacts.find((g) => g.value.id == teamdata.contact.id); contact = contacts.find((g) => g.value.id == teamdata.contact.id);
} else { } else {
contact = null; contact = null;
} }
}); });
}); });
function deleteTeam() { function deleteTeam() {
RunnerTeamService.runnerTeamControllerRemove(original.id, false) RunnerTeamService.runnerTeamControllerRemove(original.id, false)
.then((resp) => { .then((resp) => {
toast($_("team-deleted")); toast($_("team-deleted"));
location.replace("./"); location.replace("./");
}) })
.catch((err) => { .catch((err) => {
modal_open = true; modal_open = true;
delete_team = original; delete_team = original;
}); });
} }
function submit() { function submit() {
if (data_loaded === true && save_enabled) { if (data_loaded === true && save_enabled) {
toast($_("updating-team")); toast($_("updating-team"));
let postdata = teamdata; let postdata = teamdata;
postdata.parentGroup = teamdata.parentGroup.id; postdata.parentGroup = teamdata.parentGroup.id;
postdata.contact = teamdata.contact?.id; postdata.contact = teamdata.contact?.id;
RunnerTeamService.runnerTeamControllerPut(original.id, postdata) RunnerTeamService.runnerTeamControllerPut(original.id, postdata)
.then((resp) => { .then((resp) => {
Object.assign(original, teamdata); Object.assign(original, teamdata);
original = original; original = original;
toast.success($_("updated-team")); toast.success($_("updated-team"));
}) })
.catch((err) => {}); .catch((err) => {});
} }
} }
</script> </script>
<ImportRunnerModal <ImportRunnerModal
current_runners={[]} current_runners={[]}
on:cancelDelete={(event) => { on:cancelDelete={(event) => {
import_modal_open = false; import_modal_open = false;
}} }}
passed_team={teamdata} passed_team={teamdata}
passed_orgs={[]} passed_orgs={[]}
passed_org={{}} passed_org={{}}
opened_from="TeamDetail" opened_from="TeamDetail"
bind:import_modal_open bind:import_modal_open
/> />
<ConfirmTeamDeletion bind:modal_open bind:delete_team /> <ConfirmTeamDeletion bind:modal_open bind:delete_team />
{#if data_loaded} {#if data_loaded}
<section class="container p-5"> <section class="container p-5">
<div class="mb-8 text-3xl font-extrabold leading-tight"> <div class="flex flex-row mb-4">
{original.name} <div class="w-full">
<span data-id="org_actions_${teamdata.id}"> <nav class="w-full flex">
<GenerateSponsoringContracts <ol class="list-none flex flex-row items-center justify-start">
bind:sponsoring_contracts_show <li class="mr-2 flex items-center">
bind:generate_teams <svg
/> stroke="currentColor"
<GenerateRunnerCards bind:cards_show bind:generate_teams /> fill="none"
<GenerateRunnerCertificates stroke-width="2"
bind:certificates_show viewBox="0 0 24 24"
bind:generate_teams stroke-linecap="round"
/> stroke-linejoin="round"
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")} class="h-3 w-3 stroke-current"
<button height="1em"
on:click={() => { width="1em"
import_modal_open = true; xmlns="http://www.w3.org/2000/svg"
}} ><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
type="button" <polyline points="9 22 9 12 15 12 15 22" /></svg
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm" >
> </li>
{$_("import-runners")} <li class="flex items-center">
</button> <a class="mr-2" href="/">Home</a><svg
{/if} stroke="currentColor"
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")} fill="none"
{#if delete_triggered} stroke-width="2"
<button viewBox="0 0 24 24"
on:click={deleteTeam} stroke-linecap="round"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm" stroke-linejoin="round"
>{$_("confirm-delete")}</button class="h-3 w-3 mr-2 stroke-current"
> height="1em"
<button width="1em"
on:click={() => { xmlns="http://www.w3.org/2000/svg"
delete_triggered = !delete_triggered; ><line x1="5" y1="12" x2="19" y2="12" />
}} <polyline points="12 5 19 12 12 19" /></svg
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm" >
>{$_("cancel")}</button </li>
> <li class="mr-2 flex items-center">
{/if} <svg
{#if !delete_triggered} class="flex-shrink-0 w-5 h-5 mr-2"
<button fill="currentColor"
on:click={() => { width="24"
delete_triggered = true; height="24"
}} xmlns="http://www.w3.org/2000/svg"
type="button" viewBox="0 0 640 512"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm" ><path
>{$_("delete-team")}</button fill="currentColor"
> d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
{/if} /></svg
{/if} >
{#if !delete_triggered} </li>
<button <li class="flex items-center">
on:click={submit} <a class="mr-2" href="./">Teams</a><svg
disabled={!save_enabled} stroke="currentColor"
class:opacity-50={!save_enabled} fill="none"
type="button" stroke-width="2"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm" viewBox="0 0 24 24"
>{$_("save-changes")}</button stroke-linecap="round"
> stroke-linejoin="round"
{/if} class="h-3 w-3 mr-2 stroke-current"
</span> height="1em"
</div> width="1em"
<div class="flex flex-row mb-4"> xmlns="http://www.w3.org/2000/svg"
<div class="w-full"> ><line x1="5" y1="12" x2="19" y2="12" />
<nav class="w-full flex"> <polyline points="12 5 19 12 12 19" /></svg
<ol class="list-none flex flex-row items-center justify-start"> >
<li class="mr-2 flex items-center"> </li>
<svg <li class="flex items-center">
stroke="currentColor" <span class="mr-2">Team-Details #{params.teamid}</span>
fill="none" </li>
stroke-width="2" </ol>
viewBox="0 0 24 24" </nav>
stroke-linecap="round" </div>
stroke-linejoin="round" </div>
class="h-3 w-3 stroke-current" <div class="mb-8 text-3xl font-extrabold leading-tight">
height="1em" {#if group}
width="1em" {group.label}{" > "}
xmlns="http://www.w3.org/2000/svg" {/if}
><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" /> {original.name}
<polyline points="9 22 9 12 15 12 15 22" /></svg <span data-id="org_actions_${teamdata.id}">
> <GenerateSponsoringContracts
</li> bind:sponsoring_contracts_show
<li class="flex items-center"> bind:generate_teams
<a class="mr-2" href="/">Home</a><svg />
stroke="currentColor" <GenerateRunnerCards bind:cards_show bind:generate_teams />
fill="none" <GenerateRunnerCertificates
stroke-width="2" bind:certificates_show
viewBox="0 0 24 24" bind:generate_teams
stroke-linecap="round" />
stroke-linejoin="round" {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
class="h-3 w-3 mr-2 stroke-current" <button
height="1em" on:click={() => {
width="1em" import_modal_open = true;
xmlns="http://www.w3.org/2000/svg" }}
><line x1="5" y1="12" x2="19" y2="12" /> type="button"
<polyline points="12 5 19 12 12 19" /></svg class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm"
> >
</li> {$_("import-runners")}
<li class="mr-2 flex items-center"> </button>
<svg {/if}
class="flex-shrink-0 w-5 h-5 mr-2" {#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")}
fill="currentColor" {#if delete_triggered}
width="24" <button
height="24" on:click={deleteTeam}
xmlns="http://www.w3.org/2000/svg" class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm"
viewBox="0 0 640 512" >{$_("confirm-delete")}</button
><path >
fill="currentColor" <button
d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" on:click={() => {
/></svg delete_triggered = !delete_triggered;
> }}
</li> class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
<li class="flex items-center"> >{$_("cancel")}</button
<a class="mr-2" href="./">Teams</a><svg >
stroke="currentColor" {/if}
fill="none" {#if !delete_triggered}
stroke-width="2" <button
viewBox="0 0 24 24" on:click={() => {
stroke-linecap="round" delete_triggered = true;
stroke-linejoin="round" }}
class="h-3 w-3 mr-2 stroke-current" type="button"
height="1em" class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm"
width="1em" >{$_("delete-team")}</button
xmlns="http://www.w3.org/2000/svg" >
><line x1="5" y1="12" x2="19" y2="12" /> {/if}
<polyline points="12 5 19 12 12 19" /></svg {/if}
> {#if !delete_triggered}
</li> <button
<li class="flex items-center"> on:click={submit}
<span class="mr-2">Team-Details #{params.teamid}</span> disabled={!save_enabled}
</li> class:opacity-50={!save_enabled}
</ol> type="button"
</nav> class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm"
</div> >{$_("save-changes")}</button
</div> >
<div class="text-sm w-full"> {/if}
<label for="name" class="font-medium text-gray-700">Name</label> </span>
<input </div>
autocomplete="off" <div class="text-sm w-full">
placeholder="Name" <label for="name" class="font-medium text-gray-700">Name</label>
type="text" <input
bind:value={teamdata.name} autocomplete="off"
name="name" placeholder="Name"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" type="text"
/> bind:value={teamdata.name}
</div> name="name"
<div class="text-sm w-full"> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
<label for="contact" class="font-medium text-gray-700" />
>{$_("contact")}</label </div>
> <div class="text-sm w-full">
<Select <label for="contact" class="font-medium text-gray-700"
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" >{$_("contact")}</label
itemFilter={(label, filterText, option) => >
label.toLowerCase().includes(filterText.toLowerCase()) || <Select
option.value.id.toString().startsWith(filterText.toLowerCase())} containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
items={contacts} itemFilter={(label, filterText, option) =>
showChevron={true} label.toLowerCase().includes(filterText.toLowerCase()) ||
placeholder={$_("no-contact-selected")} option.value.id.toString().startsWith(filterText.toLowerCase())}
noOptionsMessage={$_("no-contact-found")} items={contacts}
bind:selectedValue={contact} showChevron={true}
on:select={(selectedValue) => placeholder={$_("no-contact-selected")}
(teamdata.contact = selectedValue.detail.value)} noOptionsMessage={$_("no-contact-found")}
on:clear={() => (teamdata.contact = null)} bind:selectedValue={contact}
/> on:select={(selectedValue) =>
</div> (teamdata.contact = selectedValue.detail.value)}
<div class="text-sm w-full"> on:clear={() => (teamdata.contact = null)}
<label for="org" class="font-medium text-gray-700" />
>{$_("organization")}</label </div>
> <div class="text-sm w-full">
<Select <label for="org" class="font-medium text-gray-700"
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" >{$_("organization")}</label
itemFilter={(label, filterText, option) => >
label.toLowerCase().includes(filterText.toLowerCase()) || <Select
option.id.value.toString().startsWith(filterText.toLowerCase())} containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
items={orgs} itemFilter={(label, filterText, option) =>
showChevron={true} label.toLowerCase().includes(filterText.toLowerCase()) ||
placeholder={$_("search-for-an-organization-by-name-or-id")} option.id.value.toString().startsWith(filterText.toLowerCase())}
noOptionsMessage={$_("no-organizations-found")} items={orgs}
bind:selectedValue={group} showChevron={true}
on:select={(selectedValue) => placeholder={$_("search-for-an-organization-by-name-or-id")}
(teamdata.parentGroup = selectedValue.detail.value)} noOptionsMessage={$_("no-organizations-found")}
on:clear={() => (teamdata.parentGroup = null)} bind:selectedValue={group}
/> on:select={(selectedValue) =>
</div> (teamdata.parentGroup = selectedValue.detail.value)}
<div class="text-sm w-full"> on:clear={() => (teamdata.parentGroup = null)}
<span class="font-medium text-gray-700">{$_("distance")}</span> />
<br /> </div>
<span class="text-gray-700" <div class="text-sm w-full">
>{(original.total_distance / 1000).toFixed(2)} km</span <span class="font-medium text-gray-700">{$_("distance")}</span>
> <br />
</div> <span class="text-gray-700"
</section> >{(original.total_distance / 1000).toFixed(2)} km</span
>
</div>
</section>
{:else} {:else}
{#await promise} {#await promise}
{$_("team-detail-is-being-loaded")} {$_("team-detail-is-being-loaded")}
{:catch error} {:catch error}
<PromiseError /> <PromiseError />
{/await} {/await}
{/if} {/if}