diff --git a/atm.js b/atm.js
new file mode 100644
index 0000000..8b3edfb
--- /dev/null
+++ b/atm.js
@@ -0,0 +1,73 @@
+const person = new Person('John', 'Example', [new Account(1500, 'EUR', 1), new Account(-2500, 'EUR', 2)]);
+
+const atm = (() => {
+ // add person name
+ document.querySelector('.card-title').innerHTML = `${person.firstName} ${person.lastName}`;
+
+ // list person accounts
+ const card = document.querySelector('.card-body');
+
+ for (let account of person.accounts) {
+ const paragraph = document.createElement('p');
+ const paragraphText = document.createTextNode(`Account Number: ${account.number}, Balance: `);
+
+ paragraph.appendChild(paragraphText);
+
+ const span = document.createElement('span');
+ span.id = 'account' + account.number;
+ span.innerText = account.balance;
+
+ paragraph.appendChild(span);
+
+ card.appendChild(paragraph);
+ }
+
+ // progress bar handling
+ const container = document.querySelector('.container');
+ const progress = document.querySelector('.progress');
+ const button = document.querySelector('button');
+ container.addEventListener('myEvent', (e) => {
+ progress.hidden = !e.detail.showProgress;
+ });
+
+ return {
+ withdrawMoney: function () {
+ const number = +document.querySelector('#number').value;
+ const amount = +document.querySelector('#amount').value;
+
+ const event = new CustomEvent('myEvent', {
+ detail: { showProgress: true },
+ bubbles: true
+ });
+
+ button.disabled = true;
+ button.dispatchEvent(event);
+
+ if (number && amount) {
+ event.detail.showProgress = false;
+
+ person.withdraw(number, amount).then(() => {
+ document.querySelector(`span#account${number}`).innerHTML = +document.querySelector(`span#account${number}`).innerHTML - amount;
+
+ button.dispatchEvent(event);
+ button.disabled = false;
+
+ }).catch((reason) => {
+ console.warn(reason);
+ button.dispatchEvent(event);
+ button.disabled = false;
+ });
+ }
+ },
+ onInputChange: function () {
+ const number = +document.querySelector('#number').value;
+ const amount = +document.querySelector('#amount').value;
+
+ if (number > 0 && amount > 0) {
+ button.disabled = false;
+ } else {
+ button.disabled = true;
+ }
+ }
+ }
+})();
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..3044dfc
--- /dev/null
+++ b/index.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+ JS Training code
+
+
+
+
+
+
+
+
+
JS Training
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..b25c83f
--- /dev/null
+++ b/main.js
@@ -0,0 +1,69 @@
+console.log('hello from main js');
+
+class Account {
+ constructor(balance, currency, number) {
+ this.balance = balance;
+ this.currency = currency;
+ this.number = number;
+ };
+};
+
+class Person {
+ constructor(firstName, lastName, accounts) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.accounts = accounts;
+ };
+
+ addAccount(account) {
+ this.accounts.push(account);
+ };
+
+ sayHello() {
+ return `Hi, my name is ${this.firstName} ${this.lastName} and I have ${this.accounts.length} bank account(s) with total balance ${this._calculateBalance()}`;
+ };
+
+ filterPositiveAccounts() {
+ return this.accounts.filter(account => account.balance > 0);
+ };
+
+ findAccount(accountNumber) {
+ return this.accounts.find(account => account.number === accountNumber);
+ };
+
+ withdraw(accountNumber, amount) {
+ const promise = new Promise((resolve, reject) => {
+ const foundAccount = this.findAccount(accountNumber);
+
+ if (foundAccount && foundAccount.balance >= amount) {
+ setTimeout(() => {
+ foundAccount.balance = foundAccount.balance - amount;
+ resolve(`Operation successful, withdrawn ${amount} from account ${accountNumber}, remaining balance ${foundAccount.balance}`);
+ }, 3000);
+ } else if (!foundAccount) {
+ reject('Incorrect account number')
+ } else {
+ reject(`Not enough funds on account number ${accountNumber}`);
+ }
+ });
+
+ return promise;
+ };
+
+ _calculateBalance() {
+ let totalBalance = 0;
+
+ for (let account of this.accounts) {
+ totalBalance = totalBalance + account.balance;
+ }
+
+ return totalBalance;
+ };
+};
+
+if (typeof module !== 'undefined') {
+ module.exports = {
+ Person: Person,
+ Account: Account
+ }
+}
diff --git a/main.spec.js b/main.spec.js
new file mode 100644
index 0000000..31ceaee
--- /dev/null
+++ b/main.spec.js
@@ -0,0 +1,94 @@
+describe('Person class tests', () => {
+
+ const firstName = 'John';
+ const lastName = 'Example';
+ let person;
+
+ beforeEach(() => {
+ person = new Person(firstName, lastName, [new Account(1500, 'EUR', 1234)]);
+ });
+
+ it('should initialize new person object', () => {
+ // given when then
+ expect(person.firstName).toBe(firstName);
+ expect(person.lastName).toBe(lastName);
+ expect(person.accounts.length).toBe(1);
+ expect(person.accounts[0].balance).toBe(1500);
+ expect(person.accounts[0].currency).toBe('EUR');
+ expect(person.accounts[0].number).toBe(1234);
+ });
+
+ it('should add account', () => {
+ // given
+ const account = new Account(200, 'EUR', 9999);
+
+ // when
+ person.addAccount(account);
+
+ // then
+ expect(person.accounts.length).toBe(2);
+ expect(person.accounts[1]).toEqual(account);
+ });
+
+ it('should introduce itself', () => {
+ // given when then
+ expect(person.sayHello()).toBe('Hi, my name is John Example and I have 1 bank account(s) with total balance 1500');
+ });
+
+ it('should filter accounts with positive balance', () => {
+ // given
+ const account = new Account(-100, 'PLN', 1010);
+
+ // when
+ person.addAccount(account);
+ const positiveAccounts = person.filterPositiveAccounts();
+
+ // then
+ expect(positiveAccounts.length = 1);
+ expect(positiveAccounts[0].balance).toBeGreaterThanOrEqual(0);
+ });
+
+ it('should find account by its number', () => {
+ // given
+ const accountNumber = 1234;
+
+ // when
+ const foundAccount = person.findAccount(accountNumber);
+
+ // then
+ expect(foundAccount.number).toBe(accountNumber);
+ });
+
+ it('should withdraw money', (done) => {
+ // given when
+ const promise = person.withdraw(1234, 200);
+
+ // then
+ promise.then(() => {
+ expect(person.accounts[0].balance).toBe(1300);
+ done();
+ });
+ });
+
+ it('should not withdraw money when account not found', (done) => {
+ // given when
+ const promise = person.withdraw(5, 2000);
+
+ // then
+ promise.catch((reason) => {
+ expect(reason).toBe('Incorrect account number');
+ done();
+ });
+ });
+
+ it('should not withdraw money when there is not enough money on the account', (done) => {
+ // given when
+ const promise = person.withdraw(1234, 20000);
+
+ // then
+ promise.catch((reason) => {
+ expect(reason).toBe('Not enough funds on account number 1234');
+ done();
+ });
+ });
+});
\ No newline at end of file
diff --git a/package.json b/package.json
index 505fe25..703a733 100644
--- a/package.json
+++ b/package.json
@@ -35,4 +35,4 @@
"dependencies": {
"bootstrap": "^4.0.0"
}
-}
+}
\ No newline at end of file
diff --git a/tests/main-node.spec.js b/tests/main-node.spec.js
new file mode 100644
index 0000000..9ada06a
--- /dev/null
+++ b/tests/main-node.spec.js
@@ -0,0 +1,28 @@
+const chai = require('chai');
+const expect = chai.expect; // we are using the "expect" style of Chai
+const Person = require('../main.js').Person;
+const Account = require('../main.js').Account;
+
+
+describe('Person class tests', () => {
+
+ let person;
+ const firstName = 'John';
+ const lastName = 'Example';
+ const accounts = [new Account(1500, 'EUR', 1234)];
+
+
+ beforeEach(() => {
+ person = new Person(firstName, lastName, accounts);
+ });
+
+ it('should initialize new person object', () => {
+ // given when then
+ expect(person.firstName).to.equal(firstName);
+ expect(person.lastName).to.equal(lastName);
+ expect(person.accounts.length).to.equal(1);
+ expect(person.accounts[0].balance).to.equal(1500);
+ expect(person.accounts[0].currency).to.equal('EUR');
+ expect(person.accounts[0].number).to.equal(1234);
+ });
+});
\ No newline at end of file