‫Okay, so now it's time to finally add a new city
‫and upload it to our fake API.
‫But before we go do that
‫there's two things that we need to do first.
‫So the first thing is that imagine
‫that the user somehow goes to the form
‫without there being a latitude and a longitude.
‫So what's gonna happen then
‫is that the Geocoding API will get your location
‫from Geolocation and then get all the city information
‫about that location as usual.
‫So that doesn't make a lot of sense.
‫And so we should only run this effect here
‫if there actually is a latitude and a longitude.
‫Cause right now, again, there are none.
‫So there are none in the URL.
‫And so here in our effect
‫we can just check if there is no latitude and no longitude
‫then just return immediately.
‫And so if we then try that again...
‫So coming there just like this,
‫then nothing is going to happen.
‫And so then like this, no HTTP request is fired off.
‫Now in this situation
‫we probably also don't even want to display the form, right?
‫And so we can then, again, account for that here.
‫So saying that if there is no lat and no longitude
‫then just return, again, a message.
‫So message with the prop of message saying,
‫start by clicking somewhere on the map.
‫So telling the user basically what to do.
‫And so that's what we get then.
‫So then of course, as we click here,
‫like on Barcelona or close, then yeah, it works.
‫All right.
‫Now as we go back, notice that we don't really go back
‫to the list of cities, but instead really
‫we just go back one in the history stack.
‫So if we click on some city here, then on another one,
‫but then maybe we want to go back to Barcelona
‫we can just click here and then the map will move back.
‫Now I'm not sure if that's really the behavior
‫that the user is expecting,
‫but I think it works fine like this.
‫So we can always just come back also by clicking here
‫on this cities button.
‫But anyway, now it's time
‫to actually create those new city objects.
‫And so for that
‫we need to start by listening to the submit event.
‫So onSubmit,
‫and then let's create, as always, a handleSubmit function.
‫So let's do that here after the effect.
‫Function handleSubmit which gets access to the event.
‫Now this form will get submitted
‫when one of the buttons is clicked, remember?
‫So that's just how HTML works.
‫So that is also the reason why here in this back button
‫we did e.preventDefault
‫so that this button actually does not submit the form.
‫So then only this add button here can submit the form.
‫And so when we click that
‫then the handleSubmit function will get called.
‫And then here we need to do, again, event.preventDefault,
‫because again otherwise our page here
‫will actually get a hard reload
‫which we do not want in a single page application.
‫Now, at the beginning of the lecture
‫I said that we should do two things
‫before actually writing this code here.
‫So before actually creating the city.
‫So that was to fix the form
‫in case there is no latitude in longitude in the URL.
‫And second, what I want to do
‫is that here we want a bit more
‫of a friendly way of adding a date.
‫So here the question is, when did you go to the city?
‫And so, of course, this is not what we want to write.
‫So usually we then have some kind of date picker.
‫And so let's get ourselves a date picker, again,
‫as an NPM package.
‫So now maybe you'll start noticing the trend
‫that whenever we need something
‫that we don't want to build ourselves,
‫we just grab it from npm.
‫And so that is one of the huge advantages of React
‫so that there is always some package available
‫for whatever we need.
‫So here we can just npm install react-datepicker
‫which will, as the name says,
‫give us a date picker component for React.
‫And as always, it's a good idea
‫to basically try to check out the documentation
‫of whatever packages that we are bringing in.
‫So this is the package that we're looking for
‫and to notice how it has 4 million downloads a month.
‫So this is a hugely popular package.
‫And so this is what it's gonna look like.
‫So here we did that.
‫And notice how we also need to import then the CSS,
‫but one thing at a time.
‫So here... Where is that?
‫Yeah, so when did you go?
‫Instead of this input right here
‫what we want is now that date picker.
‫So let's see what it looks like.
‫Yeah, this is the name of the element.
‫Then let's import that also.
‫So import DatePicker from react-datepicker like this.
‫All right, and then let's see what we get.
‫So this is really not so nice yet
‫and so that's why we need to include that CSS.
‫So let's come to our documentation,
‫just copy this line of code and place that there.
‫And so now let's see if we get something a bit nicer.
‫And indeed that looks a lot better.
‫All right.
‫So let's now then define a few props here
‫because of course, as we click this,
‫so as we click a certain date,
‫we then need to store that date somewhere.
‫So the way we do that is to,
‫just like any other input element, the onChange prop.
‫So basically we can actually just grab this here
‫or actually not really because it's gonna be different.
‫So onChange.
‫And then here actually in this callback function
‫what we get is the selected date.
‫So not an event, but really the date.
‫And so then all we have to do is set date
‫to that date that we just received.
‫And then we also want to display the current date.
‫And so usually we do that here at the value prop like this.
‫But here instead we just use the selected prop
‫which we then set to the current date.
‫So at the beginning
‫that date is going to be basically today.
‫So that's what this is.
‫And finally, we can also specify the date format.
‫So with the string, and then we can say day-day,
‫then here to uppercase Ms for the month.
‫And so here you see that now it is nicely formatted
‫as March 31st, which is today.
‫And then as we click here, we can select some other date
‫and then that's going to show up there.
‫Okay, then let's just add this ID here as well
‫just to make this attribute right here work.
‫So that we click here, then it selects that.
‫So I'm not sure if we ever did this before,
‫but so this is, again, just basic HTML.
‫With the difference that in normal HTML
‫here this is called for.
‫At least I believe so.
‫And then when you click here it will select the element
‫which has the same ID name as this one.
‫But in React here the prop is called htmlFor.
‫Okay, so now that we have a nice way of inputting the date
‫let's come here and do something with this.
‫Now, first of all, if there is no city name or no date
‫then we don't want to do anything.
‫So then we just return.
‫But if there is
‫then let's create ourselves a new city object.
‫So let's call that new city.
‫And so here what we want is the city name, the country,
‫the emoji, the date,
‫the notes that the user provided here in this box.
‫The position as well. So, position.
‫And remember that this is an object
‫with the latitude and longitude.
‫And if you're not sure about the data format here
‫then basically this is what we are looking for.
‫All right, and so I think we have all of this now
‫except for the ID,
‫but that is going to be automatically created
‫by the JSON server, so by that fake API itself.
‫So let's just log that to the console just to make sure
‫that everything is looking nice.
‫Okay.
‫And nice.
‫So everything's looking great right here.
‫And so let's then finally create that function
‫which uploads this new object to our fake API.
‫And just like all the other functions
‫that are about that API, we do that in the context.
‫So right here in the city's context.
‫So we already have gat city.
‫And now, well, let's just copy and paste this again.
‫Here we create createCity.
‫And this gets as input a newCity.
‫All right.
‫Now here, we don't need this. So just two cities.
‫And since this is now going to be a post request
‫we need to specify here the options object.
‫So the method is post,
‫then the actual data that we want to send now
‫is in the body property.
‫And so that's going to be the new city converted to JSON.
‫Or actually to a string, not to JSON.
‫And then here we just pass in the newCity.
‫And finally, we need to specify some headers.
‫So in this case, the Content-Type header
‫should be set to application/json
‫just so that the API knows what data format it is receiving.
‫All right, so pretty standard stuff.
‫And if you're not used to this,
‫then this is again, nothing about React.
‫This is just the standard way
‫of creating a post request to an API.
‫So basically to send some data to an API.
‫All right, then here for now, we don't need to set anything.
‫And then all I want to do for now here
‫is to see the results of doing this operation.
‫Okay, and so now we are ready to call this function
‫inside our handler function in the form.
‫So let's pass this into the context.
‫So createCity,
‫and then we can grab that function from there right here.
‫So const createCity and then useCities.
‫And yeah, then let's do that.
‫Let's remove that and instead createCity with a newCity.
‫Okay, so let's try that.
‫And nice.
‫So here we are now getting back this city object
‫not from here, but actually from this console.log over here.
‫So this one right here.
‫And so this is the newly created city.
‫Now if we open this,
‫then we see that it has this new ID, right?
‫Okay, but now watch what happens as we go back.
‫So maybe we expect to now see this city name there,
‫but as we go back, it is not there.
‫So it hasn't been added to this state right here.
‫So why do you think that is?
‫Well, if we think about this, then it actually makes sense
‫because nowhere in our code we are updating the state
‫that is displaying these cities here.
‫So these cities are simply fetched once in the beginning
‫but they're never updated.
‫So this cities stayed right here.
‫Again, it is fetched in the beginning,
‫but we did not update that, right?
‫Now if we reloaded the page
‫then that new city would appear down here.
‫But that's only because, well, we re-fetched the data.
‫And so then of course, it needs to be there.
‫And so what we also need to do here
‫is to add that new city to our state.
‫So basically, we're gonna keep the application state
‫in sync with the state from the UI.
‫Or in other words, using the terminology
‫that we have learned earlier in the section
‫we're gonna keep the UI state in sync with remote state.
‫Now, this is usually not the way to go
‫but in a small application like this one
‫it is perfectly fine of doing this.
‫And then the next big application
‫we will then learn how to better do this.
‫So there we will use a specialized tool called React Query
‫which will make it so
‫that whenever we add something new to the remote state
‫that data will then automatically get re-fetched
‫into our application.
‫So that would fix this problem.
‫But in this case we will just do the same thing manually.
‫So we'll now just also setCities
‫and then we take the current cities and return a new array
‫with the current cities plus the data,
‫which is basically the new city.
‫Okay, so let's try that again.
‫Somewhere else, maybe here.
‫It's not really important here.
‫And so now let's add and then let's go back.
‫And there it is, nice.
‫And of course, if we reload
‫it has been persisted to the API as well.
‫So really if we open this file, it is now here in this file.
‫So these new cities that we added
‫have indeed been added also here to our cities.json.
‫So this is how this fake API works.
‫So it really works as if it was a real API.
‫It's hard to notice that it isn't.
‫All right, but now going back,
‫we are still not really finished.
‫So let's click somewhere else here.
‫And so, two things that we need to improve.
‫First of all, there needs to be some loading indicator
‫that tells the user that we are currently adding a city.
‫And then after that we want to navigate back
‫to the cities list.
‫And so that's the use case that I mentioned
‫when I first talked about programmatic navigation.
‫Remember that?
‫So first of all, let's get the loading state.
‫So because right now when we're creating a city
‫we also set its loading to true.
‫And so we can then, as always,
‫get access to that here in this component
‫through our context.
‫So we can get access to that value.
‫So isLoading.
‫And we could now give it any other name
‫but this is okay as well.
‫So when this is loading
‫I want to now add a special class here that I created.
‫So let's check that out.
‫It is, yeah, just the loading class.
‫So that will then make the button here look disabled
‫and also the opacity will go down a bit.
‫But let's see.
‫So once again, when we need multiple classes
‫with CSS modules, we create a template literal
‫and then here we can add that class conditionally.
‫So isLoading, then here we want styles.loading.
‫And if not, then nothing.
‫So let's do a Portuguese city now again.
‫Let's edit. And nice.
‫So you saw for a short moment here the form grayed out
‫and was inactive.
‫And then after that the new city appeared here.
‫So immediately then when the form became visible again
‫that pin showed up there on the map
‫meaning that the new city has indeed been added.
‫And so now finally what we want to do
‫is to then programmatically navigate back to that list.
‫So we do that right here.
‫So, well first we need to actually get that function.
‫So remember that is what the useNavigate hook.
‫And then we can use that here.
‫All right, and we want to go back to the app page
‫which remember, will then automatically redirect to cities.
‫So we can actually write it here immediately.
‫All right.
‫However, if we do it like this
‫it's not gonna work as expected
‫because then right after we call this function here
‫immediately the navigation will happen.
‫But that's not what we want.
‫Instead, since this is an async function...
‫So it is indeed an async function
‫and so it will return a promise.
‫And so we can then await that here
‫for which of course we need to make this async in turn.
‫All right, so that's perfectly fine.
‫So the handler function can be an async function.
‫That's no problem at all.
‫And so I think with this, we have everything that we needed.
‫So let's try another one.
‫And beautiful.
‫So that other city is down here
‫that's why we didn't see it immediately.
‫But yeah, there it is.
‫And so with this, we finish this feature.
‫So this was the biggest and hardest feature yet, I believe.
‫So let's just very quickly recap everything that we did.
‫So first of all, we got the position basically from the URL
‫as soon as the form is opened.
‫So for that, we created this custom hook
‫which will get us the latitude and longitude.
‫Then each time those change
‫we fetch the data about that location.
‫So the city name, the country name and so on
‫so that we can then display that here nicely in the form.
‫So otherwise the user would have to write that out manually
‫which is not nice.
‫It would also not have been nice
‫if they had to write out the date here manually.
‫Therefore, we gave the users this date picker
‫so that they can choose from there.
‫And then with all the data in place
‫we are ready to submit the form.
‫So then we create this new object here
‫and pass that into the createCity function.
‫So this createCity function lives in our cities context
‫along with all the other functions that are responsible
‫for updating the state that is related to cities.
‫And so that's why this lives here.
‫And so this then creates a post request, which will mutate,
‫so it'll update the server state, so the remote state.
‫And we then also update the UI state right here
‫so that the new object immediately gets reflected
‫in our UI here as well.
‫So otherwise, we would have to manually re-fetch the data
‫so that it then shows up.
‫And then finally, after all that is done,
‫so we await that operation here,
‫and then in the end we navigate back to the page
‫where we came from.
‫And that's it.
‫So maybe try to review this on your own
‫if it's still a bit confusing.
‫But if everything is crystal clear,
‫then let's move on to the next lecture
‫where we will just quickly create the ability
‫of also deleting cities.