diff --git a/01-Fundamentals-Part-1/starter/index.html b/01-Fundamentals-Part-1/starter/index.html index 59529c7923..37bef55c7f 100755 --- a/01-Fundamentals-Part-1/starter/index.html +++ b/01-Fundamentals-Part-1/starter/index.html @@ -25,5 +25,6 @@

JavaScript Fundamentals – Part 1

+ diff --git a/01-Fundamentals-Part-1/starter/script.js b/01-Fundamentals-Part-1/starter/script.js new file mode 100644 index 0000000000..7574945b61 --- /dev/null +++ b/01-Fundamentals-Part-1/starter/script.js @@ -0,0 +1,67 @@ +// const inputYear = '1991'; +// console.log(Number(inputYear), inputYear); +// console.log(Number(inputYear) + 18 + " Poo"); +// console.log(Number('Jonas')); +// console.log(typeof NaN); +// console.log(String(23),23); +// type coercion +// console.log('I am ' + 23 + ' years old'); +// console.log('i am ' + String(23) + ' years old'); +// console.log('23' - '10' - 3); +// console.log('23' * '2'); + +// let n = '1' + 1; +// n=n-1; +// console.log(n); + +// 5 falsy values: 0, '', undefined, null, NaN + +// console.log(Boolean(0)); +// console.log(Boolean(undefined)); +// console.log(Boolean('Jonas')); +// console.log(Boolean({})); + +// const money = 100; +// if (money) { +// console.log("Don't spend it all ;)"); +// }else{ +// console.log('You should get a job!') +// } + +// let height = 10; +// if(height) { +// console.log("YAY! Height is defined"); +// }else{ +// console.log('Not defined'); +// } + +// const age = '18'; +// if(age === 18) console.log('Yes (strict)'); +// if(age == 18) console.log('Yes (loose)'); + +// const favorite = Number(prompt("??")); +// console.log(favorite); +// console.log(typeof favorite); + +// if (favorite === 23) { +// console.log('👌👌'); +// }else if (favorite === 7){ +// console.log('👍🙌') +// }else{ +// console.log('NO') +// } + + const hasDriversLicense = true; //A + const hasGoodVision = true; //B + + console.log(hasDriversLicense && hasGoodVision); + console.log(!hasDriversLicense || hasGoodVision); + console.log(!hasDriversLicense); + + const shouldDrive = hasDriversLicense && hasGoodVision + + if(shouldDrive){ + console.log('Sarah is able to drive!') + }else{ + console.log('Someone else should drive.') + } \ No newline at end of file diff --git a/10-Functions/final/script.js b/10-Functions/final/script.js index aa2292ad30..c543aae860 100644 --- a/10-Functions/final/script.js +++ b/10-Functions/final/script.js @@ -88,7 +88,7 @@ const transformer = function (str, fn) { transformer('JavaScript is the best!', upperFirstWord); transformer('JavaScript is the best!', oneWord); -// JS uses callbacks all the time +//JS uses callbacks all the time const high5 = function () { console.log('👋'); }; diff --git a/10-Functions/starter/script.js b/10-Functions/starter/script.js index ad9a93a7c1..57345b91a8 100644 --- a/10-Functions/starter/script.js +++ b/10-Functions/starter/script.js @@ -1 +1,319 @@ 'use strict'; + +// // const bookings = [] + +// // const createBooking = function(flightNum, numPassengers = 1, price =199 * numPassengers){ +// // // numPassengers = numPassengers || 1 +// // // price = price || 199 +// // const booking = { +// // flightNum, +// // numPassengers, +// // price +// // } +// // console.log(booking) +// // bookings.push(booking) +// // } + +// // createBooking('LH123') +// // createBooking('LH123', 2, 800) +// // createBooking('LH123', 2) +// // createBooking('LH123', 5) + +// const flight = 'LH234'; +// const jonas = { +// name: 'Jonas Schmedtmann', +// passport: 7597595798435, +// }; + +// const checkin = function (flightNum, passenger) { +// flightNum = 'LH999'; +// passenger.name = 'Mr. ' + passenger.name; +// if (passenger.passport === 7597595798435) { +// alert('Checked in'); +// } else { +// alert('Wrong passport'); +// } +// }; +// // checkin(flight,jonas) +// // console.log(flight) +// // console.log(jonas) + +// // //IS the same as doing +// // const flightNum = flight +// // const passenger = jonas + +// const newPassport = function (person) { +// person.passport = Math.trunc(Math.random() * 1000000000000); +// }; + +// newPassport(jonas); +// checkin(flight, jonas); + +// const oneWord = function (str) { +// return str.replace(/ /g, '').toLowerCase(); +// } + +// const upperFirstWord = function (str) { +// const [first, ...others] = str.split(' ') +// return [first.toUpperCase(), ...others].join(' ') +// } + +// //Higher order function +// const transformer = function (str, fn) { +// console.log(`Original string: ${str}`) +// console.log(`Transformed string: ${fn(str)}`) +// console.log(`Transformed by: ${fn.name}`) +// } + +// transformer('JavaScript is the best!', upperFirstWord) +// transformer('JavaScript is the best!', oneWord) + +// //JS uses callbacks all the time +// const high5 = function () { +// console.log('👋') +// } +// document.body.addEventListener('click', high5); + +// ['Jonas', 'Martha', 'Adam'].forEach(high5); + +// const greet = function (greeting) { +// return function (name) { +// console.log(`${greeting} ${name}`) +// } +// } + +// const greeterHey = greet('Hey') +// greeterHey('Jonas') +// greeterHey('Steven') + +// greet('Hello')('Jonas') + +// //Challenge + +// const greetArr = greeting => name => console.log(`${greeting} ${name}`) +// greetArr('Hi')('Jonas') + +// const lufthansa = { +// airline: 'Lufthansa', +// iataCode: 'LH', +// bookings: [], +// //book: function(){} +// book(flightNum, name) { +// console.log(`${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`) +// this.bookings.push({ flight: `${this.iataCode}${flightNum}`, name }) +// } +// } + +// lufthansa.book(239, 'Jonas Schmedtmann') +// lufthansa.book(635, 'John Smith') +// console.log(lufthansa) + +// const eurowings = { +// airline: 'Eurowings', +// iataCode: 'EW', +// bookings: [] +// } + +// const book = lufthansa.book + +// //Does NOT work +// // book(23, 'Sarah Williams') + +// //Call method +// book.call(eurowings, 23, 'Sarah Williams') +// console.log(eurowings) + +// book.call(lufthansa, 239, 'Mary Cooper') +// console.log(lufthansa) + +// const swiss = { +// airline: 'Swiss Air Lines', +// iataCode: 'LX', +// bookings: [] +// } + +// book.call(swiss, 583, 'Mary Cooper') +// console.log(swiss) + +// //Apply method +// const flightData = [583, 'George Cooper'] +// book.apply(swiss, flightData) +// console.log(swiss) + +// book.call(swiss, ...flightData) + +// //Bind method +// //book.call(eurowings, 23, 'Sarah Williams') +// const bookEW = book.bind(eurowings) +// const bookLH = book.bind(lufthansa) +// const bookLX = book.bind(swiss) +// bookEW(23, 'Steven Williams') + +// const bookEW23 = book.bind(eurowings, 23) +// bookEW23('Jonas Schmedtmann') + +/* +Let's build a simple poll app! + +A poll has a question, an array of options from which people can choose, and an array with the number of replies for each option. This data is stored in the starter object below. + +Here are your tasks: + +1. Create a method called 'registerNewAnswer' on the 'poll' object. The method does 2 things: + 1.1. Display a prompt window for the user to input the number of the selected option. The prompt should look like this: + What is your favourite programming language? + 0: JavaScript + 1: Python + 2: Rust + 3: C++ + (Write option number) + + 1.2. Based on the input number, update the answers array. For example, if the option is 3, increase the value AT POSITION 3 of the array by 1. Make sure to check if the input is a number and if the number makes sense (e.g answer 52 wouldn't make sense, right?) +2. Call this method whenever the user clicks the "Answer poll" button. +3. Create a method 'displayResults' which displays the poll results. The method takes a string as an input (called 'type'), which can be either 'string' or 'array'. If type is 'array', simply display the results array as it is, using console.log(). This should be the default option. If type is 'string', display a string like "Poll results are 13, 2, 4, 1". +4. Run the 'displayResults' method at the end of each 'registerNewAnswer' method call. + +HINT: Use many of the tools you learned about in this and the last section 😉 + +BONUS: Use the 'displayResults' method to display the 2 arrays in the test data. Use both the 'array' and the 'string' option. Do NOT put the arrays in the poll object! So what shoud the this keyword look like in this situation? + +BONUS TEST DATA 1: [5, 2, 3] +BONUS TEST DATA 2: [1, 5, 3, 9, 6, 1] + +GOOD LUCK 😀 +*/ + +// const poll = { +// question: 'What is your favourite programming language?', +// options: ['0: JavaScript', '1: Python', '2: Rust', '3: C++'], +// answers: new Array(4).fill(0), + +// registerNewAnswer() { +// const answer = Number(prompt(`${this.question}\n${this.options.join('\n')}\n(Write option number)`)) +// console.log(answer) + +// //Register answer +// typeof answer === 'number' && answer < this.answers.length && this.answers[answer]++ + +// this.displayResults() +// this.displayResults('string') +// }, + +// displayResults(type = 'array') { +// if (type === 'array') { +// console.log(this.answers) +// } else if (type === 'string') { +// //Poll results are 13, 2, 4, 1 +// console.log(`Poll results are ${this.answers.join(', ')}`) +// } +// } +// } + +// const poll = { +// question: 'What is your favourite programming language?', +// options: ['0: JavaScript', '1: Python', '2: Rust', '3: C++'], +// answers: new Array(4).fill(0), +// registerNewAnswer() { +// const answer = Number( +// prompt( +// `${this.question}\n${this.options.join('\n')}\n(Write option number)` +// ) +// ); +// console.log(answer); +// typeof answer === 'number' && +// answer < this.answers.length && +// this.answers[answer]++; +// console.log(this.answers); +// this.displayResults(); +// this.displayResults('string'); +// }, +// displayResults(type = 'array') { +// if (type === 'array') { +// console.log(this.answers); +// } else if (type === 'string') { +// console.log(`Poll results are ${this.answers.join(', ')}`); +// } +// }, +// }; +// poll.registerNewAnswer(); + +// document.querySelector('.poll').addEventListener('click', poll.registerNewAnswer.bind(poll)); + +// poll.displayResults.call({ answers: [5, 2, 3] }); + +// [5, 2, 3] +// [1, 5, 3, 9, 6, 1 ] + +//Immediately invoked function expressions (IIFE) + +// const runOnce = function () { +// console.log('This will never run again') +// } +// runOnce(); + +// (function () { +// console.log('This will never run again') +// const isPrivate = 23 +// console.log(23) +// })() +// console.log(isPrivate) +// var notPrivate = 46 + + +// (() => console.log('This will ALSO never run again'))() + + +// const secureBooking = function () { +// let passengerCount = 0 +// return function () { +// passengerCount++ +// console.log(`${passengerCount} passengers`) +// } +// } + +// const booker = secureBooking() + +// booker() +// booker() +// booker() +// console.dir(booker) + +// let f; + +// const g = function () { +// const a = 23; +// f = function () { +// console.log(a * 2); +// }; +// }; +// const h = function () { +// const b = 777; +// f = function () { +// console.log(b * 2); +// }; +// } +// g(); +// f(); +// h(); +// f(); +// console.dir(f); + +// //Example 2 +// const boardPassengers = function (n, wait) { +// const perGroup = n / 3; +// setTimeout (function () { +// console.log(`We are now boarding all ${n} passengers`) +// console.log(`There are 3 groups, each with ${perGroup} passengers`) +// }, wait * 1000) +// console.log(`Will start boarding in ${wait} seconds`); +// } + +// boardPassengers(180, 3); + +(function () { + const header = document.querySelector('h1') + header.style.color = 'red' + document.querySelector('body').addEventListener('click', function () { + header.style.color = 'blue' + }) +})() \ No newline at end of file diff --git a/11-Arrays-Bankist/starter/script.js b/11-Arrays-Bankist/starter/script.js index 05b54ddf31..bf19918d65 100644 --- a/11-Arrays-Bankist/starter/script.js +++ b/11-Arrays-Bankist/starter/script.js @@ -5,6 +5,7 @@ // BANKIST APP // Data + const account1 = { owner: 'Jonas Schmedtmann', movements: [200, 450, -400, 3000, -650, -130, 70, 1300], @@ -61,16 +62,639 @@ const inputLoanAmount = document.querySelector('.form__input--loan-amount'); const inputCloseUsername = document.querySelector('.form__input--user'); const inputClosePin = document.querySelector('.form__input--pin'); +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 = ` +
+
${ + i + 1 + } ${type}
+
${mov}€
+
+ `; + + containerMovements.insertAdjacentHTML('afterbegin', html); + }); +}; + +const calcDisplayBalance = function (acc) { + acc.balance = acc.movements.reduce((acc, mov) => acc + mov, 0); + labelBalance.textContent = `${acc.balance}€`; +}; + +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 = `${Math.abs(out)}€`; + const interest = acc.movements + .filter(mov => mov > 0) + .map(deposit => (deposit * acc.interestRate) / 100) + .filter(int => int >= 1) + .reduce((acc, int) => acc + int, 0); + labelSumInterest.textContent = `${interest}€`; +}; + +// console.log(containerMovements.innerHTML); +const createUserNames = function (accs) { + accs.forEach(function (acc) { + acc.username = acc.owner + .toLowerCase() + .split(' ') + .map(name => name[0]) + .join(''); + }); +}; + +createUserNames(accounts); + +const updateUI = function (acc) { + // Display movements + displayMovements(acc.movements); + // Display balance + calcDisplayBalance(acc); + // Display summary + calcDisplaySummary(acc); +}; + +// Event handlers +let currentAccount; + +btnLogin.addEventListener('click', function (e) { + // Prevent form from submitting + e.preventDefault(); + + currentAccount = accounts.find( + acc => acc.username === inputLoginUsername.value + ); + console.log(currentAccount); + + if (currentAccount?.pin === Number(inputLoginPin.value)) { + // Display UI and 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); + //console.log(amount); + if (amount > 0 && currentAccount.movements.some(mov => mov >= amount * 0.1)) { + // Add movement + currentAccount.movements.push(amount); + + // Update UI + updateUI(currentAccount); + } +}); + +btnClose.addEventListener('click', function (e) { + e.preventDefault(); + + if ( + inputCloseUsername.value === currentAccount.username && + Number(inputClosePin.value) === currentAccount.pin + ) { + const index = accounts.findIndex( + acc => acc.username === currentAccount.username + ); + console.log(index); + // .indexOf(23) + + // Delete account + accounts.splice(index, 1); + + // Hide UI + containerApp.style.opacity = 0; + } + + inputCloseUsername.value = inputClosePin.value = ''; +}); + +let sorted = false; +btnSort.addEventListener('click', function (e) { + e.preventDefault(); + displayMovements(currentAccount.movements, !sorted); + sorted = !sorted; +}); ///////////////////////////////////////////////// ///////////////////////////////////////////////// // LECTURES -const currencies = new Map([ - ['USD', 'United States dollar'], - ['EUR', 'Euro'], - ['GBP', 'Pound sterling'], -]); +// const currencies = new Map([ +// ['USD', 'United States dollar'], +// ['EUR', 'Euro'], +// ['GBP', 'Pound sterling'], +// ]); const movements = [200, 450, -400, 3000, -650, -130, 70, 1300]; ///////////////////////////////////////////////// + +// let arr = ['a', 'b', 'c', 'd', 'e']; + +// // SLICE +// console.log(arr.slice(2)); // ['c', 'd', 'e'] +// console.log(arr.slice(2, 4)); // ['c', 'd'] +// console.log(arr.slice(-2)); // ['d', 'e'] +// console.log(arr.slice(1, -2)); +// console.log(arr.slice()); // ['a', 'b', 'c', 'd', 'e'] +// console.log([...arr]); // ['a', 'b', 'c', 'd', 'e'] + +// // SPLICE +// //console.log(arr.splice(2)); // ['c', 'd', 'e'] +// arr.splice(-1); // ['a', 'b', 'c', 'd'] +// console.log(arr); // ['a', 'b', 'c', 'd'] +// arr.splice(1, 2); // ['a', 'd'] +// console.log(arr); // ['a', 'b'] + +// // REVERSE +// arr = ['a', 'b', 'c', 'd', 'e']; +// const arr2 = ['j', 'i', 'h', 'g', 'f']; +// console.log(arr2.reverse()); // ['f', 'g', 'h', 'i', 'j'] +// console.log(arr2); // ['f', 'g', 'h', 'i', 'j'] + +// // CONCAT +// const letters = arr.concat(arr2); +// console.log(letters); +// console.log([...arr, ...arr2]); + +// // JOIN +// console.log(letters.join(' - ')); + +// const arr = [23, 11, 64]; +// console.log(arr[0]); +// console.log(arr.at(0)); + +// // getting last array element +// console.log(arr[arr.length - 1]) +// console.log(arr.slice(-1)[0]); +// console.log(arr.at(-1)); + +// const movements = [200, 450, -400, 3000, -650, -130, 70, 1300]; + +// //for (const movement of movements) { +// for (const [i, movement] of movements.entries()) { +// if (movement > 0) { +// console.log(`Movement ${i + 1}: You deposited ${movement}`); +// } else { +// console.log(`Movement ${i + 1}: You withdrew ${Math.abs(movement)}`); +// } +// } + +// console.log('---- FOREACH ----'); +// movements.forEach(function (mov, i, arr) { +// if (mov > 0) { +// console.log(`Movement ${i + 1}: You deposited ${mov}`); +// } else { +// console.log(`Movement ${i + 1}: You withdrew ${Math.abs(mov)}`); +// } +// } +// ) + +// const currencies = new Map([ +// ['USD', 'United States dollar'], +// ['EUR', 'Euro'], +// ['GBP', 'Pound sterling'], +// ]); + +// //MAP +// currencies.forEach(function (value, key, map) { +// console.log(`${key}: ${value}`); +// }); + +// //SET +// const currenciesUnique = new Set(['USD', 'GBP', 'USD', 'EUR', 'EUR']); +// console.log(currenciesUnique); +// currenciesUnique.forEach(function (value, _, map) { +// console.log(`${value}: ${value}`); +// }); + +/////////////////////////////////////// +// Coding Challenge #1 + +/* +Julia and Kate are doing a study on dogs. So each of them asked 5 dog owners about their dog's age, and stored the data into an array (one array for each). For now, they are just interested in knowing whether a dog is an adult or a puppy. A dog is an adult if it is at least 3 years old, and it's a puppy if it's less than 3 years old. + +Create a function 'checkDogs', which accepts 2 arrays of dog's ages ('dogsJulia' and 'dogsKate'), and does the following things: + +1. Julia found out that the owners of the FIRST and the LAST TWO dogs actually have cats, not dogs! So create a shallow copy of Julia's array, and remove the cat ages from that copied array (because it's a bad practice to mutate function parameters) +2. Create an array with both Julia's (corrected) and Kate's data +3. For each remaining dog, log to the console whether it's an adult ("Dog number 1 is an adult, and is 5 years old") or a puppy ("Dog number 2 is still a puppy 🐶") +4. Run the function for both test datasets + +HINT: Use tools from all lectures in this section so far 😉 + +TEST DATA 1: Julia's data [3, 5, 2, 12, 7], Kate's data [4, 1, 15, 8, 3] +TEST DATA 2: Julia's data [9, 16, 6, 8, 3], Kate's data [10, 5, 6, 1, 4] + +GOOD LUCK 😀 +*/ + +// const dogsJulia = [3, 5, 2, 12, 7]; +// const dogsKate = [4, 1, 15, 8, 3]; + +// const checkDogs = function (dogsJulia, dogsKate) { +// const dogsJuliaCorrected = dogsJulia.slice(1, -2); +// const dogs = dogsJuliaCorrected.concat(dogsKate); +// dogs.forEach(function (dog, i) { +// if (dog >= 3) { +// console.log(`Dog number ${i + 1} is an adult, and is ${dog} years old`); +// } else { +// console.log(`Dog number ${i + 1} is still a puppy 🐶`); +// } +// }); +// }; +// checkDogs(dogsJulia, dogsKate); + +// const justinsArray = [1, 2, 3]; +// const addsOne = function (justinsArray) { +// justinsArray.forEach(function (i) { +// console.log(i + 1); +// }); +// }; +// addsOne(justinsArray); + +// //calculates 1/3 to 4th digit +// console.log((1 / 3).toFixed(8)); + +// const eurToUsd = 1.1; +// // const movementsUSD = movements.map(function (mov) { +// // return mov * eurToUsd; +// // }); + +// const movementsUSD = movements.map(mov => mov * eurToUsd); + +// console.log(movements); +// console.log(movementsUSD); + +// const movementsUSDfor = []; +// for (const mov of movements) movementsUSDfor.push(mov * eurToUsd); +// console.log(movementsUSDfor); + +// // movements.map(function (mov, i, arr) { +// // if (mov > 0) { +// // return `Movement ${i + 1}: You deposited ${mov}`; +// // } else { +// // return `Movement ${i + 1}: You withdrew ${Math.abs(mov)}`; +// // } +// // }); + +// const moventsDescriptions = movements.map( +// (mov, i) => +// `Movement ${i + 1}: You ${mov > 0 ? 'deposited' : 'withdrew'} ${Math.abs( +// mov +// )}` +// ); + +// console.log(moventsDescriptions); +/* +const deposits = movements.filter(function (mov) { + return mov > 0; +}); +console.log(movements); +console.log(deposits); + +const depositsFor = []; +for (const mov of movements) if (mov > 0) depositsFor.push(mov); +console.log(depositsFor); + +const withdrawals = movements.filter(mov => mov < 0); +console.log(withdrawals); + + +console.log(movements); +const balance = movements.reduce(function (acc, cur, i, arr) { + console.log(`Iteration ${i}: ${acc}`); + return acc + cur; +}, 0); + +const balances = movements.reduce((acc, cur) => acc + cur, 0); +console.log(balance); + +let balance2 = 0; +for (const mov of movements) balance2 += mov; +console.log(balance2); + +// Maximum value +const max = movements.reduce((acc, mov) => { + if (acc > mov) return acc; + else return mov; +}, movements[0]); +console.log(max); +console.log(movements); +console.log(movements.length); +console.log(movements.length - 1); +console.log(movements[movements.length - 1]); +console.log(movements[movements.length - 1] - movements[0]); +console.log(movements.slice(movements.length - 1)); +console.log(movements.slice(movements.length - 1)[0]); +console.log(movements.slice(movements.length - 1)[0] - movements[0]); +console.log(movements.slice(movements.length - 1)[0] - movements[0]); +console.log(movements.slice(movements.length - 1)[0] - movements[0]); +console.log(movements.slice(movements.length - 1)[0] - movements[0]); +console.log(movements.slice(movements.length - 1)[0] - movements[0]); +*/ +/////////////////////////////////////// +// Coding Challenge #2 + +/* +Let's go back to Julia and Kate's study about dogs. This time, they want to convert dog ages to human ages and calculate the average age of the dogs in their study. + +Create a function 'calcAverageHumanAge', which accepts an arrays of dog's ages ('ages'), and does the following things in order: + +1. Calculate the dog age in human years using the following formula: if the dog is <= 2 years old, humanAge = 2 * dogAge. If the dog is > 2 years old, humanAge = 16 + dogAge * 4. +2. Exclude all dogs that are less than 18 human years old (which is the same as keeping dogs that are at least 18 years old) +3. Calculate the average human age of all adult dogs (you should already know from other challenges how we calculate averages 😉) +4. Run the function for both test datasets + +TEST DATA 1: [5, 2, 4, 1, 15, 8, 3] +TEST DATA 2: [16, 6, 10, 5, 6, 1, 4] + +GOOD LUCK 😀 +*/ +/* +const calcAverageHumanAge = function (ages) { + const humanAges = ages.map(age => (age <= 2 ? 2 * age : 16 + age * 4)); + console.log(humanAges); + const adults = humanAges.filter(age => age >= 18); + console.log(adults); + const average = adults.reduce((acc, age) => acc + age, 0) / adults.length; + return average; +}; +const avg1 = calcAverageHumanAge([5, 2, 4, 1, 15, 8, 3]); +const avg2 = calcAverageHumanAge([16, 6, 10, 5, 6, 1, 4]); +console.log(avg1, avg2); +*/ +/* +const eurToUsd = 1.1; +console.log(movements); +const totalDepositsUSD = movements + .filter(mov => mov > 0) + .map((mov, i, arr) => { + //console.log(arr); + return mov * eurToUsd; + }) + //.map(mov => mov * eurToUsd) + .reduce((acc, mov) => acc + mov, 0); +console.log(totalDepositsUSD); +*/ +/////////////////////////////////////// +// Coding Challenge #3 + +/* +Rewrite the 'calcAverageHumanAge' function from the previous challenge, but this time as an arrow function, and using chaining! + +TEST DATA 1: [5, 2, 4, 1, 15, 8, 3] +TEST DATA 2: [16, 6, 10, 5, 6, 1, 4] + +GOOD LUCK 😀 +*/ +/* +const calcAverageHumanAge = ages => + ages + .map(age => (age <= 2 ? 2 * age : 16 + age * 4)) + .filter(age => age >= 18) + .reduce((acc, age, i, arr) => acc + age / arr.length, 0); +// adults.length + +const avg1 = calcAverageHumanAge([5, 2, 4, 1, 15, 8, 3]); +const avg2 = calcAverageHumanAge([16, 6, 10, 5, 6, 1, 4]); +console.log(avg1, avg2); + +const firstWithdrawal = movements.find(mov => mov > 0); +console.log(movements); +console.log(firstWithdrawal); + +console.log(accounts); + +const account = accounts.find(acc => acc.owner === 'Jessica Davis'); +console.log(account); + + +// console.log(movements); +// console.log(movements.includes(-130)); + +// const anyDeposits = movements.some(mov => mov > 0); +// console.log(anyDeposits); + +// const arr = [[1, 2, 3], [4, 5, 6], 7, 8]; +// console.log(arr.flat()); + +// const accountMovements = accounts.map(acc => acc.movements); +// console.log(accountMovements); +// const allMovements = accountMovements.flat(); +// console.log(allMovements); +// const overallBalances = allMovements.reduce((acc, mov) => acc + mov, 0); +// console.log(overallBalances); + +// const overallBallance = accounts +// .map(acc => acc.movements) +// .flat() +// .reduce((acc, mov) => acc + mov, 0); +// console.log(overallBallance); + +// const overallBallance2 = accounts +// .flatMap(acc => acc.movements) +// .reduce((acc, mov) => acc + mov, 0); +// console.log(overallBallance2); + +// const owners = ['Jonas', 'Zach', 'Adam', 'Martha']; +// console.log(owners.sort()); +// console.log(owners); + +// console.log(movements); + +// movements.sort((a, b) => { +// if (a > b) return 1; +// if (b > a) return -1; +// }); +// console.log(movements); + +// movements.sort((a, b) => a - b); +// console.log(movements); +// movements.sort((a, b) => b - a); +// console.log(movements); + +// const j = Array.from({ length: 100 }, (_, i) => Math.round(Math.random() * 6)); +// console.log(j); + +const k = Math.round(Math.random() * 6); +console.log(k); + +// labelBalance.addEventListener('click', function () { +// const movementsUI = Array.from( +// document.querySelectorAll('.movements__value'), +// el => Number(el.textContent.replace('€', '')) +// ); +// console.log(movementsUI); +// }); + +labelBalance.addEventListener('click', function () { + const k = Math.round(Math.random() * 6); + console.log(k); +}); + +const bankDepositSum = accounts + .map(acc => acc.movements) + .flat() + .filter(mov => mov > 0) + .reduce((acc, mov) => acc + mov, 0); +console.log(bankDepositSum); + +// const bankDeposit1000 = accounts +// .flatMap(acc => acc.movements) +// .filter(mov => mov > 1000).length; +// console.log(bankDeposit1000); + +const bankDeposit1000 = accounts + .flatMap(acc => acc.movements) + .reduce((count, curr) => (curr >= 1000 ? count + 1 : count), 0); +console.log( + accounts.flatMap(acc => acc.movements).filter(mov => mov >= 1000).length +); +console.log(bankDeposit1000); + +const sums = accounts + .flatMap(acc => acc.movements) + .reduce( + (sum, curr) => { + sum[curr >= 1000 ? 'deposits' : 'withdrawals'] += curr; + return sum; + }, + { deposits: 0, withdrawals: 0 } + ); +console.log(sums); + +//4. +//this is a nice title -> This Is a Nice Title +const convertTitleCase = function (title) { + const capitalize = str => str[0].toUpperCase() + str.slice(1); + const exceptions = ['a', 'an', 'and', 'the', 'but', 'or', 'on', 'in', 'with']; + const titleCase = title + .toLowerCase() + .split(' ') + .map(word => (exceptions.includes(word) ? word : capitalize(word))) + .join(' '); + return capitalize(titleCase); +}; +console.log(convertTitleCase('this is a nice title')); +console.log(convertTitleCase('this is a LONG title but not too long')); +console.log(convertTitleCase('and here is another title with an EXAMPLE')); +*/ +/////////////////////////////////////// +// Coding Challenge #4 + +/* +Julia and Kate are still studying dogs, and this time they are studying if dogs are eating too much or too little. +Eating too much means the dog's current food portion is larger than the recommended portion, and eating too little is the opposite. +Eating an okay amount means the dog's current food portion is within a range 10% above and 10% below the recommended portion (see hint). + +1. Loop over the array containing dog objects, and for each dog, calculate the recommended food portion and add it to the object as a new property. Do NOT create a new array, simply loop over the array. Forumla: recommendedFood = weight ** 0.75 * 28. (The result is in grams of food, and the weight needs to be in kg) +2. Find Sarah's dog and log to the console whether it's eating too much or too little. HINT: Some dogs have multiple owners, so you first need to find Sarah in the owners array, and so this one is a bit tricky (on purpose) 🤓 +3. Create an array containing all owners of dogs who eat too much ('ownersEatTooMuch') and an array with all owners of dogs who eat too little ('ownersEatTooLittle'). +4. Log a string to the console for each array created in 3., like this: "Matilda and Alice and Bob's dogs eat too much!" and "Sarah and John and Michael's dogs eat too little!" +5. Log to the console whether there is any dog eating EXACTLY the amount of food that is recommended (just true or false) +6. Log to the console whether there is any dog eating an OKAY amount of food (just true or false) +7. Create an array containing the dogs that are eating an OKAY amount of food (try to reuse the condition used in 6.) +8. Create a shallow copy of the dogs array and sort it by recommended food portion in an ascending order (keep in mind that the portions are inside the array's objects) + +HINT 1: Use many different tools to solve these challenges, you can use the summary lecture to choose between them 😉 +HINT 2: Being within a range 10% above and below the recommended portion means: current > (recommended * 0.90) && current < (recommended * 1.10). Basically, the current portion should be between 90% and 110% of the recommended portion. + +TEST DATA: +const dogs = [ + { weight: 22, curFood: 250, owners: ['Alice', 'Bob'] }, + { weight: 8, curFood: 200, owners: ['Matilda'] }, + { weight: 13, curFood: 275, owners: ['Sarah', 'John'] }, + { weight: 32, curFood: 340, owners: ['Michael'] } +]; + +GOOD LUCK 😀 +*/ +const dogs = [ + { weight: 22, curFood: 250, owners: ['Alice', 'Bob'] }, + { weight: 8, curFood: 200, owners: ['Matilda'] }, + { weight: 13, curFood: 275, owners: ['Sarah', 'John'] }, + { weight: 32, curFood: 340, owners: ['Michael'] }, +]; +dogs.forEach(dog => (dog.recFood = Math.trunc(dog.weight ** 0.75 * 28))); +console.log(dogs); + +const dogSarah = dogs.find(dog => dog.owners.includes('Sarah')); +console.log(dogSarah); +console.log( + `Sarah's dog is eating too ${ + dogSarah.curFood > dogSarah.recFood ? 'much' : 'little' + }` +); + +const ownersEatTooMuch = dogs + .filter(dog => dog.curFood > dog.recFood) + .flatMap(dog => dog.owners); +console.log(ownersEatTooMuch); + +const ownersEatTooLittle = dogs + .filter(dog => dog.curFood < dog.recFood) + .flatMap(dog => dog.owners); +console.log(ownersEatTooLittle); + +console.log(`${ownersEatTooMuch.join(' and ')}'s dogs eat too much!`); +console.log(`${ownersEatTooLittle.join(' and ')}'s dogs eat too little!`); +console.log(dogs.some(dog => dog.curFood === dog.recFood)); +console.log( + dogs.some( + dog => dog.curFood > dog.recFood * 0.9 && dog.curFood < dog.recFood * 1.1 + ) +); + +const dogsOkay = dogs.filter( + dog => dog.curFood > dog.recFood * 0.9 && dog.curFood < dog.recFood * 1.1 +); +console.log(dogsOkay); + +const dogsSorted = dogs.slice().sort((a, b) => a.recFood - b.recFood); +console.log(dogsSorted); diff --git a/11-Arrays-Bankist/starter/style.css b/11-Arrays-Bankist/starter/style.css index 05dcf39618..b047de3f76 100644 --- a/11-Arrays-Bankist/starter/style.css +++ b/11-Arrays-Bankist/starter/style.css @@ -16,7 +16,7 @@ html { } body { - font-family: "Poppins", sans-serif; + font-family: 'Poppins', sans-serif; color: #444; background-color: #f3f3f3; height: 100vh; diff --git a/12-Numbers-Dates-Timers-Bankist/final/script.js b/12-Numbers-Dates-Timers-Bankist/final/script.js index 63f7cc0810..d41bb335fa 100644 --- a/12-Numbers-Dates-Timers-Bankist/final/script.js +++ b/12-Numbers-Dates-Timers-Bankist/final/script.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict'; ///////////////////////////////////////////////// ///////////////////////////////////////////////// @@ -10,73 +10,73 @@ // DIFFERENT DATA! Contains movement dates, currency and locale const account1 = { - owner: "Jonas Schmedtmann", + owner: 'Jonas Schmedtmann', movements: [200, 455.23, -306.5, 25000, -642.21, -133.9, 79.97, 1300], interestRate: 1.2, // % pin: 1111, movementsDates: [ - "2019-11-18T21:31:17.178Z", - "2019-12-23T07:42:02.383Z", - "2020-01-28T09:15:04.904Z", - "2020-04-01T10:17:24.185Z", - "2020-05-08T14:11:59.604Z", - "2020-07-26T17:01:17.194Z", - "2020-07-28T23:36:17.929Z", - "2020-08-01T10:51:36.790Z", + '2019-11-18T21:31:17.178Z', + '2019-12-23T07:42:02.383Z', + '2020-01-28T09:15:04.904Z', + '2020-04-01T10:17:24.185Z', + '2020-05-08T14:11:59.604Z', + '2020-07-26T17:01:17.194Z', + '2020-07-28T23:36:17.929Z', + '2020-08-01T10:51:36.790Z', ], - currency: "EUR", - locale: "pt-PT", // de-DE + currency: 'EUR', + locale: 'pt-PT', // de-DE }; const account2 = { - owner: "Jessica Davis", + owner: 'Jessica Davis', movements: [5000, 3400, -150, -790, -3210, -1000, 8500, -30], interestRate: 1.5, pin: 2222, movementsDates: [ - "2019-11-01T13:15:33.035Z", - "2019-11-30T09:48:16.867Z", - "2019-12-25T06:04:23.907Z", - "2020-01-25T14:18:46.235Z", - "2020-02-05T16:33:06.386Z", - "2020-04-10T14:43:26.374Z", - "2020-06-25T18:49:59.371Z", - "2020-07-26T12:01:20.894Z", + '2019-11-01T13:15:33.035Z', + '2019-11-30T09:48:16.867Z', + '2019-12-25T06:04:23.907Z', + '2020-01-25T14:18:46.235Z', + '2020-02-05T16:33:06.386Z', + '2020-04-10T14:43:26.374Z', + '2020-06-25T18:49:59.371Z', + '2020-07-26T12:01:20.894Z', ], - currency: "USD", - locale: "en-US", + currency: 'USD', + locale: 'en-US', }; const accounts = [account1, account2]; ///////////////////////////////////////////////// // 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 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 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 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'); ///////////////////////////////////////////////// // Functions @@ -84,38 +84,33 @@ const inputClosePin = document.querySelector(".form__input--pin"); const formatMovementDate = function (date, locale) { const calcDaysPassed = (date1, date2) => Math.round(Math.abs(date2 - date1) / (1000 * 60 * 60 * 24)); - const daysPassed = calcDaysPassed(new Date(), date); console.log(daysPassed); - - if (daysPassed === 0) return "Today"; - if (daysPassed === 1) return "Yesterday"; + if (daysPassed === 0) return 'Today'; + if (daysPassed === 1) return 'Yesterday'; if (daysPassed <= 7) return `${daysPassed} days ago`; - // const day = `${date.getDate()}`.padStart(2, 0); // const month = `${date.getMonth() + 1}`.padStart(2, 0); // const year = date.getFullYear(); - // return `${day}/${month}/${year}`; return new Intl.DateTimeFormat(locale).format(date); }; const formatCur = function (value, locale, currency) { return new Intl.NumberFormat(locale, { - style: "currency", + style: 'currency', currency: currency, }).format(value); }; const displayMovements = function (acc, sort = false) { - containerMovements.innerHTML = ""; + containerMovements.innerHTML = ''; const movs = sort ? acc.movements.slice().sort((a, b) => a - b) : acc.movements; movs.forEach(function (mov, i) { - const type = mov > 0 ? "deposit" : "withdrawal"; - + const type = mov > 0 ? 'deposit' : 'withdrawal'; const date = new Date(acc.movementsDates[i]); const displayDate = formatMovementDate(date, acc.locale); @@ -131,7 +126,7 @@ const displayMovements = function (acc, sort = false) { `; - containerMovements.insertAdjacentHTML("afterbegin", html); + containerMovements.insertAdjacentHTML('afterbegin', html); }); }; @@ -142,18 +137,18 @@ const calcDisplayBalance = function (acc) { const calcDisplaySummary = function (acc) { const incomes = acc.movements - .filter((mov) => mov > 0) + .filter(mov => mov > 0) .reduce((acc, mov) => acc + mov, 0); labelSumIn.textContent = formatCur(incomes, acc.locale, acc.currency); const out = acc.movements - .filter((mov) => mov < 0) + .filter(mov => mov < 0) .reduce((acc, mov) => acc + mov, 0); labelSumOut.textContent = formatCur(Math.abs(out), acc.locale, acc.currency); const interest = acc.movements - .filter((mov) => mov > 0) - .map((deposit) => (deposit * acc.interestRate) / 100) + .filter(mov => mov > 0) + .map(deposit => (deposit * acc.interestRate) / 100) .filter((int, i, arr) => { // console.log(arr); return int >= 1; @@ -166,9 +161,9 @@ const createUsernames = function (accs) { accs.forEach(function (acc) { acc.username = acc.owner .toLowerCase() - .split(" ") - .map((name) => name[0]) - .join(""); + .split(' ') + .map(name => name[0]) + .join(''); }); }; createUsernames(accounts); @@ -195,7 +190,7 @@ const startLogOutTimer = function () { // When 0 seconds, stop timer and log out user if (time === 0) { clearInterval(timer); - labelWelcome.textContent = "Log in to get started"; + labelWelcome.textContent = 'Log in to get started'; containerApp.style.opacity = 0; } @@ -222,30 +217,30 @@ let currentAccount, timer; // updateUI(currentAccount); // containerApp.style.opacity = 100; -btnLogin.addEventListener("click", function (e) { +btnLogin.addEventListener('click', function (e) { // Prevent form from submitting e.preventDefault(); currentAccount = accounts.find( - (acc) => acc.username === inputLoginUsername.value + acc => acc.username === inputLoginUsername.value ); console.log(currentAccount); if (currentAccount?.pin === +inputLoginPin.value) { // Display UI and message labelWelcome.textContent = `Welcome back, ${ - currentAccount.owner.split(" ")[0] + currentAccount.owner.split(' ')[0] }`; containerApp.style.opacity = 100; // Create current date and time const now = new Date(); const options = { - hour: "numeric", - minute: "numeric", - day: "numeric", - month: "numeric", - year: "numeric", + hour: 'numeric', + minute: 'numeric', + day: 'numeric', + month: 'numeric', + year: 'numeric', // weekday: 'long', }; // const locale = navigator.language; @@ -264,7 +259,7 @@ btnLogin.addEventListener("click", function (e) { // labelDate.textContent = `${day}/${month}/${year}, ${hour}:${min}`; // Clear input fields - inputLoginUsername.value = inputLoginPin.value = ""; + inputLoginUsername.value = inputLoginPin.value = ''; inputLoginPin.blur(); // Timer @@ -276,13 +271,13 @@ btnLogin.addEventListener("click", function (e) { } }); -btnTransfer.addEventListener("click", function (e) { +btnTransfer.addEventListener('click', function (e) { e.preventDefault(); const amount = +inputTransferAmount.value; const receiverAcc = accounts.find( - (acc) => acc.username === inputTransferTo.value + acc => acc.username === inputTransferTo.value ); - inputTransferAmount.value = inputTransferTo.value = ""; + inputTransferAmount.value = inputTransferTo.value = ''; if ( amount > 0 && @@ -307,15 +302,12 @@ btnTransfer.addEventListener("click", function (e) { } }); -btnLoan.addEventListener("click", function (e) { +btnLoan.addEventListener('click', function (e) { e.preventDefault(); const amount = Math.floor(inputLoanAmount.value); - if ( - amount > 0 && - currentAccount.movements.some((mov) => mov >= amount * 0.1) - ) { + if (amount > 0 && currentAccount.movements.some(mov => mov >= amount * 0.1)) { setTimeout(function () { // Add movement currentAccount.movements.push(amount); @@ -331,10 +323,10 @@ btnLoan.addEventListener("click", function (e) { timer = startLogOutTimer(); }, 2500); } - inputLoanAmount.value = ""; + inputLoanAmount.value = ''; }); -btnClose.addEventListener("click", function (e) { +btnClose.addEventListener('click', function (e) { e.preventDefault(); if ( @@ -342,7 +334,7 @@ btnClose.addEventListener("click", function (e) { +inputClosePin.value === currentAccount.pin ) { const index = accounts.findIndex( - (acc) => acc.username === currentAccount.username + acc => acc.username === currentAccount.username ); console.log(index); // .indexOf(23) @@ -354,11 +346,11 @@ btnClose.addEventListener("click", function (e) { containerApp.style.opacity = 0; } - inputCloseUsername.value = inputClosePin.value = ""; + inputCloseUsername.value = inputClosePin.value = ''; }); let sorted = false; -btnSort.addEventListener("click", function (e) { +btnSort.addEventListener('click', function (e) { e.preventDefault(); displayMovements(currentAccount.movements, !sorted); sorted = !sorted; diff --git a/12-Numbers-Dates-Timers-Bankist/starter/script.js b/12-Numbers-Dates-Timers-Bankist/starter/script.js index 7fd35920a2..735e54a138 100644 --- a/12-Numbers-Dates-Timers-Bankist/starter/script.js +++ b/12-Numbers-Dates-Timers-Bankist/starter/script.js @@ -21,9 +21,9 @@ const account1 = { '2020-01-28T09:15:04.904Z', '2020-04-01T10:17:24.185Z', '2020-05-08T14:11:59.604Z', - '2020-05-27T17:01:17.194Z', - '2020-07-11T23:36:17.929Z', - '2020-07-12T10:51:36.790Z', + '2023-11-01T17:01:17.194Z', + '2023-10-27T23:36:17.929Z', + '2023-10-31T10:51:36.790Z', ], currency: 'EUR', locale: 'pt-PT', // de-DE @@ -81,20 +81,48 @@ const inputClosePin = document.querySelector('.form__input--pin'); ///////////////////////////////////////////////// // Functions -const displayMovements = function (movements, sort = false) { +const formatMovementDate = function (date, locale) { + const calcDaysPassed = (date1, date2) => + Math.abs(date2 - date1) / (1000 * 60 * 60 * 24); + const daysPassed = Math.round(calcDaysPassed(new Date(), date)); + console.log(daysPassed); + if (daysPassed === 0) return 'Today'; + if (daysPassed === 1) return 'Yesterday'; + if (daysPassed <= 7) return `${daysPassed} days ago`; + // const day = `${date.getDate()}`.padStart(2, 0); // 2 digits + // const month = `${date.getMonth() + 1}`.padStart(2, 0); // 2 digits + // const year = date.getFullYear(); + return new Intl.DateTimeFormat(currentAccount.locale).format(date); +}; + +const formatCur = function (value, locale, currency) { + return new Intl.NumberFormat(locale, { + style: 'currency', + currency: currency, + }).format(value); +}; // return value.toFixed(2) + '€'; + +const displayMovements = function (acc, sort = false) { containerMovements.innerHTML = ''; - const movs = sort ? movements.slice().sort((a, b) => a - b) : movements; + const movs = sort + ? acc.movements.slice().sort((a, b) => a - b) + : acc.movements; movs.forEach(function (mov, i) { const type = mov > 0 ? 'deposit' : 'withdrawal'; + const date = new Date(acc.movementsDates[i]); + const displayDate = formatMovementDate(date, acc.locale); + + const formattedMov = formatCur(mov, acc.locale, acc.currency); const html = `
${ i + 1 } ${type}
-
${mov}€
+
${displayDate}
+
${formattedMov}
`; @@ -104,19 +132,19 @@ const displayMovements = function (movements, sort = false) { const calcDisplayBalance = function (acc) { acc.balance = acc.movements.reduce((acc, mov) => acc + mov, 0); - labelBalance.textContent = `${acc.balance}€`; + labelBalance.textContent = formatCur(acc.balance, acc.locale, acc.currency); }; const calcDisplaySummary = function (acc) { const incomes = acc.movements .filter(mov => mov > 0) .reduce((acc, mov) => acc + mov, 0); - labelSumIn.textContent = `${incomes}€`; + labelSumIn.textContent = formatCur(incomes, acc.locale, acc.currency); const out = acc.movements .filter(mov => mov < 0) .reduce((acc, mov) => acc + mov, 0); - labelSumOut.textContent = `${Math.abs(out)}€`; + labelSumOut.textContent = formatCur(Math.abs(out), acc.locale, acc.currency); const interest = acc.movements .filter(mov => mov > 0) @@ -126,7 +154,7 @@ const calcDisplaySummary = function (acc) { return int >= 1; }) .reduce((acc, int) => acc + int, 0); - labelSumInterest.textContent = `${interest}€`; + labelSumInterest.textContent = formatCur(interest, acc.locale, acc.currency); }; const createUsernames = function (accs) { @@ -142,7 +170,7 @@ createUsernames(accounts); const updateUI = function (acc) { // Display movements - displayMovements(acc.movements); + displayMovements(acc); // Display balance calcDisplayBalance(acc); @@ -151,9 +179,55 @@ const updateUI = function (acc) { calcDisplaySummary(acc); }; +const startLogOutTimer = function () { + const tick = function () { + const min = String(Math.trunc(time / 60)).padStart(2, 0); + const sec = String(time % 60).padStart(2, 0); + + // In each call, print the remaining time to UI + labelTimer.textContent = `${min}:${sec}`; + + // When 0 seconds, stop timer and log out user + if (time === 0) { + clearInterval(timer); + labelWelcome.textContent = 'Log in to get started'; + containerApp.style.opacity = 0; + } + + // Decrease 1s + time--; + }; + + // Set time to 5 minutes + let time = 120; + + // Call the timer every second + tick(); + const timer = setInterval(tick, 1000); + + return timer; +}; /////////////////////////////////////// // Event handlers -let currentAccount; +let currentAccount, timer; + +// FAKE ALWAYS LOGGED IN +// currentAccount = account1; +// updateUI(currentAccount); +// containerApp.style.opacity = 100; + +// Experimenting API + +// console.log(locale); // en-US + +// const now = new Date(); +// const day = `${now.getDate()}`.padStart(2, 0); // 2 digits +// const month = `${now.getMonth() + 1}`.padStart(2, 0); // 2 digits +// const year = now.getFullYear(); +// const hour = `${now.getHours()}`.padStart(2, 0); +// const min = `${now.getMinutes()}`.padStart(2, 0); + +// labelDate.textContent = `${month}/${day}/${year}, ${hour}:${min}`; btnLogin.addEventListener('click', function (e) { // Prevent form from submitting @@ -164,17 +238,46 @@ btnLogin.addEventListener('click', function (e) { ); console.log(currentAccount); - if (currentAccount?.pin === Number(inputLoginPin.value)) { + if (currentAccount?.pin === +inputLoginPin.value) { // Display UI and message labelWelcome.textContent = `Welcome back, ${ currentAccount.owner.split(' ')[0] }`; containerApp.style.opacity = 100; + // Create current date and time + const now = new Date(); + const options = { + hour: 'numeric', + minute: 'numeric', + day: 'numeric', + month: 'numeric', + year: 'numeric', + // weekday: 'long', + }; + // const locale = navigator.language; + // console.log(locale); + + labelDate.textContent = new Intl.DateTimeFormat( + currentAccount.locale, + options + ).format(now); + + // const day = `${now.getDate()}`.padStart(2, 0); + // const month = `${now.getMonth() + 1}`.padStart(2, 0); + // const year = now.getFullYear(); + // const hour = `${now.getHours()}`.padStart(2, 0); + // const min = `${now.getMinutes()}`.padStart(2, 0); + // labelDate.textContent = `${day}/${month}/${year}, ${hour}:${min}`; + // Clear input fields inputLoginUsername.value = inputLoginPin.value = ''; inputLoginPin.blur(); + // Timer + if (timer) clearInterval(timer); + timer = startLogOutTimer(); + // Update UI updateUI(currentAccount); } @@ -182,7 +285,7 @@ btnLogin.addEventListener('click', function (e) { btnTransfer.addEventListener('click', function (e) { e.preventDefault(); - const amount = Number(inputTransferAmount.value); + const amount = +inputTransferAmount.value; const receiverAcc = accounts.find( acc => acc.username === inputTransferTo.value ); @@ -197,6 +300,9 @@ btnTransfer.addEventListener('click', function (e) { // Doing the transfer currentAccount.movements.push(-amount); receiverAcc.movements.push(amount); + // Add transfer date + currentAccount.movementsDates.push(new Date().toISOString()); + receiverAcc.movementsDates.push(new Date().toISOString()); // Update UI updateUI(currentAccount); @@ -206,14 +312,19 @@ btnTransfer.addEventListener('click', function (e) { btnLoan.addEventListener('click', function (e) { e.preventDefault(); - const amount = Number(inputLoanAmount.value); + const amount = Math.floor(inputLoanAmount.value); if (amount > 0 && currentAccount.movements.some(mov => mov >= amount * 0.1)) { // Add movement - currentAccount.movements.push(amount); - // Update UI - updateUI(currentAccount); + setTimeout(function () { + currentAccount.movements.push(amount); + // Add transfer date + currentAccount.movementsDates.push(new Date().toISOString()); + + // Update UI + updateUI(currentAccount); + }, 2500); } inputLoanAmount.value = ''; }); @@ -223,7 +334,7 @@ btnClose.addEventListener('click', function (e) { if ( inputCloseUsername.value === currentAccount.username && - Number(inputClosePin.value) === currentAccount.pin + +inputClosePin.value === currentAccount.pin ) { const index = accounts.findIndex( acc => acc.username === currentAccount.username @@ -251,3 +362,227 @@ btnSort.addEventListener('click', function (e) { ///////////////////////////////////////////////// ///////////////////////////////////////////////// // LECTURES +/* +console.log(23 === 23.0); // true + +// Base 10 - 0 to 9. 1/10 = 0.1. 3/10 = 3.3333333 +// Binary base 2 - 0 1 +console.log(0.1 + 0.2); // 0.30000000000000004 +console.log(0.1 + 0.2 === 0.3); // false +console.log(Number('23')); // 23 +console.log(+'23'); // 23 + +// Parsing +console.log(Number.parseInt('30px')); +console.log(Number.parseInt('30px', 10)); // 30 +console.log(Number.parseInt('e23')); // NaN + +console.log(Number.parseInt('2.5rem')); // 2 +console.log(Number.parseFloat('2.5rem')); // 2.5 + +// console.log(parseFloat('2.5rem')); // 2.5 + +console.log(Number.isNaN(20)); // false +console.log(Number.isNaN('20')); // false +console.log(Number.isNaN(+'20X')); // true + +console.log(Number.isFinite(20)); // true +console.log(Number.isFinite(0)); // true +console.log(Number.isFinite('20')); // false +console.log(Number.isFinite(+'20X')); // false + +console.log(Number.isInteger(23)); // true +console.log(Number.isInteger(23.0)); // true +console.log(Number.isInteger(23 / 0)); // false +*/ +// console.log(Math.sqrt(25)); // 5 +// console.log(25 ** (1 / 2)); // 5 +// console.log(8 ** (1 / 3)); // 2 + +// console.log(Math.max(5, 18, 23, 11, 2)); // 23 +// console.log(Math.max(5, 18, '23', 11, 2)); // 23 +// console.log(Math.max(5, 18, '23px', 11, 2)); // NaN + +// console.log(Math.min(5, 18, 23, 11, 2)); // 2 + +// console.log(Math.PI * Number.parseFloat('10px') ** 2); // 314.1592653589793 + +// console.log(Math.floor(Math.random() * 6) + 1); // 1-6 + +// const randomInt = (min, max) => +// Math.trunc(Math.random() * (max - min) + 1) + min; +// // 0...1 -> 0...(max-min) -> min...max + +// console.log(randomInt(10, 20)); // 11 + +// //rounding integers +// console.log(Math.trunc(23.3)); + +// console.log(Math.round(23.3)); +// console.log(Math.round(23.9)); + +// console.log(Math.ceil(23.3)); +// console.log(Math.ceil(23.9)); + +// console.log(Math.floor(23.3)); +// console.log(Math.floor(23.9)); + +// console.log(Math.trunc(-23.3)); +// console.log(Math.floor(-23.3)); + +// // rounding decimals +// console.log((2.7).toFixed(0)); // 3 +// console.log((2.7).toFixed(3)); // 2.700 +// console.log((2.345).toFixed(2)); // 2.35 +// console.log(+(2.345).toFixed(2)); // 2.35 + +// // the remainder operator + +// console.log(5 % 2); // 1 +// console.log(5 / 2); // 2 + +// console.log(8 % 3); // 2 +// console.log(8 / 3); // 2 + +// console.log(6 % 2); // 0 +// console.log(6 / 2); // 3 + +// console.log(7 % 2); // 1 +// console.log(7 / 2); // 3.5 + +// const isEven = n => n % 2 === 0; +// console.log(isEven(8)); // true +// console.log(isEven(23)); // false +// console.log(isEven(514)); // true + +// labelBalance.addEventListener('click', function () { +// [...document.querySelectorAll('.movements__row')].forEach(function (row, i) { +// if (i % 2 === 0) row.style.backgroundColor = 'orangered'; +// if (i % 3 === 0) row.style.backgroundColor = 'blue'; +// }); +// }); + +// const diameter = 287_460_000_000; +// console.log(diameter); + +// const price = 345_99; +// console.log(price); + +// const transferFee1 = 15_00; +// const transferFee2 = 1_500; +// console.log(transferFee1, transferFee2); + +// const PI = 3.1415_9265_3589_793; +// console.log(PI); + +// console.log(2 ** 53 - 1); +// console.log(Number.MAX_SAFE_INTEGER); +// console.log(2 ** 53); +// console.log(64654468464354354343535434354354343548963164435444n); + +//Create a date +// const now = new Date(); +// console.log(now); + +// console.log(new Date('Aug 02 2020 18:05:41')); +// console.log(new Date('December 24, 2015')); +// console.log(new Date(account1.movementsDates[0])); + +// console.log(new Date(2037, 10, 19, 15, 23, 5)); +// console.log(new Date(2037, 10, 31)); +// console.log(new Date(0)); +// console.log(new Date(3 * 24 * 60 * 60 * 1000)); + +// // Working with dates +// const future = new Date(2037, 10, 19, 15, 23); +// console.log(future); +// console.log(future.getFullYear()); // 2037 +// console.log(future.getMonth()); // 10 +// console.log(future.getDate()); // 19 +// console.log(future.getDay()); // 4 +// console.log(future.getHours()); // 15 +// console.log(future.getMinutes()); // 23 +// console.log(future.getSeconds()); // 0 + +// console.log(future.toISOString()); // 2037-11-19T15:23:00.000Z +// console.log(future.getTime()); // 2142248580000 + +// console.log(new Date(2142248580000)); + +// console.log(Date.now()); + +// future.setFullYear(2040); +// console.log(future); + +// Operations with dates +// const future = new Date(2037, 10, 19, 15, 23); +// console.log(+future); // 2142248580000 + +// const days1 = calcDaysPassed( +// new Date(2037, 3, 4), +// new Date(2037, 3, 14, 10, 8) +// ); +// console.log(days1); // 10.422685185185185 + +// const num = 3884764.23; + +// const options = { +// style: 'currency', +// unit: 'celsius', +// currency: 'EUR', +// useGrouping: false, +// }; + +// console.log('US: ', new Intl.NumberFormat('en-US', options).format(num)); // 3,884,764.23 +// console.log('Germany: ', new Intl.NumberFormat('de-DE', options).format(num)); // 3.884.764,23 +// console.log('Syria: ', new Intl.NumberFormat('ar-SY', options).format(num)); // 3,884,764.23 +// console.log( +// navigator.language, +// new Intl.NumberFormat(navigator.language, options).format(num) +// ); // 3,884,764.23 + +// const ingredients = ['olives', 'red peppers']; +// const pizzaTimer = setTimeout( +// (ing1, ing2) => console.log(`Here is your pizza 🍕 with ${ing1} and ${ing2}`), +// 3000, +// ...ingredients +// ); +// console.log('Waiting for pizza 🍕'); + +// if (ingredients.includes('spinach')) clearTimeout(pizzaTimer); + +// setInterval(function () { +// console.log('Hello'); +// }, 1000); + +// setInterval(function () { +// const now = new Date(); +// console.log(now); +// }, 1000); + +// Stopwatch + +// const startStopwatch = function () { +// const tick = function () { +// const min = String(Math.trunc(time / 60)).padStart(2, 0); // 2 digits +// const sec = String(time % 60).padStart(2, 0); // 2 digits +// // In each call, print the remaining time to UI +// labelTimer.textContent = `${min}:${sec}`; + +// // When 0 seconds, stop timer and log out +// if (time === 0) { +// clearInterval(timer); +// labelTimer.textContent = '00:00'; +// console.log('Timer stopped'); +// } +// // Decrease 1s +// time--; +// }; +// // Set time to 5 minutes +// let time = 120; + +// // Call the timer every second +// tick(); +// const timer = setInterval(tick, 1000); +// return timer; +// } diff --git a/13-Advanced-DOM-Bankist/starter/index.html b/13-Advanced-DOM-Bankist/starter/index.html index 6999b1ccef..13fb5fd104 100644 --- a/13-Advanced-DOM-Bankist/starter/index.html +++ b/13-Advanced-DOM-Bankist/starter/index.html @@ -21,6 +21,8 @@ alt="Bankist logo" class="nav__logo" id="logo" + designer="Jonas Schmedtmann" + data-version-number="3.0" />