Add card view

This commit is contained in:
Chi-Hsuan Huang 2022-04-27 16:09:41 +08:00
parent 6248683042
commit 48c89b2266
9 changed files with 236 additions and 62 deletions

View File

@ -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 {

View File

@ -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 = () => {

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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>
);

View File

@ -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 );
} );
} );

View File

@ -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 );
} );
} );