Add card view
This commit is contained in:
parent
6248683042
commit
48c89b2266
|
@ -3,13 +3,20 @@
|
|||
color: #007cba;
|
||||
}
|
||||
|
||||
.woocommerce-list {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto;
|
||||
grid-column-gap: 16px;
|
||||
grid-row-gap: 24px;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.woocommerce-list__item {
|
||||
float: left;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #dcdcde;
|
||||
width: 263px;
|
||||
height: 226px;
|
||||
margin: 12px;
|
||||
text-align: center;
|
||||
align-items: start;
|
||||
|
||||
|
@ -27,10 +34,12 @@
|
|||
&:not(.transitions-disabled) {
|
||||
&.woocommerce-list__item-enter {
|
||||
transform: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
&.woocommerce-list__item-enter-active {
|
||||
transform: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
&.woocommerce-list__item-exit-active {
|
||||
|
@ -51,6 +60,7 @@
|
|||
}
|
||||
|
||||
.woocommerce-list__item-before {
|
||||
margin-right: 0;
|
||||
background: #f0f6fc;
|
||||
padding: 8px;
|
||||
border-radius: 50%;
|
||||
|
@ -60,6 +70,7 @@
|
|||
color: $gray-900;
|
||||
line-height: 16px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.woocommerce-list__item-content {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { registerPlugin } from '@wordpress/plugins';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import CardList from './CardList';
|
||||
import CardList from './cardList';
|
||||
import { importTypes } from './importTypes';
|
||||
|
||||
const Products = () => {
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
.woocommerce-products-card-layout {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.woocommerce-products-card-layout__description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.woocommerce-products-card-list {
|
||||
margin-top: 32px;
|
||||
|
||||
.woocommerce-list {
|
||||
grid-template-columns: 215px 215px 215px;
|
||||
}
|
||||
|
||||
.woocommerce-list__item {
|
||||
width: 215px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.woocommerce-list__item-after {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Text } from '@woocommerce/experimental';
|
||||
import { Link } from '@woocommerce/components';
|
||||
import interpolateComponents from '@automattic/interpolate-components';
|
||||
import { getAdminLink } from '@woocommerce/settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { ProductType } from './constants';
|
||||
import CardList from '../experimental-import-products/cardList';
|
||||
import './card-layout.scss';
|
||||
|
||||
type CardProps = {
|
||||
items: ( ProductType & {
|
||||
onClick: () => void;
|
||||
} )[];
|
||||
};
|
||||
|
||||
const CardLayout: React.FC< CardProps > = ( { items } ) => {
|
||||
return (
|
||||
<div className="woocommerce-products-card-layout">
|
||||
<Text className="woocommerce-products-card-layout__description">
|
||||
{ interpolateComponents( {
|
||||
mixedString: __(
|
||||
'{{sbLink}}Start blank{{/sbLink}} or select a product type:'
|
||||
),
|
||||
components: {
|
||||
sbLink: (
|
||||
<Link
|
||||
onClick={ () => {
|
||||
window.location = getAdminLink(
|
||||
'post-new.php?post_type=product&wc_onboarding_active_task=products&tutorial=true'
|
||||
);
|
||||
return false;
|
||||
} }
|
||||
href=""
|
||||
type="wc-admin"
|
||||
>
|
||||
<></>
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
} ) }
|
||||
</Text>
|
||||
<CardList items={ items } />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CardLayout;
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import interpolateComponents from '@automattic/interpolate-components';
|
||||
import { Text } from '@woocommerce/experimental';
|
||||
import { ExternalLink } from '@wordpress/components';
|
||||
import { Link } from '@woocommerce/components';
|
||||
import { getAdminLink } from '@woocommerce/settings';
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
return (
|
||||
<div className="woocommerce-products-footer">
|
||||
<Text className="woocommerce-products-footer__selling-somewhere-else">
|
||||
Are you already selling somewhere else?
|
||||
</Text>
|
||||
<Text className="woocommerce-products-footer__import-options">
|
||||
{ interpolateComponents( {
|
||||
mixedString: __(
|
||||
'{{importCSVLink}}Import your products from a CSV file{{/importCSVLink}} or {{_3rdLink}}use a 3rd party migration plugin{{/_3rdLink}}.'
|
||||
),
|
||||
components: {
|
||||
importCSVLink: (
|
||||
<Link
|
||||
onClick={ () => {
|
||||
window.location = getAdminLink(
|
||||
'edit.php?post_type=product&page=product_importer&wc_onboarding_active_task=products'
|
||||
);
|
||||
return false;
|
||||
} }
|
||||
href=""
|
||||
type="wc-admin"
|
||||
>
|
||||
<></>
|
||||
</Link>
|
||||
),
|
||||
_3rdLink: (
|
||||
<ExternalLink
|
||||
href="https://woocommerce.com/products/cart2cart/?utm_medium=product"
|
||||
type="external"
|
||||
>
|
||||
<></>
|
||||
</ExternalLink>
|
||||
),
|
||||
},
|
||||
} ) }
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
|
@ -1,8 +1,7 @@
|
|||
.woocommerce-task-products {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 550px;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
@ -11,7 +10,6 @@
|
|||
|
||||
.woocommerce-task-products__title {
|
||||
font-size: 24px;
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
@ -46,5 +44,10 @@
|
|||
line-height: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.woocommerce-products-stack {
|
||||
max-width: 550px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,23 +2,26 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import interpolateComponents from '@automattic/interpolate-components';
|
||||
import { WooOnboardingTask } from '@woocommerce/onboarding';
|
||||
import { Text } from '@woocommerce/experimental';
|
||||
import { registerPlugin } from '@wordpress/plugins';
|
||||
import { useMemo, useState } from '@wordpress/element';
|
||||
import { Button, ExternalLink } from '@wordpress/components';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { Icon, chevronDown, chevronUp } from '@wordpress/icons';
|
||||
import { Link } from '@woocommerce/components';
|
||||
import { getAdminLink } from '@woocommerce/settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './index.scss';
|
||||
import { getAdminSetting } from '~/utils/admin-settings';
|
||||
import Stack from './stack';
|
||||
import { getSurfacedProductKeys } from './utils';
|
||||
import useProductTypeListItems from './use-product-types-list-items';
|
||||
import Stack from './stack';
|
||||
import Footer from './footer';
|
||||
import CardLayout from './card-layout';
|
||||
|
||||
// TODO: Use experiment data from the API, not hardcoded.
|
||||
const SHOW_STACK_LAYOUT = false;
|
||||
|
||||
const getOnboardingProductType = (): string[] => {
|
||||
const onboardingData = getAdminSetting( 'onboarding' );
|
||||
|
@ -28,8 +31,23 @@ const getOnboardingProductType = (): string[] => {
|
|||
);
|
||||
};
|
||||
|
||||
const ViewControlButton: React.FC< {
|
||||
isExpanded: boolean;
|
||||
onClick: () => void;
|
||||
} > = ( { isExpanded, onClick } ) => (
|
||||
<Button
|
||||
className="woocommerce-task-products__button-view-less-product-types"
|
||||
onClick={ onClick }
|
||||
>
|
||||
{ isExpanded
|
||||
? __( `View less product types`, 'woocommerce' )
|
||||
: __( `View more product types`, 'woocommerce' ) }
|
||||
<Icon icon={ isExpanded ? chevronUp : chevronDown } />
|
||||
</Button>
|
||||
);
|
||||
|
||||
export const Products = () => {
|
||||
const [ isCollapsed, setIsCollapsed ] = useState< boolean >( true );
|
||||
const [ isExpanded, setIsExpanded ] = useState< boolean >( false );
|
||||
const productTypes = useProductTypeListItems();
|
||||
|
||||
const surfacedProductKeys = getSurfacedProductKeys(
|
||||
|
@ -47,7 +65,7 @@ export const Products = () => {
|
|||
const surfacedProductTypes = productTypes.filter( ( productType ) =>
|
||||
surfacedProductKeys.includes( productType.key )
|
||||
);
|
||||
if ( ! isCollapsed ) {
|
||||
if ( isExpanded ) {
|
||||
// To show product types in same order, we need to push the other product types to the end.
|
||||
productTypes.forEach(
|
||||
( productType ) =>
|
||||
|
@ -58,7 +76,7 @@ export const Products = () => {
|
|||
return surfacedProductTypes;
|
||||
}, [
|
||||
surfacedProductKeys,
|
||||
isCollapsed,
|
||||
isExpanded,
|
||||
isAllProductSurfaced,
|
||||
productTypes,
|
||||
] );
|
||||
|
@ -73,55 +91,19 @@ export const Products = () => {
|
|||
{ __( 'What product do you want to add?', 'woocommerce' ) }
|
||||
</Text>
|
||||
|
||||
<Stack items={ visibleProductTypes } />
|
||||
|
||||
{ ! isAllProductSurfaced && (
|
||||
<Button
|
||||
className="woocommerce-task-products__button-view-less-product-types"
|
||||
onClick={ () => setIsCollapsed( ! isCollapsed ) }
|
||||
>
|
||||
{ isCollapsed
|
||||
? __( `View more product types`, 'woocommerce' )
|
||||
: __( `View less product types`, 'woocommerce' ) }
|
||||
<Icon icon={ isCollapsed ? chevronDown : chevronUp } />
|
||||
</Button>
|
||||
) }
|
||||
|
||||
<div className="woocommerce-products-footer">
|
||||
<Text className="woocommerce-products-footer__selling-somewhere-else">
|
||||
Are you already selling somewhere else?
|
||||
</Text>
|
||||
<Text className="woocommerce-products-footer__import-options">
|
||||
{ interpolateComponents( {
|
||||
mixedString: __(
|
||||
'{{importCSVLink}}Import your products from a CSV file{{/importCSVLink}} or {{_3rdLink}}use a 3rd party migration plugin{{/_3rdLink}}.'
|
||||
),
|
||||
components: {
|
||||
importCSVLink: (
|
||||
<Link
|
||||
onClick={ () => {
|
||||
window.location = getAdminLink(
|
||||
'edit.php?post_type=product&page=product_importer&wc_onboarding_active_task=products'
|
||||
);
|
||||
return false;
|
||||
} }
|
||||
href=""
|
||||
type="wc-admin"
|
||||
>
|
||||
<></>
|
||||
</Link>
|
||||
),
|
||||
_3rdLink: (
|
||||
<ExternalLink
|
||||
href="https://woocommerce.com/products/cart2cart/?utm_medium=product"
|
||||
type="external"
|
||||
>
|
||||
<></>
|
||||
</ExternalLink>
|
||||
),
|
||||
},
|
||||
} ) }
|
||||
</Text>
|
||||
<div className="woocommerce-product-content">
|
||||
{ SHOW_STACK_LAYOUT ? (
|
||||
<Stack items={ visibleProductTypes } />
|
||||
) : (
|
||||
<CardLayout items={ visibleProductTypes } />
|
||||
) }
|
||||
{ ! isAllProductSurfaced && (
|
||||
<ViewControlButton
|
||||
isExpanded={ isExpanded }
|
||||
onClick={ () => setIsExpanded( ! isExpanded ) }
|
||||
/>
|
||||
) }
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import CardLayout from '../card-layout';
|
||||
import { productTypes } from '../constants';
|
||||
|
||||
describe( 'CardLayout', () => {
|
||||
it( 'should render all products types in CardLayout', () => {
|
||||
const { queryByText, queryAllByRole } = render(
|
||||
<CardLayout
|
||||
items={ [
|
||||
{
|
||||
...productTypes[ 0 ],
|
||||
onClick: () => {},
|
||||
},
|
||||
] }
|
||||
/>
|
||||
);
|
||||
|
||||
expect( queryByText( productTypes[ 0 ].title ) ).toBeInTheDocument();
|
||||
|
||||
expect( queryAllByRole( 'link' ) ).toHaveLength( 1 );
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Footer from '../footer';
|
||||
|
||||
describe( 'Footer', () => {
|
||||
it( 'should render footer with two links', () => {
|
||||
const { queryAllByRole } = render( <Footer /> );
|
||||
expect( queryAllByRole( 'link' ) ).toHaveLength( 2 );
|
||||
} );
|
||||
} );
|
Loading…
Reference in New Issue