corregidos bugs de: ret, vs delivery, efectivo vs link, charsets, price query
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import { api } from "../lib/api.js";
|
||||
|
||||
const DAYS = [
|
||||
{ id: "lun", label: "Lun" },
|
||||
{ id: "mar", label: "Mar" },
|
||||
{ id: "mie", label: "Mié" },
|
||||
{ id: "jue", label: "Jue" },
|
||||
{ id: "vie", label: "Vie" },
|
||||
{ id: "sab", label: "Sáb" },
|
||||
{ id: "dom", label: "Dom" },
|
||||
{ id: "lun", label: "Lunes", short: "Lun" },
|
||||
{ id: "mar", label: "Martes", short: "Mar" },
|
||||
{ id: "mie", label: "Miércoles", short: "Mié" },
|
||||
{ id: "jue", label: "Jueves", short: "Jue" },
|
||||
{ id: "vie", label: "Viernes", short: "Vie" },
|
||||
{ id: "sab", label: "Sábado", short: "Sáb" },
|
||||
{ id: "dom", label: "Domingo", short: "Dom" },
|
||||
];
|
||||
|
||||
class SettingsCrud extends HTMLElement {
|
||||
@@ -50,11 +50,11 @@ class SettingsCrud extends HTMLElement {
|
||||
button.secondary { background:#253245; }
|
||||
button.secondary:hover { background:#2d3e52; }
|
||||
|
||||
.toggle-row { display:flex; align-items:center; gap:12px; margin-bottom:12px; }
|
||||
.toggle-row { display:flex; align-items:center; gap:12px; margin-bottom:16px; }
|
||||
.toggle {
|
||||
position:relative; width:48px; height:26px;
|
||||
background:#253245; border-radius:13px; cursor:pointer;
|
||||
transition:background .2s;
|
||||
transition:background .2s; flex-shrink:0;
|
||||
}
|
||||
.toggle.active { background:#1f6feb; }
|
||||
.toggle::after {
|
||||
@@ -65,20 +65,38 @@ class SettingsCrud extends HTMLElement {
|
||||
.toggle.active::after { transform:translateX(22px); }
|
||||
.toggle-label { font-size:14px; color:#e7eef7; }
|
||||
|
||||
.days-selector { display:flex; gap:6px; flex-wrap:wrap; }
|
||||
.day-btn {
|
||||
padding:8px 12px; border-radius:6px; font-size:12px; font-weight:600;
|
||||
background:#253245; color:#8aa0b5; border:none; cursor:pointer;
|
||||
transition:all .15s;
|
||||
/* Schedule grid */
|
||||
.schedule-grid { display:flex; flex-direction:column; gap:8px; }
|
||||
.schedule-row {
|
||||
display:grid;
|
||||
grid-template-columns:90px 32px 1fr;
|
||||
gap:12px;
|
||||
align-items:center;
|
||||
padding:8px 12px;
|
||||
background:#0f1520;
|
||||
border-radius:8px;
|
||||
border:1px solid #1e2a3a;
|
||||
}
|
||||
.day-btn:hover { background:#2d3e52; color:#e7eef7; }
|
||||
.day-btn.selected { background:#1f6feb; color:#fff; }
|
||||
|
||||
.hours-row { display:flex; align-items:center; gap:12px; margin-top:12px; }
|
||||
.hours-row input { width:90px; text-align:center; font-family:monospace; font-size:15px; letter-spacing:1px; }
|
||||
.hours-row input::placeholder { color:#6c7a89; }
|
||||
.hours-row span { color:#8aa0b5; }
|
||||
.hours-row .hour-hint { font-size:11px; color:#6c7a89; margin-left:8px; }
|
||||
.schedule-row.disabled { opacity:0.4; }
|
||||
.day-label { font-size:13px; color:#e7eef7; font-weight:500; }
|
||||
.day-toggle {
|
||||
width:32px; height:18px; background:#253245; border-radius:9px;
|
||||
cursor:pointer; position:relative; transition:background .2s;
|
||||
}
|
||||
.day-toggle.active { background:#2ecc71; }
|
||||
.day-toggle::after {
|
||||
content:''; position:absolute; top:2px; left:2px;
|
||||
width:14px; height:14px; background:#fff; border-radius:50%;
|
||||
transition:transform .2s;
|
||||
}
|
||||
.day-toggle.active::after { transform:translateX(14px); }
|
||||
.hours-inputs { display:flex; align-items:center; gap:8px; }
|
||||
.hours-inputs input {
|
||||
width:70px; text-align:center; font-family:monospace;
|
||||
font-size:13px; padding:6px 8px; letter-spacing:1px;
|
||||
}
|
||||
.hours-inputs span { color:#6c7a89; font-size:12px; }
|
||||
.hours-inputs.disabled input { opacity:0.4; pointer-events:none; }
|
||||
|
||||
.actions { display:flex; gap:12px; margin-top:24px; }
|
||||
.loading { text-align:center; padding:60px; color:#8aa0b5; }
|
||||
@@ -93,6 +111,8 @@ class SettingsCrud extends HTMLElement {
|
||||
color:#e74c3c; padding:12px 16px; border-radius:8px;
|
||||
margin-bottom:16px; font-size:14px;
|
||||
}
|
||||
|
||||
.min-order-field { margin-top:16px; padding-top:16px; border-top:1px solid #1e2a3a; }
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
@@ -114,6 +134,10 @@ class SettingsCrud extends HTMLElement {
|
||||
|
||||
try {
|
||||
this.settings = await api.getSettings();
|
||||
// Asegurar que schedule existe
|
||||
if (!this.settings.schedule) {
|
||||
this.settings.schedule = { delivery: {}, pickup: {} };
|
||||
}
|
||||
this.loading = false;
|
||||
this.render();
|
||||
} catch (e) {
|
||||
@@ -123,6 +147,60 @@ class SettingsCrud extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
getScheduleSlot(type, dayId) {
|
||||
return this.settings?.schedule?.[type]?.[dayId] || null;
|
||||
}
|
||||
|
||||
setScheduleSlot(type, dayId, slot) {
|
||||
if (!this.settings.schedule) {
|
||||
this.settings.schedule = { delivery: {}, pickup: {} };
|
||||
}
|
||||
if (!this.settings.schedule[type]) {
|
||||
this.settings.schedule[type] = {};
|
||||
}
|
||||
this.settings.schedule[type][dayId] = slot;
|
||||
}
|
||||
|
||||
renderScheduleGrid(type, enabled) {
|
||||
const defaultStart = type === "delivery" ? "09:00" : "08:00";
|
||||
const defaultEnd = type === "delivery" ? "18:00" : "20:00";
|
||||
|
||||
return DAYS.map(day => {
|
||||
const slot = this.getScheduleSlot(type, day.id);
|
||||
const isActive = slot !== null && slot !== undefined;
|
||||
const start = slot?.start || defaultStart;
|
||||
const end = slot?.end || defaultEnd;
|
||||
|
||||
return `
|
||||
<div class="schedule-row ${!enabled ? 'disabled' : ''}">
|
||||
<span class="day-label">${day.label}</span>
|
||||
<div class="day-toggle ${isActive ? 'active' : ''}"
|
||||
data-type="${type}" data-day="${day.id}"
|
||||
${!enabled ? 'style="pointer-events:none"' : ''}></div>
|
||||
<div class="hours-inputs ${!isActive ? 'disabled' : ''}">
|
||||
<input type="text"
|
||||
class="hour-start"
|
||||
data-type="${type}"
|
||||
data-day="${day.id}"
|
||||
value="${start}"
|
||||
placeholder="09:00"
|
||||
maxlength="5"
|
||||
${!enabled || !isActive ? 'disabled' : ''} />
|
||||
<span>a</span>
|
||||
<input type="text"
|
||||
class="hour-end"
|
||||
data-type="${type}"
|
||||
data-day="${day.id}"
|
||||
value="${end}"
|
||||
placeholder="18:00"
|
||||
maxlength="5"
|
||||
${!enabled || !isActive ? 'disabled' : ''} />
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
render() {
|
||||
const content = this.shadowRoot.getElementById("content");
|
||||
|
||||
@@ -137,8 +215,6 @@ class SettingsCrud extends HTMLElement {
|
||||
}
|
||||
|
||||
const s = this.settings;
|
||||
const deliveryDays = (s.delivery_days || "").split(",").filter(d => d);
|
||||
const pickupDays = (s.pickup_days || "").split(",").filter(d => d);
|
||||
|
||||
content.innerHTML = `
|
||||
<!-- Info del Negocio -->
|
||||
@@ -185,26 +261,13 @@ class SettingsCrud extends HTMLElement {
|
||||
<span class="toggle-label">Delivery habilitado</span>
|
||||
</div>
|
||||
|
||||
<div id="deliveryOptions" style="${s.delivery_enabled ? "" : "opacity:0.5;pointer-events:none;"}">
|
||||
<div class="schedule-grid" id="deliverySchedule">
|
||||
${this.renderScheduleGrid("delivery", s.delivery_enabled)}
|
||||
</div>
|
||||
|
||||
<div class="min-order-field">
|
||||
<div class="field">
|
||||
<label>Días disponibles</label>
|
||||
<div class="days-selector" id="deliveryDays">
|
||||
${DAYS.map(d => `
|
||||
<button type="button" class="day-btn ${deliveryDays.includes(d.id) ? "selected" : ""}" data-day="${d.id}">${d.label}</button>
|
||||
`).join("")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hours-row">
|
||||
<span>Horario:</span>
|
||||
<input type="text" id="deliveryStart" value="${s.delivery_hours_start || "09:00"}" placeholder="09:00" pattern="([01]?[0-9]|2[0-3]):[0-5][0-9]" maxlength="5" />
|
||||
<span>a</span>
|
||||
<input type="text" id="deliveryEnd" value="${s.delivery_hours_end || "18:00"}" placeholder="18:00" pattern="([01]?[0-9]|2[0-3]):[0-5][0-9]" maxlength="5" />
|
||||
<span class="hour-hint">(formato 24hs)</span>
|
||||
</div>
|
||||
|
||||
<div class="field" style="margin-top:12px;">
|
||||
<label>Pedido mínimo ($)</label>
|
||||
<label>Pedido mínimo para delivery ($)</label>
|
||||
<input type="number" id="deliveryMinOrder" value="${s.delivery_min_order || 0}" min="0" step="100" style="width:150px;" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -222,23 +285,8 @@ class SettingsCrud extends HTMLElement {
|
||||
<span class="toggle-label">Retiro en tienda habilitado</span>
|
||||
</div>
|
||||
|
||||
<div id="pickupOptions" style="${s.pickup_enabled ? "" : "opacity:0.5;pointer-events:none;"}">
|
||||
<div class="field">
|
||||
<label>Días disponibles</label>
|
||||
<div class="days-selector" id="pickupDays">
|
||||
${DAYS.map(d => `
|
||||
<button type="button" class="day-btn ${pickupDays.includes(d.id) ? "selected" : ""}" data-day="${d.id}">${d.label}</button>
|
||||
`).join("")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hours-row">
|
||||
<span>Horario:</span>
|
||||
<input type="text" id="pickupStart" value="${s.pickup_hours_start || "08:00"}" placeholder="08:00" pattern="([01]?[0-9]|2[0-3]):[0-5][0-9]" maxlength="5" />
|
||||
<span>a</span>
|
||||
<input type="text" id="pickupEnd" value="${s.pickup_hours_end || "20:00"}" placeholder="20:00" pattern="([01]?[0-9]|2[0-3]):[0-5][0-9]" maxlength="5" />
|
||||
<span class="hour-hint">(formato 24hs)</span>
|
||||
</div>
|
||||
<div class="schedule-grid" id="pickupSchedule">
|
||||
${this.renderScheduleGrid("pickup", s.pickup_enabled)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -266,36 +314,43 @@ class SettingsCrud extends HTMLElement {
|
||||
this.render();
|
||||
});
|
||||
|
||||
// Delivery days
|
||||
this.shadowRoot.querySelectorAll("#deliveryDays .day-btn").forEach(btn => {
|
||||
btn.addEventListener("click", () => {
|
||||
const day = btn.dataset.day;
|
||||
let days = (this.settings.delivery_days || "").split(",").filter(d => d);
|
||||
if (days.includes(day)) {
|
||||
days = days.filter(d => d !== day);
|
||||
// Day toggles
|
||||
this.shadowRoot.querySelectorAll(".day-toggle").forEach(toggle => {
|
||||
toggle.addEventListener("click", () => {
|
||||
const type = toggle.dataset.type;
|
||||
const day = toggle.dataset.day;
|
||||
const currentSlot = this.getScheduleSlot(type, day);
|
||||
|
||||
if (currentSlot) {
|
||||
// Desactivar día
|
||||
this.setScheduleSlot(type, day, null);
|
||||
} else {
|
||||
days.push(day);
|
||||
// Activar día con horarios default
|
||||
const defaultStart = type === "delivery" ? "09:00" : "08:00";
|
||||
const defaultEnd = type === "delivery" ? "18:00" : "20:00";
|
||||
this.setScheduleSlot(type, day, { start: defaultStart, end: defaultEnd });
|
||||
}
|
||||
// Ordenar días
|
||||
days.sort((a, b) => DAYS.findIndex(d => d.id === a) - DAYS.findIndex(d => d.id === b));
|
||||
this.settings.delivery_days = days.join(",");
|
||||
this.render();
|
||||
});
|
||||
});
|
||||
|
||||
// Pickup days
|
||||
this.shadowRoot.querySelectorAll("#pickupDays .day-btn").forEach(btn => {
|
||||
btn.addEventListener("click", () => {
|
||||
const day = btn.dataset.day;
|
||||
let days = (this.settings.pickup_days || "").split(",").filter(d => d);
|
||||
if (days.includes(day)) {
|
||||
days = days.filter(d => d !== day);
|
||||
// Hour inputs - update on blur
|
||||
this.shadowRoot.querySelectorAll(".hour-start, .hour-end").forEach(input => {
|
||||
input.addEventListener("blur", () => {
|
||||
const type = input.dataset.type;
|
||||
const day = input.dataset.day;
|
||||
const isStart = input.classList.contains("hour-start");
|
||||
|
||||
const slot = this.getScheduleSlot(type, day);
|
||||
if (!slot) return;
|
||||
|
||||
const value = input.value.trim();
|
||||
if (isStart) {
|
||||
slot.start = value || (type === "delivery" ? "09:00" : "08:00");
|
||||
} else {
|
||||
days.push(day);
|
||||
slot.end = value || (type === "delivery" ? "18:00" : "20:00");
|
||||
}
|
||||
days.sort((a, b) => DAYS.findIndex(d => d.id === a) - DAYS.findIndex(d => d.id === b));
|
||||
this.settings.pickup_days = days.join(",");
|
||||
this.render();
|
||||
this.setScheduleSlot(type, day, slot);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -306,25 +361,43 @@ class SettingsCrud extends HTMLElement {
|
||||
this.shadowRoot.getElementById("resetBtn")?.addEventListener("click", () => this.load());
|
||||
}
|
||||
|
||||
collectScheduleFromInputs() {
|
||||
const schedule = { delivery: {}, pickup: {} };
|
||||
|
||||
for (const type of ["delivery", "pickup"]) {
|
||||
this.shadowRoot.querySelectorAll(`.hour-start[data-type="${type}"]`).forEach(input => {
|
||||
const day = input.dataset.day;
|
||||
const endInput = this.shadowRoot.querySelector(`.hour-end[data-type="${type}"][data-day="${day}"]`);
|
||||
const toggle = this.shadowRoot.querySelector(`.day-toggle[data-type="${type}"][data-day="${day}"]`);
|
||||
|
||||
if (toggle?.classList.contains("active")) {
|
||||
schedule[type][day] = {
|
||||
start: input.value.trim() || (type === "delivery" ? "09:00" : "08:00"),
|
||||
end: endInput?.value.trim() || (type === "delivery" ? "18:00" : "20:00"),
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return schedule;
|
||||
}
|
||||
|
||||
async save() {
|
||||
// Collect form data BEFORE re-rendering
|
||||
// Collect schedule from inputs
|
||||
const schedule = this.collectScheduleFromInputs();
|
||||
|
||||
const data = {
|
||||
store_name: this.shadowRoot.getElementById("storeName")?.value || "",
|
||||
bot_name: this.shadowRoot.getElementById("botName")?.value || "",
|
||||
store_address: this.shadowRoot.getElementById("storeAddress")?.value || "",
|
||||
store_phone: this.shadowRoot.getElementById("storePhone")?.value || "",
|
||||
delivery_enabled: this.settings.delivery_enabled,
|
||||
delivery_days: this.settings.delivery_days,
|
||||
delivery_hours_start: this.shadowRoot.getElementById("deliveryStart")?.value || "09:00",
|
||||
delivery_hours_end: this.shadowRoot.getElementById("deliveryEnd")?.value || "18:00",
|
||||
delivery_min_order: parseFloat(this.shadowRoot.getElementById("deliveryMinOrder")?.value) || 0,
|
||||
pickup_enabled: this.settings.pickup_enabled,
|
||||
pickup_days: this.settings.pickup_days,
|
||||
pickup_hours_start: this.shadowRoot.getElementById("pickupStart")?.value || "08:00",
|
||||
pickup_hours_end: this.shadowRoot.getElementById("pickupEnd")?.value || "20:00",
|
||||
delivery_min_order: parseFloat(this.shadowRoot.getElementById("deliveryMinOrder")?.value) || 0,
|
||||
schedule,
|
||||
};
|
||||
|
||||
// Update settings with form values so they persist through render
|
||||
// Update settings with form values
|
||||
this.settings = { ...this.settings, ...data };
|
||||
|
||||
this.saving = true;
|
||||
|
||||
Reference in New Issue
Block a user