PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.3.7
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.3.7
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / assets / src / js / admin / order / add-courses-to-order.js

add-courses-to-order.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.3.7, at assets/src/js/admin/order/add-courses-to-order.js

425 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { AdminUtilsFunctions, Api, Utils } from '../utils-admin.js';
2 import * as lpUtils from 'lpAssetsJsPath/utils.js';
3
4 const addCoursesToOrder = () => {
5 let elModalSearchCourses;
6 let elSearchCoursesResult;
7 let elOrderDetails, modalSearchItemsTemplate, modalContainer;
8 let elOrderModalFooter, elOrderModalBtnAdd;
9 let elListOrderItems;
10 let timeOutSearch;
11 const idModalSearchItems = '#modal-search-items';
12 const idOrderDetails = '#learn-press-order';
13 let dataSend = {
14 search: '',
15 id_not_in: '',
16 paged: 1,
17 };
18 const courseIdsNewSelected = [];
19 let courseIdsAdded = [];
20
21 const getAllElements = () => {
22 elOrderDetails = document.querySelector( '#learn-press-order' );
23 modalSearchItemsTemplate = document.querySelector( '#learn-press-modal-search-items' );
24 modalContainer = document.querySelector( '#container-modal-search-items' );
25 };
26
27 /**
28 * Fetch courses from API.
29 *
30 * @param keySearch
31 * @param course_ids_exclude
32 * @param paged
33 */
34 const fetchCoursesAPI = ( keySearch = '', course_ids_exclude = [], paged = 1 ) => {
35 let id_not_in = '';
36 if ( course_ids_exclude.length > 0 ) {
37 id_not_in = course_ids_exclude.join( ',' );
38 }
39
40 dataSend = {
41 search: keySearch,
42 id_not_in,
43 paged,
44 };
45
46 AdminUtilsFunctions.fetchCourses( keySearch, dataSend, {
47 before() {
48 elModalSearchCourses.classList.add( 'loading' );
49 },
50 success( response ) {
51 const { data, status, message } = response;
52 const { courses, total_pages } = data;
53
54 if ( 'success' !== status ) {
55 console.error( message );
56 } else {
57 if ( ! courses.length ) {
58 elSearchCoursesResult.innerHTML = '<li class="lp-result-item">No courses found</li>';
59 return;
60 }
61
62 elSearchCoursesResult.innerHTML = renderSearchResult( courses );
63 const paginationHtml = renderPagination( paged, total_pages );
64 const searchNav = elModalSearchCourses.querySelector( '.search-nav' );
65 searchNav.innerHTML = paginationHtml;
66 }
67 },
68 error( err ) {
69 console.error( err );
70 },
71 completed() {
72 elModalSearchCourses.classList.remove( 'loading' );
73 },
74 } );
75 };
76
77 /**
78 * Get list course ids added.
79 */
80 const getCoursesAdded = () => {
81 courseIdsAdded = [];
82 const orderItems = document.querySelectorAll( '#learn-press-order .list-order-items tbody .order-item-row' );
83 orderItems.forEach( ( orderItem ) => {
84 const orderItemId = parseInt( orderItem.getAttribute( 'data-id' ) );
85 courseIdsAdded.push( orderItemId );
86 } );
87 };
88
89 /**
90 * Add courses to order.
91 * @param e
92 * @param target
93 */
94 const addCourses = ( e, target ) => {
95 if ( ! target.classList.contains( 'add' ) ) {
96 return;
97 }
98
99 if ( ! target.closest( idModalSearchItems ) ) {
100 return;
101 }
102 elListOrderItems = elOrderDetails.querySelector( '.list-order-items' );
103
104 e.preventDefault();
105
106 target.disabled = true;
107 const dataSend = {
108 'lp-ajax': 'add_items_to_order',
109 order_id: document.querySelector( '#post_ID' ).value,
110 items: courseIdsNewSelected,
111 nonce: lpDataAdmin.nonce,
112 };
113
114 const callBack = {
115 success( response ) {
116 const { data, messages, status } = response;
117 if ( 'error' === status ) {
118 console.error( messages );
119 return;
120 }
121
122 const { item_html, order_data } = data;
123 const elNoItem = elListOrderItems.querySelector( '.no-order-items' );
124 lpUtils.lpShowHideEl( elNoItem, 0 );
125 elNoItem.insertAdjacentHTML( 'beforebegin', item_html );
126 elOrderDetails.querySelector( '.order-subtotal' ).innerHTML = order_data.subtotal_html;
127 elOrderDetails.querySelector( '.order-total' ).innerHTML = order_data.total_html;
128 //courseIdsAdded.push( ...courseIdsNewSelected );
129 courseIdsNewSelected.splice( 0, courseIdsNewSelected.length );
130 },
131 error( err ) {
132 console.error( err );
133 },
134 completed() {
135 target.disabled = false;
136 modalContainer.style.display = 'none';
137 },
138 };
139
140 Utils.lpFetchAPI( Utils.lpAddQueryArgs( Utils.lpGetCurrentURLNoParam(), dataSend ), {}, callBack );
141 };
142
143 /**
144 * Remove course from order.
145 *
146 * @param e
147 * @param target
148 */
149 const removeCourse = ( e, target ) => {
150 if ( target.tagName !== 'SPAN' ) {
151 return;
152 }
153
154 if ( ! target.closest( '.remove-order-item' ) ) {
155 return;
156 }
157
158 e.preventDefault();
159
160 if ( ! confirm( 'Are you sure you want to remove this item?' ) ) {
161 return;
162 }
163
164 target.disabled = true;
165 target.classList.add( 'dashicons-update' );
166 const elItemRow = target.closest( '.order-item-row' );
167 const elListOrderItems = target.closest( '.list-order-items' );
168 const orderItemId = parseInt( elItemRow.getAttribute( 'data-item_id' ) );
169 const courseId = parseInt( elItemRow.getAttribute( 'data-id' ) );
170
171 const dataSend = {
172 'lp-ajax': 'remove_items_from_order',
173 order_id: document.querySelector( '#post_ID' ).value,
174 items: orderItemId,
175 nonce: lpDataAdmin.nonce,
176 };
177
178 const callBack = {
179 success( response ) {
180 const { data, messages, status } = response;
181 if ( 'error' === status ) {
182 console.error( messages );
183 return;
184 }
185
186 const { item_html, order_data } = data;
187 const elNoItem = elListOrderItems.querySelector( '.no-order-items' );
188 const orderItems = elListOrderItems.querySelectorAll( '.order-item-row' );
189 orderItems.forEach( ( orderItem ) => {
190 orderItem.remove();
191 } );
192 if ( item_html.length ) {
193 elNoItem.insertAdjacentHTML( 'beforebegin', item_html );
194 } else {
195 lpUtils.lpShowHideEl( elNoItem, 1 );
196 }
197
198 courseIdsNewSelected.splice( courseIdsNewSelected.indexOf( courseId ), 1 );
199 //courseIdsAdded.splice( courseIdsNewSelected.indexOf( courseId ), 1 );
200 elOrderDetails.querySelector( '.order-subtotal' ).innerHTML = order_data.subtotal_html;
201 elOrderDetails.querySelector( '.order-total' ).innerHTML = order_data.total_html;
202 },
203 error( err ) {
204 console.error( err );
205 },
206 completed() {
207
208 },
209 };
210 Utils.lpFetchAPI( Utils.lpAddQueryArgs( Utils.lpGetCurrentURLNoParam(), dataSend ), {}, callBack );
211 };
212
213 /**
214 * Search courses before add Order.
215 *
216 * @param e
217 * @param target
218 */
219 const searchCourse = ( e, target ) => {
220 if ( 'search' !== target.name ) {
221 return;
222 }
223
224 const elLPTarget = target.closest( idModalSearchItems );
225 if ( ! elLPTarget ) {
226 return;
227 }
228
229 e.preventDefault();
230 const keyword = target.value;
231
232 if ( ! keyword || ( keyword && keyword.length > 2 ) ) {
233 if ( undefined !== timeOutSearch ) {
234 clearTimeout( timeOutSearch );
235 }
236
237 timeOutSearch = setTimeout( function() {
238 fetchCoursesAPI( keyword, courseIdsAdded, 1 );
239 }, 800 );
240 }
241 };
242
243 /**
244 * Display list courses when search done.
245 *
246 * @param courses
247 */
248 const renderSearchResult = ( courses ) => {
249 let html = '';
250
251 courses.forEach( ( course ) => {
252 const courseId = parseInt( course.ID );
253 const checked = courseIdsNewSelected.includes( courseId ) ? 'checked' : '';
254
255 html += `
256 <li class="lp-result-item" data-id="${ courseId }" data-type="lp_course" data-text="${ course.post_title }">
257 <label>
258 <input type="checkbox" value="${ courseId }" name="selectedItems[]" ${ checked }>
259 <span class="lp-item-text">${ course.post_title } (#${ courseId })</span>
260 </label>
261 </li>`;
262 } );
263
264 return html;
265 };
266
267 /**
268 * Render pagination.
269 *
270 * @param currentPage
271 * @param maxPage
272 */
273 const renderPagination = ( currentPage, maxPage ) => {
274 currentPage = parseInt( currentPage );
275 maxPage = parseInt( maxPage );
276
277 let html = '';
278 if ( maxPage <= 1 ) {
279 return html;
280 }
281 const nextPage = currentPage + 1;
282 const prevPage = currentPage - 1;
283
284 let pages = [];
285
286 if ( maxPage <= 9 ) {
287 for ( let i = 1; i <= maxPage; i++ ) {
288 pages.push( i );
289 }
290 } else if ( currentPage <= 3 ) {
291 // x is ...
292 pages = [ 1, 2, 3, 4, 5, 'x', maxPage ];
293 } else if ( currentPage <= 5 ) {
294 for ( let i = 1; i <= currentPage; i++ ) {
295 pages.push( i );
296 }
297 for ( let j = 1; j <= 2; j++ ) {
298 const tempPage = currentPage + j;
299 pages.push( tempPage );
300 }
301 pages.push( 'x' );
302 pages.push( maxPage );
303 } else {
304 pages = [ 1, 'x' ];
305
306 for ( let k = 2; k >= 0; k-- ) {
307 const tempPage = currentPage - k;
308 pages.push( tempPage );
309 }
310
311 const currentToLast = maxPage - currentPage;
312
313 if ( currentToLast <= 5 ) {
314 for ( let m = currentPage + 1; m <= maxPage; m++
315 ) {
316 pages.push( m );
317 }
318 } else {
319 for ( let n = 1; n <= 2; n++ ) {
320 const tempPage = currentPage + n;
321 pages.push( tempPage );
322 }
323 pages.push( 'x' );
324 pages.push( maxPage );
325 }
326 }
327
328 const maximum = pages.length;
329
330 if ( currentPage !== 1 ) {
331 html += `<a class="prev page-numbers button" href="#" data-page="${ prevPage }"><</a>`;
332 }
333 for ( let i = 0; i < maximum; i++ ) {
334 if ( currentPage === parseInt( pages[ i ] ) ) {
335 html += `<a aria-current="page" class="page-numbers current button disabled" data-page="${ pages[ i ] }">
336 ${ pages[ i ] }
337 </a>`;
338 } else if ( pages[ i ] === 'x' ) {
339 html += `<span class="page-numbers dots button disabled">...</span>`;
340 } else {
341 html += `<a class="page-numbers button" href="#" data-page="${ pages[ i ] }">${ pages[ i ] } </a>`;
342 }
343 }
344
345 if ( currentPage !== maxPage ) {
346 html += `<a class="next page-numbers button" href="#" data-page="${ nextPage }">></a>`;
347 }
348
349 return html;
350 };
351
352 const showPopupSearchCourses = () => {
353 getCoursesAdded();
354 modalContainer.style.display = 'block';
355 elOrderModalBtnAdd.style.display = 'none';
356 elSearchCoursesResult.innerHTML = '';
357 fetchCoursesAPI( dataSend.search, courseIdsAdded, dataSend.paged );
358 };
359
360 // Events.
361 document.addEventListener( 'click', ( e ) => {
362 const target = e.target;
363 //console.dir( target );
364 if ( target.id === 'learn-press-add-order-item' ) {
365 e.preventDefault();
366 showPopupSearchCourses();
367 }
368
369 if ( target.classList.contains( 'close' ) && target.closest( idModalSearchItems ) ) {
370 e.preventDefault();
371 elModalSearchCourses.querySelector( 'input[name="search"]' ).value = '';
372 dataSend.search = '';
373 dataSend.paged = 1;
374 modalContainer.style.display = 'none';
375 }
376
377 if ( target.classList.contains( 'page-numbers' ) ) {
378 if ( target.closest( idModalSearchItems ) ) {
379 e.preventDefault();
380 const paged = target.getAttribute( 'data-page' );
381 fetchCoursesAPI( dataSend.search, dataSend.id_not_in, paged );
382 }
383 }
384
385 if ( target.name === 'selectedItems[]' ) {
386 if ( target.closest( idModalSearchItems ) ) {
387 const courseId = parseInt( target.value );
388 if ( target.checked ) {
389 courseIdsNewSelected.push( courseId );
390 } else {
391 const index = courseIdsNewSelected.indexOf( courseId );
392 if ( index > -1 ) {
393 courseIdsNewSelected.splice( index, 1 );
394 }
395 }
396
397 elOrderModalBtnAdd.style.display = courseIdsNewSelected.length > 0 ? 'block' : 'none';
398 }
399 }
400
401 addCourses( e, target );
402 removeCourse( e, target );
403 } );
404 document.addEventListener( 'keyup', function( e ) {
405 const target = e.target;
406
407 searchCourse( e, target );
408 } );
409
410 lpUtils.lpOnElementReady( '.lp-order-detail-items', ( el ) => {
411 getAllElements();
412 if ( ! elOrderDetails ) {
413 return;
414 }
415 modalContainer.innerHTML = modalSearchItemsTemplate.innerHTML;
416 elModalSearchCourses = modalContainer.querySelector( idModalSearchItems );
417 elSearchCoursesResult = elModalSearchCourses.querySelector( '.search-results' );
418 elOrderModalFooter = elModalSearchCourses.querySelector( 'footer' );
419 elOrderModalBtnAdd = elOrderModalFooter.querySelector( '.add' );
420 modalContainer.style.display = 'none';
421 } );
422 };
423
424 export default addCoursesToOrder;
425