It looks like nothing was found at this location. Maybe try one of the links below or a search?
import { useState, useEffect } from 'react';
import { Drawer, Button, toast } from '@bsf/force-ui';
import { CheckIcon } from '@heroicons/react/24/outline';
import { __ } from '@wordpress/i18n';
import parse from 'html-react-parser';
import { doApiFetch } from '@Store';
import SkeletonLoader from '@Components/common/skeletons/SkeletonLoader';
import SmsTemplatesDrawerBody from './SmsTemplatesDrawerBody';
const SmsTemplatesDrawer = ( { open, setOpen, template, onSave } ) => {
const [ formState, setFormState ] = useState( {
template_name: '',
sms_body: `Hi {{customer.firstname}}! You left {{cart.product.names}} in your cart. Complete your order before it’s gone: {{cart.checkout_url}}`,
sms_frequency: 10,
sms_frequency_unit: 'MINUTE',
is_activated: false,
override_global_coupon: false,
discount_type: 'percent',
coupon_amount: '',
coupon_expiry_date: 1,
coupon_expiry_unit: 'days',
auto_coupon: false,
free_shipping_coupon: false,
individual_use_only: false,
exclude_product_ids: '',
enable_sms_rule_engine: false,
sms_rule_engine: [],
} );
const [ isSubmitting, setIsSubmitting ] = useState( false );
const [ isLoading, setIsLoading ] = useState( true );
const [ errors, setErrors ] = useState( {} );
useEffect( () => {
setIsLoading( true );
if ( template ) {
setFormState( {
...template,
} );
} else {
// Reset form for new template with default values
setFormState( {
template_name: '',
sms_body: `Hi {{customer.firstname}}! You left {{cart.product.names}} in your cart. Complete your order before it’s gone: {{cart.checkout_url}}`,
sms_frequency: 10,
sms_frequency_unit: 'MINUTE',
is_activated: false,
override_global_coupon: false,
discount_type: 'percent',
coupon_amount: '',
coupon_expiry_date: 1,
coupon_expiry_unit: 'days',
auto_coupon: false,
free_shipping_coupon: false,
individual_use_only: false,
exclude_product_ids: '',
enable_sms_rule_engine: false,
sms_rule_engine: [],
} );
}
setErrors( {} );
setIsLoading( false );
}, [ template, open ] );
const handleChange = ( name, value ) => {
setFormState( ( prev ) => {
return { ...prev, [ name ]: value };
} );
// Clear error for this field if it exists
if ( errors[ name ] ) {
setErrors( { ...errors, [ name ]: null } );
}
};
const isEmptyStringOrArray = ( val ) => {
return (
( typeof val === 'string' && val.trim() === '' ) ||
( Array.isArray( val ) && val.length === 0 )
);
};
const validateForm = () => {
const newErrors = {};
if ( ! formState.template_name.trim() ) {
newErrors.template_name = __(
'Template name is required',
'woo-cart-abandonment-recovery'
);
}
if ( ! formState.sms_body.trim() ) {
newErrors.email_body = __(
'SMS body is required',
'woo-cart-abandonment-recovery'
);
}
if ( formState.email_frequency < 1 ) {
newErrors.email_frequency = __(
'Time should be minimum 1 min.',
'woo-cart-abandonment-recovery'
);
}
if ( formState.sms_body.length > 160 ) {
newErrors.sms = __(
'SMS body should be less than 160 characters.',
'woo-cart-abandonment-recovery'
);
}
if (
! [ '', '0', false ].includes( formState?.enable_sms_rule_engine )
) {
let rules = formState.sms_rule_engine || [];
if ( typeof rules === 'string' ) {
try {
rules = JSON.parse( rules );
} catch ( e ) {
newErrors.sms_rule_engine = __(
'Invalid JSON in rule engine',
'woo-cart-abandonment-recovery'
);
return false;
}
}
if (
rules.length === 0 ||
rules.some(
( group ) =>
group.rules &&
group.rules.some(
( rule ) =>
isEmptyStringOrArray( rule.condition ) ||
isEmptyStringOrArray( rule.value ) ||
isEmptyStringOrArray( rule.operator )
)
)
) {
newErrors.sms_rule_engine = __(
'Missing fields in rule: condition, operator, or value.',
'woo-cart-abandonment-recovery'
);
}
}
setErrors( newErrors );
if ( Object.keys( newErrors ).length !== 0 ) {
toast.error( 'Error!', {
description: parse( Object.values( newErrors ).join( '
' ) ),
} );
return false;
}
return true;
};
const handleSubmit = () => {
if ( ! validateForm() ) {
return;
}
setIsSubmitting( true );
const formData = new window.FormData();
// Set the full option name in the form data
formData.append( 'wcf_template_name', formState.template_name );
formData.append( 'wcf_sms_body', formState.sms_body );
formData.append( 'wcf_sms_frequency', formState.sms_frequency );
formData.append(
'wcf_sms_frequency_unit',
formState.sms_frequency_unit
);
formData.append(
'wcf_activate_sms_template',
formState.is_activated ? '1' : ''
);
formData.append(
'wcf_override_global_coupon',
formState.override_global_coupon ? '1' : ''
);
formData.append( 'wcf_discount_type', formState.discount_type );
formData.append( 'wcf_coupon_amount', formState.coupon_amount );
formData.append(
'wcf_coupon_expiry_date',
formState.coupon_expiry_date
);
formData.append(
'wcf_coupon_expiry_unit',
formState.coupon_expiry_unit
);
formData.append(
'wcf_exclude_product_ids',
formState.exclude_product_ids
);
formData.append( 'wcf_auto_coupon', formState.auto_coupon ? '1' : '' );
formData.append(
'wcf_free_shipping_coupon',
formState.free_shipping_coupon ? '1' : ''
);
formData.append(
'wcf_individual_use_only',
formState.individual_use_only ? '1' : ''
);
formData.append(
'wcf_enable_sms_rule_engine',
formState?.enable_sms_rule_engine ? '1' : ''
);
formData.append(
'wcf_sms_rule_engine',
JSON.stringify( formState?.sms_rule_engine || [] )
);
// Add template ID if editing
if ( template?.id ) {
formData.append( 'id', template.id );
formData.append( 'action', 'wcar_pro_update_sms_template' );
formData.append(
'security',
cart_abandonment_admin?.update_sms_template_nonce
);
} else {
formData.append( 'action', 'wcar_pro_save_sms_template' );
formData.append(
'security',
cart_abandonment_admin?.save_sms_template_nonce
);
}
const ajaxUrl = cart_abandonment_admin?.ajax_url || window.ajaxurl;
// Make API call
doApiFetch(
ajaxUrl,
formData,
'POST',
( response ) => {
if ( response.success ) {
// Call the parent's onSave callback with the updated template
onSave( response.data.template );
toast.success( 'Success!', {
description: __(
'Template saved successfully',
'woo-cart-abandonment-recovery'
),
} );
} else {
toast.success( 'Error!', {
description:
response.data.message ||
__(
'Failed to save template',
'woo-cart-abandonment-recovery'
),
} );
}
},
( error ) => {
toast.error( 'Error!', {
description:
error.message ||
__(
'Failed to save template',
'woo-cart-abandonment-recovery'
),
} );
},
true
).finally( () => {
setIsSubmitting( false );
} );
};
const truncateText = ( text, maxLength = 60 ) => {
return text.length > maxLength
? text.slice( 0, maxLength ) + '...'
: text;
};
return (
{ errors.submit }
It looks like nothing was found at this location. Maybe try one of the links below or a search?