PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.3.52
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.3.52
1.4.17 1.4.16 1.4.15 1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 1.3.51 1.3.50 1.3.49 1.3.48 All 180 releases
disco / backend / views / components / Main / utilities / utilities.js

utilities.js in Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO 1.3.52, at backend/views/components/Main/utilities/utilities.js

340 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { __ } from '@wordpress/i18n';
2 import moment from 'moment';
3 import { toast } from 'react-toastify';
4
5 export const getSelectedFilterData = (items, current) => {
6 let value = {};
7 items.forEach((group) => {
8 if (group.options[current]) {
9 value = group.options[current];
10 }
11 });
12
13 return value;
14 };
15
16 export const dateTimeFormatter = (datetime) => {
17 if (datetime) {
18 return moment(datetime).format('Do MMM, YYYY h:mm A');
19 } else {
20 return '-';
21 }
22 };
23
24 export const dateStringToTimestamp = (dateString) => {
25 const date = new Date(dateString);
26
27 if (isNaN(date.getTime())) {
28 return false;
29 }
30
31 return date.getTime();
32 };
33
34 export const prepareCampaignForRequest = (campaign, prefix = '') => {
35 const dataForRequest = { ...campaign };
36
37 if (dataForRequest.id) {
38 delete dataForRequest.id;
39 }
40 if (dataForRequest.created_by) {
41 delete dataForRequest.created_by;
42 }
43 if (dataForRequest.created_date) {
44 delete dataForRequest.created_date;
45 }
46 if (dataForRequest.modified_by) {
47 delete dataForRequest.modified_by;
48 }
49 if (dataForRequest.modified_date) {
50 delete dataForRequest.modified_date;
51 }
52 if (dataForRequest._links) {
53 delete dataForRequest._links;
54 }
55 if (dataForRequest.name) {
56 dataForRequest.name = dataForRequest.name + ' - ' + prefix;
57 }
58 if (dataForRequest.priority) {
59 dataForRequest.priority = '1';
60 }
61
62 return dataForRequest;
63 };
64
65 export const buildQueryUrl = (base, query) => {
66 const separator = DISCO.is_pretty_url ? '?' : '&';
67 return `${base}${separator}${query}`;
68 };
69
70 export const scrollToEmptyField = (fieldName, errorMessage) => {
71 const fields = document.getElementsByName(fieldName);
72 // Check if multiple fields are present
73 if (fields.length > 1) {
74 // Loop through all the fields and scroll to the first empty one
75 for (let i = 0; i < fields.length; i++) {
76 const field = fields[i];
77 if (field && field.value.trim().length === 0) {
78 // Scroll and focus on the first empty field
79 field.scrollIntoView({ behavior: 'smooth', block: 'center' });
80 field.focus();
81 toast.error(errorMessage);
82 return true; // Error found
83 }
84 }
85 } else if (fields.length === 1) {
86 // Handle single field case
87 const field = fields[0];
88 if (field && field.value.trim().length === 0) {
89 field.scrollIntoView({ behavior: 'smooth', block: 'center' });
90 field.focus();
91 toast.error(errorMessage);
92 return true; // Error found
93 }
94 }
95
96 return false; // No error found
97 };
98
99 export const cleanFilters = (data) => {
100 return data
101 .map((group) => {
102 const cleanedBaseFilters = (group.base_filters || []).filter(
103 (filter) => {
104 return (
105 filter.compare !== undefined && filter.compare !== ''
106 );
107 }
108 );
109
110 if (cleanedBaseFilters.length === 0) {
111 return null; // Mark this group for removal
112 }
113
114 return {
115 ...group,
116 base_filters: cleanedBaseFilters,
117 };
118 })
119 .filter((group) => group !== null); // Remove groups that are null
120 };
121
122 // utils/validateRule.js
123
124 export function validateRule(rule, prevRule = {}, index = 0) {
125 const errors = {};
126
127 const min = Number(rule.min);
128 const max = rule.max !== '' ? Number(rule.max) : null;
129 const prevMin = Number(prevRule.min);
130 const prevMax = prevRule.max !== '' ? Number(prevRule.max) : null;
131
132 // Min must be greater than 0
133 if (!rule.min || min <= 0) {
134 errors.min = 'Minimum must be greater than 0';
135 }
136
137 if (rule.recursive === 'no' && max !== null && min > max) {
138 errors.max = 'Maximum must be greater than Minimum';
139 }
140
141 if (index > 0) {
142 if (rule.recursive === 'no') {
143 if (prevRule.recursive === 'no') {
144 if (prevMax !== null ? min <= prevMax : min <= prevMin) {
145 errors.min = 'Minimum must be greater than previous rule';
146 }
147 } else if (min <= prevMin) {
148 errors.min = 'Minimum must be greater than previous rule';
149 }
150 } else if (rule.recursive === 'yes' && min <= prevMin) {
151 errors.min = 'Minimum must be greater than previous rule';
152 }
153 }
154
155 // Only show error toast for the first error (optional)
156 if (Object.keys(errors).length > 0) {
157 toast.error(Object.values(errors)[0]);
158 }
159
160 return {
161 isValid: Object.keys(errors).length === 0,
162 errors,
163 message: Object.values(errors)[0] || '',
164 };
165 }
166
167 // NEW: validate all rules at once
168 export function validateAllRules(rules) {
169 for (let i = 0; i < rules.length; i++) {
170 const current = rules[i];
171 const previous = rules[i - 1] || {};
172 const result = validateRule(current, previous, i);
173
174 if (!result.isValid) {
175 return {
176 isValid: false,
177 index: i,
178 field: Object.keys(result.errors)[0],
179 message: result.message,
180 };
181 }
182 }
183
184 return { isValid: true };
185 }
186
187 //Validate conditions, check the values is empty or not.
188 export function validateConditions(conditions) {
189 if (!conditions || conditions.length === 0) {
190 return true;
191 }
192
193 for (const group of conditions) {
194 const filters = group.base_filters || [];
195 for (const filter of filters) {
196 if (!filter.compare_with) {
197 toast.error(
198 __(
199 'Please select a condition type or remove the empty condition.',
200 'disco'
201 )
202 );
203 return false;
204 }
205
206 const value = filter.compare;
207
208 if (value === undefined || value === null || value === '') {
209 toast.error(
210 __(
211 'Please fill in the condition value or remove the empty condition.',
212 'disco'
213 )
214 );
215 return false;
216 }
217
218 if (Array.isArray(value)) {
219 const isEmpty =
220 value.length === 0 ||
221 value.every(
222 (v) => v === '' || v === undefined || v === null
223 );
224 if (isEmpty) {
225 toast.error(
226 __(
227 'Please fill in the condition value or remove the empty condition.',
228 'disco'
229 )
230 );
231 return false;
232 }
233 }
234 }
235 }
236
237 return true;
238 }
239
240 export function validateEmptyField(discount) {
241 const { products, discount_intent, discount_rules } = discount;
242 if (products.length === 0) {
243 if (
244 scrollToEmptyField(
245 'search_products',
246 __('Please select few products!', 'disco')
247 )
248 )
249 return false;
250 }
251
252 //Field validation for name
253 if (
254 scrollToEmptyField(
255 'campaign_name',
256 __('Campaign Name is Required', 'disco')
257 )
258 )
259 return false;
260
261 //Field validation for Minimum quantity
262 if (
263 discount_intent === 'Bulk' ||
264 discount_intent === 'Bundle' ||
265 discount_intent === 'BOGO'
266 ) {
267 if (
268 scrollToEmptyField(
269 'min',
270 __('Minimum Quantity is Required', 'disco')
271 )
272 )
273 return false;
274 }
275
276 if (
277 discount_intent === 'BOGO' &&
278 scrollToEmptyField(
279 'get_quantity',
280 __('Get quantity is Required', 'disco')
281 )
282 )
283 return false;
284
285 if (
286 discount_intent === 'BOGO' ||
287 discount_intent === 'Bulk' ||
288 (discount_intent === 'Bundle' && discount_rules.length > 0)
289 ) {
290 const result = validateAllRules(discount_rules);
291
292 if (!result.isValid) {
293 return false;
294 }
295 }
296
297 //Field validation for discount_value
298 if (
299 discount_intent !== 'Shipping' &&
300 scrollToEmptyField(
301 'discount_value',
302 __('Discount Value is Required', 'disco')
303 )
304 )
305 return false;
306
307 // Conditions validation
308 if (!validateConditions(discount.conditions)) {
309 return false;
310 }
311
312 return true;
313 }
314
315 export function discountRulesToTableData(discount_rules) {
316 const data = discount_rules.map((rule) => {
317 const range = rule.max ? `${rule.min}-${rule.max}` : rule.min;
318 return {
319 title: rule.discount_label,
320 discount: rule.discount_value,
321 range,
322 buy_now: 'Add To Cart',
323 };
324 });
325 return data;
326 }
327
328 /**
329 * To truncate text and add an ellipsis
330 * @param {string} str
331 * @param {number} maxLength
332 * @returns {string}
333 */
334 export function truncate(str, maxLength = 30) {
335 if (str.length > maxLength) {
336 return str.slice(0, maxLength) + '...';
337 }
338 return str;
339 }
340