Skip to content

Commit

Permalink
feat: add profile form to profile page
Browse files Browse the repository at this point in the history
  • Loading branch information
KabinKhandThakuri committed Jan 13, 2025
1 parent 46e8fd2 commit a884b66
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 2 deletions.
17 changes: 16 additions & 1 deletion packages/vue-user/src/api/user/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import client from "../axios";

import type { UserType } from "../../types";
import type { UpdateProfileInputType, UserType } from "../../types";

export const getMe = async (
apiBaseUrl: string,
Expand All @@ -15,3 +15,18 @@ export const getMe = async (
return response;
}
};

export const updateUserProfile = async (
data: UpdateProfileInputType,
apiBaseUrl: string,
): Promise<{ data: UserType }> => {
const response = await client(apiBaseUrl).put(`me`, data, {
withCredentials: true,
});

if ("error" in response.data) {
throw new Error(response.data.message);
} else {
return response;
}
};
1 change: 1 addition & 0 deletions packages/vue-user/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { default as InvitationModal } from "./invitation/InvitationModal.vue";
export { default as LoginForm } from "./LoginForm.vue";
export { default as PasswordResetForm } from "./PasswordResetForm.vue";
export { default as PasswordResetRequestForm } from "./PasswordResetRequestForm.vue";
export { default as ProfileForm } from "./profile/ProfileForm.vue";
export { default as SignInUpMenu } from "./SignInUpMenu.vue";
export { default as SignupForm } from "./SignupForm.vue";
export { default as TermsAndConditions } from "./TermsAndConditions.vue";
Expand Down
98 changes: 98 additions & 0 deletions packages/vue-user/src/components/profile/ProfileForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<template>
<Form ref="dzangolabVueUpdateProfile" class="profile-form" @submit="onSubmit">
<Input
v-model="formValues.givenName"
:label="t('user.profile.form.firstName.label')"
:placeholder="t('user.profile.form.firstName.placeholder')"
name="givenName"
type="text"
/>

<Input
v-model="formValues.surname"
:label="t('user.profile.form.lastName.label')"
:placeholder="t('user.profile.form.lastName.placeholder')"
name="surname"
type="text"
/>

<FormActions
:loading="loading || !isDirty"
@cancel="dzangolabVueUpdateProfile.resetForm()"
/>
</Form>
</template>

<script lang="ts">
export default {
name: "ProfileForm",
};
</script>

<script setup lang="ts">
import { useConfig } from "@dzangolab/vue3-config";
import { Input, Form, FormActions } from "@dzangolab/vue3-form";
import { useI18n } from "@dzangolab/vue3-i18n";
import { storeToRefs } from "pinia";
import { computed, reactive, ref } from "vue";
import { updateUserProfile } from "../../api/user";
import { emitter, useTranslations } from "../../index";
import useUserStore from "../../store";
import type { UpdateProfileInputType } from "../../types";
const config = useConfig();
const messages = useTranslations();
const { t } = useI18n({ messages });
const userStore = useUserStore();
const setUser = userStore.setUser;
const { user } = storeToRefs(userStore);
const formValues = reactive({
givenName: user.value?.givenName || "",
surname: user.value?.surname || "",
});
const dzangolabVueUpdateProfile = ref();
const loading = ref<boolean>(false);
const isDirty = computed(() => {
return (
formValues.givenName !== user.value?.givenName ||
formValues.surname !== user.value?.surname
);
});
const onSubmit = async (data: UpdateProfileInputType) => {
loading.value = true;
updateUserProfile(data, config.apiBaseUrl)
.then((response) => {
if ("data" in response) {
emitter.emit("notify", {
text: t("user.profile.form.messages.success"),
type: "success",
});
setUser(response.data);
} else {
emitter.emit("notify", {
text: t("user.profile.form.messages.error"),
type: "error",
});
}
})
.catch(() => {
emitter.emit("notify", {
text: t("user.profile.form.messages.error"),
type: "error",
});
})
.finally(() => {
loading.value = false;
});
};
</script>
30 changes: 29 additions & 1 deletion packages/vue-user/src/locales/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,20 @@
},
"title": "Update email"
},
"form": {
"firstName": {
"label": "First name",
"placeholder": "Enter your first name"
},
"lastName": {
"label": "Last name",
"placeholder": "Enter your last name"
},
"messages": {
"error": "Something went wrong. Please try again",
"success": "Profile updated successfully"
}
},
"title": "Profile"
},
"signup": {
Expand Down Expand Up @@ -373,7 +387,21 @@
},
"title": "Update email"
},
"title": "Profil"
"form": {
"firstName": {
"label": "First name",
"placeholder": "Enter your first name"
},
"lastName": {
"label": "Last name",
"placeholder": "Enter your last name"
},
"messages": {
"error": "Something went wrong. Please try again",
"success": "Profile updated successfully"
}
},
"title": "Profil"
},
"signup": {
"errors": {
Expand Down
7 changes: 7 additions & 0 deletions packages/vue-user/src/types/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ interface UpdatePasswordPayload {
newPassword: string;
}

type UpdateProfileInputType = {
email: string;
givenName: string;
surname: string;
};

interface User extends EmailPasswordUserType {
//usertype and emailusertype are same one type with different name in different recipe
email: string;
Expand Down Expand Up @@ -55,6 +61,7 @@ export type {
PasswordResetPayload,
PasswordResetRequestPayload,
UpdatePasswordPayload,
UpdateProfileInputType,
User,
UserType,
};
1 change: 1 addition & 0 deletions packages/vue-user/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type {
PasswordResetPayload,
PasswordResetRequestPayload,
UpdatePasswordPayload,
UpdateProfileInputType,
User,
UserType,
} from "./auth";
Expand Down
10 changes: 10 additions & 0 deletions packages/vue-user/src/views/Profile.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<Page :title="t('user.profile.title')" class="profile">
<AccountInfo />
<ProfileForm />
</Page>
</template>

Expand All @@ -15,9 +16,18 @@ import { useI18n } from "@dzangolab/vue3-i18n";
import { Page } from "@dzangolab/vue3-ui";
import AccountInfo from "../components/profile/AccountInfo.vue";
import ProfileForm from "../components/profile/ProfileForm.vue";
import { useTranslations } from "../index";
const messages = useTranslations();
const { t } = useI18n({ messages });
</script>

<style lang="css">
.page.profile > main {
display: flex;
flex-direction: column;
gap: 1rem;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe("Profile", () => {
stubs: {
RouterLink: RouterLinkStub,
AccountInfo: true,
profileForm: true,
},
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ exports[`Profile > matches snapshot in en 1`] = `
<main>
<account-info-stub />
<profile-form-stub />
</main>
</div>
Expand All @@ -39,6 +40,7 @@ exports[`Profile > matches snapshot in fr 1`] = `
<main>
<account-info-stub />
<profile-form-stub />
</main>
</div>
Expand Down

0 comments on commit a884b66

Please sign in to comment.