ui.js

4.79 KB
12/09/2025 08:18
JS
ui.js
/**
 * js/ui.js
 * Handles all UI rendering and DOM manipulations.
 */

import {formatDate} from './utils.js'; // Import utility for date formatting

const ui = {
  // DOM Elements
  carListContainer: document.getElementById('car-list'),
  notificationContainer: document.getElementById('notification'),
  loadingSpinner: document.getElementById('loading-spinner'),
  mobileMenuButton: document.getElementById('mobile-menu-btn'),
  navMenu: document.getElementById('nav-menu'),
  heroSection: document.getElementById('home'), // For scroll to
  carsSection: document.getElementById('cars'), // For scroll to
  howItWorksSection: document.getElementById('how-it-works'), // For scroll to
  contactSection: document.getElementById('contact'), // For scroll to

  /**
   * Creates and returns a DOM element for a single car card.
   * @param {object} car - Car data object.
   * @returns {HTMLElement} The car card element.
   */
  renderCarCard(car) {
    const card = document.createElement('div');
    card.className = 'car-card';
    card.innerHTML = `
            <img src="${car.imageUrl}" alt="${car.brand} ${car.model}" loading="lazy" width="400" height="250">
            <div class="car-card-content">
                <h3>${car.brand} ${car.model}</h3>
                <p><i class="fas fa-car"></i> ${car.type} | <i class="fas fa-users"></i> ${car.seats} ที่นั่ง</p>
                <p class="price">฿${car.pricePerDay.toLocaleString()} / วัน</p>
                <button class="btn btn-primary" data-car-id="${car.id}">ดูรายละเอียด</button>
            </div>
        `;
    return card;
  },

  /**
   * Renders a list of car cards into the car list container.
   * @param {Array<object>} cars - An array of car data objects.
   */
  renderCarList(cars) {
    if (!this.carListContainer) {
      console.warn("Car list container not found.");
      return;
    }
    this.carListContainer.innerHTML = ''; // Clear previous list

    if (cars && cars.length > 0) {
      cars.forEach(car => {
        this.carListContainer.appendChild(this.renderCarCard(car));
      });
    } else {
      this.carListContainer.innerHTML = `
                <div class="no-results">
                    <i class="fas fa-exclamation-circle"></i>
                    <p>ไม่พบรถยนต์ที่ตรงกับเงื่อนไขการค้นหาของคุณ</p>
                    <p>ลองเปลี่ยนเงื่อนไขหรือดูรถทั้งหมดของเรา</p>
                </div>
            `;
    }
  },

  /**
   * Displays a notification message to the user.
   * @param {string} message - The message to display.
   * @param {'info'|'success'|'error'|'warning'} type - Type of notification.
   */
  showNotification(message, type = 'info') {
    if (!this.notificationContainer) {
      console.warn("Notification container not found.");
      return;
    }
    this.notificationContainer.innerHTML = `<div class="alert alert-${type}">${message}</div>`;
    this.notificationContainer.style.display = 'block';

    // Automatically hide after a few seconds (CSS handles fade out)
    setTimeout(() => {
      this.notificationContainer.style.display = 'none';
      this.notificationContainer.innerHTML = ''; // Clear content
    }, 3000); // Should match CSS animation duration
  },

  /**
   * Shows or hides the global loading spinner.
   * @param {boolean} isLoading - True to show, false to hide.
   */
  showLoading(isLoading) {
    if (this.loadingSpinner) {
      this.loadingSpinner.style.display = isLoading ? 'flex' : 'none';
    }
  },

  /**
   * Toggles the mobile navigation menu's active state.
   */
  toggleMobileMenu() {
    if (this.navMenu && this.mobileMenuButton) {
      const expanded = this.navMenu.classList.toggle('active');
      this.mobileMenuButton.classList.toggle('active'); // For rotating icon
    }
  },

  /**
   * Closes the mobile navigation menu if it's open.
   */
  closeMobileMenu() {
    if (this.navMenu && this.mobileMenuButton && this.navMenu.classList.contains('active')) {
      this.navMenu.classList.remove('active');
      this.mobileMenuButton.classList.remove('active');
    }
  },

  /**
   * Updates the active state of navigation links based on the current hash.
   * @param {string} currentHash - The current URL hash (e.g., "#cars").
   */
  updateActiveNavLink(currentHash) {
    document.querySelectorAll('.nav-link').forEach(link => {
      link.classList.remove('active');
      if (link.getAttribute('href') === currentHash) {
        link.classList.add('active');
      }
    });
  }

  // You might add more specific UI rendering functions here for:
  // - renderCarDetails(car) to show a popup or dedicated section for a single car
  // - renderBookingForm(car)
  // - renderUserDashboard()
};

export default ui;