feat: add RPC for public lead creation and update migrations in docker-compose files

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
LagoESP
2026-04-29 16:33:01 +02:00
parent e85b319c93
commit bc61ffa206
9 changed files with 139 additions and 76 deletions
+26 -18
View File
@@ -48,10 +48,12 @@ const bpfPhone = document.querySelector("#bpfPhone");
const bpfMessage = document.querySelector("#bpfMessage");
const bpfFileId = document.querySelector("#bpfFileId");
const bpfFileIncome = document.querySelector("#bpfFileIncome");
const bpfSubmitBtn = document.querySelector("#bpfSubmit");
const bpfSidebar = document.querySelector("#bpfSidebar");
const bpfSidebarContent = document.querySelector("#bpfSidebarContent");
const bpfSidebarPlaceholder = document.querySelector(".bpf-sidebar-placeholder");
let bpfDurationMode = "custom"; // "day" | "weekend" | "custom"
let bpfSubmitting = false;
function formatYmdLocal(d) {
const y = d.getFullYear();
@@ -220,21 +222,20 @@ function openDetails(id) {
// ---------------- Reviews ----------------
function renderReviews() {
const list = REVIEWS[getLang()];
state.reviewIdx = state.reviewIdx % list.length;
const r = list[state.reviewIdx];
state.reviewIdx = state.reviewIdx % REVIEWS.length;
const r = REVIEWS[state.reviewIdx];
reviewStrip.innerHTML = `
<p class="review-quote">"${escapeHtml(r.quote)}"</p>
<p class="review-author">${escapeHtml(r.author)}</p>
`;
reviewDots.innerHTML = list.map((_, i) =>
reviewDots.innerHTML = REVIEWS.map((_, i) =>
`<button class="${i === state.reviewIdx ? 'active' : ''}" data-rev="${i}" aria-label="${t("review")} ${i + 1}"></button>`
).join("");
reviewDots.querySelectorAll("button").forEach(b => {
b.addEventListener("click", () => { state.reviewIdx = +b.dataset.rev; renderReviews(); });
});
}
setInterval(() => { state.reviewIdx++; renderReviews(); }, 6000);
setInterval(() => { state.reviewIdx++; renderReviews(); }, 5000);
// ---------------- BPF WIZARD ----------------
const bpfStepPanels = [
@@ -402,38 +403,43 @@ bpfTo.addEventListener("change", updateSidebar);
// Submit BPF
document.querySelector("#bpfSubmit").addEventListener("click", async () => {
if (bpfSubmitting) return;
bpfSubmitting = true;
if (bpfSubmitBtn) bpfSubmitBtn.disabled = true;
bookingFeedback.className = "form-feedback";
bookingFeedback.textContent = "...";
const vehicle = state.vehicles.find(v => v.id === bpfCar.value);
const payload = {
name: bpfName.value,
email: bpfEmail.value,
phone: bpfPhone.value || "",
vehicle_id: bpfCar.value || null,
vehicle_label: vehicle ? `${vehicle.brand} ${vehicle.model}` : "",
date_from: bpfFrom.value || null,
date_to: bpfTo.value || null,
message: bpfMessage.value || "",
source: "website",
p_name: bpfName.value,
p_email: bpfEmail.value,
p_phone: bpfPhone.value || "",
p_vehicle_id: bpfCar.value || null,
p_vehicle_label: vehicle ? `${vehicle.brand} ${vehicle.model}` : "",
p_date_from: bpfFrom.value || null,
p_date_to: bpfTo.value || null,
p_message: bpfMessage.value || "",
p_source: "website",
};
// Create lead
const { data: lead, error } = await supabase.from("leads").insert(payload).select("id").single();
// Create lead via RPC (returns inserted id without anon SELECT privileges)
const { data: leadId, error } = await supabase.rpc("create_lead", payload);
if (error) {
console.error(error);
bookingFeedback.className = "form-feedback error";
bookingFeedback.textContent = t("bookingFailed");
bpfSubmitting = false;
if (bpfSubmitBtn) bpfSubmitBtn.disabled = false;
return;
}
// Upload files
const uploads = [];
if (bpfFileId.files[0]) {
uploads.push(uploadDoc(lead.id, bpfFileId.files[0], "id_document"));
uploads.push(uploadDoc(leadId, bpfFileId.files[0], "id_document"));
}
if (bpfFileIncome.files[0]) {
uploads.push(uploadDoc(lead.id, bpfFileIncome.files[0], "income_proof"));
uploads.push(uploadDoc(leadId, bpfFileIncome.files[0], "income_proof"));
}
await Promise.all(uploads);
@@ -453,6 +459,8 @@ document.querySelector("#bpfSubmit").addEventListener("click", async () => {
document.querySelector("#bpfFileIncomeName").textContent = "";
setDurationMode("custom");
updateSidebar();
bpfSubmitting = false;
if (bpfSubmitBtn) bpfSubmitBtn.disabled = false;
});
async function uploadDoc(leadId, file, kind) {