Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Venia v2 Cart Page #2084

Merged
merged 11 commits into from
Jan 8, 2020
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useEffect } from 'react';
import { createTestInstance } from '@magento/peregrine';

import { useCartPage } from '../useCartPage';

jest.mock('../../../context/app', () => {
const state = {};
const api = {
toggleDrawer: jest.fn()
};
const useAppContext = jest.fn(() => [state, api]);

return { useAppContext };
});
jest.mock('../../../context/user', () => {
const state = {
isSignedIn: false
};
const api = {};
const useUserContext = jest.fn(() => [state, api]);

return { useUserContext };
});

const log = jest.fn();
const Component = () => {
const talonProps = useCartPage();

useEffect(() => {
log(talonProps);
}, [talonProps]);

return null;
};

test('it returns the proper shape', () => {
// Act.
createTestInstance(<Component />);

// Assert.
expect(log).toHaveBeenCalledWith({
handleSignIn: expect.any(Function),
isSignedIn: expect.any(Boolean)
});
});
20 changes: 20 additions & 0 deletions packages/peregrine/lib/talons/CartPage/useCartPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useCallback } from 'react';

import { useAppContext } from '../../context/app';
import { useUserContext } from '../../context/user';

export const useCartPage = () => {
const [, appApi] = useAppContext();
const { toggleDrawer } = appApi;
const [{ isSignedIn }] = useUserContext();

const handleSignIn = useCallback(() => {
// TODO: set navigation state to "SIGN_IN". useNavigation:showSignIn doesn't work.
supernova-at marked this conversation as resolved.
Show resolved Hide resolved
toggleDrawer('nav');
}, [toggleDrawer]);

return {
handleSignIn,
isSignedIn
};
};
76 changes: 76 additions & 0 deletions packages/venia-ui/lib/components/CartPage/cartPage.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
.root {
padding: 1.5rem;
}

.body {
display: grid;
gap: 2rem;
grid-template-columns: 66% auto;
/* The summary grid item spans the entire right column. */
grid-template-areas:
'items summary'
'adjustments summary'
'recents summary';
}

.heading_container {
display: flex;
align-items: baseline;
justify-content: space-between;

margin-bottom: 1rem;
}

.heading {
line-height: 1.25em;
}

.items_container {
grid-area: items;
}

.price_adjustments_container {
grid-area: adjustments;
}

.recently_viewed_container {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is an extension/dynamic location can we just call this cart_extension_container and rename the grid area?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know for sure that's the case? I wasn't clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yea, it was discussed when we broke the stories down that its more like a configurable area for things like "recently viewed" or "people like you purchased..." etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH It may be better to simply remove/comment out the html since those components don't exist and I'm not sure we are expected to even implement it within this epic.

grid-area: recents;
}

.sign_in {
font-weight: bold;
text-decoration: underline;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This text looks a little larger than in the mocks, at least in relation to its counterpart in the header, "Cart".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's actually a good callout - I don't know how to open the mock in XD to get the correct size. I'll dig deeper.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to find a link somewhere in the epic or linked issues. But @tjwiebell is also having trouble finding pixel/size direction from XD so not sure how to help from there.

}

.summary_container {
grid-area: summary;
height: 100%;
}

.summary_contents {
position: sticky;
/*
* TODO: Use CSS Properties (variables) or something instead of hardcoding this.
* 3.5 rem = min-height of nav header. See the "toolbar" class in header.css.
*/
top: 3.5rem;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would have liked this to be a variable but the TODO will suffice

}

/*
* Mobile-specific styles.
*/

@media (max-width: 640px) {
.body {
/* Only one column in mobile view. */
grid-template-columns: 100%;
grid-template-areas:
'items'
'adjustments'
'summary';
}

.recently_viewed_container {
display: none;
}
}
61 changes: 61 additions & 0 deletions packages/venia-ui/lib/components/CartPage/cartPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useMemo } from 'react';

import { useCartPage } from '@magento/peregrine/lib/talons/CartPage/useCartPage';

import Button from '../Button';

import { mergeClasses } from '../../classify';
import defaultClasses from './cartPage.css';

const CartPage = props => {
const { handleSignIn, isSignedIn } = useCartPage();

const classes = mergeClasses(defaultClasses, props.classes);

const signInDisplay = useMemo(() => {
return !isSignedIn ? (
<Button
className={classes.sign_in}
onClick={handleSignIn}
priority="high"
>
{'Sign In'}
</Button>
) : null;
}, [classes.sign_in, handleSignIn, isSignedIn]);

return (
<div className={classes.root}>
<div className={classes.heading_container}>
<h1 className={classes.heading}>Cart</h1>
{signInDisplay}
</div>
<div className={classes.body}>
<div className={classes.items_container}>
<a href="https://jira.corp.magento.com/browse/PWA-238">
Items List to be completed by PWA-238.
</a>
</div>
<div className={classes.price_adjustments_container}>
<a href="https://jira.corp.magento.com/browse/PWA-241">
Price Adjustments to be completed by PWA-241.
</a>
</div>
<div className={classes.summary_container}>
<div className={classes.summary_contents}>
<a href="https://jira.corp.magento.com/browse/PWA-240">
Order Summary to be completed by PWA-240.
</a>
</div>
</div>
<div className={classes.recently_viewed_container}>
<a href="https://jira.corp.magento.com/browse/PWA-270">
Recently Viewed to be completed by PWA-270.
</a>
</div>
</div>
</div>
);
};

export default CartPage;
1 change: 1 addition & 0 deletions packages/venia-ui/lib/components/CartPage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './cartPage';
4 changes: 4 additions & 0 deletions packages/venia-ui/lib/components/Routes/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Route, Switch } from 'react-router-dom';
import { fullPageLoadingIndicator } from '../LoadingIndicator';
import MagentoRoute from '../MagentoRoute';

const CartPage = lazy(() => import('../CartPage'));
const CreateAccountPage = lazy(() => import('../CreateAccountPage'));
const Search = lazy(() => import('../../RootComponents/Search'));

Expand All @@ -17,6 +18,9 @@ const Routes = () => {
<Route exact path="/create-account">
<CreateAccountPage />
</Route>
<Route exact path="/cart">
<CartPage />
</Route>
<Route>
<MagentoRoute />
</Route>
Expand Down