File size: 4,358 Bytes
ddd5681 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | /** SmOS booking + payments API (same origin on uvicorn; falls back to :7860). */
window.SmOS_API = (function () {
const FALLBACK = "http://127.0.0.1:7860";
const MODULE_ID = (window.SmOS_Module && window.SmOS_Module.id) || "SmOS_CC";
function bases() {
const list = [];
if (location.origin && !location.origin.startsWith("file:")) list.push(location.origin);
if (!list.includes(FALLBACK)) list.push(FALLBACK);
return list;
}
async function postBooking(payload) {
const body = { module_id: MODULE_ID, ...payload };
let lastErr = null;
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/bookings`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (res.ok) return await res.json();
const err = await res.json().catch(() => ({}));
const detail = err.detail;
const msg = Array.isArray(detail)
? detail.map((d) => d.msg || d).join("; ")
: detail || `HTTP ${res.status}`;
lastErr = new Error(msg);
} catch (e) {
lastErr = e;
}
}
throw lastErr || new Error("Booking API unavailable");
}
async function createMolliePayment(payload) {
const body = { module_id: MODULE_ID, ...payload };
let lastErr = null;
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/modules/SmOS_CC/mollie/create`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const data = await res.json().catch(() => ({}));
if (res.ok) return data;
const detail = data.detail;
const msg = Array.isArray(detail)
? detail.map((d) => d.msg || d).join("; ")
: detail || `HTTP ${res.status}`;
lastErr = new Error(msg);
if (res.status === 400 || res.status === 503) break;
} catch (e) {
lastErr = e;
}
}
throw lastErr || new Error("Mollie checkout unavailable");
}
async function mollieStatus(paymentId) {
let lastErr = null;
const q = `?payment_id=${encodeURIComponent(paymentId || "")}`;
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/modules/SmOS_CC/mollie/status${q}`, {
cache: "no-store",
});
const data = await res.json().catch(() => ({}));
if (res.ok) return data;
const detail = data.detail;
const msg = Array.isArray(detail)
? detail.map((d) => d.msg || d).join("; ")
: detail || `HTTP ${res.status}`;
lastErr = new Error(msg);
} catch (e) {
lastErr = e;
}
}
throw lastErr || new Error("Mollie status unavailable");
}
async function occupiedTables(date) {
let lastErr = null;
const q = date ? `?date=${encodeURIComponent(date)}` : "";
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/modules/${MODULE_ID}/tables/occupied${q}`);
if (res.ok) {
const data = await res.json();
return Array.isArray(data.occupied) ? data.occupied.map(String) : [];
}
lastErr = new Error(`HTTP ${res.status}`);
} catch (e) {
lastErr = e;
}
}
if (lastErr) console.warn("occupiedTables", lastErr);
return [];
}
async function lookupAddresses(postcode) {
let lastErr = null;
const q = `?postcode=${encodeURIComponent(postcode || "")}`;
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/modules/${MODULE_ID}/addresses${q}`);
const data = await res.json().catch(() => ({}));
if (res.ok) return data;
const detail = data.detail;
const msg = Array.isArray(detail)
? detail.map((d) => d.msg || d).join("; ")
: detail || `HTTP ${res.status}`;
lastErr = new Error(msg);
if (res.status === 400 || res.status === 404 || res.status === 503) break;
} catch (e) {
lastErr = e;
}
}
throw lastErr || new Error("Address lookup unavailable");
}
return {
postBooking,
createMolliePayment,
mollieStatus,
occupiedTables,
lookupAddresses,
bases,
moduleId: MODULE_ID,
};
})();
|