Webbserver - Love Blomberg

Show sourcecode

The following files exists in this folder. Click to view.

public_html/crumbs/admin/orders/

api.php
orders.php
sendmail.php
statusdisplay.php

orders.php

159 lines UTF-8 Windows (CRLF)
<?php
$basePath 
'../../';
$pageTitle 'Hantera Beställningar';
$activePage 'admin-orders';
include(
'../../includes/header.php');
?>

<div class="page-header">
  <div class="page-header-text">
    <h1>Beställningar</h1>
    <p>Hantera och uppdatera orderstatus. <span id="update-indicator" class="muted">Uppdateras automatiskt...</span></p>
  </div>
</div>

<div id="orders-container">
  <p class="muted">Laddar beställningar...</p>
</div>

<script>
  const statusLabels = {
    'pending': 'Väntar',
    'preparing': 'Tillagas',
    'done': 'Klar',
    'delivered': 'Levererad'
  };

  const statusClasses = {
    'pending': 'status-pending',
    'preparing': 'status-preparing',
    'done': 'status-done',
    'delivered': 'status-delivered'
  };

  function buildOrderCard(order) {
    const chips = order.items.map(item =>
      `<span class="order-item-chip"><span class="item-qty">${item.amount}x</span> ${escapeHtml(item.name)}</span>`
    ).join('');

    const instructions = order.custom_instructions ?
      `<span class="order-instructions"><span class="material-symbols-rounded" style="font-size:16px;vertical-align:middle">edit_note</span> ${escapeHtml(order.custom_instructions)}</span>` :
      '<span></span>';

    return `
  <div class="card order-card ${statusClasses[order.status]}" data-order-id="${order.order_id}">
    <div class="order-header">
      <div>
        <h3>#${order.order_id} &mdash; ${escapeHtml(order.fullname || order.username)}</h3>
        <span class="order-meta">${order.order_time}</span>
      </div>
      <div class="order-status-area">
        <div class="status-btn-group">
          <button class="status-btn status-btn-pending${order.status === 'pending' ? ' active' : ''}" onclick="updateStatus(this, ${order.order_id}, 'pending')">Väntar</button>
          <button class="status-btn status-btn-preparing${order.status === 'preparing' ? ' active' : ''}" onclick="updateStatus(this, ${order.order_id}, 'preparing')">Tillagas</button>
          <button class="status-btn status-btn-done${order.status === 'done' ? ' active' : ''}" onclick="updateStatus(this, ${order.order_id}, 'done')">Klar</button>
          <button class="status-btn status-btn-delivered${order.status === 'delivered' ? ' active' : ''}" onclick="updateStatus(this, ${order.order_id}, 'delivered')">Levererad</button>
        </div>
      </div>
    </div>
    <div style="display:inline-flex;align-items:center;gap:8px;background:var(--bg);border:1px solid var(--border);border-radius:6px;padding:4px 10px;margin-bottom:8px;">
      <span class="material-symbols-rounded" style="font-size:16px;color:var(--primary)">confirmation_number</span>
      <span style="font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;">Orderkod</span>
      <span style="font-size:15px;font-weight:700;letter-spacing:.14em;">${String(order.order_id).padStart(4, '0')}</span>
    </div>
    <div class="order-items-compact">${chips}</div>
    <div class="order-footer">
      ${instructions}
      <span class="order-total">${order.total_price} kr</span>
    </div>
  </div>`;
  }

  function renderOrders(orders) {
    const container = document.getElementById('orders-container');
    const archiveOpen = container.querySelector('details')?.open ?? false;

    if (orders.length === 0) {
      container.innerHTML = '<div class="alert alert-warning"><span class="material-symbols-rounded" style="font-size:18px">info</span> Inga beställningar hittades.</div>';
      return;
    }

    const active = orders.filter(o => o.status !== 'delivered');
    const delivered = orders.filter(o => o.status === 'delivered');

    let html = '';

    if (active.length === 0) {
      html += '<div class="alert alert-warning" style="margin-bottom:16px"><span class="material-symbols-rounded" style="font-size:18px">info</span> Inga aktiva beställningar.</div>';
    } else {
      active.forEach(o => {
        html += buildOrderCard(o);
      });
    }

    if (delivered.length > 0) {
      html += `
    <details${archiveOpen ? ' open' : ''} style="margin-top:24px">
      <summary style="cursor:pointer;font-weight:600;color:var(--muted);padding:8px 0;list-style:none;display:flex;align-items:center;gap:8px;user-select:none;">
        <span class="material-symbols-rounded" style="font-size:18px">inventory_2</span>
        Arkiverade beställningar (${delivered.length})
      </summary>
      <div style="margin-top:12px">
        ${delivered.map(o => buildOrderCard(o)).join('')}
      </div>
    </details>`;
    }

    container.innerHTML = html;
  }

  function escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }

  // Hämta orders från api och sedan kör redner orders för att visa kort.
  function fetchOrders() {
    fetch('api.php')
      .then(res => res.json())
      .then(orders => {
        renderOrders(orders);
        document.getElementById('update-indicator').textContent = 'Senast uppdaterad: ' + new Date().toLocaleTimeString('sv-SE');
      })
      .catch(err => {
        console.error('Kunde inte hämta beställningar:', err);
      });
  }

  function updateStatus(btnEl, orderId, newStatus) {
    fetch('api.php', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          order_id: parseInt(orderId),
          status: newStatus
        })
      })
      .then(res => res.json())
      .then(data => {
        if (data.success) {
          const card = btnEl.closest('.order-card');
          card.querySelectorAll('.status-btn').forEach(b => b.classList.remove('active'));
          btnEl.classList.add('active');
          Object.values(statusClasses).forEach(cls => card.classList.remove(cls));
          card.classList.add(statusClasses[newStatus]);
        }
      })
      .catch(err => {
        console.error('Kunde inte uppdatera status:', err);
      });
  }

  fetchOrders();
  setInterval(fetchOrders, 5000);
</script>

<?php include('../../includes/footer.php'); ?>