main.js

12.76 KB
28/07/2025 15:39
JS
main.js
// Main JavaScript functionality
document.addEventListener('DOMContentLoaded', function() {
  initializeApp();
});

async function initializeApp() {
  // Show loading animation
  showLoadingAnimation();

  // Load menu data first
  await loadMenuData();

  // Initialize app components
  loadMenu();
  setupEventListeners();
  setupOrderTypeSelection();
  setupMobileMenu();
  setupSmoothScrolling();
}

// Load and display menu
function loadMenu(category = 'all') {
  const menuGrid = document.getElementById('menuGrid');
  if (!menuGrid) return;

  const items = getMenuByCategory(category);

  menuGrid.innerHTML = items.map(item => createMenuItemHTML(item)).join('');

  // Add fade-in animation
  menuGrid.classList.add('fade-in');
}

// Create HTML for menu item
function createMenuItemHTML(item) {
  const optionsHTML = createOptionsHTML(item.options);

  return `
        <div class="menu-item" data-category="${item.category}">
            <div class="menu-item-image">
                <img src="${item.image}" alt="${item.name}" loading="lazy" onerror="this.src='data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDQwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMzAwIiBmaWxsPSIjZjBmMGYwIi8+Cjx0ZXh0IHg9IjIwMCIgeT0iMTUwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjOEI0NTEzIiBmb250LXNpemU9IjQ4Ij7imJXvuI88L3RleHQ+Cjwvc3ZnPg=='; this.alt='ไม่สามารถโหลดรูปภาพได้';">
            </div>
            <div class="menu-item-content">
                <h3>${item.name}</h3>
                <p>${item.description}</p>
                <div class="menu-item-price">฿${item.price}</div>
                <div class="menu-item-options" id="options-${item.id}">
                    ${optionsHTML}
                </div>
                <button class="add-to-cart" onclick="addToCartFromMenu(${item.id})">
                    เพิ่มลงตะกร้า
                </button>
            </div>
        </div>
    `;
}

// Create options HTML for menu item
function createOptionsHTML(options) {
  if (!options) return '';

  let html = '';

  for (const [key, values] of Object.entries(options)) {
    if (Array.isArray(values)) {
      const label = getOptionLabel(key);
      html += `
                <div class="option-group">
                    <label>${label}:</label>
                    <select name="${key}">
                        ${values.map(value => `<option value="${value}">${value}</option>`).join('')}
                    </select>
                </div>
            `;
    }
  }

  return html;
}

// Get option label in Thai
function getOptionLabel(key) {
  const labels = {
    size: 'ขนาด',
    sweetness: 'ความหวาน',
    intensity: 'ความเข้มข้น',
    hot: 'อุณหภูมิ',
    milk: 'ประเภทนม',
    pearls: 'ไข่มุก',
    topping: 'ท็อปปิ้ง',
    serving: 'เสิร์ฟ',
    filling: 'ไส้',
    flavor: 'รสชาติ',
    quantity: 'จำนวน'
  };
  return labels[key] || key;
}

// Add item to cart from menu
function addToCartFromMenu(itemId) {
  const optionsContainer = document.getElementById(`options-${itemId}`);
  const options = {};

  if (optionsContainer) {
    const selects = optionsContainer.querySelectorAll('select');
    selects.forEach(select => {
      options[select.name] = select.value;
    });
  }

  cart.addItem(itemId, options);
}

// Setup event listeners
function setupEventListeners() {
  // Menu category buttons
  const categoryButtons = document.querySelectorAll('.category-btn');
  categoryButtons.forEach(btn => {
    btn.addEventListener('click', function() {
      // Update active button
      categoryButtons.forEach(b => b.classList.remove('active'));
      this.classList.add('active');

      // Load menu for selected category
      const category = this.dataset.category;
      loadMenu(category);
    });
  });

  // Modal close events
  window.addEventListener('click', function(event) {
    const modals = document.querySelectorAll('.modal');
    modals.forEach(modal => {
      if (event.target === modal) {
        modal.style.display = 'none';
      }
    });
  });

  // Form submissions
  const checkoutForm = document.getElementById('checkoutForm');
  if (checkoutForm) {
    checkoutForm.addEventListener('submit', function(e) {
      e.preventDefault();
      processPayment();
    });
  }
}

// Setup order type selection
function setupOrderTypeSelection() {
  const orderOptions = document.querySelectorAll('.order-option');
  orderOptions.forEach(option => {
    option.addEventListener('click', function() {
      // Update active option
      orderOptions.forEach(opt => opt.classList.remove('active'));
      this.classList.add('active');

      // Update cart order type
      const orderType = this.dataset.type;
      cart.setOrderType(orderType);

      // Show feedback
      const optionName = orderType === 'pickup' ? 'รับที่ร้าน' : 'จัดส่ง';
      showNotification(`เลือก ${optionName} แล้ว`);
    });
  });
}

// Setup mobile menu
function setupMobileMenu() {
  const hamburger = document.querySelector('.hamburger');
  const navMenu = document.querySelector('.nav-menu');

  if (hamburger && navMenu) {
    hamburger.addEventListener('click', function() {
      hamburger.classList.toggle('active');
      navMenu.classList.toggle('active');
    });

    // Close menu when clicking on nav links
    const navLinks = document.querySelectorAll('.nav-menu a');
    navLinks.forEach(link => {
      link.addEventListener('click', function() {
        hamburger.classList.remove('active');
        navMenu.classList.remove('active');
      });
    });
  }
}

// Setup smooth scrolling
function setupSmoothScrolling() {
  const navLinks = document.querySelectorAll('a[href^="#"]');
  navLinks.forEach(link => {
    link.addEventListener('click', function(e) {
      e.preventDefault();
      const targetId = this.getAttribute('href');
      const targetSection = document.querySelector(targetId);

      if (targetSection) {
        const offsetTop = targetSection.offsetTop - 80; // Account for fixed header
        window.scrollTo({
          top: offsetTop,
          behavior: 'smooth'
        });
      }
    });
  });
}

// Helper functions for navigation
function scrollToMenu() {
  const menuSection = document.getElementById('menu');
  if (menuSection) {
    const offsetTop = menuSection.offsetTop - 80;
    window.scrollTo({
      top: offsetTop,
      behavior: 'smooth'
    });
  }
}

function scrollToAbout() {
  const aboutSection = document.getElementById('about');
  if (aboutSection) {
    const offsetTop = aboutSection.offsetTop - 80;
    window.scrollTo({
      top: offsetTop,
      behavior: 'smooth'
    });
  }
}

// Show notification
function showNotification(message, type = 'success') {
  const notification = document.createElement('div');
  const bgColor = type === 'success' ? '#28a745' : type === 'error' ? '#dc3545' : '#17a2b8';

  notification.style.cssText = `
        position: fixed;
        top: 100px;
        right: 20px;
        background: ${bgColor};
        color: white;
        padding: 15px 20px;
        border-radius: 8px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.2);
        z-index: 3000;
        font-weight: 500;
        animation: slideInRight 0.3s ease;
        max-width: 300px;
    `;
  notification.textContent = message;

  document.body.appendChild(notification);

  setTimeout(() => {
    notification.style.animation = 'slideOutRight 0.3s ease forwards';
    setTimeout(() => notification.remove(), 300);
  }, 3000);
}

// Search functionality
function searchMenu(query) {
  if (!query) {
    loadMenu();
    return;
  }

  const allItems = getAllMenuItems();
  const filteredItems = allItems.filter(item =>
    item.name.toLowerCase().includes(query.toLowerCase()) ||
    item.description.toLowerCase().includes(query.toLowerCase())
  );

  const menuGrid = document.getElementById('menuGrid');
  if (menuGrid) {
    if (filteredItems.length === 0) {
      menuGrid.innerHTML = '<p class="text-center" style="grid-column: 1 / -1; padding: 2rem;">ไม่พบสินค้าที่ค้นหา</p>';
    } else {
      menuGrid.innerHTML = filteredItems.map(item => createMenuItemHTML(item)).join('');
    }
  }
}

// Filter menu by price range
function filterByPrice(minPrice, maxPrice) {
  const allItems = getAllMenuItems();
  const filteredItems = allItems.filter(item =>
    item.price >= minPrice && item.price <= maxPrice
  );

  const menuGrid = document.getElementById('menuGrid');
  if (menuGrid) {
    menuGrid.innerHTML = filteredItems.map(item => createMenuItemHTML(item)).join('');
  }
}

// Sort menu items
function sortMenu(sortBy) {
  const allItems = getAllMenuItems();
  let sortedItems = [...allItems];

  switch (sortBy) {
    case 'price-low':
      sortedItems.sort((a, b) => a.price - b.price);
      break;
    case 'price-high':
      sortedItems.sort((a, b) => b.price - a.price);
      break;
    case 'name':
      sortedItems.sort((a, b) => a.name.localeCompare(b.name));
      break;
    default:
      break;
  }

  const menuGrid = document.getElementById('menuGrid');
  if (menuGrid) {
    menuGrid.innerHTML = sortedItems.map(item => createMenuItemHTML(item)).join('');
  }
}

// Handle window resize
window.addEventListener('resize', function() {
  // Close mobile menu if window is resized to desktop
  if (window.innerWidth > 768) {
    const hamburger = document.querySelector('.hamburger');
    const navMenu = document.querySelector('.nav-menu');

    if (hamburger && navMenu) {
      hamburger.classList.remove('active');
      navMenu.classList.remove('active');
    }
  }
});

// Handle scroll for header effect
window.addEventListener('scroll', function() {
  const header = document.querySelector('.header');
  if (header) {
    if (window.scrollY > 100) {
      header.style.background = 'rgba(255, 255, 255, 0.95)';
      header.style.backdropFilter = 'blur(10px)';
    } else {
      header.style.background = '#fff';
      header.style.backdropFilter = 'none';
    }
  }
});

// Loading animation for menu items
function showLoadingAnimation() {
  const menuGrid = document.getElementById('menuGrid');
  if (menuGrid) {
    menuGrid.innerHTML = `
            <div style="grid-column: 1 / -1; text-align: center; padding: 2rem;">
                <i class="fas fa-spinner fa-spin" style="font-size: 2rem; color: #8B4513;"></i>
                <p style="margin-top: 1rem; color: #666;">กำลังโหลดเมนู...</p>
            </div>
        `;
  }
}

// Error handling
window.addEventListener('error', function(e) {
  console.error('JavaScript Error:', e.error);
  showNotification('เกิดข้อผิดพลาด กรุณาลองใหม่อีกครั้ง', 'error');
});

// Service Worker Registration (for PWA capabilities)
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js')
      .then(function(registration) {
        console.log('ServiceWorker registration successful');
      })
      .catch(function(err) {
        console.log('ServiceWorker registration failed');
      });
  });
}

// Initialize Google Maps (if needed for advanced features)
function initializeMap() {
  const mapElement = document.getElementById('map');
  if (mapElement && window.google) {
    // Advanced Google Maps integration can be added here
    // For now, we're using iframe which works well
    console.log('Map element found, using iframe implementation');
  }
}

// Handle map loading errors
function handleMapError() {
  const mapContainer = document.getElementById('map');
  if (mapContainer) {
    mapContainer.innerHTML = `
            <div class="map-placeholder">
                <i class="fas fa-map-marker-alt"></i>
                <p>ไม่สามารถโหลดแผนที่ได้</p>
                <p style="font-size: 0.9rem; color: #999;">123 ถนนกาแฟ แขวงเครื่องดื่ม เขตร้านอาหาร กรุงเทพฯ 10110</p>
            </div>
        `;
  }
}

// Add map loading error handler
window.addEventListener('load', function() {
  const iframe = document.querySelector('.contact-map iframe');
  if (iframe) {
    iframe.addEventListener('error', handleMapError);

    // Check if iframe loaded successfully after 5 seconds
    setTimeout(() => {
      if (!iframe.contentDocument && !iframe.contentWindow) {
        console.warn('Map iframe may not have loaded properly');
      }
    }, 5000);
  }
});

// Export functions for global access
window.CoffeeHouseApp = {
  loadMenu,
  searchMenu,
  filterByPrice,
  sortMenu,
  scrollToMenu,
  scrollToAbout,
  showNotification,
  initializeMap,
  handleMapError
};