dashboard.js

13.29 KB
06/11/2025 15:25
JS
dashboard.js
// Dashboard Functions

// Load dashboard stats
async function loadDashboardStats() {
  try {
    const stats = await mockApi.getDashboardStats();

    document.getElementById('totalUsers').textContent = stats.totalUsers.toLocaleString();
    document.getElementById('totalRevenue').textContent = formatCurrency(stats.totalRevenue);
    document.getElementById('totalOrders').textContent = stats.totalOrders.toLocaleString();
    document.getElementById('totalProducts').textContent = stats.totalProducts.toLocaleString();
  } catch (error) {
    console.error('Error loading stats:', error);
    showToast('Failed to load dashboard stats', 'error');
  }
}

// Load recent activities
async function loadActivities() {
  try {
    const activities = await mockApi.getActivities();
    const activityList = document.getElementById('activityList');

    if (!activityList) return;

    activityList.innerHTML = activities.map(activity => {
      const iconColors = {
        user: '#6366f1',
        order: '#10b981',
        product: '#f59e0b',
        system: '#8b5cf6'
      };

      const icons = {
        user: 'fa-user',
        order: 'fa-shopping-cart',
        product: 'fa-box',
        system: 'fa-cog'
      };

      return `
                <div class="activity-item">
                    <div class="activity-icon" style="background-color: ${iconColors[activity.type]}">
                        <i class="fas ${icons[activity.type]}"></i>
                    </div>
                    <div class="activity-content">
                        <div class="activity-title">${activity.title}</div>
                        <div class="activity-description">${activity.description}</div>
                    </div>
                    <div class="activity-time">${formatRelativeTime(activity.time)}</div>
                </div>
            `;
    }).join('');
  } catch (error) {
    console.error('Error loading activities:', error);
  }
}

// Load products
async function loadProducts() {
  try {
    const products = await mockApi.getProducts();
    const productsGrid = document.getElementById('productsGrid');

    if (!productsGrid) return;

    productsGrid.innerHTML = products.map(product => `
            <div class="product-card" data-product-id="${product.id}">
                <img src="${product.image}" alt="${product.name}" class="product-image">
                <div class="product-info">
                    <div class="product-category">${product.category}</div>
                    <div class="product-name">${product.name}</div>
                    <div class="product-price">${formatCurrency(product.price)}</div>
                    <div class="product-stock">Stock: ${product.stock}</div>
                    <div class="product-actions">
                        <button class="action-btn edit" onclick="editProduct(${product.id})" title="Edit">
                            <i class="fas fa-edit"></i>
                        </button>
                        <button class="action-btn delete" onclick="deleteProduct(${product.id})" title="Delete">
                            <i class="fas fa-trash"></i>
                        </button>
                    </div>
                </div>
            </div>
        `).join('');
  } catch (error) {
    console.error('Error loading products:', error);
    showToast('Failed to load products', 'error');
  }
}

// Edit product
async function editProduct(productId) {
  try {
    showLoading();

    // Find product card
    const productCard = document.querySelector(`[data-product-id="${productId}"]`);
    if (!productCard) {
      showToast('Product not found', 'error');
      return;
    }

    // Extract product data from the card
    const productName = productCard.querySelector('.product-name')?.textContent || '';
    const productCategory = productCard.querySelector('.product-category')?.textContent || '';
    const productPriceText = productCard.querySelector('.product-price')?.textContent || '$0';
    const productStockText = productCard.querySelector('.product-stock')?.textContent || 'Stock: 0';

    // Parse price and stock
    const productPrice = productPriceText.replace(/[^0-9.]/g, '');
    const productStock = productStockText.replace(/[^0-9]/g, '');

    // Populate the form
    const productForm = document.getElementById('productForm');
    const modalTitle = document.querySelector('#productModal .modal-header h2');

    if (productForm && modalTitle) {
      modalTitle.textContent = 'Edit Product';
      productForm.querySelector('input[name="name"]').value = productName;
      productForm.querySelector('select[name="category"]').value = productCategory;
      productForm.querySelector('input[name="price"]').value = productPrice;
      productForm.querySelector('input[name="stock"]').value = productStock;

      // Store product ID in form for update
      productForm.dataset.editProductId = productId;
      productForm.dataset.editMode = 'true';

      openModal('productModal');
    }
  } catch (error) {
    console.error('Error editing product:', error);
    showToast('Failed to load product data', 'error');
  } finally {
    hideLoading();
  }
}

// Update product
async function updateProduct(productId, productData) {
  try {
    showLoading();

    const response = await mockApi.updateProduct(productId, productData);

    if (response.success) {
      showToast('Product updated successfully', 'success');
      closeModal('productModal');
      loadProducts();
    }
  } catch (error) {
    console.error('Error updating product:', error);
    showToast('Failed to update product', 'error');
  } finally {
    hideLoading();
  }
}

// Delete product
async function deleteProduct(productId) {
  if (!confirm('Are you sure you want to delete this product?')) return;

  try {
    showLoading();

    const response = await mockApi.deleteProduct(productId);

    if (response.success) {
      showToast('Product deleted successfully', 'success');
      loadProducts();
    }
  } catch (error) {
    console.error('Error deleting product:', error);
    showToast('Failed to delete product', 'error');
  } finally {
    hideLoading();
  }
}

// Load orders
async function loadOrders() {
  try {
    const orders = await mockApi.getOrders();
    const ordersTableBody = document.getElementById('ordersTableBody');

    if (!ordersTableBody) return;

    ordersTableBody.innerHTML = orders.map(order => `
            <tr data-order-id="${order.id}">
                <td><strong>${order.id}</strong></td>
                <td>${order.customer}</td>
                <td>${order.products} items</td>
                <td><strong>${formatCurrency(order.total)}</strong></td>
                <td><span class="status-badge ${order.status}">${order.status}</span></td>
                <td>${formatDate(order.date)}</td>
                <td class="table-actions-cell">
                    <button class="action-btn" onclick="viewOrder('${order.id}')" title="View">
                        <i class="fas fa-eye"></i>
                    </button>
                    <button class="action-btn edit" onclick="editOrder('${order.id}')" title="Edit">
                        <i class="fas fa-edit"></i>
                    </button>
                    <button class="action-btn delete" onclick="deleteOrder('${order.id}')" title="Delete">
                        <i class="fas fa-trash"></i>
                    </button>
                </td>
            </tr>
        `).join('');
  } catch (error) {
    console.error('Error loading orders:', error);
    showToast('Failed to load orders', 'error');
  }
}

// View order
async function viewOrder(orderId) {
  try {
    showLoading();

    // Get order details from API
    const orderDetails = await mockApi.getOrderDetails(orderId);

    if (!orderDetails) {
      showToast('Order not found', 'error');
      return;
    }

    // Populate order details modal
    document.getElementById('detailOrderId').textContent = orderDetails.id;

    const statusBadge = document.getElementById('detailStatus');
    statusBadge.textContent = orderDetails.status;
    statusBadge.className = `status-badge ${orderDetails.status}`;

    document.getElementById('detailDate').textContent = formatDate(orderDetails.date);
    document.getElementById('detailTotal').textContent = formatCurrency(orderDetails.total);

    // Customer information
    document.getElementById('detailCustomerName').textContent = orderDetails.customer.name;
    document.getElementById('detailCustomerEmail').textContent = orderDetails.customer.email;
    document.getElementById('detailCustomerPhone').textContent = orderDetails.customer.phone;
    document.getElementById('detailCustomerAddress').textContent = orderDetails.customer.address;

    // Order items
    const orderItemsBody = document.getElementById('detailOrderItems');
    orderItemsBody.innerHTML = orderDetails.items.map(item => `
            <tr>
                <td>${item.product}</td>
                <td>${item.quantity}</td>
                <td>${formatCurrency(item.price)}</td>
                <td><strong>${formatCurrency(item.quantity * item.price)}</strong></td>
            </tr>
        `).join('');

    // Payment information
    document.getElementById('detailPaymentMethod').textContent = orderDetails.payment.method;
    document.getElementById('detailPaymentStatus').textContent = orderDetails.payment.status;
    document.getElementById('detailTransactionId').textContent = orderDetails.payment.transactionId;

    // Shipping information
    document.getElementById('detailShippingMethod').textContent = orderDetails.shipping.method;
    document.getElementById('detailTrackingNumber').textContent = orderDetails.shipping.trackingNumber;
    document.getElementById('detailEstimatedDelivery').textContent = formatDate(orderDetails.shipping.estimatedDelivery);

    // Order summary
    document.getElementById('detailSubtotal').textContent = formatCurrency(orderDetails.subtotal);
    document.getElementById('detailShipping').textContent = formatCurrency(orderDetails.shippingCost);
    document.getElementById('detailTax').textContent = formatCurrency(orderDetails.tax);
    document.getElementById('detailGrandTotal').textContent = formatCurrency(orderDetails.total);

    openModal('orderDetailsModal');
  } catch (error) {
    console.error('Error viewing order:', error);
    showToast('Failed to load order details', 'error');
  } finally {
    hideLoading();
  }
}

// Print order
function printOrder() {
  window.print();
}

// Edit order
async function editOrder(orderId) {
  try {
    showLoading();

    // Find order row
    const orderRow = document.querySelector(`tr[data-order-id="${orderId}"]`);
    if (!orderRow) {
      showToast('Order not found', 'error');
      return;
    }

    // Extract order data from the row
    const cells = orderRow.querySelectorAll('td');
    const orderIdText = cells[0]?.textContent || '';
    const customer = cells[1]?.textContent || '';
    const productsText = cells[2]?.textContent || '0 items';
    const totalText = cells[3]?.textContent || '$0';
    const status = cells[4]?.querySelector('.status-badge')?.textContent || 'pending';

    // Parse values
    const products = productsText.replace(/[^0-9]/g, '');
    const total = totalText.replace(/[^0-9.]/g, '');

    // Populate the form
    const orderForm = document.getElementById('orderForm');
    const modalTitle = document.getElementById('orderModalTitle');

    if (orderForm && modalTitle) {
      modalTitle.textContent = 'Edit Order';
      orderForm.querySelector('input[name="orderId"]').value = orderIdText;
      orderForm.querySelector('input[name="customer"]').value = customer;
      orderForm.querySelector('input[name="products"]').value = products;
      orderForm.querySelector('input[name="total"]').value = total;
      orderForm.querySelector('select[name="status"]').value = status;

      // Store order ID in form for update
      orderForm.dataset.editOrderId = orderId;
      orderForm.dataset.editMode = 'true';

      openModal('orderModal');
    }
  } catch (error) {
    console.error('Error editing order:', error);
    showToast('Failed to load order data', 'error');
  } finally {
    hideLoading();
  }
}

// Update order
async function updateOrder(orderId, orderData) {
  try {
    showLoading();

    const response = await mockApi.updateOrder(orderId, orderData);

    if (response.success) {
      showToast('Order updated successfully', 'success');
      closeModal('orderModal');
      loadOrders();
    }
  } catch (error) {
    console.error('Error updating order:', error);
    showToast('Failed to update order', 'error');
  } finally {
    hideLoading();
  }
}

// Delete order
async function deleteOrder(orderId) {
  if (!confirm('Are you sure you want to delete this order?')) return;

  try {
    showLoading();

    const response = await mockApi.deleteOrder(orderId);

    if (response.success) {
      showToast('Order deleted successfully', 'success');
      loadOrders();
    }
  } catch (error) {
    console.error('Error deleting order:', error);
    showToast('Failed to delete order', 'error');
  } finally {
    hideLoading();
  }
}

// Initialize dashboard
function initDashboard() {
  loadDashboardStats();
  loadActivities();
  initCharts();
}

// Initialize when dashboard page is active
document.addEventListener('DOMContentLoaded', () => {
  const dashboardPage = document.getElementById('dashboard-page');
  if (dashboardPage && dashboardPage.classList.contains('active')) {
    initDashboard();
  }
});