@graphcommerce/magento-customer 9.1.0-canary.18 → 9.1.0-canary.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/components/AccountAddresses/AccountAddresses.tsx +9 -4
  3. package/components/AccountDeleteForm/AccountDeleteForm.tsx +14 -4
  4. package/components/AccountLatestOrder/AccountLatestOrder.tsx +1 -2
  5. package/components/AccountOrders/AccountOrders.tsx +1 -1
  6. package/components/CancelOrder/CancelOrderForm.tsx +2 -2
  7. package/components/CancelOrder/CancelOrderFragment.graphql +5 -0
  8. package/components/ChangeNameForm/ChangeNameForm.tsx +1 -0
  9. package/components/ContactForm/ContactUsConfig.graphql +3 -0
  10. package/components/CreditMemo/CreditMemo.graphql +43 -0
  11. package/components/CreditMemo/CreditMemoCard.graphql +12 -0
  12. package/components/CreditMemo/CreditMemoCard.tsx +66 -0
  13. package/components/CreditMemo/CreditMemoDetails.tsx +94 -0
  14. package/components/CreditMemo/CreditMemoItem.graphql +26 -0
  15. package/components/CreditMemo/CreditMemoItem.tsx +125 -0
  16. package/components/CreditMemo/CreditMemoItems.tsx +78 -0
  17. package/components/CreditMemo/CreditMemoTotals.tsx +122 -0
  18. package/components/CreditMemo/index.ts +8 -0
  19. package/components/CustomerForms/CustomerAttributeField.tsx +112 -0
  20. package/components/CustomerForms/CustomerAttributeMetadata.graphql +9 -0
  21. package/components/CustomerForms/CustomerUpdateForm.tsx +65 -0
  22. package/components/CustomerForms/UseCustomerCreateForm.graphql +7 -0
  23. package/components/CustomerForms/UseCustomerUpdateForm.graphql +7 -0
  24. package/components/CustomerForms/customerAttributeFieldHelpers.ts +127 -0
  25. package/components/CustomerForms/index.ts +8 -0
  26. package/components/CustomerForms/nameFieldset.tsx +32 -0
  27. package/components/CustomerForms/useCustomerCreateForm.ts +83 -0
  28. package/components/CustomerForms/useCustomerUpdateForm.ts +122 -0
  29. package/components/GuestOrderOverview/GuestOrderOverviewForm.tsx +28 -11
  30. package/components/Invoice/Invoice.graphql +13 -0
  31. package/components/Invoice/InvoiceCard.graphql +9 -0
  32. package/components/Invoice/InvoiceCard.tsx +66 -0
  33. package/components/Invoice/InvoiceDetails.tsx +94 -0
  34. package/components/Invoice/InvoiceItem.graphql +25 -0
  35. package/components/Invoice/InvoiceItem.tsx +125 -0
  36. package/components/Invoice/InvoiceItems.tsx +72 -0
  37. package/components/Invoice/InvoiceTotal.graphql +29 -0
  38. package/components/Invoice/InvoiceTotals.tsx +110 -0
  39. package/components/Invoice/index.ts +9 -0
  40. package/components/NameFields/NameFields.tsx +33 -18
  41. package/components/Order/OrderAdditional/OrderAdditional.graphql +16 -0
  42. package/components/Order/OrderAdditional/OrderAdditional.tsx +51 -0
  43. package/components/Order/OrderCard/OrderCard.graphql +13 -0
  44. package/components/{OrderCard → Order/OrderCard}/OrderCard.tsx +22 -18
  45. package/components/{OrderCardItem → Order/OrderCard}/OrderCardItem.graphql +1 -0
  46. package/components/Order/OrderComments/OrderComments.graphql +5 -0
  47. package/components/Order/OrderComments/SalesCommentItem.graphql +4 -0
  48. package/components/Order/OrderComments/SalesComments.tsx +28 -0
  49. package/components/Order/OrderDetails/OrderAddress.graphql +17 -0
  50. package/components/Order/OrderDetails/OrderDetails.graphql +38 -0
  51. package/components/{OrderDetails → Order/OrderDetails}/OrderDetails.tsx +70 -57
  52. package/components/Order/OrderDetails/ShippingHandling.graphql +19 -0
  53. package/components/Order/OrderDetails/TaxItem.graphql +7 -0
  54. package/components/{OrderItem → Order/OrderItem}/OrderItem.graphql +13 -0
  55. package/components/Order/OrderItem/OrderItem.tsx +144 -0
  56. package/components/Order/OrderItems/OrderItems.tsx +81 -0
  57. package/components/{OrderStateLabel → Order/OrderStateLabel}/OrderStateLabel.tsx +2 -2
  58. package/components/Order/OrderTotals/OrderTotal.graphql +32 -0
  59. package/components/Order/OrderTotals/OrderTotals.graphql +7 -0
  60. package/components/{OrderDetails → Order/OrderTotals}/OrderTotals.tsx +27 -12
  61. package/components/Order/index.ts +16 -0
  62. package/components/ReorderItems/ReorderItems.tsx +1 -1
  63. package/components/Shipment/Shipment.graphql +14 -0
  64. package/components/Shipment/ShipmentCard.graphql +8 -0
  65. package/components/Shipment/ShipmentCard.tsx +71 -0
  66. package/components/Shipment/ShipmentDetails.tsx +100 -0
  67. package/components/Shipment/ShipmentItem.graphql +19 -0
  68. package/components/Shipment/ShipmentItem.tsx +117 -0
  69. package/components/Shipment/ShipmentItems.tsx +72 -0
  70. package/components/Shipment/index.ts +7 -0
  71. package/components/SignUpForm/SignUpForm.tsx +51 -46
  72. package/components/WaitForCustomer/WaitForCustomer.tsx +12 -3
  73. package/components/index.ts +5 -8
  74. package/graphql/{AccountDashboardQueryFragment.graphql → fragments/AccountDashboardQueryFragment.graphql} +8 -3
  75. package/graphql/index.ts +10 -0
  76. package/graphql/queries/CreditMemoDetailPage.graphql +14 -0
  77. package/graphql/queries/InvoiceDetailPage.graphql +14 -0
  78. package/graphql/queries/OrderDetailPage.graphql +14 -0
  79. package/graphql/queries/ShipmentDetailPage.graphql +12 -0
  80. package/hooks/CustomerInfo.graphql +3 -3
  81. package/index.ts +1 -4
  82. package/package.json +14 -14
  83. package/utils/orderState.ts +1 -2
  84. package/components/OrderCard/OrderCard.graphql +0 -29
  85. package/components/OrderDetails/OrderDetails.graphql +0 -77
  86. package/components/OrderItem/OrderItem.tsx +0 -176
  87. package/components/OrderItems/OrderItems.tsx +0 -70
  88. package/graphql/OrderDetailPage.graphql +0 -10
  89. /package/components/{OrderItems → Order/OrderItems}/OrderItems.graphql +0 -0
  90. /package/components/{OrderStateLabel → Order/OrderStateLabel}/OrderStateLabel.graphql +0 -0
  91. /package/components/{OrderStateLabel → Order/OrderStateLabel}/OrderStateLabelInline.tsx +0 -0
  92. /package/graphql/{CustomerStoreConfig.graphql → inject/CustomerStoreConfig.graphql} +0 -0
  93. /package/graphql/{AccountDashboard.graphql → queries/AccountDashboard.graphql} +0 -0
  94. /package/graphql/{AccountDashboardAddresses.graphql → queries/AccountDashboardAddresses.graphql} +0 -0
  95. /package/graphql/{AccountDashboardCustomer.graphql → queries/AccountDashboardCustomer.graphql} +0 -0
  96. /package/graphql/{AccountDashboardOrders.graphql → queries/AccountDashboardOrders.graphql} +0 -0
@@ -0,0 +1,122 @@
1
+ import {
2
+ AttributesValueArray_to_CustomAttributesFormField,
3
+ CustomAttributesField_to_AttributeValueInputs,
4
+ useAttributesForm,
5
+ type CustomAttributeMetadata,
6
+ type CustomAttributesFormValues,
7
+ type UseAttributesFormConfig,
8
+ } from '@graphcommerce/magento-store'
9
+ import { useFormGqlMutation, type UseFormGraphQlOptions } from '@graphcommerce/react-hook-form'
10
+ import type { MutationHookOptions } from '@apollo/client'
11
+ import type { OmitDeep } from 'type-fest'
12
+ import type { CustomerInfoFragment } from '../../hooks'
13
+ import {
14
+ UseCustomerUpdateFormDocument,
15
+ type UseCustomerUpdateFormMutation,
16
+ type UseCustomerUpdateFormMutationVariables,
17
+ } from './UseCustomerUpdateForm.gql'
18
+
19
+ export type UpdateCustomerFormValues = OmitDeep<
20
+ UseCustomerUpdateFormMutationVariables,
21
+ | 'input.dob'
22
+ | 'input.date_of_birth'
23
+ | 'input.prefix'
24
+ | 'input.middlename'
25
+ | 'input.firstname'
26
+ | 'input.lastname'
27
+ | 'input.suffix'
28
+ | 'input.gender'
29
+ > &
30
+ CustomAttributesFormValues<
31
+ Record<
32
+ 'dob' | 'prefix' | 'firstname' | 'middlename' | 'lastname' | 'suffix' | 'gender',
33
+ string | undefined
34
+ >
35
+ >
36
+
37
+ /** Used for values prop of useFormGqlMutation */
38
+ export function CustomerInfo_to_UpdateCustomerFormValues(
39
+ attributes: CustomAttributeMetadata<'CustomerAttributeMetadata'>[],
40
+ customer: CustomerInfoFragment,
41
+ ): UpdateCustomerFormValues {
42
+ const { date_of_birth, prefix, firstname, middlename, lastname, suffix, gender } = customer
43
+
44
+ return {
45
+ input: {},
46
+ custom_attributes: {
47
+ ...AttributesValueArray_to_CustomAttributesFormField(attributes, customer.custom_attributes),
48
+ dob: date_of_birth ?? undefined,
49
+ prefix: prefix ?? undefined,
50
+ firstname: firstname ?? undefined,
51
+ middlename: middlename ?? undefined,
52
+ lastname: lastname ?? undefined,
53
+ suffix: suffix ?? undefined,
54
+ gender: gender ? String(gender) : undefined,
55
+ },
56
+ }
57
+ }
58
+
59
+ /** SUsed for onBeforeSubmit of useFormGqlMutation */
60
+ export function UpdateCustomerFormValues_to_UpdateCustomerVariables(
61
+ attributes: CustomAttributeMetadata<'CustomerAttributeMetadata'>[],
62
+ values: UpdateCustomerFormValues,
63
+ ): UseCustomerUpdateFormMutationVariables {
64
+ const { dob, firstname, middlename, gender, lastname, prefix, suffix, ...custom_attributes } =
65
+ values.custom_attributes ?? {}
66
+
67
+ return {
68
+ input: {
69
+ ...values.input,
70
+ firstname,
71
+ middlename,
72
+ lastname,
73
+ prefix,
74
+ suffix,
75
+ date_of_birth: dob,
76
+ gender: gender ? Number(gender) : undefined,
77
+ custom_attributes: [
78
+ ...(values.input.custom_attributes ?? []),
79
+ ...CustomAttributesField_to_AttributeValueInputs(attributes, custom_attributes),
80
+ ],
81
+ },
82
+ }
83
+ }
84
+
85
+ export type UseCustomerUpdateFormConfig = { customer: CustomerInfoFragment } & Omit<
86
+ UseAttributesFormConfig<'CustomerAttributeMetadata'>,
87
+ 'formCode' | 'typename'
88
+ >
89
+
90
+ export function useCustomerUpdateForm(
91
+ config: UseCustomerUpdateFormConfig,
92
+ useFormGqlOptions?: UseFormGraphQlOptions<
93
+ UseCustomerUpdateFormMutation,
94
+ UpdateCustomerFormValues
95
+ >,
96
+ mutationOptions?: MutationHookOptions<UseCustomerUpdateFormMutation, UpdateCustomerFormValues>,
97
+ ) {
98
+ const { customer, ...attributeFormConfig } = config
99
+ const attributes = useAttributesForm({
100
+ formCode: 'customer_account_edit',
101
+ exclude: ['email'],
102
+ typename: 'CustomerAttributeMetadata',
103
+ ...attributeFormConfig,
104
+ })
105
+
106
+ // console.log(customer, CustomerInfo_to_UpdateCustomerFormValues(attributes, customer))
107
+ const form = useFormGqlMutation<UseCustomerUpdateFormMutation, UpdateCustomerFormValues>(
108
+ UseCustomerUpdateFormDocument,
109
+ {
110
+ values: CustomerInfo_to_UpdateCustomerFormValues(attributes, customer),
111
+ onBeforeSubmit: async (values, f) => {
112
+ const result = (await useFormGqlOptions?.onBeforeSubmit?.(values, f)) ?? values
113
+ if (result === false) return false
114
+ return UpdateCustomerFormValues_to_UpdateCustomerVariables(attributes, values)
115
+ },
116
+ ...useFormGqlOptions,
117
+ },
118
+ mutationOptions,
119
+ )
120
+
121
+ return { ...form, attributes }
122
+ }
@@ -1,14 +1,19 @@
1
1
  import { EmailElement, TextFieldElement } from '@graphcommerce/ecommerce-ui'
2
- import { Button, FormActions, FormRow, useUrlQuery } from '@graphcommerce/next-ui'
2
+ import {
3
+ Button,
4
+ FormActions,
5
+ FormRow,
6
+ FullPageMessage,
7
+ iconBox,
8
+ IconSvg,
9
+ useUrlQuery,
10
+ } from '@graphcommerce/next-ui'
3
11
  import { useFormGqlQuery } from '@graphcommerce/react-hook-form'
4
12
  import { Trans } from '@lingui/macro'
5
13
  import { Box, Typography } from '@mui/material'
6
14
  import { useMemo } from 'react'
7
15
  import { ApolloCustomerErrorAlert } from '../ApolloCustomerError'
8
- import { OrderDetails } from '../OrderDetails/OrderDetails'
9
- import { OrderTotals } from '../OrderDetails/OrderTotals'
10
- import { OrderItems } from '../OrderItems/OrderItems'
11
- import { OrderStateLabel } from '../OrderStateLabel/OrderStateLabel'
16
+ import { OrderDetails, OrderItems, OrderStateLabel, OrderTotals } from '../Order'
12
17
  import type { GuestOrderQueryVariables } from './GuestOrder.gql'
13
18
  import { GuestOrderDocument } from './GuestOrder.gql'
14
19
 
@@ -84,12 +89,24 @@ export function GuestOrderOverviewForm() {
84
89
  </Box>
85
90
  ) : (
86
91
  <>
87
- <Typography sx={(theme) => ({ textAlign: 'center', mb: theme.spacings.lg })}>
88
- <OrderStateLabel {...orderData.guestOrder} />
89
- </Typography>
90
- <OrderDetails {...orderData?.guestOrder} />
91
- <OrderItems {...orderData?.guestOrder} />
92
- <OrderTotals {...orderData?.guestOrder} />
92
+ {!orderData?.guestOrder && (
93
+ <FullPageMessage
94
+ title={<Trans>Order not found</Trans>}
95
+ icon={<IconSvg src={iconBox} size='xxl' />}
96
+ />
97
+ )}
98
+
99
+ {orderData?.guestOrder && (
100
+ <>
101
+ <Typography sx={(theme) => ({ textAlign: 'center', mb: theme.spacings.lg })}>
102
+ <OrderStateLabel {...orderData.guestOrder} />
103
+ </Typography>
104
+ <OrderDetails order={orderData.guestOrder} />
105
+ <OrderItems order={orderData.guestOrder} />
106
+ <OrderTotals order={orderData.guestOrder} />
107
+ {/* <OrderAdditional order={order} /> */}
108
+ </>
109
+ )}
93
110
  </>
94
111
  )}
95
112
  </>
@@ -0,0 +1,13 @@
1
+ fragment Invoice on Invoice {
2
+ id
3
+ number
4
+ items {
5
+ ...InvoiceItem
6
+ }
7
+ total {
8
+ ...InvoiceTotal
9
+ }
10
+ comments {
11
+ ...SalesCommentItem
12
+ }
13
+ }
@@ -0,0 +1,9 @@
1
+ fragment InvoiceCard on Invoice {
2
+ id
3
+ number
4
+ total {
5
+ grand_total {
6
+ ...Money
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,66 @@
1
+ import { Money } from '@graphcommerce/magento-store'
2
+ import { breakpointVal, iconChevronRight, IconSvg, NextLink, sxx } from '@graphcommerce/next-ui'
3
+ import { Trans } from '@lingui/macro'
4
+ import type { SxProps, Theme } from '@mui/material'
5
+ import { Box, lighten } from '@mui/material'
6
+ import type { InvoiceCardFragment } from './InvoiceCard.gql'
7
+
8
+ export type InvoiceCardProps = {
9
+ orderNumber: string
10
+ invoice: InvoiceCardFragment
11
+ sx?: SxProps<Theme>
12
+ }
13
+
14
+ export function InvoiceCard(props: InvoiceCardProps) {
15
+ const { invoice, sx = [], orderNumber } = props
16
+ const { number, total } = invoice
17
+
18
+ return (
19
+ <Box
20
+ component={NextLink}
21
+ href={`/account/orders/invoice?orderNumber=${orderNumber}&invoiceNumber=${number}`}
22
+ sx={sxx(
23
+ (theme) => ({
24
+ textDecoration: 'none',
25
+ color: 'text.primary',
26
+ px: theme.spacings.xxs,
27
+ py: theme.spacings.xxs,
28
+ gap: theme.spacings.sm,
29
+ background:
30
+ theme.palette.mode === 'light'
31
+ ? theme.palette.background.default
32
+ : lighten(theme.palette.background.default, 0.15),
33
+ ...breakpointVal(
34
+ 'borderRadius',
35
+ theme.shape.borderRadius * 2,
36
+ theme.shape.borderRadius * 3,
37
+ theme.breakpoints.values,
38
+ ),
39
+ '&:hover': {
40
+ backgroundColor: theme.palette.action.hover,
41
+ },
42
+ display: 'grid',
43
+ gridTemplate: `
44
+ "number total action" / 1fr auto auto
45
+ `,
46
+ rowGap: 0.5,
47
+ columnGap: 1,
48
+ }),
49
+ sx,
50
+ )}
51
+ >
52
+ <Box sx={{ gridArea: 'number', typography: 'body1' }}>
53
+ <Trans>Invoice #{number}</Trans>
54
+ </Box>
55
+ <Box sx={{ gridArea: 'total', alignSelf: 'center' }}>
56
+ <Money {...total?.grand_total} />
57
+ </Box>
58
+
59
+ <IconSvg
60
+ src={iconChevronRight}
61
+ size='medium'
62
+ sx={{ gridArea: 'action', alignSelf: 'center' }}
63
+ />
64
+ </Box>
65
+ )
66
+ }
@@ -0,0 +1,94 @@
1
+ import {
2
+ breakpointVal,
3
+ DateTimeFormat,
4
+ extendableComponent,
5
+ SectionContainer,
6
+ } from '@graphcommerce/next-ui'
7
+ import { Trans } from '@lingui/macro'
8
+ import type { SxProps, Theme } from '@mui/material'
9
+ import { Box, lighten, Typography } from '@mui/material'
10
+ import type { InvoiceFragment } from './Invoice.gql'
11
+
12
+ export type InvoiceDetailsProps = {
13
+ invoice: InvoiceFragment
14
+ sx?: SxProps<Theme>
15
+ }
16
+
17
+ const componentName = 'InvoiceDetails'
18
+ const parts = [
19
+ 'sectionContainer',
20
+ 'invoiceDetailTitle',
21
+ 'invoiceDetailContainer',
22
+ 'invoiceDetailRow',
23
+ ] as const
24
+ const { classes } = extendableComponent(componentName, parts)
25
+
26
+ export function InvoiceDetails(props: InvoiceDetailsProps) {
27
+ const { invoice, sx = [] } = props
28
+ const { number, id } = invoice
29
+
30
+ return (
31
+ <SectionContainer
32
+ labelLeft={<Trans>Invoice details</Trans>}
33
+ sx={[
34
+ (theme) => ({
35
+ padding: theme.spacings.sm,
36
+ marginBottom: theme.spacings.md,
37
+ background:
38
+ theme.palette.mode === 'light'
39
+ ? theme.palette.background.default
40
+ : lighten(theme.palette.background.default, 0.15),
41
+ ...breakpointVal(
42
+ 'borderRadius',
43
+ theme.shape.borderRadius * 2,
44
+ theme.shape.borderRadius * 3,
45
+ theme.breakpoints.values,
46
+ ),
47
+ '& .SectionHeader-root': {
48
+ mt: 0,
49
+ mb: theme.spacings.xs,
50
+ },
51
+ }),
52
+ ...(Array.isArray(sx) ? sx : [sx]),
53
+ ]}
54
+ >
55
+ <Box
56
+ className={classes.invoiceDetailContainer}
57
+ sx={[
58
+ (theme) => ({
59
+ gridColumnGap: theme.spacings.xxl,
60
+ gridRowGap: theme.spacings.md,
61
+ display: 'grid',
62
+ [theme.breakpoints.up('sm')]: {
63
+ gridTemplateColumns: '1fr 1fr',
64
+ marginTop: theme.spacings.xxs,
65
+ },
66
+ }),
67
+ ...(Array.isArray(sx) ? sx : [sx]),
68
+ ]}
69
+ >
70
+ <Box className={classes.invoiceDetailRow}>
71
+ <SectionContainer
72
+ variantLeft='h5'
73
+ labelLeft={<Trans>Invoice number</Trans>}
74
+ className={classes.invoiceDetailTitle}
75
+ sx={{ '& .SectionHeader-root': { marginTop: 0, paddingBottom: '4px' } }}
76
+ >
77
+ <Typography>{number}</Typography>
78
+ </SectionContainer>
79
+ </Box>
80
+
81
+ <Box className={classes.invoiceDetailRow}>
82
+ {/* <SectionContainer
83
+ variantLeft='h5'
84
+ labelLeft={<Trans>Invoice ID</Trans>}
85
+ className={classes.invoiceDetailTitle}
86
+ sx={{ '& .SectionHeader-root': { marginTop: 0, paddingBottom: '4px' } }}
87
+ >
88
+ <Typography>{id}</Typography>
89
+ </SectionContainer> */}
90
+ </Box>
91
+ </Box>
92
+ </SectionContainer>
93
+ )
94
+ }
@@ -0,0 +1,25 @@
1
+ fragment InvoiceItem on InvoiceItemInterface {
2
+ __typename
3
+ id
4
+ discounts {
5
+ amount {
6
+ ...Money
7
+ }
8
+ label
9
+ }
10
+ product_name
11
+ product_sale_price {
12
+ ...Money
13
+ }
14
+ product_sku
15
+ quantity_invoiced
16
+ order_item {
17
+ id
18
+ product {
19
+ uid
20
+ thumbnail {
21
+ ...ProductImage
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,125 @@
1
+ import { Image } from '@graphcommerce/image'
2
+ import { Money, PriceModifiersList, type PriceModifier } from '@graphcommerce/magento-store'
3
+ import { ActionCard, actionCardImageSizes, type ActionCardProps } from '@graphcommerce/next-ui'
4
+ import { Trans } from '@lingui/react'
5
+ import { Box } from '@mui/material'
6
+ import type { InvoiceItemFragment } from './InvoiceItem.gql'
7
+
8
+ export type InvoiceItemProps = Omit<ActionCardProps, 'value' | 'image' | 'title'> & {
9
+ item: InvoiceItemFragment
10
+ priceModifiers?: PriceModifier[]
11
+ }
12
+
13
+ export function InvoiceItem(props: InvoiceItemProps) {
14
+ const { item, priceModifiers, size = 'responsive', ...rest } = props
15
+ const {
16
+ product_name,
17
+ product_sku,
18
+ quantity_invoiced,
19
+ product_sale_price,
20
+ discounts,
21
+ order_item,
22
+ id,
23
+ } = item
24
+
25
+ return (
26
+ <ActionCard
27
+ {...rest}
28
+ value={id}
29
+ sx={(theme) => ({
30
+ '&.ActionCard-root': {
31
+ px: 0,
32
+ py: theme.spacings.xs,
33
+ },
34
+ '& .ActionCard-rootInner': {
35
+ justifyContent: 'space-between',
36
+ alignItems: 'stretch',
37
+ },
38
+ '&.sizeSmall': {
39
+ px: 0,
40
+ },
41
+ '&.sizeResponsive': {
42
+ [theme.breakpoints.down('md')]: { px: 0 },
43
+ },
44
+ '& .ActionCard-end': {
45
+ justifyContent: 'space-between',
46
+ },
47
+ '& .ActionCard-action': {
48
+ pr: 0,
49
+ },
50
+ '& .ActionCard-image': {
51
+ alignSelf: 'flex-start',
52
+ },
53
+ '& .ActionCard-secondaryAction': {
54
+ display: 'grid',
55
+ rowGap: theme.spacings.xs,
56
+ justifyItems: 'start',
57
+ },
58
+ '& .ActionCard-price': {
59
+ pr: 0,
60
+ mb: { xs: 0.5, sm: 0 },
61
+ },
62
+ })}
63
+ size={size}
64
+ image={
65
+ order_item?.product?.thumbnail?.url && (
66
+ <Image
67
+ layout='fill'
68
+ src={order_item.product.thumbnail.url}
69
+ alt={order_item?.product.thumbnail?.label ?? ''}
70
+ sx={{
71
+ width: actionCardImageSizes[size],
72
+ height: actionCardImageSizes[size],
73
+ display: 'block',
74
+ borderRadius: 1,
75
+ objectFit: 'contain',
76
+ backgroundColor: 'background.image',
77
+ }}
78
+ sizes={actionCardImageSizes[size]}
79
+ />
80
+ )
81
+ }
82
+ title={product_name}
83
+ action={<>&nbsp;</>}
84
+ price={
85
+ <Money
86
+ currency={product_sale_price.currency}
87
+ value={(product_sale_price.value ?? 0) * (quantity_invoiced ?? 1)}
88
+ />
89
+ }
90
+ secondaryAction={
91
+ <>
92
+ <Box
93
+ sx={{
94
+ display: 'flex',
95
+ alignItems: 'center',
96
+ color: 'text.secondary',
97
+ mt: 1,
98
+ gap: '10px',
99
+ justifyContent: 'start',
100
+ }}
101
+ >
102
+ {quantity_invoiced}
103
+ {' ⨉ '}
104
+ <Money {...product_sale_price} />
105
+ </Box>
106
+
107
+ {rest.secondaryAction}
108
+ </>
109
+ }
110
+ details={
111
+ <>
112
+ {priceModifiers && priceModifiers.length > 0 && (
113
+ <PriceModifiersList
114
+ label={<Trans id='Base Price'>Base price</Trans>}
115
+ modifiers={[...priceModifiers]}
116
+ total={product_sale_price.value ?? 0}
117
+ currency={product_sale_price.currency}
118
+ />
119
+ )}
120
+ {rest.details}
121
+ </>
122
+ }
123
+ />
124
+ )
125
+ }
@@ -0,0 +1,72 @@
1
+ import {
2
+ ActionCardLayout,
3
+ breakpointVal,
4
+ extendableComponent,
5
+ nonNullable,
6
+ SectionContainer,
7
+ } from '@graphcommerce/next-ui'
8
+ import { Trans } from '@lingui/macro'
9
+ import type { SxProps, Theme } from '@mui/material'
10
+ import { Box } from '@mui/material'
11
+ import type { InvoiceFragment } from './Invoice.gql'
12
+ import { InvoiceItem } from './InvoiceItem'
13
+
14
+ export type InvoiceItemsProps = {
15
+ invoice: InvoiceFragment
16
+ sx?: SxProps<Theme>
17
+ layout?: 'list' | 'grid'
18
+ size?: 'small' | 'medium' | 'large'
19
+ }
20
+
21
+ const componentName = 'InvoiceItems'
22
+ const parts = ['root', 'items', 'actionCard'] as const
23
+ const { classes } = extendableComponent(componentName, parts)
24
+
25
+ export function InvoiceItems(props: InvoiceItemsProps) {
26
+ const { invoice, sx = [], layout = 'list', size } = props
27
+
28
+ const items = (invoice.items ?? []).filter(nonNullable)
29
+ if (!items.length) return null
30
+
31
+ return (
32
+ <Box
33
+ className={classes.root}
34
+ sx={[
35
+ (theme) => ({
36
+ my: theme.spacings.md,
37
+ padding: `${theme.spacings.sm} ${theme.spacings.sm}`,
38
+ border: `1px ${theme.palette.divider} solid`,
39
+ ...breakpointVal(
40
+ 'borderRadius',
41
+ theme.shape.borderRadius * 2,
42
+ theme.shape.borderRadius * 3,
43
+ theme.breakpoints.values,
44
+ ),
45
+ }),
46
+ ...(Array.isArray(sx) ? sx : [sx]),
47
+ ]}
48
+ >
49
+ <SectionContainer
50
+ sx={{ '& .SectionHeader-root': { mt: 0 } }}
51
+ labelLeft={<Trans>Invoiced items</Trans>}
52
+ variantLeft='h6'
53
+ className={classes.items}
54
+ >
55
+ <ActionCardLayout
56
+ sx={(theme) => ({
57
+ marginBottom: theme.spacings.md,
58
+ '&.layoutStack': {
59
+ gap: 0,
60
+ },
61
+ })}
62
+ className={classes.actionCard}
63
+ layout={layout}
64
+ >
65
+ {items.map((item) => (
66
+ <InvoiceItem key={item.id} item={item} size={size} layout={layout} variant='default' />
67
+ ))}
68
+ </ActionCardLayout>
69
+ </SectionContainer>
70
+ </Box>
71
+ )
72
+ }
@@ -0,0 +1,29 @@
1
+ fragment InvoiceTotal on InvoiceTotal {
2
+ subtotal {
3
+ ...Money
4
+ }
5
+ shipping_handling {
6
+ ...ShippingHandling
7
+ }
8
+ total_shipping {
9
+ ...Money
10
+ }
11
+ discounts {
12
+ amount {
13
+ ...Money
14
+ }
15
+ label
16
+ }
17
+ base_grand_total {
18
+ ...Money
19
+ }
20
+ grand_total {
21
+ ...Money
22
+ }
23
+ taxes {
24
+ ...TaxItem
25
+ }
26
+ total_tax {
27
+ ...Money
28
+ }
29
+ }