Cisco Meraki MR28 1.5 Mbit/s White Power over Ethernet (PoE)

Dual–radio aggregate frame rate of up to 1.5 Gbps5 GHz 2x2:2 radio and 2.4 GHz 2x2:2 radio offer a combined dual–radio aggregate frame rate of 1.5 Gbps*, with up to 1,201 Mbps in the 5 GHz band and 286 Mbps in the 2.4 GHz band. Technologies like transmit beamforming and enhanced receive sensitivity allow the MR28 to support a higher client density than typical enterprise-class access points, resulting in better performance for more clients, from each AP.Multi-User Multiple Input Multiple Output (MU-MIMO)With support for features of 802.11ax, the MR28 offers MU-MIMO and UL/DL OFDMA for more efficient transmission to multiple clients. Especially suited to environments with numerous mobile devices, MU-MIMO enables multiple clients to receive data simultaneously. This increases the total network performance and improves the end-user experience.Automatic cloud-based RF optimizationThe MR28’s sophisticated and automated RF optimization means that there is no need for the dedicated hardware and RF expertise typically required to tune a wireless network. Collected RF data is continuously fed back to the Meraki cloud. This data is then used to automatically tune the channel selection, transmit power, and client connection settings for optimal performance under even the most challenging RF conditions.Integrated enterprise security and guest accessThe MR28 features integrated, easy-to-use security technologies to provide secure connectivity for employees and guests alike. Advanced security features such as AES hardware-based encryption and Enterprise authentication with 802.1X and Active Directory integration provide wired-like security while still being easy to configure. One-click guest isolation provides secure, Internet-only access for visitors. PCI compliance reports check network settings against PCI requirements to simplify secure retail deployments.Enterprise Mobility Management (EMM) & Mobile Device Management (MDM) integrationMeraki Systems Manager natively integrates with the MR28 to offer automatic, context-aware security. Systems Manager’s self-service enrollment helps to rapidly deploy MDM without installing additional equipment, and then dynamically tie firewall and traffic shaping policies to client posture.Application-aware traffic shapingThe MR28 includes an integrated layer 7 packet inspection, classification, and control engine, enabling the configuration of QoS policies based on traffic type, helping to prioritize mission-critical applications while setting limits on recreational traffic like peer-to-peer and video streaming. Policies can be implemented per network, per SSID, per user group, or per individual user for maximum flexibility and control.Voice and video optimizationsIndustry standard QoS features are built-in and easy to configure. Wireless MultiMedia (WMM) access categories, 802.1p, and DSCP standards all ensure important applications get prioritized correctly, not only on the MR28 but on other devices in the network. Unscheduled Automatic Power Save Delivery (U-APSD) and new Target Wait Time features in 802.11ax clients ensure minimal battery drain on wireless VoIP phones.Self-configuring, self-maintaining, always up-to-dateWhen plugged in, the MR28 automatically connects to the Meraki cloud, downloads its configuration, and joins the appropriate network. If new firmware is required, this is retrieved by the AP and updated automatically. This ensures the network is kept up-to-date with bug fixes, security updates, and new features.Advanced analyticsDrilling down into the details of network usage provides highly granular traffic analytics. Visibility into the physical world can be enhanced with journey tracking through location analytics. Visitor numbers, dwell time, repeat visit rates, and track trends can all be easily monitored in the dashboard and deeper analysis is enabled with raw data available via simple APIs.Bluetooth Low Energy Beacon and scanning radioAn integrated Bluetooth radio provides seamless deployment of BLE Beacon functionality and effortless visibility of Bluetooth devices.

ON ORDER

RRP Price €378.76

Specifications

Features

2.4 GHz
Yes
5 GHz
Yes
6 GHz
No
Maximum data transfer rate
1.5 Mbit/s
Ethernet LAN data rates
10,1000 Mbit/s
Networking standards
IEEE 802.11a, IEEE 802.11ac, IEEE 802.11ax, IEEE 802.11b, IEEE 802.11e, IEEE 802.11g, IEEE 802.11h, IEEE 802.11i, IEEE 802.11k, IEEE 802.11n, IEEE 802.11r, IEEE 802.11u
Bluetooth
Yes
Bluetooth version
5.0
Bluetooth Low Energy (BLE)
Yes
MIMO
Yes
MIMO type
Multi User MIMO
Spread spectrum method
OFDMA
Wi-Fi Multimedia (WMM)/(WME)
Yes
Wi-Fi roaming
Yes
Fast roaming
Yes
VLAN support
Yes
Virtual LAN features
Tagged VLAN
Wireless isolation
Yes
Maximal-Ratio Combining (MRC)
Yes
Quality of Service (QoS) support
Yes
BeamForming
Yes

Security

Security algorithms
AES, EAP-SIM, EAP-TLS, EAP-TTLS, TKIP, WEP, WPA, WPA2-Enterprise, WPA2-PSK, WPA3, WPA3-Enterprise

Management features

Firmware upgradeable
Yes

Ports & interfaces

Ethernet LAN (RJ-45) ports
1
DC-in jack
Yes

Power

Power over Ethernet (PoE)
Yes
AC input voltage
37 - 57 V
DC voltage range
12 V
Power consumption (typical)
15 W

Design

Product colour
White
LED indicators
Power, Yes

Antenna

Antenna type
Internal
Antenna gain level (max)
6 dBi

Certificates

Compliance certificates
RoHS

Weight & dimensions

Width
124 mm
Depth
25.8 mm
Height
202 mm
Weight
272 g

Packaging content

AC adapter included
Yes

Operational conditions

Operating relative humidity (H-H)
5 - 95%
Operating temperature (T-T)
0 - 40 °C
Operating altitude
0 - 12192 m

Accessories

License

Related Products

Copyright © 2025 Yot Ltd. All rights reserved.
  Notification
Unread - 0
Loading ...
Partially Shipped / Shipped
Pending
`; }, error: function(error) { console.error("Error by activity: ", error); activity = '
Failed to load activity
'; }, complete: function() { // Always update the DOM, hide the loader $('#activitySection').empty().append(activity); } }); // Create table dynamically let total = 0; let tableRows = ''; const subtableKey = '_subtable_1002708'; const subTableDetail = details[subtableKey]; let status = ''; if (details[Status] === 'Paid') { status = `Paid`; } else if (details[Status] == 'Sent') { status = `Sent`; } else if (details[Status] == 'Overdue') { status = `Overdue`; } else if (details[Status] == 'Draft') { status = `Draft`; } else if (details[Status] == 'Partially Paid' || details[Status] == 'Partially_paid') { status = `Partially Paid`; } else { status = `N/A`; } // order Item for (const key in subTableDetail) { if (subTableDetail.hasOwnProperty(key)) { const detail = subTableDetail[key]; total += Number(detail[Price]); tableRows += `
${detail[LineItemSKU] || 'N/A'}
${detail[Description].substring(0,20) + '...' || 'N/A'}
${currency}${numberFormat(detail[Price]) || 'N/A'}
Qty : ${detail[QTY] || 'N/A'}
`; } } // Quote Detail const quoteDetaiTab = `
Account Name
${details[AccountName] || 'N/A'}
Quote Number
${details[QuoteNumber] || 'N/A'}
PI Number
${details[PINumber] || 'N/A'}
Invoice Number
${details[InvoiceNumber] || 'N/A'}
Status
${status}
Invoice Link
Total
${currency}${numberFormat(details[Total]) || 'N/A'}
Balance Left
${currency}${details[BalanceLeft] || 'N/A'}
`; $('#invoiceDetailTab').empty(); $('#invoiceDetailTab').append(quoteDetaiTab); // Quote Id const inoviceId = `
# ${details[InvoiceNumber] || 'N/A'}
`; $('#invoiceId').empty(); $('#invoiceId').append(inoviceId); return `${tableRows}`; } function generateLineItemsSubtableSubscription(details) { // Define the field names based on the listing type const SubscriptionID = "1002696"; const InvoiceID = "1003087"; const EndCustomer = "1001910"; const DaysRemaining = "1001915"; const NextRenewal = "1001909"; const Status = "2002461"; const Total = "1001923"; const LineItemSKU = "1001916"; const Description = "1001917"; const QTY = "1001918"; const Price = "1001959"; const SerialNumber = "1001919"; const AccountManager = "1001926"; const PaymentType = "1001905"; const ActicationDate = "1001911"; const Account = "2002456"; const BillingCycle = "2002459"; const NextRenewalDate = "1001909"; const StartDate = "1001904"; const NextRenewalEUR = "1002941"; const HardwareNumber = "1001908"; const Manufacturer = "1002758"; const License = "1001906"; const Date = "1001914"; const currency = ""; // Create table dynamically let total = 0; let tableRows = ''; const subtableKey = '_subtable_1001920'; const subTableDetail = details[subtableKey]; let status = ''; if (details[Status] === 'Active') { status = `Active`; } else if (details[Status] == 'Expired') { status = `Expired`; } else if (details[Status] == 'Canceled') { status = `Canceled`; } else if (details[Status] == 'Other') { status = `Other`; } else { status = `N/A`; } // order Item for (const key in subTableDetail) { if (subTableDetail.hasOwnProperty(key)) { const detail = subTableDetail[key]; total += Number(detail[Price]); SerialNoArr = subTableDetail[key][SerialNumber].split(", "); let lastCol = ``; SerialNoArr.forEach((code) => { if (code.length > 0) { lastCol += `${code}`; } }); licenseUrl = ''; if ((details[License] == "")) { licenseUrl = `
N/A
`; } else if (Array.isArray(details[License])) { details[License].forEach((file) => { if(file != ''){ licenseUrl += `
Download
`; } }); } else { licenseUrl = `
Download
` } tableRows += `
${detail[LineItemSKU] || 'N/A'}
${detail[Description].substring(0,20) + '...' || 'N/A'}
${currency}${numberFormat(detail[Price]) || 'N/A'}
Qty : ${detail[QTY] || 'N/A'}
${lastCol || '
N/A
'}
`; } } // Quote Detail const quoteDetaiTab = `
Account Name
${details[Account] || 'N/A'}
End Customer
${details[EndCustomer] || 'N/A'}
Account Manager
${details[AccountManager] || 'N/A'}
Payment Method
${details[PaymentType] || 'N/A'}
Date
${changeDateFormat(details[Date]) || 'N/A'}
Activation Date
${changeDateFormat(details[ActicationDate]) || 'N/A'}
Start Date
${changeDateFormat(details[StartDate]) || 'N/A'}
Next Renewal Date
${changeDateFormat(details[NextRenewalDate]) || 'N/A'}
Hardware Number
${details[HardwareNumber] || 'N/A'}
Manufacturer
${details[Manufacturer] || 'N/A'}
License
${licenseUrl}
Next Renewal
${details[NextRenewal] || 'N/A'}
Billing Cycle
${details[BillingCycle] || 'N/A'}
Total
${currency}${numberFormat(details[Total]) || 'N/A'}
Status
${status}
Remaining Days
${details[DaysRemaining] || 'N/A'} Days
Total Payable Amount via early renewal:
${details[Total] ? currency+ numberFormat(details[Total]) : 'N/A'}

Renewal
`; $('#subscriptionDetailTab').empty(); $('#subscriptionDetailTab').append(quoteDetaiTab); // Quote Id const subscriptionId = `
# ${details[SubscriptionID] || 'N/A'}
`; $('#subscriptionId').empty(); $('#subscriptionId').append(subscriptionId); const inoviceId = `
# ${details[InvoiceID] || 'N/A'}
`; $('#invoiceId').empty(); $('#invoiceId').append(inoviceId); return `${tableRows}`; } function generateLineItemsSubtableOrder(details) { // Define the field names based on the listing type const status1 = "1002945"; const PINumber = "1001874"; const QuoteReference = "1001890"; const TrackingtoClient = "1001953"; const CreationTime = "1002788"; const statusNotes = "1001881"; const client = "1001864"; const Invoiced = "1002942"; const Payment = "1002943"; const Shipping = "1002945"; // Line item const LineItemSKU = "1002005"; const QTY = "1002006"; const Price = "1002036"; const lastCol = "1002008"; const Tracking = "1001953"; const trackingUrl = details[Tracking]; const currency = ""; // Create table dynamically let tableRows = ''; const subtableKey = '_subtable_1002011'; const subTableDetail = details[subtableKey]; let status = ''; if (details[status1] === 'Fulfilled') { status = `Fulfilled`; } else if (details[status1] === 'Pending') { status = `Pending`; } else if (details[status1] === 'Shipped') { status = `Shipped`; } else if (details[status1] === 'Partially Shipped') { status = `Partially Shipped`; } else if (details[status1] === 'In Stock') { status = `In Stock`; } else if (details[status1] === 'On the way') { status = `On the way`; } else if (details[status1] === 'Canceled' || details[status1] === 'Cancelled') { status = `Cancelled`; } else if (details[status1] === 'Ordered') { status = `Ordered`; } else { status = `N/A`; } let activity = ''; if (trackingUrl) { let trackingNumber = trackingUrl.match(/\/(\d+)$/)[1]; $.ajax({ url: `https://username.aftership.com/trpc/trackings.getTrackingWithTrackingNumber?batch=1&input={"0":{"organization_id":"ed77e860f10b4ac4830e00ff235cf72a","tracking_number":"${trackingNumber}","translate_to":"en"}}`, method: "GET", beforeSend: function() { $('#activitySection').empty().append('
'); }, success: function(response) { if (Object.keys(response[0].result.data).length == 0) { $('#activitySection').empty().append('
Not Found!
'); return; } const checkpoints = response[0].result.data.tracking.checkpoints; const reversedCheckpoints = checkpoints.reverse(); reversedCheckpoints.forEach((checkpoint) => { activity += `
${checkpoint.status || 'Status Unknown'}
${checkpoint.message || 'No message available'}

${checkpoint.location || checkpoint.city || checkpoint.country || 'Location Unknown'}

${new Date(checkpoint.checkpoint_time).toLocaleString() || 'Time Unknown'}
`; }); $('#activitySection').empty().append(activity); // Now `activity` contains the HTML string for each checkpoint // document.getElementById('activityContainer').innerHTML = activity; }, error: function(error) { console.error("Error: ", error); activity = '
Failed to load activity
'; }, complete: function() { // Always update the DOM, hide the loader $('#activitySection').empty().append(activity); } }); } else { activity = `
${details[status1]}
`; $('#activitySection').empty().append(activity); } // order Item for (const key in subTableDetail) { if (subTableDetail.hasOwnProperty(key)) { const detail = subTableDetail[key]; tableRows += `
${detail[LineItemSKU] || 'N/A'}
Lead Time : ${changeDateFormat(detail[lastCol]) || 'N/A'}
${currency}${numberFormat(detail[Price]) || 'N/A'}
Qty : ${detail[QTY] || 'N/A'}
`; } } // Quote Detail const quoteDetaiTab = `
Account Name
${details[client] || 'N/A'}
Quote Reference
${details[QuoteReference] || 'N/A'}
Invoiced
${details[Invoiced] || 'N/A'}
Payment
${details[Payment] || 'N/A'}
Shipping
${details[Shipping] || 'N/A'}
Status
${status}
Tracking To Client
${details[TrackingtoClient] ? `
Tracking link
` : `
N/A
` }
`; $('#orderDetailTab').empty(); $('#orderDetailTab').append(quoteDetaiTab); // Quote Id const orderId = `
# ${details[PINumber] || 'N/A'}
`; $('#orderId').empty(); $('#orderId').append(orderId); $('#invoiceId').empty(); $('.InvoiceIdParentDiv').addClass('d-none'); let invoiceId = 'N/A'; let filteredInvoiceID = '' if (details[Invoiced] === 'Invoiced') { $('.InvoiceIdParentDiv').removeClass('d-none'); if (details['invoice_id']) { invoiceId = '# ' + details['invoice_id']; filteredInvoiceID = details['invoice_id']; } // Build the invoice page URL. let invoiceIdHtml = ''; if (invoiceId === 'N/A') { invoiceIdHtml = `
${invoiceId}
`; } else { const invoiceUrl = `https://www.fuse.systems/invoices?invoice=${filteredInvoiceID}`; invoiceIdHtml = `
${invoiceId}
`; } $('#invoiceId').empty(); $('#invoiceId').append(invoiceIdHtml); } return `${tableRows}`; } function sendRenewalMail(details) { if (!details) { console.log('Details are not available'); return; } // Show the loader $('#loader').removeClass('d-none'); $('#renewButton').addClass('d-none'); Swal.fire({ title: "Do you want to send request?", icon: "info", showCancelButton: true, confirmButtonText: "Yes", cancelButtonText: "Cancel", confirmButtonColor: "var(--PrimaryColor)", cancelButtonColor: "var(--Gray)", }).then((result) => { if (result.isConfirmed) { $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); let message = ""; let icon = ""; $.ajax({ url: '/send-renew-subcription-mail', method: 'POST', data: { renewalDetails: details }, success: function(response) { // Handle success response here // console.log('Renewal mail sent successfully!'); message = "Renewal request sent successfully!" icon = "success"; }, error: function(error) { // Handle error here console.error('Error sending renewal mail:', error); // console.log('Failed to send renewal mail.'); message = "Failed to send renewal request." icon = "warning"; }, complete: function() { Swal.fire({ title: message, icon: icon, confirmButtonText: "OK", confirmButtonColor: "var(--PrimaryColor)", cancelButtonColor: "var(--Gray)", }).then((result) => { $('#loader').addClass('d-none'); $('#renewButton').removeClass('d-none'); }) } }); } else { $('#loader').addClass('d-none'); $('#renewButton').removeClass('d-none'); } }); } function submitOrderContactForm() { // check validations var validationRes = orderContactValidations(); if (!validationRes) { return false; } $('#orderContactButton').addClass('d-none'); $('#orderContactButtonSpinner').removeClass('d-none'); var fname = $('#fname').val(); var lname = $('#lname').val(); var email = $('#ordContEmail').val(); var phone = $('#ordContPhone').val(); var product = $('#product').val(); var quantity = $('#quantity').val(); $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); $.ajax({ url: '/order-request', type: 'POST', dataType: 'json', data: { fname: fname, lname: lname, email: email, phone: phone, product: product, quantity: quantity, }, success: function(response) { // Handle success response if (response.success) { Swal.fire({ title: "Order created successfully!", icon: "success", confirmButtonColor: "#44d62c", }).then((result) => { window.location.reload(); }); } }, error: function(xhr) { // Handle error response console.log(xhr.responseText.error); }, complete: function() { $('#orderContactButton').removeClass('d-none'); $('#orderContactButtonSpinner').addClass('d-none'); } }); } $('#orderContactButton').click(function(e) { e.preventDefault(); submitOrderContactForm(); }); function orderContactValidations() { var is_error = 0; var fname = $('#fname').val(); if (fname.length < 3) { $('#fnameError').text('Please enter at least 3 characters.'); is_error = 1; } else { $('#fnameError').text(''); } var phone = $('#ordContPhone').val(); let phoneRegex = /^\d{9,}$/; if (phone.length < 9 || !phoneRegex.test(phone)) { $('#ordContPhoneError').text('Please enter a valid number.'); is_error = 1; } else { $('#ordContPhoneError').text(''); } var email = $('#ordContEmail').val(); var emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; if (!email.match(emailRegex)) { $('#ordContEmailError').text('Please enter a valid e-mail address.'); is_error = 1; } else { $('#ordContEmailError').text(''); } var product = $('#product').val(); if (product.length < 3) { $('#productError').text('Please enter a product SKU.'); is_error = 1; } else { $('#productError').text(''); } if (is_error) { return false; } return true; } // Function to fetch notifications from the API function loadNotifications() { $.ajax({ url: '/notifications', method: 'GET', dataType: 'json', success: function(data) { let notificationList = $('#notificationListNew'); notificationList.empty(); let noti = ''; // Check if data is an array and has items let count = 0; let allCount = 0; if (Array.isArray(data) && data.length > 0) { data.forEach(notification => { allCount++; if (notification.status === 'unread') { count++; } noti += `
${notification.notification_type}
${notification.message}
${formatDate(notification.created_at)}
`; }); } else { noti = `
No New Notification
`; } // Update the unread count if it exists in the response updateUnreadCount(count || 0, allCount || 0); // Append the generated notifications HTML to the list notificationList.append(noti); markNotificationsAsSeen(); }, error: function() { console.log('Failed to load notifications.'); } }); } // Function to update the unread message count function updateUnreadCount(count, allCount) { if (allCount == 0) { $('.unread-text').addClass('d-none'); } if (count > 0) { $('#notificationCount').text(count); $('#notificationCountIn').text(count); // Update the unread count display } else { $('#notificationCount').addClass('d-none'); $('#notificationCountIn').text(count); } } // Function to format date from the notification object function formatDate(date) { const options = { year: 'numeric', month: 'short', day: 'numeric' }; return new Date(date).toLocaleDateString('en-US', options); } $(document).on('click', '#read_all_btn', function(e) { markNotificationsAsClear(); }); // Function to mark notifications as seen function markNotificationsAsClear() { $.ajax({ url: '/notifications/mark-as-clear', method: 'POST', data: { _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { // Clear the notification list $('#notificationListNew').empty().append(`
No New Notification
`); updateUnreadCount(0, 0); // Set unread count to 0 // console.log(response.message); }, error: function() { console.log('Failed to mark notifications as read. Please try again.'); } }); } $(document).on('click', '#notificationBell', function(e) { loadNotifications(); }); $(document).on('click', '#notificationBellNew', function(e) { loadNotifications(); }); function markNotificationsAsSeen() { $.ajax({ url: '/notifications/mark-as-seen', method: 'POST', data: { _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { $('#notificationCount').addClass('d-none'); }, error: function() { console.log('Failed to mark notifications as read. Please try again.'); } }); } $(document).on('click', '#remove_single_notification', function(e) { markNotificationsAsClear(); }); function getNotificationCount() { if(session !== null){ $.ajax({ url: '/notifications/get-count', method: 'GET', success: function(response) { if (response.status && response.count > 0) { $('#notificationCount').removeClass('d-none'); $('#notificationCount').text(response.count); } }, error: function() { console.log('Failed to mark notifications as read. Please try again.'); } }); } } $(document).on('click', '#close-single-notification', function() { // Get the notification div const notificationDiv = $(this).closest('.notification_list'); const notificationId = notificationDiv.data('id'); $.ajax({ url: '/notification/delete-notification', method: 'POST', data: { id: notificationId, _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { if (response.success) { notificationDiv.animate({ marginLeft: '100%', opacity: 0 }, 500, function() { $(this).remove(); }); } else { // console.log('Could not delete the notification.'); } }, error: function() { // console.log('An error occurred while deleting the notification.'); } }); }); let debounceTimer; // Declare a variable to store the timer function debounceSearch(isUpdateValue = 1) { clearTimeout(debounceTimer); // Clear the previous timer if still running if (isUpdateValue) { const searchValue = document.getElementById('headerSearchInput').value; // const inputField = document.getElementById('headerSearchInput'); // if (searchValue !== inputField.value) { // inputField.value = searchValue; // } } // Set a new timer to wait for 300 milliseconds (or any other desired delay) debounceTimer = setTimeout(function() { getUniversalSearchData(); // Call the actual search function after delay }, 800); // Delay in milliseconds } function checkEnter(event) { // Check if the "Enter" key was pressed const inputField = document.getElementById('headerSearchInput'); const searchValue = document.getElementById('headerSearchInput').value; const baseUrl = "https://www.fuse.systems/search"; let url = new URL(window.location.href); let params = new URLSearchParams(url.search); // Set or update the "value" parameter params.set('value', searchValue); if (searchValue.length <= 0 && event.key === "Enter") { window.location.href = "https://www.fuse.systems/all-products"; } // Check if we are already on the product search page var isProductSearchPage = "false"; if (isProductSearchPage === "true") { // Update the URL without reloading the page window.history.replaceState({}, '', `${url.pathname}?${params.toString()}`); applyFilters(); // Call the filter function } else { // Redirect to search page with the updated query window.location.href = baseUrl + '?' + params.toString(); inputField.value = searchValue; } } // Ensure search input retains value after page reload document.addEventListener("DOMContentLoaded", function() { const inputField = document.getElementById('headerSearchInput'); let params = new URLSearchParams(window.location.search); let searchValue = params.get('value'); if (searchValue) { inputField.value = searchValue; } }); // Show loader function function showLoader() { $('#searchLoader').removeClass('d-none'); $('#universalSearchInput').attr('disabled'); } // Hide loader function function hideLoader() { $('#searchLoader').addClass('d-none'); $('#universalSearchInput').removeAttr('disabled'); } let isRequestInProgress = false; let currentController = null; // Variable to hold the current AbortController // Declare the main function as async to use await inside it async function getUniversalSearchData() { // Cancel the previous request if it's in progress if (isRequestInProgress) { currentController.abort(); // Abort the previous request } // Create a new AbortController for the new request currentController = new AbortController(); const signal = currentController.signal; isRequestInProgress = true; const searchValue = $('#universalSearchInput').val(); if (searchValue === "" || searchValue.length < 3) { $('#searchResultList').addClass('d-none'); isRequestInProgress = false; // Reset the request status return; } showLoader(); saveRecentSearch(searchValue); // Remove 'd-none' to show the search results $('#searchResultList').removeClass('d-none'); try { let response = await $.ajax({ url: '/get-search-data', type: 'GET', data: { search: searchValue, }, signal: signal // Attach the abort signal to the request }); // Proceed with processing the response if the request was not aborted if (isRequestInProgress) { hideLoader(); isRequestInProgress = false; const products = response.searchResult.products; const accessories = response.searchResult.accessories; const license = response.searchResult.license; const orders = response.orders; const invoices = response.invoices; const quotes = response.quotes; const subscription = response.subscription; if (response.searchCount > 10) { $('#viewMoreSearchBtn').removeClass('d-none'); const viewMore = document.getElementById('viewMoreSearchUrl'); // Generate the URL with the search input value as a query parameter const baseUrl = "https://www.fuse.systems/search"; const searchParam = searchValue ? `?value=${encodeURIComponent(searchValue)}` : ''; // Update the href attribute of the View More button viewMore.href = baseUrl + searchParam; } else { $('#viewMoreSearchBtn').addClass('d-none'); } // Clear previous search results $('#product_search_list').empty(); $('#accessories_search_list').empty(); $('#license_search_list').empty(); $('#order_search_list').empty(); $('#invoice_search_list').empty(); $('#subscription_search_list').empty(); $('#quote_search_list').empty(); $('#category_list').empty(); $('#searhNoData').empty(); $('#product_list_searched').addClass('d-none'); $('#order_list_searched').addClass('d-none'); $('#invoice_list_searched').addClass('d-none'); $('#subscription_list_searched').addClass('d-none'); $('#quote_list_searched').addClass('d-none'); $('#category_listing').addClass('d-none'); // Check if products are available if (products && Object.keys(products).length > 0) { $('#product_list_searched').removeClass('d-none'); // const SKU = "2000211"; // const Picture = "2000222"; // const Title = "2000213"; // const Description = "1002991"; // const productDetailBaseUrl = "https://www.fuse.systems/product/detail/:sku?id=%3Aid"; // const Status = "1002681"; // const Category = "2000215"; const SKU = "sku"; const Picture = "picture"; const Title = "title"; const Description = "description"; const productDetailBaseUrl = "https://www.fuse.systems/product/detail/:sku"; const Status = "status"; const Category = "category"; for (const [key, element] of Object.entries(products)) { if (element[Status] == 0 && element[Status] != "") { hideLoader(); isRequestInProgress = false; continue; } const productDetailUrl = productDetailBaseUrl .replace(':id', element.objectID) .replace(':sku', element[SKU].replace('/', '')); let imgurl = null; if (Array.isArray(element[Picture])) { // Filter out empty values const filteredImages = element[Picture].filter(image => image.trim() !== ''); var img = filteredImages.length > 0 ? filteredImages[0] : null; imgurl = img ? encodeURIComponent(img) : null; } else { const img = element[Picture]; imgurl = img ? encodeURIComponent(img) : null; } // Set a default image let productImg = `no image`; if (imgurl) { // Construct local and fallback image URLs const imageUrl = `https://www.fuse.systems/uploads/products/${imgurl}`; const fallbackUrl = `https://db.yotltd.com/sims/file.jsp?a=default&f=${imgurl}`; // Attempt to load the local image without blocking the main thread const imgElement = new Image(); imgElement.src = imageUrl; imgElement.onload = function() { // If the local image loads successfully, update the image productImg = `${element[Title]}`; // Update the DOM element dynamically document.querySelector(`#search-${element.objectID} .search_list_image img`).src = imageUrl; }; imgElement.onerror = function() { // If the local image fails to load, use the fallback URL productImg = `${element[Title]}`; // Update the DOM element dynamically document.querySelector(`#search-${element.objectID} .search_list_image img`).src = fallbackUrl; }; } // Construct the result item const tableRow = `
${productImg}
${element[SKU]}
${element[Description].length < 200 ? element[Description] : element[Description].substring(0, 200) + '...'}
`; // Append the product row to the search data $('#product_search_list').append(tableRow); } // $('#category_listing').removeClass('d-none'); // const categoryList = ` // //
//
Product
//
//
// // // // // //
//
`; // Append the product row to the search data // $('#category_list').append(categoryList); } // Check if accessories are available if (accessories && Object.keys(accessories).length > 0) { $('#accessories_list_searched').removeClass('d-none'); // const SKU = "2000211"; // const Picture = "2000222"; // const Title = "2000213"; // const Description = "1002991"; // const productDetailBaseUrl = "https://www.fuse.systems/product/detail/:sku?id=%3Aid"; // const Status = "1002681"; // const Category = "2000215"; const SKU = "sku"; const Picture = "picture"; const Title = "title"; const Description = "description"; const productDetailBaseUrl = "https://www.fuse.systems/product/detail/:sku"; const Status = "status"; const Category = "category"; // Use Object.entries to iterate over the products object for (const [key, element] of Object.entries(accessories)) { if (element[Status] == 0 && element[Status] != "") { hideLoader(); isRequestInProgress = false; continue; } const productDetailUrl = productDetailBaseUrl .replace(':id', element.objectID) .replace(':sku', element[SKU].replace('/', '')); let imgurl = null; if (Array.isArray(element[Picture])) { // Filter out empty values const filteredImages = element[Picture].filter(image => image.trim() !== ''); var img = filteredImages.length > 0 ? filteredImages[0] : null; imgurl = img ? encodeURIComponent(img) : null; } else { const img = element[Picture]; imgurl = img ? encodeURIComponent(img) : null; } // Set a default image let productImg = `no_image`; if (imgurl) { const imageUrl = `https://www.fuse.systems/uploads/products/${imgurl}`; const fallbackUrl = `https://db.yotltd.com/sims/file.jsp?a=default&f=${imgurl}`; // Check if the image exists const exists = await checkImageExists(imageUrl); if (exists) { productImg = `${element[Title]}`; } else { productImg = `${element[Title]}`; } } // Construct the result item const tableRow = `
${productImg}
${element[SKU]}
${element[Description].length < 200 ? element[Description] : element[Description].substring(0, 200) + '...'}
`; // Append the product row to the search data $('#accessories_search_list').append(tableRow); } // $('#category_listing').removeClass('d-none'); // const categoryList = ` // //
//
Accessories
//
//
// // // // // //
//
`; // Append the product row to the search data // $('#category_list').append(categoryList); } // Check if license are available if (license && Object.keys(license).length > 0) { $('#license_list_searched').removeClass('d-none'); // const SKU = "2000211"; // const Picture = "2000222"; // const Title = "2000213"; // const Description = "1002991"; // const productDetailBaseUrl = "https://www.fuse.systems/product/detail/:sku?id=%3Aid"; // const Status = "1002681"; // const Category = "2000215"; const SKU = "sku"; const Picture = "picture"; const Title = "title"; const Description = "description"; const productDetailBaseUrl = "https://www.fuse.systems/product/detail/:sku"; const Status = "status"; const Category = "category"; // Use Object.entries to iterate over the products object for (const [key, element] of Object.entries(license)) { if (element[Status] == 0 && element[Status] != "") { hideLoader(); isRequestInProgress = false; continue; } const productDetailUrl = productDetailBaseUrl .replace(':id', element.objectID) .replace(':sku', element[SKU].replace('/', '')); let imgurl = null; if (Array.isArray(element[Picture])) { // Filter out empty values const filteredImages = element[Picture].filter(image => image.trim() !== ''); var img = filteredImages.length > 0 ? filteredImages[0] : null; imgurl = img ? encodeURIComponent(img) : null; } else { const img = element[Picture]; imgurl = img ? encodeURIComponent(img) : null; } // Set a default image let productImg = `no_image`; if (imgurl) { const imageUrl = `https://www.fuse.systems/uploads/products/${imgurl}`; const fallbackUrl = `https://db.yotltd.com/sims/file.jsp?a=default&f=${imgurl}`; // Check if the image exists const exists = await checkImageExists(imageUrl); if (exists) { productImg = `${element[Title]}`; } else { productImg = `${element[Title]}`; } } // Construct the result item const tableRow = `
${productImg}
${element[SKU]}
${element[Description].length < 200 ? element[Description] : element[Description].substring(0, 200) + '...'}
`; // Append the product row to the search data $('#license_search_list').append(tableRow); } // $('#category_listing').removeClass('d-none'); // const categoryList = ` // //
//
License
//
//
// // // // // //
//
`; // Append the product row to the search data // $('#category_list').append(categoryList); } // Check if orders are available if (orders && Object.keys(orders).length > 0) { $('#order_list_searched').removeClass('d-none'); // const status1 = ""; const PINumber = "1001874"; const CreationTime = "1002788"; // Use Object.entries to iterate over the products object for (const [key, element] of Object.entries(orders)) { const orderDetailUrl = "https://www.fuse.systems/orders?id=" + encodeURIComponent(element[PINumber]); // Construct the result item const tableRow = `
${element[PINumber]}
${changeDateFormat(element[CreationTime])}
`; // Append the product row to the search data $('#order_search_list').append(tableRow); } // $('#category_listing').removeClass('d-none'); // const categoryList = ` // //
//
Order
//
//
// // // // // //
//
`; // Append the product row to the search data // $('#category_list').append(categoryList); } // Check if invoices are available if (invoices && Object.keys(invoices).length > 0) { $('#invoice_list_searched').removeClass('d-none'); const InvoiceNumber = "1001971"; const Total = "1001974"; const Date = "1001970"; // Use Object.entries to iterate over the products object for (const [key, element] of Object.entries(invoices)) { const invoiceDetailUrl = "https://www.fuse.systems/invoices?id=" + encodeURIComponent(element[InvoiceNumber]); // Construct the result item const tableRow = `
${element[InvoiceNumber]}
${changeDateFormat(element[Date])} | ${currency}${numberFormat(element[Total])}
`; // Append the product row to the search data $('#invoice_search_list').append(tableRow); } // $('#category_listing').removeClass('d-none'); // const categoryList = ` // //
//
Invoice
//
//
// // // // // //
//
`; // Append the product row to the search data // $('#category_list').append(categoryList); } // Check if invoices are available if (quotes && Object.keys(quotes).length > 0) { $('#quote_list_searched').removeClass('d-none'); const QuoteId = "2000226"; const QuoteDate = "2000228"; const GrandTotal = "2000245"; // Use Object.entries to iterate over the products object for (const [key, element] of Object.entries(quotes)) { const quoteDetailUrl = "https://www.fuse.systems/quotes?id=" + encodeURIComponent(element[QuoteId]); // Construct the result item const tableRow = `
${changeDateFormat(element[QuoteDate])} | ${currency}${numberFormat(element[GrandTotal])}
${element[QuoteId]}
`; // Append the product row to the search data $('#quote_search_list').append(tableRow); } // $('#category_listing').removeClass('d-none'); // const categoryList = ` //
//
Quote
//
//
// // // // // //
//
`; // Append the product row to the search data // $('#category_list').append(categoryList); } // Check if invoices are available if (subscription && Object.keys(subscription).length > 0) { $('#subscription_list_searched').removeClass('d-none'); const SubscriptionID = "1002696"; const NextRenewal = "1001909"; const Total = "1001923"; // Use Object.entries to iterate over the products object for (const [key, element] of Object.entries(subscription)) { const subscriptionDetailUrl = "https://www.fuse.systems/subscriptions?id=" + encodeURIComponent(element[SubscriptionID]); // Construct the result item const tableRow = `
${element[SubscriptionID]}
${changeDateFormat(element[NextRenewal])} | ${currency}${numberFormat(element[Total])}
`; // Append the product row to the search data $('#subscription_search_list').append(tableRow); } // $('#category_listing').removeClass('d-none'); // const categoryList = ` //
//
Subscription
//
//
// // // // // //
//
`; // Append the product row to the search data // $('#category_list').append(categoryList); } if (products == "" && accessories == "" && license == "" && orders == "" && invoices == "" && quotes == "" && subscription == "") { // No products found case const tableRow = `
No Result Found!
`; $('#searhNoData').append(tableRow); $('#searchResultList').removeClass('d-none'); } hideLoader(); } } catch (err) { // Handle request cancellation or other errors if (err.name === 'AbortError') { console.log('Previous request was aborted.'); } else { console.error('Error fetching search data:', err); } hideLoader(); isRequestInProgress = false; } } $(document).click(function(event) { var targetDiv = $('#search-container'); var hideDiv = $('#searchResultList'); // Check if the clicked element is outside the div if (!$(event.target).closest(targetDiv).length) { hideDiv.addClass('d-none'); // Add class if clicked outside } }); function saveRecentSearch(searchTerm) { // Get existing recent searches from localStorage or create an empty array let recentSearches = JSON.parse(localStorage.getItem('recentSearches')) || []; // Add the search term if it doesn't already exist if (!recentSearches.includes(searchTerm)) { recentSearches.unshift(searchTerm); // Add to the start of the array // if (recentSearches.length > 5) { // recentSearches.pop(); // Keep only the last 5 searches // } } // Save back to localStorage localStorage.setItem('recentSearches', JSON.stringify(recentSearches)); // Display the recent searches displayRecentSearches(); } // Flag to track if full search list is displayed or only first 3 let isShowingAll = false; // Function to retrieve and display recent searches function displayRecentSearches() { let recentSearches = JSON.parse(localStorage.getItem('recentSearches')) || []; let recentSearchList = document.getElementById('recentSearchList'); // Clear the existing recent searches recentSearchList.innerHTML = ''; // If no recent searches are available, show a message if (recentSearches.length === 0) { recentSearchList.innerHTML = '

No recent searches

'; return; } // Show only 3 searches by default, or all if "See More" was clicked const searchesToDisplay = isShowingAll ? recentSearches : recentSearches.slice(0, 3); // Loop through and display the recent searches searchesToDisplay.forEach(search => { let searchItem = `
${search}
`; recentSearchList.innerHTML += searchItem; }); // Show/Hide the "See More" button if there are more than 3 searches let toggleBtn = document.getElementById('toggleRecentSearches'); if (recentSearches.length > 3) { toggleBtn.style.display = 'block'; toggleBtn.innerText = isShowingAll ? 'See Less' : 'See More'; } else { toggleBtn.style.display = 'none'; } } // Toggle between showing only 3 searches or all function toggleRecentSearches() { isShowingAll = !isShowingAll; // Toggle the flag displayRecentSearches(); // Re-render the search list } // Handle when a user clicks on a recent search function handleSearchClick(searchTerm) { document.getElementById('universalSearchInput').value = searchTerm; getUniversalSearchData(); // Trigger search with the selected term } // Function to clear recent searches document.getElementById('clearRecentSearches').addEventListener('click', function() { localStorage.removeItem('recentSearches'); displayRecentSearches(); }); // Call this function whenever a new search is performed function handleSearch(searchTerm) { saveRecentSearch(searchTerm); getUniversalSearchData(); } // Global Variable to avoid multiple api calls let isTrackingApiCallInProgress = false; function trackShipment(trackNo = "") { // alert('dfgfd'); // return; if (isTrackingApiCallInProgress) { return; } let trackingNumber = document.getElementById('trackingUrlInput').value; // console.log('trackingNumber: ', trackingNumber); if (trackingNumber == "") { trackingNumber = trackNo; } if (trackingNumber.length == 0) { $('#activitySectionAll').empty().append('
Please provide tracking number
'); return; } isTrackingApiCallInProgress = true; $.ajax({ url: `https://username.aftership.com/trpc/trackings.getTrackingWithTrackingNumber?batch=1&input={"0":{"organization_id":"ed77e860f10b4ac4830e00ff235cf72a","tracking_number":"${trackingNumber}","translate_to":"en"}}`, method: "GET", beforeSend: function() { $('#activitySectionAll').empty().append('
'); }, success: function(response) { if (Object.keys(response[0].result.data).length == 0) { $('#activitySectionAll').empty().append('
Not Found!
'); return; } let activity = ''; const checkpoints = response[0].result.data.tracking.checkpoints; const reversedCheckpoints = checkpoints.reverse(); reversedCheckpoints.forEach((checkpoint) => { activity += `
${checkpoint.status || 'Status Unknown'}
${checkpoint.message || 'No message available'}
${checkpoint.location || checkpoint.city || checkpoint.country || 'Location Unknown'}
${changeDateFormat(new Date(checkpoint.checkpoint_time)) || 'Time Unknown'}
`; }); // Append the activity logs to the DOM $('#activitySectionAll').empty().append(activity); $('#trackingOrderId').empty().append(response[0].result.data.tracking.title.match(/PI-\d+/)[0]); $('#account_name_for_tracking').empty().append(response[0].result.data.tracking.title.replace(/PI-\d+ - /, "")); }, error: function(error) { console.error("Error: ", error); $('#activitySectionAll').empty().append('
Failed to load activity
'); }, complete: function() { isTrackingApiCallInProgress = false; } }); } function changeOrderTrackignUrl(trackingURL) { var url = new URL(trackingURL); var trackingNumber = url.pathname; var domain = window.location.protocol + "//" + window.location.host; // e.g., "http://track.yotstore.com" // Construct the new URL with the tracking number var newUrl = domain + "/tracking" + trackingNumber; // e.g., "http://fuse.yotltd.com/778145248770" return newUrl; } // Function to handle quantity change // function updateQuantity(newQuantity) { // var availableStock = $('#available-stock'); // var stockWarning = $('.stock-warning'); // var addToCartBtn = $('.add-to-cart-btn'); // const maxStock = $('.number-input').attr('data-max-stock'); // // Update the stock warning and button state // if (newQuantity > maxStock) { // availableStock.text(newQuantity - maxStock); // stockWarning.show(); // maxQuanty = true; // addToCartBtn.attr('disabled', 'true'); // } else { // maxQuanty = false; // stockWarning.hide(); // addToCartBtn.removeAttr('disabled'); // } // } // Handling number-input change $(document).on('input', '.number-input', function() { var newQuantity = parseInt($(this).val()); $(this).val(newQuantity); const maxStock = $(this).attr('data-max-stock'); // Use `this` to get the correct element's attribute // If input is not a number or less than 1, reset to 1 if (isNaN(newQuantity) || newQuantity < 1) { $(this).val(1); newQuantity = 1; } // updateQuantity(newQuantity); }); function getIdFromUrl() { const params = new URLSearchParams(window.location.search); return params.get('id'); } // Add this helper function at the appropriate scope function isProductInCart(sku) { const cart = null; return cart && cart.hasOwnProperty(sku) || cart && sku in cart; } function isProductInQuote(sku){ const quotes = null; return quotes && quotes.hasOwnProperty(sku) || quotes && sku in quotes; } let addToCartRes = true; let maxQuanty = false; $(document).on('click', '.add-to-cart-btn', function() { const session = null; const userRole = session !== null ? session["1002677"] : ''; // if (session === null) { // const swalWithBootstrapButtons = Swal.mixin({ // customClass: { // confirmButton: "btn btn-orange", // cancelButton: "btn btn-orange me-3" // }, // buttonsStyling: false // }); // swalWithBootstrapButtons.fire({ // title: "Login required", // text: "Please login first to add an item to the cart!", // icon: "warning", // showCancelButton: true, // confirmButtonText: "Register", // cancelButtonText: "Login", // reverseButtons: true // }).then((result) => { // if (result.isConfirmed) { // // Redirect to the register page // window.location.href = '/register'; // Change to your register URL // } else if (result.dismiss === Swal.DismissReason.cancel) { // // Redirect to the login page if canceled // window.location.href = '/login'; // Change to your login URL // } // }); // return; // } if (maxQuanty == true || addToCartRes == false) { return; } // Store reference to clicked button const clickedButton = $(this); addToCartRes = false; // Retrieve product details let sku = clickedButton.data('sku'); let ragicId = clickedButton.data('ragic-id'); let uniqueProductRow = $('.productrrp_' + ragicId); // let uniqueProductRowText = uniqueProductRow.text().trim(); let uniqueProductRowText = JSON.parse(uniqueProductRow.attr('data-price'))[1]; // console.log("uniqueProductRow", uniqueProductRow); // console.log("uniqueProductRowText", uniqueProductRowText); // return; let b2bPriceText; if (uniqueProductRowText.length > 0) { b2bPriceText = uniqueProductRowText; } else { b2bPriceText = uniqueProductRow.val(); } let prices = b2bPriceText.split(' ').filter(price => price.length > 0); // Determine the actual B2B price let b2bPrice = (prices.length > 1) ? prices[1] : (prices.length > 0 ? prices[0] : 0); if (b2bPrice !== 0) { b2bPrice = parseFloat(b2bPrice.replace(/[^0-9.]/g, '')); } let row = $(clickedButton).closest('tr'); if (row.length == 0) { let productDetailsDiv = $('.product_detail_price_Sec'); if (productDetailsDiv.length != 0) { row = productDetailsDiv; } else { row = $(clickedButton).closest('.order_history_card'); } } var input = row.find('.p-quantity input'); var quantity = 1; if (input.length > 0) { quantity = parseInt(input.val()); } let accountName = "N/A"; let contactId = "N/A"; let contactName = "N/A"; let totalPrice = b2bPrice * quantity; $('#loader' + ragicId).removeClass('d-none'); $('#mob_loader' + ragicId).removeClass('d-none'); $('#addtocart' + ragicId).addClass('d-none'); $('#mob_addtocart' + ragicId).addClass('d-none'); var priceData = uniqueProductRow.data('price'); // console.log('quantity3: ', quantity); // console.log('b2bPrice: ', b2bPrice); // console.log('totalPrice: ', totalPrice); // console.log('accountName: ', accountName); // console.log('contactId: ', contactId); // console.log('contactName: ', contactName); // console.log('priceData: ', priceData); // return; let productTypeElement = $('.product_type_' + ragicId); let product_type = 'product'; if (productTypeElement && productTypeElement.length > 0) { product_type = productTypeElement.val(); } // console.log('sku: ', sku, ' quantity: ', quantity, ' b2bPrice: ', b2bPrice, ' totalPrice: ', totalPrice, ' accountName: ', accountName, ' contactId: ', contactId, ' contactName: ', contactName, ' priceData: ', priceData, ' product_type: ', product_type); // return; $.ajax({ url: '/add-to-cart', method: 'POST', data: { ragic_id: ragicId, sku: sku, quantity: quantity, price_per_item: b2bPrice, total_price: totalPrice, discount: "", account_name: accountName, contact_id: contactId, contact_name: contactName, price_data: priceData, product_type: product_type, _token: "wxfy4ixxsZUb2Cvg6oKzY7HZU4mWsX3Xs8JHOzRe" }, success: function(response) { if (response.success) { // Function call for appending cart data in navbar cart icon updatecart(); // Create the "Added" message element let addedMessage = $('
', { text: 'Added!', css: { color: 'green', fontWeight: 'bold' }, class: 'added-message' }); // Create the "Go to Cart" button let goToCartBtn = $('', { class: 'btn btn-orange btn-sm my-2 go-to-cart-btn', href: userRole === "Admin" ? "https://www.fuse.systems/quote-builder" : "https://www.fuse.systems/cart" }).append(`  Go to ${userRole === 'Admin' ? 'Quote' : 'Cart'} `); // Replace only the clicked button with the new elements clickedButton.replaceWith($('
').append(addedMessage, goToCartBtn)); $('#addtocart' + ragicId).removeClass('d-none'); $('#mob_addtocart' + ragicId).removeClass('d-none'); $('#loader' + ragicId).addClass('d-none'); $('#mob_loader' + ragicId).addClass('d-none'); let itemCount = parseInt($('#navCartItemCount').html()); let result = itemCount + 1; $('#navCartItemCount').html(result); } else { console.error('Error adding product to cart:', response.error); } addToCartRes = true; }, error: function(xhr, status, error) { console.error('AJAX error:', error); addToCartRes = true; } }); }); function reinitializeDataTable(req) { setTimeout(function() { var columnDefs = []; // Add this configuration only if req === "invoice" if (req === "invoice") { columnDefs.push({ "bSortable": false, "aTargets": [7] // Disable sorting for the "Invoice Link" column (index 7) }); } var table = $('#product_table_js').DataTable({ responsive: true, searching: false, lengthChange: false, paging: false, info: false, order: [ [0, 'desc'] ], colReorder: true, // Enable Column Reordering stripeClasses: [], stateSave: false, "aoColumnDefs": columnDefs, // Apply columnDefs with condition drawCallback: function(settings) { $('#product_table_js tbody tr').removeClass('sorting_1'); } }); }, 100); // Small delay before reinitialization to ensure the DOM has fully updated } $(document).on('click', '.pdf-link', function() { let reqUrl = ""; let detailID = ""; let paramType = ""; $(".splash").removeClass('starthide'); $(".splash_clr").removeClass('animate__fadeOut'); $(".splash-icon").removeClass('animate__zoomOut'); let pdfType = $(this).data('pdf-type'); // Get the PDF type from the data attribute if(pdfType == "quote"){ reqUrl = '/get-pdf-details'; // Url paramType = 'estimateID'; detailID = $(this).data('pdf-estimateid'); // Get the PDF estimate id from the data attribute }else{ reqUrl = '/get-invoices-pdf-details'; // Url paramType = 'invoiceID'; detailID = $(this).data('pdf-invoiceid'); // Get the PDF invoice ID from the data attribute } $.ajax({ url: reqUrl, type: 'GET', data: { [paramType]: detailID }, success: function(response) { let htmlData = ""; if(response.message == "success"){ //Populate the template body with the fetched HTML if(pdfType == "quote"){ htmlData = response.data.estimate; }else{ htmlData = response.data.invoice; } $('.pcs-template-body').html(htmlData); // Update the header status $('#headerStatus').replaceWith(response.data.status); $('#downloadPDF').attr('href', response.data.downloadURL); $('#logo_content').attr('src', '/fuse/img/Invoicelogo_Logo_Zoho.png'); $('.saveBtn').show(); $('.modal_ui .template_main').removeClass('empty_pdf_div'); $('.pcs-template-body').removeClass('text-center'); }else{ $('.saveBtn').hide(); $('#headerStatus').replaceWith('
'); $('.pcs-template-body').addClass('text-center').html('Logo' + '
' + response.message + '
'); $('.modal_ui .template_main').addClass('empty_pdf_div'); } // Show the modal with the PDF content $('#showPdfModal').modal('show'); $(".splash").addClass('starthide'); $(".splash_clr").addClass('animate__fadeOut'); $(".splash-icon").addClass('animate__zoomOut'); }, error: function(xhr, status, error) { $(".splash").addClass('starthide'); $(".splash_clr").addClass('animate__fadeOut'); $(".splash-icon").addClass('animate__zoomOut'); console.log(error); } }); }); $('#print').on('click', function() { var printContent = document.getElementById('pdf-template-body').innerHTML; var printWindow = window.open('', '', 'height=800, width=1000'); printWindow.document.write('YOT LTD'); printWindow.document.write(printContent); printWindow.document.write(''); printWindow.document.close(); // Necessary for IE printWindow.print(); }); -->