Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

app-ecommerce-referral.js 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /**
  2. * Page eCommerce Referral
  3. */
  4. 'use strict';
  5. // Datatable (js)
  6. document.addEventListener('DOMContentLoaded', function (e) {
  7. let borderColor, bodyBg, headingColor;
  8. borderColor = config.colors.borderColor;
  9. bodyBg = config.colors.bodyBg;
  10. headingColor = config.colors.headingColor;
  11. // Variable declaration for table
  12. const dt_user_table = document.querySelector('.datatables-referral'),
  13. customerView = baseUrl + 'app/ecommerce/customer/details/overview',
  14. statusObj = {
  15. 1: { title: 'Paid', class: 'bg-label-success' },
  16. 2: { title: 'Unpaid', class: 'bg-label-warning' },
  17. 3: { title: 'Rejected', class: 'bg-label-danger' }
  18. };
  19. // Users datatable
  20. if (dt_user_table) {
  21. let tableTitle = document.createElement('h5');
  22. tableTitle.classList.add('card-title', 'mb-0', 'text-md-start', 'text-center');
  23. tableTitle.innerHTML = 'Referred users';
  24. var dt_user = new DataTable(dt_user_table, {
  25. ajax: assetsPath + 'json/ecommerce-referral.json', // JSON file to add data
  26. columns: [
  27. // columns according to JSON
  28. { data: 'id' },
  29. { data: 'id', orderable: false, render: DataTable.render.select() },
  30. { data: 'user' },
  31. { data: 'referred_id' },
  32. { data: 'status' },
  33. { data: 'value' },
  34. { data: 'earning' }
  35. ],
  36. columnDefs: [
  37. {
  38. // For Responsive
  39. className: 'control',
  40. searchable: false,
  41. orderable: false,
  42. responsivePriority: 2,
  43. targets: 0,
  44. render: function (data, type, full, meta) {
  45. return '';
  46. }
  47. },
  48. {
  49. // For Checkboxes
  50. targets: 1,
  51. orderable: false,
  52. searchable: false,
  53. responsivePriority: 3,
  54. checkboxes: true,
  55. render: function () {
  56. return '<input type="checkbox" class="dt-checkboxes form-check-input">';
  57. },
  58. checkboxes: {
  59. selectAllRender: '<input type="checkbox" class="form-check-input">'
  60. }
  61. },
  62. {
  63. // eCommerce full name and email
  64. targets: 2,
  65. responsivePriority: 1,
  66. render: function (data, type, full, meta) {
  67. const userName = full['user'];
  68. const email = full['email'];
  69. const avatar = full['avatar'];
  70. let output;
  71. if (avatar) {
  72. // For Avatar image
  73. output = `<img src="${assetsPath}img/avatars/${avatar}" alt="Avatar" class="rounded-circle">`;
  74. } else {
  75. // For Avatar badge
  76. const stateNum = Math.floor(Math.random() * 6);
  77. const states = ['success', 'danger', 'warning', 'info', 'dark', 'primary', 'secondary'];
  78. const state = states[stateNum];
  79. const initials = (userName.match(/\b\w/g) || []).slice(0, 2).join('').toUpperCase();
  80. output = `<span class="avatar-initial rounded-circle bg-label-${state}">${initials}</span>`;
  81. }
  82. // Creates full output for row
  83. const rowOutput = `
  84. <div class="d-flex justify-content-start align-items-center customer-name">
  85. <div class="avatar-wrapper">
  86. <div class="avatar avatar-sm me-4">${output}</div>
  87. </div>
  88. <div class="d-flex flex-column">
  89. <a href="${customerView}" class="text-heading"><span class="fw-medium">${userName}</span></a>
  90. <small class="text-nowrap">${email}</small>
  91. </div>
  92. </div>`;
  93. return rowOutput;
  94. }
  95. },
  96. {
  97. // eCommerce Role
  98. targets: 3,
  99. render: function (data, type, full, meta) {
  100. let role = full['referred_id'];
  101. return '<span>' + role + '</span>';
  102. }
  103. },
  104. {
  105. // eCommerce Status
  106. targets: 4,
  107. render: function (data, type, full, meta) {
  108. let status = full['status'];
  109. return (
  110. '<span class="badge ' +
  111. statusObj[status].class +
  112. '" text-capitalized>' +
  113. statusObj[status].title +
  114. '</span>'
  115. );
  116. }
  117. },
  118. {
  119. // value
  120. targets: 5,
  121. render: function (data, type, full, meta) {
  122. let plan = full['value'];
  123. return '<span>' + plan + '</span>';
  124. }
  125. },
  126. {
  127. // earning
  128. targets: 6,
  129. render: function (data, type, full, meta) {
  130. let earn = full['earning'];
  131. return '<span class="text-heading">' + earn + '</span > ';
  132. }
  133. }
  134. ],
  135. select: {
  136. style: 'multi',
  137. selector: 'td:nth-child(2)'
  138. },
  139. order: [[2, 'asc']],
  140. layout: {
  141. topStart: {
  142. rowClass: 'row m-3 my-0 justify-content-between',
  143. features: [tableTitle]
  144. },
  145. topEnd: {
  146. features: [
  147. {
  148. pageLength: {
  149. menu: [10, 25, 50, 100],
  150. text: '_MENU_'
  151. }
  152. },
  153. {
  154. buttons: [
  155. {
  156. extend: 'collection',
  157. className: 'btn btn-label-primary dropdown-toggle me-4',
  158. text: '<span class="d-flex align-items-center gap-2"><i class="icon-base bx bx-export me-sm-1"></i> <span class="d-none d-sm-inline-block">Export</span></span>',
  159. buttons: [
  160. {
  161. extend: 'print',
  162. text: `<span class="d-flex align-items-center"><i class="icon-base bx bx-printer me-1"></i>Print</span>`,
  163. className: 'dropdown-item',
  164. exportOptions: {
  165. columns: [2, 3, 4, 5, 6],
  166. format: {
  167. body: function (inner, coldex, rowdex) {
  168. if (inner.length <= 0) return inner;
  169. // Check if inner is HTML content
  170. if (inner.indexOf('<') > -1) {
  171. const parser = new DOMParser();
  172. const doc = parser.parseFromString(inner, 'text/html');
  173. // Get all text content
  174. let text = '';
  175. // Handle specific elements
  176. const userNameElements = doc.querySelectorAll('.customer-name');
  177. if (userNameElements.length > 0) {
  178. userNameElements.forEach(el => {
  179. // Get text from nested structure
  180. const nameText =
  181. el.querySelector('.fw-medium')?.textContent ||
  182. el.querySelector('.d-block')?.textContent ||
  183. el.textContent;
  184. text += nameText.trim() + ' ';
  185. });
  186. } else {
  187. // Get regular text content
  188. text = doc.body.textContent || doc.body.innerText;
  189. }
  190. return text.trim();
  191. }
  192. return inner;
  193. }
  194. }
  195. },
  196. customize: function (win) {
  197. win.document.body.style.color = config.colors.headingColor;
  198. win.document.body.style.borderColor = config.colors.borderColor;
  199. win.document.body.style.backgroundColor = config.colors.bodyBg;
  200. const table = win.document.body.querySelector('table');
  201. table.classList.add('compact');
  202. table.style.color = 'inherit';
  203. table.style.borderColor = 'inherit';
  204. table.style.backgroundColor = 'inherit';
  205. }
  206. },
  207. {
  208. extend: 'csv',
  209. text: `<span class="d-flex align-items-center"><i class="icon-base bx bx-file me-1"></i>Csv</span>`,
  210. className: 'dropdown-item',
  211. exportOptions: {
  212. columns: [2, 3, 4, 5, 6],
  213. format: {
  214. body: function (inner, coldex, rowdex) {
  215. if (inner.length <= 0) return inner;
  216. // Parse HTML content
  217. const parser = new DOMParser();
  218. const doc = parser.parseFromString(inner, 'text/html');
  219. let text = '';
  220. // Handle customer-name elements specifically
  221. const userNameElements = doc.querySelectorAll('.customer-name');
  222. if (userNameElements.length > 0) {
  223. userNameElements.forEach(el => {
  224. // Get text from nested structure - try different selectors
  225. const nameText =
  226. el.querySelector('.fw-medium')?.textContent ||
  227. el.querySelector('.d-block')?.textContent ||
  228. el.textContent;
  229. text += nameText.trim() + ' ';
  230. });
  231. } else {
  232. // Handle other elements (status, role, etc)
  233. text = doc.body.textContent || doc.body.innerText;
  234. }
  235. return text.trim();
  236. }
  237. }
  238. }
  239. },
  240. {
  241. extend: 'excel',
  242. text: `<span class="d-flex align-items-center"><i class="icon-base bx bxs-file-export me-1"></i>Excel</span>`,
  243. className: 'dropdown-item',
  244. exportOptions: {
  245. columns: [2, 3, 4, 5, 6],
  246. format: {
  247. body: function (inner, coldex, rowdex) {
  248. if (inner.length <= 0) return inner;
  249. // Parse HTML content
  250. const parser = new DOMParser();
  251. const doc = parser.parseFromString(inner, 'text/html');
  252. let text = '';
  253. // Handle customer-name elements specifically
  254. const userNameElements = doc.querySelectorAll('.customer-name');
  255. if (userNameElements.length > 0) {
  256. userNameElements.forEach(el => {
  257. // Get text from nested structure - try different selectors
  258. const nameText =
  259. el.querySelector('.fw-medium')?.textContent ||
  260. el.querySelector('.d-block')?.textContent ||
  261. el.textContent;
  262. text += nameText.trim() + ' ';
  263. });
  264. } else {
  265. // Handle other elements (status, role, etc)
  266. text = doc.body.textContent || doc.body.innerText;
  267. }
  268. return text.trim();
  269. }
  270. }
  271. }
  272. },
  273. {
  274. extend: 'pdf',
  275. text: `<span class="d-flex align-items-center"><i class="icon-base bx bxs-file-pdf me-1"></i>Pdf</span>`,
  276. className: 'dropdown-item',
  277. exportOptions: {
  278. columns: [2, 3, 4, 5, 6],
  279. format: {
  280. body: function (inner, coldex, rowdex) {
  281. if (inner.length <= 0) return inner;
  282. // Parse HTML content
  283. const parser = new DOMParser();
  284. const doc = parser.parseFromString(inner, 'text/html');
  285. let text = '';
  286. // Handle customer-name elements specifically
  287. const userNameElements = doc.querySelectorAll('.customer-name');
  288. if (userNameElements.length > 0) {
  289. userNameElements.forEach(el => {
  290. // Get text from nested structure - try different selectors
  291. const nameText =
  292. el.querySelector('.fw-medium')?.textContent ||
  293. el.querySelector('.d-block')?.textContent ||
  294. el.textContent;
  295. text += nameText.trim() + ' ';
  296. });
  297. } else {
  298. // Handle other elements (status, role, etc)
  299. text = doc.body.textContent || doc.body.innerText;
  300. }
  301. return text.trim();
  302. }
  303. }
  304. }
  305. },
  306. {
  307. extend: 'copy',
  308. text: `<i class="icon-base bx bx-copy me-1"></i>Copy`,
  309. className: 'dropdown-item',
  310. exportOptions: {
  311. columns: [2, 3, 4, 5, 6],
  312. format: {
  313. body: function (inner, coldex, rowdex) {
  314. if (inner.length <= 0) return inner;
  315. // Parse HTML content
  316. const parser = new DOMParser();
  317. const doc = parser.parseFromString(inner, 'text/html');
  318. let text = '';
  319. // Handle customer-name elements specifically
  320. const userNameElements = doc.querySelectorAll('.customer-name');
  321. if (userNameElements.length > 0) {
  322. userNameElements.forEach(el => {
  323. // Get text from nested structure - try different selectors
  324. const nameText =
  325. el.querySelector('.fw-medium')?.textContent ||
  326. el.querySelector('.d-block')?.textContent ||
  327. el.textContent;
  328. text += nameText.trim() + ' ';
  329. });
  330. } else {
  331. // Handle other elements (status, role, etc)
  332. text = doc.body.textContent || doc.body.innerText;
  333. }
  334. return text.trim();
  335. }
  336. }
  337. }
  338. }
  339. ]
  340. }
  341. ]
  342. }
  343. ]
  344. },
  345. bottomStart: {
  346. rowClass: 'row mx-3 justify-content-between',
  347. features: ['info']
  348. },
  349. bottomEnd: 'paging'
  350. },
  351. language: {
  352. paginate: {
  353. next: '<i class="icon-base bx bx-chevron-right scaleX-n1-rtl icon-18px"></i>',
  354. previous: '<i class="icon-base bx bx-chevron-left scaleX-n1-rtl icon-18px"></i>',
  355. first: '<i class="icon-base bx bx-chevrons-left scaleX-n1-rtl icon-18px"></i>',
  356. last: '<i class="icon-base bx bx-chevrons-right scaleX-n1-rtl icon-18px"></i>'
  357. }
  358. },
  359. // For responsive popup
  360. responsive: {
  361. details: {
  362. display: DataTable.Responsive.display.modal({
  363. header: function (row) {
  364. const data = row.data();
  365. return 'Details of ' + data['user'];
  366. }
  367. }),
  368. type: 'column',
  369. renderer: function (api, rowIdx, columns) {
  370. const data = columns
  371. .map(function (col) {
  372. return col.title !== '' // Do not show row in modal popup if title is blank (for check box)
  373. ? `<tr data-dt-row="${col.rowIndex}" data-dt-column="${col.columnIndex}">
  374. <td>${col.title}:</td>
  375. <td>${col.data}</td>
  376. </tr>`
  377. : '';
  378. })
  379. .join('');
  380. if (data) {
  381. const div = document.createElement('div');
  382. div.classList.add('table-responsive');
  383. const table = document.createElement('table');
  384. div.appendChild(table);
  385. table.classList.add('table');
  386. const tbody = document.createElement('tbody');
  387. tbody.innerHTML = data;
  388. table.appendChild(tbody);
  389. return div;
  390. }
  391. return false;
  392. }
  393. }
  394. }
  395. });
  396. }
  397. // Filter form control to default size
  398. // ? setTimeout used for referral table initialization
  399. setTimeout(() => {
  400. const elementsToModify = [
  401. { selector: '.dt-buttons .btn', classToRemove: 'btn-secondary', classToAdd: 'btn-label-secondary' },
  402. { selector: '.dt-search .form-control', classToRemove: 'form-control-sm' },
  403. { selector: '.dt-length .form-select', classToRemove: 'form-select-sm' },
  404. { selector: '.dt-length', classToAdd: 'me-2 ms-sm-n2 ms-0' },
  405. { selector: '.dt-buttons', classToAdd: 'mb-md-0 mb-6 justify-content-center' },
  406. { selector: '.dt-layout-table', classToRemove: 'row mt-2' },
  407. { selector: '.dt-layout-start', classToAdd: 'mt-md-0 mt-4 px-3' },
  408. { selector: '.dt-layout-end', classToAdd: 'px-3 mt-0' },
  409. { selector: '.dt-layout-full', classToRemove: 'col-md col-12', classToAdd: 'table-responsive' }
  410. ];
  411. // Delete record
  412. elementsToModify.forEach(({ selector, classToRemove, classToAdd }) => {
  413. document.querySelectorAll(selector).forEach(element => {
  414. if (classToRemove) {
  415. classToRemove.split(' ').forEach(className => element.classList.remove(className));
  416. }
  417. if (classToAdd) {
  418. classToAdd.split(' ').forEach(className => element.classList.add(className));
  419. }
  420. });
  421. });
  422. }, 100);
  423. });