322 lines
14 KiB
Svelte
322 lines
14 KiB
Svelte
<script>
|
|
import { _ } from "svelte-i18n";
|
|
import isEmail from "validator/es/lib/isEmail";
|
|
import { MeService } from "@odit/lfk-client-js";
|
|
import Toastify from "toastify-js";
|
|
import ConfirmProfileDeletion from "./ConfirmProfileDeletion.svelte";
|
|
import PasswordStrength, {
|
|
password_strong_enough_and_equal,
|
|
} from "../auth/PasswordStrength.svelte";
|
|
$: data_loaded = false;
|
|
$: delete_triggered = false;
|
|
$: original_data = {};
|
|
$: editable = {};
|
|
$: modal_open = false;
|
|
$: password_change = "";
|
|
$: password_confirm = "";
|
|
$: changes_performed = !(
|
|
JSON.stringify(editable) === JSON.stringify(original_data)
|
|
);
|
|
$: save_enabled = changes_performed && isEmail(editable.email);
|
|
$: update_password_enabled = password_strong_enough_and_equal(
|
|
password_change,
|
|
password_confirm
|
|
);
|
|
const user_promise = MeService.meControllerGet().then((data) => {
|
|
data_loaded = true;
|
|
data.groups = data.groups.map((g) => g.id);
|
|
data.permissions = [0];
|
|
original_data = Object.assign(original_data, data);
|
|
editable = Object.assign(editable, original_data);
|
|
});
|
|
function submit() {
|
|
if (data_loaded === true && save_enabled) {
|
|
Toastify({
|
|
text: $_("updating-your-profile"),
|
|
duration: 2500,
|
|
}).showToast();
|
|
MeService.meControllerPut(editable)
|
|
.then((resp) => {
|
|
original_data = Object.assign(original_data, editable);
|
|
Toastify({
|
|
text: $_("profile-updated"),
|
|
duration: 2500,
|
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
|
}).showToast();
|
|
})
|
|
.catch((err) => {});
|
|
}
|
|
}
|
|
function changePassword() {
|
|
if (data_loaded === true && update_password_enabled) {
|
|
Toastify({
|
|
text: $_("changing-your-password"),
|
|
duration: 2500,
|
|
}).showToast();
|
|
let postdata = Object.assign({}, original_data);
|
|
postdata.password = password_confirm;
|
|
MeService.meControllerPut(postdata)
|
|
.then((resp) => {
|
|
password_confirm = "";
|
|
password_change = "";
|
|
postdata = {};
|
|
Toastify({
|
|
text: $_("password-changed"),
|
|
duration: 2500,
|
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
|
}).showToast();
|
|
setTimeout(() => {
|
|
location.replace("./");
|
|
}, 500);
|
|
})
|
|
.catch((err) => {});
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<ConfirmProfileDeletion bind:modal_open bind:delete_triggered />
|
|
<div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12">
|
|
<div class="text-center mb-8">
|
|
<h1
|
|
class="mt-9 font-display text-4xl leading-none font-semibold text-white sm:text-5xl lg:text-6xl">
|
|
🔨<br />{$_('settings')}
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
<div class="pt-0 pb-16 bg-gray-50 overflow-hidden lg:pt-12 lg:py-24">
|
|
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
|
<div>
|
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
|
<div class="md:col-span-1">
|
|
<div class="px-4 sm:px-0">
|
|
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
|
{$_('profile')}
|
|
</h3>
|
|
<p class="mt-1 text-sm text-gray-600">
|
|
{$_('everything-concerning-your-profile')}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
{#await user_promise}
|
|
{$_('loading-profile-data')}
|
|
{:then}
|
|
<div class="mt-5 md:mt-0 md:col-span-2">
|
|
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
|
<div class="px-4 py-5 bg-white space-y-6 sm:p-6">
|
|
<div>
|
|
<!-- svelte-ignore a11y-label-has-associated-control -->
|
|
<label class="block text-sm font-medium text-gray-700">
|
|
{$_('profile-picture')}
|
|
</label>
|
|
<div class="mt-2 flex items-center">
|
|
<span
|
|
class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100">
|
|
<img
|
|
alt={$_('profile-picture')}
|
|
class="h-20 w-20 rounded-full overflow-hidden bg-gray-100"
|
|
src={editable.profilePic || 'https://lauf-fuer-kaya.de/lfk-logo.png'} />
|
|
</span>
|
|
<!-- <button
|
|
type="button"
|
|
class="ml-5 bg-white py-2 px-3 border border-gray-300 rounded-md shadow-sm text-sm leading-4 font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
|
Change
|
|
</button> -->
|
|
</div>
|
|
</div>
|
|
<div class="text-sm w-full">
|
|
<label
|
|
for="username"
|
|
class="font-medium text-gray-700">{$_('username')}</label>
|
|
<input
|
|
autocomplete="off"
|
|
placeholder={$_('username')}
|
|
type="text"
|
|
bind:value={editable.username}
|
|
name="username"
|
|
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-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
|
|
</div>
|
|
<div class="text-sm w-full">
|
|
<label
|
|
for="email"
|
|
class="font-medium text-gray-700">{$_('e-mail-adress')}</label>
|
|
<input
|
|
autocomplete="off"
|
|
placeholder={$_('e-mail-adress')}
|
|
type="email"
|
|
bind:value={editable.email}
|
|
name="email"
|
|
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-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
|
|
</div>
|
|
{#if !isEmail(editable.email)}
|
|
<span
|
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">{$_('valid-email-is-required')}</span>
|
|
{/if}
|
|
<div class="text-sm w-full">
|
|
<label
|
|
for="firstname"
|
|
class="font-medium text-gray-700">{$_('first-name')}</label>
|
|
<input
|
|
autocomplete="off"
|
|
placeholder={$_('first-name')}
|
|
type="text"
|
|
bind:value={editable.firstname}
|
|
name="firstname"
|
|
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-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
|
|
</div>
|
|
<div class="text-sm w-full">
|
|
<label
|
|
for="middlename"
|
|
class="font-medium text-gray-700">{$_('middle-name')}</label>
|
|
<input
|
|
autocomplete="off"
|
|
placeholder={$_('middle-name')}
|
|
type="text"
|
|
bind:value={editable.middlename}
|
|
name="middlename"
|
|
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-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
|
|
</div>
|
|
<div class="text-sm w-full">
|
|
<label
|
|
for="lastname"
|
|
class="font-medium text-gray-700">{$_('last-name')}</label>
|
|
<input
|
|
autocomplete="off"
|
|
placeholder={$_('last-name')}
|
|
type="text"
|
|
bind:value={editable.lastname}
|
|
name="lastname"
|
|
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-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
|
|
</div>
|
|
</div>
|
|
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
|
|
<button
|
|
type="submit"
|
|
disabled={!save_enabled}
|
|
class:opacity-50={!save_enabled}
|
|
on:click={submit}
|
|
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:ml-3 sm:w-auto sm:text-sm">
|
|
{$_('save-changes')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/await}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
|
<div>
|
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
|
<div class="md:col-span-1">
|
|
<div class="px-4 sm:px-0">
|
|
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
|
{$_('password')}
|
|
</h3>
|
|
<p class="mt-1 text-sm text-gray-600">
|
|
{$_('change-your-password-here')}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
{#await user_promise}
|
|
{$_('loading-profile-data')}
|
|
{:then}
|
|
<div class="mt-5 md:mt-0 md:col-span-2">
|
|
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
|
<div class="px-4 py-3 bg-gray-50 text-left sm:px-6">
|
|
<label
|
|
for="new_password"
|
|
class="font-medium text-gray-700">{$_('new-password')}</label>
|
|
<div class="-mt-px relative">
|
|
<input
|
|
aria-label={$_('password')}
|
|
type="password"
|
|
required=""
|
|
bind:value={password_change}
|
|
class="border-gray-300 placeholder-gray-500 appearance-none rounded-md relative block w-full px-3 py-2 border focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
|
|
placeholder={$_('password')} />
|
|
</div>
|
|
<label
|
|
for="new_password"
|
|
class="font-medium text-gray-700">{$_('confirm-the-new-password')}</label>
|
|
<div class="-mt-px relative">
|
|
<input
|
|
aria-label={$_('password')}
|
|
type="password"
|
|
required=""
|
|
bind:value={password_confirm}
|
|
class="border-gray-300 placeholder-gray-500 appearance-none rounded-md relative block w-full px-3 py-2 border focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
|
|
placeholder={$_('password')} />
|
|
</div>
|
|
<PasswordStrength bind:password_change bind:password_confirm />
|
|
</div>
|
|
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
|
|
<button
|
|
type="submit"
|
|
disabled={!update_password_enabled}
|
|
class:opacity-50={!update_password_enabled}
|
|
on:click={changePassword}
|
|
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:ml-3 sm:w-auto sm:text-sm">
|
|
{$_('update-password')}
|
|
</button>
|
|
{#if update_password_enabled}
|
|
<p>
|
|
{$_('after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that')}
|
|
</p>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/await}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
|
<div>
|
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
|
<div class="md:col-span-1">
|
|
<div class="px-4 sm:px-0">
|
|
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
|
{$_('danger-zone')}
|
|
</h3>
|
|
<p class="mt-1 text-sm text-gray-600">
|
|
{$_('stuff-that-could-harm-your-profile')}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
{#await user_promise}
|
|
{$_('loading-profile-data')}
|
|
{:then}
|
|
<div class="mt-5 md:mt-0 md:col-span-2">
|
|
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
|
<div class="px-4 py-3 bg-gray-50 text-left sm:px-6">
|
|
<span data-id="donor_actions_${editable.id}">
|
|
{#if delete_triggered}
|
|
<button
|
|
on:click={() => {
|
|
modal_open = true;
|
|
}}
|
|
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:ml-3 sm:w-auto sm:">{$_('confirm-deletion')}</button>
|
|
<button
|
|
on:click={() => {
|
|
delete_triggered = !delete_triggered;
|
|
}}
|
|
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:">{$_('cancel')}</button>
|
|
{/if}
|
|
{#if !delete_triggered}
|
|
<button
|
|
on:click={() => {
|
|
delete_triggered = true;
|
|
}}
|
|
type="button"
|
|
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:ml-3 sm:w-auto sm:">{$_('delete-profile')}</button>
|
|
{/if}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/await}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|