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 info component to user package #449

Merged
merged 14 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion packages/vue-ui/src/Data/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ const props = defineProps({
required: true,
},
value: {
default: "",
type: [Object, String, Number] as PropType<string | number | object>,
required: true,
},
});

Expand Down
3 changes: 2 additions & 1 deletion packages/vue-user/src/components/AuthGoogleCallback.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { useTranslations } from "../index";
import useUserStore from "../store";
import { verifySessionRoles } from "../supertokens";

import type { UserType } from "../types";
import type { AppConfig } from "@dzangolab/vue3-config";

const config = useConfig() as AppConfig;
Expand Down Expand Up @@ -48,7 +49,7 @@ onMounted(async () => {
(supportedRoles && (await verifySessionRoles(supportedRoles))) ||
!supportedRoles?.length
) {
setUser(response.user);
setUser(response.user as UserType);

router.push({ name: "home" });
}
Expand Down
2 changes: 2 additions & 0 deletions packages/vue-user/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as AccountInfo } from "./profile/AccountInfo.vue";
export { default as ChangePasswordForm } from "./ChangePasswordForm.vue";
export { default as DropdownUserMenu } from "./DropdownUserMenu.vue";
export { default as InvitationForm } from "./invitation/InvitationForm.vue";
Expand All @@ -9,4 +10,5 @@ export { default as SignInUpMenu } from "./SignInUpMenu.vue";
export { default as SignupForm } from "./SignupForm.vue";
export { default as TermsAndConditions } from "./TermsAndConditions.vue";
export { default as UpdateEmailForm } from "./profile/UpdateEmailForm.vue";
export { default as UpdateEmailModal } from "./profile/UpdateEmailModal.vue";
export { default as UserMenu } from "./UserMenu.vue";
82 changes: 82 additions & 0 deletions packages/vue-user/src/components/profile/AccountInfo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<div class="account-info">
<Data
:class="canUpdateEmail ? 'update-email' : ''"
:label="t('user.profile.accountInfo.label')"
>
<template #value>
{{ user?.email }}

<ButtonElement
v-if="canUpdateEmail"
:label="t('user.profile.accountInfo.actions.update')"
size="small"
variant="outlined"
@click="showModal = true"
>
<template #iconLeft>
<svg
fill="none"
viewBox="0 -0.5 25 25"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M13.2942 7.95881C13.5533 7.63559 13.5013 7.16358 13.178 6.90453C12.8548 6.64549 12.3828 6.6975 12.1238 7.02072L13.2942 7.95881ZM6.811 14.8488L7.37903 15.3385C7.38489 15.3317 7.39062 15.3248 7.39623 15.3178L6.811 14.8488ZM6.64 15.2668L5.89146 15.2179L5.8908 15.2321L6.64 15.2668ZM6.5 18.2898L5.7508 18.2551C5.74908 18.2923 5.75013 18.3296 5.75396 18.3667L6.5 18.2898ZM7.287 18.9768L7.31152 19.7264C7.36154 19.7247 7.41126 19.7181 7.45996 19.7065L7.287 18.9768ZM10.287 18.2658L10.46 18.9956L10.4716 18.9927L10.287 18.2658ZM10.672 18.0218L11.2506 18.4991L11.2571 18.491L10.672 18.0218ZM17.2971 10.959C17.5562 10.6358 17.5043 10.1638 17.1812 9.90466C16.8581 9.64552 16.386 9.69742 16.1269 10.0206L17.2971 10.959ZM12.1269 7.02052C11.8678 7.34365 11.9196 7.81568 12.2428 8.07484C12.5659 8.33399 13.0379 8.28213 13.2971 7.95901L12.1269 7.02052ZM14.3 5.50976L14.8851 5.97901C14.8949 5.96672 14.9044 5.95412 14.9135 5.94123L14.3 5.50976ZM15.929 5.18976L16.4088 4.61332C16.3849 4.59344 16.3598 4.57507 16.3337 4.5583L15.929 5.18976ZM18.166 7.05176L18.6968 6.52192C18.6805 6.50561 18.6635 6.49007 18.6458 6.47532L18.166 7.05176ZM18.5029 7.87264L19.2529 7.87676V7.87676L18.5029 7.87264ZM18.157 8.68976L17.632 8.15412C17.6108 8.17496 17.5908 8.19704 17.5721 8.22025L18.157 8.68976ZM16.1271 10.0203C15.8678 10.3433 15.9195 10.8153 16.2425 11.0746C16.5655 11.3339 17.0376 11.2823 17.2969 10.9593L16.1271 10.0203ZM13.4537 7.37862C13.3923 6.96898 13.0105 6.68666 12.6009 6.74805C12.1912 6.80943 11.9089 7.19127 11.9703 7.60091L13.4537 7.37862ZM16.813 11.2329C17.2234 11.1772 17.5109 10.7992 17.4552 10.3888C17.3994 9.97834 17.0215 9.69082 16.611 9.74659L16.813 11.2329ZM12.1238 7.02072L6.22577 14.3797L7.39623 15.3178L13.2942 7.95881L12.1238 7.02072ZM6.24297 14.359C6.03561 14.5995 5.91226 14.9011 5.89159 15.218L7.38841 15.3156C7.38786 15.324 7.38457 15.3321 7.37903 15.3385L6.24297 14.359ZM5.8908 15.2321L5.7508 18.2551L7.2492 18.3245L7.3892 15.3015L5.8908 15.2321ZM5.75396 18.3667C5.83563 19.1586 6.51588 19.7524 7.31152 19.7264L7.26248 18.2272C7.25928 18.2273 7.25771 18.2268 7.25669 18.2264C7.25526 18.2259 7.25337 18.2249 7.25144 18.2232C7.2495 18.2215 7.24825 18.2198 7.24754 18.2185C7.24703 18.2175 7.24637 18.216 7.24604 18.2128L5.75396 18.3667ZM7.45996 19.7065L10.46 18.9955L10.114 17.536L7.11404 18.247L7.45996 19.7065ZM10.4716 18.9927C10.7771 18.9151 11.05 18.7422 11.2506 18.499L10.0934 17.5445C10.0958 17.5417 10.0989 17.5397 10.1024 17.5388L10.4716 18.9927ZM11.2571 18.491L17.2971 10.959L16.1269 10.0206L10.0869 17.5526L11.2571 18.491ZM13.2971 7.95901L14.8851 5.97901L13.7149 5.04052L12.1269 7.02052L13.2971 7.95901ZM14.9135 5.94123C15.0521 5.74411 15.3214 5.6912 15.5243 5.82123L16.3337 4.5583C15.4544 3.99484 14.2873 4.2241 13.6865 5.0783L14.9135 5.94123ZM15.4492 5.7662L17.6862 7.6282L18.6458 6.47532L16.4088 4.61332L15.4492 5.7662ZM17.6352 7.58161C17.7111 7.6577 17.7535 7.761 17.7529 7.86852L19.2529 7.87676C19.2557 7.36905 19.0555 6.88127 18.6968 6.52192L17.6352 7.58161ZM17.7529 7.86852C17.7524 7.97604 17.7088 8.07886 17.632 8.15412L18.682 9.22541C19.0446 8.87002 19.2501 8.38447 19.2529 7.87676L17.7529 7.86852ZM17.5721 8.22025L16.1271 10.0203L17.2969 10.9593L18.7419 9.15928L17.5721 8.22025ZM11.9703 7.60091C12.3196 9.93221 14.4771 11.5503 16.813 11.2329L16.611 9.74659C15.0881 9.95352 13.6815 8.89855 13.4537 7.37862L11.9703 7.60091Z"
fill="currentColor"
></path>
</svg>
</template>
</ButtonElement>
</template>
</Data>

<UpdateEmailModal
v-if="canUpdateEmail"
:show="showModal"
@on:close="showModal = false"
/>
</div>
</template>

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

<script setup lang="ts">
import { useConfig } from "@dzangolab/vue3-config";
import { useI18n } from "@dzangolab/vue3-i18n";
import { ButtonElement, Data } from "@dzangolab/vue3-ui";
import { storeToRefs } from "pinia";
import { ref } from "vue";

import UpdateEmailModal from "./UpdateEmailModal.vue";
import { useTranslations } from "../../index";
import useUserStore from "../../store";

const messages = useTranslations();
const { t } = useI18n({ messages });
const { user: userConfig } = useConfig();
const userStore = useUserStore();

const { user } = storeToRefs(userStore);

const canUpdateEmail =
userConfig?.features?.updateEmail && !user.value?.thirdParty;

const showModal = ref<boolean>(false);
</script>

<style lang="css">
.account-info > .data > .data-value {
align-items: center;
display: flex;
gap: 1rem;
}

.account-info > .data > .data-value > svg {
cursor: pointer;
}
</style>
5 changes: 4 additions & 1 deletion packages/vue-user/src/components/profile/UpdateEmailForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ type UpdateEmailFormData = {
email: string;
};

const emit = defineEmits(["email:updateProcessed"]);

const config = useConfig();

const messages = useTranslations();
Expand Down Expand Up @@ -81,6 +83,8 @@ const onSubmit = async (data: UpdateEmailFormData) => {
});
}

emit("email:updateProcessed");
dzangolabVueUpdateEmail.value?.resetForm();
break;
}
case "EMAIL_ALREADY_EXISTS_ERROR": {
Expand Down Expand Up @@ -120,7 +124,6 @@ const onSubmit = async (data: UpdateEmailFormData) => {
}
}

dzangolabVueUpdateEmail.value?.resetForm();
loading.value = false;
} catch (error) {
emitter.emit("notify", {
Expand Down
36 changes: 36 additions & 0 deletions packages/vue-user/src/components/profile/UpdateEmailModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<template>
<Modal
class="update-email-modal"
:show="show"
:title="t('user.profile.accountInfo.title')"
@on:close="$emit('on:close')"
>
<UpdateEmailForm @email:update-processed="$emit('on:close')" />
</Modal>
</template>

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

<script setup lang="ts">
import { useI18n } from "@dzangolab/vue3-i18n";
import { Modal } from "@dzangolab/vue3-ui";

import UpdateEmailForm from "./UpdateEmailForm.vue";
import { useTranslations } from "../../index";

const messages = useTranslations();
const { t } = useI18n({ messages });

defineProps({
show: {
default: false,
type: Boolean,
},
});

defineEmits(["on:close"]);
</script>
12 changes: 10 additions & 2 deletions packages/vue-user/src/locales/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@
},
"profile": {
"accountInfo": {
"actions": {
"update": "Update"
},
"label": "Email",
"newEmail": "New Email",
"messages": {
Expand All @@ -159,7 +162,8 @@
"invalid": "Invalid email",
"success": "Email updated successfully.",
"verify": "Verify email to complete the email update."
}
},
"title": "Update email"
},
"title": "Profile"
},
Expand Down Expand Up @@ -351,6 +355,9 @@
},
"profile": {
"accountInfo": {
"actions": {
"update": "Update"
},
"label": "Email",
"newEmail": "New Email",
"messages": {
Expand All @@ -363,7 +370,8 @@
"invalid": "Invalid email",
"success": "Email updated successfully.",
"verify": "Verify email to complete the email update."
}
},
"title": "Update email"
},
"title": "Profil"
},
Expand Down
8 changes: 4 additions & 4 deletions packages/vue-user/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import type {
PasswordResetPayload,
PasswordResetRequestPayload,
UpdatePasswordPayload,
User,
UserType,
} from "./types";

const USER_KEY = "user";

const useUserStore = defineStore("user", () => {
const user = ref<User | undefined>(undefined);
const user = ref<UserType | undefined>(undefined);

const changePassword = async (
payload: UpdatePasswordPayload,
Expand All @@ -33,7 +33,7 @@ const useUserStore = defineStore("user", () => {
return response;
};

const getUser = (): User => {
const getUser = (): UserType => {
if (user.value) {
return user.value;
}
Expand Down Expand Up @@ -81,7 +81,7 @@ const useUserStore = defineStore("user", () => {
return doResetPassword(payload);
};

const setUser = (userData: User | undefined) => {
const setUser = (userData: UserType | undefined) => {
user.value = userData;

localStorage.setItem(USER_KEY, JSON.stringify(userData));
Expand Down
4 changes: 2 additions & 2 deletions packages/vue-user/src/supertokens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { SUPERTOKENS_API_BASE_PATH_DEFAULT } from "../constant";
import useUserStore from "../store";
import verifyEmail, { getVerificationStatus } from "./verify-email";

import type { User } from "../types";
import type { UserType } from "../types";
import type { AppConfig } from "@dzangolab/vue3-config";

const initSupertokens = (config: AppConfig) => {
Expand Down Expand Up @@ -47,7 +47,7 @@ const isLoggedIn = async () => {
return await Session.doesSessionExist();
};

const getUser = async (): Promise<User | undefined> => {
const getUser = async (): Promise<UserType | undefined> => {
const { getUser } = useUserStore();

if (await isLoggedIn()) {
Expand Down
8 changes: 4 additions & 4 deletions packages/vue-user/src/supertokens/login.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { emailPasswordSignIn } from "supertokens-web-js/recipe/thirdpartyemailpassword";

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

const login = async (
credentials: LoginCredentials,
): Promise<User | undefined> => {
let user: User | undefined;
): Promise<UserType | undefined> => {
let user: UserType | undefined;
let response;

const data = {
Expand All @@ -29,7 +29,7 @@ const login = async (
}

if (response.status === "OK") {
user = response.user;
user = response.user as UserType;

return user;
} else if (response.status === "WRONG_CREDENTIALS_ERROR") {
Expand Down
8 changes: 4 additions & 4 deletions packages/vue-user/src/supertokens/signup.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { emailPasswordSignUp } from "supertokens-web-js/recipe/thirdpartyemailpassword";

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

const signup = async (
credentials: LoginCredentials,
): Promise<User | undefined> => {
let user: User | undefined;
): Promise<UserType | undefined> => {
let user: UserType | undefined;
let response;

const data = {
Expand All @@ -29,7 +29,7 @@ const signup = async (
}

if (response.status === "OK") {
user = response.user;
user = response.user as UserType;

return user;
} else if (response.status === "FIELD_ERROR") {
Expand Down
1 change: 1 addition & 0 deletions packages/vue-user/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface DzangolabVueUserConfig {
showCheckbox?: boolean;
};
};
updateEmail?: boolean;
};
password?: {
minLength: number;
Expand Down
5 changes: 4 additions & 1 deletion packages/vue-user/src/views/Profile.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<template>
<Page :title="t('user.profile.title')" />
<Page :title="t('user.profile.title')" class="profile">
<AccountInfo />
</Page>
</template>

<script lang="ts">
Expand All @@ -12,6 +14,7 @@ export default {
import { useI18n } from "@dzangolab/vue3-i18n";
import { Page } from "@dzangolab/vue3-ui";

import AccountInfo from "../components/profile/AccountInfo.vue";
import { useTranslations } from "../index";

const messages = useTranslations();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe("Profile", () => {
],
stubs: {
RouterLink: RouterLinkStub,
AccountInfo: true,
},
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`Profile > matches snapshot in en 1`] = `
<div
class="page"
class="page profile"
>
<h1>
Profile
Expand All @@ -16,14 +16,15 @@ exports[`Profile > matches snapshot in en 1`] = `
</div>
<main>

<account-info-stub />

</main>
</div>
`;

exports[`Profile > matches snapshot in fr 1`] = `
<div
class="page"
class="page profile"
>
<h1>
Profil
Expand All @@ -37,6 +38,7 @@ exports[`Profile > matches snapshot in fr 1`] = `
</div>
<main>

<account-info-stub />

</main>
</div>
Expand Down
Loading