diff --git a/.changeset/popular-suns-exercise.md b/.changeset/popular-suns-exercise.md new file mode 100644 index 0000000000..50223a13ad --- /dev/null +++ b/.changeset/popular-suns-exercise.md @@ -0,0 +1,5 @@ +--- +'@graphcommerce/magento-customer': minor +--- + +Added support for viewing Invoices/Shipments and Credit Memo's diff --git a/examples/magento-graphcms/pages/account/index.tsx b/examples/magento-graphcms/pages/account/index.tsx index b03e4f9190..6bfc5901c5 100644 --- a/examples/magento-graphcms/pages/account/index.tsx +++ b/examples/magento-graphcms/pages/account/index.tsx @@ -7,7 +7,6 @@ import { AddressSingleLine, getCustomerAccountIsDisabled, OrderStateLabel, - OrderStateLabelInline, SignOutForm, useCustomerQuery, WaitForCustomer, diff --git a/examples/magento-graphcms/pages/account/orders/credit-memo.tsx b/examples/magento-graphcms/pages/account/orders/credit-memo.tsx new file mode 100644 index 0000000000..cb935d8902 --- /dev/null +++ b/examples/magento-graphcms/pages/account/orders/credit-memo.tsx @@ -0,0 +1,117 @@ +import type { PageOptions } from '@graphcommerce/framer-next-pages' +import { + CreditMemoDetailPageDocument, + CreditMemoItems, + CreditMemoTotals, + getCustomerAccountIsDisabled, + OrderDetails, + SalesComments, + useCustomerQuery, + WaitForCustomer, +} from '@graphcommerce/magento-customer' +import { CountryRegionsDocument, PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' +import type { GetStaticProps } from '@graphcommerce/next-ui' +import { + FullPageMessage, + iconInvoice, + IconSvg, + LayoutOverlayHeader, + LayoutTitle, +} from '@graphcommerce/next-ui' +import { i18n } from '@lingui/core' +import { Trans } from '@lingui/macro' +import { Container } from '@mui/material' +import { useRouter } from 'next/router' +import type { LayoutOverlayProps } from '../../../components' +import { LayoutOverlay } from '../../../components' +import { graphqlSharedClient, graphqlSsrClient } from '../../../lib/graphql/graphqlSsrClient' + +type GetPageStaticProps = GetStaticProps + +function CreditMemoDetailPage() { + const router = useRouter() + const { orderNumber, creditMemoNumber } = router.query + + const creditMemos = useCustomerQuery(CreditMemoDetailPageDocument, { + fetchPolicy: 'cache-and-network', + variables: { orderNumber: orderNumber as string }, + skip: !orderNumber || !creditMemoNumber, + }) + const order = creditMemos.data?.customer?.orders?.items?.[0] + const creditMemo = order?.credit_memos?.find((c) => c?.number === creditMemoNumber) + + return ( + <> + + + Credit Memo #{creditMemoNumber} + + + + + {(!creditMemoNumber || !creditMemo || !order) && ( + Credit Memo not found} + icon={} + /> + )} + + {creditMemoNumber && creditMemo && order && ( + <> + ({ mb: theme.spacings.xxs })} + > + Credit Memo #{creditMemoNumber} + + + + + + {/* */} + + + ({ mb: theme.spacings.lg })} + /> + + )} + + + + ) +} + +const pageOptions: PageOptions = { + overlayGroup: 'account', + Layout: LayoutOverlay, +} +CreditMemoDetailPage.pageOptions = pageOptions + +export default CreditMemoDetailPage + +export const getStaticProps: GetPageStaticProps = async (context) => { + if (getCustomerAccountIsDisabled(context.locale)) return { notFound: true } + + const client = graphqlSharedClient(context) + const staticClient = graphqlSsrClient(context) + const config = client.query({ query: StoreConfigDocument }) + + const countryRegions = staticClient.query({ + query: CountryRegionsDocument, + }) + + return { + props: { + ...(await countryRegions).data, + apolloState: await config.then(() => client.cache.extract()), + variantMd: 'bottom', + up: { href: '/account/orders', title: i18n._(/* i18n */ 'Orders') }, + }, + } +} diff --git a/examples/magento-graphcms/pages/account/orders/index.tsx b/examples/magento-graphcms/pages/account/orders/index.tsx index d3bf548a3f..23a06ee6cf 100644 --- a/examples/magento-graphcms/pages/account/orders/index.tsx +++ b/examples/magento-graphcms/pages/account/orders/index.tsx @@ -34,6 +34,7 @@ function AccountOrdersPage() { pageSize: 5, currentPage: Number(query?.page ?? 1), }, + errorPolicy: 'all', }) const { data } = orders const customer = data?.customer @@ -47,7 +48,7 @@ function AccountOrdersPage() { - + {customer?.orders && customer.orders.items.length > 0 && ( <> diff --git a/examples/magento-graphcms/pages/account/orders/invoice.tsx b/examples/magento-graphcms/pages/account/orders/invoice.tsx new file mode 100644 index 0000000000..66ae116ca1 --- /dev/null +++ b/examples/magento-graphcms/pages/account/orders/invoice.tsx @@ -0,0 +1,117 @@ +import type { PageOptions } from '@graphcommerce/framer-next-pages' +import { + getCustomerAccountIsDisabled, + InvoiceDetailPageDocument, + InvoiceItems, + InvoiceTotals, + OrderDetails, + SalesComments, + useCustomerQuery, + WaitForCustomer, +} from '@graphcommerce/magento-customer' +import { CountryRegionsDocument, PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' +import type { GetStaticProps } from '@graphcommerce/next-ui' +import { + FullPageMessage, + iconInvoice, + IconSvg, + LayoutOverlayHeader, + LayoutTitle, +} from '@graphcommerce/next-ui' +import { i18n } from '@lingui/core' +import { Trans } from '@lingui/macro' +import { Container } from '@mui/material' +import { useRouter } from 'next/router' +import type { LayoutOverlayProps } from '../../../components' +import { LayoutOverlay } from '../../../components' +import { graphqlSharedClient, graphqlSsrClient } from '../../../lib/graphql/graphqlSsrClient' + +type GetPageStaticProps = GetStaticProps + +function InvoiceDetailPage() { + const router = useRouter() + const { invoiceNumber, orderNumber } = router.query + + const invoices = useCustomerQuery(InvoiceDetailPageDocument, { + fetchPolicy: 'cache-and-network', + variables: { orderNumber: orderNumber as string }, + skip: !invoiceNumber || !orderNumber, + }) + + const order = invoices.data?.customer?.orders?.items?.[0] + const invoice = order?.invoices.find((i) => i?.number === invoiceNumber) + + return ( + <> + + + Invoice #{invoiceNumber} + + + + + {(!invoiceNumber || !invoice || !order) && ( + Invoice not found} + icon={} + /> + )} + + {invoiceNumber && invoice && order && ( + <> + ({ mb: theme.spacings.xxs })} + > + Invoice #{invoiceNumber} + + + + + + + + ({ mb: theme.spacings.lg })} + /> + + )} + + + + ) +} + +const pageOptions: PageOptions = { + overlayGroup: 'account', + Layout: LayoutOverlay, +} +InvoiceDetailPage.pageOptions = pageOptions + +export default InvoiceDetailPage + +export const getStaticProps: GetPageStaticProps = async (context) => { + if (getCustomerAccountIsDisabled(context.locale)) return { notFound: true } + + const client = graphqlSharedClient(context) + const staticClient = graphqlSsrClient(context) + const config = client.query({ query: StoreConfigDocument }) + + const countryRegions = staticClient.query({ + query: CountryRegionsDocument, + }) + + return { + props: { + ...(await countryRegions).data, + apolloState: await config.then(() => client.cache.extract()), + variantMd: 'bottom', + up: { href: '/account/orders', title: i18n._(/* i18n */ 'Orders') }, + }, + } +} diff --git a/examples/magento-graphcms/pages/account/orders/shipment.tsx b/examples/magento-graphcms/pages/account/orders/shipment.tsx new file mode 100644 index 0000000000..6b27835d2b --- /dev/null +++ b/examples/magento-graphcms/pages/account/orders/shipment.tsx @@ -0,0 +1,116 @@ +import type { PageOptions } from '@graphcommerce/framer-next-pages' +import { + getCustomerAccountIsDisabled, + OrderDetails, + SalesComments, + ShipmentDetailPageDocument, + ShipmentDetails, + ShipmentItems, + useCustomerQuery, + WaitForCustomer, +} from '@graphcommerce/magento-customer' +import { CountryRegionsDocument, PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' +import type { GetStaticProps } from '@graphcommerce/next-ui' +import { + FullPageMessage, + iconBox, + IconSvg, + LayoutOverlayHeader, + LayoutTitle, +} from '@graphcommerce/next-ui' +import { i18n } from '@lingui/core' +import { Trans } from '@lingui/macro' +import { Container } from '@mui/material' +import { useRouter } from 'next/router' +import type { LayoutOverlayProps } from '../../../components' +import { LayoutOverlay } from '../../../components' +import { graphqlSharedClient, graphqlSsrClient } from '../../../lib/graphql/graphqlSsrClient' + +type GetPageStaticProps = GetStaticProps + +function ShipmentDetailPage() { + const router = useRouter() + const { orderNumber, shipmentNumber } = router.query + + const shipments = useCustomerQuery(ShipmentDetailPageDocument, { + fetchPolicy: 'cache-and-network', + variables: { orderNumber: orderNumber as string }, + skip: !orderNumber || !shipmentNumber, + }) + const order = shipments.data?.customer?.orders?.items?.[0] + const shipment = order?.shipments?.find((s) => s?.number === shipmentNumber) + + return ( + <> + + + Shipment #{shipmentNumber} + + + + + {(!shipmentNumber || !shipment || !order) && ( + Shipment not found} + icon={} + /> + )} + + {shipmentNumber && shipment && order && ( + <> + ({ mb: theme.spacings.xxs })} + > + Shipment #{shipmentNumber} + + + + + {/* */} + + + ({ mb: theme.spacings.lg })} + /> + + )} + + + + ) +} + +const pageOptions: PageOptions = { + overlayGroup: 'account', + Layout: LayoutOverlay, +} +ShipmentDetailPage.pageOptions = pageOptions + +export default ShipmentDetailPage + +export const getStaticProps: GetPageStaticProps = async (context) => { + if (getCustomerAccountIsDisabled(context.locale)) return { notFound: true } + + const client = graphqlSharedClient(context) + const staticClient = graphqlSsrClient(context) + const config = client.query({ query: StoreConfigDocument }) + + const countryRegions = staticClient.query({ + query: CountryRegionsDocument, + }) + + return { + props: { + ...(await countryRegions).data, + apolloState: await config.then(() => client.cache.extract()), + variantMd: 'bottom', + up: { href: '/account/orders', title: i18n._(/* i18n */ 'Orders') }, + }, + } +} diff --git a/examples/magento-graphcms/pages/account/orders/view.tsx b/examples/magento-graphcms/pages/account/orders/view.tsx index ddd4807dde..77bef42748 100644 --- a/examples/magento-graphcms/pages/account/orders/view.tsx +++ b/examples/magento-graphcms/pages/account/orders/view.tsx @@ -8,16 +8,17 @@ import { OrderDetailPageDocument, OrderStateLabel, ReorderItems, - CancelOrderForm, getCustomerAccountIsDisabled, + OrderAdditional, } from '@graphcommerce/magento-customer' import { CountryRegionsDocument, PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' import { - IconHeader, GetStaticProps, iconBox, LayoutOverlayHeader, LayoutTitle, + FullPageMessage, + IconSvg, } from '@graphcommerce/next-ui' import { i18n } from '@lingui/core' import { Trans } from '@lingui/macro' @@ -49,9 +50,10 @@ function OrderDetailPage() { {(!orderNumber || !order) && ( - - Order not found - + Order not found} + icon={} + /> )} {orderNumber && order && ( @@ -71,11 +73,10 @@ function OrderDetailPage() { ({ textAlign: 'center', mb: theme.spacings.lg })}> - - - - - + + + + )} diff --git a/examples/magento-open-source/pages/account/index.tsx b/examples/magento-open-source/pages/account/index.tsx index 0662228bd5..66882c9830 100644 --- a/examples/magento-open-source/pages/account/index.tsx +++ b/examples/magento-open-source/pages/account/index.tsx @@ -1,5 +1,5 @@ import type { PageOptions } from '@graphcommerce/framer-next-pages' -import { cacheFirst, useQuery } from '@graphcommerce/graphql' +import { cacheFirst } from '@graphcommerce/graphql' import { AccountDashboardDocument, AccountMenu, @@ -7,7 +7,6 @@ import { AddressSingleLine, getCustomerAccountIsDisabled, OrderStateLabel, - OrderStateLabelInline, SignOutForm, useCustomerQuery, WaitForCustomer, diff --git a/examples/magento-open-source/pages/account/orders/credit-memo.tsx b/examples/magento-open-source/pages/account/orders/credit-memo.tsx new file mode 100644 index 0000000000..cb935d8902 --- /dev/null +++ b/examples/magento-open-source/pages/account/orders/credit-memo.tsx @@ -0,0 +1,117 @@ +import type { PageOptions } from '@graphcommerce/framer-next-pages' +import { + CreditMemoDetailPageDocument, + CreditMemoItems, + CreditMemoTotals, + getCustomerAccountIsDisabled, + OrderDetails, + SalesComments, + useCustomerQuery, + WaitForCustomer, +} from '@graphcommerce/magento-customer' +import { CountryRegionsDocument, PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' +import type { GetStaticProps } from '@graphcommerce/next-ui' +import { + FullPageMessage, + iconInvoice, + IconSvg, + LayoutOverlayHeader, + LayoutTitle, +} from '@graphcommerce/next-ui' +import { i18n } from '@lingui/core' +import { Trans } from '@lingui/macro' +import { Container } from '@mui/material' +import { useRouter } from 'next/router' +import type { LayoutOverlayProps } from '../../../components' +import { LayoutOverlay } from '../../../components' +import { graphqlSharedClient, graphqlSsrClient } from '../../../lib/graphql/graphqlSsrClient' + +type GetPageStaticProps = GetStaticProps + +function CreditMemoDetailPage() { + const router = useRouter() + const { orderNumber, creditMemoNumber } = router.query + + const creditMemos = useCustomerQuery(CreditMemoDetailPageDocument, { + fetchPolicy: 'cache-and-network', + variables: { orderNumber: orderNumber as string }, + skip: !orderNumber || !creditMemoNumber, + }) + const order = creditMemos.data?.customer?.orders?.items?.[0] + const creditMemo = order?.credit_memos?.find((c) => c?.number === creditMemoNumber) + + return ( + <> + + + Credit Memo #{creditMemoNumber} + + + + + {(!creditMemoNumber || !creditMemo || !order) && ( + Credit Memo not found} + icon={} + /> + )} + + {creditMemoNumber && creditMemo && order && ( + <> + ({ mb: theme.spacings.xxs })} + > + Credit Memo #{creditMemoNumber} + + + + + + {/* */} + + + ({ mb: theme.spacings.lg })} + /> + + )} + + + + ) +} + +const pageOptions: PageOptions = { + overlayGroup: 'account', + Layout: LayoutOverlay, +} +CreditMemoDetailPage.pageOptions = pageOptions + +export default CreditMemoDetailPage + +export const getStaticProps: GetPageStaticProps = async (context) => { + if (getCustomerAccountIsDisabled(context.locale)) return { notFound: true } + + const client = graphqlSharedClient(context) + const staticClient = graphqlSsrClient(context) + const config = client.query({ query: StoreConfigDocument }) + + const countryRegions = staticClient.query({ + query: CountryRegionsDocument, + }) + + return { + props: { + ...(await countryRegions).data, + apolloState: await config.then(() => client.cache.extract()), + variantMd: 'bottom', + up: { href: '/account/orders', title: i18n._(/* i18n */ 'Orders') }, + }, + } +} diff --git a/examples/magento-open-source/pages/account/orders/index.tsx b/examples/magento-open-source/pages/account/orders/index.tsx index cec50840bb..5c99aa4e3e 100644 --- a/examples/magento-open-source/pages/account/orders/index.tsx +++ b/examples/magento-open-source/pages/account/orders/index.tsx @@ -35,6 +35,7 @@ function AccountOrdersPage() { pageSize: 5, currentPage: Number(query?.page ?? 1), }, + errorPolicy: 'all', }) const { data } = orders const customer = data?.customer @@ -48,7 +49,7 @@ function AccountOrdersPage() { - + {customer?.orders && customer.orders.items.length > 0 && ( <> diff --git a/examples/magento-open-source/pages/account/orders/invoice.tsx b/examples/magento-open-source/pages/account/orders/invoice.tsx new file mode 100644 index 0000000000..66ae116ca1 --- /dev/null +++ b/examples/magento-open-source/pages/account/orders/invoice.tsx @@ -0,0 +1,117 @@ +import type { PageOptions } from '@graphcommerce/framer-next-pages' +import { + getCustomerAccountIsDisabled, + InvoiceDetailPageDocument, + InvoiceItems, + InvoiceTotals, + OrderDetails, + SalesComments, + useCustomerQuery, + WaitForCustomer, +} from '@graphcommerce/magento-customer' +import { CountryRegionsDocument, PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' +import type { GetStaticProps } from '@graphcommerce/next-ui' +import { + FullPageMessage, + iconInvoice, + IconSvg, + LayoutOverlayHeader, + LayoutTitle, +} from '@graphcommerce/next-ui' +import { i18n } from '@lingui/core' +import { Trans } from '@lingui/macro' +import { Container } from '@mui/material' +import { useRouter } from 'next/router' +import type { LayoutOverlayProps } from '../../../components' +import { LayoutOverlay } from '../../../components' +import { graphqlSharedClient, graphqlSsrClient } from '../../../lib/graphql/graphqlSsrClient' + +type GetPageStaticProps = GetStaticProps + +function InvoiceDetailPage() { + const router = useRouter() + const { invoiceNumber, orderNumber } = router.query + + const invoices = useCustomerQuery(InvoiceDetailPageDocument, { + fetchPolicy: 'cache-and-network', + variables: { orderNumber: orderNumber as string }, + skip: !invoiceNumber || !orderNumber, + }) + + const order = invoices.data?.customer?.orders?.items?.[0] + const invoice = order?.invoices.find((i) => i?.number === invoiceNumber) + + return ( + <> + + + Invoice #{invoiceNumber} + + + + + {(!invoiceNumber || !invoice || !order) && ( + Invoice not found} + icon={} + /> + )} + + {invoiceNumber && invoice && order && ( + <> + ({ mb: theme.spacings.xxs })} + > + Invoice #{invoiceNumber} + + + + + + + + ({ mb: theme.spacings.lg })} + /> + + )} + + + + ) +} + +const pageOptions: PageOptions = { + overlayGroup: 'account', + Layout: LayoutOverlay, +} +InvoiceDetailPage.pageOptions = pageOptions + +export default InvoiceDetailPage + +export const getStaticProps: GetPageStaticProps = async (context) => { + if (getCustomerAccountIsDisabled(context.locale)) return { notFound: true } + + const client = graphqlSharedClient(context) + const staticClient = graphqlSsrClient(context) + const config = client.query({ query: StoreConfigDocument }) + + const countryRegions = staticClient.query({ + query: CountryRegionsDocument, + }) + + return { + props: { + ...(await countryRegions).data, + apolloState: await config.then(() => client.cache.extract()), + variantMd: 'bottom', + up: { href: '/account/orders', title: i18n._(/* i18n */ 'Orders') }, + }, + } +} diff --git a/examples/magento-open-source/pages/account/orders/shipment.tsx b/examples/magento-open-source/pages/account/orders/shipment.tsx new file mode 100644 index 0000000000..6b27835d2b --- /dev/null +++ b/examples/magento-open-source/pages/account/orders/shipment.tsx @@ -0,0 +1,116 @@ +import type { PageOptions } from '@graphcommerce/framer-next-pages' +import { + getCustomerAccountIsDisabled, + OrderDetails, + SalesComments, + ShipmentDetailPageDocument, + ShipmentDetails, + ShipmentItems, + useCustomerQuery, + WaitForCustomer, +} from '@graphcommerce/magento-customer' +import { CountryRegionsDocument, PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' +import type { GetStaticProps } from '@graphcommerce/next-ui' +import { + FullPageMessage, + iconBox, + IconSvg, + LayoutOverlayHeader, + LayoutTitle, +} from '@graphcommerce/next-ui' +import { i18n } from '@lingui/core' +import { Trans } from '@lingui/macro' +import { Container } from '@mui/material' +import { useRouter } from 'next/router' +import type { LayoutOverlayProps } from '../../../components' +import { LayoutOverlay } from '../../../components' +import { graphqlSharedClient, graphqlSsrClient } from '../../../lib/graphql/graphqlSsrClient' + +type GetPageStaticProps = GetStaticProps + +function ShipmentDetailPage() { + const router = useRouter() + const { orderNumber, shipmentNumber } = router.query + + const shipments = useCustomerQuery(ShipmentDetailPageDocument, { + fetchPolicy: 'cache-and-network', + variables: { orderNumber: orderNumber as string }, + skip: !orderNumber || !shipmentNumber, + }) + const order = shipments.data?.customer?.orders?.items?.[0] + const shipment = order?.shipments?.find((s) => s?.number === shipmentNumber) + + return ( + <> + + + Shipment #{shipmentNumber} + + + + + {(!shipmentNumber || !shipment || !order) && ( + Shipment not found} + icon={} + /> + )} + + {shipmentNumber && shipment && order && ( + <> + ({ mb: theme.spacings.xxs })} + > + Shipment #{shipmentNumber} + + + + + {/* */} + + + ({ mb: theme.spacings.lg })} + /> + + )} + + + + ) +} + +const pageOptions: PageOptions = { + overlayGroup: 'account', + Layout: LayoutOverlay, +} +ShipmentDetailPage.pageOptions = pageOptions + +export default ShipmentDetailPage + +export const getStaticProps: GetPageStaticProps = async (context) => { + if (getCustomerAccountIsDisabled(context.locale)) return { notFound: true } + + const client = graphqlSharedClient(context) + const staticClient = graphqlSsrClient(context) + const config = client.query({ query: StoreConfigDocument }) + + const countryRegions = staticClient.query({ + query: CountryRegionsDocument, + }) + + return { + props: { + ...(await countryRegions).data, + apolloState: await config.then(() => client.cache.extract()), + variantMd: 'bottom', + up: { href: '/account/orders', title: i18n._(/* i18n */ 'Orders') }, + }, + } +} diff --git a/examples/magento-open-source/pages/account/orders/view.tsx b/examples/magento-open-source/pages/account/orders/view.tsx index 181ab5e6a9..4d45bbd6d9 100644 --- a/examples/magento-open-source/pages/account/orders/view.tsx +++ b/examples/magento-open-source/pages/account/orders/view.tsx @@ -1,7 +1,7 @@ import type { PageOptions } from '@graphcommerce/framer-next-pages' import { - CancelOrderForm, getCustomerAccountIsDisabled, + OrderAdditional, OrderDetailPageDocument, OrderDetails, OrderItems, @@ -13,7 +13,13 @@ import { } from '@graphcommerce/magento-customer' import { CountryRegionsDocument, PageMeta, StoreConfigDocument } from '@graphcommerce/magento-store' import type { GetStaticProps } from '@graphcommerce/next-ui' -import { iconBox, IconHeader, LayoutOverlayHeader, LayoutTitle } from '@graphcommerce/next-ui' +import { + FullPageMessage, + iconBox, + IconSvg, + LayoutOverlayHeader, + LayoutTitle, +} from '@graphcommerce/next-ui' import { i18n } from '@lingui/core' import { Trans } from '@lingui/macro' import { Container, Typography } from '@mui/material' @@ -45,9 +51,10 @@ function OrderDetailPage() { {(!orderNumber || !order) && ( - - Order not found - + Order not found} + icon={} + /> )} {orderNumber && order && ( @@ -67,11 +74,10 @@ function OrderDetailPage() { ({ textAlign: 'center', mb: theme.spacings.lg })}> - - - - - + + + + )} diff --git a/packages/magento-customer/components/AccountLatestOrder/AccountLatestOrder.tsx b/packages/magento-customer/components/AccountLatestOrder/AccountLatestOrder.tsx index f4e9386258..871b839949 100644 --- a/packages/magento-customer/components/AccountLatestOrder/AccountLatestOrder.tsx +++ b/packages/magento-customer/components/AccountLatestOrder/AccountLatestOrder.tsx @@ -1,8 +1,7 @@ import { SectionContainer } from '@graphcommerce/next-ui' -import React from 'react' import type { AccountOrdersFragment } from '../AccountOrders/AccountOrders.gql' import { NoOrdersFound } from '../NoOrdersFound/NoOrdersFound' -import { OrderCard } from '../OrderCard/OrderCard' +import { OrderCard } from '../Order' export type AccountLatestOrderProps = AccountOrdersFragment & { loading: boolean diff --git a/packages/magento-customer/components/AccountOrders/AccountOrders.tsx b/packages/magento-customer/components/AccountOrders/AccountOrders.tsx index 7349be4212..3aca09c49d 100644 --- a/packages/magento-customer/components/AccountOrders/AccountOrders.tsx +++ b/packages/magento-customer/components/AccountOrders/AccountOrders.tsx @@ -3,7 +3,7 @@ import type { SxProps, Theme } from '@mui/material' import { Box, Link } from '@mui/material' import React from 'react' import { NoOrdersFound } from '../NoOrdersFound/NoOrdersFound' -import { OrderCard } from '../OrderCard/OrderCard' +import { OrderCard } from '../Order' import type { AccountOrdersFragment } from './AccountOrders.gql' export type AccountOrdersProps = AccountOrdersFragment & { sx?: SxProps } diff --git a/packages/magento-customer/components/CancelOrder/CancelOrderForm.tsx b/packages/magento-customer/components/CancelOrder/CancelOrderForm.tsx index acb42f624b..e6fa64c21a 100644 --- a/packages/magento-customer/components/CancelOrder/CancelOrderForm.tsx +++ b/packages/magento-customer/components/CancelOrder/CancelOrderForm.tsx @@ -14,12 +14,12 @@ import { Trans } from '@lingui/macro' import type { AccordionProps } from '@mui/material' import { Accordion, AccordionDetails, AccordionSummary, Alert, Box } from '@mui/material' import { canCancelOrder } from '../../utils' -import type { OrderDetailsFragment } from '../OrderDetails/OrderDetails.gql' import type { CancelOrderMutation, CancelOrderMutationVariables } from './CancelOrder.gql' import { CancelOrderDocument } from './CancelOrder.gql' +import type { CancelOrderFragment } from './CancelOrderFragment.gql' export type CancelOrderFormProps = { - order: OrderDetailsFragment + order: CancelOrderFragment } & Omit export function CancelOrderForm(props: CancelOrderFormProps) { diff --git a/packages/magento-customer/components/CancelOrder/CancelOrderFragment.graphql b/packages/magento-customer/components/CancelOrder/CancelOrderFragment.graphql new file mode 100644 index 0000000000..61f762b0f2 --- /dev/null +++ b/packages/magento-customer/components/CancelOrder/CancelOrderFragment.graphql @@ -0,0 +1,5 @@ +fragment CancelOrderFragment on CustomerOrder { + id + ...OrderStateLabel + ...OrderDetails +} diff --git a/packages/magento-customer/components/CreditMemo/CreditMemo.graphql b/packages/magento-customer/components/CreditMemo/CreditMemo.graphql new file mode 100644 index 0000000000..7e4146fefb --- /dev/null +++ b/packages/magento-customer/components/CreditMemo/CreditMemo.graphql @@ -0,0 +1,43 @@ +fragment CreditMemo on CreditMemo { + id + number + items { + ...CreditMemoItem + } + total { + subtotal { + ...Money + } + adjustment { + ...Money + } + shipping_handling { + ...ShippingHandling + } + total_shipping { + ...Money + } + discounts { + amount { + ...Money + } + label + } + base_grand_total { + ...Money + } + grand_total { + ...Money + } + taxes { + ...TaxItem + } + total_tax { + ...Money + } + } + comments { + message + timestamp + } +} diff --git a/packages/magento-customer/components/CreditMemo/CreditMemoCard.graphql b/packages/magento-customer/components/CreditMemo/CreditMemoCard.graphql new file mode 100644 index 0000000000..bea85a2fcf --- /dev/null +++ b/packages/magento-customer/components/CreditMemo/CreditMemoCard.graphql @@ -0,0 +1,12 @@ +fragment CreditMemoCard on CreditMemo { + id + number + comments { + ...SalesCommentItem + } + total { + grand_total { + ...Money + } + } +} diff --git a/packages/magento-customer/components/CreditMemo/CreditMemoCard.tsx b/packages/magento-customer/components/CreditMemo/CreditMemoCard.tsx new file mode 100644 index 0000000000..9ea6051fa0 --- /dev/null +++ b/packages/magento-customer/components/CreditMemo/CreditMemoCard.tsx @@ -0,0 +1,66 @@ +import { Money } from '@graphcommerce/magento-store' +import { breakpointVal, iconChevronRight, IconSvg, NextLink, sxx } from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, lighten } from '@mui/material' +import type { CreditMemoCardFragment } from './CreditMemoCard.gql' + +export type CreditMemoCardProps = { + orderNumber: string + creditMemo: CreditMemoCardFragment + sx?: SxProps +} + +export function CreditMemoCard(props: CreditMemoCardProps) { + const { creditMemo, orderNumber, sx = [] } = props + const { number, total } = creditMemo + + return ( + ({ + textDecoration: 'none', + color: 'text.primary', + px: theme.spacings.xxs, + py: theme.spacings.xxs, + gap: theme.spacings.sm, + background: + theme.palette.mode === 'light' + ? theme.palette.background.default + : lighten(theme.palette.background.default, 0.15), + ...breakpointVal( + 'borderRadius', + theme.shape.borderRadius * 2, + theme.shape.borderRadius * 3, + theme.breakpoints.values, + ), + '&:hover': { + backgroundColor: theme.palette.action.hover, + }, + display: 'grid', + gridTemplate: ` + "number total action" / 1fr auto auto + `, + rowGap: 0.5, + columnGap: 1, + }), + sx, + )} + > + + Credit Memo #{number} + + + + + + + + ) +} diff --git a/packages/magento-customer/components/CreditMemo/CreditMemoDetails.tsx b/packages/magento-customer/components/CreditMemo/CreditMemoDetails.tsx new file mode 100644 index 0000000000..fa7dbd4a17 --- /dev/null +++ b/packages/magento-customer/components/CreditMemo/CreditMemoDetails.tsx @@ -0,0 +1,94 @@ +import { + breakpointVal, + DateTimeFormat, + extendableComponent, + SectionContainer, +} from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, lighten, Typography } from '@mui/material' +import type { CreditMemoFragment } from './CreditMemo.gql' + +export type CreditMemoDetailsProps = { + creditMemo: CreditMemoFragment + sx?: SxProps +} + +const componentName = 'CreditMemoDetails' +const parts = [ + 'sectionContainer', + 'creditMemoDetailTitle', + 'creditMemoDetailContainer', + 'creditMemoDetailRow', +] as const +const { classes } = extendableComponent(componentName, parts) + +export function CreditMemoDetails(props: CreditMemoDetailsProps) { + const { creditMemo, sx = [] } = props + const { number, id } = creditMemo + + return ( + Credit Memo details} + sx={[ + (theme) => ({ + padding: theme.spacings.sm, + marginBottom: theme.spacings.md, + background: + theme.palette.mode === 'light' + ? theme.palette.background.default + : lighten(theme.palette.background.default, 0.15), + ...breakpointVal( + 'borderRadius', + theme.shape.borderRadius * 2, + theme.shape.borderRadius * 3, + theme.breakpoints.values, + ), + '& .SectionHeader-root': { + mt: 0, + mb: theme.spacings.xs, + }, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + ({ + gridColumnGap: theme.spacings.xxl, + gridRowGap: theme.spacings.md, + display: 'grid', + [theme.breakpoints.up('sm')]: { + gridTemplateColumns: '1fr 1fr', + marginTop: theme.spacings.xxs, + }, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + + Credit Memo number} + className={classes.creditMemoDetailTitle} + sx={{ '& .SectionHeader-root': { marginTop: 0, paddingBottom: '4px' } }} + > + {number} + + + + + {/* Credit Memo ID} + className={classes.creditMemoDetailTitle} + sx={{ '& .SectionHeader-root': { marginTop: 0, paddingBottom: '4px' } }} + > + {id} + */} + + + + ) +} diff --git a/packages/magento-customer/components/CreditMemo/CreditMemoItem.graphql b/packages/magento-customer/components/CreditMemo/CreditMemoItem.graphql new file mode 100644 index 0000000000..8523c5eb51 --- /dev/null +++ b/packages/magento-customer/components/CreditMemo/CreditMemoItem.graphql @@ -0,0 +1,18 @@ +fragment CreditMemoItem on CreditMemoItemInterface { + id + discounts { + amount { + ...Money + } + label + } + order_item { + id + } + product_name + product_sale_price { + ...Money + } + product_sku + quantity_refunded +} diff --git a/packages/magento-customer/components/CreditMemo/CreditMemoItems.tsx b/packages/magento-customer/components/CreditMemo/CreditMemoItems.tsx new file mode 100644 index 0000000000..161aaa47d2 --- /dev/null +++ b/packages/magento-customer/components/CreditMemo/CreditMemoItems.tsx @@ -0,0 +1,89 @@ +import { Money } from '@graphcommerce/magento-store' +import { extendableComponent, SectionContainer } from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, Typography } from '@mui/material' +import type { CreditMemoFragment } from './CreditMemo.gql' + +export type CreditMemoItemsProps = { + creditMemo: CreditMemoFragment + sx?: SxProps +} + +const componentName = 'CreditMemoItems' +const parts = ['root', 'creditMemoItemsInnerContainer', 'itemRow', 'itemDetails'] as const +const { classes } = extendableComponent(componentName, parts) + +export function CreditMemoItems(props: CreditMemoItemsProps) { + const { creditMemo, sx = [] } = props + const { items } = creditMemo + + if (!items?.length) return null + + return ( + } + className={classes.root} + sx={[ + (theme) => ({ + marginTop: theme.spacings.md, + marginBottom: theme.spacings.sm, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + ({ mb: theme.spacings.md })} + > + {items.map((item) => { + if (!item) return null + const { + id, + product_name, + product_sku, + quantity_refunded, + product_sale_price, + discounts, + } = item + + return ( + ({ + display: 'grid', + gridTemplateColumns: '1fr auto auto', + gap: theme.spacings.sm, + padding: `${theme.spacings.xs} 0`, + borderBottom: `1px solid ${theme.palette.divider}`, + '&:last-child': { + borderBottom: 'none', + }, + alignItems: 'center', + })} + > + + + {quantity_refunded} ⨉ {product_name} + + + {/* {discounts?.map((discount) => ( + + {discount?.label}: + + ))} */} + + + SKU: {product_sku} + + + + + + ) + })} + + + ) +} diff --git a/packages/magento-customer/components/CreditMemo/CreditMemoTotals.tsx b/packages/magento-customer/components/CreditMemo/CreditMemoTotals.tsx new file mode 100644 index 0000000000..1013b922e8 --- /dev/null +++ b/packages/magento-customer/components/CreditMemo/CreditMemoTotals.tsx @@ -0,0 +1,119 @@ +import { Money } from '@graphcommerce/magento-store' +import { breakpointVal, extendableComponent } from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, Divider, Typography } from '@mui/material' +import type { CreditMemoFragment } from './CreditMemo.gql' + +export type CreditMemoTotalsProps = { + creditMemo: CreditMemoFragment + sx?: SxProps +} + +const componentName = 'CreditMemoTotals' +const parts = ['totalsContainer', 'totalsRow', 'totalsDivider', 'totalsVat'] as const +const { classes } = extendableComponent(componentName, parts) + +export function CreditMemoTotals(props: CreditMemoTotalsProps) { + const { creditMemo, sx = [] } = props + const { total } = creditMemo + + if (!total) return null + + return ( + ({ + border: `1px solid ${theme.palette.divider}`, + marginBottom: theme.spacings.md, + p: theme.spacings.sm, + ...breakpointVal( + 'borderRadius', + theme.shape.borderRadius * 2, + theme.shape.borderRadius * 3, + theme.breakpoints.values, + ), + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + + + Subtotal + + + + + {total.discounts?.map((discount) => ( + + {discount?.label} + {discount?.amount && ( + + )} + + ))} + + {total.total_shipping && ( + + + Shipping + + + + )} + + {total.adjustment && ( + + + Adjustment + + + + )} + + ({ my: theme.spacings.xxs })} /> + + ({ + display: 'flex', + justifyContent: 'space-between', + color: theme.palette.primary.main, + })} + > + + Refund total + + + + + {total.taxes?.map((tax) => ( + ({ + display: 'flex', + justifyContent: 'space-between', + color: theme.palette.text.disabled, + })} + > + + Including {tax?.title} + + + + ))} + + ) +} diff --git a/packages/magento-customer/components/CreditMemo/index.ts b/packages/magento-customer/components/CreditMemo/index.ts new file mode 100644 index 0000000000..92c59a3ae2 --- /dev/null +++ b/packages/magento-customer/components/CreditMemo/index.ts @@ -0,0 +1,7 @@ +export * from './CreditMemo.gql' +export * from './CreditMemoCard' +export * from './CreditMemoCard.gql' +export * from './CreditMemoDetails' +export * from './CreditMemoItem.gql' +export * from './CreditMemoItems' +export * from './CreditMemoTotals' diff --git a/packages/magento-customer/components/Invoice/Invoice.graphql b/packages/magento-customer/components/Invoice/Invoice.graphql new file mode 100644 index 0000000000..10c691f6c8 --- /dev/null +++ b/packages/magento-customer/components/Invoice/Invoice.graphql @@ -0,0 +1,13 @@ +fragment Invoice on Invoice { + id + number + items { + ...InvoiceItem + } + total { + ...InvoiceTotal + } + comments { + ...SalesCommentItem + } +} diff --git a/packages/magento-customer/components/Invoice/InvoiceCard.graphql b/packages/magento-customer/components/Invoice/InvoiceCard.graphql new file mode 100644 index 0000000000..9b3dc1e830 --- /dev/null +++ b/packages/magento-customer/components/Invoice/InvoiceCard.graphql @@ -0,0 +1,9 @@ +fragment InvoiceCard on Invoice { + id + number + total { + grand_total { + ...Money + } + } +} diff --git a/packages/magento-customer/components/Invoice/InvoiceCard.tsx b/packages/magento-customer/components/Invoice/InvoiceCard.tsx new file mode 100644 index 0000000000..5d0bd7a1b0 --- /dev/null +++ b/packages/magento-customer/components/Invoice/InvoiceCard.tsx @@ -0,0 +1,66 @@ +import { Money } from '@graphcommerce/magento-store' +import { breakpointVal, iconChevronRight, IconSvg, NextLink, sxx } from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, lighten } from '@mui/material' +import type { InvoiceCardFragment } from './InvoiceCard.gql' + +export type InvoiceCardProps = { + orderNumber: string + invoice: InvoiceCardFragment + sx?: SxProps +} + +export function InvoiceCard(props: InvoiceCardProps) { + const { invoice, sx = [], orderNumber } = props + const { number, total } = invoice + + return ( + ({ + textDecoration: 'none', + color: 'text.primary', + px: theme.spacings.xxs, + py: theme.spacings.xxs, + gap: theme.spacings.sm, + background: + theme.palette.mode === 'light' + ? theme.palette.background.default + : lighten(theme.palette.background.default, 0.15), + ...breakpointVal( + 'borderRadius', + theme.shape.borderRadius * 2, + theme.shape.borderRadius * 3, + theme.breakpoints.values, + ), + '&:hover': { + backgroundColor: theme.palette.action.hover, + }, + display: 'grid', + gridTemplate: ` + "number total action" / 1fr auto auto + `, + rowGap: 0.5, + columnGap: 1, + }), + sx, + )} + > + + Invoice #{number} + + + + + + + + ) +} diff --git a/packages/magento-customer/components/Invoice/InvoiceDetails.tsx b/packages/magento-customer/components/Invoice/InvoiceDetails.tsx new file mode 100644 index 0000000000..80c5a9a533 --- /dev/null +++ b/packages/magento-customer/components/Invoice/InvoiceDetails.tsx @@ -0,0 +1,94 @@ +import { + breakpointVal, + DateTimeFormat, + extendableComponent, + SectionContainer, +} from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, lighten, Typography } from '@mui/material' +import type { InvoiceFragment } from './Invoice.gql' + +export type InvoiceDetailsProps = { + invoice: InvoiceFragment + sx?: SxProps +} + +const componentName = 'InvoiceDetails' +const parts = [ + 'sectionContainer', + 'invoiceDetailTitle', + 'invoiceDetailContainer', + 'invoiceDetailRow', +] as const +const { classes } = extendableComponent(componentName, parts) + +export function InvoiceDetails(props: InvoiceDetailsProps) { + const { invoice, sx = [] } = props + const { number, id } = invoice + + return ( + Invoice details} + sx={[ + (theme) => ({ + padding: theme.spacings.sm, + marginBottom: theme.spacings.md, + background: + theme.palette.mode === 'light' + ? theme.palette.background.default + : lighten(theme.palette.background.default, 0.15), + ...breakpointVal( + 'borderRadius', + theme.shape.borderRadius * 2, + theme.shape.borderRadius * 3, + theme.breakpoints.values, + ), + '& .SectionHeader-root': { + mt: 0, + mb: theme.spacings.xs, + }, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + ({ + gridColumnGap: theme.spacings.xxl, + gridRowGap: theme.spacings.md, + display: 'grid', + [theme.breakpoints.up('sm')]: { + gridTemplateColumns: '1fr 1fr', + marginTop: theme.spacings.xxs, + }, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + + Invoice number} + className={classes.invoiceDetailTitle} + sx={{ '& .SectionHeader-root': { marginTop: 0, paddingBottom: '4px' } }} + > + {number} + + + + + {/* Invoice ID} + className={classes.invoiceDetailTitle} + sx={{ '& .SectionHeader-root': { marginTop: 0, paddingBottom: '4px' } }} + > + {id} + */} + + + + ) +} diff --git a/packages/magento-customer/components/Invoice/InvoiceItem.graphql b/packages/magento-customer/components/Invoice/InvoiceItem.graphql new file mode 100644 index 0000000000..1a2ddd4c3e --- /dev/null +++ b/packages/magento-customer/components/Invoice/InvoiceItem.graphql @@ -0,0 +1,15 @@ +fragment InvoiceItem on InvoiceItemInterface { + id + discounts { + amount { + ...Money + } + label + } + product_name + product_sale_price { + ...Money + } + product_sku + quantity_invoiced +} diff --git a/packages/magento-customer/components/Invoice/InvoiceItem.tsx b/packages/magento-customer/components/Invoice/InvoiceItem.tsx new file mode 100644 index 0000000000..bbd5008af5 --- /dev/null +++ b/packages/magento-customer/components/Invoice/InvoiceItem.tsx @@ -0,0 +1,14 @@ +import type { InvoiceItemFragment } from './InvoiceItem.gql' + +export type InvoiceItemProps = { + item: InvoiceItemFragment +} + +export function InvoiceItem(props: InvoiceItemProps) { + const { item } = props + return ( +
+ {item.product_name} {item.quantity_invoiced} +
+ ) +} diff --git a/packages/magento-customer/components/Invoice/InvoiceItems.tsx b/packages/magento-customer/components/Invoice/InvoiceItems.tsx new file mode 100644 index 0000000000..bdbfd510bc --- /dev/null +++ b/packages/magento-customer/components/Invoice/InvoiceItems.tsx @@ -0,0 +1,89 @@ +import { Money } from '@graphcommerce/magento-store' +import { extendableComponent, SectionContainer } from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, Typography } from '@mui/material' +import type { InvoiceFragment } from './Invoice.gql' + +export type InvoiceItemsProps = { + invoice: InvoiceFragment + sx?: SxProps +} + +const componentName = 'InvoiceItems' +const parts = ['root', 'invoiceItemsInnerContainer', 'itemRow', 'itemDetails'] as const +const { classes } = extendableComponent(componentName, parts) + +export function InvoiceItems(props: InvoiceItemsProps) { + const { invoice, sx = [] } = props + const { items } = invoice + + if (!items?.length) return null + + return ( + } + className={classes.root} + sx={[ + (theme) => ({ + marginTop: theme.spacings.md, + marginBottom: theme.spacings.sm, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + ({ mb: theme.spacings.md })} + > + {items.map((item) => { + if (!item) return null + const { + id, + product_name, + product_sku, + quantity_invoiced, + product_sale_price, + discounts, + } = item + + return ( + ({ + display: 'grid', + gridTemplateColumns: '1fr auto auto', + gap: theme.spacings.sm, + padding: `${theme.spacings.xs} 0`, + borderBottom: `1px solid ${theme.palette.divider}`, + '&:last-child': { + borderBottom: 'none', + }, + alignItems: 'center', + })} + > + + + {quantity_invoiced} ⨉ {product_name} + + + {/* {discounts?.map((discount) => ( + + {discount?.label}: + + ))} */} + + + SKU: {product_sku} + + + + + + ) + })} + + + ) +} diff --git a/packages/magento-customer/components/Invoice/InvoiceTotal.graphql b/packages/magento-customer/components/Invoice/InvoiceTotal.graphql new file mode 100644 index 0000000000..5a7ab5e06d --- /dev/null +++ b/packages/magento-customer/components/Invoice/InvoiceTotal.graphql @@ -0,0 +1,29 @@ +fragment InvoiceTotal on InvoiceTotal { + subtotal { + ...Money + } + shipping_handling { + ...ShippingHandling + } + total_shipping { + ...Money + } + discounts { + amount { + ...Money + } + label + } + base_grand_total { + ...Money + } + grand_total { + ...Money + } + taxes { + ...TaxItem + } + total_tax { + ...Money + } +} diff --git a/packages/magento-customer/components/Invoice/InvoiceTotals.tsx b/packages/magento-customer/components/Invoice/InvoiceTotals.tsx new file mode 100644 index 0000000000..6fb6adfac5 --- /dev/null +++ b/packages/magento-customer/components/Invoice/InvoiceTotals.tsx @@ -0,0 +1,107 @@ +import { Money } from '@graphcommerce/magento-store' +import { breakpointVal, extendableComponent } from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, Divider, Typography } from '@mui/material' +import type { InvoiceFragment } from './Invoice.gql' + +export type InvoiceTotalsProps = { + invoice: InvoiceFragment + sx?: SxProps +} + +const componentName = 'InvoiceTotals' +const parts = ['totalsContainer', 'totalsRow', 'totalsDivider', 'totalsVat'] as const +const { classes } = extendableComponent(componentName, parts) + +export function InvoiceTotals(props: InvoiceTotalsProps) { + const { invoice, sx = [] } = props + const { total } = invoice + + if (!total) return null + + return ( + ({ + border: `1px solid ${theme.palette.divider}`, + marginBottom: theme.spacings.md, + p: theme.spacings.sm, + ...breakpointVal( + 'borderRadius', + theme.shape.borderRadius * 2, + theme.shape.borderRadius * 3, + theme.breakpoints.values, + ), + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + + + Subtotal + + + + + {total.discounts?.map((discount) => ( + + {discount?.label} + {discount?.amount && ( + + )} + + ))} + + {total.total_shipping && ( + + + Shipping + + + + )} + + ({ my: theme.spacings.xxs })} /> + + ({ + display: 'flex', + justifyContent: 'space-between', + color: theme.palette.primary.main, + })} + > + + Grand total + + + + + {total.taxes?.map((tax) => ( + ({ + display: 'flex', + justifyContent: 'space-between', + color: theme.palette.text.disabled, + })} + > + + Including {tax?.title} + + + + ))} + + ) +} diff --git a/packages/magento-customer/components/Invoice/index.ts b/packages/magento-customer/components/Invoice/index.ts new file mode 100644 index 0000000000..79615a4a98 --- /dev/null +++ b/packages/magento-customer/components/Invoice/index.ts @@ -0,0 +1,9 @@ +export * from './Invoice.gql' +export * from './InvoiceCard' +export * from './InvoiceCard.gql' +export * from './InvoiceDetails' +export * from './InvoiceItem' +export * from './InvoiceItem.gql' +export * from './InvoiceItems' +export * from './InvoiceTotal.gql' +export * from './InvoiceTotals' diff --git a/packages/magento-customer/components/Order/OrderAdditional/OrderAdditional.graphql b/packages/magento-customer/components/Order/OrderAdditional/OrderAdditional.graphql new file mode 100644 index 0000000000..18d026a09c --- /dev/null +++ b/packages/magento-customer/components/Order/OrderAdditional/OrderAdditional.graphql @@ -0,0 +1,16 @@ +fragment OrderAdditional on CustomerOrder { + ...CancelOrderFragment + number + invoices { + ...InvoiceCard + } + credit_memos { + ...CreditMemoCard + } + shipments { + ...ShipmentCard + } + comments { + ...SalesCommentItem + } +} diff --git a/packages/magento-customer/components/Order/OrderAdditional/OrderAdditional.tsx b/packages/magento-customer/components/Order/OrderAdditional/OrderAdditional.tsx new file mode 100644 index 0000000000..ff3086d3c4 --- /dev/null +++ b/packages/magento-customer/components/Order/OrderAdditional/OrderAdditional.tsx @@ -0,0 +1,49 @@ +import { filterNonNullableKeys, SectionContainer, sxx } from '@graphcommerce/next-ui' +import { Box, type SxProps, type Theme } from '@mui/material' +import { CancelOrderForm } from '../../CancelOrder/CancelOrderForm' +import { CreditMemoCard } from '../../CreditMemo/CreditMemoCard' +import { InvoiceCard } from '../../Invoice/InvoiceCard' +import { ShipmentCard } from '../../Shipment/ShipmentCard' +import { SalesComments } from '../OrderComments/SalesComments' +import type { OrderAdditionalFragment } from './OrderAdditional.gql' + +export type OrderAdditionalProps = { + order: OrderAdditionalFragment + sx?: SxProps + children?: React.ReactNode +} + +export function OrderAdditional(props: OrderAdditionalProps) { + const { order, children, sx } = props + const comments = filterNonNullableKeys(order.comments) + const invoices = filterNonNullableKeys(order.invoices) + const shipments = filterNonNullableKeys(order.shipments) + const creditMemos = filterNonNullableKeys(order.credit_memos) + + return ( + ({ mb: theme.spacings.lg, display: 'grid', rowGap: theme.spacings.xs }), + sx, + )} + > + {comments.length > 0 ? : null} + + {shipments.map((shipment) => ( + + ))} + + {invoices.map((invoice) => ( + + ))} + + {creditMemos.map((creditMemo) => ( + + ))} + + {children} + + + + ) +} diff --git a/packages/magento-customer/components/Order/OrderCard/OrderCard.graphql b/packages/magento-customer/components/Order/OrderCard/OrderCard.graphql new file mode 100644 index 0000000000..604f12bd41 --- /dev/null +++ b/packages/magento-customer/components/Order/OrderCard/OrderCard.graphql @@ -0,0 +1,13 @@ +fragment OrderCard on CustomerOrder { + number + order_date + total { + grand_total { + ...Money + } + } + items { + ...OrderCardItem + } + ...OrderStateLabel +} diff --git a/packages/magento-customer/components/OrderCard/OrderCard.tsx b/packages/magento-customer/components/Order/OrderCard/OrderCard.tsx similarity index 87% rename from packages/magento-customer/components/OrderCard/OrderCard.tsx rename to packages/magento-customer/components/Order/OrderCard/OrderCard.tsx index 966e4daf10..d630f02b94 100644 --- a/packages/magento-customer/components/OrderCard/OrderCard.tsx +++ b/packages/magento-customer/components/Order/OrderCard/OrderCard.tsx @@ -94,22 +94,25 @@ export function OrderCard(props: OrderCardProps) { gap: 1, }} > - {itemsWithImages.slice(0, maxItemsToShow).map((item) => ( - {item.label - ))} + {itemsWithImages.slice(0, maxItemsToShow).map((item, index) => { + const key = `${item.url}-${index}` + return ( + {item.label + ) + })} {totalItems > 4 && ( +} + +export function SalesComments(props: SalesCommentsProps) { + const { comments, sx } = props + + if (!comments?.length) return null + + return ( + + {filterNonNullableKeys(comments).map((comment) => ( +
+ {comment.message} +
+ ))} +
+ ) +} diff --git a/packages/magento-customer/components/Order/OrderDetails/OrderAddress.graphql b/packages/magento-customer/components/Order/OrderDetails/OrderAddress.graphql new file mode 100644 index 0000000000..28d42210a2 --- /dev/null +++ b/packages/magento-customer/components/Order/OrderDetails/OrderAddress.graphql @@ -0,0 +1,17 @@ +fragment OrderAddress on OrderAddress { + company + fax + middlename + prefix + region + suffix + telephone + vat_id + city + postcode + firstname + lastname + street + country_code + region_id +} diff --git a/packages/magento-customer/components/Order/OrderDetails/OrderDetails.graphql b/packages/magento-customer/components/Order/OrderDetails/OrderDetails.graphql new file mode 100644 index 0000000000..9c9d53893a --- /dev/null +++ b/packages/magento-customer/components/Order/OrderDetails/OrderDetails.graphql @@ -0,0 +1,38 @@ +fragment OrderDetails on CustomerOrder { + id + number + order_date + status + invoices { + id + number + } + shipping_method + shipments { + id + tracking { + ...TrackingLink + } + } + applied_coupons { + ...AppliedCoupon + } + payment_methods { + name + type + additional_data { + name + value + } + } + billing_address { + ...OrderAddress + } + shipping_address { + ...OrderAddress + } + carrier + total { + ...OrderTotal + } +} diff --git a/packages/magento-customer/components/OrderDetails/OrderDetails.tsx b/packages/magento-customer/components/Order/OrderDetails/OrderDetails.tsx similarity index 86% rename from packages/magento-customer/components/OrderDetails/OrderDetails.tsx rename to packages/magento-customer/components/Order/OrderDetails/OrderDetails.tsx index 1ddc35a4a5..ee699d13b0 100644 --- a/packages/magento-customer/components/OrderDetails/OrderDetails.tsx +++ b/packages/magento-customer/components/Order/OrderDetails/OrderDetails.tsx @@ -2,6 +2,7 @@ import { breakpointVal, DateTimeFormat, extendableComponent, + filterNonNullableKeys, iconInvoice, IconSvg, SectionContainer, @@ -9,11 +10,12 @@ import { import { Trans } from '@lingui/macro' import type { SxProps, Theme } from '@mui/material' import { Box, lighten, Typography } from '@mui/material' -import { AddressMultiLine } from '../AddressMultiLine/AddressMultiLine' -import { TrackingLink } from '../TrackingLink/TrackingLink' +import { AddressMultiLine } from '../../AddressMultiLine/AddressMultiLine' +import { TrackingLink } from '../../TrackingLink/TrackingLink' import type { OrderDetailsFragment } from './OrderDetails.gql' -export type OrderDetailsProps = Partial & { +export type OrderDetailsProps = { + order: OrderDetailsFragment sx?: SxProps } @@ -28,6 +30,7 @@ const parts = [ const { classes } = extendableComponent(componentName, parts) export function OrderDetails(props: OrderDetailsProps) { + const { order, sx = [] } = props const { number, order_date, @@ -37,8 +40,7 @@ export function OrderDetails(props: OrderDetailsProps) { shipments, shipping_method, invoices, - sx = [], - } = props + } = order return ( - {payment_methods[0].name} - {invoices && invoices?.length > 0 && ( - - - {invoices?.[0]?.number} - - )} - + {payment_methods[0].name} )}
diff --git a/packages/magento-customer/components/Order/OrderDetails/ShippingHandling.graphql b/packages/magento-customer/components/Order/OrderDetails/ShippingHandling.graphql new file mode 100644 index 0000000000..b16e0341da --- /dev/null +++ b/packages/magento-customer/components/Order/OrderDetails/ShippingHandling.graphql @@ -0,0 +1,19 @@ +fragment ShippingHandling on ShippingHandling { + amount_excluding_tax { + ...Money + } + amount_including_tax { + ...Money + } + discounts { + amount { + ...Money + } + } + taxes { + ...TaxItem + } + total_amount { + ...Money + } +} diff --git a/packages/magento-customer/components/Order/OrderDetails/TaxItem.graphql b/packages/magento-customer/components/Order/OrderDetails/TaxItem.graphql new file mode 100644 index 0000000000..47b4cd65f8 --- /dev/null +++ b/packages/magento-customer/components/Order/OrderDetails/TaxItem.graphql @@ -0,0 +1,7 @@ +fragment TaxItem on TaxItem { + title + rate + amount { + ...Money + } +} diff --git a/packages/magento-customer/components/OrderItem/OrderItem.graphql b/packages/magento-customer/components/Order/OrderItem/OrderItem.graphql similarity index 77% rename from packages/magento-customer/components/OrderItem/OrderItem.graphql rename to packages/magento-customer/components/Order/OrderItem/OrderItem.graphql index 6f35039998..59b4f8a5e2 100644 --- a/packages/magento-customer/components/OrderItem/OrderItem.graphql +++ b/packages/magento-customer/components/Order/OrderItem/OrderItem.graphql @@ -22,4 +22,14 @@ fragment OrderItem on OrderItemInterface { product_sale_price { ...Money } + discounts { + amount { + ...Money + } + label + } + entered_options { + label + value + } } diff --git a/packages/magento-customer/components/OrderItem/OrderItem.tsx b/packages/magento-customer/components/Order/OrderItem/OrderItem.tsx similarity index 98% rename from packages/magento-customer/components/OrderItem/OrderItem.tsx rename to packages/magento-customer/components/Order/OrderItem/OrderItem.tsx index 35cccb48a0..248762c0fa 100644 --- a/packages/magento-customer/components/OrderItem/OrderItem.tsx +++ b/packages/magento-customer/components/Order/OrderItem/OrderItem.tsx @@ -4,7 +4,7 @@ import { useProductLink } from '@graphcommerce/magento-product/hooks/useProductL import { Money } from '@graphcommerce/magento-store' import { extendableComponent, NextLink, responsiveVal } from '@graphcommerce/next-ui' import { Box } from '@mui/material' -import type { OrderCardItemImageFragment } from '../../hooks/OrderCardItemImage.gql' +import type { OrderCardItemImageFragment } from '../../../hooks/OrderCardItemImage.gql' import type { OrderItemFragment } from './OrderItem.gql' export type OrderItemProps = OrderItemFragment & Omit diff --git a/packages/magento-customer/components/OrderItems/OrderItems.graphql b/packages/magento-customer/components/Order/OrderItems/OrderItems.graphql similarity index 100% rename from packages/magento-customer/components/OrderItems/OrderItems.graphql rename to packages/magento-customer/components/Order/OrderItems/OrderItems.graphql diff --git a/packages/magento-customer/components/OrderItems/OrderItems.tsx b/packages/magento-customer/components/Order/OrderItems/OrderItems.tsx similarity index 94% rename from packages/magento-customer/components/OrderItems/OrderItems.tsx rename to packages/magento-customer/components/Order/OrderItems/OrderItems.tsx index 8a449118c4..b6ef1ff9a0 100644 --- a/packages/magento-customer/components/OrderItems/OrderItems.tsx +++ b/packages/magento-customer/components/Order/OrderItems/OrderItems.tsx @@ -6,7 +6,8 @@ import { useState } from 'react' import { OrderItem } from '../OrderItem/OrderItem' import type { OrderItemsFragment } from './OrderItems.gql' -export type OrderItemsProps = OrderItemsFragment & { +export type OrderItemsProps = { + order: OrderItemsFragment sx?: SxProps } @@ -15,7 +16,9 @@ const parts = ['root', 'orderItemsInnerContainer', 'skeletonOrderItem', 'viewAll const { classes } = extendableComponent(componentName, parts) export function OrderItems(props: OrderItemsProps) { - const { items, sx = [] } = props + const { order, sx = [] } = props + const { items } = order + const [expanded, setExpanded] = useState(false) const maxItemsAboveFold = 4 diff --git a/packages/magento-customer/components/OrderStateLabel/OrderStateLabel.graphql b/packages/magento-customer/components/Order/OrderStateLabel/OrderStateLabel.graphql similarity index 100% rename from packages/magento-customer/components/OrderStateLabel/OrderStateLabel.graphql rename to packages/magento-customer/components/Order/OrderStateLabel/OrderStateLabel.graphql diff --git a/packages/magento-customer/components/OrderStateLabel/OrderStateLabel.tsx b/packages/magento-customer/components/Order/OrderStateLabel/OrderStateLabel.tsx similarity index 92% rename from packages/magento-customer/components/OrderStateLabel/OrderStateLabel.tsx rename to packages/magento-customer/components/Order/OrderStateLabel/OrderStateLabel.tsx index 667460b119..5f5403ec50 100644 --- a/packages/magento-customer/components/OrderStateLabel/OrderStateLabel.tsx +++ b/packages/magento-customer/components/Order/OrderStateLabel/OrderStateLabel.tsx @@ -2,8 +2,8 @@ import { extendableComponent } from '@graphcommerce/next-ui' import { Trans } from '@lingui/macro' import type { SxProps, Theme } from '@mui/material' import { Box } from '@mui/material' -import type { OrderState, OrderStateProps } from '../../utils' -import { getOrderState } from '../../utils' +import type { OrderState, OrderStateProps } from '../../../utils' +import { getOrderState } from '../../../utils' type OrderStateLabelPropsBase = OrderStateProps diff --git a/packages/magento-customer/components/OrderStateLabel/OrderStateLabelInline.tsx b/packages/magento-customer/components/Order/OrderStateLabel/OrderStateLabelInline.tsx similarity index 100% rename from packages/magento-customer/components/OrderStateLabel/OrderStateLabelInline.tsx rename to packages/magento-customer/components/Order/OrderStateLabel/OrderStateLabelInline.tsx diff --git a/packages/magento-customer/components/Order/OrderTotals/OrderTotal.graphql b/packages/magento-customer/components/Order/OrderTotals/OrderTotal.graphql new file mode 100644 index 0000000000..39abe8fa68 --- /dev/null +++ b/packages/magento-customer/components/Order/OrderTotals/OrderTotal.graphql @@ -0,0 +1,32 @@ +fragment OrderTotal on OrderTotal { + subtotal { + ...Money + } + total_shipping { + ...Money + } + shipping_handling { + ...ShippingHandling + } + discounts { + amount { + ...Money + } + label + } + base_grand_total { + ...Money + } + grand_total { + ...Money + } + total_tax { + ...Money + } + taxes { + ...TaxItem + } + total_shipping { + ...Money + } +} diff --git a/packages/magento-customer/components/Order/OrderTotals/OrderTotals.graphql b/packages/magento-customer/components/Order/OrderTotals/OrderTotals.graphql new file mode 100644 index 0000000000..2aa23604f2 --- /dev/null +++ b/packages/magento-customer/components/Order/OrderTotals/OrderTotals.graphql @@ -0,0 +1,7 @@ +fragment OrderTotals on CustomerOrder { + total { + ...OrderTotal + } + shipping_method + carrier +} diff --git a/packages/magento-customer/components/OrderDetails/OrderTotals.tsx b/packages/magento-customer/components/Order/OrderTotals/OrderTotals.tsx similarity index 92% rename from packages/magento-customer/components/OrderDetails/OrderTotals.tsx rename to packages/magento-customer/components/Order/OrderTotals/OrderTotals.tsx index f4e4ecb94c..b08f943323 100644 --- a/packages/magento-customer/components/OrderDetails/OrderTotals.tsx +++ b/packages/magento-customer/components/Order/OrderTotals/OrderTotals.tsx @@ -3,9 +3,10 @@ import { breakpointVal, extendableComponent } from '@graphcommerce/next-ui' import { Trans } from '@lingui/react' import type { SxProps, Theme } from '@mui/material' import { Box, Divider, Typography } from '@mui/material' -import type { OrderDetailsFragment } from './OrderDetails.gql' +import type { OrderTotalsFragment } from '../OrderDetails/OrderTotals.gql' -export type OrderTotalsProps = Partial & { +export type OrderTotalsProps = { + order: OrderTotalsFragment sx?: SxProps } @@ -14,7 +15,8 @@ const parts = ['totalsContainer', 'totalsRow', 'totalsDivider', 'totalsVat'] as const { classes } = extendableComponent(componentName, parts) export function OrderTotals(props: OrderTotalsProps) { - const { total, carrier, shipping_method, sx = [] } = props + const { order, sx = [] } = props + const { total, carrier, shipping_method } = order return ( +} + +export function ShipmentCard(props: ShipmentCardProps) { + const { orderNumber, shipment, sx = [] } = props + const { number } = shipment + + const tracking = filterNonNullableKeys(shipment.tracking) + + return ( + ({ + textDecoration: 'none', + color: 'text.primary', + px: theme.spacings.xxs, + py: theme.spacings.xxs, + gap: theme.spacings.sm, + background: + theme.palette.mode === 'light' + ? theme.palette.background.default + : lighten(theme.palette.background.default, 0.15), + ...breakpointVal( + 'borderRadius', + theme.shape.borderRadius * 2, + theme.shape.borderRadius * 3, + theme.breakpoints.values, + ), + // '&:hover': { + // backgroundColor: theme.palette.action.hover, + // }, + display: 'grid', + gridTemplate: ` + "number action" / 1fr auto + `, + rowGap: 0.5, + columnGap: 1, + }), + sx, + )} + > + + Shipment #{number} + + + + + ) +} diff --git a/packages/magento-customer/components/Shipment/ShipmentDetails.tsx b/packages/magento-customer/components/Shipment/ShipmentDetails.tsx new file mode 100644 index 0000000000..f7fd45ad75 --- /dev/null +++ b/packages/magento-customer/components/Shipment/ShipmentDetails.tsx @@ -0,0 +1,100 @@ +import { + breakpointVal, + DateTimeFormat, + extendableComponent, + filterNonNullableKeys, + SectionContainer, +} from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, lighten, Typography } from '@mui/material' +import { TrackingLink } from '../TrackingLink/TrackingLink' +import type { ShipmentFragment } from './Shipment.gql' + +export type ShipmentDetailsProps = { + shipment: ShipmentFragment + sx?: SxProps +} + +const componentName = 'ShipmentDetails' +const parts = [ + 'sectionContainer', + 'shipmentDetailTitle', + 'shipmentDetailContainer', + 'shipmentDetailRow', +] as const +const { classes } = extendableComponent(componentName, parts) + +export function ShipmentDetails(props: ShipmentDetailsProps) { + const { shipment, sx = [] } = props + const { number, tracking } = shipment + + return ( + Shipment details} + sx={[ + (theme) => ({ + padding: theme.spacings.sm, + marginBottom: theme.spacings.md, + background: + theme.palette.mode === 'light' + ? theme.palette.background.default + : lighten(theme.palette.background.default, 0.15), + ...breakpointVal( + 'borderRadius', + theme.shape.borderRadius * 2, + theme.shape.borderRadius * 3, + theme.breakpoints.values, + ), + '& .SectionHeader-root': { + mt: 0, + mb: theme.spacings.xs, + }, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + ({ + gridColumnGap: theme.spacings.xxl, + gridRowGap: theme.spacings.md, + display: 'grid', + [theme.breakpoints.up('sm')]: { + gridTemplateColumns: '1fr 1fr', + marginTop: theme.spacings.xxs, + }, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + + Shipment number} + className={classes.shipmentDetailTitle} + sx={{ '& .SectionHeader-root': { marginTop: 0, paddingBottom: '4px' } }} + > + {number} + + + + {tracking && tracking.length > 0 && ( + + Tracking} + className={classes.shipmentDetailTitle} + sx={{ '& .SectionHeader-root': { marginTop: 0, paddingBottom: '4px' } }} + > + {filterNonNullableKeys(tracking).map((track) => ( + + ))} + + + )} + + + ) +} diff --git a/packages/magento-customer/components/Shipment/ShipmentItem.graphql b/packages/magento-customer/components/Shipment/ShipmentItem.graphql new file mode 100644 index 0000000000..26ccaa386a --- /dev/null +++ b/packages/magento-customer/components/Shipment/ShipmentItem.graphql @@ -0,0 +1,12 @@ +fragment ShipmentItem on ShipmentItemInterface { + id + order_item { + id + } + product_name + product_sale_price { + ...Money + } + product_sku + quantity_shipped +} diff --git a/packages/magento-customer/components/Shipment/ShipmentItems.tsx b/packages/magento-customer/components/Shipment/ShipmentItems.tsx new file mode 100644 index 0000000000..605d4565c9 --- /dev/null +++ b/packages/magento-customer/components/Shipment/ShipmentItems.tsx @@ -0,0 +1,74 @@ +import { Money } from '@graphcommerce/magento-store' +import { extendableComponent, SectionContainer } from '@graphcommerce/next-ui' +import { Trans } from '@lingui/macro' +import type { SxProps, Theme } from '@mui/material' +import { Box, Typography } from '@mui/material' +import type { ShipmentFragment } from './Shipment.gql' + +export type ShipmentItemsProps = { + shipment: ShipmentFragment + sx?: SxProps +} + +const componentName = 'ShipmentItems' +const parts = ['root', 'shipmentItemsInnerContainer', 'itemRow', 'itemDetails'] as const +const { classes } = extendableComponent(componentName, parts) + +export function ShipmentItems(props: ShipmentItemsProps) { + const { shipment, sx = [] } = props + const { items } = shipment + + if (!items?.length) return null + + return ( + Shipped items} + className={classes.root} + sx={[ + (theme) => ({ + marginTop: theme.spacings.md, + marginBottom: theme.spacings.sm, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + ({ mb: theme.spacings.md })} + > + {items.map((item) => { + if (!item) return null + const { id, product_name, product_sku, quantity_shipped, product_sale_price } = item + + return ( + ({ + display: 'grid', + gridTemplateColumns: '1fr auto auto', + gap: theme.spacings.sm, + padding: `${theme.spacings.xs} 0`, + borderBottom: `1px solid ${theme.palette.divider}`, + '&:last-child': { + borderBottom: 'none', + }, + alignItems: 'center', + })} + > + + {quantity_shipped} ⨉ {product_name} + + + SKU: {product_sku} + + + + + + ) + })} + + + ) +} diff --git a/packages/magento-customer/components/Shipment/index.ts b/packages/magento-customer/components/Shipment/index.ts new file mode 100644 index 0000000000..6a2a86509a --- /dev/null +++ b/packages/magento-customer/components/Shipment/index.ts @@ -0,0 +1,6 @@ +export * from './Shipment.gql' +export * from './ShipmentCard' +export * from './ShipmentCard.gql' +export * from './ShipmentDetails' +export * from './ShipmentItem.gql' +export * from './ShipmentItems' diff --git a/packages/magento-customer/components/WaitForCustomer/WaitForCustomer.tsx b/packages/magento-customer/components/WaitForCustomer/WaitForCustomer.tsx index e4b32a535b..eead728828 100644 --- a/packages/magento-customer/components/WaitForCustomer/WaitForCustomer.tsx +++ b/packages/magento-customer/components/WaitForCustomer/WaitForCustomer.tsx @@ -12,6 +12,7 @@ import { ApolloCustomerErrorFullPage } from '../ApolloCustomerError/ApolloCustom export type WaitForCustomerProps = SetOptional & SetOptional & { unauthenticated?: React.ReactNode + allowError?: boolean } export function nonNullable(value: T): value is NonNullable { @@ -41,7 +42,14 @@ export function nonNullable(value: T): value is NonNullable { * ``` */ export function WaitForCustomer(props: WaitForCustomerProps) { - const { waitFor = [], children, fallback, unauthenticated, ...rest } = props + const { + waitFor = [], + children, + fallback, + unauthenticated, + allowError: ignoreError, + ...rest + } = props const session = useCustomerSession() const queries = Array.isArray(waitFor) ? waitFor : [waitFor] @@ -49,6 +57,7 @@ export function WaitForCustomer(props: WaitForCustomerProps) { queries.map((query) => (typeof query === 'boolean' ? null : query.error)).filter(nonNullable), ) + const hasError = error && !ignoreError return ( ))} - {session.loggedIn && error && } - {session.loggedIn && !error && children} + {session.loggedIn && hasError && } + {session.loggedIn && !hasError && children} ) } diff --git a/packages/magento-customer/components/index.ts b/packages/magento-customer/components/index.ts index de50bab86a..1aaec4d3c7 100644 --- a/packages/magento-customer/components/index.ts +++ b/packages/magento-customer/components/index.ts @@ -19,26 +19,22 @@ export * from './CompanyFields' export * from './ConfirmCustomer/ConfirmCustomerForm' export * from './ContactForm/ContactForm' export * from './CreateCustomerAddressForm/CreateCustomerAddressForm' +export * from './CreditMemo' export * from './CustomerFab/CustomerFab' -export * from './CustomerMenuFabItem/CustomerMenuFabItem' export * from './CustomerForms' +export * from './CustomerMenuFabItem/CustomerMenuFabItem' export * from './DeleteCustomerAddressForm/DeleteCustomerAddressForm' export * from './EditAddressForm/EditAddressForm' export * from './ForgotPasswordForm/ForgotPassword.gql' export * from './ForgotPasswordForm/ForgotPasswordForm' export * from './GuestOrderOverview/GuestOrderOverviewForm' +export * from './Invoice' export * from './NameFields/NameFields' export * from './NoOrdersFound/NoOrdersFound' -export * from './OrderCard/OrderCard' -export * from './OrderDetails/OrderDetails' -export * from './OrderDetails/OrderDetails.gql' -export * from './OrderDetails/OrderTotals' -export * from './OrderItem/OrderItem' -export * from './OrderItems/OrderItems' -export * from './OrderStateLabel/OrderStateLabel' -export * from './OrderStateLabel/OrderStateLabelInline' +export * from './Order' export * from './ReorderItems/ReorderItems' export * from './ResetPasswordForm/ResetPasswordForm' +export * from './Shipment' export * from './SignInForm/SignIn.gql' export * from './SignInForm/SignInForm' export * from './SignInForm/SignInFormInline' diff --git a/packages/magento-customer/graphql/OrderDetailPage.graphql b/packages/magento-customer/graphql/OrderDetailPage.graphql deleted file mode 100644 index 1750cfdcd2..0000000000 --- a/packages/magento-customer/graphql/OrderDetailPage.graphql +++ /dev/null @@ -1,10 +0,0 @@ -query OrderDetailPage($orderNumber: String) { - customer { - orders(filter: { number: { eq: $orderNumber } }) { - items { - ...OrderDetails - ...OrderItems - } - } - } -} diff --git a/packages/magento-customer/graphql/AccountDashboardQueryFragment.graphql b/packages/magento-customer/graphql/fragments/AccountDashboardQueryFragment.graphql similarity index 75% rename from packages/magento-customer/graphql/AccountDashboardQueryFragment.graphql rename to packages/magento-customer/graphql/fragments/AccountDashboardQueryFragment.graphql index 9fb09fc644..624fc9150f 100644 --- a/packages/magento-customer/graphql/AccountDashboardQueryFragment.graphql +++ b/packages/magento-customer/graphql/fragments/AccountDashboardQueryFragment.graphql @@ -9,12 +9,17 @@ fragment AccountDashboardQueryFragment on Query { sort: { sort_direction: DESC, sort_field: CREATED_AT } scope: GLOBAL ) { - items { - ...OrderCard - } + total_count page_info { + current_page + page_size total_pages } + items { + number + order_date + ...OrderStateLabel + } } ...AccountAddresses } diff --git a/packages/magento-customer/graphql/index.ts b/packages/magento-customer/graphql/index.ts new file mode 100644 index 0000000000..a22734f7e2 --- /dev/null +++ b/packages/magento-customer/graphql/index.ts @@ -0,0 +1,10 @@ +export * from './fragments/AccountDashboardQueryFragment.gql' +export * from './queries/AccountDashboard.gql' +export * from './queries/AccountDashboardAddresses.gql' +export * from './queries/AccountDashboardCustomer.gql' +export * from './queries/AccountDashboardOrders.gql' +export * from './queries/CreditMemoDetailPage.gql' +export * from './queries/InvoiceDetailPage.gql' +export * from './queries/OrderDetailPage.gql' +export * from './queries/ShipmentDetailPage.gql' +export * from './inject/CustomerStoreConfig.gql' diff --git a/packages/magento-customer/graphql/CustomerStoreConfig.graphql b/packages/magento-customer/graphql/inject/CustomerStoreConfig.graphql similarity index 100% rename from packages/magento-customer/graphql/CustomerStoreConfig.graphql rename to packages/magento-customer/graphql/inject/CustomerStoreConfig.graphql diff --git a/packages/magento-customer/graphql/AccountDashboard.graphql b/packages/magento-customer/graphql/queries/AccountDashboard.graphql similarity index 100% rename from packages/magento-customer/graphql/AccountDashboard.graphql rename to packages/magento-customer/graphql/queries/AccountDashboard.graphql diff --git a/packages/magento-customer/graphql/AccountDashboardAddresses.graphql b/packages/magento-customer/graphql/queries/AccountDashboardAddresses.graphql similarity index 100% rename from packages/magento-customer/graphql/AccountDashboardAddresses.graphql rename to packages/magento-customer/graphql/queries/AccountDashboardAddresses.graphql diff --git a/packages/magento-customer/graphql/AccountDashboardCustomer.graphql b/packages/magento-customer/graphql/queries/AccountDashboardCustomer.graphql similarity index 100% rename from packages/magento-customer/graphql/AccountDashboardCustomer.graphql rename to packages/magento-customer/graphql/queries/AccountDashboardCustomer.graphql diff --git a/packages/magento-customer/graphql/AccountDashboardOrders.graphql b/packages/magento-customer/graphql/queries/AccountDashboardOrders.graphql similarity index 100% rename from packages/magento-customer/graphql/AccountDashboardOrders.graphql rename to packages/magento-customer/graphql/queries/AccountDashboardOrders.graphql diff --git a/packages/magento-customer/graphql/queries/CreditMemoDetailPage.graphql b/packages/magento-customer/graphql/queries/CreditMemoDetailPage.graphql new file mode 100644 index 0000000000..6f6c805a03 --- /dev/null +++ b/packages/magento-customer/graphql/queries/CreditMemoDetailPage.graphql @@ -0,0 +1,14 @@ +query CreditMemoDetailPage($orderNumber: String!) { + customer { + orders(filter: { number: { eq: $orderNumber } }, scope: GLOBAL) { + items { + ...OrderDetails + id + number + credit_memos { + ...CreditMemo + } + } + } + } +} diff --git a/packages/magento-customer/graphql/queries/InvoiceDetailPage.graphql b/packages/magento-customer/graphql/queries/InvoiceDetailPage.graphql new file mode 100644 index 0000000000..ab6cd3c4c8 --- /dev/null +++ b/packages/magento-customer/graphql/queries/InvoiceDetailPage.graphql @@ -0,0 +1,14 @@ +query InvoiceDetailPage($orderNumber: String!) { + customer { + orders(filter: { number: { eq: $orderNumber } }, scope: GLOBAL) { + items { + ...OrderDetails + id + number + invoices { + ...Invoice + } + } + } + } +} diff --git a/packages/magento-customer/graphql/queries/OrderDetailPage.graphql b/packages/magento-customer/graphql/queries/OrderDetailPage.graphql new file mode 100644 index 0000000000..7127c62b12 --- /dev/null +++ b/packages/magento-customer/graphql/queries/OrderDetailPage.graphql @@ -0,0 +1,14 @@ +query OrderDetailPage($orderNumber: String) { + customer { + orders(filter: { number: { eq: $orderNumber } }, scope: GLOBAL) { + items { + id + ...OrderStateLabel + ...OrderDetails + ...OrderItems + ...OrderTotals + ...OrderAdditional + } + } + } +} diff --git a/packages/magento-customer/graphql/queries/ShipmentDetailPage.graphql b/packages/magento-customer/graphql/queries/ShipmentDetailPage.graphql new file mode 100644 index 0000000000..8074153083 --- /dev/null +++ b/packages/magento-customer/graphql/queries/ShipmentDetailPage.graphql @@ -0,0 +1,12 @@ +query ShipmentDetailPage($orderNumber: String!) { + customer { + orders(filter: { number: { eq: $orderNumber } }, scope: GLOBAL) { + items { + ...OrderDetails + shipments { + ...Shipment + } + } + } + } +} diff --git a/packages/magento-customer/index.ts b/packages/magento-customer/index.ts index 326ebb69cc..d9b07bfbf5 100644 --- a/packages/magento-customer/index.ts +++ b/packages/magento-customer/index.ts @@ -1,8 +1,5 @@ export * from './components' -export * from './graphql/AccountDashboard.gql' -export * from './graphql/AccountDashboardAddresses.gql' -export * from './graphql/AccountDashboardOrders.gql' -export * from './graphql/OrderDetailPage.gql' export * from './hooks' export * from './typePolicies' export * from './utils' +export * from './graphql' diff --git a/packages/magento-customer/utils/orderState.ts b/packages/magento-customer/utils/orderState.ts index d1b09269b4..f34999c04b 100644 --- a/packages/magento-customer/utils/orderState.ts +++ b/packages/magento-customer/utils/orderState.ts @@ -1,6 +1,5 @@ import { filterNonNullableKeys } from '@graphcommerce/next-ui' -import type { OrderDetailsFragment } from '../components/OrderDetails/OrderDetails.gql' -import type { OrderStateLabelFragment } from '../components/OrderStateLabel/OrderStateLabel.gql' +import type { OrderDetailsFragment, OrderStateLabelFragment } from '../components/Order' export type OrderState = 'pending' | 'processing' | 'complete' | 'closed'