Publica tu evento en Go Live Vegas
Envía tu evento, sube tu flyer o gráfico y completa el pago. Tu envío se guarda para revisión administrativa antes de Stripe para que Go Live Vegas pueda ver intentos de carga y mantener todo oculto hasta el pago y la aprobación.
Procesando tu envío
const TEXT = { language: "es", locale: "es", submissionPrefix: "web_es", noImage: "Aún no has seleccionado una imagen.", dateHelpPrefix: "Duración actual del evento:", hours: "horas", dateHelpSuffix: "Los eventos pueden enviarse hasta con 90 días de anticipación y no pueden durar más de 24 horas.", errors: { missing: "Completa todos los campos obligatorios.", ownership: "Debes confirmar que posees o estás autorizado para usar la información e imagen del evento enviado.", terms: "Debes aceptar los términos y la política de revisión.", endAfterStart: "La fecha/hora de finalización debe ser posterior a la fecha/hora de inicio.", tooLong: "La duración del evento no puede exceder 24 horas.", tooFar: "Los eventos solo pueden enviarse hasta con 90 días de anticipación.", imageType: "Sube una imagen JPG, PNG o WEBP.", imageSize: "La imagen debe pesar menos de 8 MB.", uploadFailed: "No se pudo subir la imagen.", checkoutFailed: "No se pudo crear el pago:", draftFailed: "No se pudo guardar el registro privado de revisión:", generic: "Algo salió mal. Inténtalo de nuevo." } };
const UPLOAD="https://uploadimagedirect-sahxxu427q-uc.a.run.app"; const CHECKOUT="https://createcheckoutredirect-sahxxu427q-uc.a.run.app"; // IMPORTANT: this is the exact function URL Firebase printed after deploy. const CREATE_DRAFT="https://createpaideventdraft-sahxxu427q-uc.a.run.app";
const MAX_ADVANCE_DAYS = 90; const MAX_DURATION_HOURS = 24; const EVENT_AMOUNT_CENTS = 1999;
const els = { form: document.getElementById("form"), title: document.getElementById("title"), email: document.getElementById("email"), startDate: document.getElementById("startDate"), startTime: document.getElementById("startTime"), endDate: document.getElementById("endDate"), endTime: document.getElementById("endTime"), desc: document.getElementById("desc"), ticketUrl: document.getElementById("ticketUrl"), file: document.getElementById("file"), agree: document.getElementById("agree"), ownership: document.getElementById("ownership"), imagePreview: document.getElementById("imagePreview"), imagePreviewText: document.getElementById("imagePreviewText"), imageName: document.getElementById("imageName"), dateHelp: document.getElementById("dateHelp"), debugBox: document.getElementById("debugBox"), statusOverlay: document.getElementById("statusOverlay"), statusUpload: document.getElementById("statusUpload"), statusDraft: document.getElementById("statusDraft"), statusVerify: document.getElementById("statusVerify"), statusRedirect: document.getElementById("statusRedirect"), submitButton: document.querySelector('#form button[type="submit"]') };
function debugLine(label, data) { try { els.debugBox.classList.add("show"); const text = typeof data === "string" ? data : JSON.stringify(data, null, 2); els.debugBox.textContent += `\n\n${label}\n${text}`; } catch (_) {} }
function pad(n){ return String(n).padStart(2, "0"); } function toDateInputValue(date) { return `${date.getFullYear()}-${pad(date.getMonth()+1)}-${pad(date.getDate())}`; } function toTimeInputValue(date) { return `${pad(date.getHours())}:${pad(date.getMinutes())}`; } function localDateTime(dateValue, timeValue) { if (!dateValue || !timeValue) return null; const d = new Date(`${dateValue}T${timeValue}`); return Number.isFinite(d.getTime()) ? d : null; } function toDateTimeLocalString(date) { return `${toDateInputValue(date)}T${toTimeInputValue(date)}`; }
function setupDateLimits() { const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const max = new Date(today.getTime() + MAX_ADVANCE_DAYS * 24 * 60 * 60 * 1000); const minDate = toDateInputValue(today); const maxDate = toDateInputValue(max); [els.startDate, els.endDate].forEach(input => { input.min = minDate; input.max = maxDate; }); if (!els.startDate.value) { const defaultStart = new Date(now.getTime() + 2 * 60 * 60 * 1000); defaultStart.setMinutes(defaultStart.getMinutes() < 30 ? 30 : 0); if (defaultStart.getMinutes() === 0) defaultStart.setHours(defaultStart.getHours() + 1); els.startDate.value = toDateInputValue(defaultStart); els.startTime.value = toTimeInputValue(defaultStart); const defaultEnd = new Date(defaultStart.getTime() + 2 * 60 * 60 * 1000); els.endDate.value = toDateInputValue(defaultEnd); els.endTime.value = toTimeInputValue(defaultEnd); } enforceEndWindow(); } function enforceEndWindow() { const start = localDateTime(els.startDate.value, els.startTime.value); if (!start) return; const maxEnd = new Date(start.getTime() + MAX_DURATION_HOURS * 60 * 60 * 1000); els.endDate.min = toDateInputValue(start); els.endDate.max = toDateInputValue(maxEnd); const end = localDateTime(els.endDate.value, els.endTime.value); if (!end || end <= start) { const nextEnd = new Date(start.getTime() + 2 * 60 * 60 * 1000); els.endDate.value = toDateInputValue(nextEnd); els.endTime.value = toTimeInputValue(nextEnd); } else if (end > maxEnd) { els.endDate.value = toDateInputValue(maxEnd); els.endTime.value = toTimeInputValue(maxEnd); } updateDateHelp(); }
function updateDateHelp() { const start = localDateTime(els.startDate.value, els.startTime.value); const end = localDateTime(els.endDate.value, els.endTime.value); if (!start || !end) return; const durationHours = Math.max(0, (end.getTime() - start.getTime()) / (60 * 60 * 1000)); els.dateHelp.textContent = `${TEXT.dateHelpPrefix} ${durationHours.toFixed(durationHours % 1 ? 1 : 0)} ${TEXT.hours}. ${TEXT.dateHelpSuffix}`; }
function resetStatus() { [els.statusUpload, els.statusDraft, els.statusVerify, els.statusRedirect].forEach(el => el.className = "statusRow"); } function showStatus() { resetStatus(); els.debugBox.textContent = ""; els.debugBox.classList.remove("show"); els.statusOverlay.classList.add("show"); els.submitButton.classList.add("btnBusy"); els.submitButton.disabled = true; } function hideStatus() { els.statusOverlay.classList.remove("show"); els.submitButton.classList.remove("btnBusy"); els.submitButton.disabled = false; resetStatus(); } function setStatus(step) { resetStatus(); if (step === "upload") { els.statusUpload.classList.add("active"); return; } if (step === "draft") { els.statusUpload.classList.add("done"); els.statusDraft.classList.add("active"); return; } if (step === "verify") { els.statusUpload.classList.add("done"); els.statusDraft.classList.add("done"); els.statusVerify.classList.add("active"); return; } if (step === "redirect") { els.statusUpload.classList.add("done"); els.statusDraft.classList.add("done"); els.statusVerify.classList.add("done"); els.statusRedirect.classList.add("done"); } }
function validateForm() { const title = els.title.value.trim(); const email = els.email.value.trim(); const start = localDateTime(els.startDate.value, els.startTime.value); const end = localDateTime(els.endDate.value, els.endTime.value); if (!title || !email || !start || !end) return TEXT.errors.missing; if (!els.ownership.checked) return TEXT.errors.ownership; if (!els.agree.checked) return TEXT.errors.terms; if (end <= start) return TEXT.errors.endAfterStart; if ((end.getTime() - start.getTime()) > MAX_DURATION_HOURS * 60 * 60 * 1000) return TEXT.errors.tooLong; if (start.getTime() > Date.now() + MAX_ADVANCE_DAYS * 24 * 60 * 60 * 1000) return TEXT.errors.tooFar; const file = els.file.files[0]; if (file) { const allowed = ["image/jpeg", "image/png", "image/webp"]; if (!allowed.includes(file.type)) return TEXT.errors.imageType; if (file.size > 8 * 1024 * 1024) return TEXT.errors.imageSize; } return ""; }
els.file.addEventListener("change", () => { const file = els.file.files[0]; if (!file) { els.imagePreview.src = ""; els.imagePreview.style.display = "none"; els.imagePreviewText.style.display = "block"; els.imageName.textContent = TEXT.noImage; return; } els.imageName.textContent = `${file.name} • ${(file.size / (1024 * 1024)).toFixed(2)} MB`; const reader = new FileReader(); reader.onload = e => { els.imagePreview.src = e.target.result; els.imagePreview.style.display = "block"; els.imagePreviewText.style.display = "none"; }; reader.readAsDataURL(file); });
[els.startDate, els.startTime, els.endDate, els.endTime].forEach(input => input.addEventListener("change", enforceEndWindow));
els.form.addEventListener("submit", async e => { e.preventDefault(); const validationError = validateForm(); if (validationError) { alert(validationError); return; }
const start = localDateTime(els.startDate.value, els.startTime.value); const end = localDateTime(els.endDate.value, els.endTime.value);
showStatus(); setStatus("upload");
try { let imageUrl = ""; const file = els.file.files[0];
if (file) { const fd = new FormData(); fd.append("file", file); debugLine("UPLOAD endpoint", UPLOAD); const res = await fetch(UPLOAD, { method: "POST", body: fd }); const data = await res.json().catch(() => ({})); debugLine("UPLOAD response", data); if (!res.ok || !data.ok || !data.imageUrl) { hideStatus(); alert(data.error || TEXT.errors.uploadFailed); return; } imageUrl = data.imageUrl; } else { els.statusUpload.classList.add("done"); }
const body = { submissionId: `${TEXT.submissionPrefix}_${Date.now()}`, amount: EVENT_AMOUNT_CENTS, currency: "usd", title: els.title.value.trim(), contactEmail: els.email.value.trim(), startLocal: toDateTimeLocalString(start), endLocal: toDateTimeLocalString(end), description: els.desc.value.trim(), ticketUrl: els.ticketUrl.value.trim(), imageUrl, zone: "NETWORKING", category: "general", language: TEXT.language, locale: TEXT.locale, moderationRequired: true, reviewStatus: "pending_graphics_review", moderationStatus: "pending_graphics_review", legalTermsAccepted: els.agree.checked, legalOwnershipConfirmed: els.ownership.checked };
setStatus("draft"); debugLine("CREATE_DRAFT endpoint", CREATE_DRAFT); debugLine("CREATE_DRAFT request", body);
const draftResp = await fetch(CREATE_DRAFT, { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(body) });
const draftText = await draftResp.text(); let draftData = {}; try { draftData = JSON.parse(draftText); } catch (_) { draftData = { raw: draftText }; } debugLine("CREATE_DRAFT response", draftData);
if (!draftResp.ok || !draftData.ok) { hideStatus(); alert((TEXT.errors.draftFailed || "Unable to save admin review record:") + " " + (draftData.error || draftText || "unknown_error")); return; }
setStatus("verify");
const resp = await fetch(CHECKOUT + "?json=1", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(body) });
const checkoutText = await resp.text(); let data = {}; try { data = JSON.parse(checkoutText); } catch (_) { data = { raw: checkoutText }; } debugLine("CHECKOUT response", data);
if (!resp.ok || !data.url) { hideStatus(); alert(TEXT.errors.checkoutFailed + " " + (data.error || checkoutText || "unknown_error")); return; }
setStatus("redirect"); setTimeout(() => { window.location.href = data.url; }, 700); } catch (err) { debugLine("CAUGHT ERROR", String(err && err.message ? err.message : err)); hideStatus(); alert(TEXT.errors.generic + " " + String(err && err.message ? err.message : err)); } });
setupDateLimits();
