Skip to content

Commit 32e5be7

Browse files
committed
Update profile page
1 parent 7614962 commit 32e5be7

File tree

6 files changed

+176
-109
lines changed

6 files changed

+176
-109
lines changed

src/App.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { RouterView } from 'vue-router';
55
<template>
66
<!-- Use key to re-generate the page view component on each navigation :key="$route.path" -->
77
<!-- Alteratively, use a watch() on each component to re-render dynamic data as needed -->
8-
<Toast position="top-center" />
8+
<Toast position="bottom-right" />
99
<RouterView v-slot="{ Component }">
1010
<Suspense timeout="0">
1111
<template #default>

src/components/DeleteUserModal.vue

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,41 @@
11
<script setup>
2-
import { useTemplateRef } from 'vue';
2+
import { ref, useTemplateRef } from 'vue';
3+
import { useRouter } from 'vue-router';
4+
import { useAxiosForm } from '@/composables/useAxiosForm';
5+
import { useFlashMessage } from '@/composables/useFlashMessage.js';
6+
import InputErrors from '@/components/InputErrors.vue';
37
48
const modalOpen = defineModel(false, {
59
type: Boolean,
610
});
11+
12+
const router = useRouter();
13+
const { setFlashMessage } = useFlashMessage();
14+
715
const passwordInput = useTemplateRef('password-input');
816
17+
const {
18+
data: formData,
19+
validationErrors,
20+
processing: deleting,
21+
del: submitForm,
22+
reset: resetFormFields,
23+
} = useAxiosForm({
24+
password: '',
25+
});
26+
const deleteAccount = () => {
27+
submitForm('/profile', {
28+
onSuccess: () => {
29+
modalOpen.value = false;
30+
router.push({ name: 'dashboard' }).then(() => {
31+
setFlashMessage('success', 'Your account has been deleted.');
32+
});
33+
},
34+
onError: () => passwordInput.value.$el.focus(),
35+
onFinish: () => resetFormFields(),
36+
});
37+
};
38+
939
function focusPasswordInput() {
1040
passwordInput.value.$el.focus();
1141
}
@@ -22,6 +52,45 @@ function focusPasswordInput() {
2252
modal
2353
@show="focusPasswordInput"
2454
>
25-
55+
<div class="mb-6">
56+
<p class="m-0 text-muted-color">
57+
Once your account is deleted, all of its resources and data
58+
will be permanently deleted. Please enter your password to
59+
confirm you would like to permanently delete your account.
60+
</p>
61+
</div>
62+
63+
<div class="flex flex-col gap-2">
64+
<InputText
65+
id="password"
66+
ref="password-input"
67+
v-model="formData.password"
68+
:invalid="Boolean(validationErrors?.password)"
69+
type="password"
70+
placeholder="Password"
71+
autocomplete="current-password"
72+
autofocus
73+
required
74+
fluid
75+
@keyup.enter="deleteAccount"
76+
/>
77+
<InputErrors :errors="validationErrors?.password" />
78+
</div>
79+
80+
<template #footer>
81+
<Button
82+
class="mr-2"
83+
label="Cancel"
84+
plain
85+
text
86+
@click="modalOpen = false"
87+
/>
88+
<Button
89+
:loading="deleting"
90+
label="Delete Account"
91+
severity="danger"
92+
@click="deleteAccount"
93+
/>
94+
</template>
2695
</Dialog>
2796
</template>

src/layouts/app/HeaderLayout.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ const toggleMobileUserMenu = (event) => {
7171
</div>
7272
</template>
7373
</Drawer>
74-
<Toast position="bottom-right" />
7574
</Teleport>
7675
<div class="min-h-screen">
7776
<!-- Primary Navigation Menu -->

src/layouts/app/SidebarLayout.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ const toggleMobileUserMenu = (event) => {
6969
</div>
7070
</template>
7171
</Drawer>
72-
<Toast position="bottom-right" />
7372
</Teleport>
7473

7574
<!-- Mobile Header -->

src/views/profile/partials/DeleteUserForm.vue

Lines changed: 0 additions & 100 deletions
This file was deleted.

src/views/settings/Profile.vue

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,57 @@
11
<script setup>
2-
import { ref } from 'vue';
2+
import { ref, useTemplateRef, computed, onMounted } from 'vue';
33
import { useToast } from 'primevue/usetoast';
4+
import { useAxiosForm } from '@/composables/useAxiosForm';
5+
import { useAuthStore } from '@/stores/auth';
6+
import { useFlashMessage } from '@/composables/useFlashMessage.js';
47
import AppLayout from '@/layouts/AppLayout.vue';
58
import SettingsLayout from '@/layouts/UserSettingsLayout.vue';
69
import DeleteUserModal from '@/components/DeleteUserModal.vue';
10+
import InputErrors from '@/components/InputErrors.vue';
711
12+
const toast = useToast();
13+
const authStore = useAuthStore();
14+
const { flashMessages } = useFlashMessage();
15+
16+
const nameInput = useTemplateRef('name-input');
17+
18+
const verificationLinkSent = computed(() => flashMessages.success === 'verification-link-sent');
819
const deleteUserModalOpen = ref(false);
20+
21+
const {
22+
data: formData,
23+
validationErrors,
24+
processing: updating,
25+
patch: submitForm,
26+
} = useAxiosForm({
27+
name: authStore.user.name || '',
28+
email: authStore.user.email || '',
29+
});
30+
const submit = () => {
31+
submitForm('/profile', {
32+
onSuccess: async () => {
33+
toast.add({
34+
severity: 'success',
35+
summary: 'Saved',
36+
detail: 'Profile information has been updated',
37+
life: 3000,
38+
});
39+
authStore.fetchUser();
40+
},
41+
});
42+
};
43+
44+
const resendVerifyEmail = () => {
45+
authStore.sendVerificationEmail();
46+
};
47+
48+
onMounted(() => {
49+
nameInput.value.$el.focus();
50+
});
951
</script>
1052

1153
<template>
1254
<AppLayout>
13-
<InertiaHead title="Profile Settings" />
14-
1555
<SettingsLayout>
1656
<div class="space-y-4 md:space-y-8">
1757
<Card
@@ -23,7 +63,67 @@ const deleteUserModalOpen = ref(false);
2363
Update your name and email address
2464
</template>
2565
<template #content>
26-
66+
<form
67+
class="space-y-6"
68+
@submit.prevent="submit"
69+
>
70+
<div class="flex flex-col gap-2">
71+
<label for="name">Name</label>
72+
<InputText
73+
id="name"
74+
ref="name-input"
75+
v-model="formData.name"
76+
type="text"
77+
class="w-full"
78+
:invalid="Boolean(validationErrors?.name)"
79+
autocomplete="name"
80+
required
81+
/>
82+
<InputErrors :errors="validationErrors?.name" />
83+
</div>
84+
<div class="flex flex-col gap-2">
85+
<label for="email">Email</label>
86+
<InputText
87+
id="email"
88+
v-model="formData.email"
89+
type="email"
90+
class="w-full"
91+
:invalid="Boolean(validationErrors?.email)"
92+
autocomplete="username"
93+
required
94+
/>
95+
<InputErrors :errors="validationErrors?.email" />
96+
</div>
97+
98+
<div v-if="authStore.mustVerifyEmail && authStore.user.email_verified_at === null">
99+
<p class="text-sm mt-2">
100+
Your email address is unverified.
101+
<a
102+
href="#"
103+
class="text-sm underline text-muted-color hover:text-color"
104+
@click="resendVerifyEmail"
105+
>
106+
Click here to re-send the verification email.
107+
</a>
108+
</p>
109+
110+
<Message
111+
v-if="verificationLinkSent"
112+
severity="success"
113+
class="shadow-sm mt-4"
114+
:closable="false"
115+
>
116+
A new verification link has been sent to your email address.
117+
</Message>
118+
</div>
119+
<div>
120+
<Button
121+
type="submit"
122+
label="Save"
123+
:loading="updating"
124+
/>
125+
</div>
126+
</form>
27127
</template>
28128
</Card>
29129
<Card

0 commit comments

Comments
 (0)