order.astro raw

   1  ---
   2  import Base from '../../layouts/Base.astro';
   3  ---
   4  <Base title="Поръчка">
   5    <section class="section">
   6      <div class="container">
   7        <a href="/user" style="display:inline-block;margin-bottom:1.5rem;color:var(--primary,#2a9d8f);text-decoration:none;font-size:1rem;">&larr; <span data-i18n="adminBack">Назад</span></a>
   8        <div id="order-detail">Зареждане...</div>
   9      </div>
  10    </section>
  11  </Base>
  12  
  13  <script>
  14  import { escapeHtml, formatLv } from '../../lib/cart-client';
  15  import { t } from '../../lib/i18n';
  16  
  17  function orderStatusLabel(s: string): string {
  18    const keys: Record<string, string> = {
  19      pending: 'adminStatusPending', paid: 'adminStatusPaid', failed: 'adminStatusFailed',
  20      expired: 'adminStatusExpired', shipped: 'adminStatusShipped', delivered: 'adminStatusDelivered', cancelled: 'adminStatusCancelled',
  21    };
  22    return keys[s] ? t(keys[s]) : s;
  23  }
  24  function orderMethodLabel(m: string): string {
  25    const keys: Record<string, string> = {
  26      stripe: 'payStripe', lightning: 'payLightning', onchain: 'payOnchain',
  27      bank: 'payBank', cod: 'payCod',
  28    };
  29    return keys[m] ? t(keys[m]) : m;
  30  }
  31  
  32  async function loadOrder() {
  33    const p = new URLSearchParams(location.search);
  34    const id = p.get('id');
  35    if (!id) {
  36      document.getElementById('order-detail')!.textContent = t('orderMissingId');
  37      return;
  38    }
  39    const token = localStorage.getItem('token');
  40    if (!token) {
  41      document.getElementById('order-detail')!.textContent = t('orderLogin');
  42      return;
  43    }
  44    const r = await fetch(`/api/user/orders/${id}`, { headers: { Authorization: 'Bearer ' + token } });
  45    if (!r.ok) {
  46      document.getElementById('order-detail')!.textContent = t('orderNotFound');
  47      return;
  48    }
  49    const view = await r.json();
  50  
  51    const items = (view.items || []).map((i: any) =>
  52      `<div class="order-item"><span>${escapeHtml(i.name)} × ${i.qty} бр.</span><span>${formatLv(i.price_cents * i.qty)}</span></div>`
  53    ).join('');
  54  
  55    document.getElementById('order-detail')!.innerHTML = `
  56      <h1>${t('orderId')} <span class="order-id">${view.id.slice(0,8)}</span></h1>
  57      <p class="order-status"><strong>${orderStatusLabel(view.status)}</strong></p>
  58      <div class="order-items">
  59        ${items}
  60        <div class="order-item order-sub"><span>${t('checkoutSubtotal')}</span><span>${formatLv(view.subtotal_cents)}</span></div>
  61        <div class="order-item order-sub"><span>${t('checkoutShippingCost')}</span><span>${view.shipping_cents === 0 ? t('checkoutFreeShipping') : formatLv(view.shipping_cents)}</span></div>
  62        <div class="order-item order-total"><strong>${t('checkoutTotal')}</strong><strong>${formatLv(view.total_cents)}</strong></div>
  63      </div>
  64      <h2>${t('checkoutShipping')}</h2>
  65      <p><strong>${t('name')}:</strong> ${escapeHtml(view.customer_name)}</p>
  66      <p><strong>${t('phone')}:</strong> ${escapeHtml(view.customer_phone || '—')}</p>
  67      <h2>${t('checkoutPayment')}: ${orderMethodLabel(view.payment_method)}</h2>
  68      ${view.payment_method === 'lightning' && view.payment?.pr ? `<code class="invoice-code">${escapeHtml(view.payment.pr)}</code>` : ''}
  69      ${view.payment_method === 'onchain' && view.payment?.checkoutUrl ? `<p><a class="btn btn-primary" href="${escapeHtml(view.payment.checkoutUrl)}">${t('payOnchain')}</a></p>` : ''}
  70    `;
  71    loadOrder();
  72  }
  73  
  74  window.addEventListener('lang-changed', () => { loadOrder(); });
  75  </script>
  76  
  77  <style>
  78    .order-id { font-family: monospace; font-size: 0.8em; color: var(--text-light,#888); }
  79    .order-items { max-width: 480px; margin: 1rem 0; }
  80    .order-item { display: flex; justify-content: space-between; padding: 0.5rem 0; border-bottom: 1px solid #eee; }
  81    .order-total { border-bottom: none; font-size: 1.1rem; }
  82    .invoice-code { display: block; word-break: break-all; background: #f5f5f5; padding: 0.75rem; border-radius: 8px; font-size: 0.8rem; max-width: 640px; margin: 0.5rem 0; }
  83  </style>
  84