‫Let's once again finish a section
‫with a nice coding challenge,
‫so that we can practice everything that we learned
‫in the section.
‫And I can't stress enough
‫how important these challenges are.
‫So please, please don't skip this video right now.
‫So we are going to build this very simple tip calculator.
‫So here you can input how much the bill was.
‫So let's say $100.
‫And then you can say how satisfied or dissatisfied
‫you were with the service and your friend.
‫So let's say that two people were out for dinner,
‫and then basically together you decide
‫how much the tip should be.
‫So for example, if you say it was good, that can be 10%,
‫but your friend says 0%.
‫And so then the average between the two of you is 5%
‫which is indeed these $5 here.
‫And so the final bill is $105,
‫which is 100 plus the $5 tip.
‫And of course if your friend found it absolutely amazing,
‫then here the average between the two of you is 15
‫and therefore it is a $15 tip.
‫And as you change the value here,
‫of course, it keeps updating down here.
‫You also have this Reset button that you can click
‫which will set everything back to the initial values.
‫Now as you build this, I want you to create
‫one separate component for each of these pieces.
‫So this one here should be one component.
‫For example, it can be called the bill input.
‫Then you should have one component for this,
‫for example called select percentage
‫and then reuse that component here again.
‫So with some different text
‫but it should be the same component.
‫Then here you have some output component
‫for displaying this text
‫and then a reset component just for this button.
‫Okay?
‫Now these three inputs here,
‫they are of course controlled elements.
‫And so you can start by adding their state value
‫into the component itself.
‫But you will soon notice that you actually need
‫this state in the parent component
‫because you will need it to calculate
‫this output right here.
‫So then you'll have to use the technique
‫of lifting state up.
‫And so hopefully you remember all the logic
‫of how that works and why we have to do that.
‫And in case there is still some doubt,
‫you can always go back and check out the lectures
‫where we talked about lifting up state.
‫and of course all the other things
‫that you need here in this challenge.
‫So, I'm aware that this challenge is not super easy
‫but that's what many students actually want.
‫So last time I asked the large majority
‫wanted really hard challenges.
‫So this is not really hard I think
‫but it can be a bit challenging.
‫So it's not just 100% straightforward.
‫Therefore if you run into any issues,
‫that's no problem at all.
‫So just write the part that you can
‫and then the rest, watch my solution.
‫That's 100% fine.
‫The most important part is that you start writing
‫at least some code and that you try it on your own.
‫And that's enough talk.
‫I see you here in 5 or 10 or whatever time that you need.
‫All right, so we have a lot of code to write
‫so let's get straight into it.
‫So I will start with a function called TipCalculator
‫which we will then call basically right here.
‫So we need no styles for this app at all.
‫So that's why I didn't provide any CSS starter files.
‫Okay, let's close down the sidebar here
‫and then let's start by writing out all our components.
‫So the next one is called BillInput.
‫Then let's create SelectPercentage.
‫And of course your component names here
‫can be completely different.
‫Then we have function Output.
‫And finally for Reset.
‫All right, now let's build them out one by one.
‫And we can actually start here in the TipCalculator
‫because all that's going to happen here
‫is that I will basically include all the other ones.
‫So let's just create a div here.
‫Then I will want the BillInput.
‫I will want two SelectPercentages.
‫And of course, we will later on then
‫pass the props into here.
‫I'm just, again, building the static parts
‫without any data at all.
‫So then we will have the Output
‫and we will have our Reset button.
‫Okay, let's start with this one.
‫Okay.
‫Then I will place this one into a label.
‫How much was the bill?
‫And then finally we have our first input
‫of the type text.
‫And let's add a placeholder as well,
‫which is always nice.
‫And so yeah, here we got already some,
‫well, something on the UI,
‫was just thinking of getting rid this class.
‫And so then we get rid
‫of basically all the styling altogether.
‫Can just come here to this CSS if we want.
‫And just like this.
‫Just to make the font family a bit nicer on the eyes.
‫But anyway, here, let's again return a div
‫and then we have a select element.
‫And as you already know, then inside the select
‫we have our different options.
‫So zero is for Dissatisfied,
‫which is 0%.
‫Then let's just copy this or a few times.
‫5, 10, and 20.
‫It was okay, is 5%,
‫then it was good is 10%,
‫and then 20% is for absolutely amazing.
‫Now, we also want some text here
‫and so we could pass that here in as a prop,
‫but I believe it's a lot nicer
‫to write it right here directly.
‫So how did you like the service?
‫Then close that.
‫And so basically including the content
‫between the opening and the closing tag.
‫How did your friend,
‫friend like the service?
‫All right.
‫And now I hope you remember how we get this text here.
‫So this content into select percentage.
‫And that's right, it gets automatically passed
‫in here as the children prop.
‫So let's create a paragraph or maybe a label
‫with exactly that.
‫There you go.
‫That looks a lot better.
‫So let's move on here.
‫Return, and here we will have an h3,
‫You pay X,
‫which is some dollars.
‫Let's say $A, plus,
‫$B for the tip.
‫So just some placeholders here for now
‫because we are building, still, the static version.
‫Now, finally here, a button that says Reset.
‫Now, okay, so that took us some time
‫just to build the static part
‫and now let's add some state.
‫And the best way to start is to create one piece of state
‫for each of these three controlled elements
‫that we need here.
‫Now as I started by saying in the very beginning,
‫you could have started by creating local state
‫right here in the component.
‫So basically like we learned before.
‫However, you would then quickly discover
‫that you need this input value here.
‫For example, right here in the TipCalculator component
‫because it's here where you will later calculate
‫this tip value right here, so that you can then display it,
‫so you can pass it into Output and then render it there.
‫Therefore, I will actually, basically,
‫immediately lift that state up and not even write it
‫in the BillInput.
‫So bill and setBill are equal to useState
‫and for some reason, sometimes, this doesn't really work
‫with the importing.
‫So then let's do it manually, useState from react.
‫Nice.
‫And actually here let's start with an empty string.
‫Okay.
‫And then we need to pass both of them in
‫because of course we will want to update that state
‫each time that the change event is fired here on the input.
‫Remember that?
‫So that's just how controlled elements work.
‫It's always the same recipe, always the same thing,
‫no matter if the state lives
‫right in this component or in another parent component.
‫But the idea is the same as you will see again in a minute.
‫So let's pass in a prop called Bill with the value of bill.
‫And then let's again use our on prefix.
‫So onSetBill will be setBill.
‫But of course it will be just as valid
‫to pass in prop with exactly this name.
‫So here we receive bill and onSetBill
‫and let's then use these values here.
‫So the value of this input field should be bill.
‫And when it changes,
‫then we want to basically set the bill
‫based on e.target.value
‫and we need to convert that whole thing to a number.
‫Now, okay.
‫Now unfortunately the dev tools don't work
‫as we experienced a few times already,
‫but in order to see it,
‫we can actually pass it in here into the output.
‫So bill is bill,
‫because remember how we actually display
‫that bill value right here.
‫So that's exactly this 80 right there.
‫So let's then receive it here.
‫So that's this first value right here.
‫So let's see.
‫That, yeah, that works beautifully.
‫So just like any normal controlled component
‫or controlled element
‫with the difference that the state
‫doesn't live in the component itself,
‫but in the parent component.
‫And now let's use the exact same logic
‫for these select percentage components.
‫So let's create two pieces of state, one for each of them.
‫So that's going to be percentage1
‫and setPercentange1
‫and the default here is zero.
‫And then let's just copy-paste.
‫And so this one here will take the value of percentage1.
‫So the percentage prop that this one will receive
‫will be equal to the percentage1 state,
‫while this other one, so this one also gets
‫a percentage prop of course,
‫but here the value will be given by this other state.
‫And so with this, we can use the same component
‫to set these two different state values.
‫Okay, and now, also the onSelect handler.
‫And this one will be setPercentage1,
‫while again here onSelect will be
‫setPercentage2.
‫All right.
‫Then down here we can receive them besides the children.
‫So the percentage and onSelect.
‫And so now all we have to do is value
‫is equal to the percentage that we receive,
‫and then onChange
‫and then onSelect.
‫So we can immediately convert to a number,
‫e.target.value.
‫It's always the same recipe.
‫So now we will not be able to immediately see a tier
‫but it seems to be working,
‫both of them.
‫Alright, and so now we have all our state that we need.
‫And so based on this, we now can already calculate the tip.
‫So how do we do that?
‫Should we create a new piece of state for the tip here?
‫Well, there is actually no need
‫and it makes no sense to do so
‫because the tip can be completely calculated
‫from the bill and the percentages.
‫And so we are in the presence of derived state.
‫So the tip is simply the bill
‫times the average of the two percentages.
‫So that's percentage1 plus percentage2,
‫divided by two,
‫and then the whole thing divided by 100.
‫Because here the percentages are these actual values.
‫So between 0 and 100
‫but then we need to calculate them between zero and one
‫because, well, that's how we calculate percentages.
‫And here, I don't really agree with this parenthesis here.
‫Let's place that right here.
‫So this we calculate the average percentage
‫and convert it to number between zero and one.
‫And then simply by multiplying it with the bill,
‫we get the amount of the tip.
‫And so now we are ready to also pass that here
‫into the output.
‫I mean here we receive it to pass it.
‫It's actually here.
‫So tip equal tip.
‫And so, can already display that here.
‫And then here it's as simple as adding the two together.
‫So let's say 100.
‫And one was dissatisfied,
‫the other one was amazing.
‫And so the average is 10%, which is exactly those $10.
‫Yep, then it becomes 20,
‫which together makes 120,
‫just make the dollar sign there.
‫And so yeah, this seems to be working just fine.
‫All we have to do now is to make this Reset button work.
‫But that is fortunately very simple.
‫So function handleReset.
‫And here all we need to do is really to set
‫all of the values
‫back to those initial states.
‫So setPercentage1 back to zero.
‫And here the same thing.
‫And then we just pass it right here.
‫So onReset should become handleReset like this.
‫And then of course the onClick event handler, onReset.
‫And let's see, and beautiful.
‫So everything back to normal.
‫And now what we should do is to not display
‫the button and this output
‫whenever there is actually no tip.
‫So then it makes no sense to display that, right?
‫So these two things right here.
‫So let's wrap them into the JavaScript mode
‫and then let's say bill greater than zero &&.
‫Now here we get a problem because we have one piece of JSX
‫which has basically two top-level elements
‫which is not allowed.
‫So there can only be one parent element.
‫And so once again, our fragment here is a very nice option.
‫We don't need these, give it a save.
‫And yeah, now they're gone.
‫And as soon as we start riding here, we have a tip value,
‫then we can see the output there in the button.
‫Great, and that's actually it.
‫So I believe the hard part here
‫was to have all the state living in the TipCalculator,
‫but then having these two components here,
‫needing that state and also updating that state.
‫So there's a lot of state passing around,
‫here with all of these props.
‫Yeah, and then also here, the tip itself.
‫So realizing that this indeed needs to be derived state.
‫'Cause otherwise you would have to calculate this tip
‫all over the place in order to keep it in sync
‫with the bill and these both percentages.
‫So that would be a lot of work.
‫And instead by having it as derived state
‫each time that the component rerenders
‫as the state is updated, this value will be calculated again
‫and can then also be rendered here onto the UI.
‫Great, but that's enough talk,
‫the video is running long enough already.
‫And so yeah, I just hope that you did
‫at least part of this coding challenge.
‫And any questions that you have, just post them in the Q&A,
‫along with your solution if you'd like.
‫So it's always nice to see different approaches
‫resulting in the same working application.
‫And with this, we then actually reach the end
‫of the section, but also of part one, basically.
‫All we have to do, if you want,
‫is now a complete practice project that is coming up next.
‫So it's a really cool project once again
‫and so I highly encourage you to not skip it
‫and meet me there as soon as possible.