Ártáblázat havi és éves nézettel JavaScript demóban

Kinek hasznos ez a demó?

Ez az önálló HTML/CSS/JS ártáblázat elsősorban azoknak a vállalkozóknak lehet hasznos, akik gyorsan, szerveroldali fejlesztés nélkül szeretnének bemutatni egy árazási struktúrát. Különösen praktikus, ha Ön:

  • szolgáltatásait havi és éves díjjal is értékesíti, és az ügyfelek számára átláthatóvá tenné a különbséget;
  • egy landing page vagy termékoldal prototípusát készíti, és vizuálisan ellenőrizné az árkiírás működését;
  • vagy csak szeretné megérteni, hogyan épül fel egy ilyen interaktív elem a v0.app dokumentációja alapján.

A demó teljesen helyi működésű, nem igényel semmilyen háttérrendszert, így bármilyen böngészőben azonnal kipróbálható.

Egy konkrét, elképzelt helyzet

Képzelje el, hogy Ön egy kkv-knak szóló szoftveres szolgáltatást értékesít. Az értékesítési anyagban szeretné bemutatni, hogy éves fizetés esetén az ügyfél mennyit takarít meg a havi díjhoz képest. Ebben a demóban beírja a havi díjat (például 12 000 Ft-ot), kiválasztja a „Havi díj” opciót, és a táblázat azonnal mutatja az éves összesített összeget. Az ügyfél ezt látva azonnal érti az ajánlat lényegét.

Hogyan használja a tényleges demót?

A kód egy beágyazott, működő felületet hoz létre. A használata három egyszerű lépésből áll:

  1. Adja meg az összeget a „Összeg (Ft)” mezőben. Az alapértelmezett érték 12 000 Ft.
  2. Válassza ki az időtartamot a legördülő menüből: „Havi díj” vagy „Éves díj”.
  3. Kattintson a „Számítás” gombra, és a táblázat automatikusan megjeleníti a konvertált értékeket.

A „Újratöltés” gomb visszaállítja az alapértékeket (12 000 Ft, havi díj), és törli a táblázatot.

Három pontos teszt a kód alapján

A kód viselkedését az alábbi tesztekkel ellenőrizheti:

  • 1. teszt – Havi összeg átváltása: Írjon be 10 000 Ft-ot, hagyja a „Havi díj” opciót, majd kattintson a „Számítás” gombra. Várt eredmény: A táblázatban megjelenik a „Havi díj” sor 10 000 Ft-tal, és az „Éves összesen (12 hónap)” sor 120 000 Ft-tal, a sor kiemelt háttérszínt kap.
  • 2. teszt – Éves összeg átváltása: Írjon be 120 000 Ft-ot, válassza az „Éves díj” opciót, majd kattintson a „Számítás” gombra. Várt eredmény: A táblázatban megjelenik az „Éves díj” sor 120 000 Ft-tal, és a „Havi egyenérték” sor 10 000 Ft-tal, szintén kiemeléssel.
  • 3. teszt – Hibás bemenet kezelése: Írjon be negatív számot (-5) vagy szöveget („abc”), majd kattintson a „Számítás” gombra. Várt eredmény: A táblázat nem jelenik meg, a visszajelzési sávban pedig hibaüzenet jelenik meg: „Hibás szám: adjon meg nem negatív pénzösszeget.” vagy „Csak számot írhat be (pl. 8500).”

A demó korlátai

Fontos tisztázni, hogy ez a megoldás kizárólag demonstrációs célokat szolgál. Nem végez valós pénznem- vagy árfolyamszámítást, nem tárol adatokat, és nem tartalmaz semmilyen üzleti logikát (például kedvezményeket vagy több összetevős árazást). A táblázat kizárólag a beírt összeg és a választott időtartam közötti matematikai átváltást mutatja be.

Mit igényelne egy éles weboldal?

Egy valódi, éles weboldalon weboldal készítés során ez a demó további kiegészítéseket igényelne:

  • Reszponzív megjelenés: Bár a kód tartalmaz alapvető nézetport-beállítást, éles környezetben alaposabban tesztelni kell a mobilos és táblagépes megjelenítést.
  • Kiszolgálóoldali ellenőrzés: Ha az árakat űrlapon keresztül küldené be, szerveroldalon is ellenőrizni kell az adatokat, nem csak a böngészőben.
  • Kedvezmény- és árfolyamlogika: Az éles megoldásban általában szükség van különböző árszintekre, esetleg kedvezményekre vagy több fizetési periódusra.
  • Szerkeszthető adatforrás: Az árakat és a választható opciókat érdemes lenne egy tartalomkezelő rendszerből (például WordPress) vagy egy külön JSON-fájlból betölteni, hogy az üzleti felhasználó módosíthassa őket programozói tudás nélkül.

A demó így is kiváló alapot ad egy gyors ötletvizsgálatra, és jól mutatja, milyen egyszerűen lehet interaktív elemeket létrehozni tiszta kóddal.

Próbáld ki a működő példát

A teljes másolható kód

Teljes, másolható index.html

<!DOCTYPE html>
<html lang="hu">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ártáblázat – havi és éves nézet</title>
    <style>
        * { box-sizing: border-box; margin: 0; }
        body {
            background: #202632;
            color: #e6eef8;
            font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
            display: flex;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            padding: 20px;
        }
        .card {
            background: #283040;
            border-radius: 24px;
            padding: 28px;
            max-width: 860px;
            width: 100%;
            box-shadow: 0 15px 30px rgba(0,0,0,0.4);
        }
        h1 {
            font-size: 1.7rem;
            font-weight: 600;
            margin-bottom: 24px;
            letter-spacing: -0.3px;
            border-left: 6px solid #39a0ff;
            padding-left: 16px;
        }
        .controls {
            display: flex;
            flex-wrap: wrap;
            gap: 16px;
            align-items: flex-end;
            margin-bottom: 28px;
        }
        .field {
            display: flex;
            flex-direction: column;
            gap: 8px;
            flex: 1 1 200px;
        }
        label {
            font-size: 0.85rem;
            font-weight: 500;
            opacity: 0.9;
            letter-spacing: 0.3px;
        }
        input, select {
            background: #1a202c;
            border: 1px solid #2f3b4e;
            border-radius: 14px;
            padding: 12px 16px;
            color: #e6eef8;
            font-size: 1rem;
            outline: none;
            transition: 0.2s;
        }
        input:focus, select:focus {
            border-color: #39a0ff;
            box-shadow: 0 0 0 3px rgba(57,160,255,0.2);
        }
        .actions {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
        }
        button {
            background: #39a0ff;
            color: #0b1a2a;
            border: 0;
            border-radius: 12px;
            padding: 12px 22px;
            font-weight: 700;
            font-size: 0.95rem;
            letter-spacing: 0.3px;
            cursor: pointer;
            transition: 0.15s;
            box-shadow: 0 4px 0 #1d6cbb;
        }
        button.clear {
            background: #5b6e8c;
            box-shadow: 0 4px 0 #3a4a66;
            color: #f0f6ff;
        }
        button:active { transform: translateY(4px); box-shadow: none; }
        .table-container {
            background: #1e242e;
            border-radius: 20px;
            padding: 12px;
            overflow-x: auto;
            margin-top: 8px;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            font-size: 0.95rem;
        }
        th, td {
            text-align: left;
            padding: 12px 10px;
            border-bottom: 1px solid #2d3748;
        }
        th {
            color: #9fb3d0;
            font-weight: 600;
            font-size: 0.8rem;
            text-transform: uppercase;
            letter-spacing: 1px;
        }
        td:last-child, th:last-child { text-align: right; }
        td:first-child, th:first-child { font-weight: 500; }
        .feedback {
            background: #2a3442;
            border-radius: 14px;
            padding: 14px 18px;
            margin-top: 20px;
            font-size: 0.9rem;
            color: #bdd3f0;
            border-left: 4px solid #39a0ff;
            min-height: 36px;
        }
        .year-highlight td {
            background: #253041;
        }
        .summary {
            margin-top: 12px;
            display: flex;
            justify-content: flex-end;
            font-size: 0.9rem;
            color: #b9d2f0;
        }
    </style>
</head>
<body>
<main class="card">
    <h1>Ártáblázat – havi / éves nézet</h1>

    <!-- beviteli mezők -->
    <div class="controls">
        <div class="field">
            <label for="amount">Összeg (Ft)</label>
            <input type="number" id="amount" min="0" step="1" value="12000" placeholder="pl. 12000">
        </div>
        <div class="field">
            <label for="unit">Időtartam</label>
            <select id="unit">
                <option value="month">Havi díj</option>
                <option value="year">Éves díj</option>
            </select>
        </div>
        <div class="actions">
            <button type="button" id="generate">Számítás</button>
            <button type="button" id="reset" class="clear">Újratöltés</button>
        </div>
    </div>

    <!-- táblázat -->
    <div class="table-container" id="tableWrap"></div>

    <!-- üzenet / visszajelzés -->
    <div class="feedback" id="feedback">Adja meg az összeget, majd válasszon nézetet.</div>
</main>

<script>
(function() {
    'use strict';

    // elemek
    const amountInput = document.getElementById('amount');
    const unitSelect = document.getElementById('unit');
    const genBtn = document.getElementById('generate');
    const resetBtn = document.getElementById('reset');
    const feedback = document.getElementById('feedback');
    const tableWrap = document.getElementById('tableWrap');

    // tisztítás segéd
    function clearTable() {
        tableWrap.innerHTML = '';
    }

    // sablon használat helyett, textContent mindenhol
    function buildTable(amount, unit) {
        // ellenőrzés + összeg normalizálás
        const numeric = Number(amount);
        if (!isFinite(numeric) || numeric < 0) {
            feedback.textContent = 'Hibás szám: adjon meg nem negatív pénzösszeget.';
            return;
        }
        if (numeric === 0) {
            feedback.textContent = 'Az összeg 0, a táblázat nullákat tartalmaz.';
        } else {
            feedback.textContent = `Érvényes összeg: ${new Intl.NumberFormat('hu-HU').format(Math.round(numeric))} Ft – nézet: ${unit === 'month' ? 'havi' : 'éves'}.`;
        }

        let rows = [];

        if (unit === 'month') {
            // havi összeg → éves (12 hónap)
            const yearly = numeric * 12;
            rows = [
                { label: 'Havi díj', value: numeric, type: 'base' },
                { label: 'Éves összesen (12 hónap)', value: yearly, type: 'total' }
            ];
        } else {
            // éves összeg → havi bontás
            const monthly = numeric / 12;
            rows = [
                { label: 'Éves díj', value: numeric, type: 'base' },
                { label: 'Havi egyenérték', value: monthly, type: 'total' }
            ];
        }

        // táblázat létrehozása DOM használatával (textContent)
        const table = document.createElement('table');
        const thead = document.createElement('thead');
        const headerRow = document.createElement('tr');

        const th1 = document.createElement('th');
        th1.textContent = 'Megnevezés';
        const th2 = document.createElement('th');
        th2.textContent = 'Összeg (Ft)';

        headerRow.appendChild(th1);
        headerRow.appendChild(th2);
        thead.appendChild(headerRow);
        table.appendChild(thead);

        const tbody = document.createElement('tbody');

        rows.forEach((row, idx) => {
            const tr = document.createElement('tr');
            if (row.type === 'total') {
                tr.classList.add('year-highlight'); // kiemelés
            }

            const tdLabel = document.createElement('td');
            tdLabel.textContent = row.label;

            const tdValue = document.createElement('td');
            // kerekítés 2 tizedesre, de kerekítés, mert pénz
            const rounded = Math.round(row.value);
            tdValue.textContent = new Intl.NumberFormat('hu-HU').format(rounded);

            tr.appendChild(tdLabel);
            tr.appendChild(tdValue);
            tbody.appendChild(tr);
        });

        table.appendChild(tbody);
        tableWrap.innerHTML = ''; // törlés
        tableWrap.appendChild(table);
    }

    // event: generálás
    function handleGenerate() {
        clearTable();
        const amount = amountInput.value.trim();
        const unit = unitSelect.value;

        // ha üres vagy nem szám
        if (amount === '') {
            feedback.textContent = 'Adjon meg egy összeget!';
            return;
        }

        const numeric = Number(amount);
        if (isNaN(numeric)) {
            feedback.textContent = 'Csak számot írhat be (pl. 8500).';
            return;
        }
        if (numeric < 0) {
            feedback.textContent = 'Negatív összeg nem lehet.';
            return;
        }

        // megfelelő visszajelzés és táblázat
        buildTable(numeric, unit);
    }

    // reset alapértékekkel
    function handleReset() {
        amountInput.value = '12000';
        unitSelect.value = 'month';
        clearTable();
        feedback.textContent = 'Alapértékek visszaállítva. Adjon meg új összeget, ha szeretné.';
    }

    // eseménykezelők (click, nem form)
    genBtn.addEventListener('click', handleGenerate);
    resetBtn.addEventListener('click', handleReset);

    // kezdeti érték – előállítunk egy alap táblázatot is (de marad a teszt kedvéért)
    // A felhasználó azonnal látja a mintát
    window.addEventListener('load', function() {
        const numeric = Number(amountInput.value);
        if (!isNaN(numeric)) {
            buildTable(numeric, unitSelect.value);
        } else {
            feedback.textContent = 'Adjon meg összeget, a példabetöltés nem sikerült.';
        }
    });
})();
</script>
</body>
</html>

Ajánlatot kérek

A weboldalon megjelenő szöveges és vizuális tartalmak előállításához mesterséges intelligenciát (AI) használunk.