creation site static coupe du monde 2026 sans Hugo

This commit is contained in:
2026-06-20 14:50:24 +02:00
parent 7f10e7a597
commit c00dd55b8d
52 changed files with 5376 additions and 38 deletions
@@ -0,0 +1,90 @@
/* ---------------- launch countdown i18n ---------------- */
const DICT = {
fr: {
meta_title: "TutoSport Expert — Ouverture le 22 juin 2026",
meta_description:
"Les académies de Dimitri Payet & Yannick Dyduch arrivent. Offre Coupe du Monde : les 2 académies à 7,90€. Ouverture le 22 juin 2026.",
tag: "Ouverture · 22 juin 2026",
h1a: "Le compte à rebours",
h1b: "est lancé.",
sub: "Les académies de Dimitri Payet & Yannick Dyduch arrivent. Préparez-vous à l'offre Coupe du Monde.",
l_d: "Jours",
l_h: "Heures",
l_m: "Minutes",
l_s: "Secondes",
offer_a: "Les 2 académies à",
offer_b: "au lieu de 80€ · offre limitée Coupe du Monde",
ph: "Ton adresse e-mail",
btn: "Préviens-moi",
thanks: "Merci ! On te prévient dès l'ouverture.",
note: "Sois prévenu·e en premier et garde l'offre 7,90€.",
rights: "© 2026 TutoSport Expert. Tous droits réservés.",
cd_d: "j",
},
en: {
meta_title: "TutoSport Expert — Opening June 22, 2026",
meta_description:
"The academies of Dimitri Payet & Yannick Dyduch are coming. World Cup offer: both academies for €7.90. Opening June 22, 2026.",
tag: "Opening · June 22, 2026",
h1a: "The countdown",
h1b: "has started.",
sub: "The academies of Dimitri Payet & Yannick Dyduch are coming. Get ready for the World Cup offer.",
l_d: "Days",
l_h: "Hours",
l_m: "Minutes",
l_s: "Seconds",
offer_a: "Both academies for",
offer_b: "instead of €80 · limited World Cup offer",
ph: "Your email address",
btn: "Notify me",
thanks: "Thanks! We'll let you know at launch.",
note: "Be the first in and keep the €7.90 offer.",
rights: "© 2026 TutoSport Expert. All rights reserved.",
cd_d: "d",
},
es: {
meta_title: "TutoSport Expert — Apertura el 22 de junio de 2026",
meta_description:
"Las academias de Dimitri Payet y Yannick Dyduch llegan. Oferta Mundial: las 2 academias por 7,90€. Apertura el 22 de junio de 2026.",
tag: "Apertura · 22 de junio de 2026",
h1a: "La cuenta atrás",
h1b: "ha comenzado.",
sub: "Las academias de Dimitri Payet y Yannick Dyduch llegan. Prepárate para la oferta del Mundial.",
l_d: "Días",
l_h: "Horas",
l_m: "Minutos",
l_s: "Segundos",
offer_a: "Las 2 academias por",
offer_b: "en vez de 80€ · oferta limitada del Mundial",
ph: "Tu correo electrónico",
btn: "Avísame",
thanks: "¡Gracias! Te avisamos en la apertura.",
note: "Entra el primero y conserva la oferta de 7,90€.",
rights: "© 2026 TutoSport Expert. Todos los derechos reservados.",
cd_d: "d",
},
pt: {
meta_title: "TutoSport Expert — Abertura em 22 de junho de 2026",
meta_description:
"As academias de Dimitri Payet e Yannick Dyduch chegam. Oferta Copa do Mundo: as 2 academias por 7,90€. Abertura em 22 de junho de 2026.",
tag: "Abertura · 22 de junho de 2026",
h1a: "A contagem regressiva",
h1b: "começou.",
sub: "As academias de Dimitri Payet e Yannick Dyduch chegam. Prepare-se para a oferta da Copa do Mundo.",
l_d: "Dias",
l_h: "Horas",
l_m: "Minutos",
l_s: "Segundos",
offer_a: "As 2 academias por",
offer_b: "em vez de 80€ · oferta limitada da Copa",
ph: "Seu e-mail",
btn: "Avise-me",
thanks: "Obrigado! Avisamos na abertura.",
note: "Seja o primeiro e garanta a oferta de 7,90€.",
rights: "© 2026 TutoSport Expert. Todos os direitos reservados.",
cd_d: "d",
},
};
const DEFAULT_LANG = "en";
const LANG_STORAGE_KEY = "tutosport_lang";
@@ -0,0 +1,372 @@
const SUPPORTED_LANGS = Object.keys(DICT);
let LANG = DEFAULT_LANG;
function getStripePricingTableHtml(lang) {
const pricingTableId =
SITE_CONFIG.stripe.pricingTableIds[lang] ||
SITE_CONFIG.stripe.pricingTableIds.en;
return (
`<stripe-pricing-table pricing-table-id="${pricingTableId}" ` +
`publishable-key="${SITE_CONFIG.stripe.publishableKey}"></stripe-pricing-table>`
);
}
function normalizeLang(value) {
if (!value) return null;
const lang = String(value).toLowerCase().split(/[-_]/)[0];
return DICT[lang] ? lang : null;
}
function getStoredLang() {
const cookieMatch = document.cookie.match(
new RegExp(`(?:^|; )${LANG_STORAGE_KEY}=([^;]*)`),
);
try {
return (
normalizeLang(localStorage.getItem(LANG_STORAGE_KEY)) ||
normalizeLang(cookieMatch && decodeURIComponent(cookieMatch[1]))
);
} catch (e) {
return normalizeLang(cookieMatch && decodeURIComponent(cookieMatch[1]));
}
}
function getUrlLang() {
return normalizeLang(new URLSearchParams(location.search).get("lang"));
}
function getBrowserLang() {
const browserLangs = navigator.languages && navigator.languages.length
? navigator.languages
: [navigator.language];
for (const lang of browserLangs) {
const normalized = normalizeLang(lang);
if (normalized) return normalized;
}
return null;
}
function getInitialLang() {
return getUrlLang() || getStoredLang() || getBrowserLang() || DEFAULT_LANG;
}
function getRootPrefix() {
if (document.body && document.body.dataset.rootPrefix) {
return document.body.dataset.rootPrefix;
}
const pathParts = location.pathname.split("/").filter(Boolean);
const parentDir = pathParts.length > 1 ? pathParts[pathParts.length - 2] : "";
return SUPPORTED_LANGS.includes(parentDir) ? "../" : "./";
}
function withLangParam(href, lang) {
const [pathWithSearch, hash = ""] = href.split("#");
const [path, search = ""] = pathWithSearch.split("?");
const params = new URLSearchParams(search);
params.set("lang", lang);
return `${path}?${params.toString()}${hash ? `#${hash}` : ""}`;
}
function getLocalizedPageUrl(lang) {
const pathParts = location.pathname.split("/").filter(Boolean);
const parentDir = pathParts.length > 1 ? pathParts[pathParts.length - 2] : "";
const fileName = pathParts[pathParts.length - 1] || "";
if (!SUPPORTED_LANGS.includes(parentDir)) return null;
if (fileName !== "cgv.html" && fileName !== "legals.html") return null;
return withLangParam(`../${lang}/${fileName}`, lang);
}
function updateInternalLinks(lang) {
const rootPrefix = getRootPrefix();
const homeHref = withLangParam(rootPrefix, lang);
const offerHref = withLangParam(`${rootPrefix}offre.html`, lang);
const legalPrefix = `${rootPrefix}${lang}/`;
const anchors = {
nav_offer: `${homeHref}#offre`,
nav_acad: `${homeHref}#academies`,
nav_how: `${homeHref}#how`,
nav_faq: `${homeHref}#faq`,
legal1: withLangParam(`${legalPrefix}cgv.html`, lang),
legal2: withLangParam(`${legalPrefix}legals.html`, lang),
};
Object.entries(anchors).forEach(([key, href]) => {
document
.querySelectorAll(`a[data-i18n="${key}"]`)
.forEach((link) => link.setAttribute("href", href));
});
document.querySelectorAll("a.brand, a.foot-logo-wrap").forEach((link) => {
link.setAttribute("href", homeHref);
});
document.querySelectorAll("a[href]").forEach((link) => {
const href = link.getAttribute("href");
if (!href || href.startsWith("http") || href.startsWith("mailto:")) return;
if (href.includes("offre.html")) {
link.setAttribute("href", offerHref);
} else if (href === "#offre" || href === "./#offre") {
link.setAttribute("href", `${homeHref}#offre`);
} else if (href === "#academies" || href === "./#academies") {
link.setAttribute("href", `${homeHref}#academies`);
}
});
}
function updateGoogleTagManagerNoScript() {
const gtmId = SITE_CONFIG.googleTagManagerId;
if (!gtmId) return;
document
.querySelectorAll('iframe[src*="googletagmanager.com/ns.html"]')
.forEach((iframe) => {
iframe.setAttribute(
"src",
`https://www.googletagmanager.com/ns.html?id=${gtmId}`,
);
});
}
function loadGoogleTagManagerScript() {
const gtmId = SITE_CONFIG.googleTagManagerId;
if (!gtmId) return;
if (
document.querySelector(
`script[src*="googletagmanager.com/gtm.js?id=${gtmId}"]`,
)
) {
return;
}
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({ "gtm.start": new Date().getTime(), event: "gtm.js" });
const f = d.getElementsByTagName(s)[0];
const j = d.createElement(s);
const dl = l !== "dataLayer" ? `&l=${l}` : "";
j.async = true;
j.src = `https://www.googletagmanager.com/gtm.js?id=${i}${dl}`;
f.parentNode.insertBefore(j, f);
})(window, document, "script", "dataLayer", gtmId);
}
function updateConfiguredSiteUrl() {
const siteUrl = SITE_CONFIG.siteUrl;
const siteUrlAliases = SITE_CONFIG.siteUrlAliases || [];
if (!siteUrl) return;
document.querySelectorAll("[href], [src]").forEach((el) => {
["href", "src"].forEach((attr) => {
const value = el.getAttribute(attr);
const alias = siteUrlAliases.find(
(item) => value && value.includes(item),
);
if (alias) {
el.setAttribute(attr, value.replaceAll(alias, siteUrl));
}
});
});
if (!document.createTreeWalker || !document.body) return;
const walker = document.createTreeWalker(document.body, 4);
let node = walker.nextNode();
while (node) {
const alias = siteUrlAliases.find((item) =>
node.nodeValue.includes(item),
);
if (alias) {
node.nodeValue = node.nodeValue.replaceAll(alias, siteUrl);
}
node = walker.nextNode();
}
}
function updateSocialLinks() {
const socialLinks = SITE_CONFIG.socialLinks || {};
const selectors = {
instagram: 'a[aria-label="Instagram"]',
facebook: 'a[aria-label="Facebook"]:not([data-disabled="true"])',
tiktok: 'a[aria-label="TikTok"]:not([data-disabled="true"])',
linkedin: 'a[aria-label="LinkedIn"]:not([data-disabled="true"])',
};
Object.entries(selectors).forEach(([key, selector]) => {
const href = socialLinks[key];
if (!href) return;
document
.querySelectorAll(selector)
.forEach((link) => {
link.setAttribute("href", href);
link.setAttribute("target", "_blank");
link.setAttribute("rel", "noopener noreferrer");
});
});
}
function getFooterPath() {
return `${getRootPrefix()}footer.html`;
}
async function loadFooter() {
const placeholders = document.querySelectorAll('[data-include="footer"]');
if (!placeholders.length || !window.fetch) return;
try {
const response = await fetch(getFooterPath());
if (!response.ok) return;
const rootPrefix = getRootPrefix();
const footerHtml = (await response.text()).replaceAll(
'src="assets/',
`src="${rootPrefix}assets/`,
);
placeholders.forEach((placeholder) => {
placeholder.innerHTML = footerHtml;
});
setLang(LANG);
updateConfiguredSiteUrl();
updateSocialLinks();
} catch (e) {}
}
function setLang(l, options = {}) {
const normalizedLang = normalizeLang(l);
if (!normalizedLang) return;
LANG = normalizedLang;
if (options.persist) {
try {
localStorage.setItem(LANG_STORAGE_KEY, normalizedLang);
} catch (e) {}
document.cookie = `${LANG_STORAGE_KEY}=${encodeURIComponent(
normalizedLang,
)};path=/;max-age=31536000;SameSite=Lax`;
}
const localizedPageUrl = options.navigate
? getLocalizedPageUrl(normalizedLang)
: null;
if (localizedPageUrl && localizedPageUrl !== location.pathname + location.search) {
location.href = localizedPageUrl;
return;
}
document.documentElement.lang = normalizedLang;
document.querySelectorAll("[data-i18n]").forEach((el) => {
const v = DICT[normalizedLang][el.getAttribute("data-i18n")];
if (v != null) el.textContent = v;
});
document.querySelectorAll("[data-i18n-html]").forEach((el) => {
const key = el.getAttribute("data-i18n-html");
const v =
key === "pricing"
? getStripePricingTableHtml(normalizedLang)
: DICT[normalizedLang][key];
if (v != null) el.innerHTML = v;
});
document.querySelectorAll("[data-i18n-content]").forEach((el) => {
const v = DICT[normalizedLang][el.getAttribute("data-i18n-content")];
if (v != null) el.setAttribute("content", v);
});
document.querySelectorAll("[data-i18n-ph]").forEach((el) => {
const v = DICT[normalizedLang][el.getAttribute("data-i18n-ph")];
if (v != null) el.setAttribute("placeholder", v);
});
document
.querySelectorAll(".langsw button")
.forEach((b) => {
const isActive = b.dataset.lang === normalizedLang;
b.classList.toggle("on", isActive);
b.setAttribute("aria-pressed", String(isActive));
});
updateInternalLinks(normalizedLang);
renderCountdown();
}
document
.querySelectorAll(".langsw button")
.forEach((b) =>
b.addEventListener("click", () =>
setLang(b.dataset.lang, { persist: true, navigate: true }),
)
);
loadGoogleTagManagerScript();
updateGoogleTagManagerNoScript();
updateConfiguredSiteUrl();
updateSocialLinks();
loadFooter();
/* ---------------- countdown ---------------- */
const TARGET = new Date("2026-07-19T23:59:59+02:00").getTime();
function renderCountdown() {
const now = Date.now();
let diff = Math.max(0, TARGET - now);
const d = Math.floor(diff / 86400000);
diff -= d * 86400000;
const h = Math.floor(diff / 3600000);
diff -= h * 3600000;
const m = Math.floor(diff / 60000);
diff -= m * 60000;
const s = Math.floor(diff / 1000);
const p = (n) => String(n).padStart(2, "0");
const du = (DICT[LANG] && DICT[LANG].cd_d) || "d";
const str = `${d}${du} ${p(h)}h ${p(m)}m ${p(s)}s`;
document.querySelectorAll(".js-cd").forEach((e) => (e.textContent = str));
}
setLang(getInitialLang());
setInterval(renderCountdown, 1000);
/* ---------------- header scroll ---------------- */
const hd = document.getElementById("hd");
if (hd) {
addEventListener(
"scroll",
() => hd.classList.toggle("scrolled", scrollY > 10),
{ passive: true },
);
}
/* ---------------- mobile menu ---------------- */
const burger = document.getElementById("burger");
if (burger && hd) {
burger.addEventListener("click", () => {
const open = hd.classList.toggle("menu-open");
burger.setAttribute("aria-expanded", open);
});
}
document.querySelectorAll("#navlinks a").forEach((a) =>
a.addEventListener("click", () => {
if (hd) hd.classList.remove("menu-open");
if (burger) burger.setAttribute("aria-expanded", "false");
}),
);
/* ---------------- faq accordion ---------------- */
document.querySelectorAll(".qa button").forEach((btn) => {
btn.addEventListener("click", () => {
const qa = btn.parentElement,
ans = qa.querySelector(".ans"),
open = qa.classList.toggle("open");
btn.setAttribute("aria-expanded", open);
ans.hidden = !open;
});
});
/* ---------------- reveal on scroll ---------------- */
const reduce = matchMedia("(prefers-reduced-motion:reduce)").matches;
if (!reduce && "IntersectionObserver" in window) {
const io = new IntersectionObserver(
(es) => {
es.forEach((e) => {
if (e.isIntersecting) {
e.target.classList.add("in");
io.unobserve(e.target);
}
});
},
{ threshold: 0.14 },
);
document.querySelectorAll(".rv").forEach((el) => io.observe(el));
} else {
document.querySelectorAll(".rv").forEach((el) => el.classList.add("in"));
}
@@ -0,0 +1,24 @@
const SITE_CONFIG = {
googleTagManagerId: "GTM-MFN88L24",
siteUrl: "https://www.tutosportexpert.com",
siteUrlAliases: [
"https://tutosportexpert.com",
"https://www.tutosportexpert.com",
],
stripe: {
publishableKey:
"pk_live_51QblVdAVnr0yCjVxfn0VB0H62Kjdpfly5Cg8mVenw34xBvSavUoWCmDZJISEYme3y3nf9SXrA2GUFngt5dHHPa0N00mCehFE2N",
pricingTableIds: {
fr: "prctbl_1TjY4mAVnr0yCjVxprPlzN6a",
en: "prctbl_1TjYLDAVnr0yCjVxbfn2vzkN",
es: "prctbl_1TjYM8AVnr0yCjVx3hmFKXx3",
pt: "prctbl_1TjYMtAVnr0yCjVxKNiktdBr",
},
},
socialLinks: {
instagram: "https://instagram.com/tutosportexpert",
facebook: "#",
tiktok: "#",
linkedin: "#",
},
};
@@ -0,0 +1,24 @@
const SITE_CONFIG = {
googleTagManagerId: "GTM-WTMNS3J8",
siteUrl: "https://preprod.tutosportexpert.com",
siteUrlAliases: [
"https://tutosportexpert.com",
"https://preprod.tutosportexpert.com",
],
stripe: {
publishableKey:
"pk_test_51QblVdAVnr0yCjVxvGKVEnsFExwJ5MJHrfpZha3hUdu6M1boWMVfo69sBvsaMAKPsnusWqI4JoDzsxgxjYOnzEot00ESickqIW",
pricingTableIds: {
fr: "prctbl_1TihgyAVnr0yCjVxitGGF6te",
en: "prctbl_1Tif1XAVnr0yCjVxU6YR803D",
es: "prctbl_1Tif20AVnr0yCjVxkV0GyCMy",
pt: "prctbl_1TifbgAVnr0yCjVxxjJTNQfC",
},
},
socialLinks: {
instagram: "https://instagram.com/tutosportexpert",
facebook: "#",
tiktok: "#",
linkedin: "#",
},
};