‫So now let's build that feature
‫where we allow our users to update their passwords,
‫their full name, and even upload an avatar image.
‫And for that, we already have two prebuilt components.
‫So we have this form here to update the password
‫and form to update the user data itself.
‫So that's gonna be the full name and also the avatar.
‫And let's actually immediately include this form
‫right here into the page.
‫So in the account page,
‫let's come here and bring in that component.
‫So, update user data form.
‫So you see that here we have the email address
‫which we are not allowed to change.
‫Then we have the full name which we can then change here,
‫and we have that button to upload the avatar.
‫And here, I'm getting this user data again
‫from this use user hook that we built earlier.
‫So this is another use case
‫and then here we have these two state variables
‫because these two elements here are controlled elements.
‫So here is the email field which is disabled by default,
‫and here we have the standard controlled element,
‫and here then to upload the image file.
‫Now here, the default value of the full name
‫can actually immediately be set with the current full name
‫coming from user data because here in this component,
‫we already know that the user will have already been loaded
‫and therefore, we don't need any loading states
‫and we can immediately use this data right here,
‫for example, to set it as a default state value.
‫Now all right,
‫so this is basically the skeleton component here
‫which doesn't do anything on its own yet.
‫And so, now it's time to add
‫yet another service function here to our authentication API.
‫So, let's do that here at the end
‫because of course now we will need a function
‫to update our user.
‫So update current user,
‫and then here we will pass in, as always,
‫an object with the data.
‫So that can be the password,
‫the full name,
‫and the avatar.
‫So let's see what we will need to do here.
‫So first we update the password
‫or the full name.
‫So we can never update both at the same time
‫because they are located here in different forms, right,
‫so we will have this same function here
‫working for both of these forms,
‫but we cannot update the password
‫and the full name at the same time.
‫Then second, we upload the avatar image
‫and then third, we use that avatar
‫to update the user again with the avatar.
‫So update the avatar in the user itself.
‫Now okay, so the way that we update
‫to currently login user is with super base dot auth
‫dot update user.
‫So this will automatically know which user
‫is currently logged in
‫and then we can update that user.
‫And for that, we need to pass in an object
‫of all the stuff that needs to be updated.
‫And so let's actually build that object here before.
‫Then of course, we will also need to await this,
‫and as always, receive the data and potential errors.
‫So let's create a variable here called update data.
‫And so then,
‫according to which data we actually received here,
‫we will build this object.
‫So if there is a password,
‫then the update data is simply gonna be an object
‫with that password.
‫But if there is a full name,
‫then the update data will look a little bit different
‫because remember that when we first signed up the user,
‫then the full name goes here into this strange data object.
‫And so here, we need to do something similar now.
‫So we need to again specify the data
‫and then that receives yet another object.
‫And so here is where we specify that full name.
‫And remember again that only one of these two
‫can be true at the same time.
‫And so that's why we can write this kind of logic there
‫and then we just need to pass that in here.
‫Okay.
‫Now if there is an error,
‫then let's just, as always, grab this,
‫and also, if there is no avatar,
‫then we are already done with the function at this point.
‫So then there's nothing to upload.
‫So if no avatar, then just return the data as usual.
‫Okay, but if there is actually
‫an avatar image specified in the input,
‫then here is where we upload that.
‫So first, let's create ourselves a unique file name.
‫So let's call that avatar.
‫And so this is gonna be a bit similar
‫to what we did earlier with the cabin images.
‫Now here, let's then use the user's ID.
‫So that's gonna be stored in the data
‫that we receive from up here.
‫So that's data dot user dot ID,
‫and then to really make sure that this is unique,
‫let's even add a random number here to the end.
‫Okay, and so now let's check if we already have
‫our storage bucket in place.
‫So let's come right here, and indeed,
‫we already created this public avatar's bucket
‫in the very beginning.
‫And it should also already have here a policy.
‫Well actually, it doesn't
‫and so it's a good thing that we came here
‫because now we need to allow access here.
‫And actually, we don't want any of the default ones,
‫but instead, we want to create our own.
‫And so let's select all of these maybe
‫and then here, let's select only authenticated users.
‫All right, now we need a policy name.
‫Allow access for auth users.
‫Let's save this.
‫And these other policies that we already have here,
‫they, right now, do actually work for all users.
‫So we could change that here for all of the four policies
‫and you can do that if you want,
‫but I will just leave it like this.
‫All right.
‫So, here we will be able to only receive an error,
‫not data, and so what we're gonna call here
‫is super base, not storage, and then dot from,
‫and here the name of the bucket.
‫And so that's, again, called avatars
‫and then we use the upload method
‫where first we pass in the file name
‫and then the image itself.
‫And so that's gonna be the avatar image which is,
‫of course, going to come from this state variable here,
‫which in turn will contain E dot target dot files
‫at position zero each time that we change the file input.
‫So each time that we select a new file,
‫that file, so that image,
‫will be stored in that avatar state.
‫And so this thing here we already did earlier
‫when we uploaded cabin images.
‫Remember that?
‫So again, that will then get passed
‫here into this function
‫and then we upload that to our bucket.
‫Now here we need to rename this to something else.
‫So storage error and then,
‫again, if there is some error,
‫we just want to throw that...
‫And if that is successful,
‫then we actually need to update the user again,
‫this time by then adding the URL to the avatar image.
‫So again, just like we did with the cabins,
‫with the difference that here, the code, is I believe,
‫a bit more straight forward.
‫But anyway, here again we receive the data and the error,
‫let's call it maybe error two this time,
‫and here, we also need to rename this one,
‫let's call it the updated user.
‫And so then, again, super base dot auth dot update user.
‫Then we create an object
‫and then this avatar also needs to go into the data object
‫and so then we have avatar, and then,
‫and so here we are going to specify that URL to the image.
‫So to see what that image is gonna look like,
‫let's just upload some file here.
‫So let's just come to our project folder
‫and that's in the wrong place now.
‫And so from here, let's just grab some image,
‫like these cabin images,
‫because I actually don't have any avatar here.
‫And so if I drop this here now,
‫then that should upload so that we can then grab the URL.
‫So get the URL here.
‫And so then we need to replace this part
‫with the actual file name.
‫So this one that we created here earlier,
‫and then also let's actually replace this part
‫with the super base URL
‫that we have stored in some other file.
‫So super base URL.
‫Now right, then let's again grab this error,
‫so error handling is very important,
‫but if everything went well,
‫then let's return the updated user
‫that we just received here.
‫Now all right, so that should be done
‫and so now it's time to consume this function here
‫in yet another custom hook.
‫So use update user dot JS
‫and here let's actually just grab the code from here.
‫So this is gonna be just very similar.
‫So let's get this and paste that here.
‫So use update user,
‫then here our mutation function is gonna be that one
‫that we just created.
‫So update current user.
‫Then here, let's call the function update user
‫and here is updating.
‫Then we no longer need this.
‫Here, let's then return update user and is updating,
‫and then finally, the query that should be invalidated
‫is just called user.
‫And here, let's also change the string,
‫user account successfully updated.
‫All right.
‫And so let's try this out here.
‫So maybe right here,
‫we get update user and we get
‫is updating from use, update user.
‫Okay.
‫And so here, let's just call that function.
‫And we pass in the full name and the avatar,
‫and first, we also need to make sure
‫that there actually is a full name.
‫So the full name needs to exist,
‫but the avatar doesn't have to.
‫All right, so let's try this out.
‫Let's try to change this to Jonas
‫and probably we should also use the is updating state here
‫to disable all our input fields.
‫So is updating and let's just grab this here,
‫and also on the buttons.
‫So let's try that, and well,
‫I'm not sure if anything is happening.
‫Let's reload that here,
‫try that again,
‫but still no result so maybe we have something wrong here.
‫Let's check out or handle submit function
‫and ah, indeed, here it should be
‫if there is no full name, then just return.
‫So then don't do anything.
‫All right, so that should work now, and nice.
‫So something is happening, and then indeed,
‫our user account was successfully updated,
‫and so now up here, we have the new user name of Jonas.
‫Nice.
‫Next up, let's then try to upload an avatar
‫and here, I will just use a cabin image again
‫because I don't really have any avatar here right now.
‫Let's also maybe try to change this to an upper case.
‫And so this should now take a bit more time,
‫but now it is finished.
‫Now here we didn't get that new image, actually.
‫Let's see what happens if we reload that.
‫And yeah, well there is the new image.
‫So it was apparently successfully uploaded here,
‫and so indeed, here it is.
‫So here's the avatar, then the user's ID,
‫and that random number.
‫Nice.
‫Now I'm not sure why that didn't change immediately.
‫Let's try to change these two things again.
‫Let's now try cabin image number one for this user,
‫and then update the account again.
‫And for some reason, it is not changing the image up there.
‫Let's see what kind of data we have here in our cache.
‫So which image we have there now,
‫and the only thing that probably has changed between them
‫is this random number.
‫So in our cache, we have this 088,
‫and so that apparently is the first one
‫that we had in the beginning.
‫So if we go back here to our bucket,
‫so if we close this,
‫yeah, then the new one is actually this one, with the 031.
‫So our cache hasn't actually really been updated.
‫And so let's do that manually in another way.
‫So now, as we left the page and came back,
‫then it did re-fetch all the data
‫and then it updated the image up here,
‫but for some reason, with the user,
‫it's not really working as intended right here.
‫So I re-invalidate the queries.
‫And so, this is a nice moment where I can show you again
‫how to update the data manually in the cache,
‫using query client dot set query data.
‫So here we can then manually set the user
‫to the user that we just received.
‫So let's grab that here.
‫So that's gonna be the user
‫and then user right here as well.
‫Okay, so we did the exact same thing earlier
‫when we logged in,
‫where we then immediately placed the new user in our cache.
‫And so here we are now going to do the exact same thing.
‫Now okay, but before we test this,
‫let's also here on this mutate function,
‫specify some things, and in particular,
‫the unsuccess handler.
‫So like we have done before many, many times
‫because here we now want to set the avatar back to no,
‫so back to the initial state,
‫but that actually won't be enough
‫to clear this name right there.
‫And so for that, we can actually do E dot target,
‫which is the form, and then on there,
‫we can call the reset function.
‫And so this is just standard HTML again.
‫Also, this cancel button that we have here
‫doesn't really work, I think,
‫because, I mean it did clear right here,
‫but if I changed something here, and I then want to cancel,
‫basically what we want is to get the initial name back here.
‫So let's also handle that event.
‫So clicking on that button,
‫so handle, cancel,
‫cancel we will call that on this button right here.
‫So handle cancel,
‫and since this button here actually has the type of reset,
‫which is an HTML five attribute,
‫this will actually not submit the form automatically.
‫So that's the reason why it did clear this file upload here.
‫And so we don't even need to do
‫any prevent default on this one.
‫All we need to do is to set the full name
‫back to the current full name
‫and set the avatar back to no.
‫So let's just briefly reload here.
‫So if I did something here and then canceled,
‫we went back to the initial name.
‫Now let's change this again and also change the image,
‫now here to number five,
‫and let's see if this time it updates immediately there.
‫Okay, so here apparently we got some error.
‫Now if we reload here, then we will see
‫that everything has been successful,
‫so the name and image have both been updated
‫because the error only happened here afterwards.
‫So only here in this unsuccess handler.
‫So let's see what we actually get here.
‫So let's then deactivate this part that we added,
‫then just log that data to the consol
‫'cause that's where apparently the error was.
‫Well, we actually do get an object with user,
‫so I'm not sure why that wasn't working earlier.
‫So let's check this again.
‫Maybe that was just an one-off error.
‫Yeah, so now actually that works,
‫so let's bring this back, let's change here again,
‫and then we have this other error.
‫So maybe we cannot do this one
‫and this one at the same time.
‫So let's try that just to make sure we reload.
‫Let's use another one just to make sure
‫and apparently we get the exact same error here.
‫So, let's just not do this then
‫and go back to just invalidating the queries.
‫So I will try to find out, offline,
‫so outside of this video, what is happening here,
‫and then maybe I will show you in the next video.
‫Now all right, so in any case,
‫this now works perfectly fine.
‫The only small issue that we had
‫was that uploading the file
‫would not immediately get reflected up here,
‫but then as soon as the data gets re-fetched at some point,
‫by re-add query, then of course,
‫that image will be updated there.
‫All right, and now let's do the update password form,
‫and in this case, actually,
‫I already have the entire form working
‫because it is actually exactly the same logic.
‫So here we have, already,
‫the update user that we created earlier,
‫and then here we use that update user
‫to pass in the password.
‫Now here, we are actually using, again,
‫that react hook form library
‫because that allows us to very easily
‫to this password verification that we did earlier.
‫So in this signup form right here.
‫So what I have here is actually pretty much the same,
‫so I just copied all this code from there.
‫There is just one thing that I'm seeing now
‫which is that we should actually also add
‫this on-click handler to the button in this signup form.
‫So,
‫yeah, this one right here
‫because even though this is a button with a type of reset,
‫this will actually only clear all the input fields,
‫but not the error messages.
‫But this builtin reset function,
‫so this function that is part of React hook form
‫will actually do that as well.
‫All right, so you can check out this code here
‫if you're interested,
‫but let's just go ahead
‫and also include this one on the page.
‫So update password form,
‫and so the function that we wrote earlier
‫should work now in the exact same way.
‫So here, I will now just write some new password,
‫so maybe let's make that a bit more explicit here.
‫So,
‫new password.
‫Then it goes to another line, so let's make it like this.
‫And so here, I'm now gonna use another password.
‫Let's see.
‫And indeed, that seems to have worked.
‫And so if I now log out here,
‫and remember that I'm using this email address,
‫so here is the new password with these eight characters,
‫and then here, let's try test at test.com,
‫and so apparently I got the wrong password there.
‫And if it doesn't work now, ah, but it did work.
‫So that was the new password
‫and so that means that this form here now also works.
‫Great, so after a long video,
‫we finally finished this very important part here as well,
‫and with this, we kind of finished
‫this entire authentication and authorization part.
‫And we didn't just implement the bare bones functionality,
‫but we went as far as even allowing some management
‫of the user account so our users
‫can even update their data here.
‫So congratulations once again
‫for finishing this very important part
‫that you will need in all web applications
‫that you're gonna build in the future.
‫And with that being said,
‫let's now move on to finally implementing
‫another nice feature which is a dark mode.