Reviewing Commit Suggestions0:05
All right, welcome back everybody. So before I get started on the tailwind and UI layout, uh, portion of the video, I'm quickly going to visit Code Rabbit and perform a review of our last commit. And you can see the suggestions are ordered by priority. So in this case it found two issues here in this case it found one. We're not gonna go over all of these because many of them are auto-generated.
We're not gonna go over all of these because many of them are auto-generated. But yeah, just as an example for you, I can take a look at idea and it looks like it found an issue here. Ah, yeah, this is fair. So it's saying, hey, you're using the enum for the default value for the database, but then when you cast, you're potentially casting an ENUM to an enum.
but then when you cast, you're potentially casting an ENUM to an enum. So they're recommending we either set it to pending and if I wanted to accept that I can apply it here and you'll see it makes that change. Or maybe what I would do instead is idea status I would do pending and then if I wanna grab the actual string value, I can do this instead. Um, that way, once again, these values specifically are isolated to this one file
Um, that way, once again, these values specifically are isolated to this one file and nowhere else, but nonetheless that is useful, right? Then for anything else like this one here, security issues, well this is valid but not valid at the same time. So in this case it's saying, Hey, your form request returns false for authorization, which means nobody is authorized. Well, we know that this is automatically generated and we haven't gotten to this point yet, but
Well, we know that this is automatically generated and we haven't gotten to this point yet, but nonetheless, if we were further along, this would be really good advice. Okay, so you get the idea. Um, generally as a rule of thumb, I will these days run code rapid before my commits. I will take a look at any recommended changes and uh, make the fixes. Cool. Alright, so let's get back to work.
Tailwind Theme Setup1:40
and uh, make the fixes. Cool. Alright, so let's get back to work. I'm now going to visit my resources CSS, app css, and you can see it's already configured for tailwinds. So, uh, it imports it. These are the files that could contain tailwind classes. And then here's where we can set up our theme. And just as a refresher, in tailwind version four, I can create CSS variables that are automatically converted into like, um,
I can create CSS variables that are automatically converted into like, um, color classes or background classes. So for example, if I said color blah to red, well then I would have a text blah, uh, utility class. I would have a background, blah, I would have a border blah class. Uh, it's really one of my favorite things of tail one four. Okay, so we're gonna set up a general theme or a color palette,
Okay, so we're gonna set up a general theme or a color palette, and you don't need to watch me do these by hand. I'm just gonna paste it in. So I'll do that now. And yeah, we just have a handful of, uh, variables for our colors, like the background color, the foreground, what does a card color look like, what is our border, um, what's the primary color? It's kind of a greenish glow. Um, and that's good. And so now for example, once again, I have a text primary
It's kind of a greenish glow. Um, and that's good. And so now for example, once again, I have a text primary that I can use if I can type, uh, within my views, which is great. Okay, so now here's what I'll do. Um, well actually before we do this, I wouldn't mind having a couple components that give us some starting, um, layout styles. So here's what I'll do. I'm gonna create a new folder
Creating CSS Components3:04
that give us some starting, um, layout styles. So here's what I'll do. I'm gonna create a new folder within here called components. And then within here I'll add a new file and we'll just do two to get us going. We'll have one for a button and one for general form styling. Again, kind of boring stuff that we don't wanna write out by hand. It's pretty horrible. So for example, for button,
that we don't wanna write out by hand. It's pretty horrible. So for example, for button, if I paste some of this in, yeah, like this is stuff we've all written a thousand times, right? I'm gonna have a class of button and just set a background color, make it a little rounded and notice how we are deferring to the tailwind variables here. So color primary, um, set the font size,
to the tailwind variables here. So color primary, um, set the font size, add a little padding, set a line height. Again, you've done this so many times. We have an outlined variant. We have a ghost variant. If the button and contains, uh, an icon, which is an SVG, make it left or right and add a little gap. Basic basic stuff. And we don't need to spend five minutes writing this out by hand.
And we don't need to spend five minutes writing this out by hand. If you wanna work along, this will be available in the source code though. All right, next I'm gonna do the same thing for my form. I'll paste that in. And once again, we're gonna have some basic classes for our inputs, for our labels and for our text areas. And again, just basic stuff, right? So the background color, we're gonna add a little
And again, just basic stuff, right? So the background color, we're gonna add a little border, we're gonna make it rounded. We'll set a default height. It's just to make it look a little more pleasing to the eye. It's not that interesting. Okay, so now we have these components. Let's go ahead and import them. And I can do it like this. I can say import. Let's go into the components directory and grab button.
I can say import. Let's go into the components directory and grab button. And a little tip here, I can specify which layer I want this to be included in. I do that via layer. In this case we'll set it two components. Yeah, so if you, if you're unfamiliar with this, it's just a way to tell Tailwind I can consider this to be a component. So nest it in the proper location so
to be a component. So nest it in the proper location so that utility classes like NT four margin top four will take precedence, right? And that depends on the order. And I'm gonna do the same thing for our forms. Alright, so that's set up and running. If I now boot up my terminal, I can run vets and this will start watching our project for changes and compiling.
Building App Layout Nav5:08
and this will start watching our project for changes and compiling. Alright, great. So now let's go into views and why don't we create a new, hmm, let's create a new components directory and then a layout folder and then a layouts that laid up HP file. So this can be our initial um, layouts. We'll call this idea and then later we can make that dynamic.
We'll call this idea and then later we can make that dynamic. I'm gonna set a background color of the background we set and a foreground color of the foreground that we set. And then here can say hello world. Okay? So now for example from the welcome page, I could replace all of this uh, with our layout. Alright, let's have a look in the browser now. Alright, and we do see hello world, but not any of our background color, right?
Alright, and we do see hello world, but not any of our background color, right? And of course that is because within our layout file we didn't specify a path to our CSS, so we're gonna use that V directive like you learned. It's within app css. Alright, so now this will handle the hot reloading as well. So back to uh, the browser, give it a refresh. And now we have the dark background
So back to uh, the browser, give it a refresh. And now we have the dark background and the light foreground. Cool, we're in business. Okay, so back to layout. This will be our initial slots, but also within here I'd like to add things like uh, our navigation bar and a maximum width, things like that. Okay, so I think maybe I should do this. Let's wrap this within a main section. And then above it I'm gonna have a navigation section,
Let's wrap this within a main section. And then above it I'm gonna have a navigation section, but personally I almost always extract navigation to its own component. So I'm just gonna do this ahead of time. I'll say let's reference our nav component as you see here. All right, so let's create that file nav blade PHP. PHP. Alright, so our initial wrapper will just be a nav where we have a border and then we set a maximum width and a dedicated height.
where we have a border and then we set a maximum width and a dedicated height. So yeah, right here we could have um, for example our logo, just call it idea for now. And then here maybe we could have the right side, um, sign up, register links, something like that. Alright, so if we take a look in the browser, ah, we have an issue. It looks like I referenced this incorrectly. Let's go into our layout file
It looks like I referenced this incorrectly. Let's go into our layout file and I'm sorry, it's layout nav, come back and yes, so now you can see we have this little border here, uh, but they're on top. So what I can do is return and say let's do flex item center, but justify between, and that will justify the distance between this guy and this guy. So effectively that makes this one on the far left
between this guy and this guy. So effectively that makes this one on the far left and this one aligned to the far right. So now this is kind of what we want. Okay? Alright, so back to our project. Now, behind the scenes, I've actually already added a logo here that you'll find just simple logo, PG very, very quick thing, okay, so I'm gonna reference that here. Images, the source is, um, we don't say slash public, we assume that's the route.
Images, the source is, um, we don't say slash public, we assume that's the route. And so we can go into the images and logo png and then I'm gonna hard code, maybe a width of a hundred or something like that. All right? So there you go. Now it's starting to look like a navigation bar. Looks pretty good. So in situations like this where we just have an image, we might wanna set some alternate text or an aria label
where we just have an image, we might wanna set some alternate text or an aria label and we'll just say idea logo. All right? And this will take us to the homepage. And then of course later, maybe we can turn this into a dedicated named route if you like. Alright, so that looks good. Next I'm gonna have some simple links here. One of them will be to sign N
Next I'm gonna have some simple links here. One of them will be to sign N and then another one will be to register. So maybe we'll swap these. This will go to register. This one will go to log in. All right, and maybe a little space in between those, let's say flex with a gap of five in between each. Yeah, that looks good. Uh, but next maybe the sign in button should be more or maybe register should be more prominent.
Uh, but next maybe the sign in button should be more or maybe register should be more prominent. So if we took that approach, I could just add that class of BTN that we worked on. So if I come back, yeah, that looks good. Why don't we set item center, you get the idea. Now our navigation is mostly complete. All right, cool. So next, if we come back into our layout file, this looks good. Maybe down the line if we have any mods,
file, this looks good. Maybe down the line if we have any mods, we could add them here, but our layout is in order. So now if I come back to welcome, this can be the homepage. Let's have a look at this. Come back, yeah, but notice it's right up against the edge. Let's fix that within my layouts. Why don't we on the main tag say, well, once again, let's set a maximum width.
Why don't we on the main tag say, well, once again, let's set a maximum width. We're gonna set the merchants to auto and then just a little padding and then push it down a little bit. Basic stuff, give it a refresh. And there we go. Yep. Now it's centered, uh, whether to add padding up top. There might be situations where we don't wanna do that. I'm not sure. We could either do it like this where we say, um, I dunno, py tin.
Creating Auth Pages10:08
I'm not sure. We could either do it like this where we say, um, I dunno, py tin. And maybe we can get away with that for now, but later we might, we might have situations where we don't want that padding, so we'll just figure it out. Okay, cool. So my next step is I want to add the initial forms for register and sign in. So here's what I'll do. I'm gonna go to my routes file and let's add some new ones.
So here's what I'll do. I'm gonna go to my routes file and let's add some new ones. Let's say route get register. And we're gonna use that convention of a registered user controller. So I'll call it registered user controller. Create. Alright, let's create that now, PHB Artisan make me a controller for a registered user. I'll keep that as empty. All right, let's import that switch over.
I'll keep that as empty. All right, let's import that switch over. We'll have our create method, and this is going to return a view to register, create. Or by the way, if you wanna stick with the auth convention for your views, that's fine as well. All right, we'll do that. So now we're gonna go into our resources views directory. We can add a new folder for auth and within there, yeah, maybe we'll change it to register.
We can add a new folder for auth and within there, yeah, maybe we'll change it to register. Yeah, so off register. All right, so once again, we reference our layout and this would be our register page. Alright, so if we come back, let's click on register and sure enough, we see our registration form. Alright, so at this point I want our registration form to be center aligned as you see something just like this. Alright, let's get going.
to be center aligned as you see something just like this. Alright, let's get going. So I'm gonna paste in just once again, just a little block to save us some time. We're gonna have a wrapping diviv that has a, a minimum height, which is basically the window height minus a little room for the navigation bar. And then right here, for example, I could say register now. So if I come back, there we go next though, let's style it properly.
So if I come back, there we go next though, let's style it properly. And this just makes it a tiny bit larger and bold. And then I'm gonna have sort of a, um, a subtitle or a description and we'll give that some styling as well. Subtitle goes here, all right, yeah, you get the idea. That looks pretty good to me. So how about this is register and account, and this is start tracking your ideas today. Cool. Alright, so now we need to add a form below it. Alright, so now we can add our form.
Cool. Alright, so now we need to add a form below it. Alright, so now we can add our form. It's gonna make a post request to register, right? Alright, so yeah, maybe each field will consist of a label and then a, an input to start. And let's make sure we add those, um, helper classes that we created back to the browser. And there you go. All right, maybe a little space there. So why don't we do this, I will add space y of two and that's just gonna add a little space in between them.
So why don't we do this, I will add space y of two and that's just gonna add a little space in between them. So now if I come back, yeah, just a little bit of breathing room there, which is good. Next on the form itself, we could probably add just a little space below it. Yeah. Okay, so imagine if you need to register, right? Well, what information do you need to provide? We need, let's say your name, email, address, and password. And that's probably good, uh, to get us going.
We need, let's say your name, email, address, and password. And that's probably good, uh, to get us going. Alright, so we have name, and then let's add the ID as well as the name. We'll add another one for email. Alright, so this will be what? Email. And email. And why don't we set a type of email in this case. All right, we'll do another one for the password And then the browser. There we go. Name, email, password.
And then the browser. There we go. Name, email, password. But notice there needs to be a little more space in between each of the, uh, form fields, right? So here's what I can do. Let's set space y of four. So four, a little bit of space in between each of the direct children, and this is what we get. Name, email, password. And then finally we need our submit button. So maybe right down here we'll have a button with a type
And then finally we need our submit button. So maybe right down here we'll have a button with a type of submit create account. There we go. It's right down there, but let's style it. So class of button, yeah, maybe a little more spacing, margin of two. Yeah, push it down and maybe a little bit larger. So notice I can add utility classes to override the default component styles.
So notice I can add utility classes to override the default component styles. And just as a refresher, that's available because I specified the layer that those components are created on. So now if I come back, yeah, is that right? 12? Yeah, 10. Maybe that's the default. No, it's not. Okay. So we'll stick with the height of 10 just to make it a little more prominent. Finally, do we want it to take up the full width? Maybe.
to make it a little more prominent. Finally, do we want it to take up the full width? Maybe. So, maybe not if we were say, width a full, that's, that's just a, that's that one's up to you, right? We'll keep it like that. Alright, so now we have some basic styles for a form, but I want this to be as reusable as possible. Uh, so with that in mind, why don't we do this? Why don't we create a brand new component within the component's directory.
Why don't we create a brand new component within the component's directory. Let's add a new folder for forms or just form, and then we'll have our master, uh, form layout file. Remember, if the component name is the same as the folder it's contained in, you can omit the directory name followed by the component name, right? It's assumed that that's the one you want. It's sort of like, um, if the file is indexed,
It's assumed that that's the one you want. It's sort of like, um, if the file is indexed, then you don't have to type it out. Uh, same, same sort of thing, okay? So what I'm gonna do here now is within register, I wanna reuse as much as I possibly can here. So I'm gonna grab all of this and go into form, paste it in. Of course, most of this cannot go in here, so this will be our slots. All right? Um, this would need to be dynamics.
our slots. All right? Um, this would need to be dynamics. So that'll be your title. And this can be your subtitle or description. Yeah, so this is sort of our centered form. We might even need to be a little more specific because if not any form, it is specifically the aligned to center form. But nonetheless, that works. So now think about it. Here's what I can do. This part is unique
But nonetheless, that works. So now think about it. Here's what I can do. This part is unique and this is unique and this is unique, but everything else is our layout. So what I can do is say X forms or form and yeah, notice I don't have to do this, it's the default, it's implied. Alright, so now I will paste in our original form and then how do we wanna do the title and the description? Well, let's just be explicit that we want a title
and then how do we wanna do the title and the description? Well, let's just be explicit that we want a title and a description and then we can reference those. Cool. So now within register, I just pass it through like this title register and accounts description. Start tracking your ideas today. Now if I come back, yep, same thing, but we have isolated or, or we're, we're allowing for a bit more reuse. We now have a dedicated form component. And by the way, if you wanna take this even further,
We now have a dedicated form component. And by the way, if you wanna take this even further, you could get the form tag itself into the layout and then allow some of this to be configurable. I'm not gonna do that in this case, but you can, you can have some fun with it. Alright, next, these are very similar. So these also are going to be their own, uh, components. So I'll add a new one here. And this represents a form field, right?
So I'll add a new one here. And this represents a form field, right? So once again, you take as much as you can, switch your component, paste it in, and then make it dynamic. That's the system we follow. So this would be our label, right? So let's make sure we accept that. In order to use this component, you need to give us a label. Next we need to know the input name effectively.
In order to use this component, you need to give us a label. Next we need to know the input name effectively. So this would be name, and let's make sure we pass that in as well. All right, next. This also would be the name. Cool. So notice we're just making it dynamic, one step at a time. Um, next, let's allow any attributes you pass in to be merged here. So we'll do attributes. Um, yeah, that looks good.
let's allow any attributes you pass in to be merged here. So we'll do attributes. Um, yeah, that looks good. So yeah, remember you can add your attributes to the top layer, which is most common. But in this case, if I'm referencing a field and I need to override something, I think almost always it would be something on the input itself. Um, but you can configure this if you need to. Alright, so let's test some of this out.
Um, but you can configure this if you need to. Alright, so let's test some of this out. Now, um, let's comment that out. So now we no longer have a name and let's try to replace it with our form field. The name is gonna be name, what is your name? And the label is gonna be a formatted version. And now we got the same thing. Great. So we can remove this entirely. And yeah, notice we're just slowly cleaning things up.
So we can remove this entirely. And yeah, notice we're just slowly cleaning things up. So I have a field for name. Now I can have one for email, but next, notice that ideally I wouldn't type of email. Here we get some, some conveniences out the box. So for example, let's bring this back. If we didn't have this, then this will be formatted to expect an email, right? But if I bring this back,
to expect an email, right? But if I bring this back, well now it's just a plain old text area, so we should allow that to be configurable. Notice the type is not, so let's set the type but default to text, but you can override that if you need to. Cool. All right, so finally we need something for password. By the way, this will be email and this will be a type of password to obscure it.
By the way, this will be email and this will be a type of password to obscure it. Password and password, alright, so yeah, notice it's just a little bit more work, but it pays dividends right now whenever I need to create a centered form, this is pretty easy to take in. And then later, if I ever need to tweak how we present a single form field, I have a dedicated file I can visit.
how we present a single form field, I have a dedicated file I can visit. And swer alert, we will be tweaking this a little bit to support errors and, and old, uh, input and things like that. Cool. So now let's, let's take one of those dividends, right? Let's duplicate this and this will be our login file. So notice I can say log in, be here.
So notice I can say log in, be here. Glad to have you back. And yeah, let's just think about how you would log in. Well, from our routes file, we would need to set up, uh, a route to log in. And once again call it login controller, if you want call it sessions controller. Uh, if you liked, uh, the more restful version, a little more traditional, anything you want.
Uh, if you liked, uh, the more restful version, a little more traditional, anything you want. All right, so I'm gonna make a controller directly from my editor. This will be sessions controller, and it's just a basic controller. All right, method create. And this is all related to auth, so I'm gonna store it. And within that auth folder, or again, if you want to be strict
And within that auth folder, or again, if you want to be strict and follow the name of the controller, you could do sessions create, that would work as well off login. Cool. All right, so are we on the same page? We now have a new route for login that will load the sessions controller, uh, in a create action. The create action loads, the login view.
uh, in a create action. The create action loads, the login view. The login view displays a form to log in. And you of course the login, we just need your email and your password. That is gonna make a post request to log in, Sign in, whatever you wanna call it. All right, so let's have a look in the browser. Here is our homepage again, we have one for register and we have another one for sign in.
Here is our homepage again, we have one for register and we have another one for sign in. Yeah, so notice in this case it is not perfectly centered. Sometimes this can be a little tricky and I think it is because of the padding that we applied to our layout file. So let's see, if I were to remove this entirely, come back. Yeah, that's a little better. It can be a little tricky though sometimes, right? Maybe there's a little margin here.
Implementing Auth Controllers22:25
It can be a little tricky though sometimes, right? Maybe there's a little margin here. I'll figure that out on my own. Nonetheless, this is looking pretty good. Okay, so now I just wanna wrap up by quickly, uh, implementing the controller logic. And this is all a recap, so I'm gonna go very fast. Let's go to a routes file and why don't we implement registered user controller. This will be a store action,
and why don't we implement registered user controller. This will be a store action, and this is where we create the stored user. All right, so let's accept the request and let's validate the form. So for your name, yeah, this is pretty basic stuff. We'll, it should be a string. You could have a minimum number of characters if you want like a minimum of three maximum for the, uh, the field type.
of characters if you want like a minimum of three maximum for the, uh, the field type. Uh, I do want this to be required. You get the idea. All right, let's do another one for email. This is, uh, also required. It should be of type email. We can just add a minimum number of character. It's a little bit superfluous though, uh, because this will take care of it. We'll add a maximum number of characters and then I am gonna add a rule.
We'll add a maximum number of characters and then I am gonna add a rule. So let's do eliminate validation rule should be unique on the user's table and specifically the email field. So this is gonna make sure that when you register there isn't already an account that has this particular email address. The one you provide us has to be unique in our database. Otherwise, you probably already have an account, in which case you should log in instead.
Otherwise, you probably already have an account, in which case you should log in instead. Alright, and then finally let's do one for password. Yeah, so remember, um, we can declare this here or you can reference your password defaults if you wanna store them, uh, elsewhere. For now, just inline is cool. Alright, so assuming all of the validation passes, we can then of course create the account. So let's do it. Let's say user create. All right?
we can then of course create the account. So let's do it. Let's say user create. All right? So we want the, uh, name, so that'll be request to name. And then let's duplicate this and we'll do another one. This will be the email and then finally the um, password. Cool, but now what about encrypting the password? Well, I'm gonna show you two ways to do this. So for now we're just gonna say we do need to encrypt it or decrypt it. Um, but we're gonna come back to that in just a second
to encrypt it or decrypt it. Um, but we're gonna come back to that in just a second because I wanna show you something. Anyways, next we're going to log in the user using the off facade. And then finally let's return a redirect back to the homepage, um, with a success message. So we're gonna throw something into the session, uh, or we're gonna flash something to the session
So we're gonna throw something into the session, uh, or we're gonna flash something to the session registration complete. Cool, pretty standard stuff. You will write this quite a bit in your layer of L career, okay? So I wanna test this out without, uh, decrypting the password to see what we get. John doe john@example.com. I will type out password, create the account,
John doe john@example.com. I will type out password, create the account, and oh, looks like we forgot to create the route. Cool. That's our next step. And we'll say, all right, listen for a post request and that'll hit the, uh, store action. And then I'm gonna do the same thing while we're here for posting to the login controller that will hit a store action. All right, let's give it one more shot.
that will hit a store action. All right, let's give it one more shot. Register, fill the fields, create the accounts, but looks like it redirected back, but I don't have any information because we don't display the validation errors. Alright, let's do that Now register. And this is a great candidate for visiting our field and we can add them directly here. Alright, so we learned in the validation episode
and we can add them directly here. Alright, so we learned in the validation episode that we can say, well, if we have an error for name or email or the variable passed in, then we can display it. So we'll say, gimme a paragraph, we'll give it a class of error and this will be the message itself. Okay? So now we can actually see why the validation failed. Let's give it a shot. Once again, John Doe give it a password, create the account, it fails,
Let's give it a shot. Once again, John Doe give it a password, create the account, it fails, it redirects back, and now we can see, okay, we already have a John toe and also the password is incorrect. Cool, so now let's just start from scratch. We'll do myself Create the account and it works. We don't have any feedback yet, but sure enough, we are signed in and yeah, take a look.
We don't have any feedback yet, but sure enough, we are signed in and yeah, take a look. If we go to users, here's some of our test users from earlier, uh, we can get rid of all of these, but I want you to notice that Jeffrey Way has a password that is already encrypted. And if you're kind of a longtime Laravel user, this will be very confusing because we didn't manually encrypt it and we didn't set up any kind of a mutator.
because we didn't manually encrypt it and we didn't set up any kind of a mutator. So as it turns out though, in the latest version of Laravel 12, this is done for you by default. And here's where if I return to my user model and scroll down, you'll see there is a new cast called Hashed. So this means whenever I assign a password, user password equals fubar, whatever. Well, when it gets persisted
password equals fubar, whatever. Well, when it gets persisted or say to the database, it will be hashed. Okay? So now that happens for you automatically. There's no reason any longer to manually run B Crypt on your password. Um, that will be taken care of for you and that's really good to know. Okay, so now I'm gonna return to my run file and do just a couple things.
Okay, so now I'm gonna return to my run file and do just a couple things. Let's add some middleware here. So in order to register, you need to be a guest, right? In order to submit the registration form, you also have to be a guest. In order to log in, you have to be a guest. But also, why don't we add one for logging out? So once again, in these situations, I don't think it's that necessary to be restful if you wanna try
So once again, in these situations, I don't think it's that necessary to be restful if you wanna try to submit a delete request to sessions, okay? Uh, but also sometimes it's like you don't have to take it that far, just do a post request to log out and you can be done. So to log out, of course you need to be signed in, okay? Looks good. So why don't we now update our navigation links and we can say, alright, well if you are signed in or we've learned that we can use auth, right?
and we can say, alright, well if you are signed in or we've learned that we can use auth, right? So you could say, here's my auth routes, here's my guest routes. That would work as well, or add an if statement, whatever you want. Okay? So now if I switch back, you'll see nothing here because we're currently signed in. So at this point we might wanna have a logout button. So let's just add that in right here.
So at this point we might wanna have a logout button. So let's just add that in right here. This is like we said, it's gonna make a post request to log out. Log out. All right. Now if I click on it, oh, call to undefined method destroy. Yes, of course, let's go ahead and implement that by saying Destroy. And this would just be off log out And yes, it logs this out.
And this would just be off log out And yes, it logs this out. And the only remaining step, of course is to redirect back to the home page as you see here. And there we go. Alright, so this video's running a little, little too long, but we got a lot to cover folks. We got a lot to cover, baby. So we're just gonna wrap up by implementing the sign in logic. I wanna sign in as John,
by implementing the sign in logic. I wanna sign in as John, however, when we submit this, we haven't actually implemented the logic yet. So if I go into Sessions controller, yep, we need a store action to handle this. Alright, so the first thing is let's validate the request as always. So this time I'm just gonna paste in basically the same request validation as we were performing before.
So this time I'm just gonna paste in basically the same request validation as we were performing before. Or again, that can be extracted into a dedicated form request class, which we might do. Alright, so now to sign in, we're gonna make sure you give us an email address. Uh, you gotta give us a password. Some people like to add a password confirmation field. You can consider that a good practice. Lately I've just been ignoring it.
You can consider that a good practice. Lately I've just been ignoring it. Uh, like I said before, sometimes the bigger thing is people forget what their email address is, almost more than their password itself. But sure enough, if you want to confirmation, you can add that in. Alright, next, let's attempt to log the user in. And this will be the attributes.
Alright, next, let's attempt to log the user in. And this will be the attributes. So let's just pass these attributes and if the attempt was successful or signed in, we can redirect them with a welcome message. Otherwise it failed to authenticate, in which case we should redirect back. So with that in mind, I, I would almost prefer this to be a guard. Let's do the failure scenario first.
I would almost prefer this to be a guard. Let's do the failure scenario first. If we couldn't sign in, then let's return a redirect back. Or by the way, there is a back helper function that will do the exact same thing. It sends a redirect back. So if you like that, you can do it instead. I'm gonna send through uh, any validation errors and I'm also gonna send through the inputs. The input is what the user typed into each of the inputs
and I'm also gonna send through the inputs. The input is what the user typed into each of the inputs and I wanna make that available to them so they don't have to retype everything from scratch. Alright, so now for the errors, why don't we just do this. Let's set our own errors and we'll say for the password, and I'll paste this in, we'll just say we were unable to authenticate using the provided credentials. We're not exposing any more details than that. Whatever you gave us, we're not gonna tell you, Hey,
We're not exposing any more details than that. Whatever you gave us, we're not gonna tell you, Hey, there is no email in our accounts or in our database. We're just gonna say, yep, that that didn't work. Okay? Otherwise, if it did succeed, then as a good practice, which we've learned, let's regenerate the session. So let's go to the session and call, is it regenerate? Yes, that's good security precaution and then redirect wherever they should go. How about return a redirect to where the user intended
and then redirect wherever they should go. How about return a redirect to where the user intended and we'll just default to the homepage. And then I'm gonna send through a success message. You are now logged in. All right? Again, pretty standard stuff that you're gonna see over and over again. So when I log in, I validate the request, I attempt to log them in. If I couldn't, I go back to that form
I attempt to log them in. If I couldn't, I go back to that form and say, Hey, couldn't do it. We pass through the input. Otherwise, if we succeeded, then we return the session and then we sent the user either where they were trying to go before they hit the login form or to the homepage, and then we send through a success me message itself. Okay, so back to the browser, let's try to log in. Ah, and it fails and we do see the
Okay, so back to the browser, let's try to log in. Ah, and it fails and we do see the validation error, which is great. Now I already know the issue, but also notice that we lost our input here even though we passed with input when we redirected back. And that's because when it, it's not magical, you still have to reference that value. So notice how nice this is
to reference that value. So notice how nice this is because our form field is its own component. I know exactly where to go to update that. Okay? So right here I'm gonna set the initial value equal to uh, the old value that came from the previous request. So gimme the old value for name or once again, I'm gonna use the variable name and then I can also set a default as the second argument.
or once again, I'm gonna use the variable name and then I can also set a default as the second argument. In this case, I don't have one. So now check this out. We fail the validation and this time it remembers the email address and that's because of that old function call. Okay? So anyways, this time I'm gonna do it properly and I'm signed in. Okay, so I get it. That was a long video, perhaps too long,
Okay, so I get it. That was a long video, perhaps too long, but we have a lot to cover, right? Nonetheless, we learned about some tailwinds set up. We created some initial CSS variables and components. We set up our layout file, our navigation, we set up our form styling, which takes a little bit of time. We set up our authentication and the controllers really quite a bit here
We set up our authentication and the controllers really quite a bit here and we're gonna keep going in the next episode.
