diff options
| author | ivarlovlie <git@ivarlovlie.no> | 2022-08-05 12:58:54 +0200 |
|---|---|---|
| committer | ivarlovlie <git@ivarlovlie.no> | 2022-08-05 12:58:54 +0200 |
| commit | bab0072e5cf709e6c1cf303f89348ee61a8007e4 (patch) | |
| tree | 3c964d27224b18364f9a378f9ab6c01d207a9153 /apps/portal/src/app/pages | |
| parent | c1d0567a0c46be08826cf4fe556b680cb2efe53a (diff) | |
| download | greatoffice-bab0072e5cf709e6c1cf303f89348ee61a8007e4.tar.xz greatoffice-bab0072e5cf709e6c1cf303f89348ee61a8007e4.zip | |
feat: Add basic profile administration
Diffstat (limited to 'apps/portal/src/app/pages')
| -rw-r--r-- | apps/portal/src/app/pages/profile/index.svelte | 159 |
1 files changed, 155 insertions, 4 deletions
diff --git a/apps/portal/src/app/pages/profile/index.svelte b/apps/portal/src/app/pages/profile/index.svelte index 0929c3c..00942ac 100644 --- a/apps/portal/src/app/pages/profile/index.svelte +++ b/apps/portal/src/app/pages/profile/index.svelte @@ -1,7 +1,90 @@ <script> - import {push} from "svelte-spa-router"; - import {Bread, Crumb} from "$shared/components/breadcrumb/index"; - import Layout from "$app/pages/_layout@loggedin.svelte"; + import {push} from "svelte-spa-router"; + import {Bread, Crumb} from "$shared/components/breadcrumb/index"; + import Layout from "$app/pages/_layout@loggedin.svelte"; + import {update_profile} from "$shared/lib/api/user"; + import Alert from "$shared/components/alert.svelte"; + import Button from "$shared/components/button.svelte"; + import {is_email} from "$shared/lib/helpers"; + import {api_base} from "$shared/lib/configuration"; + import {get_session_data} from "$shared/lib/session"; + + const archiveLink = api_base("_/api/account/archive"); + + let modal; + let understands = false; + + let formIsLoading = false; + let formError; + + let username = get_session_data()?.profile.username; + let usernameFieldMessage; + let usernameFieldMessageClass = "color-error"; + + let password; + let passwordFieldMessage; + let passwordFieldMessageClass = "color-error"; + + async function submit_form(e) { + e.preventDefault(); + if (!username && !password) { + console.error("Not submitting because both values is empty"); + return; + } + + usernameFieldMessage = ""; + passwordFieldMessage = ""; + + if (username && !is_email(username)) { + usernameFieldMessage = "Username has to be a valid email"; + return; + } + + if (password && password?.length < 6) { + passwordFieldMessage = "The new password must contain at least 6 characters"; + return; + } + + formIsLoading = true; + + const response = await update_profile({ + username, + password, + }); + + formIsLoading = false; + + if (response.ok) { + if (password) { + passwordFieldMessage = "Successfully updated"; + passwordFieldMessageClass = "color-success"; + password = ""; + } + if (username) { + usernameFieldMessage = "Successfully updated"; + usernameFieldMessageClass = "color-success"; + password = ""; + } + } else { + formError = response.data.title ?? "An unknown error occured"; + } + } + + async function handle_delete_account_button_click() { + alert("Not implemented"); + return; + if (understands && confirm("Are you absolutely sure that you want to delete your account?")) { + } + } + + export const functions = { + open() { + modal.open(); + }, + close() { + // modal.close(); + }, + }; </script> <Layout> @@ -12,5 +95,73 @@ on:click={() => push("/")}/> <Crumb name="Profile"/> </Bread> - <h1>Profile</h1> + + <main class="max-width-sm"> + <section class="margin-bottom-md"> + <p class="text-md margin-bottom-sm">Update your information</p> + <form on:submit={submit_form} + autocomplete="new-password"> + {#if formError} + <small class="color-danger">{formError}</small> + {/if} + <div class="margin-bottom-sm"> + <label for="email" + class="form-label margin-bottom-xxs">New username</label> + <input type="email" + class="form-control width-100%" + id="email" + placeholder={username} + bind:value={username}/> + {#if usernameFieldMessage} + <small class={usernameFieldMessageClass}>{usernameFieldMessage}</small> + {/if} + </div> + <div class="margin-bottom-sm"> + <label for="password" + class="form-label margin-bottom-xxs">New password</label> + <input type="password" + class="form-control width-100%" + id="password" + bind:value={password}/> + {#if passwordFieldMessage} + <small class={passwordFieldMessageClass}>{passwordFieldMessage}</small> + {/if} + </div> + <div class="flex justify-end"> + <Button text="Save" + on:click={submit_form} + variant="primary" + loading={formIsLoading}/> + </div> + </form> + </section> + <section class="margin-bottom-md"> + <p class="text-md margin-bottom-sm">Download your data</p> + <a class="btn btn--subtle" + href={archiveLink} + download>Click here to download your data</a> + </section> + <section> + <p class="text-md margin-bottom-sm">Delete account</p> + <div class="margin-bottom-sm"> + <Alert + message="Deleting your account and data means that all of your data (entries, categories, etc.) will be unrecoverable forever.<br>You should probably download your data before continuing." + type="info" + /> + </div> + <div class="form-check margin-bottom-sm"> + <input type="checkbox" + class="checkbox" + id="the-consequences" + bind:checked={understands}/> + <label for="the-consequences">I understand the consequences of deleting my account and data.</label> + </div> + <div class="flex justify-end"> + <Button text="Delete everything" + variant="accent" + disabled={!understands} + on:click={handle_delete_account_button_click}/> + </div> + </section> + </main> </Layout> |
