"use strict"; /** * Pagina-views. Elke view geeft een object terug: * { title, html, onMount? } * - title : documenttitel. * - html : markup voor de #app-container. * - onMount: optionele functie die na rendering events koppelt. * * Alle inhoud komt uit de centrale databronnen (PRODUCTS, CATEGORIES, CONTENT). */ (function () { const CL = (window.CL = window.CL || {}); const { formatPrice, escapeHtml, stars } = CL.fmt; const { productGrid, pageHead, crumb, productThumb } = CL.components; const { href } = CL.nav; const PRODUCTS = window.PRODUCTS || []; const CATEGORIES = window.CATEGORIES || [{ key: "all", label: "Alles" }]; const CONTENT = window.CONTENT || {}; const bySlug = (slug) => PRODUCTS.find((p) => p.slug === slug); const categoryLabel = (key) => (CATEGORIES.find((c) => c.key === key) || { label: key }).label; const discount = (p) => Math.round((1 - p.price / p.old) * 100); // ---- Home ----------------------------------------------------------------- function home() { const featured = PRODUCTS.slice(0, 4); return { title: "Converterland — Adapters en signaalconverters", html: `
Universele signaalconversie

Elk signaal naar elk medium. Theoretisch.

Converterland levert adapters voor verbindingen die niet bestaan en problemen die u niet heeft. Een complete catalogus aan fictieve converters, professioneel gepresenteerd en volledig onbruikbaar.

Ondersteunde signalen
Gemiddelde latency3 werkdagen
Compatibiliteit0 / 0
Garantiegeen
Retourtermijnn.v.t.
Niet op voorraad
Elk product, altijd.
Geen verzendkosten
Want geen verzending.
Veilig afrekenen
Er gebeurt niets.
Support 0/7
Wij nemen niet op.

Uitgelicht

Een greep uit onze meest besproken converters.

Alle producten →
${productGrid(featured)}
`, }; } // ---- Producten ------------------------------------------------------------ function producten() { return { title: "Producten — Converterland", html: ` ${pageHead({ eyebrow: "Assortiment", title: "Producten", intro: "Het volledige assortiment fictieve signaalconverters, overzichtelijk gepresenteerd.", crumb: crumb([{ label: "Home", path: "/" }, { label: "Producten" }]), })}

Alle converters

${PRODUCTS.length} producten

${productGrid(PRODUCTS)}
`, }; } // ---- Catalogus (zoeken / sorteren / filteren) ----------------------------- function catalogus() { const filterButtons = CATEGORIES.map( (c) => `` ).join(""); const maxPrice = Math.ceil(Math.max(...PRODUCTS.map((p) => p.price))); return { title: "Catalogus — Converterland", html: ` ${pageHead({ eyebrow: "Catalogus", title: "Catalogus", intro: "Doorzoek, sorteer en filter het volledige assortiment.", crumb: crumb([{ label: "Home", path: "/" }, { label: "Catalogus" }]), })}
${filterButtons}

${productGrid(PRODUCTS)}
`, onMount() { const state = { q: "", sort: "featured", category: "all", maxPrice }; const gridEl = document.getElementById("catalogGrid"); const countEl = document.getElementById("resultCount"); const searchEl = document.getElementById("searchInput"); const sortEl = document.getElementById("sortSelect"); const rangeEl = document.getElementById("priceRange"); const priceOut = document.getElementById("priceOut"); const filtersEl = document.getElementById("filters"); function apply() { let list = PRODUCTS.filter((p) => { if (state.category !== "all" && p.category !== state.category) return false; if (p.price > state.maxPrice) return false; if (state.q) { const hay = (p.name + " " + p.from + " " + p.to + " " + p.desc).toLowerCase(); if (!hay.includes(state.q)) return false; } return true; }); switch (state.sort) { case "price-asc": list.sort((a, b) => a.price - b.price); break; case "price-desc": list.sort((a, b) => b.price - a.price); break; case "rating": list.sort((a, b) => b.rating - a.rating || b.reviews - a.reviews); break; case "name": list.sort((a, b) => a.name.localeCompare(b.name, "nl")); break; } gridEl.innerHTML = productGrid(list); countEl.textContent = list.length + " van " + PRODUCTS.length + " producten"; } searchEl.addEventListener("input", () => { state.q = searchEl.value.trim().toLowerCase(); apply(); }); sortEl.addEventListener("change", () => { state.sort = sortEl.value; apply(); }); rangeEl.addEventListener("input", () => { state.maxPrice = Number(rangeEl.value); priceOut.textContent = formatPrice(state.maxPrice); apply(); }); filtersEl.addEventListener("click", (e) => { const btn = e.target.closest("[data-filter]"); if (!btn) return; state.category = btn.dataset.filter; filtersEl.querySelectorAll(".filter").forEach((b) => b.classList.toggle("active", b === btn)); apply(); }); apply(); }, }; } // ---- Specificaties -------------------------------------------------------- function specificaties() { const rows = PRODUCTS.map( (p) => ` ${escapeHtml(p.name)}${escapeHtml(p.id)} ${escapeHtml(p.from)} → ${escapeHtml(p.to)} ${escapeHtml(categoryLabel(p.category))} ${escapeHtml(p.stock.label)} ${formatPrice(p.price)} ` ).join(""); return { title: "Specificaties — Converterland", html: ` ${pageHead({ eyebrow: "Technische gegevens", title: "Specificaties", intro: "Een vergelijkend overzicht van het volledige assortiment. Alle waarden zijn fictief.", crumb: crumb([{ label: "Home", path: "/" }, { label: "Specificaties" }]), })}
${rows}
ProductConversieCategorieBeschikbaarheidPrijs

Algemene kenmerken

Ondersteunde signalen
Gemiddelde latency3 werkdagen
Compatibiliteit0 / 0
Garantiegeen
Retourtermijnn.v.t.
Certificeringzelfverklaard
`, }; } // ---- Aanbiedingen --------------------------------------------------------- function aanbiedingen() { const list = [...PRODUCTS].sort((a, b) => discount(b) - discount(a)); const cards = list .map((p) => { const fallback = `${escapeHtml(p.from)}${escapeHtml(p.to)}`; return `
-${discount(p)}% ${productThumb(p)}
${escapeHtml(p.id)}${stars(p.rating)}(${p.reviews})

${escapeHtml(p.name)}

${escapeHtml(p.desc)}

${formatPrice(p.price)}${formatPrice(p.old)}
`; }) .join(""); return { title: "Aanbiedingen — Converterland", html: ` ${pageHead({ eyebrow: "Tijdelijk voordeel", title: "Aanbiedingen", intro: "Alle converters zijn afgeprijsd, want niets is iets waard. Gesorteerd op korting.", crumb: crumb([{ label: "Home", path: "/" }, { label: "Aanbiedingen" }]), })}
${cards}
`, }; } // ---- Bedrijf -------------------------------------------------------------- function bedrijf() { const c = CONTENT.company; const values = c.values .map((v) => `

${escapeHtml(v.title)}

${escapeHtml(v.text)}

`) .join(""); return { title: "Bedrijf — Converterland", html: ` ${pageHead({ eyebrow: "Over de onderneming", title: "Bedrijf", intro: c.intro, crumb: crumb([{ label: "Home", path: "/" }, { label: "Bedrijf" }]), })}
${escapeHtml(c.founded)}Opgericht
${escapeHtml(c.employees)}Medewerkers
${PRODUCTS.length}Producten
0Leveringen
${values}
Over ons Vacatures Contact
`, }; } // ---- Over ons ------------------------------------------------------------- function overOns() { const c = CONTENT.company; const timeline = c.history .map((h) => `
  • ${escapeHtml(h.year)}${escapeHtml(h.text)}
  • `) .join(""); return { title: "Over ons — Converterland", html: ` ${pageHead({ eyebrow: "Onze geschiedenis", title: "Over ons", intro: c.intro, crumb: crumb([{ label: "Home", path: "/" }, { label: "Bedrijf", path: "/bedrijf" }, { label: "Over ons" }]), })}

    Hoofdkantoor

    ${escapeHtml(c.headquarters)}

    Tijdlijn

      ${timeline}
    `, }; } // ---- Contact -------------------------------------------------------------- function contact() { const c = CONTENT.contact; return { title: "Contact — Converterland", html: ` ${pageHead({ eyebrow: "Neem contact op", title: "Contact", intro: "Stuur ons een bericht. Het formulier verwerkt geen gegevens en verstuurt niets.", crumb: crumb([{ label: "Home", path: "/" }, { label: "Contact" }]), })}

    `, onMount() { const form = document.getElementById("contactForm"); const note = document.getElementById("contactNote"); form.addEventListener("submit", (e) => { e.preventDefault(); if (!form.checkValidity()) { form.reportValidity(); return; } form.reset(); note.textContent = "Bericht ontvangen in deze demonstratie. Er is niets verzonden of opgeslagen."; }); }, }; } // ---- Vacatures ------------------------------------------------------------ function vacatures() { const items = CONTENT.jobs .map( (j) => `
    ` ) .join(""); return { title: "Vacatures — Converterland", html: ` ${pageHead({ eyebrow: "Werken bij", title: "Vacatures", intro: "Wij groeien al jaren niet, maar er is altijd plek voor talent dat van niets houdt.", crumb: crumb([{ label: "Home", path: "/" }, { label: "Bedrijf", path: "/bedrijf" }, { label: "Vacatures" }]), })}
    ${items}
    `, onMount() { const jobs = document.querySelector(".jobs"); jobs.addEventListener("click", (e) => { const head = e.target.closest("[data-job]"); if (!head) return; const body = head.nextElementSibling; const open = head.getAttribute("aria-expanded") === "true"; head.setAttribute("aria-expanded", String(!open)); head.querySelector(".job-toggle").textContent = open ? "+" : "\u2212"; body.hidden = open; }); }, }; } // ---- Juridische pagina's -------------------------------------------------- function legalPage(key) { const data = CONTENT.legal[key]; const sections = data.sections .map((s) => `

    ${escapeHtml(s.h)}

    ${escapeHtml(s.p)}

    `) .join(""); return { title: data.title + " — Converterland", html: ` ${pageHead({ eyebrow: "Juridisch", title: data.title, intro: data.intro, crumb: crumb([{ label: "Home", path: "/" }, { label: data.title }]), })}
    ${sections}
    `, }; } // ---- Productdetail -------------------------------------------------------- function productDetail(slug) { const p = bySlug(slug); if (!p) return notFound(); const specRows = Object.entries(p.specs) .map(([k, v]) => `
    ${escapeHtml(k)}${escapeHtml(v)}
    `) .join(""); const features = p.features.map((f) => `
  • ${escapeHtml(f)}
  • `).join(""); const fallback = `${escapeHtml(p.from)}${escapeHtml(p.to)}`; const related = PRODUCTS.filter((x) => x.category === p.category && x.id !== p.id).slice(0, 3); const relatedHtml = related.length ? `${CL.components.productGrid(related)}` : ""; return { title: p.name + " — Converterland", html: ` ${pageHead({ crumb: crumb([ { label: "Home", path: "/" }, { label: "Producten", path: "/producten" }, { label: p.name }, ]), title: p.name, })}
    ${productThumb(p)}
    ${escapeHtml(categoryLabel(p.category))} ${escapeHtml(p.from)} → ${escapeHtml(p.to)}
    ${escapeHtml(p.id)} ${stars(p.rating)}(${p.reviews} beoordelingen)
    ${formatPrice(p.price)}${formatPrice(p.old)} U bespaart ${formatPrice(p.old - p.price)}

    ${escapeHtml(p.stock.label)}

    ${escapeHtml(p.long)}

    Verder winkelen

    Eigenschappen

      ${features}

    Technische specificaties

    ${specRows}
    ${ related.length ? `` : "" }
    `, }; } // ---- 404 ------------------------------------------------------------------ function notFound() { return { title: "Niet gevonden — Converterland", html: ` ${pageHead({ eyebrow: "Fout 404", title: "Pagina niet gevonden", intro: "Deze pagina bestaat net zomin als onze producten." })}
    Terug naar de startpagina
    `, }; } CL.pages = { home, producten, catalogus, specificaties, aanbiedingen, bedrijf, overOns, contact, vacatures, voorwaarden: () => legalPage("voorwaarden"), privacy: () => legalPage("privacy"), disclaimer: () => legalPage("disclaimer"), productDetail, notFound, }; })();