Skip to content

Commit 3f9f2f6

Browse files
Revamp profile page (#3542)
This PR redesigns the profile page, using Vue instead of Blade to enable further improvements in the near future. This redesign uses DaisyUI instead of the previous Bootstrap and raw CSS styling approach. | Before | After | | --- | --- | | <img width="2830" height="1876" alt="image" src="https://github.com/user-attachments/assets/4d24f15b-8bfa-45be-967c-f725d12fedf4" /> | <img width="2832" height="1984" alt="image" src="https://github.com/user-attachments/assets/7b74a96d-508e-4456-9c24-73ae80a3abdc" /> |
1 parent 0b25d1e commit 3f9f2f6

File tree

11 files changed

+179
-182
lines changed

11 files changed

+179
-182
lines changed

app/Http/Controllers/UserController.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,11 @@ public function edit(): View
432432
$error_msg = 'Your password has expired. Please set a new one.';
433433
}
434434

435-
return $this->view('auth.profile', 'Profile')
436-
->with('user', $user)
437-
->with('error', $error_msg)
438-
->with('message', $other_msg);
435+
return $this->vue('profile-page', 'Profile', [
436+
'user' => $user,
437+
'error' => $error_msg,
438+
'message' => $other_msg,
439+
]);
439440
}
440441

441442
public function recoverPassword(): View

resources/js/vue/app.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const app = Vue.createApp({
3737
CreateProjectPage: Vue.defineAsyncComponent(() => import('./components/CreateProjectPage.vue')),
3838
AdministrationPage: Vue.defineAsyncComponent(() => import('./components/AdministrationPage.vue')),
3939
ProjectSettingsPage: Vue.defineAsyncComponent(() => import('./components/ProjectSettingsPage.vue')),
40+
ProfilePage: Vue.defineAsyncComponent(() => import('./components/ProfilePage.vue')),
4041
},
4142
});
4243

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
<template>
2+
<div class="tw-flex tw-flex-col tw-w-full tw-max-w-3xl tw-mx-auto tw-justify-center tw-gap-12 tw-p-4 tw-mt-8">
3+
<div
4+
v-if="error"
5+
class="tw-alert tw-alert-error tw-mb-4"
6+
>
7+
{{ error }}
8+
</div>
9+
<div
10+
v-if="message"
11+
class="tw-alert tw-alert-success tw-mb-4"
12+
>
13+
{{ message }}
14+
</div>
15+
16+
<FormSection title="Profile">
17+
<form
18+
id="profile_form"
19+
method="post"
20+
action=""
21+
class="tw-flex tw-flex-col tw-gap-4"
22+
>
23+
<input
24+
type="hidden"
25+
name="_token"
26+
:value="csrfToken"
27+
>
28+
29+
<InputField
30+
v-model="profileForm.fname"
31+
name="fname"
32+
label="First Name"
33+
/>
34+
<InputField
35+
v-model="profileForm.lname"
36+
name="lname"
37+
label="Last Name"
38+
/>
39+
<InputField
40+
v-model="profileForm.email"
41+
name="email"
42+
label="Email"
43+
/>
44+
<InputField
45+
v-model="profileForm.institution"
46+
name="institution"
47+
label="Institution"
48+
/>
49+
50+
<div class="tw-flex tw-justify-end tw-mt-4">
51+
<input
52+
type="submit"
53+
value="Update Profile"
54+
name="updateprofile"
55+
class="tw-btn tw-btn-primary"
56+
>
57+
</div>
58+
</form>
59+
</FormSection>
60+
61+
<FormSection title="Change Password">
62+
<form
63+
id="password_form"
64+
method="post"
65+
action=""
66+
class="tw-flex tw-flex-col tw-gap-4"
67+
>
68+
<input
69+
type="hidden"
70+
name="_token"
71+
:value="csrfToken"
72+
>
73+
74+
<InputField
75+
v-model="passwordForm.oldpasswd"
76+
name="oldpasswd"
77+
type="password"
78+
label="Current Password"
79+
/>
80+
<InputField
81+
v-model="passwordForm.passwd"
82+
name="passwd"
83+
type="password"
84+
label="New Password"
85+
/>
86+
<InputField
87+
v-model="passwordForm.passwd2"
88+
name="passwd2"
89+
type="password"
90+
label="Confirm Password"
91+
/>
92+
93+
<div class="tw-flex tw-justify-end tw-mt-4">
94+
<input
95+
type="submit"
96+
value="Update Password"
97+
name="updatepassword"
98+
class="tw-btn tw-btn-primary"
99+
>
100+
</div>
101+
</form>
102+
</FormSection>
103+
104+
<FormSection title="Other Information">
105+
<div class="tw-flex tw-flex-col tw-gap-4">
106+
<div class="tw-flex tw-flex-row tw-justify-between tw-items-center">
107+
<span class="tw-font-bold">Internal Id</span>
108+
<span>{{ user.id }}</span>
109+
</div>
110+
</div>
111+
</FormSection>
112+
</div>
113+
</template>
114+
115+
<script>
116+
import InputField from './shared/FormInputs/InputField.vue';
117+
import FormSection from './shared/FormSection.vue';
118+
119+
export default {
120+
name: 'ProfilePage',
121+
components: {
122+
InputField,
123+
FormSection,
124+
},
125+
props: {
126+
user: {
127+
type: Object,
128+
required: true,
129+
},
130+
error: {
131+
type: String,
132+
default: '',
133+
},
134+
message: {
135+
type: String,
136+
default: '',
137+
},
138+
},
139+
data() {
140+
return {
141+
profileForm: {
142+
fname: this.user.firstname || '',
143+
lname: this.user.lastname || '',
144+
email: this.user.email || '',
145+
institution: this.user.institution || '',
146+
},
147+
passwordForm: {
148+
oldpasswd: '',
149+
passwd: '',
150+
passwd2: '',
151+
},
152+
};
153+
},
154+
computed: {
155+
csrfToken() {
156+
return document.head.querySelector('meta[name="csrf-token"]')?.content;
157+
},
158+
},
159+
};
160+
</script>

resources/js/vue/components/ProjectSettings/GeneralTab.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@
469469
</template>
470470

471471
<script>
472-
import FormSection from './FormSection.vue';
472+
import FormSection from '../shared/FormSection.vue';
473473
import gql from 'graphql-tag';
474474
import {
475475
faCircleXmark,
@@ -483,10 +483,10 @@ import {
483483
faCheck,
484484
} from '@fortawesome/free-solid-svg-icons';
485485
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
486-
import InputField from './InputField.vue';
487-
import TextAreaField from './TextAreaField.vue';
488-
import CheckboxField from './CheckboxField.vue';
489-
import SelectField from './SelectField.vue';
486+
import InputField from '../shared/FormInputs/InputField.vue';
487+
import TextAreaField from '../shared/FormInputs/TextAreaField.vue';
488+
import CheckboxField from '../shared/FormInputs/CheckboxField.vue';
489+
import SelectField from '../shared/FormInputs/SelectField.vue';
490490
import TabContent from './TabContent.vue';
491491
import LoadingIndicator from '../shared/LoadingIndicator.vue';
492492

resources/js/vue/components/ProjectSettings/IntegrationsTab.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
<script>
114114
import TabContent from './TabContent.vue';
115115
import gql from 'graphql-tag';
116-
import InputField from './InputField.vue';
116+
import InputField from '../shared/FormInputs/InputField.vue';
117117
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
118118
import {
119119
faPlus,

resources/js/vue/components/ProjectSettings/CheckboxField.vue renamed to resources/js/vue/components/shared/FormInputs/CheckboxField.vue

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,6 @@ defineProps({
4646
default: undefined,
4747
},
4848
49-
subDescription: {
50-
type: String,
51-
required: false,
52-
default: undefined,
53-
},
54-
5549
disabled: {
5650
type: Boolean,
5751
required: false,

resources/js/vue/components/ProjectSettings/InputField.vue renamed to resources/js/vue/components/shared/FormInputs/InputField.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<input
1313
v-model="model"
1414
:type="type"
15+
:name="name"
1516
class="tw-input tw-input-bordered tw-w-full"
1617
:class="{'tw-input-error': validationError}"
1718
:disabled="disabled"
@@ -65,6 +66,12 @@ defineProps({
6566
default: 'text',
6667
},
6768
69+
name: {
70+
type: String,
71+
required: false,
72+
default: undefined,
73+
},
74+
6875
min: {
6976
type: [String, Number],
7077
required: false,

resources/js/vue/components/ProjectSettings/SelectField.vue renamed to resources/js/vue/components/shared/FormInputs/SelectField.vue

File renamed without changes.

resources/js/vue/components/ProjectSettings/TextAreaField.vue renamed to resources/js/vue/components/shared/FormInputs/TextAreaField.vue

File renamed without changes.

resources/js/vue/components/ProjectSettings/FormSection.vue renamed to resources/js/vue/components/shared/FormSection.vue

File renamed without changes.

0 commit comments

Comments
 (0)