import { api } from "../lib/api.js";
import { on } from "../lib/bus.js";
import { navigateToItem } from "../lib/router.js";
function formatDate(dateStr) {
if (!dateStr) return "—";
const d = new Date(dateStr);
return d.toLocaleString("es-AR", { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit" });
}
function statusLabel(status) {
const map = {
pending: "Pendiente",
processing: "Procesando",
"on-hold": "En espera",
completed: "Completado",
cancelled: "Cancelado",
refunded: "Reembolsado",
failed: "Fallido",
};
return map[status] || status;
}
function statusColor(status) {
const map = {
pending: "#f59e0b",
processing: "#3b82f6",
"on-hold": "#8b5cf6",
completed: "#22c55e",
cancelled: "#6b7280",
refunded: "#ec4899",
failed: "#ef4444",
};
return map[status] || "#8aa0b5";
}
class OrdersCrud extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.orders = [];
this.selectedOrder = null;
this.loading = false;
// Paginación
this.page = 1;
this.limit = 50;
this.totalPages = 1;
this.totalOrders = 0;
this.shadowRoot.innerHTML = `
Detalle del Pedido
Seleccioná un pedido para ver los detalles
`;
}
connectedCallback() {
this.shadowRoot.getElementById("btnRefresh").onclick = () => this.loadOrders();
// Paginación
this.shadowRoot.getElementById("limitSelect").onchange = (e) => {
this.limit = parseInt(e.target.value);
this.page = 1;
this.loadOrders();
};
this.shadowRoot.getElementById("btnPrev").onclick = () => {
if (this.page > 1) {
this.page--;
this.loadOrders();
}
};
this.shadowRoot.getElementById("btnNext").onclick = () => {
if (this.page < this.totalPages) {
this.page++;
this.loadOrders();
}
};
// Escuchar cambios de ruta para deep-linking
this._unsubRouter = on("router:viewChanged", ({ view, params }) => {
if (view === "orders" && params.id) {
this.selectOrderById(params.id);
}
});
// Escuchar nuevos pedidos para actualizar automáticamente
this._unsubOrderCreated = on("order:created", ({ order_id }) => {
console.log("[orders-crud] order:created received, order_id:", order_id);
this.refreshWithRetry(order_id);
});
this.loadOrders();
}
disconnectedCallback() {
this._unsubRouter?.();
this._unsubOrderCreated?.();
}
/**
* Refresca la lista de pedidos con retry si el pedido esperado no aparece
* WooCommerce puede tardar en devolver un pedido recién creado
*/
async refreshWithRetry(expectedOrderId, attempt = 1) {
const maxAttempts = 3;
const delays = [500, 2000, 4000]; // ms entre intentos
// Esperar antes de refrescar
if (attempt > 1) {
await new Promise(r => setTimeout(r, delays[attempt - 1] || 2000));
} else {
// Primer intento: pequeño delay para dar tiempo a WooCommerce
await new Promise(r => setTimeout(r, 500));
}
await this.loadOrders();
// Verificar si el pedido esperado apareció
if (expectedOrderId) {
const found = this.orders.find(o => o.id === expectedOrderId);
if (!found && attempt < maxAttempts) {
console.log(`[orders-crud] order ${expectedOrderId} not found, retry ${attempt + 1}/${maxAttempts}...`);
return this.refreshWithRetry(expectedOrderId, attempt + 1);
}
if (found) {
console.log(`[orders-crud] order ${expectedOrderId} found on attempt ${attempt}`);
}
}
}
async loadOrders() {
const container = this.shadowRoot.getElementById("ordersTable");
container.innerHTML = `Cargando pedidos...
`;
try {
const result = await api.listOrders({ page: this.page, limit: this.limit });
this.orders = result.items || [];
// Actualizar paginación
if (result.pagination) {
this.totalPages = result.pagination.pages || 1;
this.totalOrders = result.pagination.total || 0;
}
this.renderTable();
this.updatePagination();
// Si hay un pedido pendiente de selección (deep-link), seleccionarlo
if (this._pendingOrderId) {
const order = this.orders.find(o => o.id === this._pendingOrderId);
if (order) {
this.selectOrder(order, { updateUrl: false });
}
this._pendingOrderId = null;
}
} catch (e) {
console.error("[orders-crud] Error loading orders:", e);
container.innerHTML = `Error cargando pedidos: ${e.message}
`;
}
}
updatePagination() {
const pageInfo = this.shadowRoot.getElementById("pageInfo");
const totalInfo = this.shadowRoot.getElementById("totalInfo");
const btnPrev = this.shadowRoot.getElementById("btnPrev");
const btnNext = this.shadowRoot.getElementById("btnNext");
const limitSelect = this.shadowRoot.getElementById("limitSelect");
pageInfo.textContent = `Página ${this.page} de ${this.totalPages}`;
totalInfo.textContent = `${this.totalOrders.toLocaleString("es-AR")} pedidos`;
btnPrev.disabled = this.page <= 1;
btnNext.disabled = this.page >= this.totalPages;
limitSelect.value = String(this.limit);
}
renderTable() {
const container = this.shadowRoot.getElementById("ordersTable");
if (this.orders.length === 0) {
container.innerHTML = `No hay pedidos
`;
return;
}
container.innerHTML = `
| # |
Tipo |
Estado |
Envío |
Pago |
Cliente |
Total |
Fecha |
${this.orders.map(order => {
const isSelected = this.selectedOrder?.id === order.id;
const customerName = [order.billing.first_name, order.billing.last_name].filter(Boolean).join(" ") || order.billing.phone || "—";
return `
| ${order.id} |
${order.is_test ? 'TEST' : 'REAL'}
${order.source === "whatsapp" ? 'WA' : 'WEB'}
|
${statusLabel(order.status)} |
${order.is_delivery ? 'DEL' : 'RET'} |
${order.is_cash ? '$' : 'MP'}
${order.is_paid ? '✓' : '✗'}
|
${customerName} |
$${Number(order.total || 0).toLocaleString("es-AR")} |
${formatDate(order.date_created)} |
`;
}).join("")}
`;
container.querySelectorAll("tr[data-order-id]").forEach(row => {
row.onclick = () => {
const orderId = parseInt(row.dataset.orderId);
const order = this.orders.find(o => o.id == orderId);
if (order) {
this.selectOrder(order);
}
};
});
}
selectOrder(order, { updateUrl = true } = {}) {
this.selectedOrder = order;
this.renderTable();
this.renderDetail();
// Actualizar URL
if (updateUrl && order) {
navigateToItem("orders", order.id);
}
}
selectOrderById(orderId) {
const id = parseInt(orderId);
if (!id) return;
// Si ya tenemos los pedidos cargados, buscar y seleccionar
const order = this.orders.find(o => o.id === id);
if (order) {
this.selectOrder(order, { updateUrl: false });
} else {
// Guardar el ID pendiente para seleccionar después de cargar
this._pendingOrderId = id;
}
}
renderDetail() {
const container = this.shadowRoot.getElementById("orderDetail");
if (!this.selectedOrder) {
container.innerHTML = `Seleccioná un pedido para ver los detalles
`;
return;
}
const order = this.selectedOrder;
const customerName = [order.billing.first_name, order.billing.last_name].filter(Boolean).join(" ") || "—";
// Construir dirección de envío
const shippingAddr = [
order.shipping?.address_1,
order.shipping?.address_2,
order.shipping?.city,
order.shipping?.state,
order.shipping?.postcode
].filter(Boolean).join(", ");
const billingAddr = [
order.billing?.address_1,
order.billing?.address_2,
order.billing?.city,
order.billing?.state,
order.billing?.postcode
].filter(Boolean).join(", ");
const address = shippingAddr || billingAddr || "—";
container.innerHTML = `
Información General
Pedido #
${order.id}
Estado
${statusLabel(order.status)}
Tipo
${order.is_test ? "Test" : "Real"} • ${order.source === "whatsapp" ? "WhatsApp" : "Web"}
Fecha
${formatDate(order.date_created)}
Total
$${Number(order.total || 0).toLocaleString("es-AR")} ${order.currency || ""}
Envío
Método
${order.is_delivery ? 'DELIVERY' : 'RETIRO'}
${order.shipping_method ? `${order.shipping_method}` : ''}
${order.is_delivery && address !== "—" ? `
Dirección
${address}
` : ''}
Pago
Método
${order.is_cash ? 'EFECTIVO' : 'LINK'}
${order.payment_method_title ? `${order.payment_method_title}` : ''}
Estado
${order.is_paid ? 'PAGADO' : 'PENDIENTE'}
${order.date_paid ? `${formatDate(order.date_paid)}` : ''}
Cliente
Nombre
${customerName}
Teléfono
${order.billing.phone || "—"}
Email
${order.billing.email || "—"}
Productos (${order.line_items.length})
${order.line_items.length === 0 ? '
Sin productos
' :
order.line_items.map(item => `
${item.name}
x${item.quantity}
$${Number(item.total || 0).toLocaleString("es-AR")}
`).join("")
}
${order.run_id ? `
Metadata
Run ID
${order.run_id}
` : ""}
`;
}
}
customElements.define("orders-crud", OrdersCrud);