Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Account Tab with User Information and Reset Password Feature #62

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 197 additions & 13 deletions layers/portal/pages/portal/account/index.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,203 @@
<script setup lang="ts"></script>
<script setup lang="ts">
import { reactive, ref, unref } from 'vue';
import type { User } from '~~/types';

useHead({
title: 'Account',
});

const toast = useToast();
const { user } = useDirectusAuth() as { user: Partial<User> };
const reactiveUser = reactive(user);

// Function to update user information
const updateUserInfo = async (firstName: string, lastName: string, title: string, location: string) => {
// Display a toast for update in progress
toast.add({
id: 'user_updating',
title: 'Uploading...',
description: 'Updating ' + unref(reactiveUser).email + '...',
icon: 'material-symbols:hourglass-top-rounded',
color: 'blue',
timeout: 0,
});

// Prepare and execute the update command
const updateCommand = updateMe({ first_name: firstName, last_name: lastName, title, location });

try {
const updatedUser = await useDirectus(updateCommand);
toast.remove('user_updating');

toast.add({
id: 'user_updated',
title: 'Account Updated',
description: updatedUser.email + ' has been successfully updated.',
icon: 'material-symbols:check-circle-rounded',
color: 'primary',
});
} catch (error) {
toast.remove('user_updating');

toast.add({
id: 'update_error',
title: 'Update Error',
description: 'An error occurred: ' + error,
icon: 'material-symbols:warning-rounded',
color: 'red',
});
}
};

const loading = ref(false);
const error = ref(null);

const formState = reactive({
title: unref(reactiveUser).title ?? '',
firstname: unref(reactiveUser).first_name ?? '',
lastname: unref(reactiveUser).last_name ?? '',
location: unref(reactiveUser).location ?? '',
});

// Function to handle form submission
async function attemptUserInfoUpdate() {
const { firstname, lastname, title, location } = formState;
loading.value = true;
error.value = null;

try {
await updateUserInfo(firstname, lastname, title, location);
} catch (err: any) {
error.value = err.message;
} finally {
loading.value = false;
}
}

const resetPassword = () => {
toast.add({
id: 'reset_password',
title: 'Reset Password',
description: 'This feature will be available soon...',
icon: 'material-symbols:hourglass-top-rounded',
color: 'blue',
});
// TODO: Add logic for reset password here
};
</script>


Check failure on line 89 in layers/portal/pages/portal/account/index.vue

View workflow job for this annotation

GitHub Actions / Lint

Delete `⏎`
<template>
<div>
<PortalPageHeader
title="Account"
:breadcrumbs="[
{
title: 'Portal',
href: '/portal',
},
{
title: 'Account',
},
]"
>
<PortalPageHeader title="Account" :breadcrumbs="[{ title: 'Portal', href: '/portal' }, { title: 'Account' }]">
<template #actions></template>
</PortalPageHeader>

<div v-auto-animate>
<UAlert
v-if="error"
type="error"
class="mb-4"
title="Oops! Something went wrong."
:description="error"
color="rose"
variant="outline"
icon="material-symbols:warning-rounded"
>
Error: {{ error }}
</UAlert>

<form class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-3" @submit.prevent="attemptUserInfoUpdate">
<UFormGroup v-slot="{ errorFirstName }" label="First Name" required :error="!formState.firstname && 'Please enter your first name'">

Check failure on line 111 in layers/portal/pages/portal/account/index.vue

View workflow job for this annotation

GitHub Actions / Lint

Replace `·v-slot="{·errorFirstName·}"·label="First·Name"··required·:error="!formState.firstname·&&·'Please·enter·your·first·name'"` with `⏎↹↹↹↹↹v-slot="{·errorFirstName·}"⏎↹↹↹↹↹label="First·Name"⏎↹↹↹↹↹required⏎↹↹↹↹↹:error="!formState.firstname·&&·'Please·enter·your·first·name'"⏎↹↹↹↹`
<UInput
v-model="formState.firstname"
:disabled="loading"
size="lg"
name="firstname"
label="First Name"
placeholder="John"
icon="material-symbols:person-book"
:trailing-icon="errorFirstName ? 'i-heroicons-exclamation-triangle-20-solid' : undefined"
/>
</UFormGroup>
<UFormGroup v-slot="{ errorLastName }" label="Last Name" required :error="!formState.lastname && 'Please enter your last name'">

Check failure on line 123 in layers/portal/pages/portal/account/index.vue

View workflow job for this annotation

GitHub Actions / Lint

Replace `··v-slot="{·errorLastName·}"·label="Last·Name"·required·:error="!formState.lastname·&&·'Please·enter·your·last·name'"` with `⏎↹↹↹↹↹v-slot="{·errorLastName·}"⏎↹↹↹↹↹label="Last·Name"⏎↹↹↹↹↹required⏎↹↹↹↹↹:error="!formState.lastname·&&·'Please·enter·your·last·name'"⏎↹↹↹↹`
<UInput
v-model="formState.lastname"
:disabled="loading"
size="lg"
name="lastname"
label="Last Name"
placeholder="Doe"
icon="material-symbols:person-book"
:trailing-icon="errorLastName ? 'i-heroicons-exclamation-triangle-20-solid' : undefined"
/>
</UFormGroup>
<UFormGroup label="Title" hint="Optional">
<UInput
v-model="formState.title"
:disabled="loading"
size="lg"
name="title"
label="Title"
placeholder="Dr. / Prof. / etc."
icon="material-symbols:badge"
/>
</UFormGroup>
<UFormGroup label="Location" hint="Optional">
<UInput
v-model="formState.location"
:disabled="loading"
size="lg"
name="location"
label="Location"
placeholder="City or Region"
icon="material-symbols:location-on-outline"
/>
</UFormGroup>
<UFormGroup
label="Email"
class="md:col-span-2"
hint="Only View"
help="If you want to change your email, please contact any Administrators."
>
<UInput
v-model="reactiveUser.email"
disabled
size="lg"
name="email"
label="Email"
placeholder="email@example.com"
icon="i-heroicons-envelope"
/>
</UFormGroup>

<div class="md:col-span-2 flex flex-col md:flex-row gap-4">
<div class="flex w-full md:w-1/2 justify-center">
<UButton
type="submit"
:loading="loading"
:disabled="!formState.firstname || !formState.lastname"
size="lg"
:color="loading ? 'gray' : 'primary'"
label="Save"
trailing-icon="material-symbols:save"
class="w-full justify-center"
/>
</div>
<div class="flex w-full md:w-1/2 justify-center">
<UButton
size="lg"
label="Reset Password"
:color="loading ? 'gray' : 'orange'"
trailing-icon="material-symbols:passkey"
class="w-full justify-center"
@click="resetPassword"
/>
</div>
</div>
</form>
</div>

<UNotifications />
</div>
</template>
Loading