Skip to content

Commit

Permalink
fix(vue-demo): double opt in registration (#1489)
Browse files Browse the repository at this point in the history
* fix(vue-demo): double opt in registration

* fix: changes after CR

* feat(vue-demo): add confirmation page

* chore: remove svgs

---------

Co-authored-by: patzick <[email protected]>
  • Loading branch information
mdanilowicz and patzick authored Dec 4, 2024
1 parent 9c84519 commit 2c337b5
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/funny-chicken-play.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@shopware-pwa/composables-next": minor
---

Changed `registration` method in the `useUser` composable. Because of changes in the double opt-in on registration flow in the Shopware backend we are adjusting this method on our side. In new approach we are checking `active` and `doubleOptInRegistration` properties that represents current status of the user.
5 changes: 5 additions & 0 deletions .changeset/light-games-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vue-demo-store": patch
---

Fix registration form for the double opt in registration flow
5 changes: 5 additions & 0 deletions .changeset/young-chicken-confess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vue-demo-store": minor
---

Added a confirmation page after the double opt-in option. The confirmation link is included in the email after registration.
25 changes: 25 additions & 0 deletions packages/composables/src/useUser/useUser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,31 @@ describe("useUser", () => {
expect(vm.isLoggedIn).toBe(true);
});

it("register function with double opt-in option should not automatically log user in", async () => {
const { vm, injections } = useSetup(() => useUser());
injections.apiClient.invoke.mockResolvedValue({
data: {
active: true,
doubleOptInRegistration: true,
id: "test123",
guest: false,
},
});

await vm.register(REGISTRATION_DATA);

expect(injections.apiClient.invoke).toHaveBeenCalledWith(
expect.stringContaining("register"),
expect.objectContaining({
body: {
...REGISTRATION_DATA,
storefrontUrl: "http://localhost:3000", // This is the default value from the useInternationalization
},
}),
);
expect(vm.isLoggedIn).toBe(false);
});

it("logout", async () => {
const { vm, injections } = useSetup(() => useUser());
injections.apiClient.invoke.mockResolvedValue({ data: {} });
Expand Down
7 changes: 5 additions & 2 deletions packages/composables/src/useUser/useUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,11 @@ export function useUser(): UseUserReturn {
storefrontUrl: getStorefrontUrl(),
},
});
_user.value = data;
if (_user.value?.active) await refreshSessionContext();
// Update the user data in the context if the user is active and not using double opt-in registration set in the Shopware Admin
if (data.active && !data.doubleOptInRegistration) {
_user.value = data;
}
await refreshSessionContext();
return data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,13 @@ const invokeSubmit = async () => {
try {
loading.value = true;
const response = await register(state);
if (response?.active) router.push("/");
else if (response && !response.active) {
if (response?.doubleOptInRegistration) {
Object.assign(state, JSON.parse(JSON.stringify(initialState)));
showDoubleOptInBox.value = true;
await nextTick();
doubleOptInBox.value?.scrollIntoView();
$v.value.$reset();
}
} else if (response?.active) router.push("/");
} catch (error) {
if (error instanceof ApiClientError) {
const errors = resolveApiErrors(error.details.errors);
Expand Down Expand Up @@ -147,7 +146,8 @@ useBreadcrumbs([
{{ $t("account.messages.signUpSuccess") }}
</div>
<form
class="w-full relative"
v-if="!showDoubleOptInBox"
class="w-full relative mt-10"
data-testid="registration-form"
@submit.prevent="invokeSubmit"
>
Expand Down
3 changes: 2 additions & 1 deletion templates/vue-demo-store/i18n/de-DE/account.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"paymentSetSuccessfully": "Standardzahlungsmethode erfolgreich festgelegt",
"signUpSuccess": "Vielen Dank für Ihre Registrierung! Sie erhalten in Kürze eine Bestätigungs-E-Mail. Klicken Sie auf den Link darin, um die Registrierung abzuschließen.",
"paymentMethodChanged": "Zahlungsmethode geändert",
"productsAdded": "Produkte hinzugefügt"
"productsAdded": "Produkte hinzugefügt",
"verifying": "Konto bestätigen"
}
}
}
3 changes: 2 additions & 1 deletion templates/vue-demo-store/i18n/de-DE/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"CHECKOUT__UNKNOWN_PAYMENT_METHOD": "Die ausgewählte Zahlungsmethode existiert nicht.",
"VIOLATION::TOO_SHORT_ERROR": "{field} ist zu kurz.",
"CHECKOUT__ORDER_ORDER_ALREADY_PAID": "Die Bestellung mit der Bestellnummer {orderNumber} wurde bereits bezahlt und kann nicht mehr bearbeitet werden.",
"CHECKOUT__ORDER_ORDER_NOT_FOUND": "Diese Bestellung konnte nicht gefunden werden."
"CHECKOUT__ORDER_ORDER_NOT_FOUND": "Diese Bestellung konnte nicht gefunden werden.",
"CHECKOUT__CUSTOMER_IS_ALREADY_CONFIRMED": "Die E-Mail-Adresse wurde bereits bestätigt oder die URL ist ungültig."
}
}
3 changes: 2 additions & 1 deletion templates/vue-demo-store/i18n/en-GB/account.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
"paymentSetSuccessfully": "Set default payment method successfully",
"signUpSuccess": "Thank you for signing up! You will receive a confirmation email shortly. Click on the link in it to complete the sign-up.",
"paymentMethodChanged": "Payment method changed successfully",
"productsAdded": "Products added to cart"
"productsAdded": "Products added to cart",
"verifying": "Account confirmation"
}
}
}
3 changes: 2 additions & 1 deletion templates/vue-demo-store/i18n/en-GB/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"CHECKOUT__UNKNOWN_PAYMENT_METHOD": "The selected payment method does not exist.",
"VIOLATION::TOO_SHORT_ERROR": "{field} is too short.",
"CHECKOUT__ORDER_ORDER_ALREADY_PAID": "The order with the order number {orderNumber} was already paid and cannot be edited afterwards.",
"CHECKOUT__ORDER_ORDER_NOT_FOUND": "This order could not be found."
"CHECKOUT__ORDER_ORDER_NOT_FOUND": "This order could not be found.",
"CHECKOUT__CUSTOMER_IS_ALREADY_CONFIRMED": "Either the email address has already been confirmed or the URL is invalid."
}
}
3 changes: 2 additions & 1 deletion templates/vue-demo-store/i18n/pl-PL/account.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"paymentSetSuccessfully": "Ustawiono domyślną metodę płatności",
"signUpSuccess": "Dziękujemy za rejestrację! Wkrótce otrzymasz e-mail z potwierdzeniem. Kliknij w link w nim zawarty, aby ukończyć rejestrację.",
"paymentMethodChanged": "Metoda płatności została zmieniona",
"productsAdded": "Produkty zostały dodane do koszyka"
"productsAdded": "Produkty zostały dodane do koszyka",
"verifying": "Potwierdzenie konta"
}
}
}
3 changes: 2 additions & 1 deletion templates/vue-demo-store/i18n/pl-PL/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"CHECKOUT__UNKNOWN_PAYMENT_METHOD": "Wybrana metoda płatności nie istnieje.",
"VIOLATION::TOO_SHORT_ERROR": "{field} jest za krótkie.",
"CHECKOUT__ORDER_ORDER_ALREADY_PAID": "Zamówienie o numerze {orderNumber} zostało już opłacone i nie może zostać zrealizowane.",
"CHECKOUT__ORDER_ORDER_NOT_FOUND": "Nie udało się znaleźć tego zamówienia."
"CHECKOUT__ORDER_ORDER_NOT_FOUND": "Nie udało się znaleźć tego zamówienia.",
"CHECKOUT__CUSTOMER_IS_ALREADY_CONFIRMED": "Adres e-mail został już potwierdzony lub URL jest nieprawidłowy."
}
}
57 changes: 57 additions & 0 deletions templates/vue-demo-store/pages/registration/confirm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<script setup lang="ts">
import { ApiClientError } from "@shopware/api-client";
import type { ApiError } from "@shopware/api-client";
const { apiClient } = useShopwareContext();
const { refreshSessionContext } = useSessionContext();
const { pushSuccess, pushError } = useNotifications();
const { query } = useRoute();
const router = useRouter();
const { t } = useI18n();
const hash = query.hash;
const em = query.em;
const alreadyConfirmedError = ref(false);
onMounted(async () => {
try {
await apiClient.invoke("registerConfirm post /account/register-confirm", {
body: {
hash: hash as string,
em: em as string,
},
});
await refreshSessionContext();
pushSuccess(t("account.messages.loggedInSuccess"));
router.push({ path: "/" });
} catch (error) {
if (error instanceof ApiClientError) {
if (
error.details.errors[0].code ===
"CHECKOUT__CUSTOMER_IS_ALREADY_CONFIRMED"
) {
alreadyConfirmedError.value = true;
} else {
for (const singleError of error.details.errors) {
if (singleError?.detail) {
pushError(singleError.detail);
}
}
}
}
}
});
</script>
<template>
<div class="flex justify-center items-center my-20">
<div v-if="!alreadyConfirmedError" class="flex flex-row items-center">
<p class="text-15">{{ $t("account.messages.verifying") }}</p>
<div class="ml-10 size-15 i-carbon-circle-dash animate-spin animate-count-infinite animate-duration-2000" />
</div>
<div v-else class="text-red flex items-center gap-5">
<div class="w-10 h-10 i-carbon-error" />
<p class="text-xl">
{{ $t("errors.CHECKOUT__CUSTOMER_IS_ALREADY_CONFIRMED") }}
</p>
</div>
</div>
</template>

0 comments on commit 2c337b5

Please sign in to comment.