Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 0 additions & 57 deletions js/src/components/app-button-modal-trigger.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import GridiconPlusSmall from 'gridicons/dist/plus-small';
*/
import Section from '~/components/section';
import AppButton from '~/components/app-button';
import AppButtonModalTrigger from '~/components/app-button-modal-trigger';
import VerticalGapLayout from '~/components/vertical-gap-layout';
import useToggle from '~/hooks/useToggle';
import { useAdaptiveFormInputProps } from '~/components/adaptive-form';
import OfferFreeShippingCheckbox from '~/components/order-value-condition-section/offer-free-shipping-checkbox';
import isNonFreeShippingRate from '~/utils/isNonFreeShippingRate';
Expand All @@ -36,6 +36,7 @@ const MinimumOrderCard = ( { value = [], helper, onChange } ) => {
const offerFreeShippingCardInputProps = useAdaptiveFormInputProps(
'offer_free_shipping'
);
const [ isAddModalOpen, toggleAddModal ] = useToggle();

const renderGroups = () => {
const nonZeroShippingRates = value.filter( isNonFreeShippingRate );
Expand Down Expand Up @@ -105,28 +106,24 @@ const MinimumOrderCard = ( { value = [], helper, onChange } ) => {
} ) }
{ emptyThresholdGroup && (
<div>
<AppButtonModalTrigger
button={
<AppButton
isSecondary
icon={ <GridiconPlusSmall /> }
>
{ __(
'Add another condition',
'google-listings-and-ads'
) }
</AppButton>
}
modal={
<AddMinimumOrderFormModal
countryOptions={
emptyThresholdGroup.countries
}
initialValues={ emptyThresholdGroup }
onSubmit={ addHandler }
/>
}
/>
<AppButton
isSecondary
icon={ <GridiconPlusSmall /> }
onClick={ toggleAddModal }
>
{ __(
'Add another condition',
'google-listings-and-ads'
) }
</AppButton>
{ isAddModalOpen && (
<AddMinimumOrderFormModal
countryOptions={ emptyThresholdGroup.countries }
initialValues={ emptyThresholdGroup }
onSubmit={ addHandler }
onRequestClose={ toggleAddModal }
/>
) }
</div>
) }
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { __ } from '@wordpress/i18n';
* Internal dependencies
*/
import AppButton from '~/components/app-button';
import AppButtonModalTrigger from '~/components/app-button-modal-trigger';
import AppInputPriceControl from '~/components/app-input-price-control';
import useToggle from '~/hooks/useToggle';
import { useAdaptiveFormContext } from '~/components/adaptive-form';
import { EditMinimumOrderFormModal } from './minimum-order-form-modals';
import MinimumOrderInputControlLabelText from './minimum-order-input-control-label-text';
Expand All @@ -35,6 +35,7 @@ const MinimumOrderInputControl = ( props ) => {
const { countryOptions, value, onChange, onDelete } = props;
const { countries, threshold, currency } = value;
const { values } = useAdaptiveFormContext();
const [ isEditModalOpen, toggleEditModal ] = useToggle();

const handleBlur = ( event, numberValue ) => {
if ( numberValue === value.threshold ) {
Expand All @@ -55,36 +56,35 @@ const MinimumOrderInputControl = ( props ) => {
}

return (
<AppInputPriceControl
className="gla-minimum-order-input-control"
label={
<div className="gla-minimum-order-input-control__label">
<div className="gla-minimum-order-input-control__label_country">
<MinimumOrderInputControlLabelText
countries={ countries }
/>
<AppButtonModalTrigger
button={
<AppButton isTertiary>
{ __( 'Edit', 'google-listings-and-ads' ) }
</AppButton>
}
modal={
<EditMinimumOrderFormModal
countryOptions={ countryOptions }
initialValues={ value }
onSubmit={ onChange }
onDelete={ onDelete }
/>
}
/>
<>
<AppInputPriceControl
className="gla-minimum-order-input-control"
label={
<div className="gla-minimum-order-input-control__label">
<div className="gla-minimum-order-input-control__label_country">
<MinimumOrderInputControlLabelText
countries={ countries }
/>
<AppButton isTertiary onClick={ toggleEditModal }>
{ __( 'Edit', 'google-listings-and-ads' ) }
</AppButton>
</div>
<>{ `Cost (${ currency })` }</>
</div>
<>{ `Cost (${ currency })` }</>
</div>
}
value={ threshold }
onBlur={ handleBlur }
/>
}
value={ threshold }
onBlur={ handleBlur }
/>
{ isEditModalOpen && (
<EditMinimumOrderFormModal
countryOptions={ countryOptions }
initialValues={ value }
onSubmit={ onChange }
onDelete={ onDelete }
onRequestClose={ toggleEditModal }
/>
) }
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import GridiconPlusSmall from 'gridicons/dist/plus-small';
*/
import Section from '~/components/section';
import AppButton from '~/components/app-button';
import AppButtonModalTrigger from '~/components/app-button-modal-trigger';
import VerticalGapLayout from '~/components/vertical-gap-layout';
import useStoreCurrency from '~/hooks/useStoreCurrency';
import useToggle from '~/hooks/useToggle';
import groupShippingRatesByCurrencyRate from './groupShippingRatesByCurrencyRate';
import ShippingRateInputControl from './shipping-rate-input-control';
import { AddRateFormModal } from './rate-form-modals';
Expand Down Expand Up @@ -42,6 +42,7 @@ export default function EstimatedShippingRatesCard( {
const { handleAddSubmit, getChangeHandler, getDeleteHandler } = getHandlers(
{ value, onChange }
);
const [ isAddModalOpen, toggleAddModal ] = useToggle();

/**
* Function to render the shipping rate groups from `value`.
Expand Down Expand Up @@ -99,30 +100,28 @@ export default function EstimatedShippingRatesCard( {
} ) }
{ remainingCountries.length >= 1 && (
<div>
<AppButtonModalTrigger
button={
<AppButton
isSecondary
icon={ <GridiconPlusSmall /> }
>
{ __(
'Add another rate',
'google-listings-and-ads'
) }
</AppButton>
}
modal={
<AddRateFormModal
countryOptions={ remainingCountries }
initialValues={ {
countries: remainingCountries,
currency: currencyCode,
rate: 0,
} }
onSubmit={ handleAddSubmit }
/>
}
/>
<AppButton
isSecondary
icon={ <GridiconPlusSmall /> }
onClick={ toggleAddModal }
>
{ __(
'Add another rate',
'google-listings-and-ads'
) }
</AppButton>
{ isAddModalOpen && (
<AddRateFormModal
countryOptions={ remainingCountries }
initialValues={ {
countries: remainingCountries,
currency: currencyCode,
rate: 0,
} }
onSubmit={ handleAddSubmit }
onRequestClose={ toggleAddModal }
/>
) }
</div>
) }
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { Pill } from '@woocommerce/components';
* Internal dependencies
*/
import AppInputPriceControl from '~/components/app-input-price-control';
import AppButtonModalTrigger from '~/components/app-button-modal-trigger';
import AppButton from '~/components/app-button';
import useToggle from '~/hooks/useToggle';
import { EditRateFormModal } from './rate-form-modals';
import ShippingRateInputControlLabelText from './shipping-rate-input-control-label-text';
import './shipping-rate-input-control.scss';
Expand Down Expand Up @@ -38,6 +38,7 @@ const ShippingRateInputControl = ( {
onDelete,
} ) => {
const { countries, currency, rate } = value;
const [ isEditModalOpen, toggleEditModal ] = useToggle();

const handleBlur = ( event, numberValue ) => {
if ( rate === numberValue ) {
Expand All @@ -58,27 +59,24 @@ const ShippingRateInputControl = ( {
<ShippingRateInputControlLabelText
countries={ countries }
/>
<AppButtonModalTrigger
button={
<AppButton isTertiary>
{ __( 'Edit', 'google-listings-and-ads' ) }
</AppButton>
}
modal={
<EditRateFormModal
countryOptions={ countryOptions }
initialValues={ value }
onSubmit={ onChange }
onDelete={ onDelete }
/>
}
/>
<AppButton isTertiary onClick={ toggleEditModal }>
{ __( 'Edit', 'google-listings-and-ads' ) }
</AppButton>
</div>
}
suffix={ currency }
value={ rate }
onBlur={ handleBlur }
/>
{ isEditModalOpen && (
<EditRateFormModal
countryOptions={ countryOptions }
initialValues={ value }
onSubmit={ onChange }
onDelete={ onDelete }
onRequestClose={ toggleEditModal }
/>
) }
{ rate === 0 && (
<div className="gla-input-pill-div">
<Pill>
Expand Down
18 changes: 18 additions & 0 deletions js/src/hooks/useToggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* External dependencies
*/
import { useState, useCallback } from '@wordpress/element';

/**
* A hook to toggle a boolean state.
*
* @param {boolean} [initialValue=false] The initial value of the toggle.
* @return {Array} A tuple of `[ value, toggle ]`.
*/
const useToggle = ( initialValue = false ) => {
const [ value, setValue ] = useState( initialValue );
const toggle = useCallback( () => setValue( ( prev ) => ! prev ), [] );
return [ value, toggle ];
};
Comment on lines +12 to +16

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The name toggle explicitly implicates that the function should be to toggle on/off. I don't think there's a strong case for accepting a boolean as a parameter here.


export default useToggle;
42 changes: 42 additions & 0 deletions js/src/hooks/useToggle.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* External dependencies
*/
import { renderHook, act } from '@testing-library/react';

/**
* Internal dependencies
*/
import useToggle from '~/hooks/useToggle';

describe( 'useToggle', () => {
it( 'defaults to false when no initialValue is provided', () => {
const { result } = renderHook( () => useToggle() );
const [ value ] = result.current;
expect( value ).toBe( false );
} );

it( 'respects a custom initialValue', () => {
const { result } = renderHook( () => useToggle( true ) );
const [ value ] = result.current;
expect( value ).toBe( true );
} );

it( 'toggles from false to true', () => {
const { result } = renderHook( () => useToggle() );
act( () => result.current[ 1 ]() );
expect( result.current[ 0 ] ).toBe( true );
} );

it( 'toggles from true to false', () => {
const { result } = renderHook( () => useToggle( true ) );
act( () => result.current[ 1 ]() );
expect( result.current[ 0 ] ).toBe( false );
} );

it( 'returns a stable toggle function reference across renders', () => {
const { result, rerender } = renderHook( () => useToggle() );
const toggleFirst = result.current[ 1 ];
rerender();
expect( result.current[ 1 ] ).toBe( toggleFirst );
} );
} );
Loading
Loading