@graphcommerce/magento-review 2.105.1

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 (36) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/components/AccountReviews/AccountReviews.gql.ts +4 -0
  3. package/components/AccountReviews/AccountReviews.graphql +5 -0
  4. package/components/AccountReviews/index.tsx +64 -0
  5. package/components/CreateProductReviewForm/CreateProductReview.gql.ts +16 -0
  6. package/components/CreateProductReviewForm/CreateProductReview.graphql +15 -0
  7. package/components/CreateProductReviewForm/ProductReviewRatingsMetadata.gql.ts +10 -0
  8. package/components/CreateProductReviewForm/ProductReviewRatingsMetadata.graphql +12 -0
  9. package/components/CreateProductReviewForm/index.tsx +231 -0
  10. package/components/CustomerReview/CustomerReview.gql.ts +4 -0
  11. package/components/CustomerReview/CustomerReview.graphql +20 -0
  12. package/components/CustomerReview/index.tsx +103 -0
  13. package/components/CustomerReview/review_star_filled.svg +7 -0
  14. package/components/CustomerReview/review_star_outlined.svg +7 -0
  15. package/components/JsonLdProductReview/JsonLdProductReview.gql.ts +16 -0
  16. package/components/JsonLdProductReview/JsonLdProductReview.graphql +5 -0
  17. package/components/JsonLdProductReview/index.ts +28 -0
  18. package/components/ProductReviewChip/ProductReviewSummary.gql.ts +16 -0
  19. package/components/ProductReviewChip/ProductReviewSummary.graphql +4 -0
  20. package/components/ProductReviewChip/index.tsx +45 -0
  21. package/components/ProductReviews/ProductReviewProductName.gql.ts +12 -0
  22. package/components/ProductReviews/ProductReviewProductName.graphql +9 -0
  23. package/components/ProductReviews/ProductReviewRatingsMetadata.gql.ts +10 -0
  24. package/components/ProductReviews/ProductReviewRatingsMetadata.graphql +12 -0
  25. package/components/ProductReviews/ProductReviews.gql.ts +16 -0
  26. package/components/ProductReviews/ProductReviews.graphql +22 -0
  27. package/components/ProductReviews/ProductReviewsPage.gql.ts +14 -0
  28. package/components/ProductReviews/ProductReviewsPage.graphql +10 -0
  29. package/components/ProductReviews/index.tsx +205 -0
  30. package/components/index.ts +16 -0
  31. package/index.ts +2 -0
  32. package/inject/AccountDashboardCustomerReviews.gql.ts +4 -0
  33. package/inject/AccountDashboardCustomerReviews.graphql +8 -0
  34. package/package.json +38 -0
  35. package/queries/AccountDashboardReviews.gql.ts +10 -0
  36. package/queries/AccountDashboardReviews.graphql +7 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,124 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [2.105.1](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-review@2.105.0...@graphcommerce/magento-review@2.105.1) (2021-09-27)
7
+
8
+ **Note:** Version bump only for package @graphcommerce/magento-review
9
+
10
+
11
+
12
+
13
+
14
+ # 2.105.0 (2021-09-27)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * customer-order folder structure ([b7fabd1](https://github.com/ho-nl/m2-pwa/commit/b7fabd12014b2925d0b89c21f58e9974ce1c8b40))
20
+ * introduced SvgImageSimple and solve issue with review chips ([931d7fd](https://github.com/ho-nl/m2-pwa/commit/931d7fdcf0faa9d2264899b72e564138215b6bd8))
21
+ * make separate queries folder, create injectable for account and inject reviews ([5d82a5d](https://github.com/ho-nl/m2-pwa/commit/5d82a5d9162f687c2678cce215b77eedbaf1669e))
22
+ * remove coupon form style was too large ([30df274](https://github.com/ho-nl/m2-pwa/commit/30df274ecdffdcebd76710a5304d6fa248e81211))
23
+ * **review:** make sure chip is rendered correctly ([387df34](https://github.com/ho-nl/m2-pwa/commit/387df3456973290f9ce98d47823a7c71a6d95850))
24
+ * SvgSimpleImage sizing didn't use rem ([1ba07a5](https://github.com/ho-nl/m2-pwa/commit/1ba07a5694bd60ad3cee2e8102814643d2a7c79d))
25
+
26
+
27
+ ### Features
28
+
29
+ * **playwright:** added new playwright package to enable browser testing ([6f49ec7](https://github.com/ho-nl/m2-pwa/commit/6f49ec7595563775b96ebf21c27e39da1282e8d9))
30
+ * renamed all packages to use [@graphcommerce](https://github.com/graphcommerce) instead of [@reachdigital](https://github.com/reachdigital) ([491e4ce](https://github.com/ho-nl/m2-pwa/commit/491e4cec9a2686472dac36b79f999257c0811ffe))
31
+ * **theme:** restructured fonts and applied to home and category page ([6adf5f1](https://github.com/ho-nl/m2-pwa/commit/6adf5f11321bdfbf499125f1161c5abf5a1bfe4a))
32
+ * upgraded to nextjs 11 ([0053beb](https://github.com/ho-nl/m2-pwa/commit/0053beb7ef597c190add7264256a0eaec35868da))
33
+
34
+
35
+ ### Reverts
36
+
37
+ * Revert "chore: upgrade @apollo/client" ([55ff24e](https://github.com/ho-nl/m2-pwa/commit/55ff24ede0e56c85b8095edadadd1ec5e0b1b8d2))
38
+
39
+
40
+
41
+
42
+
43
+ # Change Log
44
+
45
+ All notable changes to this project will be documented in this file. See
46
+ [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
47
+
48
+ # [2.104.0](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-review@2.103.2...@graphcommerce/magento-review@2.104.0) (2021-08-12)
49
+
50
+ ### Bug Fixes
51
+
52
+ - remove coupon form style was too large
53
+ ([30df274](https://github.com/ho-nl/m2-pwa/commit/30df274ecdffdcebd76710a5304d6fa248e81211))
54
+
55
+ ### Features
56
+
57
+ - upgraded to nextjs 11
58
+ ([0053beb](https://github.com/ho-nl/m2-pwa/commit/0053beb7ef597c190add7264256a0eaec35868da))
59
+
60
+ ## [2.103.2](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-review@2.103.1...@graphcommerce/magento-review@2.103.2) (2021-08-09)
61
+
62
+ ### Bug Fixes
63
+
64
+ - SvgSimpleImage sizing didn't use rem
65
+ ([1ba07a5](https://github.com/ho-nl/m2-pwa/commit/1ba07a5694bd60ad3cee2e8102814643d2a7c79d))
66
+
67
+ ### Reverts
68
+
69
+ - Revert "chore: upgrade @apollo/client"
70
+ ([55ff24e](https://github.com/ho-nl/m2-pwa/commit/55ff24ede0e56c85b8095edadadd1ec5e0b1b8d2))
71
+
72
+ ## [2.103.1](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-review@2.103.0...@graphcommerce/magento-review@2.103.1) (2021-08-09)
73
+
74
+ ### Bug Fixes
75
+
76
+ - **review:** make sure chip is rendered correctly
77
+ ([387df34](https://github.com/ho-nl/m2-pwa/commit/387df3456973290f9ce98d47823a7c71a6d95850))
78
+
79
+ # [2.103.0](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-review@2.102.6...@graphcommerce/magento-review@2.103.0) (2021-08-06)
80
+
81
+ ### Bug Fixes
82
+
83
+ - introduced SvgImageSimple and solve issue with review chips
84
+ ([931d7fd](https://github.com/ho-nl/m2-pwa/commit/931d7fdcf0faa9d2264899b72e564138215b6bd8))
85
+
86
+ ### Features
87
+
88
+ - **theme:** restructured fonts and applied to home and category page
89
+ ([6adf5f1](https://github.com/ho-nl/m2-pwa/commit/6adf5f11321bdfbf499125f1161c5abf5a1bfe4a))
90
+
91
+ # [2.102.0](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-review@2.101.3...@graphcommerce/magento-review@2.102.0) (2021-07-26)
92
+
93
+ ### Features
94
+
95
+ - **playwright:** added new playwright package to enable browser testing
96
+ ([6f49ec7](https://github.com/ho-nl/m2-pwa/commit/6f49ec7595563775b96ebf21c27e39da1282e8d9))
97
+
98
+ ## 2.101.1 (2021-07-23)
99
+
100
+ ### Bug Fixes
101
+
102
+ - customer-order folder structure
103
+ ([b7fabd1](https://github.com/ho-nl/m2-pwa/commit/b7fabd12014b2925d0b89c21f58e9974ce1c8b40))
104
+ - make separate queries folder, create injectable for account and inject reviews
105
+ ([5d82a5d](https://github.com/ho-nl/m2-pwa/commit/5d82a5d9162f687c2678cce215b77eedbaf1669e))
106
+
107
+ # [2.101.0](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-product-review@2.100.14...@graphcommerce/magento-product-review@2.101.0) (2021-07-21)
108
+
109
+ ### Bug Fixes
110
+
111
+ - write review button mobile styles
112
+ ([8f6b883](https://github.com/ho-nl/m2-pwa/commit/8f6b883fa0a513f84b7c6d8ed376b0e8d4b8a3bd))
113
+
114
+ ### Features
115
+
116
+ - **reviews:** no reviews written message
117
+ ([8ade3db](https://github.com/ho-nl/m2-pwa/commit/8ade3dbe830f5a59af09c002dfa38fa5349a4b61))
118
+
119
+ ## [2.100.11](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-product-review@2.100.10...@graphcommerce/magento-product-review@2.100.11) (2021-07-20)
120
+
121
+ ### Bug Fixes
122
+
123
+ - ignore md files from triggering version updates
124
+ ([4f98392](https://github.com/ho-nl/m2-pwa/commit/4f9839250b3a32d3070da5290e5efcc5e2243fba))
@@ -0,0 +1,4 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ export type AccountReviewsFragment = { items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, product: { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> }, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> };
@@ -0,0 +1,5 @@
1
+ fragment AccountReviews on ProductReviews {
2
+ items {
3
+ ...CustomerReview
4
+ }
5
+ }
@@ -0,0 +1,64 @@
1
+ import { makeStyles, Theme } from '@material-ui/core'
2
+ import { Skeleton } from '@material-ui/lab'
3
+ import { SectionContainer } from '@graphcommerce/next-ui'
4
+ import React from 'react'
5
+ import CustomerReview from '../CustomerReview'
6
+ import { AccountReviewsFragment } from './AccountReviews.gql'
7
+
8
+ type AccountReviewsProps = AccountReviewsFragment & { loading: boolean }
9
+
10
+ const useStyles = makeStyles(
11
+ (theme: Theme) => ({
12
+ reviewsContainer: {
13
+ marginBottom: theme.spacings.md,
14
+ },
15
+ olderReviewsContainer: {
16
+ [theme.breakpoints.up('md')]: {
17
+ marginTop: theme.spacings.lg,
18
+ marginBottom: theme.spacings.lg,
19
+ },
20
+ marginTop: theme.spacings.md,
21
+ marginBottom: theme.spacings.md,
22
+ },
23
+ }),
24
+ { name: 'AccountReviews' },
25
+ )
26
+
27
+ export default function AccountReviews(props: AccountReviewsProps) {
28
+ const { items, loading } = props
29
+ const classes = useStyles()
30
+ const showLatestReviews = 2
31
+ const latestReviews = items?.slice(0, Math.min(items?.length, showLatestReviews))
32
+ const olderReviews = items?.slice(Math.min(items?.length, showLatestReviews), items?.length)
33
+
34
+ if (loading) {
35
+ return (
36
+ <div className={classes.reviewsContainer}>
37
+ <SectionContainer labelLeft='Latest'>
38
+ <Skeleton height={196} />
39
+ <Skeleton height={196} />
40
+ </SectionContainer>
41
+ </div>
42
+ )
43
+ }
44
+ return (
45
+ <div className={classes.reviewsContainer}>
46
+ <SectionContainer labelLeft='Latest'>
47
+ {latestReviews?.map(
48
+ (review) => review && <CustomerReview key={review.created_at} {...review} />,
49
+ )}
50
+ </SectionContainer>
51
+
52
+ {items && items.length >= showLatestReviews + 1 && (
53
+ <SectionContainer
54
+ labelLeft='Older'
55
+ classes={{ sectionContainer: classes.olderReviewsContainer }}
56
+ >
57
+ {olderReviews?.map(
58
+ (review, i) => review && <CustomerReview key={review.created_at} {...review} />,
59
+ )}
60
+ </SectionContainer>
61
+ )}
62
+ </div>
63
+ )
64
+ }
@@ -0,0 +1,16 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const CreateProductReviewDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProductReview"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"nickname"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"ratings"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ProductReviewRatingInput"}}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"sku"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"summary"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"text"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createProductReview"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"nickname"},"value":{"kind":"Variable","name":{"kind":"Name","value":"nickname"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"ratings"},"value":{"kind":"Variable","name":{"kind":"Name","value":"ratings"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"sku"},"value":{"kind":"Variable","name":{"kind":"Name","value":"sku"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"summary"},"value":{"kind":"Variable","name":{"kind":"Name","value":"summary"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"text"},"value":{"kind":"Variable","name":{"kind":"Name","value":"text"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"review"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"average_rating"}},{"kind":"Field","name":{"kind":"Name","value":"created_at"}},{"kind":"Field","name":{"kind":"Name","value":"product"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"uid"}},{"kind":"Field","name":{"kind":"Name","value":"url_key"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"thumbnail"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"label"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"nickname"}},{"kind":"Field","name":{"kind":"Name","value":"summary"}},{"kind":"Field","name":{"kind":"Name","value":"text"}},{"kind":"Field","name":{"kind":"Name","value":"ratings_breakdown"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]}}]} as unknown as DocumentNode<CreateProductReviewMutation, CreateProductReviewMutationVariables>;
7
+ export type CreateProductReviewMutationVariables = Types.Exact<{
8
+ nickname: Types.Scalars['String'];
9
+ ratings: Array<Types.Maybe<Types.ProductReviewRatingInput>> | Types.Maybe<Types.ProductReviewRatingInput>;
10
+ sku: Types.Scalars['String'];
11
+ summary: Types.Scalars['String'];
12
+ text: Types.Scalars['String'];
13
+ }>;
14
+
15
+
16
+ export type CreateProductReviewMutation = { createProductReview: { review: { average_rating: number, created_at: string, nickname: string, summary: string, text: string, product: { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> }, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> } } };
@@ -0,0 +1,15 @@
1
+ mutation CreateProductReview(
2
+ $nickname: String!
3
+ $ratings: [ProductReviewRatingInput]!
4
+ $sku: String!
5
+ $summary: String!
6
+ $text: String!
7
+ ) {
8
+ createProductReview(
9
+ input: { nickname: $nickname, ratings: $ratings, sku: $sku, summary: $summary, text: $text }
10
+ ) {
11
+ review {
12
+ ...CustomerReview
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,10 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const ProductReviewRatingsMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProductReviewRatingsMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productReviewRatingsMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"values"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"value_id"}}]}}]}}]}}]}}]} as unknown as DocumentNode<ProductReviewRatingsMetadataQuery, ProductReviewRatingsMetadataQueryVariables>;
7
+ export type ProductReviewRatingsMetadataQueryVariables = Types.Exact<{ [key: string]: never; }>;
8
+
9
+
10
+ export type ProductReviewRatingsMetadataQuery = { productReviewRatingsMetadata: { items: Array<Types.Maybe<{ id: string, name: string, values: Array<Types.Maybe<{ value: string, value_id: string }>> }>> } };
@@ -0,0 +1,12 @@
1
+ query ProductReviewRatingsMetadata {
2
+ productReviewRatingsMetadata {
3
+ items {
4
+ id
5
+ name
6
+ values {
7
+ value
8
+ value_id
9
+ }
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,231 @@
1
+ import { useQuery } from '@apollo/client'
2
+ import { Box, makeStyles, TextField, Theme, Typography } from '@material-ui/core'
3
+ import { Alert } from '@material-ui/lab'
4
+ import { ProductReviewRatingInput } from '@graphcommerce/graphql'
5
+ import {
6
+ Button,
7
+ Form,
8
+ UseStyles,
9
+ responsiveVal,
10
+ FormActions,
11
+ FormRow,
12
+ StarRatingField,
13
+ } from '@graphcommerce/next-ui'
14
+ import { useFormGqlMutation } from '@graphcommerce/react-hook-form'
15
+ import { useRouter } from 'next/router'
16
+ import React, { useEffect, useState } from 'react'
17
+ import ApolloCustomerErrorAlert from '../../../magento-customer/components/ApolloCustomerError/ApolloCustomerErrorAlert'
18
+ import { CreateProductReviewDocument } from './CreateProductReview.gql'
19
+ import { ProductReviewRatingsMetadataDocument } from './ProductReviewRatingsMetadata.gql'
20
+
21
+ const useStyles = makeStyles(
22
+ (theme: Theme) => ({
23
+ ratingContainer: {
24
+ marginBottom: theme.spacings.xxs,
25
+ },
26
+ rating: {
27
+ paddingBottom: 'unset',
28
+ gridTemplateColumns: `minmax(${responsiveVal(60, 80)}, 0.1fr) max-content`,
29
+ alignItems: 'center',
30
+ },
31
+ ratingLabel: {
32
+ fontWeight: 'normal',
33
+ justifySelf: 'left',
34
+ },
35
+ submitButton: {
36
+ width: responsiveVal(200, 250),
37
+ height: responsiveVal(40, 50),
38
+ borderRadius: responsiveVal(20, 25),
39
+ },
40
+ cancelButton: {
41
+ display: 'block',
42
+ maxWidth: 'max-content',
43
+ margin: '0 auto',
44
+ },
45
+ formActions: {
46
+ gridAutoFlow: 'row',
47
+ gap: 8,
48
+ marginTop: theme.spacings.xxs,
49
+ },
50
+ }),
51
+ {
52
+ name: 'CreateProductReviewForm',
53
+ },
54
+ )
55
+
56
+ type CreateProductReviewFormProps = {
57
+ sku: string
58
+ nickname?: string
59
+ } & UseStyles<typeof useStyles>
60
+
61
+ export default function CreateProductReviewForm(props: CreateProductReviewFormProps) {
62
+ const { sku, nickname } = props
63
+ const classes = useStyles(props)
64
+ const router = useRouter()
65
+ const [ratings, setRatings] = useState<ProductReviewRatingInput[]>([])
66
+
67
+ const { data, loading } = useQuery(ProductReviewRatingsMetadataDocument)
68
+
69
+ const form = useFormGqlMutation(
70
+ CreateProductReviewDocument,
71
+ {
72
+ defaultValues: { sku, nickname },
73
+ onBeforeSubmit: (formData) => ({
74
+ ...formData,
75
+ ratings: ratings.some((r) => r.value_id === '') ? [] : ratings,
76
+ }),
77
+ },
78
+ { errorPolicy: 'all' },
79
+ )
80
+ const { handleSubmit, muiRegister, formState, required, error } = form
81
+ const submitHandler = handleSubmit(() => {})
82
+
83
+ useEffect(() => {
84
+ if (loading || !data) return
85
+
86
+ // set initial state
87
+ if (ratings.length === 0) {
88
+ const reviewMetadataRatings = data.productReviewRatingsMetadata.items.map((metadata) => ({
89
+ id: metadata?.id ?? '',
90
+ value_id: '',
91
+ }))
92
+
93
+ setRatings(reviewMetadataRatings)
94
+ }
95
+ }, [loading, data, ratings.length])
96
+
97
+ if (!data) return <></>
98
+
99
+ if (formState.isSubmitSuccessful && data) {
100
+ return (
101
+ <>
102
+ <Alert severity='success' variant='standard'>
103
+ Thank you! Your review was successfully submitted for approval
104
+ </Alert>
105
+ <Box mt={6}>
106
+ <Button
107
+ variant='contained'
108
+ color='primary'
109
+ text='bold'
110
+ size='large'
111
+ onClick={() => router.back()}
112
+ >
113
+ Continue shopping
114
+ </Button>
115
+ </Box>
116
+ </>
117
+ )
118
+ }
119
+
120
+ return (
121
+ <Form onSubmit={submitHandler} noValidate>
122
+ <FormRow>
123
+ <TextField
124
+ variant='outlined'
125
+ type='text'
126
+ error={!!formState.errors.nickname || !!error}
127
+ label='Name'
128
+ required={required.nickname}
129
+ {...muiRegister('nickname', { required: required.nickname })}
130
+ helperText={formState.errors.nickname?.message}
131
+ disabled={formState.isSubmitting}
132
+ InputProps={{
133
+ readOnly: typeof nickname !== 'undefined',
134
+ }}
135
+ />
136
+ </FormRow>
137
+
138
+ <div className={classes.ratingContainer}>
139
+ {data?.productReviewRatingsMetadata?.items?.map((prrvm) => (
140
+ <FormRow key={prrvm?.id} className={classes.rating}>
141
+ <Typography variant='h5' component='span' className={classes.ratingLabel}>
142
+ {prrvm?.name}
143
+ </Typography>
144
+ {prrvm && (
145
+ <StarRatingField
146
+ id={prrvm?.id ?? ''}
147
+ onChange={(id, value) => {
148
+ const productReviewRatingInputValue =
149
+ data.productReviewRatingsMetadata.items.find((meta) => meta?.id === id)?.values[
150
+ value - 1
151
+ ]
152
+
153
+ const ratingsArr = [...ratings]
154
+
155
+ const clonedProductReviewRatingInputValue = ratingsArr.find(
156
+ (meta) => meta.id === id,
157
+ )
158
+
159
+ if (
160
+ !clonedProductReviewRatingInputValue ||
161
+ typeof productReviewRatingInputValue?.value_id === undefined
162
+ ) {
163
+ console.error('Cannot find product review rating input value in local state')
164
+ return
165
+ }
166
+
167
+ clonedProductReviewRatingInputValue.value_id =
168
+ productReviewRatingInputValue?.value_id ?? ''
169
+
170
+ setRatings(ratingsArr)
171
+ }}
172
+ />
173
+ )}
174
+ </FormRow>
175
+ ))}
176
+ </div>
177
+
178
+ <FormRow>
179
+ <TextField
180
+ variant='outlined'
181
+ type='text'
182
+ error={!!formState.errors.summary || !!error}
183
+ label='Summary'
184
+ required={required.summary}
185
+ {...muiRegister('summary', { required: required.summary })}
186
+ helperText={formState.errors.summary?.message}
187
+ disabled={formState.isSubmitting}
188
+ />
189
+ </FormRow>
190
+
191
+ <FormRow>
192
+ <TextField
193
+ variant='outlined'
194
+ type='text'
195
+ error={!!formState.errors.text || !!error}
196
+ label='Review'
197
+ required={required.text}
198
+ {...muiRegister('text', { required: required.text })}
199
+ helperText={formState.errors.text?.message}
200
+ disabled={formState.isSubmitting}
201
+ multiline
202
+ rows={8}
203
+ rowsMax={8}
204
+ />
205
+ </FormRow>
206
+
207
+ <FormActions className={classes.formActions}>
208
+ <Button
209
+ variant='pill'
210
+ color='primary'
211
+ text='bold'
212
+ type='submit'
213
+ size='medium'
214
+ className={classes.submitButton}
215
+ >
216
+ Submit review
217
+ </Button>
218
+ <Button
219
+ variant='text'
220
+ color='primary'
221
+ onClick={() => router.back()}
222
+ className={classes.cancelButton}
223
+ >
224
+ Cancel
225
+ </Button>
226
+ </FormActions>
227
+
228
+ <ApolloCustomerErrorAlert error={error} />
229
+ </Form>
230
+ )
231
+ }
@@ -0,0 +1,4 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ export type CustomerReviewFragment = { average_rating: number, created_at: string, nickname: string, summary: string, text: string, product: { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> }, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> };
@@ -0,0 +1,20 @@
1
+ fragment CustomerReview on ProductReview {
2
+ average_rating
3
+ created_at
4
+ product {
5
+ uid
6
+ url_key
7
+ name
8
+ thumbnail {
9
+ url
10
+ label
11
+ }
12
+ }
13
+ nickname
14
+ summary
15
+ text
16
+ ratings_breakdown {
17
+ name
18
+ value
19
+ }
20
+ }
@@ -0,0 +1,103 @@
1
+ import { useQuery } from '@apollo/client'
2
+ import { makeStyles, Theme } from '@material-ui/core'
3
+ import { Image } from '@graphcommerce/image'
4
+ import { StoreConfigDocument } from '@graphcommerce/magento-store'
5
+ import { responsiveVal } from '@graphcommerce/next-ui'
6
+ import { CustomerReviewFragment } from './CustomerReview.gql'
7
+ import filledStar from './review_star_filled.svg'
8
+ import outlinedStar from './review_star_outlined.svg'
9
+
10
+ type CustomerReviewProps = CustomerReviewFragment
11
+
12
+ const useStyles = makeStyles(
13
+ (theme: Theme) => ({
14
+ container: {
15
+ padding: `${theme.spacings.md} 0 ${theme.spacings.md} 0`,
16
+ display: 'grid',
17
+ gridTemplateAreas: `
18
+ 'image stars'
19
+ 'image title'
20
+ 'image text'
21
+ 'image date'`,
22
+ gridTemplateColumns: `${responsiveVal(96, 196)} 1fr`,
23
+ gridColumnGap: theme.spacings.md,
24
+ gridRowGap: theme.spacings.sm,
25
+ alignItems: 'start',
26
+ ...theme.typography.body1,
27
+ borderBottom: `1px solid ${theme.palette.divider}`,
28
+ [theme.breakpoints.up('sm')]: {
29
+ gridRowGap: theme.spacings.xxs,
30
+ },
31
+ },
32
+ image: {
33
+ gridArea: 'image',
34
+ '& img': {
35
+ width: '100%',
36
+ height: 'auto',
37
+ },
38
+ },
39
+ stars: {
40
+ gridArea: 'stars',
41
+ margin: '-6px 0 -6px -6px',
42
+ },
43
+ title: {
44
+ gridArea: 'title',
45
+ fontWeight: theme.typography.fontWeightBold,
46
+ },
47
+ text: {
48
+ gridArea: 'text',
49
+ },
50
+ date: {
51
+ gridArea: 'date',
52
+ fontStyle: 'italic',
53
+ color: theme.palette.primary.mutedText,
54
+ },
55
+ }),
56
+ { name: 'CustomerReview' },
57
+ )
58
+
59
+ export default function CustomerReview(props: CustomerReviewProps) {
60
+ const { product, text, average_rating, created_at } = props
61
+ const classes = useStyles()
62
+
63
+ const maxAverageRating = 100
64
+ const totalStars = 5
65
+ const valuePerStar = maxAverageRating / totalStars
66
+ const totalFilledStars = (average_rating / maxAverageRating / valuePerStar) * 100
67
+
68
+ const { data: config } = useQuery(StoreConfigDocument)
69
+ const locale = config?.storeConfig?.locale?.replace('_', '-')
70
+
71
+ const dateFormatter = new Intl.DateTimeFormat(locale, {
72
+ year: 'numeric',
73
+ month: 'long',
74
+ day: 'numeric',
75
+ })
76
+
77
+ return (
78
+ <div className={classes.container}>
79
+ <div className={classes.image}>
80
+ {product && product.thumbnail && (
81
+ <Image
82
+ src={product.thumbnail?.url ?? ''}
83
+ width={196}
84
+ height={196}
85
+ alt={product.thumbnail?.label ?? ''}
86
+ />
87
+ )}
88
+ </div>
89
+ <div className={classes.stars}>
90
+ {[...new Array(totalStars)].map((value, index) => (
91
+ <Image
92
+ src={index < totalFilledStars ? filledStar : outlinedStar}
93
+ alt='star'
94
+ loading='eager'
95
+ />
96
+ ))}
97
+ </div>
98
+ <div className={classes.title}>{product?.name}</div>
99
+ <div className={classes.text}>{text}</div>
100
+ <div className={classes.date}>{dateFormatter.format(new Date(created_at ?? ''))}</div>
101
+ </div>
102
+ )
103
+ }
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <title>desktop_Star_Filled</title>
4
+ <g id="desktop_Star_Filled" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
5
+ <polygon id="Path" stroke="#FF4A55" stroke-width="0.5" fill="#FF4A55" points="16.3216665 21.1249997 11.1783333 23.8291663 12.1608332 18.1016665 8 14.0458332 13.7499999 13.2108332 16.3216665 8 18.8933331 13.2108332 24.643333 14.0458332 20.4824998 18.1016665 21.4649997 23.8291663"></polygon>
6
+ </g>
7
+ </svg>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <title>desktop_Star_Outline</title>
4
+ <g id="desktop_Star_Outline" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
5
+ <polygon id="Path" stroke="#FF4A55" stroke-width="0.5" points="16.3216665 21.1249997 11.1783333 23.8291663 12.1608332 18.1016665 8 14.0458332 13.7499999 13.2108332 16.3216665 8 18.8933331 13.2108332 24.643333 14.0458332 20.4824998 18.1016665 21.4649997 23.8291663"></polygon>
6
+ </g>
7
+ </svg>
@@ -0,0 +1,16 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ export type JsonLdProductReview_BundleProduct_Fragment = { review_count: number, rating_summary: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
5
+
6
+ export type JsonLdProductReview_ConfigurableProduct_Fragment = { review_count: number, rating_summary: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
7
+
8
+ export type JsonLdProductReview_DownloadableProduct_Fragment = { review_count: number, rating_summary: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
9
+
10
+ export type JsonLdProductReview_GroupedProduct_Fragment = { review_count: number, rating_summary: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
11
+
12
+ export type JsonLdProductReview_SimpleProduct_Fragment = { review_count: number, rating_summary: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
13
+
14
+ export type JsonLdProductReview_VirtualProduct_Fragment = { review_count: number, rating_summary: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
15
+
16
+ export type JsonLdProductReviewFragment = JsonLdProductReview_BundleProduct_Fragment | JsonLdProductReview_ConfigurableProduct_Fragment | JsonLdProductReview_DownloadableProduct_Fragment | JsonLdProductReview_GroupedProduct_Fragment | JsonLdProductReview_SimpleProduct_Fragment | JsonLdProductReview_VirtualProduct_Fragment;
@@ -0,0 +1,5 @@
1
+ fragment JsonLdProductReview on ProductInterface @inject(into: ["ProductPageItem"]) {
2
+ ...ProductReviews
3
+ review_count
4
+ rating_summary
5
+ }
@@ -0,0 +1,28 @@
1
+ import { Product } from 'schema-dts'
2
+ import { JsonLdProductReviewFragment } from './JsonLdProductReview.gql'
3
+
4
+ export function jsonLdProductReview(props: JsonLdProductReviewFragment): Partial<Product> {
5
+ const { reviews, review_count, rating_summary } = props
6
+
7
+ return {
8
+ aggregateRating: {
9
+ '@type': 'AggregateRating',
10
+ reviewCount: review_count ?? undefined,
11
+ ratingValue: rating_summary ? Math.max(rating_summary * 0.5 * 0.1, 1) : undefined,
12
+ },
13
+ review: reviews.items.map((review) => ({
14
+ '@type': 'Review',
15
+ reviewRating: {
16
+ '@type': 'Rating',
17
+ ratingValue: Math.max((review?.average_rating || 1) * 0.5 * 0.1, 1),
18
+ },
19
+ name: review?.summary,
20
+ author: {
21
+ '@type': 'Person',
22
+ name: review?.nickname,
23
+ },
24
+ datePublished: review?.created_at,
25
+ reviewBody: review?.text,
26
+ })),
27
+ }
28
+ }
@@ -0,0 +1,16 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ export type ProductReviewSummary_BundleProduct_Fragment = { rating_summary: number };
5
+
6
+ export type ProductReviewSummary_ConfigurableProduct_Fragment = { rating_summary: number };
7
+
8
+ export type ProductReviewSummary_DownloadableProduct_Fragment = { rating_summary: number };
9
+
10
+ export type ProductReviewSummary_GroupedProduct_Fragment = { rating_summary: number };
11
+
12
+ export type ProductReviewSummary_SimpleProduct_Fragment = { rating_summary: number };
13
+
14
+ export type ProductReviewSummary_VirtualProduct_Fragment = { rating_summary: number };
15
+
16
+ export type ProductReviewSummaryFragment = ProductReviewSummary_BundleProduct_Fragment | ProductReviewSummary_ConfigurableProduct_Fragment | ProductReviewSummary_DownloadableProduct_Fragment | ProductReviewSummary_GroupedProduct_Fragment | ProductReviewSummary_SimpleProduct_Fragment | ProductReviewSummary_VirtualProduct_Fragment;
@@ -0,0 +1,4 @@
1
+ fragment ProductReviewSummary on ProductInterface
2
+ @inject(into: ["ProductListItem", "ProductPageItem"]) {
3
+ rating_summary
4
+ }
@@ -0,0 +1,45 @@
1
+ import { Chip, ChipProps } from '@material-ui/core'
2
+ import { SvgImageSimple, iconStarYellow } from '@graphcommerce/next-ui'
3
+ import React from 'react'
4
+
5
+ export type ProductReviewChipProps = {
6
+ rating?: number
7
+ reviewSectionId?: string
8
+ max?: number
9
+ } & ChipProps
10
+
11
+ export default function ProductReviewChip(props: ProductReviewChipProps) {
12
+ const { rating, reviewSectionId = '', max = 5, ...chipProps } = props
13
+
14
+ if (!rating) return null
15
+
16
+ const normalizedRating = Math.round(rating / (10 / max)) / 10
17
+
18
+ const handleClick: React.MouseEventHandler<HTMLDivElement> = (e) => {
19
+ const element = document.getElementById(reviewSectionId)
20
+ e.preventDefault()
21
+ if (!element) return
22
+
23
+ window.scrollTo({
24
+ top: element.offsetTop - 50,
25
+ left: 0,
26
+ behavior: 'smooth',
27
+ })
28
+ }
29
+
30
+ const chip = (
31
+ <Chip
32
+ variant='outlined'
33
+ clickable={!!reviewSectionId}
34
+ onClick={handleClick}
35
+ icon={<SvgImageSimple src={iconStarYellow} alt='Stars' />}
36
+ color='default'
37
+ label={`${normalizedRating}/5`}
38
+ {...chipProps}
39
+ />
40
+ )
41
+
42
+ if (!reviewSectionId) return chip
43
+
44
+ return chip
45
+ }
@@ -0,0 +1,12 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const ProductReviewProductNameDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProductReviewProductName"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"sku"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"products"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"sku"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"sku"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"uid"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode<ProductReviewProductNameQuery, ProductReviewProductNameQueryVariables>;
7
+ export type ProductReviewProductNameQueryVariables = Types.Exact<{
8
+ sku: Types.Scalars['String'];
9
+ }>;
10
+
11
+
12
+ export type ProductReviewProductNameQuery = { products?: Types.Maybe<{ items?: Types.Maybe<Array<Types.Maybe<{ __typename: 'BundleProduct', uid: string, name?: Types.Maybe<string> } | { __typename: 'ConfigurableProduct', uid: string, name?: Types.Maybe<string> } | { __typename: 'DownloadableProduct', uid: string, name?: Types.Maybe<string> } | { __typename: 'GroupedProduct', uid: string, name?: Types.Maybe<string> } | { __typename: 'SimpleProduct', uid: string, name?: Types.Maybe<string> } | { __typename: 'VirtualProduct', uid: string, name?: Types.Maybe<string> }>>> }> };
@@ -0,0 +1,9 @@
1
+ query ProductReviewProductName($sku: String!) {
2
+ products(filter: { sku: { eq: $sku } }) {
3
+ items {
4
+ __typename
5
+ uid
6
+ name
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const ProductReviewRatingsMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProductReviewRatingsMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productReviewRatingsMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"values"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"value_id"}}]}}]}}]}}]}}]} as unknown as DocumentNode<ProductReviewRatingsMetadataQuery, ProductReviewRatingsMetadataQueryVariables>;
7
+ export type ProductReviewRatingsMetadataQueryVariables = Types.Exact<{ [key: string]: never; }>;
8
+
9
+
10
+ export type ProductReviewRatingsMetadataQuery = { productReviewRatingsMetadata: { items: Array<Types.Maybe<{ id: string, name: string, values: Array<Types.Maybe<{ value: string, value_id: string }>> }>> } };
@@ -0,0 +1,12 @@
1
+ query ProductReviewRatingsMetadata {
2
+ productReviewRatingsMetadata {
3
+ items {
4
+ id
5
+ name
6
+ values {
7
+ value
8
+ value_id
9
+ }
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,16 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ export type ProductReviews_BundleProduct_Fragment = { review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
5
+
6
+ export type ProductReviews_ConfigurableProduct_Fragment = { review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
7
+
8
+ export type ProductReviews_DownloadableProduct_Fragment = { review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
9
+
10
+ export type ProductReviews_GroupedProduct_Fragment = { review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
11
+
12
+ export type ProductReviews_SimpleProduct_Fragment = { review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
13
+
14
+ export type ProductReviews_VirtualProduct_Fragment = { review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
15
+
16
+ export type ProductReviewsFragment = ProductReviews_BundleProduct_Fragment | ProductReviews_ConfigurableProduct_Fragment | ProductReviews_DownloadableProduct_Fragment | ProductReviews_GroupedProduct_Fragment | ProductReviews_SimpleProduct_Fragment | ProductReviews_VirtualProduct_Fragment;
@@ -0,0 +1,22 @@
1
+ fragment ProductReviews on ProductInterface @inject(into: ["ProductPageItem"]) {
2
+ reviews(pageSize: $reviewPageSize, currentPage: $reviewPage) {
3
+ page_info {
4
+ total_pages
5
+ current_page
6
+ }
7
+ items {
8
+ average_rating
9
+ created_at
10
+ nickname
11
+ ratings_breakdown {
12
+ name
13
+ value
14
+ }
15
+ summary
16
+ text
17
+ }
18
+ }
19
+ review_count
20
+ url_key
21
+ sku
22
+ }
@@ -0,0 +1,14 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const ProductReviewsPageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProductReviewsPage"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"urlKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"reviewPageSize"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"reviewPage"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"products"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"url_key"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"urlKey"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"uid"}},{"kind":"Field","name":{"kind":"Name","value":"review_count"}},{"kind":"Field","name":{"kind":"Name","value":"reviews"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"pageSize"},"value":{"kind":"Variable","name":{"kind":"Name","value":"reviewPageSize"}}},{"kind":"Argument","name":{"kind":"Name","value":"currentPage"},"value":{"kind":"Variable","name":{"kind":"Name","value":"reviewPage"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"page_info"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total_pages"}},{"kind":"Field","name":{"kind":"Name","value":"current_page"}}]}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"average_rating"}},{"kind":"Field","name":{"kind":"Name","value":"created_at"}},{"kind":"Field","name":{"kind":"Name","value":"nickname"}},{"kind":"Field","name":{"kind":"Name","value":"ratings_breakdown"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}},{"kind":"Field","name":{"kind":"Name","value":"summary"}},{"kind":"Field","name":{"kind":"Name","value":"text"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"url_key"}},{"kind":"Field","name":{"kind":"Name","value":"sku"}}]}}]}}]}}]} as unknown as DocumentNode<ProductReviewsPageQuery, ProductReviewsPageQueryVariables>;
7
+ export type ProductReviewsPageQueryVariables = Types.Exact<{
8
+ urlKey: Types.Scalars['String'];
9
+ reviewPageSize?: Types.Maybe<Types.Scalars['Int']>;
10
+ reviewPage: Types.Scalars['Int'];
11
+ }>;
12
+
13
+
14
+ export type ProductReviewsPageQuery = { products?: Types.Maybe<{ items?: Types.Maybe<Array<Types.Maybe<{ __typename: 'BundleProduct', uid: string, review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } } | { __typename: 'ConfigurableProduct', uid: string, review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } } | { __typename: 'DownloadableProduct', uid: string, review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } } | { __typename: 'GroupedProduct', uid: string, review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } } | { __typename: 'SimpleProduct', uid: string, review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } } | { __typename: 'VirtualProduct', uid: string, review_count: number, url_key?: Types.Maybe<string>, sku?: Types.Maybe<string>, reviews: { page_info: { total_pages?: Types.Maybe<number>, current_page?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } }>>> }> };
@@ -0,0 +1,10 @@
1
+ query ProductReviewsPage($urlKey: String!, $reviewPageSize: Int, $reviewPage: Int!) {
2
+ products(filter: { url_key: { eq: $urlKey } }) {
3
+ items {
4
+ __typename
5
+ uid
6
+ review_count
7
+ ...ProductReviews
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,205 @@
1
+ import { useQuery } from '@apollo/client'
2
+ import { Chip, makeStyles, Theme, Typography } from '@material-ui/core'
3
+ import {
4
+ Button,
5
+ iconStarFilledMuted,
6
+ iconStarYellow,
7
+ Pagination,
8
+ responsiveVal,
9
+ StarRatingField,
10
+ SvgImage,
11
+ } from '@graphcommerce/next-ui'
12
+ import Link from 'next/link'
13
+ import React, { useState } from 'react'
14
+ import ProductReviewChip from '../ProductReviewChip'
15
+ import { ProductReviewsFragment } from './ProductReviews.gql'
16
+ import { ProductReviewsPageDocument } from './ProductReviewsPage.gql'
17
+
18
+ const useStyles = makeStyles(
19
+ (theme: Theme) => ({
20
+ review: {
21
+ display: 'grid',
22
+ gap: theme.spacings.sm,
23
+ borderBottom: `1px solid ${theme.palette.divider}`,
24
+ padding: `${theme.spacings.md} 0`,
25
+ ...theme.typography.body1,
26
+ },
27
+ title: {
28
+ display: 'grid',
29
+ gridAutoFlow: 'column',
30
+ justifyContent: 'start',
31
+ gap: theme.spacings.xs,
32
+ alignItems: 'center',
33
+ },
34
+ meta: {
35
+ color: theme.palette.text.disabled,
36
+ display: 'grid',
37
+ gridAutoFlow: 'column',
38
+ justifyContent: 'space-between',
39
+ },
40
+ nickname: {},
41
+ date: {},
42
+ reviewsBottomContainer: {
43
+ display: 'flex',
44
+ alignItems: 'center',
45
+ justifyContent: 'space-between',
46
+ marginTop: theme.spacings.sm,
47
+ },
48
+ paginationRoot: {
49
+ margin: `0 -16px 0`,
50
+ },
51
+ paginationButton: {
52
+ padding: 0,
53
+ minWidth: 'unset',
54
+ borderRadius: '100%',
55
+ '& > .MuiButton-label': {
56
+ padding: 0,
57
+ },
58
+ },
59
+ ratingRow: {
60
+ display: 'flex',
61
+ flexWrap: 'wrap',
62
+ gap: theme.spacings.sm,
63
+ color: theme.palette.text.disabled,
64
+ ...theme.typography.body2,
65
+ },
66
+ rating: {
67
+ display: 'grid',
68
+ gridAutoFlow: 'column',
69
+ gridTemplateColumns: '0.4fr 0.6fr',
70
+ justifyContent: 'space-between',
71
+ marginRight: theme.spacings.xxs,
72
+ rowGap: responsiveVal(8, 16),
73
+ gap: 8,
74
+ alignItems: 'center',
75
+ },
76
+ writeReviewButton: {
77
+ [theme.breakpoints.down('xs')]: {
78
+ padding: '8px 16px 8px',
79
+ whiteSpace: 'nowrap',
80
+ },
81
+ },
82
+ container: {
83
+ marginTop: `calc(${theme.spacings.xxs} * -1)`,
84
+ },
85
+ }),
86
+ { name: 'ProductReviews' },
87
+ )
88
+
89
+ export type ProductReviewsProps = ProductReviewsFragment
90
+
91
+ export default function ProductReviews(props: ProductReviewsProps) {
92
+ const { reviews, url_key, sku } = props
93
+ const classes = useStyles()
94
+ const config = 'en_US'
95
+ const locale = config.replace('_', '-')
96
+
97
+ const [reviewPage, setPage] = useState<number>(1)
98
+
99
+ const { data: otherReviewsPage, loading } = useQuery(ProductReviewsPageDocument, {
100
+ skip: reviewPage === 1,
101
+ variables: {
102
+ urlKey: url_key ?? '',
103
+ reviewPage,
104
+ reviewPageSize: 3,
105
+ },
106
+ })
107
+
108
+ const myReviews = otherReviewsPage?.products?.items?.[0]?.reviews ?? reviews
109
+
110
+ const { current_page, total_pages } = myReviews.page_info
111
+
112
+ const formatter = new Intl.DateTimeFormat(locale, {
113
+ year: 'numeric',
114
+ month: 'long',
115
+ day: 'numeric',
116
+ hour: 'numeric',
117
+ minute: 'numeric',
118
+ })
119
+
120
+ if (!reviews) {
121
+ return null
122
+ }
123
+
124
+ const actions = (
125
+ <div className={classes.reviewsBottomContainer}>
126
+ <Link href={`/account/reviews/add?sku=${sku}`} passHref>
127
+ <Button
128
+ variant='pill'
129
+ color='primary'
130
+ text='bold'
131
+ size='large'
132
+ className={classes.writeReviewButton}
133
+ >
134
+ Write a review
135
+ </Button>
136
+ </Link>
137
+
138
+ {!!total_pages && total_pages > 1 && (
139
+ <Pagination
140
+ count={total_pages ?? 1}
141
+ page={current_page ?? 1}
142
+ classes={{ root: classes.paginationRoot }}
143
+ renderLink={(p: number, icon: React.ReactNode) => (
144
+ <Button onClick={() => setPage(p)} className={classes.paginationButton}>
145
+ {icon}
146
+ </Button>
147
+ )}
148
+ />
149
+ )}
150
+ </div>
151
+ )
152
+
153
+ if (reviews?.items.length === 0) {
154
+ return (
155
+ <div className={classes.container}>
156
+ <div className={classes.review}>
157
+ <div className={classes.title}>
158
+ <Typography variant='subtitle1'>Be the first to write a review!</Typography>
159
+ </div>
160
+ </div>
161
+ {actions}
162
+ </div>
163
+ )
164
+ }
165
+
166
+ return (
167
+ <div className={classes.container}>
168
+ {!loading &&
169
+ myReviews.items.map((review) => (
170
+ <div key={review?.summary} className={classes.review}>
171
+ <div className={classes.title}>
172
+ <ProductReviewChip rating={review?.average_rating} variant='default' />
173
+ <Typography variant='h5'> {review?.summary}</Typography>
174
+ </div>
175
+ <Typography variant='body1'>{review?.text}</Typography>
176
+
177
+ {(review?.ratings_breakdown ?? 0) > 1 && (
178
+ <div className={classes.ratingRow}>
179
+ {review?.ratings_breakdown.map((ratingBreakdown) => (
180
+ <div key={`rating-${ratingBreakdown?.value}`} className={classes.rating}>
181
+ <span>{ratingBreakdown?.name}</span>
182
+ <StarRatingField
183
+ iconSize={16}
184
+ readOnly
185
+ size='small'
186
+ defaultValue={Number(ratingBreakdown?.value ?? 0)}
187
+ />
188
+ </div>
189
+ ))}
190
+ </div>
191
+ )}
192
+
193
+ <div className={classes.meta}>
194
+ <div className={classes.nickname}>Written by {review?.nickname}</div>
195
+ <time className={classes.date} dateTime={review?.created_at}>
196
+ {review?.created_at &&
197
+ formatter.format(new Date(review?.created_at.replace(/-/g, '/')))}
198
+ </time>
199
+ </div>
200
+ </div>
201
+ ))}
202
+ {actions}
203
+ </div>
204
+ )
205
+ }
@@ -0,0 +1,16 @@
1
+ export { default as AccountReviews } from './AccountReviews'
2
+ export { default as CreateProductReviewForm } from './CreateProductReviewForm'
3
+ export { default as CustomerReview } from './CustomerReview'
4
+ export { default as ProductReviews } from './ProductReviews'
5
+ export { default as ProductReviewChip } from './ProductReviewChip'
6
+
7
+ export * from './AccountReviews/AccountReviews.gql'
8
+ export * from './ProductReviews'
9
+ export * from './CustomerReview/CustomerReview.gql'
10
+ export * from './ProductReviewChip/ProductReviewSummary.gql'
11
+ export * from './ProductReviews/ProductReviewProductName.gql'
12
+ export * from './CreateProductReviewForm/CreateProductReview.gql'
13
+ export * from './CreateProductReviewForm/ProductReviewRatingsMetadata.gql'
14
+
15
+ export * from './JsonLdProductReview/JsonLdProductReview.gql'
16
+ export * from './JsonLdProductReview'
package/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './components'
2
+ export * from './queries/AccountDashboardReviews.gql'
@@ -0,0 +1,4 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ export type AccountDashboardCustomerReviewsFragment = { reviews: { page_info: { total_pages?: Types.Maybe<number> }, items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, product: { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> }, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } };
@@ -0,0 +1,8 @@
1
+ fragment AccountDashboardCustomerReviews on Customer @inject(into: ["AccountDashboardCustomer"]) {
2
+ reviews {
3
+ page_info {
4
+ total_pages
5
+ }
6
+ ...AccountReviews
7
+ }
8
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@graphcommerce/magento-review",
3
+ "version": "2.105.1",
4
+ "sideEffects": false,
5
+ "prettier": "@graphcommerce/prettier-config-pwa",
6
+ "browserslist": [
7
+ "extends @graphcommerce/browserslist-config-pwa"
8
+ ],
9
+ "eslintConfig": {
10
+ "extends": "@graphcommerce/eslint-config-pwa",
11
+ "parserOptions": {
12
+ "project": "./tsconfig.json"
13
+ }
14
+ },
15
+ "devDependencies": {
16
+ "@graphcommerce/browserslist-config-pwa": "^3.0.1",
17
+ "@graphcommerce/eslint-config-pwa": "^3.0.1",
18
+ "@graphcommerce/prettier-config-pwa": "^3.0.1",
19
+ "@graphcommerce/typescript-config-pwa": "^3.0.1",
20
+ "@playwright/test": "^1.14.1"
21
+ },
22
+ "dependencies": {
23
+ "@apollo/client": "^3.3.21",
24
+ "@graphcommerce/graphql": "^2.103.1",
25
+ "@graphcommerce/image": "^2.104.1",
26
+ "@graphcommerce/magento-product": "^3.0.1",
27
+ "@graphcommerce/magento-store": "^3.0.1",
28
+ "@graphcommerce/next-ui": "^3.0.1",
29
+ "@graphql-typed-document-node/core": "^3.1.0",
30
+ "@material-ui/core": "^4.12.3",
31
+ "@material-ui/lab": "^4.0.0-alpha.60",
32
+ "clsx": "^1.1.1",
33
+ "next": "^11.1.2",
34
+ "react": "^17.0.2",
35
+ "react-dom": "^17.0.2",
36
+ "schema-dts": "^1.0.0"
37
+ }
38
+ }
@@ -0,0 +1,10 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const AccountDashboardReviewsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AccountDashboardReviews"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"reviews"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"average_rating"}},{"kind":"Field","name":{"kind":"Name","value":"created_at"}},{"kind":"Field","name":{"kind":"Name","value":"product"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"uid"}},{"kind":"Field","name":{"kind":"Name","value":"url_key"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"thumbnail"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"label"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"nickname"}},{"kind":"Field","name":{"kind":"Name","value":"summary"}},{"kind":"Field","name":{"kind":"Name","value":"text"}},{"kind":"Field","name":{"kind":"Name","value":"ratings_breakdown"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode<AccountDashboardReviewsQuery, AccountDashboardReviewsQueryVariables>;
7
+ export type AccountDashboardReviewsQueryVariables = Types.Exact<{ [key: string]: never; }>;
8
+
9
+
10
+ export type AccountDashboardReviewsQuery = { customer?: Types.Maybe<{ reviews: { items: Array<Types.Maybe<{ average_rating: number, created_at: string, nickname: string, summary: string, text: string, product: { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> } | { uid: string, url_key?: Types.Maybe<string>, name?: Types.Maybe<string>, thumbnail?: Types.Maybe<{ url?: Types.Maybe<string>, label?: Types.Maybe<string> }> }, ratings_breakdown: Array<Types.Maybe<{ name: string, value: string }>> }>> } }> };
@@ -0,0 +1,7 @@
1
+ query AccountDashboardReviews {
2
+ customer {
3
+ reviews {
4
+ ...AccountReviews
5
+ }
6
+ }
7
+ }