PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.3.34
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.3.34
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.34, at backend/views/components/Main/utilities/utilities.js

322 lines 7.1 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 if (rule.recursive === 'no' && max !== null && min > max) {
133 errors.max = 'Maximum must be greater than Minimum';
134 }
135
136 if (index > 0) {
137 if (rule.recursive === 'no') {
138 if (prevRule.recursive === 'no') {
139 if (prevMax !== null ? min <= prevMax : min <= prevMin) {
140 errors.min = 'Minimum must be greater than previous rule';
141 }
142 } else if (min <= prevMin) {
143 errors.min = 'Minimum must be greater than previous rule';
144 }
145 } else if (rule.recursive === 'yes' && min <= prevMin) {
146 errors.min = 'Minimum must be greater than previous rule';
147 }
148 }
149
150 // Only show error toast for the first error (optional)
151 if (Object.keys(errors).length > 0) {
152 toast.error(Object.values(errors)[0]);
153 }
154
155 return {
156 isValid: Object.keys(errors).length === 0,
157 errors,
158 message: Object.values(errors)[0] || '',
159 };
160 }
161
162 // NEW: validate all rules at once
163 export function validateAllRules(rules) {
164 for (let i = 0; i < rules.length; i++) {
165 const current = rules[i];
166 const previous = rules[i - 1] || {};
167 const result = validateRule(current, previous, i);
168
169 if (!result.isValid) {
170 return {
171 isValid: false,
172 index: i,
173 field: Object.keys(result.errors)[0],
174 message: result.message,
175 };
176 }
177 }
178
179 return { isValid: true };
180 }
181
182 //Validate conditions, check the values is empty or not.
183 export function validateConditions(conditions) {
184 if (!conditions || conditions.length === 0) {
185 return true;
186 }
187
188 for (const group of conditions) {
189 const filters = group.base_filters || [];
190 for (const filter of filters) {
191 if (!filter.compare_with) {
192 toast.error(
193 __(
194 'Please select a condition type or remove the empty condition.',
195 'disco'
196 )
197 );
198 return false;
199 }
200
201 const value = filter.compare;
202
203 if (value === undefined || value === null || value === '') {
204 toast.error(
205 __(
206 'Please fill in the condition value or remove the empty condition.',
207 'disco'
208 )
209 );
210 return false;
211 }
212
213 if (Array.isArray(value)) {
214 const isEmpty =
215 value.length === 0 ||
216 value.every(
217 (v) => v === '' || v === undefined || v === null
218 );
219 if (isEmpty) {
220 toast.error(
221 __(
222 'Please fill in the condition value or remove the empty condition.',
223 'disco'
224 )
225 );
226 return false;
227 }
228 }
229 }
230 }
231
232 return true;
233 }
234
235 export function validateEmptyField(discount) {
236 const { products, discount_intent, discount_rules } = discount;
237 if (products.length === 0) {
238 if (
239 scrollToEmptyField(
240 'search_products',
241 __('Please select few products!', 'disco')
242 )
243 )
244 return false;
245 }
246
247 //Field validation for name
248 if (
249 scrollToEmptyField(
250 'campaign_name',
251 __('Campaign Name is Required', 'disco')
252 )
253 )
254 return false;
255
256 //Field validation for Minimum quantity
257 if (
258 discount_intent === 'Bulk' ||
259 discount_intent === 'Bundle' ||
260 discount_intent === 'BOGO'
261 ) {
262 if (
263 scrollToEmptyField(
264 'min',
265 __('Minimum Quantity is Required', 'disco')
266 )
267 )
268 return false;
269 }
270
271 if (
272 discount_intent === 'BOGO' &&
273 scrollToEmptyField(
274 'get_quantity',
275 __('Get quantity is Required', 'disco')
276 )
277 )
278 return false;
279
280 if (
281 discount_intent === 'BOGO' ||
282 discount_intent === 'Bulk' ||
283 (discount_intent === 'Bundle' && discount_rules.length > 0)
284 ) {
285 const result = validateAllRules(discount_rules);
286
287 if (!result.isValid) {
288 return false;
289 }
290 }
291
292 //Field validation for discount_value
293 if (
294 discount_intent !== 'Shipping' &&
295 scrollToEmptyField(
296 'discount_value',
297 __('Discount Value is Required', 'disco')
298 )
299 )
300 return false;
301
302 // Conditions validation
303 if (!validateConditions(discount.conditions)) {
304 return false;
305 }
306
307 return true;
308 }
309
310 export function discountRulesToTableData(discount_rules) {
311 const data = discount_rules.map((rule) => {
312 const range = rule.max ? `${rule.min}-${rule.max}` : rule.min;
313 return {
314 title: rule.discount_label,
315 discount: rule.discount_value,
316 range,
317 buy_now: 'Add To Cart',
318 };
319 });
320 return data;
321 }
322