Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/fredy-rizo/ecommerce-delivery-frontend/llms.txt

Use this file to discover all available pages before exploring further.

Order management gives admin staff a complete view of every sale in the system. The SalesReport component renders a paginated, Excel-style table where each row represents one sale. Admins can change the payment status, update the delivery tracking history, inspect uploaded payment proof images, and export the full list to an .xlsx file with one click. Customers have a separate, lighter view at /shoppingList that shows only their own orders and auto-refreshes every five seconds.

Route

/sales renders pages/sales/salesPage.vue, which mounts the SalesReport component. The page requires admin role (2) — validateUser({ rol: 2 }) is called inside every data-fetching function and redirects to /login when the check fails.

Sales table columns

ColumnFieldDescription
ComprobanteimgPayPayment proof thumbnail / “Ver” button
Estadostatus.nameCurrent payment status
TotaltotalOrder total
DomicilioaddressDelivery address
CiudadcityDelivery city
FechadateproofOrder date
CorreoemailCustomer email
IdentificacionidentificationCustomer ID number
Nombrename_clientCustomer first name
ApellidolastName_clientCustomer last name
Telefonophone_numberCustomer phone

Loading sales

Sales are fetched server-side via Quasar’s q-table @request event. The handler calls getSales(), which uses Authorization: Basic <token>:
let res = await fetch(
  process.env.API_SERVER +
    `/api/sale/all-list/${pagination.value.page}/${pagination.value.rowsPerPage}`,
  {
    method: "POST",
    mode: "cors",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Basic " + sessionUser.token,
    },
    body: JSON.stringify(filter.value),
  }
);
The server response populates pagination.rowsNumber so Quasar can render the correct page count without fetching all records at once.

Filtering sales

The BarFilterSales component calls getDataFilter(query) in the parent whenever the search input changes. For a non-empty query the parent fires:
const response = await fetch(
  `${process.env.API_SERVER}/api/sale/get-search/${encodeURIComponent(query)}`,
  {
    method: "POST",
    headers,
  }
);
Clearing the search resets the list via resetListSale(), which re-runs getSales() from page 1.

Changing order status

Clicking the blue checklist icon (checklist) in the actions column sets dialogchangestatus = true and opens ChangeStatusSale inside a maximised q-dialog. The component shows the current payment proof image (if any) and a q-select with five status options:
const options = ref([
  { name: "Pagado",     value: "1" },
  { name: "Pendiente",  value: "2" },
  { name: "Cancelado",  value: "3" },
  { name: "Validando",  value: "4" },
  { name: "Entregado",  value: "5" },
]);
Saving posts to POST /api/sale/status-change/:idSale with the selected status object:
const res = await fetch(
  process.env.API_SERVER + `/api/sale/status-change/${props.idsale}`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${sessionUser.token}`,
    },
    body: JSON.stringify({
      status: {
        name: status.value.name,
        value: status.value.value,
      },
    }),
  }
);
On success the parent list is reloaded via the reloadlist prop callback and the dialog closes.

Viewing delivery tracking

Clicking the green local_shipping icon opens DeliveryTracking inside a full-width q-dialog. The component receives the delivery_status array from the row and the sale ID. See the Delivery Tracking page for the full update flow.

Viewing payment proof

When a sale row has a non-empty imgPay array, a Ver button appears in the Comprobante column:
<q-btn
  v-if="
    props.row.imgPay &&
    props.row.imgPay.length > 0 &&
    props.row.imgPay[0].imgPay
  "
  label="Ver"
  color="primary"
  size="sm"
  @click="() => {
    imgPreview = props.row.imgPay[0].imgPay;
    dialogImg = true;
  }"
/>
Clicking opens a maximised dark dialog that displays the full-resolution proof image.

Excel export

The export button triggers excel_export(), which POSTs the current filter object to the export endpoint and auto-downloads the response blob as ventas.xlsx:
const excel_export = async () => {
  let res = await fetch(
    process.env.API_SERVER + `/api/sale/export-list-sale-xlsx`,
    {
      method: "POST",
      mode: "cors",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${sessionUser.token}`,
      },
      body: JSON.stringify(filter.value),
    }
  );

  if (!res.ok) throw new Error("Error al generar el archivo: " + res.status);

  const bolb = await res.blob();
  const urldownload = URL.createObjectURL(bolb);

  const automatico = document.createElement("a");
  automatico.href = urldownload;
  automatico.download = "ventas.xlsx";
  document.body.appendChild(automatico);
  automatico.click();
  document.body.removeChild(automatico);
};
The admin sales list endpoint (/api/sale/all-list) uses Authorization: Basic <token>, while the Excel export endpoint (/api/sale/export-list-sale-xlsx) uses Authorization: Bearer <token>. Use the correct scheme for each call exactly as shown in the source.

Customer order history

Customers can view their own purchases at /shoppingList, rendered by pages/shopping/ShoppingList.vue. The page calls POST /api/sale/list-sale/:pag/:perpage with Authorization: Basic <token> and displays a table with Total, Estado, and Codigo columns.
let res = await fetch(
  process.env.API_SERVER +
    `/api/sale/list-sale/${pagination.value.pag}/${pagination.value.perpage}`,
  {
    method: "POST",
    mode: "cors",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Basic " + sessionUser.token,
    },
  }
);
The page sets up a setInterval on mount to call getShopping() every 5 seconds so status changes made by the admin are reflected in near-real-time without a manual refresh:
onMounted(() => {
  getShopping();
  refreshInterval = setInterval(getShopping, 5000);
});

onBeforeUnmount(() => {
  clearInterval(refreshInterval);
});
From this view, customers can also open the DeliveryStatusList dialog (shipping icon) and upload a payment proof (payments icon, shown only when status.value == 2 or 3).

Build docs developers (and LLMs) love