16235369cb
Highlights include configurable menus, specials, cart/checkout, taxes, customer accounts with email 2FA, newsletters, analytics, refunds, PDF/CSV exports, Square/Mailgun adapters, and optional MySQL migration. See README.md for setup and production configuration. Verified PHP/JavaScript syntax, responsive layouts, registration, 2FA, checkout, dashboard workflows, settings persistence, and PDF generation. Real Square, Mailgun, and MySQL connections require credentials/server access. Square implementation follows the official Payments API and Refunds API.
86 lines
2.9 KiB
JavaScript
86 lines
2.9 KiB
JavaScript
(() => {
|
|
const navToggle = document.querySelector(".nav-toggle");
|
|
const nav = document.querySelector(".site-nav");
|
|
if (navToggle && nav) {
|
|
navToggle.addEventListener("click", () => {
|
|
const open = nav.classList.toggle("is-open");
|
|
navToggle.setAttribute("aria-expanded", String(open));
|
|
});
|
|
}
|
|
|
|
document.querySelectorAll(".flash-close").forEach((button) => {
|
|
button.addEventListener("click", () => button.closest(".flash")?.remove());
|
|
});
|
|
|
|
window.setTimeout(() => {
|
|
document.querySelectorAll(".flash").forEach((flash) => {
|
|
flash.style.opacity = "0";
|
|
window.setTimeout(() => flash.remove(), 220);
|
|
});
|
|
}, 7000);
|
|
|
|
document.querySelectorAll("[data-confirm]").forEach((element) => {
|
|
element.addEventListener("click", (event) => {
|
|
if (!window.confirm(element.dataset.confirm || "Continue?")) {
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
});
|
|
|
|
const checkoutForm = document.querySelector("#checkout-form");
|
|
if (!checkoutForm || checkoutForm.dataset.squareEnabled !== "true") {
|
|
return;
|
|
}
|
|
|
|
const appId = checkoutForm.dataset.squareAppId;
|
|
const locationId = checkoutForm.dataset.squareLocationId;
|
|
const submit = document.querySelector("#checkout-submit");
|
|
const errors = document.querySelector("#card-errors");
|
|
let card;
|
|
|
|
const initializeSquare = async () => {
|
|
if (!window.Square || !appId || !locationId) {
|
|
return;
|
|
}
|
|
try {
|
|
const payments = window.Square.payments(appId, locationId);
|
|
card = await payments.card();
|
|
await card.attach("#card-container");
|
|
} catch (error) {
|
|
if (errors) {
|
|
errors.textContent = "Payment form could not be loaded. Please refresh and try again.";
|
|
}
|
|
if (submit) {
|
|
submit.disabled = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
checkoutForm.addEventListener("submit", async (event) => {
|
|
if (!card || checkoutForm.dataset.tokenized === "true") {
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
submit.disabled = true;
|
|
submit.textContent = "Securing Payment...";
|
|
errors.textContent = "";
|
|
|
|
try {
|
|
const result = await card.tokenize();
|
|
if (result.status !== "OK") {
|
|
throw new Error(result.errors?.[0]?.message || "Card details could not be verified.");
|
|
}
|
|
document.querySelector("#square-token").value = result.token;
|
|
checkoutForm.dataset.tokenized = "true";
|
|
checkoutForm.submit();
|
|
} catch (error) {
|
|
errors.textContent = error.message || "Payment could not be processed.";
|
|
submit.disabled = false;
|
|
submit.textContent = "Try Payment Again";
|
|
}
|
|
});
|
|
|
|
initializeSquare();
|
|
})();
|
|
|