add: UserEditForm
This commit is contained in:
577
frontend/src/lib/components/UserEditForm.svelte
Normal file
577
frontend/src/lib/components/UserEditForm.svelte
Normal file
@@ -0,0 +1,577 @@
|
|||||||
|
<script>
|
||||||
|
import InputField from "$lib/components/InputField.svelte";
|
||||||
|
import SmallLoader from "$lib/components/SmallLoader.svelte";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { applyAction, enhance } from "$app/forms";
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import { receive, send } from "$lib/utils/helpers";
|
||||||
|
import { t } from "svelte-i18n";
|
||||||
|
import { fly } from "svelte/transition";
|
||||||
|
|
||||||
|
/** @type {import('../../routes/auth/about/[id]/$types').ActionData} */
|
||||||
|
export let form;
|
||||||
|
|
||||||
|
/** @type {App.Locals['subscriptions']}*/
|
||||||
|
export let subscriptions;
|
||||||
|
|
||||||
|
/** @type {App.Locals['user']}*/
|
||||||
|
export let user;
|
||||||
|
|
||||||
|
/** @type {App.Locals['licence_categories']} */
|
||||||
|
export let licence_categories;
|
||||||
|
|
||||||
|
const userStatusOptions = [
|
||||||
|
{ value: 1, label: $t("userStatus.1"), color: "#b1b1b1" }, // Grey for "Nicht verifiziert"
|
||||||
|
{ value: 2, label: $t("userStatus.2"), color: "#90EE90" }, // Light green for "Verifiziert"
|
||||||
|
{ value: 3, label: $t("userStatus.3"), color: "#00bc00" }, // Green for "Aktiv"
|
||||||
|
{ value: 4, label: $t("userStatus.4"), color: "#FFC0CB" }, // Pink for "Passiv"
|
||||||
|
{ value: 5, label: $t("userStatus.5"), color: "#FF4646" }, // Red for "Deaktiviert"
|
||||||
|
];
|
||||||
|
|
||||||
|
const userRoleOptions = [
|
||||||
|
{ value: 0, label: $t("userRole.0"), color: "#b1b1b1" }, // Grey for "Mitglied"
|
||||||
|
{ value: 1, label: $t("userRole.1"), color: "#00bc00" }, // Green for "Betrachter"
|
||||||
|
{ value: 4, label: $t("userRole.4"), color: "#FFC0CB" }, // Pink for "Bearbeiter"
|
||||||
|
{ value: 8, label: $t("userRole.8"), color: "#FF4646" }, // Red for "Admin"
|
||||||
|
];
|
||||||
|
const membershipStatusOptions = [
|
||||||
|
{ value: 3, label: $t("userStatus.3"), color: "#00bc00" }, // Green for "Aktiv"
|
||||||
|
{ value: 4, label: $t("userStatus.4"), color: "#FFC0CB" }, // Pink for "Passiv"
|
||||||
|
{ value: 5, label: $t("userStatus.5"), color: "#FF4646" }, // Red for "Deaktiviert"
|
||||||
|
];
|
||||||
|
const licenceStatusOptions = [
|
||||||
|
{ value: 1, label: $t("userStatus.1"), color: "#b1b1b1" }, // Grey for "Nicht verifiziert"
|
||||||
|
{ value: 3, label: $t("userStatus.3"), color: "#00bc00" }, // Green for "Aktiv"
|
||||||
|
{ value: 4, label: $t("userStatus.4"), color: "#FFC0CB" }, // Pink for "Passiv"
|
||||||
|
{ value: 5, label: $t("userStatus.5"), color: "#FF4646" }, // Red for "Deaktiviert"
|
||||||
|
];
|
||||||
|
|
||||||
|
const TABS = ["profile", "licence", "membership", "bankaccount"];
|
||||||
|
let activeTab = TABS[0];
|
||||||
|
|
||||||
|
let isUpdating = false,
|
||||||
|
password = "",
|
||||||
|
password2 = "";
|
||||||
|
|
||||||
|
/** @type {Object.<string, App.Locals['licence_categories']>} */
|
||||||
|
$: groupedCategories = groupCategories(licence_categories);
|
||||||
|
$: subscriptionModelOptions = subscriptions.map((sub) => ({
|
||||||
|
value: sub?.name ?? "",
|
||||||
|
label: sub?.name ?? "",
|
||||||
|
}));
|
||||||
|
$: selectedSubscriptionModel =
|
||||||
|
subscriptions.find(
|
||||||
|
(sub) => sub?.id === user.membership?.subscription_model.id
|
||||||
|
) || null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates groups of categories depending on the first letter
|
||||||
|
* @param {App.Locals['licence_categories']} categories - the categories to sort and group
|
||||||
|
* @returns {Object.<string, App.Locals['licence_categories']>} Grouped categories
|
||||||
|
*/
|
||||||
|
function groupCategories(categories) {
|
||||||
|
return Object.entries(categories)
|
||||||
|
.sort((a, b) => a[1].category.localeCompare(b[1].category))
|
||||||
|
.reduce(
|
||||||
|
(
|
||||||
|
/** @type {Object.<string, App.Locals['licence_categories']>} */ acc,
|
||||||
|
[_, category]
|
||||||
|
) => {
|
||||||
|
const firstLetter = category.category[0];
|
||||||
|
if (!acc[firstLetter]) {
|
||||||
|
acc[firstLetter] = [];
|
||||||
|
}
|
||||||
|
acc[firstLetter].push(category);
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
console.dir(user);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the active tab
|
||||||
|
* @param {string} tab - The tab to set as active
|
||||||
|
*/
|
||||||
|
function setActiveTab(tab) {
|
||||||
|
activeTab = tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {import('../../routes/auth/about/[id]/$types').SubmitFunction} */
|
||||||
|
const handleUpdate = async ({ form, formData, action, cancel }) => {
|
||||||
|
isUpdating = true;
|
||||||
|
return async ({ result }) => {
|
||||||
|
isUpdating = false;
|
||||||
|
if (result.type === "success" || result.type === "redirect") {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
await applyAction(result);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form
|
||||||
|
class="content"
|
||||||
|
action="?/updateUser"
|
||||||
|
method="POST"
|
||||||
|
use:enhance={handleUpdate}
|
||||||
|
>
|
||||||
|
<input name="id" type="number" hidden bind:value={user.id} />
|
||||||
|
<h1 class="step-title" style="text-align: center;">{$t("user_edit")}</h1>
|
||||||
|
{#if form?.success}
|
||||||
|
<h4
|
||||||
|
class="step-subtitle warning"
|
||||||
|
in:receive={{ key: Math.floor(Math.random() * 100) }}
|
||||||
|
out:send={{ key: Math.floor(Math.random() * 100) }}
|
||||||
|
>
|
||||||
|
Um einen fehlerhaften upload Ihres Bildes zu vermeiden, clicke bitte auf
|
||||||
|
den "Update" Button unten.
|
||||||
|
</h4>
|
||||||
|
{/if}
|
||||||
|
{#if form?.errors}
|
||||||
|
{#each form?.errors as error (error.id)}
|
||||||
|
<h4
|
||||||
|
class="step-subtitle warning"
|
||||||
|
in:receive={{ key: error.id }}
|
||||||
|
out:send={{ key: error.id }}
|
||||||
|
>
|
||||||
|
{$t(error.field) + ": " + $t(error.key)}
|
||||||
|
</h4>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
hidden
|
||||||
|
name="profile_picture"
|
||||||
|
bind:value={user.profile_picture}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
{#each TABS as tab}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="button-dark"
|
||||||
|
class:active={activeTab === tab}
|
||||||
|
on:click={() => setActiveTab(tab)}
|
||||||
|
>
|
||||||
|
{$t(tab)}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tab-content"
|
||||||
|
style="display: {activeTab === 'profile' ? 'block' : 'none'}"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
name="status"
|
||||||
|
type="select"
|
||||||
|
label={$t("status")}
|
||||||
|
bind:value={user.status}
|
||||||
|
options={userStatusOptions}
|
||||||
|
/>
|
||||||
|
{#if user.role_id === 8}
|
||||||
|
<InputField
|
||||||
|
name="role_id"
|
||||||
|
type="select"
|
||||||
|
label={$t("user_role")}
|
||||||
|
bind:value={user.role_id}
|
||||||
|
options={userRoleOptions}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
<InputField
|
||||||
|
name="password"
|
||||||
|
type="password"
|
||||||
|
label={$t("password")}
|
||||||
|
placeholder={$t("placeholder.password")}
|
||||||
|
bind:value={password}
|
||||||
|
otherPasswordValue={password2}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="password2"
|
||||||
|
type="password"
|
||||||
|
label={$t("password_repeat")}
|
||||||
|
placeholder={$t("placeholder.password")}
|
||||||
|
bind:value={password2}
|
||||||
|
otherPasswordValue={password}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="first_name"
|
||||||
|
label={$t("first_name")}
|
||||||
|
bind:value={user.first_name}
|
||||||
|
placeholder={$t("placeholder.first_name")}
|
||||||
|
required={true}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="last_name"
|
||||||
|
label={$t("last_name")}
|
||||||
|
bind:value={user.last_name}
|
||||||
|
placeholder={$t("placeholder.last_name")}
|
||||||
|
required={true}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="company"
|
||||||
|
label={$t("company")}
|
||||||
|
bind:value={user.company}
|
||||||
|
placeholder={$t("placeholder.company")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="email"
|
||||||
|
type="email"
|
||||||
|
label={$t("email")}
|
||||||
|
bind:value={user.email}
|
||||||
|
placeholder={$t("placeholder.email")}
|
||||||
|
required={true}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="phone"
|
||||||
|
type="tel"
|
||||||
|
label={$t("phone")}
|
||||||
|
bind:value={user.phone}
|
||||||
|
placeholder={$t("placeholder.phone")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="birth_date"
|
||||||
|
type="date"
|
||||||
|
label={$t("birth_date")}
|
||||||
|
bind:value={user.date_of_birth}
|
||||||
|
placeholder={$t("placeholder.birth_date")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="address"
|
||||||
|
label={$t("address")}
|
||||||
|
bind:value={user.address}
|
||||||
|
placeholder={$t("placeholder.address")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="zip_code"
|
||||||
|
label={$t("zip_code")}
|
||||||
|
bind:value={user.zip_code}
|
||||||
|
placeholder={$t("placeholder.zip_code")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="city"
|
||||||
|
label={$t("city")}
|
||||||
|
bind:value={user.city}
|
||||||
|
placeholder={$t("placeholder.city")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="notes"
|
||||||
|
type="textarea"
|
||||||
|
label={$t("notes")}
|
||||||
|
bind:value={user.notes}
|
||||||
|
placeholder={$t("placeholder.notes", {
|
||||||
|
values: { name: user.first_name || "" },
|
||||||
|
})}
|
||||||
|
rows={10}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tab-content"
|
||||||
|
style="display: {activeTab === 'licence' ? 'block' : 'none'}"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
name="licence_status"
|
||||||
|
type="select"
|
||||||
|
label={$t("status")}
|
||||||
|
bind:value={user.drivers_licence.status}
|
||||||
|
options={licenceStatusOptions}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="licence_number"
|
||||||
|
type="text"
|
||||||
|
label={$t("licence_number")}
|
||||||
|
bind:value={user.drivers_licence.licence_number}
|
||||||
|
placeholder={$t("placeholder.licence_number")}
|
||||||
|
toUpperCase={true}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="issued_date"
|
||||||
|
type="date"
|
||||||
|
label={$t("issued_date")}
|
||||||
|
bind:value={user.drivers_licence.issued_date}
|
||||||
|
placeholder={$t("placeholder.issued_date")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="expiration_date"
|
||||||
|
type="date"
|
||||||
|
label={$t("expiration_date")}
|
||||||
|
bind:value={user.drivers_licence.expiration_date}
|
||||||
|
placeholder={$t("placeholder.expiration_date")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="country"
|
||||||
|
label={$t("country")}
|
||||||
|
bind:value={user.drivers_licence.country}
|
||||||
|
placeholder={$t("placeholder.issuing_country")}
|
||||||
|
/>
|
||||||
|
<div class="licence-categories">
|
||||||
|
<h3>{$t("licence_categories")}</h3>
|
||||||
|
<div class="checkbox-grid">
|
||||||
|
{#each Object.entries(groupedCategories) as [group, categories], groupIndex}
|
||||||
|
{#if groupIndex > 0}
|
||||||
|
<div class="category-break" />
|
||||||
|
{/if}
|
||||||
|
{#each categories as category}
|
||||||
|
<div class="checkbox-item">
|
||||||
|
<div class="checkbox-label-container">
|
||||||
|
<InputField
|
||||||
|
type="checkbox"
|
||||||
|
name="licence_categories[]"
|
||||||
|
value={JSON.stringify(category)}
|
||||||
|
label={category.category}
|
||||||
|
checked={user.drivers_licence.licence_categories != null &&
|
||||||
|
user.drivers_licence.licence_categories.some(
|
||||||
|
(cat) => cat.category === category.category
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span class="checkbox-description">
|
||||||
|
{$t(`licenceCategory.${category.category}`)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tab-content"
|
||||||
|
style="display: {activeTab === 'membership' ? 'block' : 'none'}"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
name="membership_status"
|
||||||
|
type="select"
|
||||||
|
label={$t("status")}
|
||||||
|
bind:value={user.membership.status}
|
||||||
|
options={membershipStatusOptions}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="subscription_model_name"
|
||||||
|
type="select"
|
||||||
|
label={$t("subscription_model")}
|
||||||
|
bind:value={user.membership.subscription_model.name}
|
||||||
|
options={subscriptionModelOptions}
|
||||||
|
/>
|
||||||
|
<div class="subscription-info">
|
||||||
|
<div class="subscription-column">
|
||||||
|
<p>
|
||||||
|
<strong>{$t("monthly_fee")}:</strong>
|
||||||
|
{selectedSubscriptionModel?.monthly_fee || "-"}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>{$t("hourly_rate")}:</strong>
|
||||||
|
{selectedSubscriptionModel?.hourly_rate || "-"}
|
||||||
|
</p>
|
||||||
|
{#if selectedSubscriptionModel?.included_hours_per_year}
|
||||||
|
<p>
|
||||||
|
<strong>{$t("included_hours_per_year")}:</strong>
|
||||||
|
{selectedSubscriptionModel?.included_hours_per_year}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
{#if selectedSubscriptionModel?.included_hours_per_month}
|
||||||
|
<p>
|
||||||
|
<strong>{$t("included_hours_per_month")}:</strong>
|
||||||
|
{selectedSubscriptionModel?.included_hours_per_month}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="subscription-column">
|
||||||
|
<p>
|
||||||
|
<strong>{$t("details")}:</strong>
|
||||||
|
{selectedSubscriptionModel?.details || "-"}
|
||||||
|
</p>
|
||||||
|
{#if selectedSubscriptionModel?.conditions}
|
||||||
|
<p>
|
||||||
|
<strong>{$t("conditions")}:</strong>
|
||||||
|
{selectedSubscriptionModel?.conditions}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<InputField
|
||||||
|
name="membership_start_date"
|
||||||
|
type="date"
|
||||||
|
label={$t("start")}
|
||||||
|
bind:value={user.membership.start_date}
|
||||||
|
placeholder={$t("placeholder.start_date")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="membership_end_date"
|
||||||
|
type="date"
|
||||||
|
label={$t("end")}
|
||||||
|
bind:value={user.membership.end_date}
|
||||||
|
placeholder={$t("placeholder.end_date")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="parent_member_id"
|
||||||
|
type="number"
|
||||||
|
label={$t("parent_member_id")}
|
||||||
|
bind:value={user.membership.parent_member_id}
|
||||||
|
placeholder={$t("placeholder.parent_member_id")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tab-content"
|
||||||
|
style="display: {activeTab === 'bankaccount' ? 'block' : 'none'}"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
name="account_holder_name"
|
||||||
|
label={$t("bank_account_holder")}
|
||||||
|
bind:value={user.bank_account.account_holder_name}
|
||||||
|
placeholder={$t("placeholder.bank_account_holder")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="bank"
|
||||||
|
label={$t("bank_name")}
|
||||||
|
bind:value={user.bank_account.bank}
|
||||||
|
placeholder={$t("placeholder.bank_name")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="iban"
|
||||||
|
label={$t("iban")}
|
||||||
|
bind:value={user.bank_account.iban}
|
||||||
|
placeholder={$t("placeholder.iban")}
|
||||||
|
toUpperCase={true}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="bic"
|
||||||
|
label={$t("bic")}
|
||||||
|
bind:value={user.bank_account.bic}
|
||||||
|
placeholder={$t("placeholder.bic")}
|
||||||
|
toUpperCase={true}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="mandate_reference"
|
||||||
|
label={$t("mandate_reference")}
|
||||||
|
bind:value={user.bank_account.mandate_reference}
|
||||||
|
placeholder={$t("placeholder.mandate_reference")}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="mandate_date_signed"
|
||||||
|
label={$t("mandate_date_signed")}
|
||||||
|
type="date"
|
||||||
|
bind:value={user.bank_account.mandate_date_signed}
|
||||||
|
readonly={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="button-container">
|
||||||
|
{#if isUpdating}
|
||||||
|
<SmallLoader width={30} message={"Aktualisiere..."} />
|
||||||
|
{:else}
|
||||||
|
<button type="button" class="button-dark" on:click={close}>
|
||||||
|
{$t("cancel")}</button
|
||||||
|
>
|
||||||
|
<button type="submit" class="button-dark">{$t("confirm")}</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.category-break {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
height: 1px;
|
||||||
|
background-color: #ccc;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 20%;
|
||||||
|
width: 60%;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.licence-categories {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label-container {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 4em;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-description {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #9b9b9b;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.checkbox-grid {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.checkbox-item {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-description {
|
||||||
|
margin-left: 24px;
|
||||||
|
margin-top: 5px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.subscription-info {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscription-column {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscription-column p {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscription-column strong {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
.tab-content {
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 0 0 3px 3px;
|
||||||
|
}
|
||||||
|
.button-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container button {
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-width: 120px;
|
||||||
|
max-width: calc(50%-5px);
|
||||||
|
}
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.button-container button {
|
||||||
|
flex-basis: 100%;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import ImageInput from "$lib/components/ImageInput.svelte";
|
|
||||||
import InputField from "$lib/components/InputField.svelte";
|
|
||||||
import SmallLoader from "$lib/components/SmallLoader.svelte";
|
import SmallLoader from "$lib/components/SmallLoader.svelte";
|
||||||
import Modal from "$lib/components/Modal.svelte";
|
import Modal from "$lib/components/Modal.svelte";
|
||||||
import Avatar from "$lib/img/TeamAvatar.jpeg";
|
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { applyAction, enhance } from "$app/forms";
|
import { applyAction, enhance } from "$app/forms";
|
||||||
import { page } from "$app/stores";
|
import { page } from "$app/stores";
|
||||||
import { receive, send } from "$lib/utils/helpers";
|
import { receive, send } from "$lib/utils/helpers";
|
||||||
import { t } from "svelte-i18n";
|
import { t } from "svelte-i18n";
|
||||||
import { fly } from "svelte/transition";
|
import { fly } from "svelte/transition";
|
||||||
|
import UserEditForm from "$lib/components/UserEditForm.svelte";
|
||||||
|
|
||||||
/** @type {import('./$types').ActionData} */
|
/** @type {import('./$types').ActionData} */
|
||||||
export let form;
|
export let form;
|
||||||
@@ -20,83 +18,10 @@
|
|||||||
/** @type {App.Locals['user']}*/
|
/** @type {App.Locals['user']}*/
|
||||||
$: user = $page.data.user;
|
$: user = $page.data.user;
|
||||||
|
|
||||||
/**
|
|
||||||
* creates groups of categories depending on the first letter
|
|
||||||
* @param {App.Locals['licence_categories']} categories - the categories to sort and group
|
|
||||||
* @returns {Object.<string, App.Locals['licence_categories']>} Grouped categories
|
|
||||||
*/
|
|
||||||
function groupCategories(categories) {
|
|
||||||
return Object.entries(categories)
|
|
||||||
.sort((a, b) => a[1].category.localeCompare(b[1].category))
|
|
||||||
.reduce(
|
|
||||||
(
|
|
||||||
/** @type {Object.<string, App.Locals['licence_categories']>} */ acc,
|
|
||||||
[_, category]
|
|
||||||
) => {
|
|
||||||
const firstLetter = category.category[0];
|
|
||||||
if (!acc[firstLetter]) {
|
|
||||||
acc[firstLetter] = [];
|
|
||||||
}
|
|
||||||
acc[firstLetter].push(category);
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {App.Locals['licence_categories']} */
|
/** @type {App.Locals['licence_categories']} */
|
||||||
$: licence_categories = $page.data.licence_categories;
|
$: licence_categories = $page.data.licence_categories;
|
||||||
|
|
||||||
/** @type {Object.<string, App.Locals['licence_categories']>} */
|
let showModal = false;
|
||||||
$: groupedCategories = groupCategories(licence_categories);
|
|
||||||
|
|
||||||
// /** @typedef {{name: string, src: string}} Avatar */
|
|
||||||
// const avatarFiles = import.meta.glob("$lib/img/Avatar-*.jpeg", {
|
|
||||||
// eager: true,
|
|
||||||
// });
|
|
||||||
// /** @type{Avatar[]} */
|
|
||||||
// let avatars = [];
|
|
||||||
|
|
||||||
const TABS = ["profile", "licence", "membership", "bankaccount"];
|
|
||||||
let activeTab = TABS[0];
|
|
||||||
|
|
||||||
$: subscriptionModelOptions = subscriptions.map((sub) => ({
|
|
||||||
value: sub?.name ?? "",
|
|
||||||
label: sub?.name ?? "",
|
|
||||||
}));
|
|
||||||
|
|
||||||
const userStatusOptions = [
|
|
||||||
{ value: 1, label: $t("userStatus.1"), color: "#b1b1b1" }, // Grey for "Nicht verifiziert"
|
|
||||||
{ value: 2, label: $t("userStatus.2"), color: "#90EE90" }, // Light green for "Verifiziert"
|
|
||||||
{ value: 3, label: $t("userStatus.3"), color: "#00bc00" }, // Green for "Aktiv"
|
|
||||||
{ value: 4, label: $t("userStatus.4"), color: "#FFC0CB" }, // Pink for "Passiv"
|
|
||||||
{ value: 5, label: $t("userStatus.5"), color: "#FF4646" }, // Red for "Deaktiviert"
|
|
||||||
];
|
|
||||||
|
|
||||||
const userRoleOptions = [
|
|
||||||
{ value: 0, label: $t("userRole.0"), color: "#b1b1b1" }, // Grey for "Mitglied"
|
|
||||||
{ value: 1, label: $t("userRole.1"), color: "#00bc00" }, // Green for "Betrachter"
|
|
||||||
{ value: 4, label: $t("userRole.4"), color: "#FFC0CB" }, // Pink for "Bearbeiter"
|
|
||||||
{ value: 8, label: $t("userRole.8"), color: "#FF4646" }, // Red for "Admin"
|
|
||||||
];
|
|
||||||
const membershipStatusOptions = [
|
|
||||||
{ value: 3, label: $t("userStatus.3"), color: "#00bc00" }, // Green for "Aktiv"
|
|
||||||
{ value: 4, label: $t("userStatus.4"), color: "#FFC0CB" }, // Pink for "Passiv"
|
|
||||||
{ value: 5, label: $t("userStatus.5"), color: "#FF4646" }, // Red for "Deaktiviert"
|
|
||||||
];
|
|
||||||
const licenceStatusOptions = [
|
|
||||||
{ value: 1, label: $t("userStatus.1"), color: "#b1b1b1" }, // Grey for "Nicht verifiziert"
|
|
||||||
{ value: 3, label: $t("userStatus.3"), color: "#00bc00" }, // Green for "Aktiv"
|
|
||||||
{ value: 4, label: $t("userStatus.4"), color: "#FFC0CB" }, // Pink for "Passiv"
|
|
||||||
{ value: 5, label: $t("userStatus.5"), color: "#FF4646" }, // Red for "Deaktiviert"
|
|
||||||
];
|
|
||||||
|
|
||||||
let showModal = false,
|
|
||||||
isUploading = false,
|
|
||||||
isUpdating = false,
|
|
||||||
// showAvatars = false,
|
|
||||||
password = "",
|
|
||||||
password2 = "";
|
|
||||||
|
|
||||||
const open = () => (showModal = true);
|
const open = () => (showModal = true);
|
||||||
const close = () => {
|
const close = () => {
|
||||||
@@ -105,38 +30,10 @@
|
|||||||
form.errors = undefined;
|
form.errors = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// const toggleAvatars = () => (showAvatars = !showAvatars);
|
|
||||||
|
|
||||||
$: selectedSubscriptionModel =
|
|
||||||
subscriptions.find(
|
|
||||||
(sub) => sub?.id === user.membership?.subscription_model.id
|
|
||||||
) || null;
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
console.dir(user);
|
console.dir(user);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the active tab
|
|
||||||
* @param {string} tab - The tab to set as active
|
|
||||||
*/
|
|
||||||
function setActiveTab(tab) {
|
|
||||||
activeTab = tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {import('./$types').SubmitFunction} */
|
|
||||||
const handleUpdate = async ({ form, formData, action, cancel }) => {
|
|
||||||
isUpdating = true;
|
|
||||||
return async ({ result }) => {
|
|
||||||
isUpdating = false;
|
|
||||||
if (result.type === "success" || result.type === "redirect") {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
await applyAction(result);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @type {import('./$types').SubmitFunction} */
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="hero-container">
|
<div class="hero-container">
|
||||||
@@ -202,363 +99,13 @@
|
|||||||
|
|
||||||
{#if showModal}
|
{#if showModal}
|
||||||
<Modal on:close={close}>
|
<Modal on:close={close}>
|
||||||
<form
|
<UserEditForm
|
||||||
class="content"
|
{form}
|
||||||
action="?/updateUser"
|
{user}
|
||||||
method="POST"
|
{subscriptions}
|
||||||
use:enhance={handleUpdate}
|
{licence_categories}
|
||||||
>
|
on:cancel={close}
|
||||||
<input name="id" type="number" hidden bind:value={user.id} />
|
|
||||||
<h1 class="step-title" style="text-align: center;">{$t("user_edit")}</h1>
|
|
||||||
{#if form?.success}
|
|
||||||
<h4
|
|
||||||
class="step-subtitle warning"
|
|
||||||
in:receive={{ key: Math.floor(Math.random() * 100) }}
|
|
||||||
out:send={{ key: Math.floor(Math.random() * 100) }}
|
|
||||||
>
|
|
||||||
Um einen fehlerhaften upload Ihres Bildes zu vermeiden, clicke bitte
|
|
||||||
auf den "Update" Button unten.
|
|
||||||
</h4>
|
|
||||||
{/if}
|
|
||||||
{#if form?.errors}
|
|
||||||
{#each form?.errors as error (error.id)}
|
|
||||||
<h4
|
|
||||||
class="step-subtitle warning"
|
|
||||||
in:receive={{ key: error.id }}
|
|
||||||
out:send={{ key: error.id }}
|
|
||||||
>
|
|
||||||
{$t(error.field) + ": " + $t(error.key)}
|
|
||||||
</h4>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
hidden
|
|
||||||
name="profile_picture"
|
|
||||||
bind:value={user.profile_picture}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="button-container">
|
|
||||||
{#each TABS as tab}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="button-dark"
|
|
||||||
class:active={activeTab === tab}
|
|
||||||
on:click={() => setActiveTab(tab)}
|
|
||||||
>
|
|
||||||
{$t(tab)}
|
|
||||||
</button>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="tab-content"
|
|
||||||
style="display: {activeTab === 'profile' ? 'block' : 'none'}"
|
|
||||||
>
|
|
||||||
<InputField
|
|
||||||
name="status"
|
|
||||||
type="select"
|
|
||||||
label={$t("status")}
|
|
||||||
bind:value={user.status}
|
|
||||||
options={userStatusOptions}
|
|
||||||
/>
|
|
||||||
{#if user.role_id === 8}
|
|
||||||
<InputField
|
|
||||||
name="role_id"
|
|
||||||
type="select"
|
|
||||||
label={$t("user_role")}
|
|
||||||
bind:value={user.role_id}
|
|
||||||
options={userRoleOptions}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
<InputField
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
label={$t("password")}
|
|
||||||
placeholder={$t("placeholder.password")}
|
|
||||||
bind:value={password}
|
|
||||||
otherPasswordValue={password2}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="password2"
|
|
||||||
type="password"
|
|
||||||
label={$t("password_repeat")}
|
|
||||||
placeholder={$t("placeholder.password")}
|
|
||||||
bind:value={password2}
|
|
||||||
otherPasswordValue={password}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="first_name"
|
|
||||||
label={$t("first_name")}
|
|
||||||
bind:value={user.first_name}
|
|
||||||
placeholder={$t("placeholder.first_name")}
|
|
||||||
required={true}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="last_name"
|
|
||||||
label={$t("last_name")}
|
|
||||||
bind:value={user.last_name}
|
|
||||||
placeholder={$t("placeholder.last_name")}
|
|
||||||
required={true}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="company"
|
|
||||||
label={$t("company")}
|
|
||||||
bind:value={user.company}
|
|
||||||
placeholder={$t("placeholder.company")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="email"
|
|
||||||
type="email"
|
|
||||||
label={$t("email")}
|
|
||||||
bind:value={user.email}
|
|
||||||
placeholder={$t("placeholder.email")}
|
|
||||||
required={true}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="phone"
|
|
||||||
type="tel"
|
|
||||||
label={$t("phone")}
|
|
||||||
bind:value={user.phone}
|
|
||||||
placeholder={$t("placeholder.phone")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="birth_date"
|
|
||||||
type="date"
|
|
||||||
label={$t("birth_date")}
|
|
||||||
bind:value={user.date_of_birth}
|
|
||||||
placeholder={$t("placeholder.birth_date")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="address"
|
|
||||||
label={$t("address")}
|
|
||||||
bind:value={user.address}
|
|
||||||
placeholder={$t("placeholder.address")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="zip_code"
|
|
||||||
label={$t("zip_code")}
|
|
||||||
bind:value={user.zip_code}
|
|
||||||
placeholder={$t("placeholder.zip_code")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="city"
|
|
||||||
label={$t("city")}
|
|
||||||
bind:value={user.city}
|
|
||||||
placeholder={$t("placeholder.city")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="notes"
|
|
||||||
type="textarea"
|
|
||||||
label={$t("notes")}
|
|
||||||
bind:value={user.notes}
|
|
||||||
placeholder={$t("placeholder.notes", {
|
|
||||||
values: { name: user.first_name || "" },
|
|
||||||
})}
|
|
||||||
rows={10}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="tab-content"
|
|
||||||
style="display: {activeTab === 'licence' ? 'block' : 'none'}"
|
|
||||||
>
|
|
||||||
<InputField
|
|
||||||
name="licence_status"
|
|
||||||
type="select"
|
|
||||||
label={$t("status")}
|
|
||||||
bind:value={user.drivers_licence.status}
|
|
||||||
options={licenceStatusOptions}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="licence_number"
|
|
||||||
type="text"
|
|
||||||
label={$t("licence_number")}
|
|
||||||
bind:value={user.drivers_licence.licence_number}
|
|
||||||
placeholder={$t("placeholder.licence_number")}
|
|
||||||
toUpperCase={true}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="issued_date"
|
|
||||||
type="date"
|
|
||||||
label={$t("issued_date")}
|
|
||||||
bind:value={user.drivers_licence.issued_date}
|
|
||||||
placeholder={$t("placeholder.issued_date")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="expiration_date"
|
|
||||||
type="date"
|
|
||||||
label={$t("expiration_date")}
|
|
||||||
bind:value={user.drivers_licence.expiration_date}
|
|
||||||
placeholder={$t("placeholder.expiration_date")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="country"
|
|
||||||
label={$t("country")}
|
|
||||||
bind:value={user.drivers_licence.country}
|
|
||||||
placeholder={$t("placeholder.issuing_country")}
|
|
||||||
/>
|
|
||||||
<div class="licence-categories">
|
|
||||||
<h3>{$t("licence_categories")}</h3>
|
|
||||||
<div class="checkbox-grid">
|
|
||||||
{#each Object.entries(groupedCategories) as [group, categories], groupIndex}
|
|
||||||
{#if groupIndex > 0}
|
|
||||||
<div class="category-break" />
|
|
||||||
{/if}
|
|
||||||
{#each categories as category}
|
|
||||||
<div class="checkbox-item">
|
|
||||||
<div class="checkbox-label-container">
|
|
||||||
<InputField
|
|
||||||
type="checkbox"
|
|
||||||
name="licence_categories[]"
|
|
||||||
value={JSON.stringify(category)}
|
|
||||||
label={category.category}
|
|
||||||
checked={user.drivers_licence.licence_categories !=
|
|
||||||
null &&
|
|
||||||
user.drivers_licence.licence_categories.some(
|
|
||||||
(cat) => cat.category === category.category
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<span class="checkbox-description">
|
|
||||||
{$t(`licenceCategory.${category.category}`)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="tab-content"
|
|
||||||
style="display: {activeTab === 'membership' ? 'block' : 'none'}"
|
|
||||||
>
|
|
||||||
<InputField
|
|
||||||
name="membership_status"
|
|
||||||
type="select"
|
|
||||||
label={$t("status")}
|
|
||||||
bind:value={user.membership.status}
|
|
||||||
options={membershipStatusOptions}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="subscription_model_name"
|
|
||||||
type="select"
|
|
||||||
label={$t("subscription_model")}
|
|
||||||
bind:value={user.membership.subscription_model.name}
|
|
||||||
options={subscriptionModelOptions}
|
|
||||||
/>
|
|
||||||
<div class="subscription-info">
|
|
||||||
<div class="subscription-column">
|
|
||||||
<p>
|
|
||||||
<strong>{$t("monthly_fee")}:</strong>
|
|
||||||
{selectedSubscriptionModel?.monthly_fee || "-"}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>{$t("hourly_rate")}:</strong>
|
|
||||||
{selectedSubscriptionModel?.hourly_rate || "-"}
|
|
||||||
</p>
|
|
||||||
{#if selectedSubscriptionModel?.included_hours_per_year}
|
|
||||||
<p>
|
|
||||||
<strong>{$t("included_hours_per_year")}:</strong>
|
|
||||||
{selectedSubscriptionModel?.included_hours_per_year}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
{#if selectedSubscriptionModel?.included_hours_per_month}
|
|
||||||
<p>
|
|
||||||
<strong>{$t("included_hours_per_month")}:</strong>
|
|
||||||
{selectedSubscriptionModel?.included_hours_per_month}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div class="subscription-column">
|
|
||||||
<p>
|
|
||||||
<strong>{$t("details")}:</strong>
|
|
||||||
{selectedSubscriptionModel?.details || "-"}
|
|
||||||
</p>
|
|
||||||
{#if selectedSubscriptionModel?.conditions}
|
|
||||||
<p>
|
|
||||||
<strong>{$t("conditions")}:</strong>
|
|
||||||
{selectedSubscriptionModel?.conditions}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<InputField
|
|
||||||
name="membership_start_date"
|
|
||||||
type="date"
|
|
||||||
label={$t("start")}
|
|
||||||
bind:value={user.membership.start_date}
|
|
||||||
placeholder={$t("placeholder.start_date")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="membership_end_date"
|
|
||||||
type="date"
|
|
||||||
label={$t("end")}
|
|
||||||
bind:value={user.membership.end_date}
|
|
||||||
placeholder={$t("placeholder.end_date")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="parent_member_id"
|
|
||||||
type="number"
|
|
||||||
label={$t("parent_member_id")}
|
|
||||||
bind:value={user.membership.parent_member_id}
|
|
||||||
placeholder={$t("placeholder.parent_member_id")}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="tab-content"
|
|
||||||
style="display: {activeTab === 'bankaccount' ? 'block' : 'none'}"
|
|
||||||
>
|
|
||||||
<InputField
|
|
||||||
name="account_holder_name"
|
|
||||||
label={$t("bank_account_holder")}
|
|
||||||
bind:value={user.bank_account.account_holder_name}
|
|
||||||
placeholder={$t("placeholder.bank_account_holder")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="bank"
|
|
||||||
label={$t("bank_name")}
|
|
||||||
bind:value={user.bank_account.bank}
|
|
||||||
placeholder={$t("placeholder.bank_name")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="iban"
|
|
||||||
label={$t("iban")}
|
|
||||||
bind:value={user.bank_account.iban}
|
|
||||||
placeholder={$t("placeholder.iban")}
|
|
||||||
toUpperCase={true}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="bic"
|
|
||||||
label={$t("bic")}
|
|
||||||
bind:value={user.bank_account.bic}
|
|
||||||
placeholder={$t("placeholder.bic")}
|
|
||||||
toUpperCase={true}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="mandate_reference"
|
|
||||||
label={$t("mandate_reference")}
|
|
||||||
bind:value={user.bank_account.mandate_reference}
|
|
||||||
placeholder={$t("placeholder.mandate_reference")}
|
|
||||||
/>
|
|
||||||
<InputField
|
|
||||||
name="mandate_date_signed"
|
|
||||||
label={$t("mandate_date_signed")}
|
|
||||||
type="date"
|
|
||||||
bind:value={user.bank_account.mandate_date_signed}
|
|
||||||
readonly={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="button-container">
|
|
||||||
{#if isUpdating}
|
|
||||||
<SmallLoader width={30} message={"Aktualisiere..."} />
|
|
||||||
{:else}
|
|
||||||
<button type="button" class="button-dark" on:click={close}>
|
|
||||||
{$t("cancel")}</button
|
|
||||||
>
|
|
||||||
<button type="submit" class="button-dark">{$t("confirm")}</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -701,67 +248,6 @@
|
|||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .avatar-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.current-avatar {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 1rem;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-buttons button {
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-selection {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 10px;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-option {
|
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
|
||||||
padding: 0;
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: transform 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-option:hover,
|
|
||||||
.avatar-option:focus {
|
|
||||||
transform: scale(1.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-option img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 50%;
|
|
||||||
} */
|
|
||||||
.button-container {
|
.button-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
Reference in New Issue
Block a user