Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
latest work (will roll back on resume)
Browse files Browse the repository at this point in the history
  • Loading branch information
nerrad committed May 23, 2023
1 parent dfd77df commit 3a67f0d
Show file tree
Hide file tree
Showing 17 changed files with 472 additions and 1 deletion.
21 changes: 21 additions & 0 deletions assets/js/atomic/blocks/product-elements/price/attributes-new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* External dependencies
*/
import { BlockAttributes } from '@wordpress/blocks';

export const blockAttributes: BlockAttributes = {
isDescendentOfSingleProductTemplate: {
type: 'boolean',
default: false,
},
isDescendentOfSingleProductBlock: {
type: 'boolean',
default: false,
},
productId: {
type: 'number',
default: 0,
},
};

export default blockAttributes;
146 changes: 146 additions & 0 deletions assets/js/atomic/blocks/product-elements/price/block-new-edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/**
* External dependencies
*/
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
import { useEffect } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import {
InnerBlockLayoutContextProvider,
useInnerBlockLayoutContext,
ProductDataContextProvider,
} from '@woocommerce/shared-context';
import { useStoreProducts } from '@woocommerce/base-context/hooks';

/**
* Internal dependencies
*/
import { originalPriceName } from './inner-blocks';
import { TEMPLATE } from './template';

interface Attributes {
isDescendentOfSingleProductBlock: boolean;
isDescendentOfSingleProductTemplate: boolean;
productId?: number;
}

interface Context {
postId?: number;
queryId?: number;
}

interface Props {
context: Context;
attributes: Attributes;
setAttributes: ( attributes: Partial< Attributes > ) => void;
}

interface ContextProviderProps extends Props {
children: JSX.Element | JSX.Element[] | undefined;
}

type ProductIdProps = Partial< ContextProviderProps > & { productId: number };

const ProviderFromAPI = ( {
productId,
children,
}: ProductIdProps ): JSX.Element => {
// TODO: this would be good to derive from the WP entity store at some point.
const { products, productsLoading } = useStoreProducts( {
include: productId,
} );
let product = null;
if ( products.length > 0 ) {
product =
products.find(
( productIteration ) => productIteration.id === productId
) || null;
}

return (
<ProductDataContextProvider
product={ product }
isLoading={ productsLoading }
>
{ children }
</ProductDataContextProvider>
);
};

const DerivedProductDataContextProvider = ( {
context,
attributes,
setAttributes,
children,
}: ContextProviderProps ): JSX.Element => {
const { queryId, postId } = context;
const { productId } = attributes;
const isDescendentOfQueryLoop = Number.isFinite( queryId );
const id = isDescendentOfQueryLoop ? postId : productId;
const isDescendentOfSingleProductTemplate = useSelect(
( select ) => {
const editSiteStore = select( 'core/edit-site' );
const editorPostId = editSiteStore?.getEditedPostId<
string | undefined
>();

return Boolean(
editorPostId?.includes( '//single-product' ) &&
! isDescendentOfQueryLoop
);
},
[ isDescendentOfQueryLoop ]
);

useEffect(
() =>
setAttributes( {
isDescendentOfSingleProductTemplate,
} ),
[ isDescendentOfSingleProductTemplate, setAttributes ]
);
if ( id && id > 0 ) {
return <ProviderFromAPI productId={ id }>{ children }</ProviderFromAPI>;
}
return (
<ProductDataContextProvider isLoading={ false }>
{ children }
</ProductDataContextProvider>
);
};

const EditBlock = ( {
context,
attributes,
setAttributes,
}: Props ): JSX.Element => {
const blockProps = useBlockProps();
const { parentClassName } = useInnerBlockLayoutContext();
return (
<DerivedProductDataContextProvider
context={ context }
attributes={ attributes }
setAttributes={ setAttributes }
>
<div { ...blockProps } className={ parentClassName }>
<InnerBlocks
allowedBlocks={ [ originalPriceName ] }
// todo add template for initial price layout
template={ TEMPLATE }
/>
</div>
</DerivedProductDataContextProvider>
);
};

const Edit = ( props: Props ): JSX.Element => {
return (
<InnerBlockLayoutContextProvider
parentName={ 'woocommerce/price-block' }
parentClassName={ 'wc-block-price-element' }
>
<EditBlock { ...props } />
</InnerBlockLayoutContextProvider>
);
};

export default Edit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* External dependencies
*/
import type { Currency } from '@woocommerce/types';
import type { CSSProperties } from 'react';

export interface ProductPriceProps {
/**
* CSS class for the wrapper
*/
wrapperClassName?: string | undefined;
/**
* Currency configuration object
*/
currency?: Currency;
/**
* The string version of the element to use for the price interpolation
*
* **Note:** It should contain `<price/>` (which is also the default value)
*/
format?: string;
/**
* The maximum price in a range
*/
maxPrice?: string | number;
/**
* The minimum price in a range
*/
minPrice?: string | number;
/**
* The current price
*/
price?: string | number;
/**
* CSS class for the price
*/
priceClassName?: string;
/**
* Custom style for the price
*/
priceStyle?: CSSProperties;
/**
* Custom style for the wrapper
*/
style?: CSSProperties;
}

export const ProductPrice = ( {
className,
currency,
format = '<price/>',
maxPrice,
minPrice,
price,
priceClassName,
priceStyle,
style,
} ) => {};
43 changes: 43 additions & 0 deletions assets/js/atomic/blocks/product-elements/price/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* External dependencies
*/
import { registerBlockType } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import sharedConfig from '../shared/config';
import edit from './block-new-edit';
import { save } from './save';
import attributes from './attributes-new';
import { supports } from './supports';
import {
BLOCK_TITLE as title,
BLOCK_ICON as icon,
BLOCK_DESCRIPTION as description,
} from './constants';

const { ancestor, ...configuration } = sharedConfig;

const blockConfig = {
...configuration,
apiVersion: 2,
title,
description,
usesContext: [ 'postId', 'queryId' ],
providesContext: {
'woocommerce/isDescendentOfSingleProductTemplate':
'isDescendentOfSingleProductTemplate',
'woocommerce/isDescendentOfSingleProductBlock':
'isDescendentOfSingleProductBlock',
},
icon: { src: icon },
attributes,
supports,
edit,
save,
};

console.log( 'IN HERE - REGISTERING' );

registerBlockType( 'woocommerce/product-price', blockConfig );
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Edit } from './edit';
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Internal dependencies
*/
import './original-price/index.ts';

export { BLOCK_NAME as originalPriceName } from './original-price/index';
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "woocommerce/original-price",
"version": "1.0.0",
"icon": "info",
"title": "Original Price",
"description": "Display the original price for the product",
"category": "woocommerce",
"keywords": [ "WooCommerce" ],
"textdomain": "woo-gutenberg-products-block",
"apiVersion": 2,
"$schema": "https://schemas.wp.org/trunk/block.json"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* External dependencies
*/
import type { HTMLAttributes } from 'react';
import classnames from 'classnames';
import { useStyleProps } from '@woocommerce/base-hooks';
import { useInnerBlockLayoutContext } from '@woocommerce/shared-context';
import ProductPrice from '@woocommerce/base-components/product-price';

/**
* Internal dependencies
*/
import type { PriceProps } from '../../types';
//import './style.scss';

type Props = PriceProps & HTMLAttributes< HTMLDivElement >;

const Block = ( {
attributes,
context,
rawPrice,
currency,
}: Props ): JSX.Element | null => {
const { className } = attributes;
const { isDescendentOfSingleProductTemplate = false } = context || {};
const { className: stylesClassName, style } = useStyleProps( attributes );
const { parentClassName } = useInnerBlockLayoutContext();
const wrapperClassName = classnames(
'wc-block-product-price__original',
className,
{
[ `${ parentClassName }__product-price` ]: parentClassName,
},
stylesClassName
);
if ( ! rawPrice && ! isDescendentOfSingleProductTemplate ) {
return <ProductPrice className={ wrapperClassName } />;
}

const pricePreview = '5000';
const priceClassName = classnames( {
[ `${ parentClassName }__product-original-price__value` ]:
parentClassName,
} );

return (
<ProductPrice
className={ wrapperClassName }
style={ style }
priceStyle={ style }
priceClassName={ priceClassName }
currency={ currency }
price={
isDescendentOfSingleProductTemplate ? pricePreview : rawPrice
}
/>
);
};

export default Block;
Loading

0 comments on commit 3a67f0d

Please sign in to comment.