Project shows: 22 document.querySelector(…)’s are used to handle access to the many moving parts of this DOM.

Class objects are used to hold individual customer account data. A class object is also used to hold currency data. An array is used to hold deposits/withdrawls for each account.

Functions are used to do the following:
displayAccountHolders = function (accts) { *.insertAdjacentHTML(…, html) }

displayMovements = function (movements, sort = false) { …
  … = sort ?.slice().sort((a, b) => a – b) :
  movs.forEach(function (mov, i) { … *.insertAdjacentHTML(…, html) } }
calcDisplayBalance = function (acc) { … =.reduce((acc, mov) => acc + mov, 0) … }
calcDisplaySummary = function (acc) { … = .filter(mov => mov > 0).reduce((acc, mov=> acc + mov, 0) …
  … =  ….filter(mov => mov > 0).map(deposit => (deposit * acc.interestRate) / 100).filter((int, i, arr=> int >= 1).reduce((acc, int=> acc + int, 0) … }
createUserNames = function (accnts) { … =.toLowerCase().split(‘ ‘).map(name => name[0]).join() }

And a global function is used to:

updateUI = function (acc) { … displayMovements(…) calcDisplayBalance(…)  calcDisplaySummary(acc) }
5 eventListeners are used for:
– btn….addEventListener(‘click’, function (e) { e.preventDefault() …
  currentAccount = accounts.find(acc => acc.username === inputLoginUsername.value) … }
<!DOCTYPE html>
<html lang=“en”>
  <head>
    <meta charset=“UTF-8” />
    <meta name=“viewport” content=“width=device-width, initial-scale=1.0” />
    <meta http-equiv=“X-UA-Compatible” content=“ie=edge” />
    <link rel=“shortcut icon” type=“image/png” href=“/icon.png” />

    <link
      href=“https://fonts.googleapis.com/css?family=Poppins:400,500,600&display=swap”
      rel=“stylesheet”
    />

    <link rel=“stylesheet” href=“style.css” />
    <title>Bankist</title>
  </head>
  <body>
    <!– TOP NAVIGATION –>
    <nav>
      <p class=“welcome”>Log in to get started</p>
      <img src=“logo.png” alt=“Logo” class=“logo” />
      <div class=“accounts”>
        <div class=“acc_username_pin”></div>
      </div>
      <form class=“login”>
        <input
          type=“text”
          placeholder=“user”
          class=“login__input login__input–user”
          value=“js”
        />
        <!– In practice, use type=”password” –>
        <input
          type=“text”
          placeholder=“PIN”
          maxlength=“4”
          class=“login__input login__input–pin”
          value=“1111”
        />
        <button class=“login__btn”>&rarr;</button>
      </form>
    </nav>

    <main class=“app”>
      <!– BALANCE –>
      <div class=“balance”>
        <div>
          <p class=“balance__label”>Current balance</p>
          <p class=“balance__date”>
            As of <span class=“date”>05/03/2037</span>
          </p>
        </div>
        <p class=“balance__value”>0000€</p>
      </div>

      <!– MOVEMENTS –>
      <div class=“movements”>
        <div class=“movements__row”>
          <div class=“movements__type movements__type–deposit”>2 deposit</div>
          <div class=“movements__date”>3 days ago</div>
          <div class=“movements__value”>4 000€</div>
        </div>
        <div class=“movements__row”>
          <div class=“movements__type movements__type–withdrawal”>
            1 withdrawal
          </div>
          <div class=“movements__date”>24/01/2037</div>
          <div class=“movements__value”>-378€</div>
        </div>
      </div>

      <!– SUMMARY –>
      <div class=“summary”>
        <p class=“summary__label”>In</p>
        <p class=“summary__value summary__value–in”>0000€</p>
        <p class=“summary__label”>Out</p>
        <p class=“summary__value summary__value–out”>0000€</p>
        <p class=“summary__label”>Interest</p>
        <p class=“summary__value summary__value–interest”>0000€</p>
        <button class=“btn–sort”>&downarrow; SORT</button>
      </div>

      <!– OPERATION: TRANSFERS –>
      <div class=“operation operation–transfer”>
        <h2>Transfer money</h2>
        <form class=“form form–transfer”>
          <input type=“text” class=“form__input form__input–to” />
          <input type=“number” class=“form__input form__input–amount” />
          <button class=“form__btn form__btn–transfer”>&rarr;</button>
          <label class=“form__label”>Transfer to</label>
          <label class=“form__label”>Amount</label>
        </form>
      </div>

      <!– OPERATION: LOAN –>
      <div class=“operation operation–loan”>
        <h2>Request loan</h2>
        <form class=“form form–loan”>
          <input type=“number” class=“form__input form__input–loan-amount” />
          <button class=“form__btn form__btn–loan”>&rarr;</button>
          <label class=“form__label form__label–loan”>Amount</label>
        </form>
      </div>

      <!– OPERATION: CLOSE –>
      <div class=“operation operation–close”>
        <h2>Close account</h2>
        <form class=“form form–close”>
          <input type=“text” class=“form__input form__input–user” />
          <input
            type=“password”
            maxlength=“6”
            class=“form__input form__input–pin”
          />
          <button class=“form__btn form__btn–close”>&rarr;</button>
          <label class=“form__label”>Confirm user</label>
          <label class=“form__label”>Confirm PIN</label>
        </form>
      </div>

      <!– LOGOUT TIMER –>
      <p class=“logout-timer”>
        You will be logged out in <span class=“timer”>05:00</span>
      </p>
    </main>

    <!– <footer>
      &copy; by Jonas Schmedtmann. Don’t claim as your own 🙂
    </footer> –>

    <script src=“script.js”></script>
  </body>
</html>
‘use strict’;

// Data
const account1 = {
  owner: ‘Jonas Schmedtmann’,
  movements: [200, 450, 400, 3000, 650, 130, 70, 1300],
  interestRate: 1.2, // %
  pin: 1111,
};

const account2 = {
  owner: ‘Jessica Davis’,
  movements: [5000, 3400, 150, 790, 3210, 1000, 8500, 30],
  interestRate: 1.5,
  pin: 2222,
};

const account3 = {
  owner: ‘Steven Thomas Williams’,
  movements: [200, 200, 340, 300, 20, 50, 400, 460],
  interestRate: 0.7,
  pin: 3333,
};

const account4 = {
  owner: ‘Sarah Smith’,
  movements: [430, 1000, 700, 50, 90],
  interestRate: 1,
  pin: 4444,
};

const accounts = [account1, account2, account3, account4];

// Elements
const labelWelcome = document.querySelector(‘.welcome’);
const labelDate = document.querySelector(‘.date’);
const labelBalance = document.querySelector(‘.balance__value’);
const labelSumIn = document.querySelector(‘.summary__value–in’);
const labelSumOut = document.querySelector(‘.summary__value–out’);
const labelSumInterest = document.querySelector(‘.summary__value–interest’);
const labelTimer = document.querySelector(‘.timer’);

const accounts_username_pin = document.querySelector(‘.accounts’);

const containerApp = document.querySelector(‘.app’);
const containerMovements = document.querySelector(‘.movements’);

const btnLogin = document.querySelector(‘.login__btn’);
const btnTransfer = document.querySelector(‘.form__btn–transfer’);
const btnLoan = document.querySelector(‘.form__btn–loan’);
const btnClose = document.querySelector(‘.form__btn–close’);
const btnSort = document.querySelector(‘.btn–sort’);

const inputLoginUsername = document.querySelector(‘.login__input–user’);
const inputLoginPin = document.querySelector(‘.login__input–pin’);
const inputTransferTo = document.querySelector(‘.form__input–to’);
const inputTransferAmount = document.querySelector(‘.form__input–amount’);
const inputLoanAmount = document.querySelector(‘.form__input–loan-amount’);
const inputCloseUsername = document.querySelector(‘.form__input–user’);
const inputClosePin = document.querySelector(‘.form__input–pin’);

const currencies = new Map([
  [‘USD’, ‘United States dollar’],
  [‘EUR’, ‘Euro’],
  [‘GBP’, ‘Pound sterling’],
]);

const movements = [200, 450, 400, 3000, 650, 130, 70, 1300];

const displayAccountHolders = function (accts) {
  accts.forEach(function (acc, i) {
    const html = `
      <div class=”acc_username_pin”>Username: ${acc.username}, PIN ${acc.pin}</div>
        `;

    accounts_username_pin.insertAdjacentHTML(‘afterbegin’, html);
  });
};
const displayMovements = function (movements, sort = false) {
  containerMovements.innerHTML = ;

  const movs = sort ? movements.slice().sort((a, b) => a b) : movements;

  movs.forEach(function (mov, i) {
    const type = mov > 0 ? ‘deposit’ : ‘withdrawal’;
    const html = `
      <div class=”movements__row”>
            <div class=”movements__type movements__type–${type}“>${
      i + 1
    } ${type}</div>
            <div class=”movements__value”>${mov}€</div>
          </div>
        `;

    containerMovements.insertAdjacentHTML(‘afterbegin’, html);
  });
};
//displayMovements(account1.movements);

//console.log(containerMovements.innerHTML);

const calcDisplayBalance = function (acc) {
  acc.balance = acc.movements.reduce((acc, mov) => acc + mov, 0);
  labelBalance.textContent = `${acc.balance} €`;
};
//calcDisplayBalance(account1.movements);

const calcDisplaySummary = function (acc) {
  const incomes = acc.movements
    .filter(mov => mov > 0)
    .reduce((acc, mov) => acc + mov, 0);
  labelSumIn.textContent = `${incomes}€`;

  const out = acc.movements
    .filter(mov => mov < 0)
    .reduce((acc, mov) => acc mov, 0);
  labelSumOut.textContent = `${out}€`;

  const interest = acc.movements
    .filter(mov => mov > 0)
    .map(deposit => (deposit * acc.interestRate) / 100)
    .filter((int, i, arr) => int >= 1)
    .reduce((acc, int) => acc + int, 0);
  labelSumInterest.textContent = `${interest}€`;
};
//calcDisplaySummary(account1.movements);

// create the account username and add it to the objects
const createUserNames = function (accnts) {
  accnts.forEach(function (accnt) {
    accnt.username = accnt.owner
      .toLowerCase()
      .split(‘ ‘)
      .map(name => name[0])
      .join();
  });
};

createUserNames(accounts);
//console.log(accounts);

// Display account holders
displayAccountHolders(accounts);

const updateUI = function (acc) {
  // Display movements
  displayMovements(acc.movements);

  // Display balance
  calcDisplayBalance(acc);

  // Display summary
  calcDisplaySummary(acc);
};

let currentAccount;

btnLogin.addEventListener(‘click’, function (e) {
  // Prevent form from submitting
  e.preventDefault();

  currentAccount = accounts.find(
    acc => acc.username === inputLoginUsername.value
  );

  if (currentAccount?.pin === Number(inputLoginPin.value)) {
    // Display UI and welcome message
    labelWelcome.textContent = `Welcome back ${
      currentAccount.owner.split(‘ ‘)[0]
    }`;
    containerApp.style.opacity = 100;

    // Clear input fields
    inputLoginUsername.value = inputLoginPin.value = ;
    inputLoginPin.blur();

    // Update UI
    updateUI(currentAccount);
  }
});

btnTransfer.addEventListener(‘click’, function (e) {
  e.preventDefault();
  const amount = Number(inputTransferAmount.value);
  const receiverAcc = accounts.find(
    acc => acc.username === inputTransferTo.value
  );
  inputTransferAmount.value = inputTransferTo.value = ;

  if (
    amount > 0 &&
    receiverAcc &&
    currentAccount.balance >= amount &&
    receiverAcc.username !== currentAccount.username
  ) {
    // Doing the transfer
    currentAccount.movements.push(amount);
    receiverAcc.movements.push(amount);

    // Update UI
    updateUI(currentAccount);
  }
});

btnLoan.addEventListener(‘click’, function (e) {
  e.preventDefault();

  const amount = Number(inputLoanAmount.value);

  if (amount > 0 && currentAccount.movements.some(mov => mov >= amount * 0.1)) {
    // Add the movement
    currentAccount.movements.push(amount);

    // Update UI
    updateUI(currentAccount);
  }
  inputLoanAmount.value = ;
});

btnClose.addEventListener(‘click’, function (e) {
  e.preventDefault();
  if (
    inputCloseUsername.value === currentAccount.username &&
    currentAccount.pin === Number(inputClosePin.value)
  ) {
    const index = accounts.findIndex(
      acc => acc.username === currentAccount.username
    );

    // Delete account
    accounts.splice(index, 1);

    // Hide UI
    containerApp.style.opacity = 0;
  }
  inputCloseUsername = inputClosePin = ;
});

let sorted = false;

btnSort.addEventListener(‘click’, function (e) {
  e.preventDefault();
  displayMovements(currentAccount.movements, !sorted);
  sorted = !sorted;
});
/*
 * Use this CSS to learn some intersting techniques,
 * in case you’re wondering how I built the UI.
 * Have fun! 😁
 */

* {
  margin: 0;
  padding: 0;
  box-sizing: inherit;
}

html {
  font-size: 62.5%;
  box-sizing: border-box;
}

body {
  font-family: ‘Poppins’, sans-serif;
  color: #444;
  background-color: #f3f3f3;
  height: 100vh;
  padding: 2rem;
}

nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 2rem;
}

.accounts {
  font-size: 1.5rem;
  font-weight: 300;
}

.welcome {
  font-size: 1.9rem;
  font-weight: 500;
}

.logo {
  height: 5.25rem;
}

.login {
  display: flex;
}

.login__input {
  border: none;
  padding: 0.5rem 2rem;
  font-size: 1.6rem;
  font-family: inherit;
  text-align: center;
  width: 12rem;
  border-radius: 10rem;
  margin-right: 1rem;
  color: inherit;
  border: 1px solid #fff;
  transition: all 0.3s;
}

.login__input:focus {
  outline: none;
  border: 1px solid #ccc;
}

.login__input::placeholder {
  color: #bbb;
}

.login__btn {
  border: none;
  background: none;
  font-size: 2.2rem;
  color: inherit;
  cursor: pointer;
  transition: all 0.3s;
}

.login__btn:hover,
.login__btn:focus,
.btn–sort:hover,
.btn–sort:focus {
  outline: none;
  color: #777;
}

/* MAIN */
.app {
  position: relative;
  max-width: 100rem;
  margin: 4rem auto;
  display: grid;
  grid-template-columns: 4fr 3fr;
  grid-template-rows: auto repeat(3, 15rem) auto;
  gap: 2rem;

  /* NOTE This creates the fade in/out anumation */
  opacity: 0;
  transition: all 1s;
}

.balance {
  grid-column: 1 / span 2;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 2rem;
}

.balance__label {
  font-size: 2.2rem;
  font-weight: 500;
  margin-bottom: -0.2rem;
}

.balance__date {
  font-size: 1.4rem;
  color: #888;
}

.balance__value {
  font-size: 4.5rem;
  font-weight: 400;
}

/* MOVEMENTS */
.movements {
  grid-row: 2 / span 3;
  background-color: #fff;
  border-radius: 1rem;
  overflow: scroll;
}

.movements__row {
  padding: 2.25rem 4rem;
  display: flex;
  align-items: center;
  border-bottom: 1px solid #eee;
}

.movements__type {
  font-size: 1.1rem;
  text-transform: uppercase;
  font-weight: 500;
  color: #fff;
  padding: 0.1rem 1rem;
  border-radius: 10rem;
  margin-right: 2rem;
}

.movements__date {
  font-size: 1.1rem;
  text-transform: uppercase;
  font-weight: 500;
  color: #666;
}

.movements__type–deposit {
  background-image: linear-gradient(to top left, #39b385, #9be15d);
}

.movements__type–withdrawal {
  background-image: linear-gradient(to top left, #e52a5a, #ff585f);
}

.movements__value {
  font-size: 1.7rem;
  margin-left: auto;
}

/* SUMMARY */
.summary {
  grid-row: 5 / 6;
  display: flex;
  align-items: baseline;
  padding: 0 0.3rem;
  margin-top: 1rem;
}

.summary__label {
  font-size: 1.2rem;
  font-weight: 500;
  text-transform: uppercase;
  margin-right: 0.8rem;
}

.summary__value {
  font-size: 2.2rem;
  margin-right: 2.5rem;
}

.summary__value–in,
.summary__value–interest {
  color: #66c873;
}

.summary__value–out {
  color: #f5465d;
}

.btn–sort {
  margin-left: auto;
  border: none;
  background: none;
  font-size: 1.3rem;
  font-weight: 500;
  cursor: pointer;
}

/* OPERATIONS */
.operation {
  border-radius: 1rem;
  padding: 3rem 4rem;
  color: #333;
}

.operation–transfer {
  background-image: linear-gradient(to top left, #ffb003, #ffcb03);
}

.operation–loan {
  background-image: linear-gradient(to top left, #39b385, #9be15d);
}

.operation–close {
  background-image: linear-gradient(to top left, #e52a5a, #ff585f);
}

h2 {
  margin-bottom: 1.5rem;
  font-size: 1.7rem;
  font-weight: 600;
  color: #333;
}

.form {
  display: grid;
  grid-template-columns: 2.5fr 2.5fr 1fr;
  grid-template-rows: auto auto;
  gap: 0.4rem 1rem;
}

/* Exceptions for interst */
.form.form–loan {
  grid-template-columns: 2.5fr 1fr 2.5fr;
}
.form__label–loan {
  grid-row: 2;
}
/* End exceptions */

.form__input {
  width: 100%;
  border: none;
  background-color: rgba(255, 255, 255, 0.4);
  font-family: inherit;
  font-size: 1.5rem;
  text-align: center;
  color: #333;
  padding: 0.3rem 1rem;
  border-radius: 0.7rem;
  transition: all 0.3s;
}

.form__input:focus {
  outline: none;
  background-color: rgba(255, 255, 255, 0.6);
}

.form__label {
  font-size: 1.3rem;
  text-align: center;
}

.form__btn {
  border: none;
  border-radius: 0.7rem;
  font-size: 1.8rem;
  background-color: #fff;
  cursor: pointer;
  transition: all 0.3s;
}

.form__btn:focus {
  outline: none;
  background-color: rgba(255, 255, 255, 0.8);
}

.logout-timer {
  padding: 0 0.3rem;
  margin-top: 1.9rem;
  text-align: right;
  font-size: 1.25rem;
}

.timer {
  font-weight: 600;
}