/** * Ayula Store POS System * Main JavaScript file for transaction page functionality */ $(document).ready(function() { // Initialize globals initializeGlobals(); // Setup event handlers setupEventHandlers(); // Initialize UI components initializeUI(); // Check and update the "Clear All" button state on page load updateClearCartButtonInitialState(); // Make sure cart functionality is properly initialized ensureCartFunctionalityInitialized(); }); /** * Make sure cart functionality is properly initialized * This acts as a safety measure to ensure critical functions are available */ function ensureCartFunctionalityInitialized() { // Check if key functions exist, if not define them if (typeof setupQuantityControls !== 'function') { console.log('Initializing missing cart functions...'); // Define quantity controls if missing window.setupQuantityControls = function() { // Remove any existing event handlers to prevent duplicates $('.quantity-btn.increment, .quantity-btn.decrement').off('click'); // Setup increment button $('.quantity-btn.increment').on('click', function() { const quantityField = $(this).siblings('.quantity-field'); const currentValue = parseInt(quantityField.val()) || 0; const maxStock = parseInt(quantityField.data('max-stock')) || 99; // Only increment if below max stock if (currentValue < maxStock) { quantityField.val(currentValue + 1); } }); // Setup decrement button $('.quantity-btn.decrement').on('click', function() { const quantityField = $(this).siblings('.quantity-field'); const currentValue = parseInt(quantityField.val()) || 0; // Only decrement if above 1 if (currentValue > 1) { quantityField.val(currentValue - 1); } }); // Handle manual input validation $('.quantity-field').on('change', function() { let value = parseInt($(this).val()) || 0; const maxStock = parseInt($(this).data('max-stock')) || 99; // Ensure value is between 1 and max stock if (value < 1) value = 1; if (value > maxStock) value = maxStock; $(this).val(value); }); // Enable form submission with enter key $('.quantity-field').on('keydown', function(e) { if (e.keyCode === 13) { e.preventDefault(); $(this).closest('form').submit(); } }); }; // Define cart deletion confirmation if missing window.setupCartDeletionConfirmation = function() { // Remove any existing event handlers to prevent duplicates $('.delete-cart-item').off('click'); // Setup delete button click event $('.delete-cart-item').on('click', function(e) { e.preventDefault(); const itemIndex = $(this).data('index'); // Set the confirmation button's href $('#confirm-delete-btn').attr('href', 'index.php?remove_item=' + itemIndex); // Show the confirmation modal if (typeof bootstrap !== 'undefined' && $('#deleteConfirmModal').length) { const deleteModal = new bootstrap.Modal(document.getElementById('deleteConfirmModal')); deleteModal.show(); } else { // Fallback if Bootstrap modal isn't available if (confirm('Apakah Anda yakin ingin menghapus item ini dari keranjang Anda?')) { window.location.href = 'index.php?remove_item=' + itemIndex; } } }); }; // Initialize these functions right away setupQuantityControls(); setupCartDeletionConfirmation(); console.log('Cart functions initialized'); } } /** * Initialize global variables and state */ function initializeGlobals() { // Variables to track selected products window.selectedProducts = []; window.multiSelectToolbar = $('.multi-select-toolbar'); // Store product stock information window.productStock = {}; $('.productset').each(function() { const productId = $(this).data('product-id'); const stockText = $(this).find('.productsetimg h6').text(); const stockValue = parseInt(stockText.replace('Stok: ', '')) || 0; window.productStock[productId] = stockValue; }); } /** * Check and update the "Clear All" button state on page load */ function updateClearCartButtonInitialState() { const cartItemsCount = $('.product-lists').length; console.log('Initial cart items count:', cartItemsCount); // Get the clear cart button const clearCartBtn = $('#clear-cart-btn'); if (cartItemsCount > 0) { // Enable the clear cart button clearCartBtn.attr('href', 'javascript:void(0);') .removeClass('disabled') .css({ 'opacity': '1', 'cursor': 'pointer' }) .off('click') .on('click', function(e) { e.preventDefault(); if (typeof bootstrap !== 'undefined' && $('#clearCartModal').length) { try { const clearModal = new bootstrap.Modal(document.getElementById('clearCartModal')); clearModal.show(); } catch (error) { console.log('Modal error, using fallback:', error); if (confirm('Apakah Anda yakin ingin menghapus semua item dari keranjang Anda?')) { window.location.href = 'index.php?clear_cart=1'; } } } else { if (confirm('Apakah Anda yakin ingin menghapus semua item dari keranjang Anda?')) { window.location.href = 'index.php?clear_cart=1'; } } }); console.log('Clear cart button initially enabled'); } else { // Disable the clear cart button clearCartBtn.attr('href', '#') .addClass('disabled') .css({ 'opacity': '0.5', 'cursor': 'not-allowed' }) .off('click'); console.log('Clear cart button initially disabled'); } } /** * Setup all event handlers for the page */ function setupEventHandlers() { // Product card selection setupProductSelection(); // Toolbar actions setupToolbarActions(); // Setup modal buttons properly setupModalButtons(); } /** * Setup modal buttons for all modals */ function setupModalButtons() { // Delete confirmation modal $('#deleteConfirmModal').on('show.bs.modal', function (event) { // Make sure the confirm delete button is functional $('#confirm-delete-btn').off('click').on('click', function(e) { // Use the href attribute for navigation const href = $(this).attr('href'); if (href) { window.location.href = href; } }); }); // Clear cart modal $('#clearCartModal').on('show.bs.modal', function (event) { // Make sure cancel button closes the modal $('#cancel-clear-cart').off('click').on('click', function() { const clearModal = bootstrap.Modal.getInstance(document.getElementById('clearCartModal')); if (clearModal) { clearModal.hide(); } }); // Make sure confirm button navigates to clear cart action $('#confirm-clear-cart').off('click').on('click', function() { window.location.href = 'index.php?clear_cart=1'; }); }); } /** * Initialize UI components */ function initializeUI() { // Hide all check marks initially $('.check-product i').hide(); // Trigger toggle button click to activate it when page loads setTimeout(function() { $("#toggle_btn").trigger('click'); }, 100); // Focus search field when search icon is clicked $('.responsive-search').on('click', function() { setTimeout(function() { $('input[name="search"]').focus(); }, 100); }); // Focus the page header search field on click $('.product-search-form input[name="search"]').on('click', function() { $(this).focus(); }); // Enable live search functionality setupLiveSearch(); // Enable AJAX category navigation setupCategoryNavigation(); // Initialize cash payment functionality setupCashPayment(); } /** * Setup product selection functionality */ function setupProductSelection() { // Click on product card to toggle selection $('.productset').on('click', function(e) { // Only handle clicks on the card itself, not buttons or links inside if ($(e.target).closest('button, a, form').length === 0) { const productId = $(this).data('product-id'); const checkbox = $(this).find('.product-checkbox'); const isChecked = checkbox.prop('checked'); console.log('Clicked product ID:', productId); // Toggle checkbox checkbox.prop('checked', !isChecked); if (!isChecked) { // Add to selected list and highlight window.selectedProducts.push(productId); $(this).addClass('selected'); $(this).find('.check-product i').show(); } else { // Remove from selected list and unhighlight window.selectedProducts = window.selectedProducts.filter(id => id !== productId); $(this).removeClass('selected'); $(this).find('.check-product i').hide(); } console.log('Selected products:', window.selectedProducts); updateToolbar(); } }); } /** * Setup toolbar action buttons */ function setupToolbarActions() { // Cancel selection button $('#cancel-selection').on('click', function() { // Uncheck all checkboxes and hide check marks $('.product-checkbox').prop('checked', false); $('.productset').removeClass('selected'); $('.check-product i').hide(); window.selectedProducts = []; updateToolbar(); }); // Add selected products to cart $('#add-selected-to-cart').on('click', function() { if (window.selectedProducts.length > 0) { console.log('Adding products to cart:', window.selectedProducts); // Create a form to submit selected products const form = $('
', { method: 'post', action: 'index.php' }); // Add each product ID as a hidden input window.selectedProducts.forEach(function(productId) { form.append( $('').attr({ type: 'hidden', name: 'product_ids[]', value: productId }) ); }); // Log form contents before submission console.log('Form contents:', form.serialize()); // Add the form to the body and submit it $('body').append(form); form.submit(); } }); } /** * Update the toolbar state based on selected products */ function updateToolbar() { if (window.selectedProducts.length > 0) { $('.selected-count').text(window.selectedProducts.length + ' item' + (window.selectedProducts.length > 1 ? 's' : '') + ' selected'); window.multiSelectToolbar.addClass('active'); } else { window.multiSelectToolbar.removeClass('active'); } } /** * Setup live search functionality */ function setupLiveSearch() { // Handle both search inputs - top nav and product header search const searchInputs = $('input[name="search"]'); // Store the original URL for reference const originalUrl = window.location.href.split('?')[0]; const urlParams = new URLSearchParams(window.location.search); // Clear search buttons functionality $('.product-search-form a, .search-addon a').on('click', function(e) { e.preventDefault(); urlParams.delete('search'); // Build the new URL let newUrl = originalUrl; const paramString = urlParams.toString(); if (paramString) { newUrl += '?' + paramString; } // Navigate to the new URL window.location.href = newUrl; }); // Custom form submission to prevent loader $('.product-search-form form, .top-nav-search form').on('submit', function(e) { e.preventDefault(); // Prevent the default form submission // Get the search query const searchQuery = $(this).find('input[name="search"]').val().trim(); // Get any type filter const typeParam = $(this).find('input[name="type"]').val(); // Build the URL let newUrl = originalUrl; if (searchQuery || typeParam) { newUrl += '?'; if (searchQuery) { newUrl += 'search=' + encodeURIComponent(searchQuery); if (typeParam) { newUrl += '&'; } } if (typeParam) { newUrl += 'type=' + encodeURIComponent(typeParam); } } // Use AJAX to fetch the page content $.ajax({ url: newUrl, type: 'GET', beforeSend: function() { // Add a simple loading indicator to the product area $('.tab_content').addClass('loading'); $('.tab_content > .row').css('opacity', '0.5'); }, success: function(response) { // Extract and replace just the product content const $response = $(response); const newProductContent = $response.find('.tab_content').html(); // Update the DOM with new content $('.tab_content').html(newProductContent); // Update browser URL without reloading history.pushState({}, '', newUrl); // Update search info area if it exists const searchInfoContent = $response.find('.search-results-info').html(); if (searchInfoContent) { if ($('.search-results-info').length) { $('.search-results-info').html(searchInfoContent); } else { $('
') .html(searchInfoContent) .insertAfter('.page-header'); } $('.search-results-info').show(); } else { $('.search-results-info').hide(); } // Update the other search input with the same value searchInputs.val(searchQuery); // Reset the loading state $('.tab_content').removeClass('loading'); $('.tab_content > .row').css('opacity', '1'); // Reinitialize product selection for newly loaded products setupProductSelection(); }, error: function() { // If something goes wrong, just do a normal page load window.location.href = newUrl; } }); }); } /** * Setup AJAX-based category navigation */ function setupCategoryNavigation() { // Original URL for reference const originalUrl = window.location.href.split('?')[0]; // Add click event handlers to all category links $('.tabs li a.category-tab').on('click', function(e) { e.preventDefault(); // Get category type from URL const href = $(this).attr('href'); const url = new URL(href, window.location.origin); const typeParam = url.searchParams.get('type'); // Get current search query if any const currentUrl = new URL(window.location.href); const searchQuery = currentUrl.searchParams.get('search'); // Build the target URL let targetUrl = originalUrl; const params = new URLSearchParams(); // Add type parameter if set if (typeParam) { params.set('type', typeParam); } // Preserve search query if exists if (searchQuery) { params.set('search', searchQuery); } // Append parameters to URL if any const paramString = params.toString(); if (paramString) { targetUrl += '?' + paramString; } // Highlight the active category tab $('.tabs li').removeClass('active'); $(this).closest('li').addClass('active'); // Use AJAX to fetch the category products $.ajax({ url: targetUrl, type: 'GET', beforeSend: function() { // Add loading indicator to product area $('.tab_content').addClass('loading'); $('.tab_content > .row').css('opacity', '0.5'); }, success: function(response) { // Extract and replace just the product content const $response = $(response); const newProductContent = $response.find('.tab_content').html(); // Update the DOM with new content $('.tab_content').html(newProductContent); // Update browser URL without reloading history.pushState({}, '', targetUrl); // Reset the loading state $('.tab_content').removeClass('loading'); $('.tab_content > .row').css('opacity', '1'); // Reinitialize product selection for newly loaded products setupProductSelection(); }, error: function() { // If something goes wrong, just do a normal page load window.location.href = targetUrl; } }); }); } /** * Setup cash payment functionality */ function setupCashPayment() { const cashInput = $('#cash-amount'); const changeDisplay = $('#change-amount'); const changeContainer = $('#change-container'); const hiddenCashAmount = $('#hidden-cash-amount'); const hiddenChangeAmount = $('#hidden-change-amount'); const totalAmount = parseFloat($('.total-value h6').text().replace(/[^\d]/g, '')); // Format cash input with thousand separators cashInput.on('input', function() { // Remove non-numeric characters let value = $(this).val().replace(/[^\d]/g, ''); // Convert to number and format with thousand separator if (value !== '') { const numericValue = parseInt(value); // Calculate change const change = numericValue - totalAmount; // Update hidden fields for form submission - store raw numeric values hiddenCashAmount.val(numericValue); hiddenChangeAmount.val(Math.max(0, change)); // Format display value $(this).val(formatNumber(numericValue)); // Show change if payment is sufficient if (change >= 0) { changeDisplay.text('Rp. ' + formatNumber(change)); changeContainer.show(); } else { changeContainer.hide(); } } else { $(this).val(''); changeContainer.hide(); } }); // Quick cash buttons $('.quick-cash').on('click', function() { const value = $(this).data('value'); cashInput.val(formatNumber(value)); // Calculate change const change = value - totalAmount; // Update hidden fields for form submission hiddenCashAmount.val(value); hiddenChangeAmount.val(Math.max(0, change)); // Show change if (change >= 0) { changeDisplay.text('Rp. ' + formatNumber(change)); changeContainer.show(); } else { changeContainer.hide(); } }); // Form submission check $('#checkout-form').on('submit', function(e) { const cashValue = parseFloat(hiddenCashAmount.val()); // Check if cash amount is sufficient if (cashValue < totalAmount) { e.preventDefault(); alert('Cash amount is not sufficient!'); return false; } return true; }); // Trigger input event to initialize on page load cashInput.trigger('input'); } /** * Format number with thousand separator */ function formatNumber(number) { return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "."); }