Jonas: Let's now finally implement the login feature
of our application.
And this is gonna be a lot of work
so let's get started right away.
And to start, let's take a look at our demo application.
So in this case here in the beginning,
we cannot see anything, so there's no logged in user.
And then we can input a username.
And so this is the kind of username that we computed
before, remember, and then the PIN.
And if that is correct,
so if the PIN corresponding to this account is correct,
then we get logged in.
And that's gonna happen whether we click on this button here
or hit the Enter key.
And so then all of this appears,
so all the values here are calculated.
And yeah, so that's the main thing that we need
to do in this lecture.
Then of course, if someone else logs in,
then their values are gonna be displayed.
And so let's take a look at the HTML here of this form.
So indeed here we have a form element
and this form has a button.
And so it's onto this login button
that we will attach the addEventListener method.
Then as for the inputs,
the username is gonna come from this one
with this class, login user dash dash input.
And the PIN is gonna come from this one.
And as always, I already have all of this here selected.
So this is the button here.
And then we have inputLoginUsername and inputLoginPin.
So let's now create these event handlers.
So event handlers right here.
So btnLogin.addEventListener for the click.
And then as always, our callback function.
And here, let's just log to the console, LOGIN.
And now did you see what happened here?
Take a close look down here what happens as we click.
So for a flash there, you saw the login
and then the page reloaded.
And that's because this is the button in a form element.
And so in HTML,
the default behavior when we click the Submit button
is for the page to reload.
So we need to stop that from happening.
And for that, we need to actually give this function here
the event parameter and let's just call it event.
And you already know how this callback function gets access
to this event object, remember?
And so on that event, we can call a method
called preventDefault, like this.
And so as the name says,
this will then prevent this form from submitting.
So prevent form from submitting.
So let's do that again.
And now we fixed that problem and we can see LOGIN.
Now another thing that's great about forms
is that whenever we have one of these fields here inputted,
and when we then hit Enter like this,
then that will actually automatically trigger
a click event on this button.
So once again, hitting Enter in this field
or in this field is exactly the same
as the user clicking right here.
So both of these things will trigger a click event.
So you see as I hit Enter,
we get more and more click events.
So that's why we get then LOGIN logged to the console.
But now let's do the actual work.
So to log the user actually in,
we need to find the account from the accounts array
with the username that the user inputted.
And so that's where our find method comes into play again.
So we can do accounts.find,
and then this is actually the same
that we did in the last video.
So account.owner should be the same as,
so three equals actually.
And so remember we have this value at inputLoginUsername.
So that is this element here.
And then from there we need to take the value property.
Remember that?
So we did this here, I think in the guess my number game
where we also read the value out of an input field.
And so here, this is the same.
And so now let's actually save this into a variable.
Now this variable needs to be defined
outside of this function.
And that's because we will need this information
about the current account also later in other functions.
So it's a good thing to have this big important information
outside of this function so that we can then remember it
for other actions in our application.
For example, when we transfer money here, then we need
to know from which account that money should actually go.
And so for that, we need the current account.
So currentAccount, and here we just define it
and that's why we need a let.
And so then here we assign it this value.
So currentAccount.
So let's check that.
So js, and we get undefined.
So there was some problem here,
and the problem is, as I see right away,
is that we are looking for the owner,
but we need to look for the username.
So the owner is the whole name,
but the username property is these properties
that we created earlier.
So here in this function, remember?
So we need to compare this value here that the user inputs
of course, to that username.
So try that again.
And now here we get the object which has
exactly this username.
And so it is here, my object basically.
So we got the user that is trying to log in
and now all we need to do in order
to actually log the user in is
to check if the PIN is correct.
So PIN here is like a password,
but something that we usually use like in an ATM.
And so I decided to just go with that here
because I think this also looks a little bit
like an ATM machine here.
So let's then do that test.
So if currentAccount.pin is equal to inputLoginPin.
So that's the variable that holds the selection
of selecting this element.
And then again, we need to take the value.
And finally, we also need to convert this
to a number, because as I mentioned earlier,
this value will always be a string.
And so here, before we do anything,
let's just log in again here to the console.
So js, and we got logged in.
But if we only input js,
then we simply get the object itself,
but without being logged in because the PIN is correct.
And now let's try just some other user
to see what happens here.
And we get an error.
So that error is cannot read property pin of undefined.
And so the reason for this is that this object here
is now undefined.
Because no account could be found for this username.
And so the find method,
so this one here, will return undefined if no element
matches this condition.
So that's something that we haven't seen before
and so that's why I'm showing this to you.
But anyway, how should we solve this?
Well the first thing that might come into mind is
to simply check if the currentAccount exists, like this.
So this would fix the problem, but we can do better
because we already learned about something called
optional chaining.
Remember?
So we can do this, and then this pin property
will only be read in case
that the current account here actually exists.
Remember that?
And so this is a lot easier and a lot more elegant.
So let's try that.
And so now nothing happened, so no error.
All we get here is the undefined
because, yeah, this account does not exist,
but that's of course not a problem.
But now in case that the account does exist
and that the PIN is correct, what should we do?
Well, let's take a look at our flowchart here.
So this is the part we already checked.
So if we have the correct credentials.
And so if yes, then we should display the UI
and the welcome message.
So let's write that here in our script.
Put that here.
And so I like to kind of plan out
what I'm doing here using comments.
So display UI and a welcome message.
Next up, we should display and calculate the balance.
Then the same with the summary
and the same with the movements.
This part here, we are leaving
for the next section about the timer.
So display balance, summary, and movements.
So display movements, display balance, display summary.
And let's start with the message here.
So that is this element here.
So let me inspect that.
So it's this paragraph here called welcome.
And so as always, I already have that selected.
So it's a label, so probably it's called labelWelcome.
Label, ah, indeed, here it is,
labelWelcome.textContent as always.
And then here we are gonna write, welcome back,
and then the first name of the person.
Welcome back, and then the owner of the current account.
So that's currentAccount.owner
and then only the first word.
So how do we do that?
Well, we use our good friend split,
and we split it with a space.
So as I said, we use this one all the time.
And then from the resulting array,
we simply take the first element, like this.
So this displays the message
and now about displaying the UI,
remember how in the beginning we set the opacity here
from zero basically back to 100, which is the default.
So usually the opacity here is at zero.
And so now when we log the user in,
we actually set this opacity here to 100.
So as we save this now it will all disappear.
And so now what we will do is the containerApp,
I think, yes.
So containerApp is the element that we selected previously,
which has this app class.
So this element, we will manipulate the style
and in particular, the opacity style.
Now remember how I said in another project
that it's also good to use classes for this.
But in this case it's really just one style,
so it's not a big work to just do it like this.
So let's test this one out for now.
So js and my PIN.
And indeed we get our message here
and also we get everything here now back to visible.
And Jessica Davis now, which has PIN 2222.
And so now we also get Jessica.
Now as you see these balances
and these movements here, they're all still hard coded
from what we had back here.
So here we called calcDisplaySummary
and also the balance and the movements.
But now we want to do that not here,
but actually inside of the login function.
So let's remove all of this,
again, because we do not want
to call these functions right in the beginning
when our script is loaded.
We only want to calculate
and display the balance and the movements
and the summary as soon as we actually get the data
that we want to display.
That makes sense.
So let's remove all of that and actually do it here.
So displayMovements,
and then it is the currentAccount.movements.
And that's because this method here,
or actually this function here,
it expects a movement argument.
And as we hover this function name, VS Code is so smart
that it actually shows it to us here.
And so from there, we can immediately see what we need
to pass into the function.
So that's really handy.
Then the same with the balance,
so display or calcDisplayBalance actually.
And so once again, let's just hover this here
to make sure what we need and it is the movements,
so that data is stored in the currentAccount.movements.
And finally also the summary.
So calcDisplaySummary.
And once again we will need the movements
so that data is in currentAccount.movements.
Now we will have to come back to this function here
by the end of this lecture,
but for now, let's leave it like this
and let's log in again, first with Jonas.
And so this is the data that we are already used
to seeing, this balance value and this movements here,
because we have always been printing these values here
using that account.
But now as we log in as Jessica Davis, you will see
that these values here will all change accordingly.
So let's see.
And yes, so that's great.
Now we are getting all of these values.
So this data here dynamically
really from the account object itself.
So we have all her movements,
we calculated all of these statistics or summaries.
And of course also the balance
is now really about this account itself.
And we have more.
Let's try Steven here.
So Steven Thomas Williams with PIN 3333.
And this kind of messed up our UI here
because of this calculation.
So Steven only has a balance of 10 euros.
And now finally we can try Sarah Smith.
And so once again, we see all her different movements here.
And yeah, this is great.
So this now really works depending on the user's data.
So let's go back here.
So what I want to do next is to, as we log in,
also get rid of this data here.
So basically emptying these two fields
and also as we log in, like this,
I didn't want this field here to lose its focus.
So let's do that before this.
So clear the input fields.
And so we already know that the fields are
inputLoginUsername, which we want to set
to the empty string.
And then also inputLoginPin.
And we can do it like this, LoginPin, also set it to equal
because the assignment operator works from right to left.
So it'll start here assigning equal to this field here.
And then this here will become the empty string.
And so then empty string will also be assigned to this one.
We are just missing the dot value here.
Otherwise we would set the entire element
to the empty string.
So js, 1111.
And now this happens, what I mentioned before
is that this field here still has this focus,
so we can see the cursor there blinking.
And so that's a bit ugly.
And so on that field, so inputLoginPin,
we can use this blur function or method.
So just call blur.
And so that will make it so that this field loses its focus.
So you see, now it looks great.
And now just to finish, we also need to come back
to this function here, just as I mentioned earlier.
So calcDisplaySummary and let's go there.
So this one here, and as you see,
we calculated the interest using this 1.2 rate.
So right now for all of the accounts,
the interest rate is now calculated
using this 1.2 interest rate.
However, as we take a look at the accounts,
each of them actually has a different interest rate.
So this one has 1.2, but this one has 1.5,
and this one has less.
So it gets less interest.
And so now of course we also want
to dynamically use this interest rate
depending on the current user.
That makes sense.
And so we have to modify this function here a little bit.
And so in order to get access to that data,
so to that interest rate,
we now need more than just the movements.
Instead of the movements, we want now the entire account
because then we can take the movements from the account
and also the interest rate.
So again, we will now change this function
and pass in the entire account
and not just the movements array.
And so then from there,
we will be able to take the movements
that we need to calculate these three statistics here.
And then also the interest rate that we have here.
So account, let's just call it,
or let's just call acc one more time.
So here now we need to take the movements from that account.
The same here and here.
And now here, instead of this 1.2 fixed rate,
we take acc dot, the interest rate that's in there.
So let's just see if everything still works.
And let's see it with Steven.
So that was stw and 3333.
And you see that now our UI is no longer messed up.
Ah, but of course we forgot
to call this function here correctly.
That's probably why we got this error.
Yeah, right.
So down here we are still calling this function
only with the movements array.
So we need to instead pass in the entire account
because as you see now we do need the account here.
So try that again, stw.
And so now we get the correct interest.
And maybe you remember that before it was different,
it was this crazy long number
with a lot of zeros which messed up our user interface here.
So this means that it is now being calculated differently
for each of the user according
to their own specific interest rate.
Great.
And with this, we implemented all of the tasks
that we had in our flowchart for this functionality.
And in practice what this means is that
for the first time, we made all of this data
that we see here in our application dynamic.
So depending on which user is actually logging in.
So let's see that change again, let's try a wrong PIN here.
And so now nothing happens.
And of course we could now hide the user interface
and display an error message,
but I want to keep it simple here.
So this is just a simple learning application,
so we don't need to mess with all of that.
What matters is only the correct version for now.
And so with the correct PIN now,
as you saw, the data changed here,
back to this Jonas account.
Awesome, that's great.
So that's really great progress.
Congratulations for making it this far in this section.
I know there's a lot to learn and a lot to take in,
but I hope that this lecture too was clear to you
how everything worked here.
And just to recap, clearly the most important part here is
the usage of this find method here
and knowing that this is the correct method for the job.
So maybe analyze this line here a little bit
and then see exactly what happens here.
Also this nice usage of the optional chaining.
And then we are ready to implement our next feature,
which is gonna be transferring money
from one of our users to another.