Creating a basic calculator using 2 prompts

I asked Codex to create a calculator using the following prompt:

Create a calculator that can add, subtract, multiply and divide 2 numbers together

/* Create a calculator that can add, subtract, multiply and divide 2 numbers together */
var calculator = document.createElement('div');
calculator.innerHTML = '<input type="text" id="num1" value="0" /> <input type="text" id="num2" value="0" /> <button id="add">+</button> <button id="subtract">-</button> <button id="multiply">*</button> <button id="divide">/</button> <div id="result"></div>';
document.body.appendChild(calculator);
var num1 = document.getElementById('num1');
var num2 = document.getElementById('num2');
var result = document.getElementById('result');
document.getElementById('add').addEventListener('click', function() {
  result.innerHTML = parseInt(num1.value) + parseInt(num2.value);
});
document.getElementById('subtract').addEventListener('click', function() {
  result.innerHTML = parseInt(num1.value) - parseInt(num2.value);
});
document.getElementById('multiply').addEventListener('click', function() {
  result.innerHTML = parseInt(num1.value) * parseInt(num2.value);
});
document.getElementById('divide').addEventListener('click', function() {
  result.innerHTML = parseInt(num1.value) / parseInt(num2.value);
});
I then noticed I needed to add a button to clear the results so I could do another calculation. 

/* create a button that clears the results of the calculator */
var clear = document.createElement('button');
clear.innerHTML = 'Clear';
document.body.appendChild(clear);
clear.addEventListener('click', function() {
  result.innerHTML = '';
});

This thing is so incredibly powerful.

I’ll bet there are a lot of examples of this exact exercise in the training data. So amazing that it has glued all of them together, and it works (almost) perfectly!

I had create this calculator https://calculateurheure.fr/ using ChatGPT with just two prompts. I know its not an extraordinary but it completes my visitors needs and they are happy with.

To be serious I can’t have any knowledge about coding, So if there was not ChatGPT, I can’t do this. Thanks Open AI.

Here’s a GPT-5.2 Pro matter-of-fact rewrite of the above Calculatrice de durĂ©e page from its source in one “autonomous” go. The code should be cleaner, standalone (no longer living in WordPress) 
 and for those of us that don’t have fluency in French, internationalized strings in English and Spanish are also employable via the UI.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Duration Calculator</title>
  <style>
:root {
 --bg: #ffffff;
 --surface: #ffffff;
 --surface-muted: #f8fafc;
 --text: #2d3748;
 --text-strong: #1a202c;
 --text-muted: #718096;
 --text-faint: #a0aec0;
 --border: #e2e8f0;
 --border-strong: #cbd5e0;
 --accent: #805ad5;
 --btn-add: #10b981;
 --btn-sub: #475569;
 --shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
 --radius-sm: 8px;
 --radius-md: 10px;
 --radius-lg: 12px;
 --radius-xl: 16px;
 --font: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
 margin: 0;
 font-family: var(--font);
 font-size: 17px;
 line-height: 1.6;
 background: var(--bg);
 color: var(--text);
}
button, input, select { font: inherit; }
button { cursor: pointer; }
:focus-visible {
 outline: 2px solid rgba(128, 90, 213, 0.45);
 outline-offset: 2px;
}

.sr-only {
 position: absolute;
 width: 1px;
 height: 1px;
 padding: 0;
 margin: -1px;
 overflow: hidden;
 clip: rect(0, 0, 0, 0);
 white-space: nowrap;
 border: 0;
}

.app {
 min-height: 100%;
 display: grid;
 place-items: start center;
 padding: 28px 12px;
}

.calculator {
 width: 100%;
 max-width: 480px;
 background: var(--surface);
 padding: 10px;
}

.toolbar {
 display: flex;
 justify-content: flex-end;
 padding: 0 10px 8px 10px;
}

.lang-select {
 display: inline-flex;
 align-items: center;
 gap: 8px;
 font-size: 12px;
 color: var(--text-muted);
}

.lang-select select {
 border: 1px solid var(--border-strong);
 border-radius: 999px;
 padding: 6px 10px;
 background: #fff;
 color: var(--text);
}

.header-row {
 display: flex;
 padding: 0 10px;
 margin-bottom: 8px;
 gap: 10px;
}

.header-col {
 flex: 1;
 font-size: 11px;
 font-weight: 800;
 color: var(--text-muted);
 text-transform: uppercase;
 letter-spacing: 0.5px;
 text-align: center;
}

.header-spacer { width: 30px; }

.rows {
 display: grid;
 gap: 10px;
}

.row {
 background: #fff;
 border: 1px solid var(--border);
 border-radius: var(--radius-lg);
 padding: 10px;
 display: flex;
 align-items: center;
 box-shadow: var(--shadow);
}

.inputs {
 display: flex;
 flex: 1;
 gap: 10px;
}

.field {
 flex: 1;
 border: 1px solid var(--border-strong);
 border-radius: var(--radius-sm);
 position: relative;
 height: 55px;
 background: #fff;
}

.field-label {
 position: absolute;
 top: 4px;
 left: 8px;
 font-size: 10px;
 font-weight: 700;
 color: var(--accent);
 text-transform: uppercase;
}

.field-input {
 width: 100%;
 height: 100%;
 border: none;
 background: transparent;
 text-align: center;
 font-size: 20px;
 font-weight: 700;
 color: var(--text);
 padding-top: 12px;
 outline: none;
}

.field-input::placeholder { color: var(--border); }

.field-input::-webkit-inner-spin-button,
.field-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.field-input { -moz-appearance: textfield; }

.delete {
 width: 30px;
 margin-left: 8px;
 border: 0;
 background: transparent;
 color: var(--border-strong);
 display: flex;
 align-items: center;
 justify-content: center;
 padding: 0;
}

.delete svg { width: 20px; height: 20px; }

.add-line-wrap {
 text-align: center;
 margin: 15px 0 25px 0;
}

.btn-outline {
 background: #fff;
 border: 1px solid var(--border-strong);
 border-radius: 999px;
 padding: 8px 24px;
 color: var(--text-muted);
 font-weight: 700;
 font-size: 11px;
 display: inline-flex;
 align-items: center;
 gap: 6px;
 outline: none;
 text-transform: uppercase;
 letter-spacing: 0.5px;
}

.actions {
 display: flex;
 gap: 12px;
 margin-bottom: 20px;
}

.main-btn {
 flex: 1;
 padding: 14px;
 border: none;
 border-radius: var(--radius-md);
 font-size: 13px;
 font-weight: 800;
 text-transform: uppercase;
 letter-spacing: 0.5px;
 display: inline-flex;
 align-items: center;
 justify-content: center;
 gap: 8px;
}

.btn-add { background: var(--btn-add); color: #fff; }
.btn-sub { background: var(--btn-sub); color: #fff; }

.reset-wrap {
 text-align: center;
 margin-bottom: 25px;
}

.reset svg { width: 14px; height: 14px; }

.result {
 background: var(--surface-muted);
 border: 1px solid #edf2f7;
 border-radius: var(--radius-xl);
 padding: 25px;
 text-align: center;
}

.result-title {
 color: var(--text-faint);
 font-size: 11px;
 font-weight: 700;
 text-transform: uppercase;
 letter-spacing: 1.5px;
 margin-bottom: 10px;
}

.result-value {
 font-size: 42px;
 font-weight: 800;
 color: var(--text-strong);
 line-height: 1;
 display: flex;
 justify-content: center;
 align-items: baseline;
}

.unit {
 font-size: 20px;
 color: var(--border-strong);
 font-weight: 700;
 margin-left: 2px;
 margin-right: 12px;
}

.unit:last-child { margin-right: 0; }

@media (max-width: 600px) {
 .app { padding: 18px 8px; }
 .calculator { max-width: 100%; padding: 10px 5px; }
}
  </style>
</head>
<body>
  <main class="app">
    <section class="calculator" id="dc-app" aria-label="Duration calculator">
      <div class="toolbar">
        <div class="lang-select">
          <label for="dc-lang" data-i18n="languageLabel">Language</label>
          <select id="dc-lang" name="lang" data-role="lang">
            <option value="en">English</option>
            <option value="fr">Français</option>
            <option value="es">Español</option>
          </select>
        </div>
      </div>

      <div class="header-row" role="row">
        <div class="header-col" role="columnheader" data-i18n="hours">HOURS</div>
        <div class="header-col" role="columnheader" data-i18n="minutes">MINUTES</div>
        <div class="header-col" role="columnheader" data-i18n="seconds">SECONDS</div>
        <div class="header-spacer" aria-hidden="true"></div>
      </div>

      <div class="rows" id="dc-rows" aria-live="polite"></div>

      <div class="add-line-wrap">
        <button class="btn-outline" id="dc-add-row" type="button">
          <span aria-hidden="true">+</span>
          <span data-i18n="addRow">ADD A ROW</span>
        </button>
      </div>

      <div class="actions">
        <button class="main-btn btn-add" id="dc-add" type="button">
          <span aria-hidden="true">+</span>
          <span data-i18n="add">ADD</span>
        </button>
        <button class="main-btn btn-sub" id="dc-sub" type="button">
          <span aria-hidden="true">−</span>
          <span data-i18n="subtract">SUBTRACT</span>
        </button>
      </div>

      <div class="reset-wrap">
        <button class="btn-outline reset" id="dc-reset" type="button">
          <svg aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
          </svg>
          <span data-i18n="reset">RESET</span>
        </button>
      </div>

      <div class="result" role="status" aria-live="polite">
        <div class="result-title" id="dc-mode"></div>
        <div class="result-value" data-i18n-aria-label="result" aria-label="Result">
          <span id="dc-res-h">00</span><span class="unit" id="dc-unit-h">h</span>
          <span id="dc-res-m">00</span><span class="unit" id="dc-unit-m">m</span>
          <span id="dc-res-s">00</span><span class="unit" id="dc-unit-s">s</span>
        </div>
      </div>

      <template id="dc-row-template">
        <div class="row">
          <div class="inputs">
            <div class="field">
              <span class="field-label" aria-hidden="true">H</span>
              <input class="field-input dc-h" type="number" inputmode="numeric" pattern="[0-9]*" min="0" placeholder="00" autocomplete="off" data-i18n-placeholder="placeholder" data-i18n-aria-label="ariaHours">
            </div>
            <div class="field">
              <span class="field-label" aria-hidden="true">M</span>
              <input class="field-input dc-m" type="number" inputmode="numeric" pattern="[0-9]*" min="0" placeholder="00" autocomplete="off" data-i18n-placeholder="placeholder" data-i18n-aria-label="ariaMinutes">
            </div>
            <div class="field">
              <span class="field-label" aria-hidden="true">S</span>
              <input class="field-input dc-s" type="number" inputmode="numeric" pattern="[0-9]*" min="0" placeholder="00" autocomplete="off" data-i18n-placeholder="placeholder" data-i18n-aria-label="ariaSeconds">
            </div>
          </div>
          <button class="delete" type="button" data-action="delete" data-i18n-title="deleteRow" data-i18n-aria-label="deleteRow" title="Delete row" aria-label="Delete row">
            <span class="sr-only" data-i18n="deleteRow">Delete row</span>
            <svg aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
            </svg>
          </button>
        </div>
      </template>
    </section>
  </main>

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

  // i18n : dictionnaire central, détection de langue, et application des textes/attributs.
  const STRINGS = {
    en: {
      appTitle: 'Duration Calculator (add or subtract)',
      languageLabel: 'Language',
      hours: 'HOURS',
      minutes: 'MINUTES',
      seconds: 'SECONDS',
      addRow: 'ADD A ROW',
      add: 'ADD',
      subtract: 'SUBTRACT',
      reset: 'RESET',
      deleteRow: 'Delete row',
      placeholder: '00',
      result: 'Result',
      ariaHours: 'Hours',
      ariaMinutes: 'Minutes',
      ariaSeconds: 'Seconds',
      modeAdd: 'ADDITION',
      modeSub: 'SUBTRACTION',
      totalMode: 'TOTAL ({mode})',
      unitH: 'h',
      unitM: 'm',
      unitS: 's'
    },
    fr: {
      appTitle: 'Calculatrice de durée (addition ou soustraction)',
      languageLabel: 'Langue',
      hours: 'HEURES',
      minutes: 'MINUTES',
      seconds: 'SECONDES',
      addRow: 'AJOUTER UNE LIGNE',
      add: 'AJOUTER',
      subtract: 'SOUSTRAIRE',
      reset: 'RÉINITIALISER',
      deleteRow: 'Supprimer la ligne',
      placeholder: '00',
      result: 'Résultat',
      ariaHours: 'Heures',
      ariaMinutes: 'Minutes',
      ariaSeconds: 'Secondes',
      modeAdd: 'ADDITION',
      modeSub: 'SOUSTRACTION',
      totalMode: 'TOTAL ({mode})',
      unitH: 'h',
      unitM: 'm',
      unitS: 's'
    },
    es: {
      appTitle: 'Calculadora de duraciĂłn (sumar o restar)',
      languageLabel: 'Idioma',
      hours: 'HORAS',
      minutes: 'MINUTOS',
      seconds: 'SEGUNDOS',
      addRow: 'AÑADIR UNA FILA',
      add: 'SUMAR',
      subtract: 'RESTAR',
      reset: 'REINICIAR',
      deleteRow: 'Eliminar fila',
      placeholder: '00',
      result: 'Resultado',
      ariaHours: 'Horas',
      ariaMinutes: 'Minutos',
      ariaSeconds: 'Segundos',
      modeAdd: 'SUMA',
      modeSub: 'RESTA',
      totalMode: 'TOTAL ({mode})',
      unitH: 'h',
      unitM: 'm',
      unitS: 's'
    }
  };

  const STORAGE_KEY = 'durationCalculator.locale';
  const DEFAULT_LOCALE = 'en';

  function normalizeLocale(tag) {
    const base = String(tag || '').toLowerCase().split('-')[0];
    return STRINGS[base] ? base : DEFAULT_LOCALE;
  }

  function detectLocale() {
    const saved = localStorage.getItem(STORAGE_KEY);
    if (saved && STRINGS[saved]) return saved;

    const candidates = Array.isArray(navigator.languages) && navigator.languages.length ? navigator.languages : [navigator.language];
    for (const candidate of candidates) {
      const normalized = normalizeLocale(candidate);
      if (STRINGS[normalized]) return normalized;
    }

    return DEFAULT_LOCALE;
  }

  function formatTemplate(text, vars) {
    return String(text).replace(/\{(\w+)\}/g, (_, key) => {
      if (!vars) return `{${key}}`;
      return key in vars ? String(vars[key]) : `{${key}}`;
    });
  }

  const i18n = {
    locale: detectLocale(),
    t(key, vars) {
      const dict = STRINGS[this.locale] || STRINGS[DEFAULT_LOCALE];
      const fallback = STRINGS[DEFAULT_LOCALE];
      const raw = key in dict ? dict[key] : (fallback[key] || key);
      return formatTemplate(raw, vars);
    },
    apply(root) {
      const setText = (el, key) => { el.textContent = this.t(key); };
      const setAttr = (el, attr, key) => { el.setAttribute(attr, this.t(key)); };

      root.querySelectorAll('[data-i18n]').forEach(el => setText(el, el.getAttribute('data-i18n')));
      root.querySelectorAll('[data-i18n-title]').forEach(el => setAttr(el, 'title', el.getAttribute('data-i18n-title')));
      root.querySelectorAll('[data-i18n-placeholder]').forEach(el => setAttr(el, 'placeholder', el.getAttribute('data-i18n-placeholder')));
      root.querySelectorAll('[data-i18n-aria-label]').forEach(el => setAttr(el, 'aria-label', el.getAttribute('data-i18n-aria-label')));

      document.title = this.t('appTitle');
      document.documentElement.lang = this.locale;

      const unitH = document.getElementById('dc-unit-h');
      const unitM = document.getElementById('dc-unit-m');
      const unitS = document.getElementById('dc-unit-s');
      if (unitH) unitH.textContent = this.t('unitH');
      if (unitM) unitM.textContent = this.t('unitM');
      if (unitS) unitS.textContent = this.t('unitS');
    },
    setLocale(locale, { persist = true } = {}) {
      const next = normalizeLocale(locale);
      this.locale = next;
      if (persist) localStorage.setItem(STORAGE_KEY, next);
      this.apply(document);
      document.dispatchEvent(new CustomEvent('i18n:changed', { detail: { locale: next } }));
    }
  };

  window.DurationCalculator = window.DurationCalculator || {};
  window.DurationCalculator.i18n = i18n;
})();
  </script>

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

  // Calculatrice : gestion des lignes dynamiques et calculs (addition / soustraction).
  document.addEventListener('DOMContentLoaded', () => {
    const i18n = window.DurationCalculator.i18n;

    const els = {
      rows: document.getElementById('dc-rows'),
      tpl: document.getElementById('dc-row-template'),
      lang: document.getElementById('dc-lang'),
      addRow: document.getElementById('dc-add-row'),
      add: document.getElementById('dc-add'),
      sub: document.getElementById('dc-sub'),
      reset: document.getElementById('dc-reset'),
      mode: document.getElementById('dc-mode'),
      resH: document.getElementById('dc-res-h'),
      resM: document.getElementById('dc-res-m'),
      resS: document.getElementById('dc-res-s')
    };

    let lastMode = 'add';

    function pad2(n) {
      return n < 10 ? '0' + n : String(n);
    }

    function secsFromRow(row) {
      const h = parseInt(row.querySelector('.dc-h').value, 10) || 0;
      const m = parseInt(row.querySelector('.dc-m').value, 10) || 0;
      const s = parseInt(row.querySelector('.dc-s').value, 10) || 0;
      return (h * 3600) + (m * 60) + s;
    }

    function setResult(totalSecs) {
      const isNeg = totalSecs < 0;
      const abs = Math.abs(totalSecs);

      const h = Math.floor(abs / 3600);
      const rem = abs % 3600;
      const m = Math.floor(rem / 60);
      const s = rem % 60;

      els.resH.textContent = (isNeg ? '-' : '') + pad2(h);
      els.resM.textContent = pad2(m);
      els.resS.textContent = pad2(s);
    }

    function renderMode(mode) {
      lastMode = mode;
      const modeLabel = mode === 'sub' ? i18n.t('modeSub') : i18n.t('modeAdd');
      els.mode.textContent = i18n.t('totalMode', { mode: modeLabel });
    }

    function addRow() {
      const fragment = els.tpl.content.cloneNode(true);
      els.rows.appendChild(fragment);
      i18n.apply(document);
    }

    function resetRows() {
      els.rows.innerHTML = '';
      addRow();
      addRow();
    }

    function calculateAdd() {
      let total = 0;
      els.rows.querySelectorAll('.row').forEach((row) => {
        total += secsFromRow(row);
      });
      setResult(total);
      renderMode('add');
    }

    function calculateSub() {
      const rows = Array.from(els.rows.querySelectorAll('.row'));
      if (!rows.length) {
        setResult(0);
        renderMode('sub');
        return;
      }

      let total = secsFromRow(rows[0]);
      for (let i = 1; i < rows.length; i += 1) {
        total -= secsFromRow(rows[i]);
      }

      setResult(total);
      renderMode('sub');
    }

    els.lang.addEventListener('change', () => {
      i18n.setLocale(els.lang.value);
      els.lang.value = i18n.locale;
      renderMode(lastMode);
    });

    els.addRow.addEventListener('click', addRow);

    els.rows.addEventListener('click', (e) => {
      const deleteBtn = e.target.closest('[data-action="delete"]');
      if (!deleteBtn) return;

      const row = deleteBtn.closest('.row');
      const remaining = els.rows.querySelectorAll('.row').length;

      if (remaining > 1) {
        row.remove();
      } else {
        row.querySelectorAll('input').forEach((input) => { input.value = ''; });
      }
    });

    els.reset.addEventListener('click', () => {
      resetRows();
      setResult(0);
      renderMode('add');
    });

    els.add.addEventListener('click', calculateAdd);
    els.sub.addEventListener('click', calculateSub);

    i18n.apply(document);
    i18n.setLocale(i18n.locale, { persist: true });
    els.lang.value = i18n.locale;
    resetRows();
    setResult(0);
    renderMode('add');
  });
})();
  </script>
</body>
</html>

The style and structure was also prompted. The original rather opaque “subtraction” was preserved, where a better UI might be to have a (+) or (-) per-entry.

106k → 18k
Just offered here instead of promoting a host location.

After this task, another calculation done

image