Implement widget and fix some bugs

This commit is contained in:
inpsyde-maticluznar 2024-11-28 10:31:16 +01:00
parent 6225943c00
commit fac3dfcf84
No known key found for this signature in database
GPG key ID: D005973F231309F6
6 changed files with 306 additions and 215 deletions

View file

@ -13,7 +13,7 @@
"@wordpress/scripts": "^30.3.0"
},
"dependencies": {
"@paypal/paypal-js": "^8.1.2",
"@paypal/react-paypal-js": "^8.7.0",
"@woocommerce/settings": "^1.0.0",
"deepmerge": "^4.3.1",
"react-select": "^5.8.3"

View file

@ -33,9 +33,16 @@
&__preview {
width: calc(100% - 422px);
background-color: #FAF8F5;
display: flex;
align-items: center;
&-inner {
width: 100%;
padding: 24px;
}
}
&__section--rc{
&__section--rc {
.ppcp-r-styling__title {
@include font(13, 20, 600);
color: $color-black;
@ -44,6 +51,12 @@
}
}
&__section--empty.ppcp-r-styling__section {
padding-bottom: 0;
margin-bottom: 0;
border-bottom: none;
}
&__select {
label {
@include font(13, 16, 600);

View file

@ -1,12 +1,20 @@
import { CheckboxControl } from '@wordpress/components';
export const PayPalCheckbox = ( props ) => {
let isChecked = null;
if ( Array.isArray( props.currentValue ) ) {
isChecked = props.currentValue.includes( props.value );
} else {
isChecked = props.currentValue;
}
return (
<div className="ppcp-r__checkbox">
<CheckboxControl
label={ props?.label ? props.label : '' }
value={ props.value }
checked={ props.currentValue.includes( props.value ) }
checked={ isChecked }
onChange={ ( checked ) =>
handleCheckboxState( checked, props )
}
@ -86,7 +94,9 @@ export const PayPalRdbWithContent = ( props ) => {
export const handleCheckboxState = ( checked, props ) => {
let newValue = null;
if ( checked ) {
if ( ! Array.isArray( props.currentValue ) ) {
newValue = checked;
} else if ( checked ) {
newValue = [ ...props.currentValue, props.value ];
} else {
newValue = props.currentValue.filter(

View file

@ -2,7 +2,8 @@ import { __, sprintf } from '@wordpress/i18n';
import { SelectControl, RadioControl } from '@wordpress/components';
import { PayPalCheckboxGroup } from '../../ReusableComponents/Fields';
import { useState, useMemo, useEffect } from '@wordpress/element';
import Renderer from '../../../../../../ppcp-button/resources/js/modules/Renderer/Renderer';
import { PayPalScriptProvider, PayPalButtons } from '@paypal/react-paypal-js';
import {
defaultLocationSettings,
paymentMethodOptions,
@ -13,15 +14,32 @@ import {
} from '../../../data/settings/tab-styling-data';
const TabStyling = () => {
useEffect( () => {
generatePreview();
}, [] );
const [ location, setLocation ] = useState( 'cart' );
const [ canRender, setCanRender ] = useState( false );
const [ locationSettings, setLocationSettings ] = useState( {
...defaultLocationSettings,
} );
// Sometimes buttons won't render. This fixes the timing problem.
useEffect( () => {
const handleDOMContentLoaded = () => setCanRender( true );
if (
document.readyState === 'interactive' ||
document.readyState === 'complete'
) {
handleDOMContentLoaded();
} else {
document.addEventListener(
'DOMContentLoaded',
handleDOMContentLoaded
);
}
}, [] );
document.addEventListener( 'DOMContentLoaded', () => {
setCanRender( true );
} );
const currentLocationSettings = useMemo( () => {
return locationSettings[ location ];
}, [ location, locationSettings ] );
@ -41,145 +59,80 @@ const TabStyling = () => {
}, [] );
const updateButtonSettings = ( key, value ) => {
const updatedLocationSettings = { ...currentLocationSettings };
updatedLocationSettings.settings = {
...updatedLocationSettings.settings,
...{ [ key ]: value },
};
setLocationSettings( {
...locationSettings,
[ location ]: { ...updatedLocationSettings },
[ location ]: {
...currentLocationSettings,
settings: {
...currentLocationSettings.settings,
[ key ]: value,
},
},
} );
};
const updateButtonStyle = ( key, value ) => {
setLocationSettings( {
...locationSettings,
[ location ]: {
...currentLocationSettings,
settings: {
...currentLocationSettings.settings,
style: {
...currentLocationSettings.settings.style,
[ key ]: value,
},
},
},
} );
};
if ( ! canRender ) {
return <></>;
}
return (
<div className="ppcp-r-styling">
<div className="ppcp-r-styling__settings">
<SectionIntro />
<TabStylingSection className="ppcp-r-styling__section--rc">
<SelectControl
className="ppcp-r-styling__select"
value={ location }
onChange={ ( newLocation ) =>
setLocation( newLocation )
}
label={ __(
'Locations',
'woocommerce-paypal-payments'
) }
options={ locationOptions }
/>
</TabStylingSection>
<TabStylingSection
title={ __(
'Payment Methods',
'woocommerce-paypal-payments'
) }
className="ppcp-r-styling__section--rc"
>
<div className="ppcp-r-styling__payment-method-checkboxes">
<PayPalCheckboxGroup
value={ paymentMethodOptions }
changeCallback={ ( newValue ) =>
updateButtonSettings(
'paymentMethods',
newValue
)
}
currentValue={
currentLocationSettings.settings.paymentMethods
}
/>
</div>
</TabStylingSection>
{ currentLocationSettings.settings?.buttonLayout && (
<TabStylingSection
className="ppcp-r-styling__section--rc"
title={ __(
'Button Layout',
'woocommerce-paypal-payments'
) }
>
<RadioControl
className="ppcp-r__horizontal-control"
onChange={ ( newValue ) =>
updateButtonSettings( 'buttonLayout', newValue )
}
selected={
currentLocationSettings.settings.buttonLayout
}
options={ buttonLayoutOptions }
/>
</TabStylingSection>
) }
<TabStylingSection
title={ __( 'Shape', 'woocommerce-paypal-payments' ) }
className="ppcp-r-styling__section--rc"
>
<RadioControl
className="ppcp-r__horizontal-control"
onChange={ ( newValue ) =>
updateButtonSettings( 'shape', newValue )
}
selected={ currentLocationSettings.settings.shape }
options={ shapeOptions }
/>
</TabStylingSection>
<TabStylingSection>
<SelectControl
className="ppcp-r-styling__select"
onChange={ ( newValue ) =>
updateButtonSettings( 'buttonLabel', newValue )
}
selected={
currentLocationSettings.settings.buttonLabel
}
label={ __(
'Button Label',
'woocommerce-paypal-payments'
) }
options={ buttonLabelOptions }
/>
</TabStylingSection>
<TabStylingSection>
<SelectControl
className="ppcp-r-styling__select"
label={ __(
'Button Color',
'woocommerce-paypal-payments'
) }
options={ colorOptions }
/>
</TabStylingSection>
{ currentLocationSettings.settings?.tagLine && (
<TabStylingSection
title={ __( 'Tagline', 'woocommerce-paypal-payments' ) }
className="ppcp-r-styling__section--rc"
>
<PayPalCheckboxGroup
value={ [
{
value: 'enable-tagline',
label: __(
'Enable Tagline',
'woocommerce-paypal-payments'
),
},
] }
changeCallback={ ( newValue ) =>
updateButtonSettings( 'tagLine', newValue )
}
currentValue={
currentLocationSettings.settings.tagLine
}
/>
</TabStylingSection>
) }
<SectionLocations
locationOptions={ locationOptions }
location={ location }
setLocation={ setLocation }
/>
<SectionPaymentMethods
locationSettings={ currentLocationSettings }
updateButtonSettings={ updateButtonSettings }
/>
<SectionButtonLayout
locationSettings={ currentLocationSettings }
updateButtonStyle={ updateButtonStyle }
/>
<SectionButtonShape
locationSettings={ currentLocationSettings }
updateButtonStyle={ updateButtonStyle }
/>
<SectionButtonLabel
locationSettings={ currentLocationSettings }
updateButtonStyle={ updateButtonStyle }
/>
<SectionButtonColor
locationSettings={ currentLocationSettings }
updateButtonStyle={ updateButtonStyle }
/>
<SectionButtonTagline
locationSettings={ currentLocationSettings }
updateButtonStyle={ updateButtonStyle }
/>
</div>
<div className="ppcp-preview ppcp-r-button-preview ppcp-r-styling__preview">
<div id="ppcp-r-styling-preview"></div>
<div className="ppcp-r-styling__preview-inner">
<SectionButtonPreview
locationSettings={ currentLocationSettings }
/>
</div>
</div>
</div>
);
@ -225,74 +178,165 @@ const SectionIntro = () => {
);
};
const generatePreview = () => {
const render = () => {
const settings = {
button: {
wrapper: '#ppcp-r-styling-preview',
style: {
color: 'gold',
shape: 'rect',
label: 'paypal',
tagline: false,
layout: 'horizontal',
},
},
separate_buttons: {},
};
const wrapperSelector =
Object.values( settings.separate_buttons ).length > 0
? Object.values( settings.separate_buttons )[ 0 ].wrapper
: settings.button.wrapper;
const wrapper = document.querySelector( wrapperSelector );
if ( ! wrapper ) {
return;
}
wrapper.innerHTML = '';
const renderer = new Renderer(
null,
settings,
( data, actions ) => actions.reject(),
null
);
try {
renderer.render( {} );
jQuery( document ).trigger(
'ppcp_paypal_render_preview',
settings
);
} catch ( err ) {
console.error( err );
}
};
renderPreview( () => {
console.log( 'CALLBACK' );
}, render );
const SectionLocations = ( { locationOptions, location, setLocation } ) => {
return (
<TabStylingSection className="ppcp-r-styling__section--rc">
<SelectControl
className="ppcp-r-styling__select"
value={ location }
onChange={ ( newLocation ) => setLocation( newLocation ) }
label={ __( 'Locations', 'woocommerce-paypal-payments' ) }
options={ locationOptions }
/>
</TabStylingSection>
);
};
function renderPreview( settingsCallback, render ) {
let oldSettings = settingsCallback();
const form = jQuery( '#mainform' );
form.on( 'change', ':input', () => {
const newSettings = settingsCallback();
if ( JSON.stringify( oldSettings ) === JSON.stringify( newSettings ) ) {
return;
}
const SectionPaymentMethods = ( {
locationSettings,
updateButtonSettings,
} ) => {
return (
<TabStylingSection
title={ __( 'Payment Methods', 'woocommerce-paypal-payments' ) }
className="ppcp-r-styling__section--rc"
>
<div className="ppcp-r-styling__payment-method-checkboxes">
<PayPalCheckboxGroup
value={ paymentMethodOptions }
changeCallback={ ( newValue ) =>
updateButtonSettings( 'paymentMethods', newValue )
}
currentValue={ locationSettings.settings.paymentMethods }
/>
</div>
</TabStylingSection>
);
};
render( newSettings );
const SectionButtonLayout = ( { locationSettings, updateButtonStyle } ) => {
const buttonLayoutIsAllowed =
locationSettings.settings.style?.layout &&
locationSettings.settings.style?.tagline === false;
return (
buttonLayoutIsAllowed && (
<TabStylingSection
className="ppcp-r-styling__section--rc"
title={ __( 'Button Layout', 'woocommerce-paypal-payments' ) }
>
<RadioControl
className="ppcp-r__horizontal-control"
onChange={ ( newValue ) =>
updateButtonStyle( 'layout', newValue )
}
selected={ locationSettings.settings.style.layout }
options={ buttonLayoutOptions }
/>
</TabStylingSection>
)
);
};
oldSettings = newSettings;
} );
const SectionButtonShape = ( { locationSettings, updateButtonStyle } ) => {
return (
<TabStylingSection
title={ __( 'Shape', 'woocommerce-paypal-payments' ) }
className="ppcp-r-styling__section--rc"
>
<RadioControl
className="ppcp-r__horizontal-control"
onChange={ ( newValue ) =>
updateButtonStyle( 'shape', newValue )
}
selected={ locationSettings.settings.style.shape }
options={ shapeOptions }
/>
</TabStylingSection>
);
};
jQuery( document ).on( 'ppcp_paypal_script_loaded', () => {
oldSettings = settingsCallback();
const SectionButtonLabel = ( { locationSettings, updateButtonStyle } ) => {
return (
<TabStylingSection>
<SelectControl
className="ppcp-r-styling__select"
onChange={ ( newValue ) =>
updateButtonStyle( 'label', newValue )
}
value={ locationSettings.settings.style.label }
label={ __( 'Button Label', 'woocommerce-paypal-payments' ) }
options={ buttonLabelOptions }
/>
</TabStylingSection>
);
};
render( oldSettings );
} );
const SectionButtonColor = ( { locationSettings, updateButtonStyle } ) => {
return (
<TabStylingSection>
<SelectControl
className=" ppcp-r-styling__select"
label={ __( 'Button Color', 'woocommerce-paypal-payments' ) }
onChange={ ( newValue ) =>
updateButtonStyle( 'color', newValue )
}
value={ locationSettings.settings.style.color }
options={ colorOptions }
/>
</TabStylingSection>
);
};
const SectionButtonTagline = ( { locationSettings, updateButtonStyle } ) => {
const taglineIsAllowed =
locationSettings.settings.style.hasOwnProperty( 'tagline' ) &&
locationSettings.settings.style?.layout === 'horizontal';
return (
taglineIsAllowed && (
<TabStylingSection
title={ __( 'Tagline', 'woocommerce-paypal-payments' ) }
className="ppcp-r-styling__section--rc"
>
<PayPalCheckboxGroup
value={ [
{
value: 'tagline',
label: __(
'Enable Tagline',
'woocommerce-paypal-payments'
),
},
] }
changeCallback={ ( newValue ) => {
updateButtonStyle( 'tagline', newValue );
} }
currentValue={ locationSettings.settings.style.tagline }
/>
</TabStylingSection>
)
);
};
const SectionButtonPreview = ( { locationSettings } ) => {
return (
<PayPalScriptProvider
options={ {
clientId: 'test',
merchantId: 'QTQX5NP6N9WZU',
components: 'buttons,googlepay',
'buyer-country': 'US',
currency: 'USD',
} }
>
<PayPalButtons
style={ locationSettings.settings.style }
forceReRender={ [ locationSettings.settings.style ] }
>
Error
</PayPalButtons>
</PayPalScriptProvider>
);
};
render( oldSettings );
}
export default TabStyling;

View file

@ -1,19 +1,23 @@
import { __ } from '@wordpress/i18n';
const settings = {
paymentMethods: [],
buttonLayout: 'horizontal',
shape: null,
buttonLabel: 'paypal',
buttonColor: 'gold',
tagLine: [],
};
const cartAndExpressCheckoutSettings = {
paymentMethods: [],
shape: null,
buttonLabel: 'paypal',
buttonColor: 'gold',
style: {
shape: 'pill',
label: 'paypal',
color: 'gold',
},
};
const settings = {
paymentMethods: [],
style: {
layout: 'vertical',
shape: cartAndExpressCheckoutSettings.style.shape,
label: cartAndExpressCheckoutSettings.style.label,
color: cartAndExpressCheckoutSettings.style.color,
tagline: false,
},
};
export const defaultLocationSettings = {
@ -77,11 +81,11 @@ export const buttonLabelOptions = [
label: __( 'Checkout', 'woocommerce-paypal-payments' ),
},
{
value: 'paypal-buy-now',
value: 'buynow',
label: __( 'PayPal Buy Now', 'woocommerce-paypal-payments' ),
},
{
value: 'pay-with-paypal',
value: 'pay',
label: __( 'Pay with PayPal', 'woocommerce-paypal-payments' ),
},
];
@ -126,7 +130,7 @@ export const shapeOptions = [
label: __( 'Pill', 'woocommerce-paypal-payments' ),
},
{
value: 'rectangle',
value: 'rect',
label: __( 'Rectangle', 'woocommerce-paypal-payments' ),
},
];

View file

@ -1881,6 +1881,21 @@
dependencies:
promise-polyfill "^8.3.0"
"@paypal/react-paypal-js@^8.7.0":
version "8.7.0"
resolved "https://registry.yarnpkg.com/@paypal/react-paypal-js/-/react-paypal-js-8.7.0.tgz#26b9dc9b881827afcb2fb8dea5078a9c90e24128"
integrity sha512-KW4EdL8hlLWBY6f9l1csxQ8Szh5bhMFLxl+DV29jHNwdlM6z3s+w4LZQ7GtgHktSrlNBHgblNNvwLNpcDtsZgg==
dependencies:
"@paypal/paypal-js" "^8.1.2"
"@paypal/sdk-constants" "^1.0.122"
"@paypal/sdk-constants@^1.0.122":
version "1.0.150"
resolved "https://registry.yarnpkg.com/@paypal/sdk-constants/-/sdk-constants-1.0.150.tgz#26b9f3b980bc1c73846ae0c1af99719e490dff48"
integrity sha512-ETm/mtiTBw4gHPdKo3GXzSQyXfZKevSg+ujfEvZbLT9gCc/YFmTBnWDroqmzOeuSXnf2Ll4bBSp3xbr47NQbUQ==
dependencies:
hi-base32 "^0.5.0"
"@pkgr/core@^0.1.0":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31"
@ -6595,6 +6610,11 @@ hey-listen@^1.0.8:
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
hi-base32@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/hi-base32/-/hi-base32-0.5.1.tgz#1279f2ddae2673219ea5870c2121d2a33132857e"
integrity sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==
highlight-words-core@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/highlight-words-core/-/highlight-words-core-1.2.3.tgz#781f37b2a220bf998114e4ef8c8cb6c7a4802ea8"