@riosst100/pwa-marketplace 1.0.1 → 1.0.3

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 (37) hide show
  1. package/package.json +1 -1
  2. package/src/componentOverrideMapping.js +5 -1
  3. package/src/components/BecomeSeller/becomeSeller.js +184 -81
  4. package/src/components/BecomeSeller/becomeSeller.module.css +2 -3
  5. package/src/components/BecomeSellerLink/becomeSellerLink.js +45 -0
  6. package/src/components/BecomeSellerLink/becomeSellerLink.module.css +13 -0
  7. package/src/components/BecomeSellerPage/becomeSellerPage.js +9 -13
  8. package/src/components/BecomeSellerPage/becomeSellerPage.module.css +21 -0
  9. package/src/components/SellerAccountPage/index.js +1 -0
  10. package/src/components/SellerAccountPage/sellerAccountPage.js +138 -0
  11. package/src/components/SellerAccountPage/sellerAccountPage.module.css +55 -0
  12. package/src/components/SellerVerification/index.js +1 -0
  13. package/src/components/SellerVerification/sellerVerification.js +198 -0
  14. package/src/components/SellerVerification/sellerVerification.module.css +47 -0
  15. package/src/components/SellerVerificationPage/index.js +1 -0
  16. package/src/components/SellerVerificationPage/sellerVerificationPage.js +43 -0
  17. package/src/components/SellerVerificationPage/sellerVerificationPage.module.css +21 -0
  18. package/src/components/WebsiteSwitcher/websiteSwitcher.js +109 -0
  19. package/src/components/WebsiteSwitcher/websiteSwitcher.module.css +111 -0
  20. package/src/components/WebsiteSwitcher/websiteSwitcher.shimmer.js +6 -0
  21. package/src/components/WebsiteSwitcher/websiteSwitcherItem.js +47 -0
  22. package/src/components/WebsiteSwitcher/websiteSwitcherItem.module.css +20 -0
  23. package/src/intercept.js +40 -37
  24. package/src/overwrites/peregrine/lib/store/actions/user/asyncActions.js +96 -0
  25. package/src/overwrites/peregrine/lib/talons/AccountMenu/useAccountMenuItems.js +65 -0
  26. package/src/overwrites/peregrine/lib/talons/SignIn/signIn.gql.js +56 -0
  27. package/src/overwrites/peregrine/lib/talons/SignIn/useSignIn.js +226 -0
  28. package/src/overwrites/venia-ui/lib/components/Header/header.js +2 -2
  29. package/src/overwrites/venia-ui/lib/components/Header/storeSwitcher.js +2 -2
  30. package/src/talons/BecomeSeller/becomeSeller.gql.js +46 -0
  31. package/src/talons/BecomeSeller/useBecomeSeller.js +146 -0
  32. package/src/talons/BecomeSellerLink/useBecomeSellerLink.js +11 -0
  33. package/src/talons/BecomeSellerPage/useBecomeSellerPage.js +66 -0
  34. package/src/talons/SellerAccountPage/useSellerAccountPage.js +174 -0
  35. package/src/talons/WebsiteByIp/useWebsiteByIp.js +2 -0
  36. package/src/talons/WebsiteSwitcher/useWebsiteSwitcher.js +218 -0
  37. package/src/talons/WebsiteSwitcher/websiteSwitcher.gql.js +45 -0
@@ -0,0 +1,111 @@
1
+ .root {
2
+ composes: grid from global;
3
+ composes: items-center from global;
4
+ composes: justify-items-start from global;
5
+ composes: max-w-site from global;
6
+ composes: mx-auto from global;
7
+ composes: my-0 from global;
8
+ composes: px-xs from global;
9
+ composes: py-2xs from global;
10
+ composes: relative from global;
11
+
12
+ composes: sm_justify-items-end from global;
13
+ }
14
+
15
+ .trigger {
16
+ composes: max-w-[15rem] from global;
17
+ composes: overflow-ellipsis from global;
18
+ composes: overflow-hidden from global;
19
+ composes: whitespace-nowrap from global;
20
+
21
+ composes: sm_max-w-full from global;
22
+ }
23
+
24
+ .menu {
25
+ composes: absolute from global;
26
+ composes: bg-white from global;
27
+ composes: border from global;
28
+ composes: border-solid from global;
29
+ composes: border-subtle from global;
30
+ composes: bottom-md from global;
31
+ composes: left-xs from global;
32
+ composes: max-w-[90vw] from global;
33
+ composes: opacity-0 from global;
34
+ composes: pb-2xs from global;
35
+ composes: pt-2xs from global;
36
+ composes: right-auto from global;
37
+ composes: rounded from global;
38
+ composes: shadow-menu from global;
39
+ composes: top-auto from global;
40
+ composes: w-max from global;
41
+ composes: z-menu from global;
42
+ transform: translate3d(0, -8px, 0);
43
+ transition-duration: 192ms;
44
+ transition-timing-function: var(--venia-global-anim-out);
45
+ transition-property: opacity, transform, visibility;
46
+
47
+ /* TODO @TW: review (B6) */
48
+ /* composes: invisible from global; */
49
+ visibility: hidden;
50
+
51
+ composes: sm_bottom-auto from global;
52
+ composes: sm_left-auto from global;
53
+ composes: sm_right-xs from global;
54
+ composes: sm_top-md from global;
55
+ }
56
+
57
+ .menu_open {
58
+ composes: menu;
59
+
60
+ composes: opacity-100 from global;
61
+ transform: translate3d(0, 4px, 0);
62
+ transition-duration: 224ms;
63
+ transition-timing-function: var(--venia-global-anim-in);
64
+
65
+ /* TODO @TW: review (B6) */
66
+ /* composes: visible from global; */
67
+ visibility: visible;
68
+ }
69
+
70
+ .menuItem {
71
+ composes: hover_bg-subtle from global;
72
+ }
73
+
74
+ .groups {
75
+ composes: max-h-[24rem] from global;
76
+ composes: overflow-auto from global;
77
+ }
78
+
79
+ .groupList {
80
+ composes: border-b from global;
81
+ composes: border-solid from global;
82
+ composes: border-subtle from global;
83
+ composes: pb-2xs from global;
84
+ composes: pt-2xs from global;
85
+
86
+ composes: last_border-none from global;
87
+ }
88
+
89
+ /*
90
+ * Mobile-specific styles.
91
+ */
92
+
93
+ @media (max-width: 639px) {
94
+ .root:only-child {
95
+ grid-column: 2;
96
+ }
97
+
98
+ /* TODO @TW: cannot compose */
99
+ .root:last-child .menu {
100
+ right: 1rem;
101
+ left: auto;
102
+ }
103
+
104
+ .menu {
105
+ transform: translate3d(0, 8px, 0);
106
+ }
107
+
108
+ .menu_open {
109
+ transform: translate3d(0, -4px, 0);
110
+ }
111
+ }
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import Shimmer from '@magento/venia-ui/lib/components/Shimmer';
3
+
4
+ export default () => {
5
+ return <Shimmer width={6} height={2.25} />;
6
+ };
@@ -0,0 +1,47 @@
1
+ import React, { useCallback } from 'react';
2
+ import { Check } from 'react-feather';
3
+ import { bool, func, shape, string } from 'prop-types';
4
+
5
+ import { useStyle } from '@magento/venia-ui/lib/classify';
6
+ import Icon from '@magento/venia-ui/lib/components/Icon/icon';
7
+ import defaultClasses from './websiteSwitcherItem.module.css';
8
+
9
+ const WebsiteSwitcherItem = props => {
10
+ const { active, onClick, option, option2, children } = props;
11
+ const classes = useStyle(defaultClasses, props.classes);
12
+
13
+ const handleClick = useCallback(() => {
14
+ onClick(option, option2);
15
+ }, [option, option2, onClick]);
16
+
17
+ const activeIcon = active ? (
18
+ <Icon data-cy="WebsiteSwitcherItem-activeIcon" size={20} src={Check} />
19
+ ) : null;
20
+
21
+ return (
22
+ <button
23
+ data-cy="WebsiteSwitcherItem-button"
24
+ className={classes.root}
25
+ disabled={active}
26
+ onClick={handleClick}
27
+ >
28
+ <span className={classes.content}>
29
+ <span className={classes.text}>{children}</span>
30
+ {activeIcon}
31
+ </span>
32
+ </button>
33
+ );
34
+ };
35
+
36
+ WebsiteSwitcherItem.propTypes = {
37
+ active: bool,
38
+ classes: shape({
39
+ content: string,
40
+ root: string,
41
+ text: string
42
+ }),
43
+ onClick: func,
44
+ option: string
45
+ };
46
+
47
+ export default WebsiteSwitcherItem;
@@ -0,0 +1,20 @@
1
+ .root {
2
+ composes: flex from global;
3
+ composes: items-center from global;
4
+ composes: w-full from global;
5
+ }
6
+
7
+ .content {
8
+ composes: gap-3 from global;
9
+ composes: grid from global;
10
+ composes: grid-cols-[1fr] from global;
11
+ composes: grid-flow-col from global;
12
+ composes: items-center from global;
13
+ composes: px-xs from global;
14
+ composes: py-2xs from global;
15
+ composes: w-full from global;
16
+ }
17
+
18
+ .text {
19
+ composes: text-left from global;
20
+ }
package/src/intercept.js CHANGED
@@ -3,30 +3,24 @@ const moduleOverridePlugin = require('./moduleOverrideWebpackPlugin');
3
3
  const { DefinePlugin } = require('webpack');
4
4
  const { getAvailableWebsitesConfigData } = require('./Utilities/graphQL');
5
5
 
6
- /**
7
- * Custom intercept file for the extension
8
- * By default you can only use target of @magento/pwa-buildpack.
9
- *
10
- * If do want extend @magento/peregrine or @magento/venia-ui
11
- * you should add them to peerDependencies to your package.json
12
- *
13
- * If you want to add overwrites for @magento/venia-ui components you can use
14
- * moduleOverrideWebpackPlugin and componentOverrideMapping
15
- */
16
- module.exports = async targets => {
6
+ module.exports = targets => {
7
+ // Perform the asynchronous operation outside the tap
8
+ let availableWebsites;
9
+
10
+ // Use an IIFE (Immediately Invoked Function Expression) to enable async/await
11
+ (async () => {
12
+ availableWebsites = await getAvailableWebsitesConfigData();
13
+ })();
14
+
17
15
  targets.of('@magento/pwa-buildpack').specialFeatures.tap(flags => {
18
- /**
19
- * Wee need to activated esModules and cssModules to allow build pack to load our extension
20
- * {@link https://magento.github.io/pwa-studio/pwa-buildpack/reference/configure-webpack/#special-flags}.
21
- */
22
- flags[targets.name] = { esModules: true, cssModules: true, graphqlQueries: true };
16
+ flags[targets.name] = { esModules: true, cssModules: true, graphqlQueries: true };
23
17
  });
24
18
 
25
19
  targets.of('@magento/pwa-buildpack').webpackCompiler.tap(compiler => {
26
- new moduleOverridePlugin(componentOverrideMapping).apply(compiler);
20
+ new moduleOverridePlugin(componentOverrideMapping).apply(compiler);
27
21
  });
28
22
 
29
- targets.of('@magento/pwa-buildpack').envVarDefinitions.tap((defs) => {
23
+ targets.of('@magento/pwa-buildpack').envVarDefinitions.tap(defs => {
30
24
  defs.sections.push({
31
25
  name: "Default Website Code",
32
26
  variables: [
@@ -39,32 +33,41 @@ module.exports = async targets => {
39
33
  });
40
34
  });
41
35
 
42
- const availableWebsites = await getAvailableWebsitesConfigData();
36
+ // Define the routes using the results of the asynchronous operation
37
+ const routes = [
38
+ {
39
+ exact: true,
40
+ name: "BecomeSellerRoute",
41
+ pattern: "/become-seller",
42
+ path: require.resolve("./components/BecomeSellerPage/index.js"),
43
+ authed: true,
44
+ redirectTo: "/sign-in"
45
+ },
46
+ {
47
+ exact: true,
48
+ name: "SellerAccountRoute",
49
+ pattern: "/seller-account",
50
+ path: require.resolve("./components/SellerAccountPage/index.js"),
51
+ authed: true,
52
+ redirectTo: "/become-seller"
53
+ },
54
+ ];
43
55
 
56
+ // Apply DefinePlugin using the results of the asynchronous operation
44
57
  targets.of('@magento/pwa-buildpack').webpackCompiler.tap(compiler => {
45
58
  new DefinePlugin({
46
59
  AVAILABLE_WEBSITES: JSON.stringify(availableWebsites.availableStoresByUserIp),
47
60
  WEBSITE_CODE: process.env.WEBSITE_CODE
48
61
  }).apply(compiler);
49
62
  });
50
-
51
- // targets.of("@magento/venia-ui").routes.tap(routes => {
52
- // routes.push({
53
- // name: "Become Seller",
54
- // pattern: "/become-seller",
55
- // path: require.resolve("../components/BecomeSeller/index.js")
56
- // });
57
- // return routes;
58
- // });
59
- };
60
63
 
61
- module.exports = (targets) => {
62
- targets.of("@magento/venia-ui").routes.tap((routes) => {
63
- routes.push({
64
- name: "BecomeSellerRoute",
65
- pattern: "/become-seller",
66
- path: require.resolve("./components/BecomeSellerPage/index.js"),
67
- });
68
- return routes;
64
+ targets.of('@magento/pwa-buildpack').specialFeatures.tap(flags => {
65
+ flags[targets.name] = { esModules: true, cssModules: true, graphqlQueries: true };
66
+ });
67
+
68
+ // Handle the routes directly within the routes tap
69
+ targets.of("@magento/venia-ui").routes.tap(routesArray => {
70
+ routesArray.push(...routes);
71
+ return routesArray;
69
72
  });
70
73
  };
@@ -0,0 +1,96 @@
1
+ import BrowserPersistence from '@magento/peregrine/lib/util/simplePersistence';
2
+ import { removeCart } from '@magento/peregrine/lib/store/actions/cart';
3
+ import { clearCheckoutDataFromStorage } from '@magento/peregrine/lib/store/actions/checkout';
4
+
5
+ import actions from '@magento/peregrine/lib/store/actions/user/actions';
6
+
7
+ const storage = new BrowserPersistence();
8
+
9
+ export const signOut = (payload = {}) =>
10
+ async function thunk(dispatch, getState, { apolloClient }) {
11
+ const { revokeToken } = payload;
12
+
13
+ if (revokeToken) {
14
+ // Send mutation to revoke token.
15
+ try {
16
+ await revokeToken();
17
+ } catch (error) {
18
+ console.error('Error Revoking Token', error);
19
+ }
20
+ }
21
+
22
+ // Remove token from local storage and Redux.
23
+ await dispatch(clearToken());
24
+ await dispatch(actions.reset());
25
+ await clearCheckoutDataFromStorage();
26
+ await apolloClient.clearCacheData(apolloClient, 'cart');
27
+ await apolloClient.clearCacheData(apolloClient, 'customer');
28
+
29
+ // Now that we're signed out, forget the old (customer) cart.
30
+ // We don't need to create a new cart here because we're going to refresh
31
+ // the page immediately after.
32
+ await dispatch(removeCart());
33
+ };
34
+
35
+ export const getUserDetails = ({ fetchUserDetails }) =>
36
+ async function thunk(...args) {
37
+ const [dispatch, getState] = args;
38
+ const { user } = getState();
39
+
40
+ if (user.isSignedIn) {
41
+ dispatch(actions.getDetails.request());
42
+
43
+ try {
44
+ const { data } = await fetchUserDetails();
45
+
46
+ if (data.customer) {
47
+ const isSeller = data.customer.is_seller;
48
+ if (isSeller) {
49
+ storage.setItem('is_seller', true);
50
+ }
51
+ }
52
+
53
+ dispatch(actions.getDetails.receive(data.customer));
54
+ } catch (error) {
55
+ dispatch(actions.getDetails.receive(error));
56
+ }
57
+ }
58
+ };
59
+
60
+ export const resetPassword = ({ email }) =>
61
+ async function thunk(...args) {
62
+ const [dispatch] = args;
63
+
64
+ dispatch(actions.resetPassword.request());
65
+
66
+ // TODO: actually make the call to the API.
67
+ // For now, just return a resolved promise.
68
+ await Promise.resolve(email);
69
+
70
+ dispatch(actions.resetPassword.receive());
71
+ };
72
+
73
+ export const setToken = token =>
74
+ async function thunk(...args) {
75
+ const [dispatch] = args;
76
+
77
+ // Store token in local storage.
78
+ // TODO: Get correct token expire time from API
79
+ storage.setItem('signin_token', token, 3600);
80
+
81
+ // Persist in store
82
+ dispatch(actions.setToken(token));
83
+ };
84
+
85
+ export const clearToken = () =>
86
+ async function thunk(...args) {
87
+ const [dispatch] = args;
88
+
89
+ // Clear token from local storage
90
+ storage.removeItem('signin_token');
91
+
92
+ storage.removeItem('is_seller');
93
+
94
+ // Remove from store
95
+ dispatch(actions.clearToken());
96
+ };
@@ -0,0 +1,65 @@
1
+ import { useCallback } from 'react';
2
+
3
+ /**
4
+ * @param {Object} props
5
+ * @param {Function} props.onSignOut - A function to call when sign out occurs.
6
+ *
7
+ * @returns {Object} result
8
+ * @returns {Function} result.handleSignOut - The function to handle sign out actions.
9
+ */
10
+ export const useAccountMenuItems = props => {
11
+ const { onSignOut } = props;
12
+
13
+ const handleSignOut = useCallback(() => {
14
+ onSignOut();
15
+ }, [onSignOut]);
16
+
17
+ const MENU_ITEMS = [
18
+ {
19
+ name: 'Seller Account Information',
20
+ id: 'accountMenu.sellerAccountInfoLink',
21
+ url: '/seller-account'
22
+ },
23
+ {
24
+ name: 'Order History',
25
+ id: 'accountMenu.orderHistoryLink',
26
+ url: '/order-history'
27
+ },
28
+ // Hide links until features are completed
29
+ // {
30
+ // name: 'Store Credit & Gift Cards',
31
+ // id: 'accountMenu.storeCreditLink',
32
+ // url: ''
33
+ // },
34
+ {
35
+ name: 'Favorites Lists',
36
+ id: 'accountMenu.favoritesListsLink',
37
+ url: '/wishlist'
38
+ },
39
+ {
40
+ name: 'Address Book',
41
+ id: 'accountMenu.addressBookLink',
42
+ url: '/address-book'
43
+ },
44
+ {
45
+ name: 'Saved Payments',
46
+ id: 'accountMenu.savedPaymentsLink',
47
+ url: '/saved-payments'
48
+ },
49
+ {
50
+ name: 'Communications',
51
+ id: 'accountMenu.communicationsLinak',
52
+ url: '/communications'
53
+ },
54
+ {
55
+ name: 'Account Information',
56
+ id: 'accountMenu.accountInfoLink',
57
+ url: '/account-information'
58
+ }
59
+ ];
60
+
61
+ return {
62
+ handleSignOut,
63
+ menuItems: MENU_ITEMS
64
+ };
65
+ };
@@ -0,0 +1,56 @@
1
+ import { gql } from '@apollo/client';
2
+ import { CheckoutPageFragment } from '@magento/peregrine/lib/talons/CheckoutPage/checkoutPageFragments.gql';
3
+
4
+ export const GET_CUSTOMER = gql`
5
+ query GetCustomerAfterSignIn {
6
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
7
+ customer {
8
+ email
9
+ firstname
10
+ lastname
11
+ is_subscribed
12
+ is_seller
13
+ }
14
+ }
15
+ `;
16
+
17
+ export const SIGN_IN = gql`
18
+ mutation SignIn($email: String!, $password: String!) {
19
+ generateCustomerToken(email: $email, password: $password) {
20
+ token
21
+ }
22
+ }
23
+ `;
24
+
25
+ export const CREATE_CART = gql`
26
+ mutation CreateCartAfterSignIn {
27
+ cartId: createEmptyCart
28
+ }
29
+ `;
30
+
31
+ export const MERGE_CARTS = gql`
32
+ mutation MergeCartsAfterSignIn(
33
+ $sourceCartId: String!
34
+ $destinationCartId: String!
35
+ ) {
36
+ mergeCarts(
37
+ source_cart_id: $sourceCartId
38
+ destination_cart_id: $destinationCartId
39
+ ) {
40
+ id
41
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
42
+ items {
43
+ uid
44
+ }
45
+ ...CheckoutPageFragment
46
+ }
47
+ }
48
+ ${CheckoutPageFragment}
49
+ `;
50
+
51
+ export default {
52
+ createCartMutation: CREATE_CART,
53
+ getCustomerQuery: GET_CUSTOMER,
54
+ mergeCartsMutation: MERGE_CARTS,
55
+ signInMutation: SIGN_IN
56
+ };