diff --git a/examples/magento-graphcms/package.json b/examples/magento-graphcms/package.json index c4b978fd08..14ecaa1f18 100644 --- a/examples/magento-graphcms/package.json +++ b/examples/magento-graphcms/package.json @@ -52,6 +52,7 @@ "@graphcommerce/magento-customer": "8.0.3-canary.7", "@graphcommerce/magento-graphql": "8.0.3-canary.7", "@graphcommerce/magento-newsletter": "8.0.3-canary.7", + "@graphcommerce/magento-payment-adyen": "8.0.3-canary.7", "@graphcommerce/magento-payment-included": "8.0.3-canary.7", "@graphcommerce/magento-product": "8.0.3-canary.7", "@graphcommerce/magento-product-bundle": "8.0.3-canary.7", diff --git a/examples/magento-graphcms/pages/checkout/payment.tsx b/examples/magento-graphcms/pages/checkout/payment.tsx index d8326568fb..1c42559cb2 100644 --- a/examples/magento-graphcms/pages/checkout/payment.tsx +++ b/examples/magento-graphcms/pages/checkout/payment.tsx @@ -1,4 +1,4 @@ -import { ComposedForm, WaitForQueries } from '@graphcommerce/ecommerce-ui' +import { ComposedForm } from '@graphcommerce/ecommerce-ui' import { PageOptions } from '@graphcommerce/framer-next-pages' import { ApolloCartErrorFullPage, @@ -16,6 +16,7 @@ import { useCartLock, PaymentMethodActionCardListForm, PaymentMethodContextProvider, + WaitForPaymentQueries, } from '@graphcommerce/magento-cart-payment-method' import { SubscribeToNewsletter } from '@graphcommerce/magento-newsletter' import { PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' @@ -49,7 +50,7 @@ function PaymentPage() { - } title={}> @@ -141,7 +142,7 @@ function PaymentPage() { )} - + ) } diff --git a/packages/magento-cart-payment-method/index.ts b/packages/magento-cart-payment-method/index.ts index 7913dc2413..ecefc47ff5 100644 --- a/packages/magento-cart-payment-method/index.ts +++ b/packages/magento-cart-payment-method/index.ts @@ -9,3 +9,4 @@ export * from './PaymentMethodPlaceOrder/PaymentMethodPlaceOrder' export * from './PaymentMethodPlaceOrderNoop/PaymentMethodPlaceOrderNoop' export * from './PaymentMethodToggles/PaymentMethodToggles' export * from './PaymentMethodActionCardList/PaymentMethodActionCardListForm' +export { WaitForQueries as WaitForPaymentQueries } from '@graphcommerce/ecommerce-ui' diff --git a/packages/magento-payment-multisafepay/components/MSPPaymentHandler/MSPPaymentHandler.tsx b/packages/magento-payment-multisafepay/components/MSPPaymentHandler/MSPPaymentHandler.tsx index 0ae5e187f0..feb331c5f6 100644 --- a/packages/magento-payment-multisafepay/components/MSPPaymentHandler/MSPPaymentHandler.tsx +++ b/packages/magento-payment-multisafepay/components/MSPPaymentHandler/MSPPaymentHandler.tsx @@ -1,5 +1,5 @@ -import { useMutation } from '@graphcommerce/graphql' -import { useAssignCurrentCartId } from '@graphcommerce/magento-cart' +import { useApolloClient, useMutation } from '@graphcommerce/graphql' +import { useAssignCurrentCartId, useCurrentCartId } from '@graphcommerce/magento-cart' import { PaymentHandlerProps, usePaymentMethodContext, @@ -9,16 +9,25 @@ import { Trans } from '@lingui/react' import { useEffect } from 'react' import { useMSPCartLock } from '../../hooks/useMSPCartLock' import { MSPPaymentHandlerDocument } from './MSPPaymentHandler.gql' +import { CustomerTokenDocument } from '@graphcommerce/magento-customer' export const MSPPaymentHandler = (props: PaymentHandlerProps) => { const { code } = props const [lockStatus, , unlock] = useMSPCartLock() const assignCurrentCartId = useAssignCurrentCartId() const { onSuccess } = usePaymentMethodContext() - + const { cache } = useApolloClient() const [restore, { error }] = useMutation(MSPPaymentHandlerDocument) - const { justLocked, success, cart_id: cartId, locked, method, order_number } = lockStatus + const { + justLocked, + success, + cart_id: cartId, + locked, + method, + order_number, + customer_token, + } = lockStatus const canProceed = !(justLocked || !locked || !cartId || method !== code) @@ -26,15 +35,26 @@ export const MSPPaymentHandler = (props: PaymentHandlerProps) => { const shouldRestore = canProceed && success !== '1' useEffect(() => { if (!shouldRestore) return - + if (customer_token) + cache.writeQuery({ + query: CustomerTokenDocument, + data: { + customerToken: { + token: customer_token, + valid: true, + createdAt: new Date().toUTCString(), + __typename: 'CustomerToken', + }, + }, + broadcast: true, + }) // eslint-disable-next-line @typescript-eslint/no-floating-promises restore({ variables: { cartId } }).then(({ data }) => { if (!data?.getPaymentMeta) return undefined - assignCurrentCartId(data.getPaymentMeta) - return unlock({ success: null }) + return unlock({ success: null, order_number: null, customer_token: null }) }) - }, [assignCurrentCartId, cartId, restore, shouldRestore, unlock]) + }, [assignCurrentCartId, cache, cartId, customer_token, restore, shouldRestore, unlock]) // If successfull we clear it's cart and redirect to the success page. const shouldRedirect = canProceed && success === '1' diff --git a/packages/magento-payment-multisafepay/components/MSPPaymentPlaceOrder/MSPPaymentPlaceOrder.tsx b/packages/magento-payment-multisafepay/components/MSPPaymentPlaceOrder/MSPPaymentPlaceOrder.tsx index 40eec33b12..4e774218b8 100644 --- a/packages/magento-payment-multisafepay/components/MSPPaymentPlaceOrder/MSPPaymentPlaceOrder.tsx +++ b/packages/magento-payment-multisafepay/components/MSPPaymentPlaceOrder/MSPPaymentPlaceOrder.tsx @@ -11,6 +11,7 @@ import { useRouter } from 'next/router' import { useMSPCartLock } from '../../hooks/useMSPCartLock' import { MSPPaymentHandlerDocument } from '../MSPPaymentHandler/MSPPaymentHandler.gql' import { MSPPaymentPlaceOrderDocument } from './MSPPaymentPlaceOrder.gql' +import { useCustomerSession } from '@graphcommerce/magento-customer' export function MSPPaymentPlaceOrder(props: PaymentPlaceOrderProps) { const { code, step } = props @@ -21,6 +22,7 @@ export function MSPPaymentPlaceOrder(props: PaymentPlaceOrderProps) { const [restoreCart, restoreResult] = useMutation(MSPPaymentHandlerDocument) const billingPage = useCartQuery(BillingPageDocument) + const { token } = useCustomerSession() /** * In the this folder you'll also find a PaymentMethodOptionsNoop.graphql document that is @@ -51,6 +53,7 @@ export function MSPPaymentPlaceOrder(props: PaymentPlaceOrderProps) { await lock({ method: selectedMethod.code, order_number: result.data?.placeOrder?.order.order_number, + customer_token: token, }) await new Promise((resolve) => setTimeout(resolve, 1000)) diff --git a/packages/magento-payment-multisafepay/hooks/useMSPCartLock.ts b/packages/magento-payment-multisafepay/hooks/useMSPCartLock.ts index af5581cb4e..7596d1f3f1 100644 --- a/packages/magento-payment-multisafepay/hooks/useMSPCartLock.ts +++ b/packages/magento-payment-multisafepay/hooks/useMSPCartLock.ts @@ -3,6 +3,7 @@ import { CartLockState, useCartLock } from '@graphcommerce/magento-cart-payment- type MSPLockState = CartLockState & { success?: string | null order_number?: string | null + customer_token?: string | null } /** diff --git a/packages/magento-payment-multisafepay/hooks/useMSPCartRevive.ts b/packages/magento-payment-multisafepay/hooks/useMSPCartRevive.ts new file mode 100644 index 0000000000..5cee35396e --- /dev/null +++ b/packages/magento-payment-multisafepay/hooks/useMSPCartRevive.ts @@ -0,0 +1,65 @@ +import { useApolloClient, useMutation } from '@graphcommerce/graphql' +import { useAssignCurrentCartId, useCartQuery, useCurrentCartId } from '@graphcommerce/magento-cart' +import { BillingPageDocument } from '@graphcommerce/magento-cart-checkout' +import { CustomerTokenDocument } from '@graphcommerce/magento-customer' +import { useEffect } from 'react' +import { MSPPaymentHandlerDocument } from '../components/MSPPaymentHandler/MSPPaymentHandler.gql' +import { useMSPCartLock } from './useMSPCartLock' + +export function useMSPReviveCart() { + const [{ cart_id, method, customer_token }, , unlock] = useMSPCartLock() + const billingPage = useCartQuery(BillingPageDocument, { fetchPolicy: 'cache-only' }) + const client = useApolloClient() + const { currentCartId } = useCurrentCartId() + const assignCurrentCartId = useAssignCurrentCartId() + const [restore, { error, loading }] = useMutation(MSPPaymentHandlerDocument) + + const reviveNow = + cart_id && + !billingPage.data?.cart?.id && + method?.startsWith('multisafepay_') && + currentCartId !== cart_id + + useEffect(() => { + if (!reviveNow) return // eslint-disable-next-line @typescript-eslint/no-floating-promises + ;(async () => { + // In GraphCommerce 8 the user would automatically be presented with a restore session dialog + if (customer_token) { + client.cache.writeQuery({ + query: CustomerTokenDocument, + broadcast: true, + data: { + customerToken: { + __typename: 'CustomerToken', + token: customer_token, + createdAt: new Date().toUTCString(), + valid: true, + }, + }, + }) + } else { + client.cache.evict({ fieldName: 'customerToken' }) + } + + const restoredId = (await restore({ variables: { cartId: cart_id } })).data?.getPaymentMeta + + if (restoredId) assignCurrentCartId(restoredId) + + await unlock({ customer_token: null, order_number: null, success: null }) + })() + }, [ + assignCurrentCartId, + billingPage, + cart_id, + client.cache, + currentCartId, + customer_token, + error, + restore, + reviveNow, + unlock, + ]) + + if (billingPage.data) return !billingPage.loading + return !loading +} diff --git a/packages/magento-payment-multisafepay/package.json b/packages/magento-payment-multisafepay/package.json index ddb885ae8b..1c7c5ddd15 100644 --- a/packages/magento-payment-multisafepay/package.json +++ b/packages/magento-payment-multisafepay/package.json @@ -21,6 +21,7 @@ "@graphcommerce/magento-cart-checkout": "^8.0.3-canary.7", "@graphcommerce/magento-cart-payment-method": "^8.0.3-canary.7", "@graphcommerce/magento-cart-shipping-address": "^8.0.3-canary.7", + "@graphcommerce/magento-customer": "^8.0.3-canary.7", "@graphcommerce/magento-product": "^8.0.3-canary.7", "@graphcommerce/magento-product-configurable": "^8.0.3-canary.7", "@graphcommerce/magento-store": "^8.0.3-canary.7", diff --git a/packages/magento-payment-multisafepay/plugins/UseMSPReviveCart.tsx b/packages/magento-payment-multisafepay/plugins/UseMSPReviveCart.tsx new file mode 100644 index 0000000000..ee1c443fe4 --- /dev/null +++ b/packages/magento-payment-multisafepay/plugins/UseMSPReviveCart.tsx @@ -0,0 +1,20 @@ +import { WaitForPaymentQueries } from '@graphcommerce/magento-cart-payment-method' +import type { PluginProps } from '@graphcommerce/next-config' +import { ComponentProps } from 'react' +import { useMSPReviveCart } from '../hooks/useMSPCartRevive' + +export const component = 'WaitForPaymentQueries' +export const exported = '@graphcommerce/magento-cart-payment-method' + +function UseMSPReviveCart(props: PluginProps>) { + const { Prev, waitFor: w, ...rest } = props + const reviving = useMSPReviveCart() + + let waitFor: typeof w + + if (w) waitFor = [...(Array.isArray(w) ? w : [w]), reviving] + else waitFor = reviving + + return +} +export const Plugin = UseMSPReviveCart diff --git a/packages/magento-payment-paypal/components/PayPalPaymentPlaceOrder/PayPalPaymentPlaceOrder.tsx b/packages/magento-payment-paypal/components/PayPalPaymentPlaceOrder/PayPalPaymentPlaceOrder.tsx index 89b18bba6b..20f3d3530e 100644 --- a/packages/magento-payment-paypal/components/PayPalPaymentPlaceOrder/PayPalPaymentPlaceOrder.tsx +++ b/packages/magento-payment-paypal/components/PayPalPaymentPlaceOrder/PayPalPaymentPlaceOrder.tsx @@ -4,11 +4,13 @@ import { PaymentPlaceOrderProps } from '@graphcommerce/magento-cart-payment-meth import { useRouter } from 'next/router' import { usePayPalCartLock } from '../../hooks/usePayPalCartLock' import { PayPalPaymentPlaceOrderDocument } from './PayPalPaymentPlaceOrder.gql' +import { useCustomerSession } from '@graphcommerce/magento-customer' export function PayPalPaymentPlaceOrder(props: PaymentPlaceOrderProps) { const { code, step } = props const [, lock] = usePayPalCartLock() const { push } = useRouter() + const { token: sessionToken } = useCustomerSession() const form = useFormGqlMutationCart(PayPalPaymentPlaceOrderDocument, { onBeforeSubmit: (variables) => ({ @@ -27,7 +29,7 @@ export function PayPalPaymentPlaceOrder(props: PaymentPlaceOrderProps) { 'Error while starting the PayPal payment, please try again with a different payment method', ) - await lock({ token, method: code, PayerID: null }) + await lock({ token, method: code, PayerID: null, customerToken: sessionToken }) // We are going to redirect, but we're not waiting, because we need to complete the submission to release the buttons // eslint-disable-next-line @typescript-eslint/no-floating-promises push(start) diff --git a/packages/magento-payment-paypal/graphql/UsePayPalCartRevive.graphql b/packages/magento-payment-paypal/graphql/UsePayPalCartRevive.graphql new file mode 100644 index 0000000000..26303ec45c --- /dev/null +++ b/packages/magento-payment-paypal/graphql/UsePayPalCartRevive.graphql @@ -0,0 +1,15 @@ +mutation UsePayPalCartRevive($cartId: String!, $paymentMethod: PaymentMethodInput!) { + setPaymentMethodOnCart(input: { cart_id: $cartId, payment_method: $paymentMethod }) { + cart { + __typename + id + email + ...BillingAddress + ...ShippingAddress + ...Coupon + ...PaymentMethodContext + ...OrderSuccesPage + ...PaymentMethodUpdated + } + } +} diff --git a/packages/magento-payment-paypal/hooks/usePayPalCartLock.ts b/packages/magento-payment-paypal/hooks/usePayPalCartLock.ts index a965d49bb2..aa47e040e9 100644 --- a/packages/magento-payment-paypal/hooks/usePayPalCartLock.ts +++ b/packages/magento-payment-paypal/hooks/usePayPalCartLock.ts @@ -3,6 +3,7 @@ import { CartLockState, useCartLock } from '@graphcommerce/magento-cart-payment- type PayPalLockState = CartLockState & { token?: string | null PayerID: string | null + customerToken?: string | null } /** diff --git a/packages/magento-payment-paypal/hooks/usePayPalCartRevive.ts b/packages/magento-payment-paypal/hooks/usePayPalCartRevive.ts new file mode 100644 index 0000000000..4a9e3979d6 --- /dev/null +++ b/packages/magento-payment-paypal/hooks/usePayPalCartRevive.ts @@ -0,0 +1,77 @@ +import { useApolloClient, useMutation } from '@graphcommerce/graphql' +import { useCartQuery } from '@graphcommerce/magento-cart' +import { BillingPageDocument } from '@graphcommerce/magento-cart-checkout' +import { CustomerTokenDocument } from '@graphcommerce/magento-customer' +import { useEffect } from 'react' +import { PayPalPaymentHandlerDocument } from '../components/PayPalPaymentHandler/PayPalPaymentHandler.gql' +import { usePayPalCartLock } from './usePayPalCartLock' +import { UsePayPalCartReviveDocument } from '../graphql/UsePayPalCartRevive.gql' + +type UsePayPalCartReviveProps = { + code: string | null +} + +export function usePayPalCartRevive(props: UsePayPalCartReviveProps) { + const { code } = props + const [lockStatus] = usePayPalCartLock() + + const { token, PayerID, customerToken, method, cart_id: cartId } = lockStatus + const [placeOrder, result] = useMutation(UsePayPalCartReviveDocument) + + const billingPage = useCartQuery(BillingPageDocument, { fetchPolicy: 'cache-only' }) + const client = useApolloClient() + + const reviveNow = + cartId && + !billingPage.data?.cart?.id && + method?.startsWith('paypal_') && + PayerID && + token && + code + + useEffect(() => { + if (!reviveNow) return // eslint-disable-next-line @typescript-eslint/no-floating-promises + ;(async () => { + // In GraphCommerce 8 the user would automatically be presented with a restore session dialog + if (customerToken) { + client.cache.writeQuery({ + query: CustomerTokenDocument, + broadcast: true, + data: { + customerToken: { + __typename: 'CustomerToken', + token: customerToken, + createdAt: new Date().toUTCString(), + valid: true, + }, + }, + }) + } else { + client.cache.evict({ fieldName: 'customerToken' }) + } + + const cart = ( + await placeOrder({ + variables: { + cartId, + paymentMethod: { code, paypal_express: { token, payer_id: PayerID } }, + }, + }) + ).data?.setPaymentMethodOnCart?.cart + + if (!cart) { + console.log('Could not revive cart') + return + } + client.cache.writeQuery({ + query: BillingPageDocument, + variables: { cartId }, + data: { cart }, + broadcast: true, + }) + })() + }, [PayerID, cartId, client.cache, code, customerToken, placeOrder, reviveNow, token]) + + if (billingPage.data) return !billingPage.loading + return !result.loading +} diff --git a/packages/magento-payment-paypal/package.json b/packages/magento-payment-paypal/package.json index f18bbb2521..c430a76bc1 100644 --- a/packages/magento-payment-paypal/package.json +++ b/packages/magento-payment-paypal/package.json @@ -17,7 +17,9 @@ "@graphcommerce/graphql": "^8.0.3-canary.7", "@graphcommerce/image": "^8.0.3-canary.7", "@graphcommerce/magento-cart": "^8.0.3-canary.7", + "@graphcommerce/magento-cart-checkout": "^8.0.3-canary.7", "@graphcommerce/magento-cart-payment-method": "^8.0.3-canary.7", + "@graphcommerce/magento-customer": "^8.0.3-canary.7", "@graphcommerce/magento-store": "^8.0.3-canary.7", "@graphcommerce/next-ui": "^8.0.3-canary.7", "@graphcommerce/prettier-config-pwa": "^8.0.3-canary.7", diff --git a/packages/magento-payment-paypal/plugins/UsePayPalReviveCart.tsx b/packages/magento-payment-paypal/plugins/UsePayPalReviveCart.tsx new file mode 100644 index 0000000000..5d8617cc7a --- /dev/null +++ b/packages/magento-payment-paypal/plugins/UsePayPalReviveCart.tsx @@ -0,0 +1,21 @@ +import { WaitForPaymentQueries } from '@graphcommerce/magento-cart-payment-method' +import type { PluginProps } from '@graphcommerce/next-config' +import { ComponentProps } from 'react' +import { usePayPalCartRevive } from '../hooks/usePayPalCartRevive' + +export const component = 'WaitForPaymentQueries' +export const exported = '@graphcommerce/magento-cart-payment-method' + +function UsePayPalReviveCart(props: PluginProps>) { + const { Prev, waitFor: w, ...rest } = props + + const reviving = usePayPalCartRevive({ code: 'paypal_express' }) + + let waitFor: typeof w + + if (w) waitFor = [...(Array.isArray(w) ? w : [w]), reviving] + else waitFor = reviving + + return +} +export const Plugin = UsePayPalReviveCart diff --git a/packages/mollie-magento-payment/components/MolliePlaceOrder/MolliePlaceOrder.tsx b/packages/mollie-magento-payment/components/MolliePlaceOrder/MolliePlaceOrder.tsx index c883d5d0ea..8bf3f51f7c 100644 --- a/packages/mollie-magento-payment/components/MolliePlaceOrder/MolliePlaceOrder.tsx +++ b/packages/mollie-magento-payment/components/MolliePlaceOrder/MolliePlaceOrder.tsx @@ -1,5 +1,7 @@ +import { useApolloClient } from '@graphcommerce/graphql' import { useFormGqlMutationCart } from '@graphcommerce/magento-cart' import { PaymentPlaceOrderProps } from '@graphcommerce/magento-cart-payment-method' +import { CustomerTokenDocument } from '@graphcommerce/magento-customer' import { useFormCompose } from '@graphcommerce/react-hook-form' import { useRouter } from 'next/router' import { useCartLockWithToken } from '../../hooks/useCartLockWithToken' @@ -9,6 +11,7 @@ export function MolliePlaceOrder(props: PaymentPlaceOrderProps) { const { step, code } = props const { push } = useRouter() const [, lock] = useCartLockWithToken() + const { cache } = useApolloClient() const form = useFormGqlMutationCart(MolliePlaceOrderDocument, { onBeforeSubmit(variables) { @@ -19,6 +22,8 @@ export function MolliePlaceOrder(props: PaymentPlaceOrderProps) { current.searchParams.set('order_number', 'ORDER_NUMBER') current.searchParams.set('method', code) current.searchParams.set('locked', '1') + const customerToken = cache.readQuery({ query: CustomerTokenDocument })?.customerToken?.token + if (customerToken) current.searchParams.set('customer_token', customerToken) const returnUrl = current .toString() .replace('PAYMENT_TOKEN', '{{payment_token}}') @@ -33,7 +38,14 @@ export function MolliePlaceOrder(props: PaymentPlaceOrderProps) { // When redirecting to the payment gateway if (mollie_redirect_url && mollie_payment_token) { - await lock({ mollie_payment_token, method: code, order_number }) + const customerToken = cache.readQuery({ query: CustomerTokenDocument })?.customerToken + ?.token + await lock({ + mollie_payment_token, + method: code, + order_number, + customer_token: customerToken, + }) await new Promise((resolve) => { setTimeout(resolve, 1000) }) diff --git a/packages/mollie-magento-payment/graphql/ReviveCart.graphql b/packages/mollie-magento-payment/graphql/ReviveCart.graphql new file mode 100644 index 0000000000..93f375799e --- /dev/null +++ b/packages/mollie-magento-payment/graphql/ReviveCart.graphql @@ -0,0 +1,15 @@ +mutation ReviveCart($cartId: String!) { + mollieRestoreCart(input: { cart_id: $cartId }) { + cart { + __typename + id + email + ...BillingAddress + ...ShippingAddress + ...Coupon + ...PaymentMethodContext + ...CartItems + ...CartTotals + } + } +} diff --git a/packages/mollie-magento-payment/hooks/useCartLockWithToken.ts b/packages/mollie-magento-payment/hooks/useCartLockWithToken.ts index f736ae916a..a874cad400 100644 --- a/packages/mollie-magento-payment/hooks/useCartLockWithToken.ts +++ b/packages/mollie-magento-payment/hooks/useCartLockWithToken.ts @@ -3,6 +3,7 @@ import { CartLockState, useCartLock } from '@graphcommerce/magento-cart-payment- type MollieLockState = CartLockState & { mollie_payment_token: string | null order_number?: string | null + customer_token?: string | null } export const useCartLockWithToken = () => useCartLock() diff --git a/packages/mollie-magento-payment/hooks/useMollieReviveCart.ts b/packages/mollie-magento-payment/hooks/useMollieReviveCart.ts new file mode 100644 index 0000000000..e42b4ffcdc --- /dev/null +++ b/packages/mollie-magento-payment/hooks/useMollieReviveCart.ts @@ -0,0 +1,55 @@ +import { useApolloClient, useMutation } from '@graphcommerce/graphql' +import { useCartQuery } from '@graphcommerce/magento-cart' +import { BillingPageDocument } from '@graphcommerce/magento-cart-checkout' +import { CustomerTokenDocument } from '@graphcommerce/magento-customer' +import { useEffect } from 'react' +import { useCartLockWithToken } from './useCartLockWithToken' +import { ReviveCartDocument } from '../graphql/ReviveCart.gql' + +export function useMollieReviveCart() { + const [{ cart_id, method, customer_token }] = useCartLockWithToken() + const billingPage = useCartQuery(BillingPageDocument, { fetchPolicy: 'cache-only' }) + const client = useApolloClient() + const [revive, result] = useMutation(ReviveCartDocument) + + const reviveNow = cart_id && !billingPage.data?.cart?.id && method?.startsWith('mollie_') + + useEffect(() => { + if (!reviveNow) return // eslint-disable-next-line @typescript-eslint/no-floating-promises + ;(async () => { + // In GraphCommerce 8 the user would automatically be presented with a restore session dialog + if (customer_token) { + client.cache.writeQuery({ + query: CustomerTokenDocument, + broadcast: true, + data: { + customerToken: { + __typename: 'CustomerToken', + token: customer_token, + createdAt: new Date().toUTCString(), + valid: true, + }, + }, + }) + } else { + client.cache.evict({ fieldName: 'customerToken' }) + } + + const cart = (await revive({ variables: { cartId: cart_id } })).data?.mollieRestoreCart?.cart + + if (!cart) { + console.log('Could not revive cart') + return + } + client.cache.writeQuery({ + query: BillingPageDocument, + variables: { cartId: cart_id }, + data: { cart }, + broadcast: true, + }) + })() + }, [cart_id, client.cache, customer_token, revive, reviveNow]) + + if (billingPage.data) return !billingPage.loading + return !result.loading +} diff --git a/packages/mollie-magento-payment/plugins/UseMollieCartRevive.tsx b/packages/mollie-magento-payment/plugins/UseMollieCartRevive.tsx new file mode 100644 index 0000000000..1549d0d17d --- /dev/null +++ b/packages/mollie-magento-payment/plugins/UseMollieCartRevive.tsx @@ -0,0 +1,20 @@ +import { WaitForPaymentQueries } from '@graphcommerce/magento-cart-payment-method' +import type { PluginProps } from '@graphcommerce/next-config' +import { ComponentProps } from 'react' +import { useMollieReviveCart } from '../hooks/useMollieReviveCart' + +export const component = 'WaitForPaymentQueries' +export const exported = '@graphcommerce/magento-cart-payment-method' + +function UseMollieReviveCart(props: PluginProps>) { + const { Prev, waitFor: w, ...rest } = props + const reviving = useMollieReviveCart() + + let waitFor: typeof w + + if (w) waitFor = [...(Array.isArray(w) ? w : [w]), reviving] + else waitFor = reviving + + return +} +export const Plugin = UseMollieReviveCart diff --git a/yarn.lock b/yarn.lock index d3de2b4531..c7b0fb21b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3677,6 +3677,7 @@ __metadata: "@graphcommerce/magento-customer": "npm:8.0.3-canary.7" "@graphcommerce/magento-graphql": "npm:8.0.3-canary.7" "@graphcommerce/magento-newsletter": "npm:8.0.3-canary.7" + "@graphcommerce/magento-payment-adyen": "npm:8.0.3-canary.7" "@graphcommerce/magento-payment-included": "npm:8.0.3-canary.7" "@graphcommerce/magento-product": "npm:8.0.3-canary.7" "@graphcommerce/magento-product-bundle": "npm:8.0.3-canary.7" @@ -3794,7 +3795,7 @@ __metadata: languageName: unknown linkType: soft -"@graphcommerce/magento-payment-adyen@workspace:packages/magento-payment-adyen": +"@graphcommerce/magento-payment-adyen@npm:8.0.3-canary.7, @graphcommerce/magento-payment-adyen@workspace:packages/magento-payment-adyen": version: 0.0.0-use.local resolution: "@graphcommerce/magento-payment-adyen@workspace:packages/magento-payment-adyen" peerDependencies: @@ -3915,6 +3916,7 @@ __metadata: "@graphcommerce/magento-cart-checkout": ^8.0.3-canary.7 "@graphcommerce/magento-cart-payment-method": ^8.0.3-canary.7 "@graphcommerce/magento-cart-shipping-address": ^8.0.3-canary.7 + "@graphcommerce/magento-customer": ^8.0.3-canary.7 "@graphcommerce/magento-product": ^8.0.3-canary.7 "@graphcommerce/magento-product-configurable": ^8.0.3-canary.7 "@graphcommerce/magento-store": ^8.0.3-canary.7 @@ -3941,7 +3943,9 @@ __metadata: "@graphcommerce/graphql": ^8.0.3-canary.7 "@graphcommerce/image": ^8.0.3-canary.7 "@graphcommerce/magento-cart": ^8.0.3-canary.7 + "@graphcommerce/magento-cart-checkout": ^8.0.3-canary.7 "@graphcommerce/magento-cart-payment-method": ^8.0.3-canary.7 + "@graphcommerce/magento-customer": ^8.0.3-canary.7 "@graphcommerce/magento-store": ^8.0.3-canary.7 "@graphcommerce/next-ui": ^8.0.3-canary.7 "@graphcommerce/prettier-config-pwa": ^8.0.3-canary.7