Real-Time Messenger Clone: Next.js 13, React, Tailwind, Prisma, MongoDB, NextAuth, Pusher (2023)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there my name is Antonio and welcome to this comprehensive tutorial where we'll embark on an exciting journey to create a state-of-the-art real-time messenger clone using some of the most powerful and cutting-edge Technologies available today in this video we'll cover a wide range of features that will help you build a fully functional and Visually stunning chat application first we'll harness the power of next 13 utilizing the app router for efficient routing and dynamic page rendering next we'll dwell into react for building reusable components that will form the backbone of our application to create a modern and Visually appealing design will employ Tailwind CSS and headless UI which will allow us to create a Sleek user interface while ensuring a seamless user experience for our backend we'll combine the robustness of Prisma with the flexibility of mongodb to create an efficient and scalable database solution this will ensure that our app can handle a multitude of users and conversions with ease in terms of security we'll incorporate next out to manage user authentication and protect the sensitive data we'll also enable social login using popular platforms such as Google and GitHub making it easy and convenient for users to sign up and log in to bring our messenger clone to Life we'll Leverage The Power of Pusher for real-time messaging and notifications creating a truly immersive and interactive experience for our users for image upload we are going to use cloudinery and finally we'll explore react hook form for efficient form handling ensuring that user input is managed seamlessly throughout the application and in the end you're going to learn how to deploy all of this on Virtual so buckle up and get ready to level up your web development skills as we dive into this feature-reach tutorial and create a messenger clone that Rivals the best in the industry so let's go ahead and head into your terminal and we're going to use the npx create Dash next Dash app command to initialize our new next 13 project and in the newest update you can actually use the flag dash dash Tailwind to initialize the project without need to manually configure Tailwind which I think is a great thing and we're going to use that today so let's go into our terminal and let's run MPX create next Dash app at latest dash dash typescript dash dash hail wind like that and press enter press yes and let's name our project in my case it's going to be messenger Dash clone for the S linked option select yes for the source directory select no for the experimental app directory make sure you select yes because we're going to use the experimental app directory in this project for the import Alias you can just press enter and that is going to start installing all of the packages we need for this project great and now that this has finished you can actually go ahead and you can open your newly created uh messenger clone folder right here or whatever you named your project so I'm gonna click open here and I'm gonna see this new structure that we have as you can see we already have tailwind.config.js configured for us right here along with some theme options here and we also have the post CSS these are the things we usually had to build ourselves so without further Ado let's actually go into the terminal and let's start this project to see what we're actually working with so go ahead and run npm run Dev and press enter and now you can go ahead and go into localhost 3000 in your browser and refresh or press enter if you haven't already wait a couple of seconds and you should be able to see the new next 13 welcome screen great and now you have the new next 13 welcome screen what I want to do next is I want to clean this up a little bit uh so because we we're not gonna need any of this here so I'm just gonna collapse the terminal right here and I'm gonna go into the app folder and here we're created with the layout and page.dsx files so let's check both of them out so inside this home right here what you can do is you can just remove everything uh except the return function so just go ahead like this and just remove everything and instead of this I'm just going to write a simple div and I'm going to write a paragraph which is going to say hello messenger like this and you can just save the file great and now you can see I have this hello messenger text right here so I'm doing this in the page.dsx file right here great now the layout can stay as it is so in the layout file you can edit the metadata if you want you can edit the font uh nothing else to do here so let's go ahead in this metadata if you want to you can change the title to messenger clone for example and you can change the description to messenger clone as well and in a couple of seconds after this hot reloads you can see that my tab name has changed to messenger clone great so what we've done so far is we edited the page.tsx file to be a very simple hello messenger home function and the layout well we just modified the metadata the rest can stay the same and great uh what I want to do now is I want to go into globals.css right here and as you can see we have some predefined Styles here uh we're actually not going to need any of these so let's go ahead and you can remove everything except the Tailwind directives right here so just make sure you clean it like that and now let's go ahead and write some additional classes which we are going to need here so go ahead and write HTML comma body comma root like that and just write height 100 percent great and you can go ahead and save the file and your screen should turn to White maybe it already was white perhaps it depends uh on the dark and light mode in your system but when you remove all the Styles and write your globals.css file like this it should look something like that great and now you can go into tailwind.config.js right here here and you can actually remove this extend object is in its entirety like this you can just make sure it's an empty extend because we're not going to need any of those uh gradients that are defined great amazing amazing job and now just to test out if everything is working fine let's go into app into page.esx right here and let's try and give this text a color and increase the font size so I'm going to go ahead and write class name is equal to text Dash uh Sky Dash 500 and text-3 Excel for example and as you can see when it hot reloads it changes uh the way our page looks great amazing amazing job and you can also remove this import image from next image at the top because we're not gonna be using it and the same goes with the inter font so your page.tsx file can be a very simple function home which just returns 8 div which has a paragraph inside with a two very simple class names using Tailwind great this saved us a lot of time usually we had to Define Tailwind ourselves great great job all right so now let's go ahead and let's start creating our authentication screen which is going to be routed at the slash path so this initial localhost 3000 is actually going to show our authentication screen and if we are logged in it's going to redirect it to slash conversations or slash users great so what I'm going to do is I'm gonna shut down uh my project right here so I have it running but I'm going to shut it down because we're going to modify this a little bit and I just don't want to cause any problems so we're gonna write our authentication screen inside this page.dsx but I don't want to keep my initial page.sx in the root of the app folder I want to have it in a separate folder and there is a cool way we can do that by creating a new folder and write parenthesis site inside this is the equivalent of an indexed folder app like that great and now what I'm going to do is I'm gonna copy everything inside page.dsx like that and I'm going to create a new file inside the site folder called page that ESX just like that I'm gonna paste this here and we can change hello Messenger to hello index page like this great and now that I have this app uh parenthesis site folder inside with page.tsx here I can actually go ahead and remove this app page.dsx like that and now I'm gonna go and head into my terminal again and I'm gonna run npm run Dev and I'm just gonna refresh this and in a couple of seconds we're gonna see if we did everything correctly great as you can see we now have Hello index page great so that means that now we can safely work inside this parentheses aside folder and treat it like it's the root of the app folder great so let's go ahead and I'm actually going to remove this inside and at this top div I'm gonna give it a couple of class names so I'm gonna write the following I'm gonna write Flex Min Dash H dash full Flex slash call justify Dash Center ey dash 12 SM bx-6 LG px-8 DG Dash gray Dash 800 like that and you can see that we have this uh grayed out uh background now perhaps it's not so visible for you but it is a tiny bit less visible than fully white now you might be wondering why do I have this color block right here and how come when I cover when I hover my cursor on these classes I can actually see what they mean in CSS if you want to have the exact same effect you can go into your extensions right here and make sure you install the Tailwind CSS intellisense extension like that and then you're gonna have the exact same thing that I am you're also going to get a bit of autocomplete as well and this is very useful if you're interested in what specific Tailwind class does you can just hover and it's going to show you the exact CSS and it's also going to convert this Ram values to pixels for you to easily understand what they are great now inside of this div let's create another div and let's give it a class name of SM mx-out photo SN W-4 and SM Max W MD like that great and inside of that we're going to add our messenger logo so before we do that we actually need to get an image and to do that uh go into my repository the link is in the description or you can Google a messenger logo or any other logo if you want to and you can go into my repository go into public right here go into images and logo.png and you can just go ahead and download this image great and now we can go into public you can create a new folder right here called images and you can drag and drop logo inside and make sure it's not named the logo 4 or logo 2 this will happen if you already have logo files in your download folder so just make sure you rename it hook to logo.ng like that and now we can go back into app folder parenthesis site folder page.dsx right here and you can actually import the image component from next slash image so import image from next slash image like this great and it's a self-closing tag just like that so first let's give it an out an opt is going to be our logo next we're going to give it a height of 48 we're going to give it a bit of 48 as well sorry 48 like that and we're going to give it a class name of nx-auto w Dash Auto as well and we're going to give it a source of Slash Images slash logo.ng like that and that is gonna be it you can save the file and head back into your messenger clone and you can see we have a nice centered little image of our messenger logo right here great and just below this image right here I want to write a paragraph called H2 sorry a heading H2 like that and I give I want to give it a couple of class names so I'm going to write class name and inside I'm going to write empty-6 text Dash Center text Dash 3XL Pond Dash bold tracking tracking Dash kite and text Dash gray Dash 900 and inside of that heading I want to write sign in to your account like that great and now we have this signed into your account text here and perhaps your text is a bit smaller that is because I have zoomed in my screen to 150 so perhaps it's gonna look uh something like this and outside of this div you can for now just write a comment uh because this is where we're going to put our out form in the next part like that great so let's recap what we did so we had our page.dsx file inside of our app folder and it served as a root file but because I want to keep this in a separate folder because we're going to have a new folder inside of that called components and perhaps something else scattered around I want to keep it structured inside this specific folder so that's why I moved the page.tsx inside this special convention named parenthesis a site folder which serves the exact same purpose and it's treated like a root file we also added an image of our logo.png and we use that in page.tsx right here great great job so let's go ahead and let's continue with the development of our out screen so in here we wrote the comment out form let's replace that and write the actual component I'll form like this and if you save we're going to get an error because out form is not defined so what I want to do is I want to create a components folder inside this site folder right here let's go ahead and write components like that and just write out form that's ESX like that and I can just go ahead and create a very simple out form component like this with a div out form like that great and you can save that and then you can go back into your page.dsx and you can import it from dot slash components slash out form like that and if you save the error should go away great and now we have this little text out form right here which comes from this out phone component great so let's go ahead and let's write something at the top we're going to write use client the reason we're going to write use client inside of here is because we're going to make this out form interactive we're going to have inputs we're gonna have buttons we're gonna have some use effects we're going to have a bunch of things which are not compatible with server components so we have to Define use client at the top so next 13 knows okay this is a client component I'm not gonna treat it as a server component great so now let's go ahead and let's go into our terminal and I want to do something I want to install a couple of packages so I'm gonna go and I'm going to write npm install and I'm going to write react Dash icons also I'm gonna write um react Dash hook Dash form and I'm gonna write c c l s x like that great so these are the three packages we're going to install it's going to be uh react Dash icons it's going to be react cook form and clsx like that and you can just press enter and wait a couple of seconds for these to install great and you can go ahead and run npm run Dev again make sure you refresh after you run npn run Dev great and just wait a second uh for this to load again great and now we can go back into outform.tsx right here and just change something to ensure everything is working fine great it changed for me immediately so everything is fine all right so what I'm gonna do next is I'm gonna create a state here called variant so I'm going to write const variant and comma set Florent from U.S state like that and you can import your state from react like that and I'm going to Define types for this variant so I'm going to write type variant is equal to either login or register like that so this is a pipe symbol right here and we're going to use this variant to define the possibilities of this eu's state function here so it's going to be variant and the default option inside of it you can already see how typescript autocompletes for us so it's either going to be login or register I want to make it default to be login like that great now let's go ahead and below that we're going to write another state honest is loading set is loading like that also use State and default is going to be false we're going to use this to disable our buttons and inputs after we have submitted our form great now let's write the function which is going to toggle between login and register warrant so I'm going to write const toggle variance like that is going to be a use callback function so we memorize this function go ahead and write an arrow function inside of that and what I'm going to write is I'm going to change the variant depending on the current state of the variant so I'm going to write a very simple if Clause if variant is equal to log in in that case we're going to go ahead and write set variant it's going to be register great otherwise it's going to be set variant login like that great and in the dependency array make sure you add the variant variable like that great now below that we're going to create our react hook form submit function and other functions so go ahead and write const you can create an mg or empty object for now and write equals use form which you can import from react Dash hook Dash form which we installed just a minute ago great and now let's Define the types for this use form so you can go ahead and open these pointy brackets here and inside of that you're going to write field values and you can import field values from a react hook form as well like that great and now you can open parenthesis here and open an object inside and go ahead and write default values like this and you're going to write name and give it an empty string you're going to write email give it an end a string and password and give it an empty string as well so these are going to be the default possible values in our form so obviously if we are registering we're going to have name email and password but if you're logging in we're just going to use email and password and now in this empty object you can actually extract some functions so we're going to extract register we're going to extract handle submit and we're going to extract form State and we're going to structure it immediately and just State errors because that's all we're gonna need from the form State great you can go ahead and save that nothing much should change because this is just some logic which we've written here for us great now what I want to do is I want to write our on submit function which for now is not going to do anything uh so go ahead and write const on submit and give it a value of submit Handler which you can import again from a react Dash hook Dash form so I'm just gonna collapse this so you can nicely see everything so so far we've we've imported use form submit Handler and field values from react Dash hook Dash form right here great and inside of this submit Handler you can open pointy brackets again and just write field values again like that great it's going to be an arrow function which for the first parameter is going to accept data so just go ahead and open the function like that and inside first thing we're going to do is we're going to change this set is loading to be true because obviously if we are submitting that means we have to enable our loading so go ahead and write set is loading to be true like that great and now I'm just going to write a couple of empty if Clauses because for now this unsubmit is not going to do much because we know we have no Prisma we have no database we have no routes ready but let's just write a placeholder for what it's going to be so go ahead and write if variant is equal to register just write a comment axis register so in the future we're going to make an axios call to our register route and below that you can write if variant is equal login and you can just say a comment next out sign in because we're going to use a library called maxed out and we're going to immediately use its sign in function here like that great great job all right and below that we're also going to create another function which is going to be called social action so const social action is also going to be a narrow function the first parameter is going to take is action which is a type of string like that and all it's going to do is also going to set is loading to true and we're going to write a very simple comment next out uh social sign and great so we have defined placeholders for everything we're going to need and now we can start and style our form great so go ahead and remove this inside of this div and for the first one uh let's give it the following class names so class name is going to be empty-8sn and x dash Auto SM W Dash full SM Max W Dash MD like that great now inside of that you can write another div just like this and you're going to give it another set of class names so class name here is going to be BG Dash white px-4 py-8 shadow SM rounded LG and snpx-10 great and if you save the file you're actually going to see a little box here in which where we're gonna add our inputs our buttons and some other text great so now inside of this new box that we created so this div go ahead and write the form element great you can actually remove the action because we're not going to use it in the PHP way we're going to use it in the react way and let's give it a couple of attributes so we're going to give it a class name of space Dash Y dash six and we're going to give it an on submit function of handle submit which is going to wrap our on signage like that so where do we get the handle submit from and what is on submit so our handle submit function right here is exported from use form and our handle submit is going to wrap our own submit function right here so why does that work that way well that is how we get the data from this react hook form that's the only reason we need to write uh wrap this on submit inside handle submit because if we just wrote on submit here technically yeah this function will definitely get triggered but guess what we will not have this data because there is no way this form can actually know for it that's why we have to write handle submit inside parenthesis on submit like that and then this handle submit is going to pass that data right here and we're going to be able to use it and send let's do our server great and now inside of this form we're going to create our input component so let's go ahead and write input just like this and if you save of course we're going to get an error because input does not exist so to fix that I want to go ahead into our app folder right here uh and I want to go uh and create a new folder called components so this components folder is not going to be tied uh to the app folder like sorry to the site folder like here it's going to be in the root of the app folder inside and inside of that components folder we're going to create inputs folder like that great and inside of that you can go ahead and create a new file input.psx like that great so you should have the app folder the components folder the input folder inside that components folder and input.tsx inside great and let's just quickly fix this error so I'm going to write a very simple input component here and it's going to return 8 div which says I am an input like that great and now we can go back into the site components out form right here and you can import that from add slash app slash components inputs input like this so you can see how my project use the add sign if you're wondering where that came from that is during our initialization where we defined an alias I told you to just press enter that defaults to this add sign so if you just press enter you can write it exactly like this and it's going to work for you but for if for any case this is not working for you you can use the good older regular dot dot slash dot dot slash component lens slash inputs slash input like that just in case it doesn't work for you but feel free to use the uh add app sign as well great so you can either do it like that or you can do it so I'm just going to demonstrate here I'm going to rename this to input 2. and instead of this I'm going to use add slash app slash components and you can see that it leads uh to this input that we created great so I'm gonna go ahead and save this and great our error has gone away uh the uh the the error is not here anymore great now let's go back into our components input folder input.tsx file and let's actually uh make this functional so first things first make sure you write use client at the top because input is going to be interactive next thing we're going to do is we're going to import clsx from clsx like that which is a package we installed earlier great now you're going to import field errors comma field values and use form register like that from react Dash form like that perfect now let's write the types for our input so interface input props is going to have a label which is a type of string is going to have an ID which is a type of string it's going to have a type which is an optional type of string it's going to have the required Boolean like this which is also optional so we don't have to always pass it we're going to have the register which is required and the type of register is use form register open pointy brackets and write field values like that great now we're going to have also an errors object which is the type of field errors which we have imported from here and we're going to have disabled which is optional Boolean like this perfect now let's go ahead and let's assign this input props to this input right here let's go ahead and write react.fc open point in Brackets and you can just copy input props and paste it right here and now let's destructure all of these values so label ID type required register errors and disable like that perfect now let's go ahead and let's actually start styling our div great so inside this div instead of the text we're going to have our first component uh sorry our first element which is a label the HTML html4 is going to be uh targeting our ID right here which we have in our props and the label he's also going to have a couple of class names so let's go ahead and give it that first before we start writing anything else so last name is gonna have block text SM Bond dash medium leading dash six Dash gray Dash 900 like that and we're gonna have uh uh the text we're gonna pass inside is label like this great so right now nothing should happen but if you go back into out form the TSX and pass in the label here for example email you can see that we have a little label right here great great job all right and now just below that we're gonna write our actual input but before we do that we have to install another package called Tailwind CSS form so let's go ahead and let's go into our terminal again and I recommend shutting down your application for now and go ahead and write npm install at Tailwind CSS Dash forms like that and just press enter and wait a couple of seconds for this to install great and now before you run the application I actually want you to go into tailwind.config.js right here and you can go into plugins you're going to write require and inside you're going to write at failing css-forms which we just installed and you can write you're going to open this function like that and you're going to immediately return an object inside you're going to write a strategy class like this so make sure in your tailwind.config.js in the plugins array you require the newly installed Tailwind CSS Dash forms and the strategy you use is class I'm going to explain that in a bit now when we will write in the classes so go ahead back into your terminal and just make sure you run npm run Dev again and before you start developing always make sure you refresh your page so everything is up to date great and now I'm gonna collapse this terminal and I'm gonna go back uh not into out form but in our input component so go ahead in the components input folder input right here and just below this label you're going to create another div right here didn't give it a class name of empty-2 and inside you're going to write the uh Native HTML input component like that great it is a self-closing tab and we're going to give it a couple of attributes so first let's give it an ID which is an ID a type which is type let's give it an autocomplete ID like that disabled disabled and now we're gonna open an object and we're going to spread our register a function like that and the first parameter is going to be ID and the second is going to be an object and we're just going to write required so this is equivalent of writing required required but we're going to use a shorthand because the key and the value is the same great if you save you're actually going to get an error but don't worry we're gonna fix that in just a second so the way you fix that is you go back into your out form right here and what do you do well you just pass in the register prop and what do you pass inside well this register which really structured from use form so just go ahead and pass register like that and that is going to fix your error and now uh yeah we have not passed the ID so also make sure you pass the ID email like that great no errors now so make sure you pass the ID make sure you pass the label and make sure you pass the register like that obviously it's a red underline because it's missing a couple of more things here but we're gonna do that in a moment for now let's head back into components slash inputs folder input right here and let's continue developing so I'm going to write a class name here and it's not going to be a string it's actually going to use our clsx which we imported right here at the top so the this clsx is a library which allows us to dynamically use our classes so go ahead and open parenthesis here and you can either write all of this in one line like this using the normal parenthesis but I'm going to write in multiple lines so I'm going to use this back text so I can collapse classes like that again you don't have to do this so feel completely free to just write classes like text SM uh all in one line if you want to but just for the sake of this tutorial I'm going to use back clicks so I can safely collapse this into multiple lines if you want to you can use backticks as well but it's not required the first class I'm going to give it is form Dash input and you can already see how we have this uh a little box right here so this form Dash input usually does not exist in Tailwind so why does it work for us well that is because if you remember just a couple of moments ago we installed the Tailwind CSS slash forms package and we added that into our plugins right here so that's why we can safely use that in our input component great let's continue with the styling so let's write block W Dash full rounded Dash MD border Dash zero ey Dash 1.5 text Dash gray 900 Shadow Dash SM ring dash one ring Dash inset ring Dash gray Dash 300 placeholder text Dash gray Dash 400 Focus ring Dash 2 Focus ring Dash inset Focus again ring Dash sky-600 SM Pax Dash SM and SM leading dash six like that great and now uh I'm just going to collapse it like this and you can actually write a comma after this so it's still inside this parenthesis of clsx inside and let's write some Dynamic classes here so first errors ID so if there is an ID inside of our errors we're gonna give it a class name of focus ring rows 500 so we're going to give it a red outline if there is an error and we're going to use the same method to disable our Styles so disabled and end and it's going to write opacity dash 50 and cursor Dash default great and if you save you're gonna get an error because we have not passed the errors so let's go back into our form right here and let's just pass errors errors like this where do we get the errors from again we get it from this this structured from form state from the use form hook right here great and you can see we have our nice little uh nice little uh input right here great and just to wrap it up all right so this is our completed input component it has everything we need and it uses this a register to handle uh on change on focus on blur a bunch of these functions which we don't have to write ourselves and we use this Dynamic clsx to write this Dynamic classes alongside this default ones here great great job all right let's go back into out form now and let's actually uh uh modify this a little bit so instead of just writing email we're going to write different things depending on the variant uh that the uh that our out form is so our variants are either register or login so let's go ahead inside of this form object right here and I'm going to write a dynamic here so variant is equal to register and end I'm going to open parenthesis and we're going to render this input but instead of email this is going to be an ID of name and a label of name great so only if we are registering we're going to show this name input otherwise we're not going to show anything great just below that we're going to write some more inputs the inputs we need for other states which is a login so go ahead and paste this here and this one instead of name is going to have email it's going to have a label of email address and the type of email like that great and just below that you can copy and paste again an ID here is going to be password the label is going to be password and type is going to be password as well great so now we have these two beautiful inputs right here great and now what I'm going to below this is write another div and we're going to create a new component called button so go ahead and write button like this and you can just go ahead and write a test inside and if we save of course we get an error because button does not exist so where do we create our button well we created uh in our Global components folder so inside app inside components create a new file called button.dsx so just to answer the question why is the input inside the inputs folder but button is Standalone well because we're going to have a couple of inputs we're also going to have the select input but not for now so this button is the only variant of the button so that's why it can be Standalone inside of this components folder structure wise great now let's just write a very simple button component here and I'm just going to return a div which says hello button like that let's go back into our form and let's just import this button uh you can see it automatically uses the add graphics for me so add slash app slash component slash button again if ad doesn't work for you you can just use this dot dot slash abbrevience of it great and if you save the error should go away and we do get an underline because we're passing children but we have not defined that children are available inside the button component great so let's go back into our button.dsx and let's add some inputs some imports here so we're gonna write news client at the top I'm going to import clsx from clsx like this and I'm going to write an interface over our button so interface button props is going to be type now the type can either be button or submit or reset or undefined like that the full width prop is going to be an optional Boolean the children is going to be an optional as well and it's going to be react dot react node like that then we're going to have it on click which is also optional and a type of void like that secondary which is an optional Boolean danger which is the exact same optional Boolean and at last disabled which is exactly the same as the previous two great and now let's assign this props so react.fc button props like that and let's extract all of those so type pull with children on click secondary danger and disabled like that great and now let's go ahead and replace this div with a button element like that so I'm gonna give it an on click of on click like that I'm gonna give it a type of type I'm gonna give it a disabled or disabled and last name is going to be dynamic so go ahead and write clsx again I'm going to use backpicks for this so I can write in multiple lines right here like that so I'm going to write Flex justify Dash Center rounded Dash ND px-3 py-2 text Dash SM font semi bold Focus slash visible outline Focus Dash visible outline Dash 2 Focus dash visible outline Dash offset-2 so I'm writing a couple of this Focus dash visible just so we are more semantically correct when it comes to our Styles and now I'm going to write a comma here for the other arguments and these are going to be our Dynamic classes so first I'm going to handle the disabled state so if it's disabled I'm going to give it the class name of opacity-50 and cursor Dash default next I'm going to write the equal Advanced so if it's full width very simple I'm just going to give it a class of w Dash cool great next we're going to have secondary which is going to be uh a uh this shorthand if Clause so if it's secondary it's going to have a text Dash gray Dash 900 otherwise it's gonna have text Dash white like that next thing we're going to have is danger so if there is a danger we're gonna give it a class name of BG Dash rows Dash 500 hover VG Dash rows-600 and focus the action visible outline Dash rows Dash 600 like that so on danger we have BG Dash rows 500 hover b0 600 and Focus dash visible outline Dash rows Dash 600. great all right and below that we're gonna write if it's not secondary so exclamation point is secondary so if it's not secondary and if it's not danger then we're just going to give it our default stylus that we want which is a very simple BG Dash Sky 500 hover BG Dash Sky 600 and Focus dash visible outline Dash sky-600 great so very simple like we did above but instead of using rows values we're using Sky values which are our default nice blue color which do not indicate any errors great and inside of this Shield inside of this button I'm just gonna render children like this and great you can now see the test button is right here great great job so just a recap it's a very simple component which has Dynamic classes and if you can if you cannot see these classes I just collapsed them so on danger PG rows hover BG rows and focus visible outline rows on secondary if it's not secondary and if it's not danger we give it the default of BG Sky 500 hover BG Sky 600 and Focus dash visible outline Sky 600 as well great now let's go back into our app form component right here and instead of a hard coding test we're going to write depending on the variant so if variant is equal to logged in in that case we're gonna write sign in otherwise we're going to write register like that so by default we are in login variant so the text is going to be sign in great now the props we're going to give to this button is disabled if is loading we're going to give it a pull width as well and a type is going to be submit this way we don't need an explicit on click function for this button because this button is inside of our form element right here which means that when we click on this button it is going to trigger the on submit function right here great great job all right so just below our form elements right here we're going to write another div and this div is going to have a class name of mt-6 at the top so it separates a bit from the form and inside of that we're gonna create another div with the class name of relative like that now I'm just going to collapse it like here and inside of there we're going to write another div and give it the following class names so class name is going to be absolute inset-0 blacks and items Dash Center like that great and inside of that div we're going to create another div very simple one which is going to have a class name of W Dash full border Dash T and Border Dash gray Dash 300 like that so we have this little line here and if you want to you can actually remove the closing tag and just make it a self-closing tag like this so it's just border with this I'm just gonna collapse this so it's easier for you to see like this so feel free to make it a much simpler like that great and now below that and below this div right here you're gonna create a new div with a class name of a relative Flex justify Dash Center and text SM class right here and inside of that you're gonna write a span with a class name of DG Dash white px-2 and text Dash gray Dash 500 like that so the top div is gonna have the following class names so foreign Flags justify Center and text SM and the span is going to have BG white bx2 and text Gray like that and inside of this pen we're going to write or continue width like that great so you can see how we have this nice little effect where our text is in between this line great and now just below that below this div and below this div as well like this so it goes span end of this div and of this div and just in here we're going to find a little space to create another element also a dip we're going to give it a class name of mt-6 flex in gap Dash 2 like that and inside of there we're gonna write another component called out social button like that and if you see we're gonna get an error because this does not exist so to fix that in our inside our app folder inside the site folder inside this components we're going to create a new file out social button that is sex like that so let's just go ahead and fix the error I'm gonna write out social button like that and I'm just going to return a div which is gonna say social button great and I I can quickly go back into my out form and just import this from dot slash out social button so why is this dot slash out social button and these are in components well because we are in the same folder right here so we did not create our social button inside our app components but inside our site folder inside components right here because it's not going to be reused anywhere else besides this screen right here and you can see how we have the text social button right here great so enter this out social button now and let's uh add a class name here so import sorry not class name let's add an import icon type from react Dash icons like that if you have not installed react Dash icons which we did previously along with all those other packages just make sure you go into your terminal know and run npm install react Dash icons and now let's write interface out social button props like that and right icon which is a type of Icon type and right on click it is a type of void like that great now let's assign this props so react.fc out social button props and let's just extract these values so icon which you can immediately remap to Capital icon like that so we can use it as a component and on click like this great instead of div we're going to return a button like this and the button is gonna have a couple of attributes so type is going to be button on click is going to be on click and class name is going to be all static and we're going to write inline Dash complex W Dash full justify Dash Center rounded Dash MD BG Dash white tx-4 py-2 text Dash gray Dash 500 Shadow SM ring dash one ring Dash inset a ring Dash gray-300 over BG Dash gray Dash activity and focus outline Dash offset Dash is 0 like that so we have plethora of class names here but it's going to be all awarded for the effect and inside of the button we're going to render our icon like that so what where can we use this icon well because we remapped it right here and as you can see I I'm getting an error here and that is because in the out form I did not pass the icon so let's go ahead and let's actually add some attributes here in the out form so the icon is going to be BS GitHub like that and you can import vs GitHub right here at the top so import BS GitHub prompt react icons slash BS like that and if you save now and refresh in a couple of seconds the error should go away and you have a nice GitHub icon right here great and now let's also give it on click which is gonna trigger the social action with an action type of GitHub like that great and you can just copy and paste this foreign from react Dash icons BS so BS GitHub and Bs Google like that and social action here is going to be Google just like that great so now we have these two social actions here great great job and last thing we have to write is the function to toggle between a register and login so we're going to write that outside of this div right here so outside of here we're going to write another div like this and we're going to give it a class name of flex Gap Dash 2 justify Dash Center tax Dash SM t-6 px-2 text Dash gray Dash 500 like that and inside of that we're going to write another div which is going to be conditional so if variant is type of login we're going to ask a question new to Messenger like that otherwise we're gonna ask already have an account question mark like that great so now you can see we have this question new to messenger if the default is login so user can click here and then it's going to change it to register great and just below this div create another dip and give it an on click of toggle variants which we created at the beginning of our tutorial and give it a class name of underline cursor Dash pointer like that and again it's going to be dynamic depending on the variant so if variant this type of logged in in that case the action is going to be uh create an account otherwise it's going to be login like this great so now at the bottom we have this question in YouTube messenger and if we click create an account you can see that we are switched to the register screen so we now have the name input and this has changed to already have an account where we can click login and we are back into the sign up screen great great job so you finish the placeholder So currently not functional but the design is here and everything from now on is very easy and we have created The crucial components which we're going to need throughout our application which are inputs and buttons so I just want to quickly recap what we've done so far so inside our out form right here we added the actions which we're going to use to sign up uh we created the input component which handles uh the react hook form functionality and it changes depending if we have an error of if it's disabled and we can actually click sign in and you can see uh how we actually disable this button right here for example so what I want to do now is I want to also use this uh is loading to disable our inputs so right here where the variant register is name I want to give it disabled is loading like that and you can copy and paste that in every input we have like that great and now if you refresh and if you click sign in you can see that the email is disabled the password is disabled and the sign in button is disabled greater right now it stays disabled because we have not added a function to remove it back to false but we're gonna do that in the next part of the tutorial great great job you've written some great UI and code so far all right so in this part of the tutorial we're going to set up a Prisma and a connection to our mongodb database so to do that let's go ahead and let's go into our terminal let's shut down the application and let's run end game install Dash D Prisma like that and press enter after a couple of seconds uh the packages will install and we are ready to run another command great so after this has been installed go ahead and run the following command npx Prisma in it and press enter wait a couple of seconds and you should have your Prisma set up and if you take a look at your structure right now I'm going to collapse everything here and take a look you have a new folder called Prisma along with schema.prisma right here we have predefined it as postgra SQL we're going to change that to mongodb in a moment and we also have a new file dot EnV also generated by Prisma in here we have a database URL pointing to a non-existing postgresql database we are going to change that with our mongodb database so first things first let's go into our schema dot Prisma right here and let's change the poscra SQL to mongodb like this so provider should be mongodb and now we have to get the proper database URL which we're going to fill in our DOT environment file in database underscore URL file right here so go into Google and write mongodb Atlas press in the first link right here then press on sign in and you can either create an account use your email or Google GitHub after you are in you're going to be greeted with a screen similar to this find a button which says build a database and let's start building our database you're going to select the m0 or the free uh cluster right here so just make sure it says free for me it's the most right option right here and just confirm one more time that is free right here at the bottom above the create button you can leave the provider region and cluster name as it is and just press create now let's define our user so my user is going to be I already have an existing one but I'm going to remove it just so I have the same situation as you so my username is going to be Antonio and my password is also going to be Antonio when you create your password make sure you don't put special characters such as question marks inside because that is going to cause errors and just click create user great now we have our user you can leave the local environment here and for the IP address you can either write click here to add your current IP address but there is a chance that you have a dynamic IP and that it's not going to work for you so just go ahead and write 0.0.0.0 slash zero like that and press add entry 0.0.0 will allow access from anywhere and then just click finish and close and press go to databases like that great now that you have your cluster right here you can go ahead and click on the big connect button here and I want you to select vs code option right here because it gives us a specific type of URL which we are able to use in our environment file so go ahead and copy this right here and now go back into your vs code and you're going to replace this database URL with the new mongodb URL which we just created so it should look something like this mongodb plus SRV dash dash Antonio and now what you have to do is replace this pointy brackets password with your actual password that we've created just a moment ago in my case it was Antonio Antonio so all I have to do is replace this password with Antonio like this and make sure that you have slash test at the end this is the name of your database it should be automatically here if you copied it from this link right here great go ahead and save your environment file and now that that is done it can go back into schema.prisma and we can go ahead and start defining our models and relations but before we do that if for some reason your schema.prismo file is completely blank for example your generator client is not blue your strings are not yellow and these variables are not white that is because you're missing an extension for Prisma so just go into your extensions and write Prisma and in here you should find the extension called Prisma which adds the syntax highlighting and other autocomplete functions so let's go back into into our Prisma folder in schema.prisma right here and let's start declining our models first model we're going to write is the user model so go ahead and write model user and let's define the ID the ID is a type of string special decorator at ID special decorator at default inside of its brackets right Auto and just execute that out of function whoops like this great and now we have to map this ID to special mongodb underscore ID so right atmap question mark sorry annotations underscore ID like that and lastly at db.object ID like that and the error should go away so this is the type of ID which we're going to use in all of our models so ID is a type of string special decorator at ID we're going to give it a default value of Auto we're going to map it to underscore ID because this is what's under underneath the hood of this Prisma we are using mongodb so in mongodb the ideas begin with an underscore ID so we have to map our ID object to that and we just add another decorator at the end db.object ID after that we're going to have a name which is a type of optional string we're going to have an email which is a type of optional string and a decorator at unique because we don't want multiple users with the same email we're also going to have a field email verified and that is going to be a optional data time like this below that we're going to have an image which is a type of string we're going to have hashed password which is a type of string as well and it's optional we're gonna have to have uh two date time types here create an ad which is a type of date time and the default decorator of now we're also going to have updated at which is a date of time at updated at decorator great and now we're going to create some relations for this user model so this is our base User it's going to have an ID name email email verified image hash password created at an updated ad the reason hashed password is optional email verified is optional and all of these things is because we are also going to enable social login and for social login some of these things are not needed and we want them to give a control over that so now let's write the relations for all of our conversations that the user will be able to have so go ahead and write conversations IDs which is a type of string which is an array and a decorator db.object ID so conversation IDs is going to be an array of strings with a special decorator object ID so this is where we're going to store IDs of all of the conversations this user is a part of and to map that to actual conversations we're going to write conversations conversation which is a model we don't yet have make sure you don't misspell conversation like that and we had to define a relation so go ahead and write at relation Fields open an array and the field we're going to use is this conversation ID is right here so just put that in the array of fields like that uh write a comma references and inside of the ID of references just write ID so what does this mean we're going to have a an object sorry a property in this user model which Maps our conversation model which does not exist yet as an array and it uses the conversation IDs which refer refer to an ID of this conversation which we're going to create in a minute great now below that we have to create some more relations for this user so go ahead and write scene messages scene messaging IDs like that and just write string which is also an array of at db.object ID and below that scene messages like this and that is going to be a type of message array and it's also going to need a relation like this and we're going to give a special name to this relation called scene with a capital S and then we're going to write fields inside this array we're going to put scene message IDs which you defined above and references is just going to be ID as in above great so we have defined uh two more properties here scene message IDs and scene messages it works exactly the same way uh it works exactly the same way as the one above one thing I want to quickly fix is uh conversation IDs I don't want I don't want it to be named conversations like this I just wanted to be named conversation IDs like this and then you can go ahead and fix that in this field right here so make sure you use conversation IDs and conversation IDs right here and this convers this will be conversations so multiple and this will be send messages see messages and this will be seen message IDs like that great perfect and now let's just Define a couple of more relations here so every user is also going to be able to have an account so write accounts which is a type of an array of accounts and messages which is a type of an array of messages like this perfect now let's go ahead and Define our conversation model sorry first let's define our account model because we have to wrap up our user model so model account he's gonna have uh an ID so for that you can just copy what you define in the user right here and place it here because it's exactly the same below that right user ID which is a string and a special decorator BB dot object ID like that below that write a type which is a required string provider which is a string provider account ID which is another string refresh underscore token which is an optional string and a type of DB dot string so what is the difference between this string and this string well we have to do this special typing in mongodb because this is usually in postgresql db.txt but that does not exist in so we have to do this special mapping uh to uh DB dot string all right below that we're going to use access underscore token which is also an optional string with a special decorator pdb dot string as well below that we're going to use expires underscore at which is an optional integer below that token underscore type which is an optional string below that we're going to use the scope which is an optional string as well ID underscore token which is an optional string with a decorator DB dot string again and session underscore state which is an optional string as well and now we have to define the relation of this account with the user so go ahead and write user Capital user at relation Fields open an array write user ID references ID and on delete Escape like that what this means is we are mapping our user model to this user ID field right here and we are referring to the user ID right here and on the lead we're just giving it instructions what happens when this relation is deleted great and one more thing we have to add here is ADD at unique and write an array of provider and provider account ID so we are also defining a rule for this account model that the combination of provider and provider account ID need to be unique great now let's go ahead and create our conversation model so go ahead and write model conversation and you can go ahead and copy the ID either from the user or from the account because it is exactly the same great next thing conversation is going to have is created at which is a date time with the default of now the same way our user had it then we're gonna have last message at which is a date time with the add default now as well I'm gonna have a name which is an optional string is group which is an optional Boolean like this and now we're gonna write some relations for this conversation so each conversation is going to have a lot of messages so go ahead and write messages IDs which is a type of string of arrays at vb.object ID and go ahead and write messages like that and below that you're gonna write user IDs string at db.object ID like that and below that you're gonna write users user array relation Fields user ID inside references ID like that great and what's left is to Define our message model so go ahead and write model message you can copy the ID from conversation or any of the previous ones we've made and before we continue I have a typo here so instead of user ID we have to use this user IDs so multiple user ideas right here great so no error here so users is a relational Fields targeting these user IDs and referring to an ID of each individual user great now let's continue with defining our message model other than ID it's also going to have a body which is a type of optional string it's going to have an image which is a type of optional string as well created ad which is a date time at Recall now like that and now we're gonna have SIM IDs which is an array of string and a special decorator DB dot object ID great and now we're going to have it create a relation for these scene IDs so go ahead and write this scene user array at relation name it scene capital S as we did right here in the user model so it needs to be the same comma Fields array scene IDs which you defined right here above comma references ID like that perfect and now below that each message needs to have a relation with the conversation so go ahead and write conversation ID which is a type of string at bb.object ID like that and below that you can write conversation conversation at relation Fields conversation ID which you define right here above comma references ID and on delete Escape like that perfect and now we have to create uh the last relation and that is with the sender ID so the person who sent this message so go ahead and write sender ID string at DB dot object ID like that and sender user at relation fields in your array right sender ID and references ID and on delete stayed just like that great and now you can go ahead and go through your Prisma file I'm going to zoom out just a little bit so you can see this a full things we've written so we have our user model with an ID name email email verified image hash password created it and updated that we have relations with conversation IDs and conversations again make sure that in this field you actually use this conversation ID is right here same thing for scene messages make sure and see messages you're using scene message IDs right here great in the account make sure you have this exact setup because it needs to uh to have it exactly like this in order to work with social login for the conversation make sure you have messages like this message make sure you have user IDs which you use in these fields right here and in the message model make sure you have scene IDs which you use in the scene conversation ID which you use in the conversation and sender ID which you use in the sender great and now we can go back into your terminal just make sure you save your schema.prismap file right here and you can run npx Prisma DB push great you should have this message that collection users have been created collection account has been created conversation and message as well and now it's going to run this generate command for you and create the Prisma client and now we can go back into your mongodb here and you can click browse collections here and in your cluster you should actually see account conversation message and user this means that Prisma has successfully connected with mongodb if for any reason you're having errors and the MPX Prisma DB push did not work for you there's a couple of reasons that might happen first one is you did not add the proper URL in your dot environment file maybe you added a space here for example that can cause errors so make sure there is no space second one is you might have entered invalid email and password you might have not put the database name at the end or the last one could be that in your network access right here you do not have 0.0.0 so just make sure you have this so Prisma access your database regardless if you have a dynamic IP address great great job all right so we're going to continue and we're going to create our next out uh system in this part of the tutorial one thing I want to mention if you found this part of defining schema.prismail complicated or you feel like you might have missed something don't worry you can always visit my GitHub and you can find Prisma schema dot Prisma file right here which has all of that defined so you can just copy it or double check uh if you've written it from the tutorial correctly great now let's go back and let's head into our terminal right here I'm gonna shut down my application in fact it wasn't even running and I'm gonna write the following command so I'm going to expand this a little bit we're gonna install a couple of packages so npm install next dash out as Prisma slash client at next dash out slash Prisma Dash adapter and decrypt and if you want to you can also add a decorator to the next out at latest like this so you have the newest version of next out even though it should automatically pull the newest version but just in case uh if you want to you can write npm install next dash out slash latest because the older versions of maxed out do not support the app folder which we are using in this tutorial so make sure you install next out at latest at Prisma slash client and add next out slash add next slash out slash Prisma adapter like that I'm just gonna collapse so you can see this in one line so add next dash out slash Prisma adapter and Big Crypt and just press enter wait a couple of seconds for this to install and then go ahead and run one more command and game install Dash capital D at types slash be Crypt like that because the decrypt kit package by default does not have those types and you can go ahead and npm run Dev your project now great and you can just refresh your localhost to confirm that everything is working but we're not going to use localhost for now yet so what I want you to do now is I want you to open your sidebar like this I'm going to expand a bit I want you to go into the app folder and create a new folder called Libs and inside of there you're going to create a new file called Prisma db.ts great inside of that file you're going to import Prisma client from at Prisma slash client a package which we just installed and then you're gonna write const client is equal to Global this dot Prisma pipe pipe new Prisma client like this and we do get an error here because Prisma by default does not exist in global this but we're gonna fix that in a minute which sometimes and just below that you're going to write an if Clause so if process dot environment type that node environment is not equal to production in that case we're going to assign Global this dot Prisma to be equal to client like that great so I'm just gonna zoom out in just a little bit so you can see this in one line like this all right and below that make sure you write export default client like this and now let's go ahead and fix this globalbiz.prised my error so at the top of your file right here right declare global war Prisma is a type of Prisma client quite undefined like this and the globalbiz dot Prisma error should go away and if you hover you can see that it has this Prisma client type right here great next thing we have to do is we have to Define our next out file in order to do that open your cyber again I'm going to collapse everything so it's easier go into your app folder into API and in here you already have a Hello uh folder and you can go ahead and delete that one because we are not going to need it but make sure you keep the API folder and inside create a new folder called app like that and Inside Out folder you're going to create a new folder and you're going to name it in this square brackets and you're gonna spread next out like that and just name the folder like that and inside these square brackets where you write dot dot dot next Out Create a new file called route.ts so you should have an app folder API folder out folder and a square bracket where you spread the next out like that and go into route.ts inside of that folder and in here let's import some packages so import decrypt from Big Crypt again if this shows an error for you saying that the types do not exist and make sure you have run npm installed capital d uh bcrypt types which we did just a moment ago then run import next out comma open an object and the structure out options from next dash out like this below that import credentials provider from next dash out slash providers slash credentials like that we're also going to need a GitHub Provider from next dash out slash providers slash GitHub and we're going to need a Google Provider from net slash out slash providers slash Google like that and in the end we're also going to need our Prisma adapter from uh next dash out slash Prisma Dash adapter which we also installed alongside bcrypt maxed out great and now we have to import our newly created lib Prisma DB right here so go ahead and write import Prisma from add slash app slash Libs Prisma DB like that again if the add sign is not working for you for any reason you can always use the good old uh dot dot abbreviation so dot dot and just Define reasonable to be manually like this but I'm going to use this add sign right here because it looks cleaner all right and now I'm going to Define my out options so make sure you write export cons out options like that the export is very important because we're going to need out options uh to create a server session later in the tutorial so out options is going to be a type of out options which we imported from next out right here that is an object so go ahead and write adapter Prisma adapter and inside of that you're gonna put Prisma which you have imported from here our newly created Library which Returns the client like this great below the adapter you can now create a new property providers which is a type of array which accepts many providers we have first one is going to be GitHub provider open an object inside its function and write client ID process.environment dot GitHub underscore ID as string like that and below that you're also going to have client secret and instead of GitHub ID it's going to be GitHub underscore secret so we don't have this in our environment file yet but we are going to create them later great and then you can do the same thing for Google provider now so again open an object inside of its parenthesis and write client ID is equal to process dot environment dot Google underscore client underscore ID as string and below that client secret process dot environment that Google that client that secret as a string as well great make sure you don't misspell secret as something else that happens often so just make sure it's Google underscore client underscore secret look at that great and below the base we're going to need our credentials provider so our credentials provider is the basic login functionality using email and password so if user doesn't want to use Google or GitHub and they want to use email and password this is where we are going to handle that so first we have to give it a name and the name is simply going to be credentials like that below that we have an actual object called credentials open it and write some Fields so first field is going to be email it's going to have a label of email and it's going to have a type of text like that and below that write a field called password which is going to have a label of password and a type of password as well great below credentials we're going to have our authorized function in which we're going to compare what user has written as his password and compare that to the database to see whether we can log in the user or not so go ahead and write asynchronous authorize which accepts the credentials open this object and first thing you're going to do is check if the email and password has been passed from the form so if there is no credentials question mark dot email or if there is no credentials question mark dot password in that case just throw new error invalid credentials like that if that is okay in that case we can continue uh with searching for our user so go ahead and write const user is equal await Prisma dot user you should get an autocomplete for the user if you run npx Prisma DB push so go ahead and write prisoner that user dot find unique and we're going to use the where attribute here and we're going to find the user by the unique ID so email credentials dot email like that great and now we're gonna check if this user actually exists so if there is no user or if user does not have hashed password we're going to throw new error again invalid credentials so what is the case that this could happen well what could happen is that we have passed the email and we have passed the password in this sign up form but the email we pass does not exist in our database that means that the user will not be found and how come hash password cannot exist well that means that the user has registered using Google or GitHub so it has not set up an explicit password and we cannot use the sign up form with email and password to log in that user the only users we are going to be able to log in using the credentials providers are the one who register using name email and password here and not use Google or GitHub so that's why we have to do this checks great what we have to do now is check if user entered the correct password so go ahead and write const is correct password is equal to a weight bigcrypt dot compare in the first argument you're going to pass credentials that password and in the second one you're gonna pass user.hash password like that so we're going to compare what the form user has submitted with what we have hashed in the database like that perfect and then we're going to check if the password is not correct so if exclamation point is correct password in that case we're going to throw new error invalid credentials again and just make sure you put a weight before bcrypt dot compare otherwise this is not going to be a Boolean it's going to be a promise so just make sure you put a weight in front of bcrypt.compare like that perfect and in the end all we have to do is return the user so if all of these checks have passed if there is an existing user if it does have a hash password and in the if the password is correct all we have to do is return the user great and now outside of this providers object right here so just below this uh array you're gonna write a property called debug which is going to be very useful if you're in development so go ahead and write process.environment dot node underscore environment is identical to development so only in development we're going to turn on debug mode so in your terminal you're going to see a bunch of useful information uh for your authentication State then let's define our session so our session is going to have a strategy of jvt like that and what we have to do in the end is write a secret so go ahead and write the property secret which is a type of process.environment that Nextel underscore secret like that great and now that we have completed uh our auth options here we can go below right here and just write const Handler is equal next out options like that so where do we get this next out form well we imported it here at the beginning and Alpha options is the object we just created right here so just make sure you don't accidentally pass this type alt options that is not the same thing and you're going to get an error make sure you actually pass this object with lowercase a at the beginning and to wrap this up all you have to do is go to the bottom and write export Handler as get and Handler as post like that in previous versions of maxed out you did not have to do this step but since you're using the new route handlers inside the app folder this is how it's done in the documentation great great job just make sure you save this file and let's just confirm you have this in your app folder in the API folder Inside Out folder inside this square brackets dot dot next out folder right here great great job so let's continue with our tutorial and first thing we have to do is we actually have to assign this next Out secret GitHub ID GitHub secret Google client ID and Google client secret environment variables so let's just go into our DOT environment file to prepare those so just below this database URL I'm going to add next out underscore secret like this and I'm gonna name it next Out secret you can put anything you want in here like that now one thing I want to mention make sure you don't misspell this a lot of people misspell like next out make sure it's next out they also misspell a secret with sir set like this so just make sure it's secret like this if you're not sure you can just copy and paste what you written here so if you define process.environment dot next Out secret you can copy this and make sure you paste it as a name right here and I'm going to do the same thing for GitHub ID and GitHub secret for now I'm just going to leave them empty so go ahead and copy GitHub Secret leave that empty as well and the same thing for Google client ID and Google client the secret we are going to add them a bit later great after you've added this that is enough for us to do the registration part so what I want you to do next is I'm going to collapse everything here and I'm going to go into my app folder into API and inside API I'm going to create a new folder called register like that so just make sure you don't accidentally put this in the out folder because out folder is reserved for next out actions this register is not exactly connected to our next out we're not using it in that way so just make sure that your register folder is in the root of the API folder like that and inside create a new file route.ps like that go ahead and import bcrypt from Big Crypt like that and just go ahead and import Prisma from add slash app slash lips slash Prisma DB and also import next response from next slash server like that and now you can go ahead and write export asynchronous function post and open the parenthesis and the first argument is going to take is request which is a type of request you don't have to import this type from anywhere it is native in next environment great now we're going to extract our body so right constant body is equal to a weight request dot Json like that and then you can extract all of those values which we need for registration and that is email name and password from body like that and then you can just write an if Clause so if there is no email or if there is no name or if there is no password and you can just run uh return new next response you can just write missing uh info and an object with status 400 like that great and adjust below that and we're going to create our hashed password which we're going to store in the database because we never Store Plain text passwords in the database we have to encrypt them so go ahead and write const password is equal to a weight decrypt dot hash first argument is password and the second argument takes the number 12 as options and then just Define the user so const user is equal to await Prisma dot user dot create open an object and write data and the data it will accept is email name and hash password just like that and in the end just write return nextresponse dot jsonuser like that great and if you want to um protect this route from any internal errors you can wrap all of this in a try and catch function if you want to so I'm going to do that I'm going to write this entire thing inside a try catch like this and then here I'm going to catch the error you just type of any and all I'm going to do is I'm going to console log the error and I'm going to map that under registration error you don't have to do this but it's very helpful when debugging your application that you have these errors in the terminal so you can just find registration error and then you know okay the error is in this route right here and what you want to do is just return new next response internal error with a status 500 like that perfect so why do we have to explicitly say new next response when we are throwing errors but we don't have to when we're sending our user well that's because we use this dot Json which does not require the new indicator before it great great job all right uh and now we're gonna go back into our out form now that we have this register route right here so I'm going to go into app into site components out form right here and in the hour on submit function right here where we wrote the comment axios register we're actually going to write our axios call before we continue we actually have to install axis so I'm going to shut down the application and write npm install axios like that great now that it has been installed you can go ahead and run npm run Dev again and just make sure you refresh your localhost so everything is up to date great and now you can remove this axis register comment right here and you can actually write axios which you can import right here uh import axios from axios I'm gonna put it at the top so you can see clearly so make sure you do this import axis from axis at the top and then you can use axis.post and you can Target slash API slash register and you can pass in the data right here so this data is going to consist of name email and password right and in our route you can see we check for email name and password which are those exact values and the reason we know it's slash API slash register it's because that's what we named it in our API folder in our register folder we have a route so that's why it's mapped through slash API slash register like that great and for now you can just save it like this refresh your page one more time I'm going to prepare my mongodb right here so we can see if the new user has been created successfully so right now I have no users in my database and I'm also going to open my network tab so I can clearly see if something goes wrong I'm going to click create an account so I'm looking at the register variant and I'm going to name myself Antonio with an email Antonio mail.com and the password of one two three three two one and I'm going to click register and you can see we pointed at the register route right here and we get a success message of 200 and you can see that it returned our newly created user great now let's go back uh in mongodb and see if the user has been created and there we go we have a name of Antonio email of Antonio and a hashed password right here what I showed you in the network was my payload the preview is what was created you can see that we have an empty array of conversation IDs created at hashed password ID image name scene messages and updated at great great job all right foreign so now I want to add some feedback depending on whether we for example don't send name or email so we can actually see the errors coming from the server in our application and we're also going to complete a signing in because right now we only have the register functionality and we're also going to complete this um disabled State turning off after some time so go ahead and refresh your localhost for now so everything is clear and the first thing I want you to do is I want you to go into your terminal right here you can shut down the application for now and go ahead and run npm install react Dash hot Dash toast like that great after this has been installed I want you to go I'm going to close everything here go into your app folder and create a new folder called context inside this context I want you to create a new file called toaster context.dsx like that great I want to start by defining use client at the top and then just write import poster from react Dash hot Dash toast like that and all you're going to do is write const toaster context return an arrow function and just return coaster which is a self-closing tag like this and make sure you export people poster context like this great and now you can go back uh in your layout.tsx right here in the app folder uh and you're gonna just collapse this body right here and you're gonna wrap uh you're actually not gonna wrap children anything but you're just gonna write toaster context like this which is a self-closing tab as well and you can import poster contacts from dot slash context slash a context uh those are contexts like that great and I'm just gonna separate this Imports like that beautiful and now we have the toaster context which we can use to trigger our toasts great now I want you to go back in your site components out form uh right here and what I want you to do is I want you to write a DOT catch function and what you're gonna do here is just trigger an arrow function which is going to call Toast which you can import from react hot toast so that has been done here so import destructive toast from react Dash hot Dash sorry destructed so make sure you write in an object like this and then you can use toast dot error something went wrong like that great and yeah make sure you run your application after you install the package so npm run Dev in the terminal and just refresh your localhost great and now I'm gonna click create an account again I'm going to click register and you can see that I get back an error something went wrong why do we get that error when you can check that in your network tab right here on the side if you click on network I'm just going to refresh one more time I'm going to click create an account and I'm going to click register and you can see that because we have not sent email name and password we get back an error and you can see how that little toast notification came up at the top uh great I'm gonna close the terminal like this but I'm Gonna Keep the app running and to prevent this uh from always being disabled I'm just going to write a Dot finally here in which I'm just gonna write set is loading false like that so now if you refresh one more time and go into create an account right here and even if you get an error you can see we get an error but we can click again and we can try again great beautiful and I'm just gonna test uh what happens uh if we enter a correct one so I'm going to write markmail.com one two three three two one and I'm gonna register uh and you can see in this case we get no error and we also stop loading because the user has been successfully created I can refresh the user one more time here in the database and you're gonna see that I have Antonio and I have a Mark here great and now let's actually Implement a login here so in order to implement a login we're going to need to use next out sign in function so I'm just going to write sign in here which we will have to import from a next out so just go to the top right here and write import sign in from next dash out slash react like this so make sure you import sign in from next dash out slash react great and now we can go back here in the variant login and what we will send for login well the first thing we have to Define how are we logging in we have to choose a provider and if you remember we have three providers in our next out file so I'm just going to quickly open that for context so inside of my next out file I have GitHub provider Google provider and credentials provider for this exact thing we are doing right now we want to use the credentials provider so we have to use this name that we've given it right here credentials so back in my out form in the first parameter I'm gonna write credentials just like that and the data I'm going to pass in is going to be spread this existing data that we also send in the register but the reason I'm spreading it is because I'm also going to add another argument redirect and just set it to false like that great and now I'm going to use dot then and open an arrow function inside and in this Dot and then I'm going to have a callback and first I'm going to check if there is an error during login so if there is a callback question mark dot error in that case I just want to return a toast so I'm going to write toast.error invalid credentials like that and if all back question mark dot OK in that case I'm just gonna for now I'm just gonna say post that info success actually that info does not exist I want it straight.box success like this or you can just write log in like that beautiful great I'm gonna refresh my application here and I'm going to try and log in as something that does not exist so uh I'm gonna try wrongmail.com and password I'm going to click sign in and as you can see okay I got both of them so there is obviously a mistake I'm gonna fix that in just a second and we also have to disable but what's important is that we got this invalid credentials as well all right so to fix this uh all you have to do besides checking of K you also have to check if there is no callback ER like this and then the login will not show so if I try this one more time and before I try uh just below this dot then I'm also going to add that finally right here which is just going to return an arrow function and set is loading to false like we did uh in the register right now and you can refresh just to make sure it's all reflected and I'm going to test again so wrong and I'm going to click sign in and you can see I get invalid credentials like that but if I try my existing account you can see that I get logged in perfect great great job all right now we have to set up our GitHub and Google social login so first I'm going to collapse everything and the only thing we have to change uh for now is just set up this GitHub ID and Google find ID variables so first let's do GitHub because it's much simpler than Google and I just logged in in my GitHub I realized I was not logged in so just make sure you're in your GitHub you're logged in and go into your settings I'm going to zoom everything in just a little bit so you can see so in my settings I'm gonna go all the way down and click developer settings right here and I'm going to click on all out apps I see you see I have a couple of them uh just click on new or out app right here I'm going to name this messenger video now the home page URL is going to be your localhost 3000 so you can just copy this and make sure it includes the HTTP protocol make sure it's not https because we are working with HTTP great and with the authorization callback URL make sure you do the exact the same thing and you can leave everything else as it is and just click register application great now go ahead and copy this client ID and paste it here and click generate a new secret to get the client Secret and then you're gonna have this little message here and you can just click copy in this green box and make sure you paste the GitHub secret here as well great now I'm gonna go back into my messenger clone right here I'm gonna go back into out form and I'm going to go right here in the social action and one thing we have to do in this social action is the same thing we did uh with uh login so what I'm gonna do it after set is loading I'm going to call uh sign in and instead of passing credentials like I did here I'm gonna pass either Google or GitHub because that's what we do right here so we we call the Social Action with either Google or GitHub here so that's why we know those are the only two options we can get so I'm gonna pass in the action right here and an object I'm gonna pass is not data because we're not using email and password here all I have to do is write redirect pulse in the social action and in the dot then again I'm gonna get a callback right here and just do the exact same thing so if there's a callback question mark error in that case you can just run toast that error in the lead credentials and if there is a callback okay and if there is no callback question mark error in that case you can just run toast that success logged in like that perfect and just make sure you add that finally here and just run set is loading to pause like that perfect and now I'm just going to refresh everything here and I'm gonna go and try and click on my GitHub right here to see what happens and you can see I'm in the authorization screen I'm going to click authorize my account and in a few seconds you can see that I'm back here so now we can check if this worked correctly by going to our database and clicking Refresh on the user and see if a third user has been created okay no user for now but let's check if it's an account yes so an account is here that means it's working but why is there a new user being created well that happens uh when we work with both credentials and uh social login so what I advise you to do is to remove all of your users like I'm doing right now if you have the same problem happening because a lot of people have that go into your account and remove all the accounts as well like this and what I suggest you do is you open your terminal sorry open your sidebar like this inspect element and just do an empty cache and reload on this application to make sure you're not logged in and just press on GitHub again all right so this time I did not have an authorization screen because I already allowed it but let's refresh to see if we successfully created an account this time all right so we have an account let's check it for our user and we have our user great so that fixes it when you create social login make sure you remove all of your users and all of your accounts and just clear cache perhaps you don't have to clear cache but I just want to make sure that everything is working for you so then try again and this time you will not have the authorization screen perhaps your screen will just hang a little bit it will look like nothing is happening but it's actually creating the user in the background and you can just check your accounting user again you can see that I have a user which uses my Gmail account and it has an image with the GitHub user content inside perfect and now we just have to do the Google login all right so for Google let's go into Google and let's just write Google Cloud console like this and make sure you select this Google Cloud platform uh link for me is the second one after this sponsored one so just make sure it's called Google Cloud platform like this so the link is console.cloud.google.com and in here you can see I have Airbnb clone from my previous tutorial so what I'm going to do is I'm going to click here I'm going to click create a new project my new project is going to be called messenger Dash video the organization does not matter so I'm just going to click create and just wait a couple of seconds that this create project finishes great after it has finished you can just click select project right here and make sure you're in the messenger video right here at the top and then you can just write in API here and just click on apis and services right here and the first thing we're going to have to create is an oauth consent screen so in this sidebar make sure you click allow the consent screen right here wait for a couple of seconds to load and make sure you select external so it's available to anyone with a Google account and click create I'm just going to collapse this for the app name is going to be called messenger Dash video for the user support email and just select your email it's going to autofill it for you you can leave all of this empty including the authorized domains and in the email address just write your email one more time and just press save and continue you can leave these exactly as it is and just press save and continue again and one more time save and continue and that is it and then you can go into your credentials right here in the sidebar and in the top you can click create credentials or out client ID like this for the application type select a web application name you can leave it as a web client one you can leave the authorized JavaScript Origins empty for now and just click add URI for authorize the redirect Uris and what you're going to write is going to be similar to GitHub but a bit more uh complicated so http localhost 3000 slash API slash out slash callback slash Google so I'm just going to zoom in so you can see what I've written here so it's a localhost 3000 slash API slash auth slash callback slash Google like that and just press create great and now we have our client ID and client secret so let's go back into our DOT environment file right here let's copy client ID and paste it here and let's copy client Secret and paste it here as well great and now we can go back into our messenger clone right here and what I'm going to do is I'm going to remove again all of my accounts actually I'm gonna do that individually like this so I'm going to delete my user first right here then I'm going to go into an account and I'm going to remove my account right here great uh and now I'm going to refresh this one more time and I'm going to use the empty cache and hard reload and I am going to click on Google this time and you can see it uh prompts prompts me to select my account I'm going to click on the first one I'm gonna wait a couple of seconds okay we are back to base the screen and let's see if I refresh my accounts right here if Google account has been created this time and there we go we have a Google account created in our database and if I go and check my users you can see that the user is here as well great if you try GitHub perhaps it will not work now and that is either because you're logged in at the moment so if you are logged in since we did not create a redirect from this screen at this point in the tutorial uh it will probably cause some problems if you try to social login while you're logged in as another user the other problem you could have is that your GitHub and Google share the same email so make sure that your credential login your Google login and your GitHub login all have a different email great you completely finished the authentication screen and in the next part of the tutorial we're going to work on redirecting to our actual messenger screen where we will load our users and we're also going to wrap the entire application in a session provider so you can actually trigger logout as well and actually see what user you're logged in as so we're going to continue now and we're going to create redirection after successful login or register to our slash user screen or so-called the actual messenger view in order to do that first we have to add authentication context to the root of our application so let's close everything app and let's go back into our app into context folder right here where we already have the toaster context and create a new file called alt context.ps inside great just make sure it's not TSX instead of TS so auth context dot DSX is the new file inside the context folder and first let's define use client at the top and then let's just import session Provider from next dash out slash react just like that and then let's create our interface so interface out context props children react.react node like that and then let's just export default function out context children and let's just assign these props right here so out context props like that and inside all you're going to do is return session provider and inside of there you're gonna write children and you're going to close the session provider just like that perfect and that's it for our auth context so make sure you import session Provider from next dash out slash react make sure you've written this props which only accept children make sure you have signed those props and just create this session provider which accepts children in the middle great and now let's go back into our app layout.tsx file right here and what you're going to do is you're going to wrap the toaster context and the children Inside Out context so go ahead and write out context like this and just wrap toaster context and children inside and you can kind of indent them a little bit and you can import out context from dot slash context slash out context the same way you did with toaster context great and now you can go back into your site components out form right here and inside you can now import session hook so right here at the top right const session is equal use session from next dash out slash react the same Library where we imported sign in function great and now just about toggle variant I'm gonna write a use effect right here in which I'm going to check if the current session status is authenticated so if session question mark dot status is equal to authenticated in that case I'm gonna uh for now just console log authenticated like this and make sure you pass in uh the session question mark status like this all right and I'm just gonna expand on my browser a little bit so I can open the console and you can see that I have a console log authenticated here perhaps you might not have that if you're not logged in but basically what we want to do is user is if user is authenticated and tries to visit the login screen we want to redirect them to slash users great so before we do the redirection part what I want to do is I want to go into my uh app right here and I want to create a new folder inside called users like this and inside users I'm going to create a new file page.psx like that I'm gonna name it users and I'm just going to return a div processed hello users like that great and now we can go back into our form and just below this session you can add const router is equal to use router just make sure you do not import that from next slash router you have to import it from next slash navigation so import use router from next slash navigation like this so make sure you do not accidentally import it from a router this is a common autocomplete but that is an old version of next in the next 13 we are using uh next slash navigation like that and now that we have our router instead of console log authenticated we can write a router that push slash users like this great and make sure you add the router to the dependency array perfect and now if I try and refresh this page you can see that I'm redirected to hello users great great job all right and what I'm gonna add here in my users page so I'm going to go back into my users page right here and I'm going to add a little button so that we can safely log in sorry log out so instead of hello users we're gonna have a button here which is going to for now just say log out and on click we're going to do an arrow function which is going to call sign out from next Dash alt slash react and just make sure you execute it like this in an arrow function so just a very simple button with an on click which calls an arrow function which executes this sign out like this great yeah and just of course make sure you wrap this in US client at the top so you don't get any errors great and now we have this button doesn't really look like a button but once we click uh log out well we'll steer at the users page that is because we have not protected this route but if you go back to localhost 3000 you can see that now we are not redirected back because we are successfully logged out great so what I want to do now uh is I want to go back into my out form and I want to use this router that push slash users in some other places so first thing I want to do is after we successfully log in instead of just having a toast success logged in I also want to use router that push slash users so once they successfully log in I also want to um redirect to slash users and also once I register I immediately want to log in so what I can do here is call Dot then like this and I can just use sign in credentials data like that so I'm immediately signed in once I register so we're going to test both of that now so first I'm going to try and log in actually I'm going to try and register because I removed all of my users if you remember so I'm going to create a new user right here and if everything is correct I should immediately be redirected um to slash users after this has been completed and there we go I am back in slash users perfect I'm gonna log out again nothing's gonna happen so I have to manually go back to localhost 3000 and we confirmed that the register Works let's try uh if the login works as well so I click sign in and there we go I'm logged in and I'm redirected to users great and now I want to protect this user's route right here so what I'm gonna do I'm gonna close everything up right here and in my uh root folder so not inside the app but in my root folder I'm going to create a new file called middleware.ts like that and first I'm going to import without from next dash out slash middleware like this and I'm going to export default without I'm going to open an object inside of its function I'm going to write the pages sign in and I'm going to give it a sign in page of Slash because this is our sign in page localhost 3000 slash is our initial login page and now I'm just going to write a config which is going to protect our routes so I'm going to write export const config matcher I'm going to open an array and I'm going to write slash users slash path Asterix it at the end so even though we are not gonna have any nested routes inside our user this is a good practice so you can protect all of the routes inside of the user so this is also going to cover things like slash user slash Antonio slash messages for example and that is exactly what we want perfect all right so now just to confirm that everything is okay I'm going to shut down my application and I'm going to run it again just in case this middleware is not reflected with hot reload so just click refresh again wait a couple of seconds for everything to load great and now I'm going to try again and click log out now and our middleware should automatically redirect us to the login screen great great job and I'm gonna try and go back again actually while I'm not logged in I'm gonna try and manually enter slash user so you can see that we protected it right now you can see I'm immediately returned back here and if I try and log in in that case everything should work just fine there we go I'm logged in and I'm in the users perfect great job so now I'm gonna go back into my app folder into users page.dsx right here then I'm going to start writing some code here instead so for now I'm gonna remove this logout button because we're going to use that in a sidebar later so go ahead and write a div give it a class name of hidden LG block lgpl-80 and h-4 so on small devices this is going to be hidden on large it's going to be a block and on large it's also going to have a padding left of 80 which is 20 Ram or 320 pixels and it's gonna have a full height so why do I move this by the left by so much well because this is going to be a space for our sidebar and for some other items which you're going to see in the future and inside of this what I'm going to do is I'm going to write a new component empty State like this and if I save of course I'm going to get an error because that does not exist so let's go into our app folder into our components and in the root of our components create a new file empty state.dsx like that let's just fix the error so I'm just going to return a div which says empty like this and I'm going to go back into my users page and I'm going to import this from dot dot slash components empty State and I'm going to save this file and the error should go uh away I'm going to refresh one more time okay we're getting some errors let's just fix that all right so in order to fix this error uh we have to remove the use client from the top of our page in userspage.tsx so just make sure you move use client and remove sign out because we're not going to need them and then if you refresh the error should go away I'm just going to zoom out a little bit and you should see the empty if you cannot see the empty it means you're zoomed out to in too much in because this is only visible on large devices you can see that this entire space on the left is empty for us because this is where we're going to put our sidebar and some other lists we will have great so now let's go back into our empty state uh and let's start styling it so I'm going to give it a class name of px-4 py-10 SM bx-6 lgbx-8 H dash full Flex justify Dash center items Dash Center and BG Dash gray Dash 100 and you can see how we now we have this little effect where the empty section is grayed out great now I'm gonna go uh inside of this div and I'm gonna write another div we're just gonna have um a class name of text Dash Center python Center Plex and flex Dash call so just make sure it's text Center item Center flex and flex Dash called like that and inside I'm gonna have an H3 which is going to say select a chat or start a new conversation like that great and now we have this text right here and I'm just going to give this a class name of the following mp-2 text-2 XL semi mold and tax Dash gray Dash 900 like this great and that covers uh our empty State we're going to reuse this empty State a couple of times in our application so it's great that we've finished it is so uh fast in this video great now I'm gonna close everything and I'm just going to recap what we did so I'm going to expand my code a little bit make sure you have all the changes that I do so we added a new folder called users and we have a page.tsx inside of it which Imports the empty State and just returns it we had an error because we could use client here at the top perhaps if I edit again it's going to show again so just confirm that this is that error which you had yes so that shows the hydration error so just make sure you remove use client from the users page we added that because we used it for the log out thing but we did not need it and if you're not seeing the empty message that means you have to expand your screen or zoom out if you're to zoomed in great great job and now we're going to go ahead and create our sidebar component so let's go and close everything and let's go into our app folder into our users and create a new file called layout.thesx like this and first let's do export default async function users layout like this and you can just open it and return like this the prop is going to take its children and you can just uh easily uh add the props for that so open another object children react.react node like that great and now just open this function and for now you can just return a div and paste the children inside like this great okay now we have this little bugged out view but don't worry we're gonna fix that uh soon so what have we done here well we'll defined a common layout for all of our users route so every route inside this user is going to share this exact layout which is different from the root layout that we have but root layout is also shared of course but specific design we want is in the layout of our users page right here great the reason we created this as an asynchronous function is because in the future we are going to use this server component to fetch users directly from the database great so let's give this a class name of H dash full just to fix uh this bugged out view there we go now it's much much better all right and now I'm gonna wrap this entire thing inside a sidebar now a sidebar does not exist yet so of course um we are going to get an error so just save the file and we get an error so let's go and fix that let's go into app into components and let's create a new folder called sidebar like this and inside of that you're going to create a new file Capital sidebar dot the SX so capital S sidebar dot PSX like that great and inside of here what we're going to do um is we're going to write a synchronous function sidebar again it's going to accept children and let's just Define the title of children to react.react node like this and let's just return this function so return let's just wrap this div right here let's give it the class name of H dash a full again and let's just render the children uh one more time great and now let's go back into users layout.psx and let's just import this sidebar component so I'm going to go to the top right here I'm going to import sidebar from components slash sidebar slash sidebar like this and let's just fix this error so sidebar is not a module uh of course we have not exported it so just in the sidebar component make sure you write export default sidebar like this all right now uh let's just confirm that this is okay all right so we get this error that sidebar cannot be used as a jsx component why well because our sidebar is an asynchronous function so the way uh git shop recommends fixing this is by adding a comment here so that's exactly what we're going to do you can either write at the S Dash ignore or a better way would be at TS Dash expect Dash error server component so we wrote this uh special tag which fixes our typescript error and uh basically when they fix this error it's going to alert us that we can remove this comment then so GitHub issues recommend doing it this way so that's what I want to do it this way and that fixes our error nicely great now let's go back into our components sidebar sidebar.tsx again and let's continue developing here so uh besides wrapping the children inside a div I'm also going to wrap it inside a main element like this so we are semantically correct and I'm also going to give it a class name of LG pl-20 and H dash full like this so you can see we we moved our uh empty State even a little bit further it's all going to make sense very soon great now inside of here let's create another component desktop sidebar like this if you save of course we are going to get an error so let's go ahead and fix that in our sidebar folder in components create a new file desktop sidebar that the SX like this and let's just fix this sub desktop sidebar return a div desktop sidebar like that let's go back into our sidebar folder sidebar component and let's just import this neighborly component we can just use dot slash desktop cyber and you can see how it's positioned here exactly where we expect it to be positioned great all right so let's continue with developing our desktop sidebar to continue we're going to need to create a couple of hooks so open your sidebar right here and in the app folder create a new folder called Crooks inside of there you're going to create a new file called use conversation.ds we're going to need this hook in the future as well and we're also going to need this in our sidebar so go ahead and import use params from next slash navigation and also import use Memo from react just like that and then just write const use conversation it's a very simple arrow function and write const parents Ezekiel use parents like this and const conversation ID is equal use memo foreign just write the dependency array at the bottom like this and what we're going to do is we're going to search for conversation ID inside of these parameters so if there is no params question mark dot conversation ID we're going to return an empty string otherwise we're going to return harem's dot conversation ID as a string like that and make sure you add param's question mark dot conversation ID in the dependency array then next we're going to write const is open which is going to be a use memo again write an arrow function and we're just going to put double exclamation point conversation ID and just put conversation ID in the dependency array of this eu's memo so this double exclamation point turns this string into a Boolean so now we can see that is open is a type of Boolean because if we don't do this we can technically just do this but then our is open as a type of string but we want to use it as a Boolean so make sure you don't accidentally put just one exclamation point this is going to turn it uh into a full C string make sure you put two exclamation points this turns it into a proper Boolean great and in the end what you want to do is return use memo again and write an arrow function open a parenthesis and return an immediate object which is open and conversation ID and in the dependence array put is open and conversation ID so our results are now memorized and Export people use conversation like that perfect and now that we have this hook ready we can move on and create another hook called user out so in the file create use routes.ds like this and in this these routes you're going to import use Memo from react and you're going to import use parents from next slash navigation and to continue we have to install a package so I'm going to go into my terminal right here I'm going to shut down the application and I'm going to run npm install react Dash icons so I'm going to expand just a little bit like this so npm install react Dash icons and wait a couple of seconds for this to install great now that this has been installed you can go ahead and run npm run Dev again and just refresh your localhost so everything is working correctly great I'm going to collapse this and I'm going to continue with my imports so I'm going to import hi chat from react icon slash hi I'm also going to import hi Arrow left on rectangle from react Dash icons hi2 like this so make sure you do not import this from hi because it is not going to work and besides importing this hi Arrow left on rectangle I'm also going to import another icon here from this very same package called hi users like that great I'm also going to import the sign out from next slash out slash react and I'm going to import use conversation from dot Slash use conversation which we just created they are in the same folder so we can use this shorthand like this great now let's write const use routes which is a hook and just an empty return for now now let's add the path name so pronounced that name is equal use path name and you can import that name from next slash navigation my apologies we're not going to need use params at all so you can remove them we're just going to use use path name from next slash navigations great all right and below that we're going to extract conversation ID from use conversation like this if it exists great and I'm gonna write our routes so const routes is equal to use memo and we're going to return an array of objects so the first route we're going to have is a label chat like this with an href of Slash conversations like this and an icon of hi chat an active path name slash conversations or if there is a conversation ID like this so the same thing double exclamation points conversation ID all right and make sure you also add the dependency array of path name and conversation ID like this great so this is our first route and we're gonna have two more routes so the other one is labeled users with an href of Slash users icon of hi users and active of path name is identical to slash users like this we don't have to check our conversation ID because in the user's route we cannot have that to happen great and the last thing we're going to have is the log out so label log out href actually yeah href is going to be just an empty hash because we are going to use on click here which is going to be an arrow function which is going to call sign out like this all right and an icon is going to be hi Arrow left on rectangle like this perfect and all we're going to return is routes so this memoized function which we just created and make sure you export default user outs like this perfect and now we can go back into our components sidebar desktop sidebar component right here and right here at the top uh before we start writing our hooks let's define this as use client like this and now let's write const routes is equal use routes sorry not use router use routes from at app slash hooks Slash use routes again if you cannot use the ad you can use the dot dot slash abbreviation and find where your hooks are great uh and below that we're going to create is open and set is open and I use state of pause like this great we're going to use this uh later on in tutorial but I just want to prepare it here so this is going to be used for our model but we're not going to have that just now all right and inside of this div we're going to start by styling it a little bit so let's go ahead and write fastening hidden LG fixed LG inside Y dash zero LG let zero LG z-40 LG w-20 Excel px-6 LG overflow Dash Y dash Auto LG VG Dash White LG border Dash R open square brackets 1 pixel lgb-4 LG Flex LG let's Dash call and justify Dash between like this all right and now inside of that we're going to create a nav element and we're going to give it a couple of plus things as well so last name here is going to be MP Dash or Plex Flex Dash call and justify Dash between like this and inside of this nav bar we're going to create a unordered list and we're going to give it a couple of attributes here so we're gonna have it a row of list so we are semantically correct with our elements and we're going to give it a class name of blacks black slash call Item slash Center and space Dash Y dash one like this and what we're going to do is we're going to map over our routes you can see how we already have this little box right here you can see we have this border so this is our sidebar right here great what we're going to do here is we're going to map over our routes from user routes and we're going to have to create a special component for that so for now what you want to do is routes that map item and you can immediately return desktop item like this if you save of course you're gonna get an error because desktop item does not exist yet but I'm just going to continue and give it some attributes so key is item dot label ahref is item.href label is item dot label same as the key value icon is item dot icon active is item.active and on click this item that on click like this great and now we have to create the desktop item so in the same folder sidebar inside of our components create a new file desktop item dot ESX this let's just fix the arrow so desktop item and I'm just going to return a div saying desktop item like this and you can go back into your uh desktop sidebar and just import this uh there in the same folder so you can just easily import it like this and you can see we have a desktop item repeating three times that's because we have three routes in our user routes right here so chat users and logout that are going to turn uh here later so go back into your newly created desktop item right here and let's add some imports so um first I wanna mark this as use client and then we're going to give it an import.clsx from clsx and import link from next slash link like this great now let's write the interface so interface desktop item props label which is a string icon which is any href which is a string on click which is optional and it is just an empty void like this an active which is an optional Boolean like this now you can just assign this props so react.fc desktop item props like this and let's just extract all of these values so label icon href on click and active great so we imported this to the things we marked it as use client and we defined the interface for our desktop item great now let's write our handle click function so const handle clicked is a very simple arrow function I'm just going to check if on click exists and if that's true all it's going to do is return on click very simple great and now we can go ahead and actually style our desktop item so instead of returning a div we're going to return a list item like this so we're going to give the list item on on click off handle click like this and inside we're going to use the next link which we imported at the top like this great let's go ahead and inside of this link I'm going to create a span and I'm going to say uh label inside of that so we'll render that very same label and if I refresh now okay I get an error because the link does not have an href so just make sure you add href href to the link like this go ahead and refresh and there we go we have chat users and log out now all right um and adjust Above This label I also want to give it an icon so we're going to use this icon right here in order to do that we have to remap this icon to Capital icon like this all right and now we can use it right here as icon great and I'm going to give it a class name of h-6w-6 and Shrink Dash zero great and if you save you can see that we now have our icons great now let's go ahead uh and I'm just going to collapse this because we're gonna give this link a couple of styles so write class name is clsx again you can use normal annotations here but because I'm going to write this in multiple lines I'm going to use backpicks so I can safely do that all right so I'm going to write group Flex Gap Dash x dash three rounded Dash MD E-3 tax Dash SM leading dash six Point semi bold backslash Gray 500. however that's Dash black and hover 100 like this and I'm gonna give it a comma here so I can create a dynamic style active and end BG Dash gray Dash 100 backslash black like this all right and now what I want to do is I want to hide this span uh and leave it only in server side so I'm going to write class name Sr Dash only like this this is going to hide this on the client and only leave it available uh for our server side rendering so we have better SEO because our navigation will actually have the name great great job and you can see we have our little routes here and you can see how our users are automatically selected because we are on slash users and we can again log out using this button all right and you can see how I logged out now and I'm gonna log in back again and I can see my sidebar back here great great job now if we try and collapse this you can see that on mobile it looks quite empty so this sidebar only works well on desktop let's go ahead and let's fix that by adding a mobile footer so I'm gonna stretch this just as much as I can so I can still visibly see this and now I'm gonna go back into my sidebar component where we added a desktop sidebar and just below that I'm going to add mobile footer like this and of course if we save we're going to get an error so let's go back into our sidebar folder and create a new file mobile twitter.dsx like this let's just mark it as use client so we don't forget later and let's just fix the error mobile folder like this create the mobile footer like that let's go back into our sidebar where the error is and let's just import it the same way we did with the desktop sidebar and now the error should go away you can see how our text is kind of trying to be a scene here don't worry we're going to position this correctly in a moment all right let's go back into our mobile footer right here and first let's add const routes use routes which you can import from add slash app hooks use routes it is the same one we use in the desktop sidebar as well and then we're also going to use the use conversation so const use conversation which you can also import from add slash app hooks use conversation and we're going to extract is open because we return it separately great and what I'm going to do is I'm going to hide the mobile footer if the user has an active conversation going on so it is open I'm going to return now this is because on the bottom we only want the user to have the message form and not the mobile folder great and otherwise we can continue and style basis so I'm going to remove this mobile folder like this uh and what I'm going to do is I'm going to give this div a couple of class names so fixed justify Dash between W Dash full bottom 0z Dash 40 blacks items Dash Center VG Dash white border Dash T square brackets 1 pixel and LG it's hidden like this all right and I'm just gonna collapse this now so you can actually right now we still cannot see anything but I'm gonna start collapsing it so we can actually see the changes we are doing here great all right now in here I'm going to do routes.map the same way we did uh in the desktop sidebar route and instead of rendering a desktop item this time we're going to render mobile item like this again if you save this uh you're gonna get an error because mobile item does not exist but before we fix that let's just give it all the attributes we need so we're going to use the route that href or you can use route that label like we did in the desktop item both are unique href is going to be Rob that href active is going to be around that active icon is going to be route that icon and on click is going to be route dot on click like this and I'm going to save and I'm going to get my error now I'm going to go back into my uh components sidebar and I'm going to create a new file mobile item dot the SX like this great and in this mobile item let's first just quickly fix the error so mobile item the mobile item like that and let's go back into Mobile footer now where the error is and let's just import this there in the same folder very simple to import and just save the file and the error should go away and you can see I'm going to zoom in you can see how here I have mobile item one mobile item 2 and mobile item three great great job all right now let's go back into Mobile item right here and the first thing I want to do is Mark this as use client at the top and I'm going to import link from next slash link and I'm going to import clsx from clsx like we did in the desktop item great now let's write the interface mobile item props and it's going to be pretty much the same href a type of string icon I type of any active and optional Boolean and on click and optional empty void function like that and let's just assign this props here so react react FC mobile item props great uh okay make sure you do not misspell it oh I said mobile items so the correct is mobile item a singular item like that so mobile item props any mobile item props here now let's just extract all of this so href icon active and on click Perfect all right now let's write our handle click the same way we did in the desktop item so const handle click a very simple arrow function which checks if on click exists and in that case just Returns on click like that make sure you do not uh put the wrong brackets here like I did like that perfect uh and now let's actually go ahead and style this so instead of returning a div we're going to return a link components here let's give it an href of href so we immediately fix that error if it happens all right and inside of that link I'm gonna give it an icon like this now we get an error because this icon does not exist that's because we have to remap it to Capital icon in the props the same way we did with the desktop item like that great and now at the bottom you can see I have three uh little items I'm going to zoom in so you can see them so we have three little icons here great and what I'm going to do is I'm gonna add a couple of attributes to this link right here so I'm going to give it a non-click I'll click I'm going to give it some href okay we already have the href let's start giving it some class names so class name is also going to be clsx same rules apply you can use the normal annotations for the second tutorial I'm going to use backticks so I can uh write them in multiple lines so group Plex Gap Dash x-3 backslash SM leading dash six pump Dash semi bold W Dash full justify Dash Center gray 100 like this okay I can zoom out a bit now they're starting to get too big uh and I'm just gonna write a comma at the end of this string of the clsx and I'm going to give it a conditional active and and PG Dash gray Dash 100 and text that's black like this and you can see how it now selected our users great and I'm gonna give this icon a class name of h-6 and W uh six like that and now the icons are a bit larger great now we have uh our uh mobile folder but if I expand the screen enough you can see how we also have the desktop sidebar great great job and you can test to see if the logout works on mobile as well so I just clicked here and there we go I am logged out I'm gonna go back in I'm going to click sign in and you can see that now I'm both our desktop logout works and our mobile work logout works as well great great job I'm going to zoom out a bit so we work in the desktop mode from now on so just to recap everything we've done here we did a lot of work so uh first things first we created this user's uh layout page and layout and Page make sure you do not accidentally put use client in this user's page because that causes an error we created this empty State component right here which we use when nothing is selected uh besides that we also have the layout with fix this sidebar error because it is a returning a promise which is not something that react is used to uh we created the actual sidebar component which renders desktop sidebar and mobile sidebar depending on the resolution of our screen we created two hooks uh use conversation which handles our active conversation which you will see in the future right now it doesn't make much sense but uh it's all going to make sense in the future and we also have the user out hook which uh the only reason we created them in a hook is because we want to uh dynamically change their active status depending on the current uh route or if conversation ID is open or not great great job so we're going to continue now and what we're going to do is we're actually going to fetch the current user which is logged in so we can display a little Avatar here at the bottom in order to do that first we have to Define some actions here so I'm going to close everything here and I'm going to create a new folder inside our app called actions my bad it wasn't focused on this window actions like that and inside I'm going to create a new action get session.ts like this it's going to be a very simple action we're going to import yes session sorry the server session from next dash out and we're going to import out options from dot dot slash API slash out slash square brackets our dot dot dot next out slash route so if you remember what this is it's our uh that is our app folder API out next out route and what are these out options well it's this thing we exported here if you remember I explicitly said that we're gonna need to export this constant out options which at the bottom we use in the Handler here so just make sure you separately export this out options from here and you will have no problem importing it just like this so just go ahead and locate uh your out options from here great and a very simple action expert default passing function get session and all it's going to do is return a weight get a server session and you're gonna pass in the out options like this perfect and now that we have this get session we can actually create another action called getcurrentuser.es like this this one is going to be a tad more complicated so first import Prisma from add slash app slash lives Prisma DB then below that import get session from dot slash get session because they are in the same folder of actions great now right oops okay so now write const get current user synchronous function open a try and catch block so let's just fix the catch first so if there is an error which is a type of any all you want to do in the action is return null we don't want to throw any errors because that's going to break the application this is not an API route this is a server action all right now inside of here first let's get our session so console session is equal await get session like that so the only reason we separated this get session is so we don't have to write this every single time so we don't have to import out options and then pass it to get server session simply we can do this once and then use it in the actions as we need it great and now what I'm going to do here is I'm going to check if the current session exists so if there is no session question mark dot user question mark dot email in that case I'm just going to return null no current user found otherwise let's go and search for the current user using that email so const current user is equal to a weight Charisma dot user dot find unique where email is equal to session.user.enail as string just like that great and now we're going to check if the current user exists so if there is no current user I'm just going to return email like this otherwise return current user like that perfect and now we can go back into our sidebar component so go into app components a sidebar folder and pick the main sidebar.tsx right here and remember we made this as an asynchronous function which means that we can uh await a get current user in here so what I'm going to do is write const current user is equal await get current user like this let's just go back into our get current user to see if we exported we did not so in this get current user just make sure you do export default get current user at the bottom like that so inside get current user just ensure that you export default now go back into sidebar and it should automatically create an import for you like this from at app slash actions slash get current user perfect and now we have this current user right here and I want to do is I want to pass it to desktop sidebar so I'm going to write current user print user like this and inside desktop sidebar we have to Define uh props that can accept the current user so go ahead and write interface desktop sidebar props current user is a type of user which you can import from at Prisma slash client this is generated because year run MPX Prisma DB push and npx Prisma generate in all of those commands which have been run by Prisma command line interfaces so it's exactly as you define in your schema we have ID name email email verified image hash password everything we defined in our schema great and now let's assign these props here so react FC desktop sidebar props and let's just extract the current user like this perfect and what I'm going to do now in this client component I'm just going to console log the current user so we can go ahead and see it so I'm gonna collapse everything here so I can open my sidebar here and I'm going to refresh one more time and you can see that we have the current user perfect but one thing that you're going to notice right now if you look into your terminal um you will find not exactly an error but a warning uh which will say that you are passing uh date objects in the client component so in order to fix that uh what you can do is you can install a certain plugin as an npm package so we're going to go ahead and do that I'm going to go back into my terminal again I'm going to shut down the application and I'm going to run npm install next Dash super Json Dash plugin wait a couple of seconds for this to install great now that is here do not start the application yet before you do that go back into your next dot config.js right here and inside what you're going to do just below this app there you're going to add SVC plugins you're going to open uh an array and inside that array you can open another array and write next Dash super Json Dash plugin you're going to add a second parameter here which is just an empty object like this great and now go ahead and run your application again so NTM run Dev again and I'm going to close the terminal for now and I'm just going to refresh everything here what this super Json plugin does is it sanitizes our objects so that we can safely pass them even though they have date objects and other complex uh properties which are not compatible uh when passing from server components like sidebar into a client component like desktop sidebar for example so just wait a couple of seconds for this to initialize great so I had my app up and running again and now those terminal errors will not appear this is uh something that happened in the Airbnb video and we did a very complex way of fixing it but thankfully there is this next Super Json plugin which now supports next 13 and can fix that for you all right and now what I want to do is I'm going to go back into sidebar and just quickly fix this error by just adding a exclamation point at the end so we it's possible for the user to be null as well great great job now let's go back into desktop sidebar and we're going to start to develop our Avatar all right so I'm going to close this right here and I'm going to zoom out even more just so I can see the desktop version because that's what we're going to be working with all right so right here at the bottom where we Define this navigation um below that we're gonna open another navigation right here and we're going to give it a class name of empty-4 Plex Black slash call justify Dash Queen and items Dash Center like this and inside what I'm going to do is open a div element and I'm going to give it a couple of attributes so first I'm gonna do on click I'm gonna open an arrow function I'm going to set set is open the true where do we get this set is open well we defined a little State here which yet we do not use but we're going to use it in the future to open the settings model which we're also going to add but that's for the future all right and besides this on click we're also going to need a couple of class names so let's give it a cursor Dash pointer hover opacity Dash is 75 and transition like this perfect and what's gonna be inside is our Avatar component which we do not yet have so we're going to get an error course but we're already going to pass some properties here so just write user is equal current user like this save the file and of course we're gonna get an error because Avatar does not exist so let's go ahead and fix that so I'm just going to close everything here and I'm also going to collapse everything so go into your app in the components and create a new file avatar.psx like this I'm going to quickly fix the error error so I'm going to write avatar they've like this and I'm going to go back into my sidebar into a desktop sidebar right here and I'm just going to import the avatar from dot dot slash Avatar like this and I'm just going to reorder my uh Imports a little bit so they look nicer all right so import avatar from dot dot slash Avatar in the desktopside our component so here at the bottom you do not have this error great we still have an error because of the types but don't worry we're gonna fix that in a second if you look closely you can now see this Avatar little button sorry Avatar text at the bottom of my sidebar navigation we're going to turn that into an image now all right so what we have to do now is Define this Avatar as a client component because we're gonna in the future we're gonna use some hooks here but that's uh we're gonna not gonna do that now we're gonna use that for an active status all right now let's write an interface for our Avatar so interface Avatar props user user from Prisma slash client like this let's assign these props other props and let's extract our user like this perfect and now let's give this some class names so the first div is going to have a class name of relative like this now inside of that we're gonna create another div with the following class names so class name is going to be a relative inline Dash block rounded Dash full overflow Dash hidden h-9 W-9 mdh-11 and MD W Dash 11 clap this all right and what we're going to write inside of this is our image component but before we do that we have to add a placeholder image to our project in order to do that you can either Google placeholder in Google or you can go into my repository into public into images and find placeholder that uh JPEG and you can just save the image and you're going to drag and drop it in your project in public images file right here so I'm going to drop it the same way we did with logo and make sure you rename it placeholder like this so it doesn't have any numbers in it perfect all right now I'm going to go back um into my avatar component which we started working on and let's actually add the image so we're going to use next image image which you can import from next slash image just like this it's a self-closing tag and let's give it an out of Avatar let's give it a source of user question mark dot image quite pipe slash Images slash placeholder .jpg like this and I made a typo here it's dot image like this perfect and make sure you use the fill attribute as well and now I'm going to save the file and you can see that I have this empty placeholder image right here now there is a chance you might have gotten an error here I'm going to demonstrate that now so I'm going to purposely log out now and I'm going to log in using my GitHub or my Google account just to show you what happens all right so we have some errors because uh I need to clean my users so just a second let me resolve this in my database all right so I logged in with my Google account and you can see that I have this error invalid Source Pro that is because whenever we use next image we need to Define where the image comes from in order to fix this we have to go back into our uh next config so next dot config.js the same place where we added the super Json plugin and just outside this experimental object I'm going to add images open an object right domains open an array and we're going to resolve a couple of them so first we're going to resolve res Dot cloudinary .com then during the result of avatars dot GitHub user content.com and lastly lh3.googleusercontent.com if you're not sure what this is written here you can actually just copy this whatever the error says you can just copy it and paste it in your images domains like this great and now I'm just going to refresh everything to see if this has been resolved in just a moment great and now you can see that the I'm using my Google image here which was automatically pulled from my login perfect so if that happens to you just make sure you add this to your images right here and now I'm just going to wrap up my avatar component so I'm going to go back into Avatar right here so you you saw how it looks when we use the placeholder now you see how it looks when we use the user image and one more thing I'm gonna add here is for now I'm going to hard code um this active status for us later on we're going to make it Dynamic depending whether the user is actually active in the messenger so just write a span element here and it can actually be a self-closing tag like this and let's just give it a couple of class names so class name is gonna have an absolute position block rounded Dash a pull BG Dash green Dash 500 ring Dash 2 ring Dash white top Dash zero right dash zero h-2 W-2 MB h-3 and MD w-3 as well and now after this hot reloads you can see that I have a nice little uh Green Dot on my avatar and you should have it here as well perfect uh you've finished passing the current user uh to the sidebar you have a little Avatar here great we are ready to start working on the user list and start creating some conversations so let's continue and let's create our users list in this white space right here but before we go there I just want to fix a typo I made in the last part so go back in your next dot config.js right here and I misspelled the cloudinary so just make sure it's rest.claudinary.com like that and save the file but don't worry even if we misspelled something here you are gonna get an error if you use an image from a host which is not in this images domains array but you can fix that very easily but just copying the host from the error and pasting it here but if you have the config like this it should not happen in this tutorial great so what we have to do now is create a action to get our users so let's go into app folder into actions and create a new file getusers.ts inside let's write the following let's import Prisma from add slash app slash Libs Prisma DB and let's import that session from uh dot slash get session like that because they are in the same folder actions great so const get user is an asynchronous arrow function first we're gonna get the session so concession is equal wait get session like this and then we're gonna check if we have the session so if there is no session question mark dot user question mark lot email in that case we're gonna return an empty array and now let's open our try and cash block right here in the catch let's first solve the error so the error type is any and we are going to return an empty array here as well and now in the try we're gonna try and find all of the users excluding our own user because in this list of users we want to show all the people who use our messenger but we have no reason to show ourselves here because we don't want to start the conversation with ourselves so const user is equal to 08 Prisma dot user dot find many first you're going to order by created at the sending so the newest users are at the top and where is going to be a special query Capital not like this open an object email session dot user dot email like this so what are we doing here well first of all let's rename user to users like this so it's correct because this is an array of users we are using find many we are ordering all the users by newest using created at descending here and this query what it means is that we are finding every user where the email is not our current user so that's the way we are going to eliminate our own user from the list of these users and very simply we can just return users at the end right here perfect that is it per hour get users action and let's just rename this to get users so const get users and don't remember to export default yes users at the bottom like this perfect so now that we have this finished let's go back and I'm gonna close everything for now and let's go into app folder into our users folder into layout.dsx and since this is a synchronous server component we can call get users inside of here without need for an Avi call so I'm going to write const users is equal await get users from dot dot slash actions slash get users just like this perfect and we're gonna pass these users to a new component called user list and we're going to create that right here so go ahead and write user list like this and we're going to pass in items users like this and if you save of course we're going to get an error here so I'm just going to refresh so everything is up to date and there we go I got this error you probably have the same error as well so let's go ahead and let's go in our users folder create a new folder called components and inside of there you're going to create a new file user list.tsx and let's just quickly fix this so name it user list like this and I'm just going to return a div which says user list like this perfect and now I can go back into users layout.tsx and I can import this from dot slash components slash user list and save the file and in a couple of seconds this should get fixed and you can see how it says user list right here perfect now we have this typescript error which we are going to fix very soon so let's go back into our users list and let's map this as use client right here at the top great and now let's write the interface so interface user list props is going to hold items which is a type of array of users so go ahead and import user from add Prisma slash client and just put a little array at the end so that Styles typescript okay this is an array of users perfect now let's just assign this so react function component and just put in user list props like this and inside you can destructure items like this perfect great now instead of writing this div we're going to use some bit more semantically correct elements here so go ahead and write aside like this and you can close a site like that let's go ahead and give it some class names so class name fixed instead Dash Y dash zero db-20 LG pb-0 LG left-20 LG w-80 LG block overflow Dash Y dash Auto border Dash R order Dash gray-200 block W Dash pool and left Dash zero like that perfect now inside of here we're going to create a new div like this I'm going to give this a class name of px-5 like that and inside of that we're going to create another div with a class name of flats Dash hole perfect and let's create another did inside with the following uh class names so we're going to give it text to XL font Dash bold backslash neutral Dash 800 and ty-4 and we're gonna write people or you can write to users whatever you like but I think people uh looks just fine great all right and your people should look like this so you should have a bit of a padding and it should have uh this bold font right here perfect uh and now just below this div right here uh we're gonna create uh an iteration over these items and we're gonna create another component called user box so just make sure outside of this div outside of this div you're going to create items.map item and it can immediately return user box like this and before I save the file I'm just going to write key item.id and data is going to be item like this and once I save I'm going to get an error because because user box does not exist all right so let's open our users folder components again and create a new file userbox.the SX like this let's map this as use client right here and let's just quickly fix the error so user box like this and I'm just gonna say user like that let's go back into our user list and just import this newly created user box at the top dot slash user box like that and once you save the file the error should go away and you can see I have a single user which is not mine user if you're not seeing any users here that means you have not created any additional accounts so in order to do that just log out for now and you should be greeted with our registration screen and just click create an account and just make sure you create another one so this is going to be called new newmail.com one two three three two one and Press Register and you're gonna have another user in your database beside the one you were just using and you can see now I have two users here excluding my user that I'm logged in as so just make sure you do that otherwise you're not going to be able to see any users because we exclude our own user from the get users action great now let's go back into user box right here and let's write an interface for it so interface user box props data is going to be a type of user which you can import from at Prisma slash client just like this and let's just assign these props so user box rocks like this and you can extract data like that perfect uh what I want to do now is I'm going to add a router I'm going to add some states and some on click functions here so first let's add our router so const router is equal use router from next slash navigation like that const is loading set is loading it's going to be your state false we're going to use this later but I just want to prepare it right now and you can import new state from react right here at the top great now let's add our handle click function here which is going to point to an API call which for Now does not exist but we're going to create that just after we finish this so const handle click is a use callback function so we can memorize it make sure you put the dependency array right here and you can import use callback from react the same way you did with us State all right first let's set the loading to true to set is loading is going to be true and after that we're going to call axis which you can import from axios like I did right here and we're going to call a DOT post slash API slash conversations and in the body we're gonna pass in uh user ID data dot ID all right so what does this mean well we're going to initialize an axis postcode to a route which we do not have at the moment it's going to be API slash conversations and in the body element we're going to send the user ID that we are starting the conversation with right so if I click on the first user let's say the name is Antonio I'm going to start a conversation with Antonio all right and now in the uh dot then function right here uh once I get the data I'm already going to prepare this what I'm going to do is router.push and open back ticks like this slash conversations slash and just open this special object so you can write inside backticks data.data dot ID like this which is going to exist in the future and that finally you can just say set is loading in false like this and in the dependency array make sure you put data and rather like that perfect now you can go ahead and actually style our user box right here so instead of this div like this we're going to add an on click we're just gonna call handle clicked like this which we just defined and let's add some class names here so the class names we are going to have are W Dash full relative blacks items Dash Center space Dash X slash three BG Dash white p-3 hover BG Dash neutral Dash 100 rounded Dash LG transition and cursor Dash pointer like that great and inside of this first we're gonna add our Avatar components which we created while we were working on the sidebar and you can import avatar from add slash app slash components slash out there so it's in the root of the components file it is not in the user's components it's in This Global components we have in the app folder right here great and now that we have this what we can actually do is we can pass the user as data like this because our data prop right here if you look at the user list uh if you look at the items those are the users so we know that the data here is the actual user so you can just pass in data here and great you can see how I already have these images and uh well right now A hard-coded active status which we're going to change in the future but you can already see how good this looks already great below this Avatar create another div with a class name of min-w-0 flex dash one like that and inside of that we're going to create a class name of focus outline none like this and inside of that we're gonna create a span with a class name of absolute Dash inset sorry absolute inside there's zero so two separate classes uh actually we don't need this at all my bad you can remove this span and you can immediately go ahead and write a div with the following class names so class name is going to be Plex justify Dash between items Dash Center mb-1 like that and inside of that div just open a paragraph right here and write The Following last names so we're going to have tax Dash SM Point medium and tax Dash gray Dash 900 and inside of the paragraph we're going to render data dot name like this great and now we have Antonio and Antonio's right here so Antonio is the one I created using credentials and this one with an image is the one I created using um social login and I'm gonna open my network tab in here just for you to see how once I click on it it's going to call something so once I click here you can see uh that it tried to call uh Slash conversations but since it does not exist we get a 404 so that is a completely expected don't worry about that for now and while we are here you can actually see how this looks on mobile as well so we have a list of people which takes the entire screen which is uh what we want in our design great great job uh you finished the People page now we're gonna start working on the conversation page page so let's continue and let's create an API route to create our conversations so let's open our sidebar and I'm going to collapse everything here I'm gonna go into the app folder into the API folder I'm going to create a new folder called conversations like that and in the root of that folder I'm going to create a new file called route.ds like that first I'm going to import get current user from add slash app slash actions get the current user like this then I'm going to import next response from next slash server I'm going to import Prisma from add slash app slash Libs Prisma BB and I'm going to uh well that's it for our inverse for now uh what we're going to do next is we're going to create our post function for this route so go ahead and write export async function host which accepts the request which is the type of request open this function and first let's open a try and catch block right here so the error type is any like this and what we're going to do in the cache block is return new next response internal error with a status of 500 like this all right and now we can go back into our try route right here so first let's get the current user const current user is equal to await get current user below that we're going to parse our body so constant body is equal to a weight request dot Json like this now we're going to extract all the possible values from our body so const open an array say equal body like this and now inside of this array we're gonna destructure all of the possible properties which we can send when creating a new conversation so so far what we know is from user box once we click on the user box we know that one of the fields we will definitely have is a user ID and that is for creating a single one-to-one conversation but our conversation route is also going to be able to handle group chats so that's what we're going to have a bit more elements in this body that you might think where did they come from well I'm just preparing for the future because we're going to need all of those values so first one is user ID we know that from the user box below that we're going to have an option is group which is a Boolean below that we're going to have members and we're going to have a name so user ID is needed if we are creating a one-on-one conversation but if we are creating a group we are also going to need members and we're going to need the name of that group chat because if we only use the user ID in that case the name of the chat is going to be well different for every user for me it's going to be Antonio for Antonio is going to be whatever the name uh is that I have in my account all right now let's write an if Clause to check if we have the current user so if there is no current user question mark dot ID or if there is no current user question mark dot email in that case we can return new next response unauthorized with a status of 401 like this great below that we're gonna check if we send uh is group true but we have not sent members or we have not sent name so if is group and open parenthesis if there is no members at all or if members.length is less then two or if there is no name in that case we're going to return new next response uh invalid data with a status of 400 great so if we send is group to true and if there are no members sent or there is not enough number of members to create a group chat or if there is no name we're going to send an error invalid data great all right and now let's create the code to create a group chat if this group is present so open an if Clause if is group like this and inside we are going to create a new conversation so const new conversation is equal to await Prisma dot conversation dot create inside I'm just going to expand my code a little bit so this collapse to mobile view for me don't worry uh what I'm gonna do inside this create is write some data so first I'm going to pass in the name for the group chat I'm gonna pass in the is group Boolean and for the users we're gonna immediately connect them using Prisma so connect open an array and inside we're going to spread members .net member which is going to have a type of value string like this and open an arrow function inside and open and return an immediate object here with an ID of member dot value like this and below that add another object with an ID of current user dot ID all right so we have this connect array right here which separately adds the current user to the group of members because when we create a group chat again we are not going to send our own ID there because we're going to filter out our user from the list of possible users to add in a group chat so that's why we need to separately add our user to the group as well if we are the one creating a group chat and what this function does right here is it iterates over the array of members which we passed which are going to have a value object inside of them which is going to serve as an ID and we're going to use the ID to connect our users great great job so now we have this new conversation right here and just below this data I'm also going to add a comma and write include users true what include users do does is it populates the users when we fetch the conversation so by default when you get a new conversation you're not gonna get uh an array of objects of your users inside of that group chat you're only going to get IDs but if you want to work with those users for example display their image or display their name you need to populate them and in Prisma we do that using include the field we want to populate and true like this perfect and now that we have this new conversation right here all we have to do is write return nextresponse.json new conversation great so we finished our group chat logic here now what we're going to do is we're going to handle a single one-to-one conversation creation it's going to be a bit different from group chat because if you notice when we create a group chat we don't check if a existing conversation if an existing group chat exists with those exact numbers because we do not care people can create as many groups yet as they want with the exact same members if they want to but for single one-to-one conversations we have to check if there is an existing conversation with that user so what we're going to do is write const existing conversation is equal to a weight Prisma dot conversation dot find many now why do I use find many and not find unique well because we're going to use a special query which only is supported in find many unfortunately but that does not prevent us from doing uh from not being able to do what we want because all right we're just gonna get an array and then we're gonna have to extract the first one from the array so to be more correct we can name this existing conversations like this because it's multiple of them uh even though it's gonna be only one inside of the array uh I just want to follow the semantics because this is going to be an array of conversations great and what I'm going to write inside is a where uh query right here and inside of there we're going to write a capitalized or and the capitalized or is going to have an array inside so just open that array like this open an object and you can write user IDs you're going to write another object inside of that equals the current user.id comma user ID like this and in uh we're going to create another object exactly like this inside of this or array so open another object inside and write user IDs again equals again user ID current user dot ID now I'm not exactly sure if we have to do this but I did encounter some errors where I had an existing conversation but for some reason another one was created so this just covers uh uh all of those cases great so what we do is we look throughout all of the conversations that exist we search for the user IDs field and we are going to find if there is a conversation which has only these two users so the user that we're currently logged in as and the user that we are trying to start a new conversation with if it already exists we are not going to create a new one for them great so now that we have these existing conversations right here let let's extract the only existing one like this so const single conversation is equal to existing conversations which we have from right here just open an array and pick the first one inside like this and then you can safely write if there is a single conversation in that case we can return the very same conversation back to the user instead of creating a new one so return nextresponse dot Json single conversation like that perfect and now we're gonna handle creating a new conversation if this query does not exist so just below this I'm going to write const new conversation is equal to await prisma.conversation dot create like this and for the data I'm gonna give it a user's object and I'm going to again connect the users we are using so the first user we're going to connect is of ID current user.id which is ourselves and the second user we're going to connect in this conversation is the user ID which we pressed from the user box right here and also just below this data object we are going to write include users true because we need them uh because we're going to use them in our UI so that's why in here for example we did not need to include those user because we don't want to do hard on our database queries if there is no need to but in this case we do need our users so that's what we're going to include them perfect and right here at the bottom all you're going to write is return nextresponse dot Json new conversation like that perfect now that we have this saved what I'm going to do is I'm going to expand this window and I'm going to open my network tab one more time if you remember previously I got a 404 error for my slash API slash conversations route and I'm also going to prepare my database here so you can see my conversations are completely empty right now I don't have a single conversation but once I click on Antonio it should create a new conversation so let's see if that works and it does and we are redirected to slash conversations and slash conversation ID but we get a 404 here because we did not create a UI route for that but that's completely fine let's go back into our database and let's click refresh in our conversations to see if we created the new one and we did and you can see that it has two users inside one of them is the user I'm logged in with and the other one is the one I clicked in the user box in my case it's Antonio a great great job and just to get rid of this error you can go to slash users back here so you don't have this ugly error here great and now that we have this existing conversation try and click again on the very same user what should happen is you will be immediately redirected to an existing conversation and if I click refresh right here I should not have two conversations great I only have the exact same one because it has already been created so we are not going to create a new one if there is no need to do that great so again just go back to slash users so you don't have this error and in the next part we're going to create our slash conversations so we don't get that ugly 404 page great great job so let's continue and let's create our slash conversations route which will be triggered once we click on this chat icon right here so I'm gonna go and I'm gonna close everything for now I'm going to expand this window a little bit and inside my app folder I'm going to create a new folder called conversations like that and inside of there I'm going to create a new file page.tsx like this I'm going to mark this as use client I'm going to import clsx from clsx and I'm going to import use conversation from dot dot slash hooks use conversation we created this when we were creating our sidebar because we needed to use it in our use arouse so this is how it looks like if in case you forgot all right now that we have this we're also going to import empty state from dot dot slash components slash empty State and that is this select chat or start a new conversation box right here so we're going to reuse it the same way we did for the user list right here great and I'm going to write cons the home it is a very simple arrow function and first we're going to extract is open from use conversation like this and then we're going to return you're going to return a div like this and inside we're going to put empty State like that and we're gonna ask for default uh home just like this perfect so now when I click on slash conversations or on the chat right here you can see that I am right here and it looks a bit weird but don't worry we are going to fix that now in this div right here open class name and make sure it's clsx like this in the first argument I'm gonna write LG pl-80 H dash full and LG block like this and for the second argument I'm going to use is open conditional to trigger either between blocked or hidden like this perfect so now it's uh it fits the style of our um uh users list great so basically what's gonna happen uh once I Collapse as you can see it's going to remove dynamically and also some other things are going to happen once we implement the actual conversation view where you will see this is is open uh in full effect perfect so now that we've done that we have to go and create our layout for conversations so go ahead and write layout.dsx like this and you're getting an error because there is no default export here right now so go ahead and write export default as synchronous function conversations layout like this and the prop is going to take its children and you can immediately create types for that so children is a type of react.react node perfect so go ahead and open this and first thing we're going to get um well we're just going to return for now the sidebar like this which you can import from dot dot slash components uh Slash sidebar slash a sidebar component we already did this for the users and inside what we're gonna do is we're going to create a div with a class name of H dash full like this and inside we're just gonna paste our children like this and I will save this layout and it will automatically hot reload you can also manually refresh if it doesn't do that for you and now you can see uh that I have my uh sidebar here as well and now we have this error right here for the sidebar and you can fix that exactly the same way you did with the user list so TS Dash expect Dash error server component just like this perfect and what we have to add now uh is another component called uh conversationalist so I got an error here I think it's just cash uh okay let me see what's going on here all right so I had an error with cash if your screen did not fill this entire if your empty state did not fill this entire screen under conversations and you got that same error that I did all you have to do is shut down your application and run npm run Dev again so it's a simple cache issue uh nothing too complicated to fix great so let's continue now and let's go back into layout and below this H4 I'm gonna write conversation list like this and I'm gonna pass in initial items which are going to be well for now just an empty array like this so just go ahead and save this and you're gonna get an error right here so in order to fix this what we have to do is we have to go in conversations and create a new folder called components like that and inside of that create a new file called conversation list.tsx like this and let's just quickly fix the error so conversation list the conversation let's like this and go back into your conversations layout and just import that component from dot slash components slash conversation list and the error should go away and now we have to find a way to fill these initial items before we start and develop this conversation list so in order to do that let's create a new action in this actions folder called get conversations dot TS like this great now let's import Prisma from add slash app slash live Prisma DB like that and let's import get current user from dot slash get current user because they are in the same folder right here let's write const get conversations which is an asynchronous function and first let's get the current user so const current user is equal to await get current uh get current user like that if there is no current user question mark dot ID in that case just return an empty array now let's open a try and catch a block the error type is any and the same thing just return an empty array if there is any error perfect now let's go into our try block right here and let's find the conversations so const conversations is equal await Prisma dot conversation dot find many and in the query first we're going to order them by last message at descending what this means is that we are going to order our newly conversations uh by the latest message that has been sent in them so we are not going to order them by newest we're going to order them by latest active so if a user sent a message in one of the conversations that is going to be our most top conversation all right now another query we are going to do is where and first things first user IDs has current user.id so we're going to load every single conversation that includes our current user that includes single one-on-one conversations and group chats so with this very simple query we handled all of those cases what we have to do now is populate uh some of the fields we have in the conversations model so go ahead and write include users true now if you're wondering how do you include something inside of the users or something inside of this property well for example we will want to include messages so we can just write true but I also want to populate the users inside of those messages so what you can do is instead of writing true open an array inside like this and again write include and what we're going to include from the messages is sender and scene sender is the author of the message and scene is an array of people who have seen delay the latest message perfect you can close this and you can safely just return conversations like that and just make sure you write export default use conversation sorry uh not use conversations but get conversations like this so very simple action uh and just remember to export the default get conversations great now that that is done we can go back uh into conversations layout that DSX right here and now uh we can uh safely uh since this is a synchronous server component we can now safely load the conversations here so I'm going to write const conversations is equal to await get conversations from dot dot slash actions slash get conversations it's at the top of my file right here perfect and now that I have that I'm gonna pass that instead of an empty array right here perfect and now we can go back into conversationalist component and we can start uh developing here so first thing I'm going to write is an interface uh for our conversation list so I'm gonna write conversation list props I'm going to write initial items which is uh gonna be an array of conversation from Prisma client like this and make sure you mark this as you use client like that and we're gonna assign this right here like that and then you can extract that as initial items like this why do we call this initial items well because uh later in the tutorial uh we're going to update these items in real time using Pusher which uses sockets underneath so it's incorrect to name these items since they're going to just be used as an initial uh load for our messenger but we are actually going to sorry I did something with my screen but we are actually going to update those messages dynamically depending um on the real-time sockets and Pusher all right and now that we have uh This what I want to show you real quick is if you go back into layout right here you will see that the types we are sending to the initial items is not the same that we are receiving from our action you can see that what I get from a weight get conversations has a scene which is an array of users and a sender which is a user as well as users which is a user but in our conversation list initial items is just a simple conversation and you can see that it uses user IDs instead now you might get a typescript error for this I'm not getting it right now but I remember during development I definitely got this error so I'm going to show you how to properly create types for this so we're gonna go and I'm going to collapse everything here and inside the app folder create a new folder called types and inside of that create a new file index.ts like this and I'm going to import conversation message and user from at Prisma slash client like this and now that we have this import we can write a a couple of special types for us so export type cool message type is equal to message and sender which is the type of user and scene which is an array of users like this and we are also going to export type full conversation type which is a type of conversation and users which is an array of user and messages which is the title full message type like this and now that we have this full conversation type just make sure you save this file and make sure you wrote in you've written export here we can use this full conversation type inside of our newly created conversation list so I don't want to use this conversation I want to use a full conversation type and I'm going to import it from add slash app slash types and then you can remove this just like that and now I'm gonna go back here and see okay so now I have this error so I'm just gonna quickly see what's going on here all right so I made a small error so let's go back into our uh types folder which we just created and instead of a single full message type we have to add an array here like this and now if you go back to layout you can see that what we send and what we expect is a full conversation type and it is exactly matching and you should not get any errors so just to recap what I've done right here so in conversationalists right here I've assigned a new type full conversation type and array at the end and if we take a look at what full conversation type is it uses the existing conversation but it extends it to fill to give types of populated user and populated messages why do we need that well because in our get conversations we use this include which populates the users and populates the messages so that's why the types were incompatible so we have to manually resolve them if you are still having errors uh just confirm you can also use my GitHub which is in the description that your types are exactly like this confirm that you're correctly adding the include light right here and in Last Resort you can try and just reload your window like this sometimes typescript gets cached inside but if you want to be 100 sure you can hover your mouse over get conversations and once it loads it's going to show you what kind of type it is returning so if I hover here okay it's still loading let's just wait a second great so you can see that I'm returning a conversation and messages and messages has seen and sender and users and it's an array and you can hover here to see what you're expecting to get perfect now let's go back uh in our conversation list so I'm just gonna find it right here I'm gonna close everything else great now in this conversation list first things first we're gonna assign this initial items to a state so go ahead and write const items set items is equal use state which you can import from react and just pass in initial items like this great below that we're going to add const router is equal use router and you can import router from next slash navigation just make sure you do not accidentally import it from router the correct is navigation like this perfect below that we're going to use our use conversation hook which we already used a couple of times so const use conversation like this which you can import from add slash app slash hooks use conversation right here and you're going to destructure inside conversation ID and is open like that perfect now we can go ahead and we can start styling our conversation list so instead of returning a div we're going to use this semantically correct aside element like we did in the user list great now let's write some class names so class name is going to be clsx right here and as always you can use the strings here but I'm going to use backpicks so I can safely write in multiple lines here and make sure you import clsx from clsx I'm going to put it to the top right here and I'm gonna quickly organize my stuff like this beautiful all right now inside of this clsx let's write some class names so it's going to be fixed instead Dash y Y dash s0 pb-20 LGB Dash 0 LG last Dash 20 LG W Dash 80 LG block overflow Dash Y dash Auto border Dash R border Dash gray Dash 200 like this and in the second argument of the clsx what I'm going to write is a conditional so I'm going to use is open question mark hidden otherwise I'm gonna use block W Dash pull left-0 like this perfect so now you can see I have the exact same thing as we have in our users except in the users we actually love the users but we're gonna do the very similar thing here uh for the conversations perfect so inside of this aside element create a new div like this and give it a class name of px-5 like that inside of there we're gonna create a new div with the class name of Plex justify Dash between mb-4 and pt-4 like that inside create a new div and just write messages inside and messages should now appear right here perfect now let's style this so let's give it some Styles uh text Dash to excel font Dash bold and text neutral Dash 800 so the same thing with it with uh users perfect now it looks very nice all right now below this div I'm going to create another div and inside I'm going to add a react icons icon so I'm going to use MD outline group AD like this and I'm gonna import this right here at the top so I'm going to import and the outline group AD from react icon slash MD like this perfect and now I'm Gonna Save this uh and you're probably uh I'm gonna refresh this just to see if it's visible or not so it's taking some time for me there you can see a very small icon that has appeared in my corner so as always if your Hopper load stops working you can just manually refresh next 13 can be slow in development it is still very experimental all right and now let's actually style this uh MD outline group AD here so first I want to give it a size of 20 so it looks a little bit bigger than this and now let's go ahead and write some class names here so class name is going to be rounded Dash full p dash 2 dg-3-100 backslash gray Dash 600 cursor Dash pointer hover opacity Dash is 75 and transition like this all right I'm gonna refresh one more time and there we go we have a nice little icon right here in the corner perfect exactly what we wanted so for now this is not going to do anything in the future it's going to open a model to create a group chat all right and now just below uh this uh to divs right here we're going to create uh an iteration over our items so I'm going to write items.net item and I'm going to immediately return a conversation box like this right now it does not exist so of course if we save we are going to get an error but I'm also going to populate it with some attributes here so I'm going to give it a key of item dot ID I'm going to give it data of item and I'm going to give it a selected of conversation ID is equal to item dot ID like this so that is why we needed this conversation uh ID from the use conversation route hook sorry now if I save this file we are going to get an error because our conversation box does not exist so let's go ahead and create that so let's go into our conversations components and create a new file conversation box dot TSX let's mark it as use client and let's just quickly uh fix the error by writing conversation box like this and just return a div conversation box like that go back into your conversation list and just import this uh from dot slash conversation box like this and save the file and the error should go away just wait a couple of seconds and there we go I have uh one instance of conversation if you're not seeing anything confirm that in your database you actually have a conversation if you don't make sure you have enough users in this user page right here which I clicked on is just taking a couple of seconds to compile and make sure you click on the conversation like this so I just clicked on this uh Antonio it's right here and it's going to give me a404 because we do not have the individual conversation ID route yet but if I go back to slash conversations I should have two conversations right now because I clicked on both users and I have conversations with both of them right now perfect so I'm gonna go back into conversation box now uh and I'm gonna start adding some imports here so first I'm going to import use callback and use Memo from react I'm going to import use router from next slash navigation I'm going to import conversation message and user from at Prisma slash client because we're going to need those individual types uh what I'm going to do next is I'm going to install a new package which we are going to need so go ahead and open your terminal I'm going to shut down the application and I'm going to write npm install date Dash SMS like this wait a couple of seconds for this to install and after it's been installed you can go ahead and npm run Dev again and just refresh your page to make sure the app has been loaded great so I have my app up and running again and I'm going to add the import from that package called format so from date Dash FNS like this great and I'm also going to import use session from next slash auth uh sorry next dash out slash react like this and I'm going to import clsx from clsx like that perfect uh and what we're going to do now is we're going to start and write types for this conversation box so go ahead and write the interface conversation box props data is going to be full conversation type which you can import from at slash up slash types which we created just recently and selected is going to be an optional Boolean like this perfect now let's just assign this props right here so conversation box props like that and just this structure data and select it from here perfect all right now we're gonna have to create a hook which is going to help us to select the other user from the conversation because if you think about it when we load our conversations depending on which user is looking at them we do not want to show uh the current user as the name of that conversation we want to show the other user so that is exactly uh what we are going to do now so I'm gonna open my navigation here and inside the app folder I'm going to create a new folder uh sorry we already have the folder called Hooks and inside I'm going to create a new file called use other user.ds like that so very explicit name so we know what it is doing I'm going to import news session from next Alpha slash react like this I'm going to import use Memo from react I'm going to import full conversation type from dot dot slash types and I'm going to import user from at Prisma slash client like that so this is everything we are going to need for this hook then I'm going to write const use other user I'm gonna give it a conversation of a full conversation type pipe I'm going to open an array sorry I'm going to open an object in which I'm going to write users and I'm going to give it a type of user and an array like this and I'm just going to open and return an arrow function for this hook perfect and just make sure you immediately add export default use other user so you don't forget about it all right now first let's get our session so const session is equal use session uh like this and now let's write const uh other user is equal to use memo open an arrow function and give it a dependency array like this and first thing I'm going to do is I'm gonna get the current user email to do that I'm going to use a session so const current user email is equal to session question mark dot data question mark dot user question mark dot email like that and then I'm going to filter to the converse through the conversation users and I'm going to filter out uh whatever is not my user using the email so I'm going to write const order user is equal to conversation dot users dot filter I'm going to find the user and what I'm gonna do is I'm gonna write user.email is not equal to current user email like this so I'm just gonna expand this view like this so you can see so const other user is equal to conversations dot users we're gonna filter through the users and we're going to remove uh sorry we are going to leave only the user which is not our current user so that's how we find the other user the opposite of uh the currently logged in one and all we have to do is just write return other user like this and in the dependency array you're going to write session question mark dot data question mark dot whoops question mark doc user questionna dot email and conversation dot users like this and what you're going to return from this Hook is return other user like that perfect so I'm just gonna bring this back a bit and now we can head back into my uh conversation box now that I have this new hook sorry uh not conversation box Yes Yes actually conversation box right here and the hook I'm gonna use here is the newly created use other user so const other user is equal use other user and you can import it from add slash app slash a hooks use other user perfect and the argument it accepts is either conversation or an array of users which we will use for group for group chats but for now we have this very simple case where we can just pass in the data like this next we're gonna get our session so called in session is equal to use session like this and below that const router is equal use router like this perfect now let's go ahead and write our handle click function so const handle click is a use callback don't forget the dependency array right here and all we're going to do is router that push us backticks slash conversations slash open the special object data dot ID very simple like this and give it a dependency array of data.id and router like that perfect and now we're going to write a couple of constants for the text which we are going to use in our UI so first let's write a constant a variable which is going to be able to fetch the last message sent in the conversation so const last message is equal to use memo which we have imported from react already don't forget the dependency array first I'm going to get all messages so const messages is going to be data.messages pipe pipe empty array like this and the way we can get the last message from this is very simple so I'm going to return messages .length minus one like this and in the dependency array all I'm going to put is data dot messages like this perfect we have the logic to get the last message from the conversation alright now let's create a variable uh to fetch our user email uh you already saw how we did that in use other users so we're going to do a very similar thing but we're going to memorize it because we're going to use it across our other variables in this component so in conversation box make sure you write const user email is equal to use memo don't forget to put the dependency array as well and what you're going to do is you're just going to return session dot data question mark dot user question mark dot email like this and in Independence area you're going to put the very same things of session dot beta question mark use it question mark email like that so now we have the user email and now we're going to write the constant for our scene Boolean so we're going to create a control whether the user has seen this message already or not so write const has seen is again use memo make sure you put a dependency array again and it has seen first we're going to check if there even is an existing last message so if there is no last message return false because it's not possible that we've seen a message that does not exist great and now we're going to fetch uh not fetch but we're gonna structure the scene array so const scene array is going to be equal to last message Dot scene pipe pipe empty array just so we don't break something accidentally if uh dot scene does not exist by chance all right uh and now we're gonna do another check if there is no current user email so if there is no user email in that case we will also going to return pause because we cannot compare uh the scene array with anything so we need the user email to be loaded in order to compare whether it is in this scene array right here great and all we're going to return is return scene array and I'm just gonna you can do this in one line that filter but I'm just gonna do it like this dot filter user user dot email is identical to user email which we've written uh up there and uh since it needs to be a Boolean we're going to use dot length uh is not equal to zero so basically what we're gonna do is first we're gonna check if there is an existing last message if there is no last message we're going to return false to our Boolean as seen because there is no way we can see in that message next thing we're going to do is we are going to structure our scene array using last message dot scene and we're going to use this safety pipe pipe empty array so that we can safely run dot filter on the scenari without JavaScript giving a scenario like you cannot use dot filter on undefined so that's why we do this safety right here next thing we check if there is no user email because if there is no user email there is nothing we can compare it in this filter to how is it possible that there is no user email well that's because the session hook which we use right here needs some time to load so that's why I put it in a used memo here so it's immediately updated once it is loaded perfect and then what we do is we go through the scene array which is going to hold all the users who have seen the message sent and we are going to filter them basically this is just the way there are many ways you can do this but I just chose this method for now I'm going to filter the scenari to only find uh the user which is the current logged in user and I just confirmed that the length of that array is not zero meaning that there is at least one user inside that matches the email of the logged in user meaning that the logged in user has seen this message all right and in the dependency array all you have to do is write user email and last message like this perfect and the last variable we're going to write before we start on the UI is the last message text so const last message and text is also a use memo don't forget the dependency array first thing we're going to do is we're going to check if there if the last message is actually an image right because if it is an image we cannot show any text to the user so what we're going to write is if last message question mark dot image in that case we're going to return return send an image like that send an image just like this all right and if there is a body of the last message that means that there is some text that we can display so if last message question mark dot body in that case we can safely return last message dot body like this so this is going to be the actual message that someone has sent and if there is none of this that means that we have just started the conversation and there is not a single message sent in there yet which is the case for our two conversations because we do not have a functionality to create messages at all so what we do here is we turn it started a conversation like this perfect and the only thing we need in the dependency array is last message like this perfect and now we are ready to start styling our conversation box right here so I'm just going to remove this text inside and first thing I'm gonna do is I'm gonna give this uh some class names so uh before he had a class name actually we can add a non-click to uh trigger handle click which we defined uh it was the first thing we wrote in this functions so a very simple redirect to slash conversations slash the conversation ID this rock does not exist yet but we're gonna do that later on all right below this on click we're also going to add class name it's gonna be clsx and again I'm going to use backticks so I can safely do this in multiple lines I'm going to give it a w Dash full relative Flex item slash Center space Dash x-3 hover BG Dash neutral Dash 100 rounded Dash LG transition and cursor Dash pointer all right and in the second argument of the clsx so you add a comma and then you write a second argument I'm going to use the selected Boolean to either show BG Dash neutral Dash 100 or VG Dash white like this all right and now what I'm going to add here is Avatar and I'm going to give the user of other user like this and we do not have Avatar imported so just make sure you import the avatar from add slash app slash components Avatar and you can save the file and now you can see uh that I have uh the other user uh inside but there is an error we are having here so I'm just going to go ahead and quickly check what's going on here yes so I did a mistake in my use other user hook so that is a very simple fix go back into your hooks use other user right here and instead of returning the entire array because that filter returns an array you can just write 0 like this and that is going to return a single user and I'm just going to refresh my page here and there you go you can see how I now I show uh this Avatar the correct diameter of the conversation of the user I started the conversation with uh perfect so I just want to confirm that you understand what we did with this other user thing so it might use other user hook right here I just picked the first user from this array which is guaranteed for us to be the user which is not our current user so previously I just did this and if that is incorrect because this is an array of users what we want is just a single user so then this return function right here only gives us a single user and then that works well with this Avatar which expects a single user great and in this class names right here below cursor pointer I also want to give it another style of t-3 so we have a bit more spacing you can see how everything now looks much much better all right now below this Avatar open another div and you're gonna write the following you're gonna write a class name of min-w-0 and flex-1 inside I'm just gonna indent this I'm going to give you the class name of focus outline Dash none like this and inside I'm going to create another div and I'm going to give you the class name of flex justify Dash between items Dash as Center and mb-1 like that and inside of that I'm going to create a paragraph now this paragraph is either going to render data.name which is a group chat conversation name but since we are not working with groups right now you're never going to render this for now except in the later parts of the tutorial so if there is no data.name we're going to use the pipe pipe to render other user.name instead like this and now you can see how it says Antonio's and Antonio here but if we were to create a group chat we would primarily use the name that we named our group chat instead of a random user from that group great now let's just give this a paragraph some class names so class name let's give it a text Dash MD let's give it a font of medium and let's give it a text Gray Dash 900 like this perfect and now below this paragraphs here let's check if we have the last message so if we have a last message question mark dot creative at we're gonna do an end end right here and we're going to write a paragraph right here and we're going to use format new date last message got created at and we're going to give it a format of key like this so basically if there is a last message sent in this conversation we're going to display a little time when the last message has been sent if we save right now we're not going to see anything because there is no last message available here and let's just make sure to style this here so class name to this paragraph which will display our last message uh created at the date text Dash XS tax Dash gray Dash 400 and font dash light so it's going to be a very small um text here and I just want to make sure that you can actually test this so uh you don't have to do this but I just want to show you how this will look so I'm going to remove this for now and I'm going to hard code this to True like this and I'm Gonna Save it so you see how this looks see we get this little text which shows us uh 9 38 PM which is my current time so I'm just going to revert this back and make sure you do as well use lastmessage.created at endlessmessage.created at in this new date right here I just did that to show you how this is going to look and how it should look for you uh all right and now just below this div right here you're going to create a paragraph inside and this paragraph is going to render last message text like this and in our case that is going to be started a conversation why well if you go back to last message text you can see our conditions if there is an image in the last message we're going to show send an image if there is a body in last message we're going to show whatever the last message is that the user sent if there is none of those conditions in that case we're just going to show started a conversation because we just started the conversation and there is no messages yet great and now let's go ahead and let's style this paragraph So class name is equal to clsx again I'm going to use backticks here I'm going to give it a trunk cake SM and in the second argument right here I'm going to use has seen question mark text Dash gray Dash 500 otherwise tax Dash black font Dash medium like that great and you can see how it's now a bit more compact in this uh uh conversation box right here so if I send the message to Antonio it's going to be written a last message here if I have not seen this message yet it's going to be molded in a dark color but if I did see it it's going to be more of a light color uh to indicate like on the actual messenger app perfect and that is it for our conversation box right here in the future we are also going to add a dynamic difference between either showing an avatar or a group of avatars if it's a group chat but for now we don't have to do that we're gonna do that later in the tutorial uh great great job uh for if you want to check the last message you can do what I did so just replace this with true like this and make sure you remove this inside so you can see how that looks and then also just don't forget to bring it back here great great great job in the next part of the tutorial we are going to create an actual a slash ID here right now if I click I get a 404 so we're going to work on this page next I'm just gonna go back so there is no error for now great great job so we're going to continue with the development of our messenger by creating the slash conversations slash ID which are routed through when it clicked on any of the conversations in the sidebar to do that first we have to create a page for that so I'm going to collapse everything here I'm gonna go into the app folder into conversations and inside I'm going to create a new folder square brackets conversation ID like this and inside I'm going to create a new file page dot the SX like that and what I'm going to do inside is very simple so first I'm going to write the interface for my parameters so I'm going to write interface I parents conversation ID a type of string like this and then I'm going to write const conversation ID is equal to an asynchronous function asynchronous Arrow function like this give it parents and give it params I params type like this just make sure you use the capital uh P like this so don't make the same typo that I did and just open this Arrow function and return uh like this so very simple to start with great and in here all I'm going to do for now is I'm going to create a div and I'm just going to say memorization ID like this and I'm going to export the whole conversation ID just like this so now once I have this page if I click on my conversation I should no longer get a 404 view instead what I'm going to get uh well we're going to see that in a second you can see that I have this text conversation ID right here it is not yet positioned correctly but that is what we wanted we just wanted to avoid uh having um well the 404 page great so what we have to do now is we have to create a couple of actions which we are going to call in This Server component right here so so let's go uh into actions folder and let's create a file get conversation by id.ts great and inside of that uh we are going to import Prisma ROM add slash add slash Libs Prisma like this sorry Prisma DB and we are going to import current user so import that current user from dot slash uh get current user beautiful all right and now let's define this action so const get conversation by ID is a synchronous function which accepts conversation ID which is a type of string like this and I just like to put a space here great and return an arrow function here and open a try and catch block and in the catch right here Define the error as any and all you're going to do is return null like this great and now inside this try block what you can do is write const current user is equal to a weight get current user like that so first let's check if there is no current user so if there is no current user question mark email like this in that case again return null for the conversation ID and now let's use Prisma to find the conversation so const conversation is equal to await Prisma dot conversation dot find unique and we are going to use the where query pointing to the ID which is going to compare conversation ID which we sent to the parameters right here great and I'm also going to include users so just write users it true like this and what you can do then is just return conversation like that perfect and make sure you do export default get conversation by ID at the end right here so you can actually import this uh in your project great before we move on uh back to our page we have to create another action so let's go again in the actions folder and create a new file that messages.ds let's import Prisma from add slash app slash ellipse Prisma DB again and let's write const get messages if people do async conversation ID which is a type of a string again and inside we're going to open a try and catch block let's resolve the catch so error is a type of any and inside you're just going to return an empty array like this so now let's go and do const messages is equal to await Prisma Dot message that find many where conversation ID is equal to conversation ID like this and include sender and scene like that and you're also going to order by created at sending like this because when we load our messages the newest ones by default are going to be on top but Messengers don't work like that Messengers show the newest version on the bottom right here so that's why we don't use descending we use ascending like this and all we have to do is return messages like that and don't forget to export people get messages like this beautiful and now we can safely go back into our app folder into conversations into conversation ID into page right here perfect and now in this page here what we can do is called both the conversation and messages so first let's fetch our conversation so I'm going to write const conversation is equal oh wait get conversation by ID and I'm going to pass in parents dot conversation ID like that and below that I'm going to load our messages so const constant messages is equal await get messages like that and I'm also going to pass in params.conversation.id just like I did here uh with the conversation great and now that we have that uh let's first handle if there is no conversation so if we entered an invalid ID in the URL so if there is no conversation what we are going to do is just return a div like that let's give the class name of lgpl-80 and H dash equal like this and just make sure you don't make a mistake like I did here and inside of that create another div with a class name H dash full Flex Flex Dash call and just use the uh our pre-made empty state which we already used a couple of times in the project like this great and you can import the empty state from ad slash app slash components empty State like this I'm just gonna move this up so the code is a bit more uh prettier like this uh Perfect all right and now I'm just going to collapse this a little bit so we can see uh the desktop view because that's what we want to design now so I'm going to give this a class name in the main return function now I'm going to give this a class name of LG pl-80 H dash full like that and inside of that I'm going to create another div which is going to wrap this conversation ID here and with a class name of H dash full Plex Flex Dash called like that great and I'm just going to refresh here so everything uh is reflected and you can see that now our conversation ID here has moved to this area right here great now instead of writing conversation ID here I'm going to create a component called a header so I'm going to write header like this it's a self-closing tag and I'm going to pass conversation conversation just like this and if we save of course we're going to get an error because a header does not exist right now so go into your conversations folder conversations ID and create a new folder called components and inside create a new file called header.dsx and let's just quickly fix this error so I'm going to Define use client and I'm going to use a shorthand to create a header component here which is just going to say header for now great I'm gonna go back into conversation ID page here and I'm going to import that header from dot slash components slash header like this and once I save the error will go away let's just wait a couple of seconds and there we go we have our header here great so now let's go ahead and fix this typescript error in the header by declining the interface so interface header props accepts the conversation which is a type of conversation from Prisma client you can import it right here and we're going to extend it a little bit because we also include the users so I'm gonna write user like this and you can import user from Prisma client as well in this line right here and then we can use this header props to assign it to react.fc like that beautiful and I'm just going to extract that here so conversation like that great great job all right and now we can safely pass in the conversation here uh what I'm gonna do now is I'm gonna add some hooks here so we're going to use the hook we created previously called use other user because we want to display this user's name in the header right here so that's what I'm gonna do I'm gonna write post other user is equal use other user which you can import from add slash app slash hooks use other user like that great now that we have that we can pass in the conversation because that is what it takes great now inside a new variable here I'm going to define a status text for now it's going to be pretty static because we don't have the functionality for active and offline and online status yet but we're gonna write a functionality which is going to be able uh to at least in change the status for the groups which you will see the functionality of later so go ahead and write const status text is equal use memo make sure you don't forget the dependency array and first we're going to check if the conversation is a group so if conversation is group in that case we're gonna return open pointy brackets and just write conversation dot users dot length members like that so if we are in a group we're not going to show the individual online or offline status we're just gonna show five members or two members or 16 members great and now below this uh if closed what we're gonna do is we're going to uh return uh active for now so we're gonna hard code it and what we have to pass here is conversation like this and now we have the status text so we hardcoded active for now later on this is going to be dynamic it's going to be either active or offline depending uh on our Pusher subscription status great and now we can go ahead and start developing this UI here so I'm going to remove this div for now sorry this text for now I'm gonna create some class names for this div so I'm going to write VG Dash white W full Flex border Dash b 1 pixel below that I'm going to write SM the x-4 py-3 dx-4 LG px-6 justify Dash between item slash Center and Shadow Dash SM uh like that great and now inside of this div you want to open another div you can see how our little nav bar is visible Here and Now inside of this div we can give it a class name of flex Gap Dash three items Dash Center just like that all right and now we're gonna create a mobile only Chevron back uh so I'm gonna collapse this like this and I'm going to zoom in so we can see what's going on here so I don't know if you can see but I have this little nav bar right here at the top so this is where I'm going I recommend you also collapse your screen to mobile otherwise you're not going to be able to see what you're doing so go ahead and add the link component which you can import from next slash link which I did right here and this link component uh let's do it like this for now so where it's going to point at the href is going to be slash conversations like that and besides the href we're also going to give it some classes so I'm just gonna go ahead and collapse this and I'm gonna write some class names so class name is going to be LG hidden block backslash sky-500 hover attacks that Sky Dash 600 transition and cursor Dash pointer like this and inside I'm gonna use the hi Chevron left from react Dash icons slash hi2 so there are two of them one is from uh react Dash icons h i but I'm going to use the one from hi2 you can try yourself and see if you like one more so let's just see where we imported this so we have an import of hi Chevron left from react Dash icons slash hi2 like that great and I'm just going to give it the size of 32 like that and now you can see I have this big icon uh on mobile screens which serves as the back icon but if I expand a lot you can see that there's no need for that so we'll only use that on mobile devices where we do not show the sidebar great so for now you can actually move your screen back to desktop view because now we're going to develop uh things for desktop great so below this link right here uh go ahead and write the Avatar component which you can import uh from add slash app components Avatar we already used it a few times in the project great it is a self-closing tag and the user you're going to pass is other user like that and just save the file and in a couple of seconds you should see this same uh image of this user you selected right here great and now just below this Avatar create a div and give it a class name of flex Flex Dash a call like that inside create another div which is either going to have a conversation dot name if it's a group chat or other user that name if it is a single um chat like this great and below this did create another div and I'm gonna give it some class names so write class name and we're gonna give it backslash SM on dash light backslash neutral Dash 500 like that and I'm just gonna pass in the status text component sorry text say this text variable which we defined here and which we will improve a bit uh in the future so status text inside of this div below the conversation.name and other user.name and just save the file and you can see how it says uh active right here uh great great job and one more thing we're gonna add to the header is adjust below everything here so before the last closing div right here just add hi ellipsis horizontal which you can import from react Dash icons slash hi2 so the same one you imported hi Chevron with great and it is going to be a self-closing tag like this and let's just go ahead and give it some properties so size is going to be 32. it's going to have an on click which for now is just going to be an empty function later it's going to open a profile drawer and class name is going to be text whoops let me just enter so text Sky Dash 500 cursor Dash pointer hover text sky-600 and transition like that great and now we have this little uh menu item right there and it's also visible on mobile Button mobile we also have this Chevron back icon great I really like how this looks so for now that's gonna be it for our header component let's go back into the page component of conversation ID right here and let's add another component here called body like this for now uh let's just go ahead and fix the error which it is going to give us because uh body does not exist right now so the same way we added header I just go ahead in your components and create a new file body.tsx like this and all you're going to do is Mark it as us client and a very simple fix so just body and return 8 div which says body like that and then you can go back into the page.tsx of the conversation ID and just import it from dot slash components slash body like you did with the header and save your file and the error should go away just wait a couple of seconds for hot reload to work and there we go we have our body now I'm gonna go inside the body again and we're not going to do too much here for now because we don't have the functionality we don't have any messages yet so there's no point in writing all of that code to render messages we cannot even see so all I'm going to do for now is I'm gonna write a class name here plex-1 overflow Dash Y dash Auto like that and Save the file and if that is going to be it for our body component for now and then you can go back into page.tsx and we're going to create a form component which we are going to use to create messages so just below your body element right here you're gonna go ahead and write form just like this and again we're going to get an error so let's just quickly fix that by adding a new file form.ex inside mark it as used client and let's just fix the error so form and return a div which says form like that and then just go back in your page and import form the same way you imported a header and body great and now that we have the form we can actually go inside just wait for this to fix all right and we have the form right here at the bottom of the screen if you can see uh great now let's go into this form and let's start developing inside so first thing we're going to add is we're going to extract the conversation ID from use conversation then we're going to make use of use form hook which we already did in the login and register screen so write const is equal to use form which you can import from react Dash hook Dash form right here and give it a value of field values like that which you can also import from use form so I'm just going to collapse this because we're going to have a bunch of these items here so field values and just open this and return an object inside with the default values message empty like that and what we are going to extract is register handle submit set value and form state and just extract errors like this so that's all we're gonna need from this use form right here and now we're going to write our on submit function here so const on submit is going to be a submit Handler which you can import from react hook form as well so right here submit Handler and it's also going to accept field values which we already have imported it's going to be a function which accepts the data as a parameter and just returns an arrow function where we are going to set uh where we are going to post this uh to our API which does not exist yet but this is what it's going to look like so axios which you can import from axios right here dot post and it's going to uh point to slash API slash messages with the body of dot dot data and we are also going to pass in conversation ID conversation ID like that you can also use a shorthand if you want like this great so we are going to spread the data which is only going to hold our message for now but we're also going to add conversation ID which we get using this use conversation hook right here and basically what this is going to extract is this URL uh right here at the top great uh now that we have that what I also want to do is I want to use this set value to reset the message back to nothing and we are also going to use should validate true like this so it's re-rent so it re-renders this component so once we click submit I just want to clear our uh message input which we will have right here at the bottom so that's why we have uh this line right here great and now let's go uh into our return function and let's start styling this so let's give this a couple of class names so we're going to be the class name of ey 4 px-4 BG Dash white border Dash e Flex item slash Center Gap Dash 2 LG Gap Dash 4 and W Dash full great so now you can see uh how at the bottom uh you have a nice little separator at the top which is top border which clearly separates this from the body element right here great now inside of that first thing I'm going to add here is hi photo which you can import from react Dash icons slash hi2 and it's going to be a self-closing tag like this and I imported it right here from react icons slash hi2 like that great and I'm also going to give this a size of 30 like that and a class name of text sky-500 like this great and now I have this little uh photo image right here and you can also check out how it looks uh on a mobile uh so it works exactly the same way great so now that I have this uh what I'm going to do is I'm going to open a form element here and inside this form element first thing I'm going to do is I'm going to write on submit which is basically going to call handle submit which we exported sorry destructured here from use form and our handle submit is going to wrap our custom on submit right here in the parenthesis and then this handle submit is going to provide our custom on submit with this data which is controlled from here in the default values which is exactly what we want that's how we use reactbook form and let's give this a class name of flex items Dash Center yak-2 LG gap-4 and W Dash full like that all right and now inside of this form we are going to create another component called message input like this uh and I'm going to save this and we should get an error for that but before we start working on this I just want to pass in all the attributes which we are going to need here so make sure you pass an ID of message make sure you add register register which we desstructured uh from our use form right here great so ID of message the same thing we added here all right uh and register errors required and placeholder which is going to say write a message like that great now let's go and create this message input component so I'm gonna go here in conversations conversation ID components and what I'm going to do is create a new file message input.dsx like that great let's mark this as use client and let's just fix the error quickly so message input live message input like that go back into your form.dsx in the conversation ID components right here and just import this from dot slash message input like this and once you save the file the error should go away once the website uh hop reloads great and you can see how it says message input right here in my footer here great I'm gonna go back into message input now and first I'm going to define the props for this so interface message input props are going to be a placeholder which is an optional string ID which is a required string type which is an optional string required which is an optional Boolean register which is in use form register which you can import from react hook form like I did right here and open pointy brackets and just write field values which you can import also from react hook form here great and errors which are field errors like that great now that we have that let's just assign all of those here so message input props like that and you can go ahead and extract all of those here so type required register and errors like that all right now at this top the first thing you want to do is give the class name of relative W Dash full like that and instead of this text we're going to render an input component which is a self-closing tag here we're going to pass in an ID ID type of type autocomplete of ID we're going to spread the register first argument is going to be ID and second is going to be an object which accepts required like that so this is a shorthand for required required which is going to be true or false since it is in Boolean so we can just write it like this required required and placeholder which is a placeholder uh and now let's actually style this by giving it some class names uh whoops like this so I'm going to give it a text Dash black I'm going to give it a font dash light I'm going to give it the py-2 px-4 BG Dash neutral Dash 100 W Dash full rounded Dash full and on Focus I'm gonna give it outline Dash none like this great and if you take a look now I'm going to use mobile so you can see better so you can see we have this nice little input here which is exactly which looks very similar to the messenger the actual Facebook Messenger great and this is where we can actually type our message now great uh we are done with the message input here and we can go back into our form uh dot TSX great so uh inside of this form just below the message input we're going to create a button element like this we're gonna give it a type of submit so this button is going to trigger this form on submit so make sure that your button is inside of this form or just below this message input great uh and we're going to give it a class name of the following so it's going to have rounded Dash full d-2 bg-sky-500 cursor Dash pointer hover vg-sky-600 and transition like that great and inside of the button we're going to have an icon hi paper plane sorry paper airplane and you can either import it from hi or hi2 I'm going to use hi2 because I like those icons better so let me just confirm that yes so import HR paper airplane and hi photo from react Dash icons hi2 great and let's just add some final attributes to this button so size is going to be 18 and a class name is going to be backstash white like that and now if you take a look you can see how we have a nice little uh Arrow here so I'm just going to zoom in a bit so you can see we have an image which will it's going to trigger cloudinery in the future we have a message and we have a submit button right here great great job and now we can actually go ahead and try uh if I click on network right here so if you try on empty nothing is going to happen because we said in our form that our input right here is required so if I send test and click here you can see that we are trying to reach our API messages but that does not exist but this is a good thing because it does exactly what we want it to do it cleared the input and in the payload it sent the conversation ID and the message test which is exactly what we want so we are now ready to create uh the endpoint which is going to create the messages for our messenger great great job so I'm just going to align this great so let's continue and let's create the route which is going to create our messages so I'm going to collapse everything here I'm going to expand this a little bit and I'm going to go into my app folder into API and I'm going to create a new folder called messages and inside messages I'm going to create a new file a route dot TS like that inside this route I'm going to export a synchronous function post which is going to accept request of type request to the parameter great inside I'm going to open a try and catch block I'm gonna resolve this error so the error type is any uh I'm going to console log I recommend you do this in every post route so I'm going to write error and I'm gonna say error messages like this so when I'm debugging my application I know that this is where the error is coming from and all I'm going to do is return new next response internal error with a status of 500 and just make sure you import next response from next slash server like that great and now let's go ahead and let's get our current user in this try block so const current user is equal to away get current user like that below that yeah make sure you import get current user from at app slash actions get current user below that we're going to parse our body silicon's body is equal away request.json like that and now let's just extract all the values we need from our body like this so we're going to destruct message image and conversation ID uh right now we know that we send the message because that's what we do in our form right here which we just tested but we will also be able to send an image once we set up a cloudinery and you also know that we send conversation ID which is this part of the URL at the end right here great so first let's check if any of these are missing uh specifically current user so if there is no current user question mark ID or if there is no current user question mark email in that case we're going to return new next response unauthorized with a status of 401 like this great and now let's go ahead and let's create a new message so const new message is equal to await Prisma just don't make a mistake when you write Prisma like this because right now it's not throwing any errors but that is only because we declared it globally you every time you use Prisma like this you have to import it so just go here to the top and import Prisma from add slash app slash Libs Prisma BB like that otherwise if you don't import it it's going to work locally without import but in production in the in deployment is going to break so make sure you import your prismol where you use it so what we're going to do here is Prisma Dot message dot create and first things first let's give it a data of body which is going to be our message let's give it image which is going to be our image if it exists conversation uh we are going to just give it a a connect command and inside this connect command we're going to write ID conversation ID like that great for the sender we're going to do a similar thing we're going to connect it by ID using the current user dot ID and for the scene since we are the one who sent the message which can automatically push us in the array of this scene user so I'm just going to write connect again ID print user dot ID so the person who has seen this message immediately is the person who sent it so we're connected the current user as our sender and we connected this at one of the persons who saw the message and we connected the conversation using conversation ID great and just below this data let's also write include scene true so we want to populate this array of scene users and sender true as well great and now that we have that I'm also going to update our conversation uh with this new message right here so I'm going to write const updated conversation is equal to a week Prisma dot conversation dot update I'm going to use the where query to find the conversation by ID using the conversation ID parameter from our body and I'm going to give it a data of last message add so since we send the new message into this conversation we're going to update the last message add field because that is by how we order our conversations so I'm just going to write new date here and now I'm going to connect the messages so I'm just going to write messages connect ID new message dot ID like that great and just below this data I'm also going to include users true and I'm also gonna include messages here include scene true like that so we don't need to include users we just need to include scene here right now we are not going to return this updated conversation but we are going to use this updated conversation once we add pushers that's why I wrote it like this so for now we are not going to send it back to the user uh we're just gonna leave it like this but it's uh we anyway we we still have to update it we have to connect the message and we have to update the last message ad so it's a good thing we did this already even without Pusher but we could have done it just like this but since we're going to need it in the future I already prepared this updated conversation which we are then going to send to all of our active users uh in order to give them real-time update about their current conversation in the sidebar so that's why I prepared that here but we are not going to return it now what we are going to return in this API is return nextresponse dot Json and we are going to send new message inside so we are going to leave this updated conversation alone for now and we are going to use this new message right here great so make sure you save this file and let's go back here I'm going to open my network again right here all right and I'm going to test sending my message so I'm going to write test I'm going to click Send and if I look at my response you can see that I have successfully uh created a message here great uh and you can confirm that by going in your mongodb you can see that I don't have any messages but if I refresh after I've added a message now uh I have a message right here and you can see I immediately have seen IDs because I seen the message and it's the exact same ID for the sender ID because I'm the creator of that message great great job and now that we have our first message we can actually start and render some messages but before we do that we're also going to learn how to enable cloudinery for this so we can send images so we are going to continue and we are going to create our cloudinary account and set up the actual action to this little message box uh in the in our submit form so first I have the next cloudinary page opened in this browser here and we're going to go ahead and open our terminal I'm going to close everything for now and I'm gonna go and install next Dash cloudinery so npm install next-claudinary like that and just press enter and wait a couple of seconds uh for this to install great after this has been installed you can go ahead and run npm run Dev again and just make sure you refresh your page after you've done this so everything is reflected I'm going to close the terminal for now and I'm gonna go into my DOT environment file and inside I'm going to add next underscore public underscore cloudinary cloudinary Cloud name like this or you can go to next cloudinery and just copy this right here and what we're going to fill here well for that we have to create a cloudinary account so go into Google and write cloudinery and select the first link right here go and find a way to log in so I'm here in the mobile view I'm going to use Google to log in you can choose anything of your choice and once you're inside you're going to see your API key your Cloud name and a bunch of other useful stuff so I'm just going to expand this a little bit so you have the desktop view uh the same as I do so uh you can find your next public cloud in every cloud name right here uh In This Cloud name option here so I'm just going to click copy here and I'm going to paste it right here great and that's it for this uh next cloudinary setup uh right here what I want you to do next is uh we're going to go back into our localhost but keep this page open because you're also going to need to create an upload preset and I'm going to show you what that is in a moment but I just want us to complete this part for now so let's go back on localhost here and let's go back into our form component which is located in conversations folder conversation ID into components right here so I'm gonna go uh right here and where we added this hi photo we're gonna modify it a little bit by wrapping it in CLD upload button which you can now import from next Dash cloudinary a new package that we just installed and you can wrap this hi photo inside of that so just make sure you import the CLD upload button from next cloudinery like that all right and now I'm gonna add some options here so I'm going to give it options Max files is going to be one on upload for now just give it an empty function and now we have to assign the upload press it so up will press it for now is an empty string and I'm going to show you how you can create your upload preset to make this work so go back into cloudinery and if you can see right here at the bottom in the lower left corner you can find your settings so go ahead and click on this wait for a couple of seconds for this to load and now in this sidebar select upload and here I I probably have a bunch of this upload presents which you do not have because I tested this before you're probably only gonna have one or maybe not a single one but all you have to do is click on this add upload present option right here and make sure you select unsigned option right here and just click save like that and after that has been created you're gonna have it right here make sure it says mode unsigned and just go ahead and copy it like that and then you can use that and assign it as an upload for present right here great and before we just move on uh what I want to do is I want to create a function which is going to upload this so uh go ahead let's go ahead and let's create a function called const handle upload like this the result is going to be a type of any and what we're going to do is we are going to call axios.post slash API slash messages so the same way we did with on submit but this is going to be Standalone away from our reactive form and for the body we're going to pass a image of a result question mark dot info question mark dot secure underscore URL like this and don't forget to also pass the conversation ID like that so result question mark info question mark secure underscore URL like that and then you can use the handle upload here and assign it right here great I'm going to expand this into desktop view and I'm going to refresh this and one cool thing you can see is that we have the latest message if you've sent this uh right here in my conversation box so it changed from start of the conversation that is really cool but it will only happen once you refresh for now since we are not real time so let's go ahead and let's click on this now and as you can see it opens uh our uh cloudinary uh file selection tool so I'm gonna go ahead and I'm going to select the file from here so I'm gonna find something like this I'm going to upload it and there we go with nothing has happened yet but if you go back and refresh your messages you should find a message which has an image which points to rest.cloudinary here great great job and if I refresh here actually in our newest conversate conversation box you should see a message which says send an image just like that great great job so our form is officially complete and we can now go ahead and create the actual body where we are going to render our messages so let's continue and let's create our body elements that actually works so I'm going to expand this a little bit and I'm going to close everything for now and I'm going to go back into app into conversation conversation ID components into body right here and I'm also going to open page.tsx uh right here the reason I want to open page.tsx is because we are going to pass something through the body and that is going to be messages so we're going to go ahead and pass initial messages and we're going to pass messages here like that so it's going to be the same way as initial items in the in our conversation list uh this will this will only serve to load when user loads the page but every additional message is actually going to be dynamically added using Pusher once we get to that great so now let's go back into body and let's actually create an interface for this so I'm going to write interface is body props initial messages and it's going to be a type of full message type which you can import from add slash app slash types and make sure you put a little array uh at the end like that and now let's use react FC to assign this to the body component and now if you look at our page.tsx you can see that the error is gone and body can successfully accept these messages right here great and now let's destructure these messages here uh sorry it's initial messages like that and what we're going to do now is we're going to create a state so messages set messages is equal to use state from react which you can import right here and the initial value is going to be initial messages just like this and I'm also going to create a bottom wrath which will have no function for now but later it's going to serve that when we get a new message we scroll down even if the user is all the way up or a lot of new messages have come so it provides a better user experience so go ahead and write const bottom graph is equal to uh news graph which you can import from react right here open pointy brackets and write HTML the element like that and just give it the default value of null like this all right uh and now I'm also going to use the use conversation to extract the conversation ID so const use conversation which you can import from add app slash hooks Slash use conversation and make sure you extract the conversation ID great and now inside of this body uh first we're gonna replace this with a bottom div so it can be a self-closing type because it serves no purpose but for us later to scroll down to this element so I'm just going to give it a ref off bottom ref and a class name of tt-24 because we want to create some space where we can scroll all right and now uh Above This bottom ref we're going to create an iteration of our messages and so we're going to do messages .net message and then index here and we are going to immediately return message box like this of course this does not exist yet so if you save you're going to get an error but before we start working inside first let's define some props which we are going to send here so it's last is going to be a comparison to our index uh identical the messages that length minus one so that's how we are going to know if the current message is the last message T is going to be message dot ID and data is going to be message like that and of course um if you save uh you're going to get an error and don't worry that we don't use the conversation ID I just prepared it for when we add Pusher and other real-time stuff here all right and now let's go back into these components where we have the body form and header and let's create a message box that's the SX component uh great let's mark it as use client and let's just quickly fix the error so message box like that go back into body and just import that from dot slash message box like this I'm just gonna pre-order my types a bit okay I'm going to save this and after I refresh the errors should go away and there we go I have two messages right here because that's how many I've sent if I send a third message here so I'm just gonna name it third message uh nothing is going to happen immediately but after I refresh I should get loaded with three messages right here great so if this is not happening to you please confirm that you're actually having new messages added in your database right here so how many times you've entered in this form should be how many times uh you have seen it in this database right here if the database is okay but this is still not showing that means that in your page you have something wrong in your get messages function right here but if you follow along everything should be just fine so let's go back in our message box right here and let's define the interface for this so interface message box rocks uh is gonna have a data which is a type of fullness type which you can import from add slash app slash types like this uh we're gonna have islast which is an optional Boolean like that and let's just assign this using react FC message box props like that and then you can extract data and is last like that I'm just gonna collapse this a little bit just in case some of you are confused why am I having a mobile view here great uh what we will do next is we are going to get our session here using a hook so const session is equal we use session which you can import from next dash out slash react like that great now I'm going to write a couple of uh conditional uh variables here which we are which we will use to recognize whether the message is our own message is it the other user's message should we displaying uh should be displayed that this message has been seen by someone and stuff like that so const is own is going to be session question mark data question mark user question mark email is equal to data question mark sender question mark email like that so basically what we are doing here uh is we are comparing the current session email with the email of the sender of that message how do we get this email from the sender well that is in the get messages because we populated the sender there so the sender is not going to be a random ID it's actually going to be a complete user model which you can also check in this full message type as you can see sender is a user model so that's how we know it should have an email type here and that's how we are going to compare to his own variable all right the next thing we're going to do is create a scene list so we're going to create a list of all the users that have seen this message and we're going to turn it into a text that we can immediately render so const scene list is equal open parenthesis data dot scene by pipe empty array so we add the empty array here just to prevent a chance that that this dot scene is undefined so because if we try to dot map or dot filter on undefined JavaScript is going to throw an error but by doing this we kind of protected that because it's going to use this empty array if this is undefined great so you can write all of this in one line if you want to but I'm just going to click press enter so it's simpler for the tutorial I'm going to click filter here I'm going to select the user and I'm going to write user.email is not equal to data question mark sender question mark email like that and then I'm going to we're going to go through map user and I'm going to return each user name and I'm going to join all of that using a comma and a space inside of a string great so basically what we are doing here is we are filtering through this data dot scene and we are removing our uh the sender user from the list of people who have seen the message because it makes no sense to display seen by Antonio if Antonio is the person who sent that message right so that's why we filter that out but in our database of course we keep info that we have seen our message and then we just map over that filtered array and we return the name of the each user so we work with array of strings and then we can use that array of strings and just map dot join and create an array so this is going to produce something like uh Antonio Mark John for example if three users are inside of the scene object great so we have that now and what we're going to do now is we're going to create uh a couple of classes here all of them are going to be very Dynamic so I would rather keep them in variables than directly write them here so let's do that I'm going to write const container and it's going to be clsx which you can import from clsx right here and the first value I'm going to give here is flex gap-3p-4 and the second one is going to be a conditional its own and and justify Dash and like this great for the second one I'm gonna have an avatar so it comes to Avatar again it's going to be clsx and it's only going to be conditional so it's own and and order Dash 2 like that below that we're going to have a class for body so constant body is going to be tlsx in the first parameter I'm going to send Flex Flex Dash call gap-2 and in the second one I'm going to give a conditional is on and then items n like this and the last one is going to be the message class so const message is going to be tlsx again and the first argument is going to be text SM W Dash fit overflow Dash hidden like that the second argument is going to be dynamic is own like this BG Dash Sky Dash 500 x dash white otherwise it's going to be BG Dash gray Dash 100 like that and the third argument is going to modify the message class if the message is an image so data.image question mark rounded MD and p-0 otherwise rounded Dash full py-2 px-3 like that perfect so we have prepared all of these Dynamic classes I think it's cleaner to keep them in uh variables since there are so many of dynamic ones usually we only have one or two but almost every single one here is dynamic great so uh let's go right here and instead of displaying message here in this first div uh we're gonna give it a class name and we're just going to assign container like this so just this container here like that great uh and now inside uh we're gonna use a div and give it a last name of Avatar so make sure you don't put this in a string because this is using this variable which we Define right here and inside we're going to use an avatar component which you can import uh from add slash app slash components slash Avatar like that and the user you're going to send inside is data whoops make sure you use curly brackets it's data dot sender like that great and outside of here as you can see you can see that I send this messages so they are on the uh right side of the body that's exactly what we want and now in outside of this div which wraps the Avatar you're going to create another div and give it a class name of body so again it's this one which we defined right here great and let's give it a div a class name Plex item slash Center and GAP dash one and inside uh we're going to create another div with the class name text Gray Dash 500 like that and just write data.center.name like that uh great and now you can see that my name uh is right here next to my image uh great uh and now uh just below this data center and name we're going to add another div right here the class name of backslash XS attacks that gray Dash 400 and inside we're going to use format which you can import from date FNS so I'm going to do that right here I'm going to import format from date Dash FNS like this and what I'm going to format is the created ad of this message so I'm going to use new date data.created at and we're gonna pass in p uh as a second argument of this format make sure you don't accidentally do this like this because this is not going to work so inside a new date parenthesis you only pass data dot current at and then you add a comma and you pass a lowercase b so uppercase and lowercase are not the same thing in format those are different format things so make sure you're just passing the lowercase b like that and if you save the file you can see that now I have the time when this has been sent and the minute great that's exactly what we want uh now what you're gonna do is go just outside of this div right here and you're gonna create another div and give it a class name of message again make sure you don't accidentally put this in a string so that is using this variable which we created uh right here great and now we're gonna create you can see how we have a nice little uh blue uh background here but this one does not have it that is because for the second message I've sent an image so our code is working as expected great so first let's render an image if possible so I'm going to use data.image question mark I'm going to open parenthesis and I'm going to render image from next slash image so just make sure you import image from next slash image here great I'm going to close this it's a self-closing tag I'm going to give it an out of image I'm going to give it a height of 288 I'm gonna give it a width of 288 as well like this I'm gonna give it a source of data.image and I'm going to read the class name of object dash cover cursor batch pointer power scale 110 transition and Translate like that and before we save we also have to create an alternative to this uh shorthand if Clause so just write like this open parenthesis again and just write a very simple div in which you you will render data dot body and just close the div like that and now you can save I'm just gonna wait a couple of seconds and uh there we go so you can see I have the image it has a little effect once I hover and you can see that the messages are clearly visible amazing amazing job you're doing a great job so far what I want to mention if if you got an error during this especially showing a cloudinary error just make sure that in your next configure.js you have configured rest.cloudinary.com inside your images inside your domains array if you don't have a rest cloudinery for example I'm going to remove it now and I'm gonna purposely wait a couple of seconds for all of this to reload and you're gonna see the kind of error I get I just want to show you this in case you get the same error so you know how to fix it so there we go this is what the error looks like so it tells you that hostname rest.cloudinary.com is not uh configured so just make sure that you have rested cloudinary avatars.github user content and lh3 Google user content otherwise you're gonna get errors in the messages so just go ahead and save this if you haven't refresh your page and everything should be working just fine so before we wrap up our work on the body I just want to note that later we will also add a model which will open on click of any image right now we're not going to do that because we are wrapping everything up first and what I want to do next is I want to go back into uh body right here and what I'm going to do I'm going to expand this just a little bit I'm going to add a use effect which you can import from react uh just make sure you put the dependency array here and what I'm going to do is I'm gonna make a call an axios call to a route that we're going to create now so axios that post also make sure you import axios from axios like I did right here so just make sure you access that post and use backticks for this slash API slash conversations slash conversation ID slash scene like this so every time that we we open this body component or when this exact page loads we are going to send a post route to scene the last message and if you're wondering well how will that work when new messages are coming to us don't worry we're going to handle that with Pusher so all you have to put now in this dependency array is conversation ID right here great and now let's go ahead and let's create this route right here so I'm gonna go open my sidebar here I'm going to go into API we got an error here we got a 404 because this uh use effect route does not exist yet so that's completely fine so I'm going to go in API in conversations right here and I'm going to create a new folder inside open square brackets conversation ID like that and then inside I'm going to create a new folder called scene and inside of that I'm going to create a new file route Dot es like that and what I'm going to do inside is first I'm going to define the interface so interface I params like this it's going to be a conversation ID question mark string like that and then we can do export asynchronous function post we're just gonna accept request which is a type of request and it's also going to accept a second parameter which we will immediately distract in the parameters so params like this and just map it to parents I patterns like that uh important thing to note make sure that this is the second argument you cannot do it like this this is not going to work make sure that your parameters are a second argument here great and now what I'm going to do is I'm going to open a try and catch block here so go ahead and open try catch error which is a type of any right here and what we are going to do in the error is we're going to console log because it's a good practice to do uh we're gonna write the error and we're going to say error messages scene like this so you know when you're debugging if you have an error in your console this is where it's happening and we're going to turn a new next response which you can import from next slash server like here and we're going to write internal error and we're just going to send a status of 500 like this great now let's go back into our try and let's first fetch our current user so const current user is equal to await get current user which you can get from at app actions get current user like that great now let's extract the conversation ID from our parameters like that great and what we're gonna write here is we're going to check if we have the current user so if there is no current user question mark ID off if there is no current user question mark email we are going to return new next response unauthorized with a status whoops of 401 like that great uh if everything is okay with our current user first we're going to find the existing conversation like this so we're gonna write conversation is equal to await Prisma again don't make a mistake just because there is no error here because your production is not going to work make sure you do import Prisma from add slash app slash lip slash Prisma VB like that and now everything is fine and go back here where we wrote find the existing conversation and right away.prisma dot conversation dot find unique and we're going to use the where query defined by ID using our conversation ID from the parameters like that and what you want to include here is messages open an object and write include again scene true like this and besides messages you also want to include users so just write users true as well great and I'm going to put a semicolon here and now we're going to check if we successfully fetched this conversation so if there is no conversation whoops you can just use this so if there is no conversation you're gonna return a new next response invalid ID status or 100 not 4 000 but 400 like that a great and now what we're going to do is we're going to find the uh the last message uh using this existing conversation uh right here so how are we going to do that we're going to write const the last message is equal to conversation dot messages we're gonna open uh an array here no it's not really an array it's just a way to access this array right here so I'm going to write conversation dot messages dot length minus one so that is how we are going to select the last message from this conversation that we have great and now that we have the last message uh well first let's confirm that we have the last message so if there is no last message we can just return nextresponse dot Json and just return the conversation like that oh great and if we do have the last message in that case we're going to update scene of last message great so let's go ahead and write almost updated message is equal to away freezeman.messages.update where ID is equal to last message dot ID and instead of Prisma dot messages make sure you write Prisma Dot message like this and for the aware use the ID last message dot ID great for the include you're going to write sender true and scene true like this and for the data you're going to pass in scene object connect open an object again and write ID print user dot ID like that perfect and all you're going to do is return next response dot Json updated message like that great so what do we actually do here why did we just not create a route which simply has the last message ID inside of it well that's because uh we prepared this route for Pusher later on uh because we have the conversation here and the last message and the updated message is going to be much easier for us to propagate through all of the channels channels where we will be subscribed to it will make more sense in the future but to explain what we did so basically we used the conversation ID to find uh the last message in that conversation and then we used Prisma message update and we use the query lastmessage.id and we connected our current user to the array of scene objects inside that message great great job so now I'm just gonna collapse this a bit and I'm gonna refresh here again just to confirm that we do not no longer get an error great we no longer get an error and now I just want to test some if you see this jumping up and left and right that's because this session has not exactly loaded yet so what I want to do now is I'm going to select a random person from here for example this Antonio and I'm gonna say uh test scene message here and I'm just going to press enter to send this message nothing's gonna happen I have the manual refresh because remember we don't have um we don't have Pusher yet great so it says that I sent this message but I cannot see whether this user has seen that message so I'm gonna go and I'm gonna log out and I'm gonna enter this Antonio user and I'm gonna uh I'm gonna just just open the message and see uh if then I'm able uh to see it okay let's just wait a second for our logout to work oh well we have a small bug here let me just see if I can manually uh go here I can't uh okay I'm gonna check out what it was perhaps it was just cash because I think the code is okay so I'm gonna write Antonio mail.com I'm going to enter here I'm going to wait a couple of seconds to see if I will be redirected back yes I will all right I'm gonna go into my conversations here next 13 in development is a bit slow great so I have this test scene message and I'm going to click here now and now I'm going to refresh here just to double check that I definitely seen this message uh and great so I can see that a person called new has sent me this message and I can see that it's no longer uh in a bold font here that means that I've seen it so I'm just gonna log out again I'm going to confirm whether this is a bug with logout or just some weird cache I'm not sure why it's returning like that and I'm gonna go bang it to New right here to see uh if our scene text is working so I'm going to go into my conversations here I'm gonna click here uh all right uh it's not showing our user I'm just gonna check why that is happening all right so uh the reason this is happening is because we did not add uh the code which actually uses our scene by uh it's a good thing I caught this so I'm just gonna uh collapse this a little bit here and we're gonna go back into a message box right here and we're gonna go uh just below this uh div right here and I'm gonna open a conditional here and I'm gonna write is last and end is own and end scene list that length is bigger than zero and just write end and again and open parenthesis and open a div like this and inside we're gonna write use backlinks for this and just write scene bye scene list like this and we're gonna give this div a couple of class names so I'm just gonna add class name tax Dash XS so you can see we have this huge text seen by Antonia here text excess font dash light and text Gray Dash 500 like this let's just wait for hot wheel load to work and there we go you can see that because I logged out and I went into my Antonio account and I opened this message I can now see this function seen by Antonia a great great job so before we move on I just want to fix this issue we have with logging out while we are on the slash conversations screen this happens because in the middleware that we use for non-authenticated Pages we only added slash users but not slash conversations so in order to fix that go back I'm going to close everything so it's clearer for you and go back into your middleware.ds right here and you can see that we only protect the slash user's route let's go ahead and add a comma here and just write slash conversations slash path like this and this is going to protect you from logging out uh during the uh if you're on the conversation screen so I'm gonna open uh Antonio for example just let's wait a couple of seconds for this to load and then I'm gonna try uh and log out from that screen all right so it loaded right here and I'm gonna try and log out now and after a couple of seconds there we go we are redirected uh back to the logging screen like this great so I'm just gonna log in back as Antonio here and in my code editor I'm gonna go back uh into app conversations conversation ID components folder and I'm going to select a header like this and inside of this header what I'm going to do is I'm going to get a state which is going to control uh this button that we have right here in the corner let's just wait a couple of seconds for this to load if you remember we added a horizontal dots icon which will serve as a button to open our model so write this uh in the corner if you can see write this three dots right here so we're gonna turn that uh into a button which is going to open a drawer here on the side so we can see more information about a hour conversation and also to be able to delete it so let's start right here in the header and let's just add a state home's drawer open and set Rover open like this from use state which you can import from react and let's just give it a default of false so I imported use state from react right here the same way we did with use memo and now what I'm going to do is I'm going to wrap this uh entire return function so this entire div inside my header in a fragment like this and I'm just going to indent the entire div and I'm going to expand it so you can see what I'm actually working with so we already written this I just wrapped it into a fragment the reason I wrapped it into a fragment because Above This div to be semantically correct I'm gonna add a profile drawer like this it is a self-closing tab we're going to create it in a moment I'm going to give you the data of conversation I'm going to give it an is open value of drawer open from the state that we just created and on close is going to be an arrow function which calls set drawer open and sets it to false like this and if you save you're going to get an error because profile drawer does not exist now let's just quickly fix this error by going back into components in our uh Slash conversation ID folder right here and create a new file profile drawer dot the SX like that I'm going to mark it as use client and I'm just going to quickly fix this error so I will write profile drawer like this and we're just going to return a div profile drawer like that and I'm gonna go back into my header component where I added this and I'm just going to import it it's in the same folder so it's very easy to import like that great and now that we have this I'm gonna go back into my profile drawer and I'm gonna create an interface so go back into profile drawer right here and create an interface profile drawer props like that and let's give it a prop is open which is a Boolean let's give it an on close function which is a simple void function and any data which is going to be a type of conversation which you can import from Prisma slash client and we're going to extend it by also adding users which is a type of user which you can also import from Prisma client and remember to put an array at the end of this user because users is an array of users and now what you can do is just run react.fc right here and give it a type of profile drawer props and then you can safely extract is open on close and data like this now to continue in the profile drawer we are going to install headless UI which we will use um to create a semantically correct uh drawer as well as our models in the future so go into your terminal right here I'm going to shut down the application and I'm going to write I'm going to expand this so you can see what I'm writing I'm going to write npm install at headless UI slash react and I'm gonna press enter and just wait a couple of seconds for this to install after it's been installed you can go ahead and run npm run Dev again all right and I'm just going to refresh my page here so I know that my application is up to date after I've shut down my application and run it again and great and now let's go ahead and let's start developing this drawer so first let's add some functions here so const other user from use other user you can import that from add slash app slash hooks Slash use other user like I did right here and the parameter is going to accept is data which is of course a type of conversation like this and now that we have that let's create a value for our joined date since when we click on this button right here we want to show some information about this conversation and we're going to create we're going to show when the user joined messenger so const joined date is going to be a type of use a memo which you can import from react don't forget to put the dependency rate at the end and all we're going to do is return formats and you can import format from date FNS just go to the top right here and import format from date slash Dash FNS like this and now that we have this format open parenthesis and write new date other user dot created app like this and the format is going to be Capital PP like this so make sure you don't use lowercase it's double P Capital like that and in the dependency rate you have to give it a other user dot created app like that great and now that we have that let's also create our title so cons title is also going to be a used memo don't forget the dependency array and inside all we're going to do is return data.name so either the conversation name if it's a group chat or other user.name the same way we did uh in the header and in this conversation box right here and the dependency array needs to take in data.name and other user.name like that and last thing we're going to do is we're going to create a status text variable silicon status text the same way we did with header use memo don't forget the dependency array like that and we're going to check if data is grouped in that case we're going to return the same thing we did in the header so open back ticks and write data dot users dot length members like that so it's going to display five members or six members or 100 members uh otherwise we're just going to return hard-coded active for now and later in the tutorial we're going to change this into either offline or active depending on The Pusher subscription and in this um dependency array just pass in the data like that great and now we can go ahead and start developing uh this UI right here so instead of this div we're going to have a transition which you can import from add headless UI react like I did right here and it's going to be transition dot root like this and we're going to give it some props so we're going to give it a show which is a type of it's open and we're going to give it as which is a type of fragment uh like this and fragment is imported from react so just make sure you do that so also import fragment alongside use Memo from react like this great and now that we have the transition root uh we're going to use another component from headless UI called dialog you can also import dialogue from headless UI so just go ahead and add the dialogue as well uh go ahead and let's give it some attributes so as div last name is going to be a relative z-50 and on close on close like this great now inside of this dialog we're gonna open uh another transition so I'm gonna write transition dot child we already have transition imported so we can safely do this transition uh dot child like this and let's give this some props so as fragment again and let's give it some animations so on enter it's going to have an ease out duration Dash 500 on enter from it's going to have opacity zero on enter 2 it's going to have opacity Dash 100 on leave we're going to give it an ease in animation with duration of 500 milliseconds leave from is going to be opacity Dash 100 and leave two is going to be opacity Dash zero so these are special attributes which this transition.child accepts and they are part of headless UI you can visit their documentation for more information here but this creates a nice little effect when we leave or enter sorry when we open or close our drawer great and inside what I'm gonna give I'm gonna create just a div and you can turn this into a self-closing div and we're just going to give it a class name or fixed inset-0 BG Dash black and bg- opacity Dash 40 uh like that and you can go ahead now and try clicking on this drawer uh let's see if anything happens or if we had not written enough code for this so I'm just going to refresh this page one more time and I'm gonna try and click here okay nothing happens so we have to develop a bit further uh sorry what I said was incorrect the reason it doesn't work is because uh we did not set this set drawer anywhere uh except the profile drawer so we we were here in the profile drawer go back to header and use this set drawer open right here at the bottom uh where we created an empty function for our hi ellipse is horizontal and just put it to set drawer open true like this and now after this hot reloads uh if you try and click it should get a little effect perhaps we still don't have enough code for that but I'm pretty confident we should get an effect so just make sure you refresh your page if your hop reload uh is slow great so now if you try and click you see how our screen got dark and if you try and click escape button on your keyboard you should be able to exit it so you can see how headless UI gives us this default um let's call that accessibility points so we don't have to write them ourselves great usually when we created our own model we had to write everything ourselves but this creates us this nice smooth animations and everything else great now we can go back into profile drawer component right here and let's continue developing so just below this a transition dot child uh we're going to create another div like this and let's give it some class names so class name is going to be fixed inset-0 overflow Dash hidden like that and inside of that create another div uh with the following last name so class name is going to be absolute inset-0 and overflow Dash hidden again great and inside of that div we're going to create another one and this one is going to have a pointer Dash events Dash none fixed inset Dash Y dash zero right dash zero blacks Max W Dash full pl-10 and while we were developing this I recommend having this uh turned on so you can see changes in real time when they begin to happen a great and now that we have this inside we're going to open another transition child which is going to be our actual drawer so what those transitions which we just made are only for the background so now we're going to create one for the drawer so go ahead and write uh transition dot child again and we're gonna give it a couple of attributes so as fragment like this below that uh we're gonna write enter to be translate Dash x dash full so just make sure you don't misspell translate like that enter from uh sorry enter from is going to be translate Dash x dash full so you can just copy that here like that and in the enter you're going to write transform transition is Dash in dash out duration Dash 500. so enter is going to have this animation and enter from is going to have this initial setting great now enter two it's gonna have uh translate Dash x-0 like that uh leave is gonna have another animation here so transform transition is Dash in dash out duration that's 500 so the same as enter and leave two is going to be translate Dash X slash for great and now inside of that we can create another dialog panel so I'm just gonna expand this a little bit all right so we got a couple of errors here I misspelled a leave right here so just make sure you write leave two like that and save your file so the error goes away and inside transition.child you're going to open another dialog.panel like this and dialog panel is going to have a couple of class names so class name uh is going to be uh pointer Dash event slash Auto W screen and Max W Dash MD like that and I'm just going to zoom out my code so I can open this panel uh right here so my code is still showing this error but that's because the cache has not reset so you will not have this error if you correctly spelled leave too so mine is showing me that I uh wrote and invalid I love it too so there we go it just go it went away great so after you've written this dialog panel inside of here uh go ahead and create a div and this div is going to have a couple of class names so class name inside the div is going to be Plex H dash full H dash full let's Dash call overflow Dash Y dash scroll BG Dash white py-6 and Shadow Dash XL like this great and inside of that they've create another div so you can see how I got this nice little uh drawer right here on the side now great now inside of this div uh you're gonna create a class name with b x 4 smpx-6 like that uh inside of that another div with a class name of flex so I'm just going to collapse this since it's going to be a number of classes so Flex uh items Dash start and justify Dash and like this great and now that you are inside of that div just create another one with a class name ml-3 flex h-7 and items Dash Center uh like that so we are creating uh our uh a position for our close button here that's why we are entering so many divs right here uh all right and now inside of that uh you're going to create a button element right here let's give it a couple of attributes so type is going to be button last name is going to be rounded Dash MD DG Dash white text Gray Dash 400 hover text Dash gray Dash 500 focus is going to be outlined sorry focus is going to be outline Dash none uh then we're going to add Focus ring Dash two Focus ring Dash Sky Dash 500 and focus ring Dash offset Dash 2 like that and uh inside of this button right here what you're going to write uh you're going to write a span first with a name close panel like that and we're going to give it a class name of sr-only so this is for our server side only it's not going to be visible here on the client so you should not be able to see this text and the button we're going to use is IO close like this and you can import i o close at the top so I'm going to do that here import i o close from react icon slash io5 like that great now let's go back uh right here and find our IO close button and let's give it a size of 24 like that so just wait a couple of seconds uh to see if this will render properly uh perhaps you can refresh if you cannot see everything uh or maybe I missed a button uh oh there we go so it's right here I just refreshed so let's just wait a couple of seconds I'm going to open it again and there we go so you can see I have my button right here and you can see when you press tab on your keyboard you can see how it immediately selects that so we are using accessibility programming here so it's immediately selected great and what I want to do on this button right here besides the classes so this button that wraps the i o close I also want to give it a non-click on close like that and we passed the on close uh from the prop great so just make sure you pass the on click to this button which holds our i i o close right here and if your code has got reloaded and when you press on this it should close your drawer and there you go you can see how it closed my drawer so just a second for my page to refresh again I'm gonna open again and I can close and I can also close using uh the escape button or I can click on this gray area right here so great uh just keep this open uh so you uh so you can see the changes that you are doing so now we're going to add an avatar right here so just go outside but inside this last div in the dialog panel right here so you can just press enter so one two three this third div right here make sure you are inside of this div and inside the dialog panel right here and you're gonna go ahead and create another div right here and give it a class name uh of relative mt-6 plex-1 px-4 and smpx-6 like this great now go inside of that div and create a another div the class name whoops of Plex Black slash call and item slash Center like that and inside of that they've uh create a another div which is going to wrap our Avatar and give it a class name of mb-2 and you could just go ahead and write avatar like this and you can Import Auto from add slash app slash components slash Avatar like that so I just imported my avatar right here at the top and now we're going to use this other user to pass the Avatar so go back to your avatar right here and pass in the user as other user like that and go ahead and save your file and once this hop reloads uh you should be able to see your user here great so there I have the Avatar of the other user and now outside of this div which wraps the Avatar create another div and inside you can just put the title which we created so a variable which we created uh right here and now you should be able to see uh the username or if you're using a group chat we're going to see the group name so there we go it says New Right Here and Now below that I'm going to create another div and I'm going to give this a class name of text SM tax Dash gray Dash 500 and the variable we're going to use is status text like this so another uh uh a US memo which we created right here so just make sure you put that in this div below the title and there we go we have new and it says active right here which of course is going to be dynamic in the future so go go outside of this div and create another div and give this a class name uh flex get-10 and Y dash eight like that uh and what we're going to do inside here is we're going to create a button to delete our conversation so go ahead and create another div and let's give it some properties so on click it's just going to be an empty function for now the class names are going to be the following so Flex Flex slash call Gap Dash three items Dash Center cursor Dash pointer Dash pointer like that and on Hover we're gonna have an opacity of 75 like this great and now just inside of that we're going to create two divs so one is going to hold our icon and one is going to hold our text let's go ahead and create a class name for this div inside with values of w-10h10 VG Dash neutral Dash 100 rounded Dash full Flex items Dash is Center and Justified Dash Center like that and the icon we're going to use is going to be IO trash and you can import IO trash from react Dash icons io5 so the same place we imported our i o close button four so just make sure you import IO trash from react Dash icons io5 here now I'm gonna go back here and I'm just gonna give it a size of 20. not 200 but 20 like that and in a couple of seconds you're gonna see the button great so we have the button right here and now I just want to give it uh a text so outside of this div right here create another div like this and give it a text I'll delete like that and we're going to give this text some class names so it looks just a bit better so I'm gonna give it the class name of text Dash SM font dash light and text Dash neutral Dash uh 600 like this and this is going to make it just a little bit muted great so there we go we have our text right here you can see when I hover um it hovered the opacity turns down so once we click on this button what we're going to do is we're going to show a model uh for the confirmation of whether we actually want to delete this conversation or not so we don't do it uh accidentally so let's just start wrapping this up so we're going to create a couple of more information here so after this delete text right here go outside of this div outside of this div and outside of the third div right here and create a new div and this one is also going to have a couple of class names so class name is going to be W Dash full uh pb-5 pt-5 smpx-0 and snpp-0 as well great and now inside of there we're going to create another element called DL like this so we are semantically correct with our elements uh and we're going to give it a class name foreign space Dash y-6 and smpx-6 like this and now we're going to create a conditional here so we are only going to display this variable that I'm going to write here if we are not in a group chat so to do that uh we're gonna write the following we're going to say exclamation point data is group like this and then we're going to open this and end and open parenthesis like that and now we can freely write inside what is only going to be visible in single one-on-one conversations so go ahead and write another div inside let's write the DT element again so we are semantically corrected our elements and the class then we're going to give to this DP is the following so we're going to write text SM on dash medium backslash gray Dash 500 snw Dash 40 SM Flex Dash shrink Dash zero like that and we're gonna write inside email like this great uh and now below that uh we're going to open another element called DD so go ahead and write DD like this uh and let's give this a class name so the class name here uh it's going to be empty dash one tax Dash SM the backslash gray Dash 900 and SM call Dash span Dash 2 like this so you can see we have a nice little email text right here and now inside of here what we're going to write is other other user dot email like that so you can display uh the other user email great and all we have to do now is create another conditional so just outside of this uh curly brackets right here uh open it again and again the exclamation point data that is grouped like this open and end and just open parenthesis again uh and I'm gonna use a fragment here like this so I can put an HR here like that and then I'm gonna open a div inside of this div I'm going to put a DT element like we did before so we're going to use this as a title and we're gonna give it a class name of tagslash SM phones Dash medium backslash gray Dash 500 SM W 40 SM flat slash shrink Dash zero like that and the title is going to be joined like that so you can already guess what we're going to show uh in the following element below that uh where we what we're gonna name DD like this so make a DD element inside and let's give this a couple of class names so class name it's going to be SM and text Dash gray Dash 900 and SM call Dash span Dash 2 like that great and all we're going to do inside is we're going to create a time element again so we're semantically correct here we're going to give it a date time value of joined date so another one of the variables which we created above and inside you're gonna do the exact same thing great and join date of course uh is a variable which we created right here so we use date FNS format to uh format our creative at date in a nice way and in a couple of seconds uh you're gonna see that right here so there we go now in our drawer in each conversation we can see the email of the user and when they joined and we can also click this delete which for now doesn't do anything uh but we're gonna create this in a model later so you can go ahead and you can try some new conversations if you want to so I'm going to go into my users right here just with a couple of seconds uh for this to compile and I'm going to select another user and then I'm gonna see uh their uh information so I'm going to select uh Antonio erdelics for example and once I am rerouted to the conversation of this user I'm gonna click in the drawer and you're going to see how we are able to see uh the same information but instead of the new user about Antonio ardellat's user so there we go it loaded the conversation and once I click here you can see that I have my name my image my email and also the date that I joined great great job you can play around this uh with other conversations if you want uh they should not look the same but the information should look different so let's continue with our tutorial and let's create this delete Model and also the common model component which we're going to reuse also also for this delete but also for this group chat button and also for our settings bottom in the corner so make sure you have your drawer opened like that and what we are going to do is I'm going to go back into my profile drawer here so just make sure you are where we left off and I'm gonna go and scroll all the way uh to the top here and I'm going to wrap this entire return function inside a fragment so I'm just going to collapse it like this I'm just going to open a fragment and I'm going to wrap everything inside and indent it a bit and I'm Gonna Save the file and you can expand this uh so this is the view that you have this is all we've written in the previous part all right and now inside of here I'm going to add a new component called Model like this and of course you should get a red underline because it does not exist and one thing I want to set here is is open like this and once you save your file uh you will of course get an error because model does not exist so let's go uh and open our sidebar here and let's go into the app folder into the global components here and create a new file called model.tsx so we're going to create this and then we're going to reuse it across other models that we need in the project so make sure you classify this as use client and let's just quickly fix this model right here so I'm going to return a div which is going to say hello model like this now you can go back into profile drawer and import this model from add slash app slash components slash model so I just did that right here great and I'm going to save the file and of course we have this error for this open because it does not accept that prop yet and you can see how I have my hello model right here but don't worry uh we're gonna fix that so just make sure you have your drawer opened like this great and now let's go back into this model and let's write the interface so interface model crops is going to be is open which is an optional Boolean like this it's going to have an enclosed function which is just an empty void and it's going to have a children which are type of react.react node like this and now just make sure you assign this right here so model props like that and then you can extract all of those so is open on closed and children like that great I'm going to save this file uh and now when I go back here um this is open uh it should use open error should go away great and we do have an error here because we are missing on close so to fix that you can just write on close and just give it an empty function uh like this but we're still missing the children uh but don't worry about that now because we're gonna replace this later I just want to write it here so you can see what we are developing now let's go back into our model.dsx again make sure you have your drawer opened here all right and let's remove this and let's write transition which you can import from headless UI react like this so transition dot root like this and let's give this a couple of attributes so I'm going to give it a show of it's open and as fragment and you can import fragment from react uh like I did right here great now inside of this transition dot root you're going to add a dialog which you can also import from headless UI like this great and this dialog is going to have a couple of props as well so we're going to give it an S prop as div we're going to give it a class name of relative z-50 and on closed on on clothes like this now inside of this dialog you're going to open a transition that child like that and the props you're going to write here are as fragment again now we're going to write some animations for smooth transition when this model is opened or closed so enter is going to be is dash out duration Dash 300 enter Chrome is going to be opacity Dash 0 enter 2 is going to be the opacity Dash 100 uh and then we're gonna write our leave so leave make sure you do not misspell it is Dash in duration Dash 200 leave a from is going to be opacity Dash 100 and leave two is going to be opacity Dash zero like that make sure you save your file and we get an error because we have put nothing inside but don't worry uh let's just continue developing so write a div right here inside and give it a class name or fixed inset-0 BG Dash gray Dash 500 BG Dash opacity-75 and transition Dash opacity again so just make sure you don't misspell this so transition like this and save your file and you can see how I have this even more darkened screen that's because in our profile drawer we've set the model to be is open always right so it's not false by default great uh so we can uh develop this even if our profile drawer is not open all right now inside of this div that we created right here we're actually not going to put anything but I just want to show you that you can turn that into a self-closing tag like this because it's not going to have any children great and now just outside of this transition.child I'm going to create a div inside and I'm gonna give it a class name of flex Min Dash H dash full items Dash Center justify Dash Center p-4 text Dash Center and smp-0 like that and inside of there I'm gonna open another transition.child so this is this this first transition was only for our background and now we're going to create the actual panel for our model so transition dot child and the props is going to have is as fragment enter is going to be ease dash out duration Dash 300 enter from is going to be opacity-0 translate y-4 SM translate y-0 and SM scale Dash 95 like that and I'm just going to expand my code so you can see all of that in one line like this now we're going to write enter enter two is going to be opacity that's 100 translate Dash Y dash 0 and SM scale Dash scale Dash 100 like that leave is going to be is Dash in duration Dash 200 and leave of ROM is going to be opacity opacity that's 100 translate Dash Y dash 0 and SM scale Dash 100 and leave to uh is going to be opacity Dash zero translate y-4 SM translate Dash y-0 and SN scale Dash 95 like that right now inside of this transition we're going to open a dialog.panel you can save your file I'm just going to collapse it a bit so we can see what we're working with and in this dialog panel I'm going to give a couple of class names here so I'm going to write relative transform overflow Dash hidden like this roundab Dash LG DG Dash white px-4 TB Dash 4 text Dash left Shadow Dash XL transition Dash all W Dash pool SM ny-8 smw dash full SM Max Dash W Dash LG and SM p-6 like this great now inside of that I'm gonna write a div and that div is going to have a class name here in which we're going to to put absolute right dash zero top Dash zero hidden PR Dash or pt-4 SM block z-10 like this and inside of there uh we're going to open I just refreshed my page in the morning about this uh a button element like that with the type of button last name of the following so it's going to be rounded Dash MD BG Dash white text Dash gray Dash 400 hover attack slash gray Dash 500 Focus outline Dash non Focus Oculus outline sorry ring Dash 2 Focus ring Dash Sky Dash 500 and focus ring Dash offset Dash 2 like this and on click to this button is going to be on close like that great and the span we're going to which we are going to write inside of this button is going to be uh close but we're also going to write class name sr-only like this all right and below that I'm going to add an icon IO close which you can import from react Dash icons il5 right so I imported it right here great uh and I'm gonna give this a class name of h-6w-6 like this great and now just outside of this div but inside the dialogue panel I'm just going to render children like this great uh and that's how we finished our entire uh model and now what we're gonna do is we're gonna go back into profile drawer right here and at the top right here that's the user data I'm going to add uh is open and set is open State like this and your state is going to be pulse by default and then we're going to use this uh sorry uh is model open and set is model open like that because we already have is open so make sure you use this is model open here and instead of hard coding is open we're going to make it Dynamic like this and instead of this Arrow function here we're gonna write set is open to true sorry to false like this and now you can try and extend this model like that I'm just going to create a small div with a class name of BG Dash white p dash five and a paragraph inside hello model like that uh and not set is open but set is model open like that so just make sure you use set is model open here and we're also going to use this set this model open uh all the way down here find the trash icon so not the close icon but find uh the trash icon right here so we have this i o trash and of the div of this i o track you can give an on click like this uh set this model open just make sure it's an arrow function like this to True like that great uh but actually you didn't have to do it here you can do it in this div where we gave it an arrow function so find the i o trash and not in this first div but in this second div right here so I'm going to remove this and I'm going to replace this empty function with set is model open to True like this great I'm going to refresh my uh messenger here I'm going to open the drawer and I'm going to click delete and you can see that I have my hello model right here the only problem is I don't want it to be at the bottom I want it to be in the center so I'm just going to resolve that and show you how to fix it so the fix is very simple all you have to do is go back into model.tsx right here and inside of this transition dot child element right here um what you have to do sorry not inside of this transition.child right here so where the transition.child ends what you have to do is wrap this entire elements all the way uh to here you have to wrap that in another div so just to make sure you found this correctly we have the transition root we have the dialog we have the transition.transition dot child and inside we have this div and here we have the end of transition dot child so before we begin with this div just go ahead and create another div here and you're going to wrap the entire div inside of that so just before the dialog ends like this and then you can indent this div like that and I'm just going to expand it so now I have this new div which wraps my entire code inside of this div like that great and what I'm going to do to this newly created div is give it a class name of picks inset-0 z-10 and overflow Dash Y dash Auto like this and now my model is centered great great job so now let's convert this placeholder model with an actual confirmation on whether we want to delete this or not so in order to do that let's go back into profile drawer where we actually are and you can close the model we are done with that and I just want to rename this States right here so instead of is model open I'm going to use another name for that I'm going to use confirm confirm open and set confirmed open like that so it indicates that we are opening a confirmation model and all we have to do here is replace this is open with confirm open and this set confirm open instead of set is model open and you can search through your code and find where else we use this so uh we also use this inside of our trash button so make sure you find the trash button right here and instead of set this model open to True use the set confirm open to True like that and now we can save the file and it should work exactly the same way but it's just not throw any errors to you great and now instead of using this model we're actually going to use confirm model like this and it's going to be a self closing tag like this and if you save you're going to get an error because confirm model uh does not exist so let's go uh into conversation conversations ID components and create a new file confirm model.tsx like that mark it as use client and just quickly fix the error so I'm going to use a shorthand confirmed model and with a div of confirmed model like this I'm going to go back into my profile drawer and I'm just going to import confirm model from the dot slash confirm model right here and you can remove this import for the model because we're going to use it inside of that model instead great and now if you save the error should go away but you should have these type errors because we did not Define any types here yes great and now you can see we are back to uh where we came from confirm model just says here at the header so let's go inside the confirm model and let's write the interface first so interface is going to be confirm model confirm model props is going to accept is open which is an optional Boolean and it's going to accept on clothes which is an empty void like this now just assign these props right here so confirm model crops and then you can extract is open and on closed like that great uh what I want to do now is I want to add some functions inside of this confirm model so first let's add the router so console router is going to be use router which you can import from next slash navigation like this make sure you don't accidentally do next slash router because this is next slash navigation next we're gonna get the conversation ID from use conversation after that we're going to create a a loading state so const is loading set is loading use state which you can import from react and give it the default value of false uh what we're gonna do next is we are going to create our on delete method so constant on the lead is going to be a used callback like this uh set is loading is going to be true and then we're going to run axis which you can import from axis like I did right here dot delete and we're going to point to a route that we did not have yet but we're going to create soon so instead of normal strings make sure you use backticks slash API slash conversations slash open this special object and just write in conversation ID like that and then we're going to use dot then to close this model and then router that push is going to redirect the slash conversations because this conversation is going to be deleted so we just go back to all conversations and router dot refresh like this uh we're going to catch this as well and we're just going to write post which you can import from uh react hot toast like this and we're going to write those that error something went wrong like that and finally bringing the set is loading the false like that make sure you put conversation ID and router uh inside uh the dependency array and also make sure you put on close like that great so now we have the on the lid here and now we can actually turn this into a proper model so instead of them we're going to use our model which we just created so make sure you import model from uh add slash app slash components slash model like this great so now let's just uh expand the model like this and first let's give it the is open tag and let's match it to our is open crop uh let's use on close and match it to our own close prop like that and now inside create a Dev with a class name SM Plex SM items Dash start like this and before we go further uh you can actually try and open this in your uh drawer so open your drawer and press on the trash icon and you should see our little model right here it should only have a close button for now great now let's start and develop this further so I'm going to open another div right here and I'm going to give it a class name of mx-alco flex h-12w dash 12 Flex Dash shrink Dash print Dash zero items Dash Center rounded Dash full DG Dash red Dash 100 SM mx-0 SMH 10 SM W dash 10 like this and inside we are going to use an icon so if I alert triangle like this and you can import fi alert triangle uh like this from react Dash icon slash fi like that now go back to your triangle here uh and I'm going to give it I'm going to give it a class name of h-6w-6 and pack slash red Dash 600 like that and I'm going to save this and now you can see that I have um this little icon right here great and just to center it uh below this items Dash Center you can also add justify Dash Center so the icon will be right here in the middle uh where we want it uh great and now outside of this div which wraps our triangle open another div right here and give this a last name of empty-3 text Dash Center SM ml-4 SM mt-0 SM tax Dash black like this great and now inside of that we're going to use dialog that title and inside here we're gonna give it uh also make sure you import dialog from headless UI slash react my apologies so import dialog from headless UI slash react like I did right here great and now that you have this uh give it a few attributes so as is going to be H3 and plus name is going to be text Dash base font semi bold leading Dash 6 and text Gray Dash 900 and the title is going to be delete conversation like that great uh and now uh just below this dialogue title you're going to open another div right here and you're gonna give it a class name of empty empty-2 and you're gonna give this a paragraph inside with a question are you sure you want to delete this conversation this account sorry this action cannot be undone or you can write whatever you want inside so you can see we have this long text here and let's just style it a bit so class name is going to be text SM and text Dash gray Dash 500 like this great and now we have this smooth text right here uh great and now outside of this div outside of this div and outside of this div right here you're going to open another div like this and you're going to give this a class name of empty-5 SM mt-4 SM Plex SM Flex Dash row Dash reverse like that and now we're gonna use the buttons which we created in the first part of the tutorial when we were creating the authentication screen so button which you can input from add slash app slash components slash button uh like I did uh right here at the top great uh and now this button is gonna say delete like this and you can see that I have this delete button uh right here uh and media I just made a mistake here make sure you uh don't combine these two classes so the parents should have SM flex and SM Flex row uh reverse like that so your buttons should be in this right corner like this great and now let's give this some attributes so it's going to be disabled when our is loading state is true uh it's going to be of type danger if you remember we defined that as well and now you can see it's red and on click is going to be on the link like that perfect and just below this you can copy and paste this button because we're gonna have two of them but this one is not gonna be danger it's going to be secondary like that and instead of on the lead it's going to say on close and instead of uh Delete is going to be canceled great so now you have uh these two buttons right here if I click cancel nothing happens but if I click uh Delete I should get an error that something went wrong because our delete API route does not exist yet so let's go ahead and create that delete route so I'm going to expand everything here I'm going to collapse it I'm going to go into my app folder into API into conversations into conversation ID and we already have the scene folder here but I don't want to create anything in the scene folder I want to create it in the conversation ID so right click on your conversation ID folder create a new file called route.ds so now you should have a route.ds which is inside this conversation ID folder and also a scene folder which has its own route so make sure you don't accidentally create another one in the scene folder we just want a route inside our conversation ID right here great now let's define an interface here so interface I params is going to accept conversation ID which is a optional string like that and now let's just write export asynchronous function delete like this uh it accepts a request which is a type of request and the second argument we're going to destructure it in the params and we're immediately going to return the type of parents to I parents like this as I've mentioned before make sure you don't accidentally do this because that is not going to work or this so terms are a second argument and they need to be second in this list three now uh you can go ahead and open a try and catch block I'm going to catch the error which is a type of any here and I'm going to console log the error with the message error conversation error conversation delete so when you're debugging your application you know this is where the error came from and I'm going to return new next response which you can import from next slash server and I'm just gonna say internal error with a status of 500 like this great now I'm going to go back into my try block right here and first I'm going to extract the conversation ID from the parameters so conversation ID from parents like that then I'm gonna get my current user so const current user is equal await get current user you can import a get current user from ad slash app slash actions get current user like this first let's check if we don't have a current user so if there is no current user question mark ID in that case return next response uh sorry return new next response announcer unauthorized with a status of 400 N1 to be more correct great uh if that is okay we're gonna find the conversation so const existing conversation is going to be await Prisma dot conversation dot Point unique okay so I made a mistake here before you write uh anything further make sure you import Prisma so go ahead and write import Prisma Prisma BB like this great and now we can go back here to await Prisma and we can now write Prisma dot conversation dot find unique where ID is conversation ID like that we're gonna write include users true like this we're gonna check if there is no existing conversation so if there is no existing conversation return new next response invalid ID with a status of 400 like this great now if there is we're going to delete our conversation so const deleted conversation is going to be away Charisma dot conversation dot delete many where ID is conversation ID and important we're going to protect that not anyone can remove any conversation so only users which are part of the group can remove the group so we're gonna write user IDs has some current user dot ID great and we're going to return nextresponse.json deleted conversation so I know what you're thinking why did I not just call this why do we have to look for our existing conversation here well again I'm just preparing for when we add real-time Pusher because we need to find the users inside of that conversation and in real time remove the conversation from their sidebar so that's why we are using this but unfortunately we can only use include users if we use find unique we cannot add include users to a deleted conversation so that will not work with delete many so unfortunately that's why we have to do it at this way it's going to make sense in the future when we map over these users and send each and any one of them uh the uh Pusher update great so I'm just going to refresh this now I'm going to expand my browser here I'm going to open a network tab as well just collapse it a little bit so that I'm in the desktop view all right and I'm going to open my network like this I'm going to open the drawer and I'm going to click delete and delete again all right uh we got an error here let's see uh what happened so slash API slash conversations all right we got request method delete 405 method uh not allowed so let's just check uh what we did wrong so uh perhaps this worked for you I did not save my file so I'm just going to try uh again and yeah it works I just didn't save my file apologies so great after that what I'm going to do well after I've deleted this I'm just going to go back to slash conversations like this and my conversation should not be here and it's not great I can click on Antonio sorry for new on new for example now and I can try and remove that conversation as well so nothing we did wrong I just didn't save my file apologies great after I remove this you can see that I'm rerouted back and we're going to update this I mean remove this with Pusher in real time so right now it's still here until we refresh and just for you to have some conversations you can go ahead and go into users and just select one conversation so you create another one to confirm that's working as well so let's just wait a couple of seconds for this uh to compile and build and there we go uh hello new conversation like that uh great okay so we still have to refresh because nothing uh is real time yet great uh so we finished uh our we finished our uh delete Model right here and now we're gonna reuse that model to create our group chat model and our settings model great great job great so now we're going to create our settings model so I'm going to expand my code right here uh make sure you are in desktop view so you can see the sidebar and I'm going to go back into my app folder into components sidebar desktop cider component right here and what I'm going to do I'm going to wrap this entire div inside a fragment so I'm going to write fragment like this and like this at the bottom and then you can indent all of that here great and what we're going to add here is the settings model like this which does not exist yet but let's go ahead and let's give it some attributes so it's going to have the current user like this is going to have is open it is open and it's going to have on close set is open balls like that okay so we do not have the is open we actually do so we created this state but we did not use it until now great so just make sure you have this EU state with is open and set is open and if you save the file you're going to get an error because settings model does not exist yet so just make sure you go into sidebar and the components into sidebar and create a new file settings model.tsx like that make sure you uh mark this as use client and quickly fix this error using the shorthand so settings model Dev settings model like that and now I'm going to go back into desktop sidebar and just import this from dot slash settings model like this and if you save the error should go away now uh all right and I'm gonna go back into my settings model and I'm gonna start uh developing the interface for that so interface settings model props is going to accept is open which is an optional Boolean on close which is a void and current user which is a type of user from App Prisma slash client like this and then you can assign this props so react FC is going to be uh settings model props like this you can extract here so it's open on close and current user like that and now what I'm going to do I'm going to create some hooks here and functionalities so I'm going to write const router easy to use router from next slash navigation like we did uh before in other models I'm going to get these loading stage so const is loading set is loading use state to false and make sure you import use State prom react like this great and now we're going to add our use form so const and the object is equal to use the form from react hook form like I did right here great and just make sure you execute this like that uh and we're going to give this pointy brackets to this used form and type is going to be field values which you can also import from react uh hook form like I did right here at the top great and inside of this object here you're going to write default values and you're going to give it a name of current user question mark name and image of current user question mark image like that great and everything we're going to extract from this object is going to be register handle submit set value watch form state and errors like this great and and now that we have that we're going to define a custom variable which is going to watch our image great so go ahead and write const image is equal to watch image like this so just make sure you don't misspell the image as you've written it here in the default values great and now go ahead and write a function called const handle upload which is going to accept result of type any it's an arrow function which is going to call set value which we have right here distracted it from use form and it's going to assign image so just make sure that this image this image this image and this image is not misspelled correctly and it's going to assign result question mark dot info question mark dot secure underscore URL like this and make sure you open an object at the end as a third parameter and write should validate true like this perfect now you have your handle upload and now we're gonna have a const on submit which is a type of submit Handler which you can import from react a hook form as we did with use form and fill values like that and it's going to accept field values in these pointy brackets just write field values which we already have imported so that means it's going to have a data open an arrow function like this set is loading to true and we're going to make an axios call so make sure that you import axis from axis like I did here and just write the axis that post slash API slash settings like that and pass in the data uh dot then what we're going to do is we are going to call router.refresh and we're going to trigger the manual on close uh in dot catch we're just going to throw toast which you can import from react uh hot toast like I did right here great and the toast is going to be dot error something went wrong like this and that finally it's just going to be an arrow function which resets the set is loading to false again great and now that we have that we can start developing the UI for our settings model right here so instead of this div it's going to be a model component which you can import from dot dot slash model because we are already in the components folder great so just make sure you import your model from dot dot slash model since you are already in the app components what we do is we go outside the sidebar folder and Target this model right here great so now that you added this model give it an is open all through is open prop and on close our on close prop like that great now inside we're going to open a form we're going to give this an on submit of handle subnet on submit like that so we use the handle submit from use form and we wrap that around uh sorry we've wrapped our on submit around the handle submit so we have this data uh which is either going to be an image or the username great and just to see what we are doing uh what you can do is you can go back into desktop sidebar in the settings model find this set is open scroll all the way down and find your avatar and you already set we already said the set is open to true so just make sure you have this around your avatar in the desktop sidebar or on the div make sure you have an on click and then when you click here it should open a model that looks empty great now go back into settings model right here and let's continue developing uh this form so open a div uh and give it a last name of space Dash Y-12 inside create another div with the class name border Dash B the Border Dash Gray 900-10 so slash 10 means opacity 10 npb-12 like that uh and inside an H2 uh which is going to say profile like this and give it a class name of text base font touch semi bold leading dash 7 and text Gray Dash 900 like this and just below this H2 create a paragraph which is going to say edit your public information like that or whatever you want it to say and give it a class name of mt-1 tax Dash SM leading Dash 6 and text Dash gray Dash 600 like that great so now that we have that just below this paragraph create another div like this and you're going to give it a class name of mt-10 flex Black slash coal and get Dash Y dash eight like that and now we're going to reuse our inputs from the out form that we created so input which you can input from dot dot slash inputs slash input so like I did here so like we did with the model we go outside of our sidebar into the inputs and we target the input so that's why we're doing that great it's a self-closing tag uh now we're going to give this a disabled up is loading we're going to give it a label of name we're going to give it an ID op name we're going to give it an errors of errors and required and register up register like this great uh so now we have this name and it immediately filled uh our Antonia name here great that's exactly uh what we wanted and now inside of this div which we are going to create below this input you're going to create a label like this which is going to say photo like that and let's go ahead and give some class names to this label so it's going to be a block text Dash SM Pawn slash medium leading dash six packs Dash gray Dash 900 like that uh great and now our photo label is going to look like the label for our input the reason we are not using the input here is because it's not going to be a normal input it's going to be especially designed for uh for image upload So Below this label create a div like this and give it a class name of mt-2 collects items Dash Center and GAP Dash x-3 like that now inside we're going to use an image component from next slash image so just make sure you import that image from next slash image all right go down to your image here and give it a width of 48 give it a height of 48 class name of rounded Dash full and source is going to be either an image pipe pipe current user question mark dot image or pipe pipe is going to be our default slash Images slash placeholder that jpeg like that and of course give it an alt of Avatar like this great so now you can see that it's using this default image right here but if we upload an image it's going to use that image or if we already have an image in our current user is going to use that image which is exactly what we want great now just below this image we're going to use a component from next cloudinery CLD upload button so just make sure you import this from next Dash cloudinery like that uh like this we're going to give it options of Max files one on upload is going to Target handle upload which we defined above and upload press it is going to be you can either find it in your cloudinary settings or you can re find it where we did it in the uh form where we upload our images so we created this upload preset and you can just copy it so if you don't know where this is in your conversations folder in conversation ID in components form so we already have image upload for our messages and you can reuse that exact preset so we just go ahead copied go back into your settings model and paste that same preset to the upload button here great and now we're going to add our button component so make sure you import that from dot dot slash button so the same way uh we did for model and input so dot dot slash button uh and in here you're going to write change like this you're gonna give it a disabled of uh is loading and it's going to be secondary and type is going to be button like this uh great great so now you have this button which when clicked shoot the trigger uh an upload of an image and if you try and upload an image if our form works correctly if I select this for example uh and after I upload it um it should change your photo to this why well because we target this image which is in our watch right here where we defined it and the beginning great so now that we have that what we have to do uh is we have to create the submit button so just go right here to the bottom where we have the last slash div the last slash form and slash model so right here where I left the space like that and you can just create a new div right here and I'm gonna give this a class name of nt-6 flex items Dash Center justify Dash and GAP Dash X-6 like this great and now uh inside of that div create a button like this uh with a text of cancel give it an attribute of disabled is loading secondary and on click on close like this so now you will have your cancel button and you can go ahead and copy this button since we're gonna have two of them the second one is not going to be secondary so you can remove that and the type is going to be submit so it's not going to have any on click it's going to call our form on submit right here great so just make sure it's inside of the form and instead of cancel it's going to be save like this great so now if you try and change your name for example I'm going to change into Antonia 2 and click save everything should be disabled for a second and then we're gonna get an error of course because the route which we defined right here in the handle submit uh does not exist and that's what we're going to create now so I'm going to open my sidebar I'm going to collapse everything and I'm going to go into app into API and I'm going to create a new folder called settings and inside settings I'm going to create a new file route.ds like this I'm going to export asynchronous function post it's going to accept request which is a type of request we're going to open a try and catch Block in our catch we're going to catch an error which is a type of any we can console up the error with a uh error settings message so we know where it's coming from and just returning new next response which you can import from next slash server with a message of internal error and a status of 500 like this right now inside of our try first let's get the current user so const current user is equal await get current user which you can import from add slash app actions get current user like this body is await request.json so we destructure the body like this and inside the body we get the name and an image like that first let's check if our current user is here so if there is no current user question mark.ib in that case return new next response an authorized with a status of 401 like this otherwise let's update our user so const updated user is equal to await Prisma and just make sure you also add Prisma so import Prisma from add slash app slash lives Prisma BB like this great so now we have uh the Prisma so away.prisma.user.update where ID is equal to current user dot ID like that and the data which we are going to update is image image and name name if you want you can also use shortcans for this but this works just fine and then just return next response dot Json updated user like that great make sure you save this and now I'm gonna go here I'm gonna open my network tab here and I'm going to click I'm going to change this to Antonia 3 and I'm going to click save like this we have our settings right here and there we go and now I'm going to refresh my page and you can see that my name has changed so uh right here I'm in a different conversation but you can see that I sent this message and now it says Antonio 3 it has my new image and I have my new image here at the bottom and you can see how it's right here and you can try for example mark this is my new name I'm going to click save again uh and if I refresh again you can see now it says Mark right here and if I open my settings folder it says Mark great great job uh you finished the settings model in the next part we're going to create the group chat model so let's continue with our development and let's create a model to create a group chat so first I want you to open your sidebar right here I'm going to collapse everything and I'm going to go into the app folder into my conversations uh into components and I'm going to select a conversation list so not conversation box uh conversation list like this I'm going to try and expand this if it's possible great so make sure you select conversationalist like this great and I'm just going to expand this make sure you're in desktop mode as well so you can see this plus button here great so now that you're in conversational list here I want you to add another state just below this one so go ahead and write const is model open comma set is model open like this is equal to use State and default value is going to be false and now we're going to use this set is model open when we click on this uh button right here next to the messages text great so copy this set is model open right here and go ahead and just find the div uh that wraps the MD outline group AD in my case that is a this div right here it should be the same for you and just add on click is equal to an arrow function which sets the settings model open to True like this great and now what I'm gonna do is I'm going to wrap this uh entire aside thing into a fragment so just go ahead and write a fragment like this and go all the way to the bottom and end the fragment like that and now we can go ahead and indent everything inside so it should look something like this so your fragment should wrap the entire aside element here and inside of here we're going to create a new element called group chat model which does not exist yet we're going to create it and the props I want the best here is is open to be is model open and on close is going to be an arrow function set is model open polls like this if you save you're going to get an error because group chat does not exist so let's just fix that quickly uh right here in your components you can go ahead and create a new file group chat model that's the SX like this so go ahead and Mark this as use client like this and just do a shorthand uh to fix the error so group chat model for me it's just going to be a Dev group chat model like this and go back into your conversational list and just import that at the top so the group chat model is not defined error goes away after you hot reload and don't worry about this type error we're gonna fix that soon so now you should see the text group chat model above your messages but we're going to turn that into a proper model so before we start doing that what I want you to do is I want you to open your sidebar and go into conversations folder into layout right here so the place where we call our conversations and alongside conversations we're also going to call our users which is an action we already have because we have the users page so go ahead and write const users is equal to await get users and you can import that from dot dot slash actions slash get users like this so the same way you did with get conversations just import get users we already have that and now just make sure that in conversation list you pass in the users like this now we have this error of course so let's just go ahead back into our conversation list and let's add users which is a type of user which you can import from at Prisma slash client and make sure you put an array at the end and save the file and if you go back into your layout there should be no error for you sending users here great now let's go ahead uh and let's also pass users to this group chat model here so I'm going to write users is equal to users like this so group chat model should have the users is open and on close and of course make sure you actually destructure the users from the props here in the conversation list after you've added it to the types and then if you save you should not get these error users is not defined great and now we can go and focus on developing our group chat model here so first thing I'm going to do I'm going to write an interface for it so interface group chat model model crops it's going to accept is open which is an optional Boolean on close which is just an empty void and users which is a type of user which you can import from ad Prisma slash client and make sure it's an array like this now use react FC just add these types right here and feel free to extract all of those props so it's open on close and users like this perfect so what we're going to do now uh is we are going to add some actions here so I'm going to add const router is equal to use router from next slash navigation um const is loading set is loading is going to be used state which you can import from react and make sure the default value is false so I input the new state from react and use router from next slash navigation right here great and now we're going to create our use form functions so const open an empty array and just write use form which you can import from react hook form go ahead and open the pointy brackets and the target is going to accept this field values which you can import from reactive form as well open parenthesis and open an object inside and we're just going to define the default values like this it's going to have a name which is by default on empty string and members which is an empty array by default great and now we're going to extract something in this object right here so go ahead and write register handle submit set value watch and form state and the structure errors from it like this great so now that we have that we can go ahead and we can watch our members so the same thing we have to do uh in our settings model with the image so const members is equal watch members like this make sure you don't accidentally misspell members so make sure that members is here members is here and members is here great what I'm going to do next is I'm going to create our own submit function so const on submit is a type of submit Handler which you can import uh from react hook form alongside field values and use form like that open the pointy brackets and just write field values inside you should already have that it's going to be an arrow function which accepts the data as parameter or open an object like this and just write set is loading the true and then we're going to initiate an axios call which you can import and you can import access from axios like this and just write axios dot post slash API slash conversations so it's the same route that we are calling when we create a single one-on-one conversation but if you remember in our conversations API route we also created the functionality to create a group chat so what we're going to do is we're going to spread this data and we're going to add an important value here is group to be true like this great uh on that then I'm going to create an arrow function and just write uh sorry I'm going to open it like this and first I'm going to router.refresh and then I'm going to do on close like this uh in the dot catch I'm going to do an arrow function which calls it host which you can import uh from react hot toast like this and it's going to call an error something went wrong like that a great okay so I have an error here whoops my bad so make sure you import those like this and I'm just going to retype this since I obviously made an error so error something went wrong like that and that finally uh in which arrow function we're just going to set is loading defaults back again great you completed the on submit function here and now we can go ahead and start developing the model so instead of the div it's going to be a model which you can import from add slash app slash components slash model like this so just make sure that you've imported it like I did right here great I'm going to go here I'm going to give it some props so it's open we're going to give the prop is open like that on close it's going to be on close like that great now inside of this div we're going to open a form element like this and we're going to give it an on submit of handle submit and just wrap your our custom on submit inside of it so again we do this so our on submit can have access to this data which is the type of field values and field values is defined here and they are controlled by the use form great so now that we have the form uh let's go ahead and create a div inside and let's give this div a class name of space Dash Y dash 12 like this and before we move any further uh I suggest that you click on your icon right here and it should open an empty model so you can actually see what you are developing so you don't develop blindly great now inside of this div let's go ahead and let's write another div and let's give it a class name of Border Dash B border Dash gray Dash 900 10pb-12 like this great inside of that we're going to add an H2 element and we're going to give it a class name of text Dash base Point semi bulb leading dash 7 and text Gray Dash 900 like this great and inside of the H2 we're going to write create a group chat like that and just below this H2 we're going to create a paragraph which is going to have a text of create a chat with more than two people like this and let's give this a class name of empty that's one text Dash SM leading dash six tax Dash gray Dash 600 like that perfect uh and now just below uh this paragraph right here we're gonna open another div we're gonna give this a class name of mt-10 flex Flex Dash call and GAP Dash y-8 like this inside of that div go ahead and import the input which we already used a couple of times in this project so add slash app slash components slash inputs folder and the input element so just like this great uh it's going to be a self-closing tag and what we're gonna give it is register register and we use register from uh use form destructuring like this great below that we're going to give it a label of name and ID of name a disabled off is loading and required uh like this and let's also give you the errors errors like that and another an input should be uh shown right here great uh what we have to do next is we're gonna have to create a select uh component so I'm just going to prepare it here so just right select it does not exist yet it's going to exist soon uh give it a disabled of is loading give it a label of members give it an options of users.map user go ahead and open an immediate object like this value user dot ID and label user.name like that and for an on change you're going to write an arrow function which accepts the value in its parameter right here and we're going to call set value which we have the structured from form state in use sorry from use form right here open parenthesis here and first we Define what value we want to update well we want to update the members value that's why we watch it separately because it's not like our regular inputs so just go ahead and write members here as well great go ahead and open the third parameter uh sorry the second parameter is going to be the actual value like this and the third parameter is going to be an object so go ahead and expand it and just write should validate true like this great and also give it a value of members like that where do we get the members from well from the const members watch members so just make sure that you have members in the default value as an empty array make sure you have a variable called members with a watch function with the same string members make sure you set the value to the exact members and make sure you have the value prop members so the value prop is very important right here and now what we're going to do is we're going to create this select button right here so let's go ahead and let's open our navigation here let's go into components into inputs folder and create a new file select.dsx like this Mark it as use client like that and let's just quickly fix the errors to select I'm just going to write div select like this I'm going to go back into my group chat model and I'm just going to import this from add slash app slash components slash input slash select uh like this I can go ahead and save the file so this is how I imported the select the same way we did with the input great uh the select is not defined error should go away any second now and now we're going to go ahead and actually fix this errors so just make sure you have your model opened like this go back into select.vsx and first let's write the interface for it so interface select props is going to be a label which is a type of string a value which is optional and a type of record open pointy brackets string Dash any sorry string comma any uh on change is going to accept the value which is the type of record string comma any and just an empty void like this options is going to be an array of record any so go ahead and write it like this so record screen comma any and that's good an array at the end so the type is correct and disabled it's going to be an optional Boolean like that great and now just use react dot FC to properly assign this select props here and now we can go ahead and destructure all of them inside so label value on change options and disabled like that perfect and now let's go and uh let's start creating uh our select so first let's give this a class name of Z Dash open square brackets 100 like this great now inside I'm going to remove this text so I'm going to write a label like this I'm going to give it a class name of blocks text SM on medium leading dash six and tag slash gray Dash 900 like that and inside the label we're going to use our label prop which we structured right here and which we set as required and of course which we send in the select in the group chat make sure you send all of this otherwise you might be getting some errors where you're developing this great so now that we have uh the label let's go ahead and let's open a div and let's give this a last name of empty Dash two great so now we have to install a package called react select to create our autocomplete so let's go ahead and let's go into terminal I'm going to close everything and I'm just going to write npm install react Dash select like this wait a couple of seconds for this to install great and now I'm gonna go ahead and run npm run Dev again I'm going to close the terminal and I'm going to refresh my application just in case uh uh it has out the hover load is not working great so now we can start developing the react select right here I'm just going to wait a couple of seconds for my page to load great and now I'm going to add react select and we're going to import react select from react select so to go ahead and write import react select from react Dash select like this usually you might see examples of Select from react select but that is a problem because our component is name select so just make sure you don't have the same name as our component so I'm going to use react select from react Dash select like this and then we can safely use it right here great it's going to be a self-closing tag like this and let's go ahead and give it some props so it's disabled it's going to be our prop disabled like this value is going to be value like this on change is going to be on change is multi is going to be the true so you can either write it like this or you can use a shorthand like this it's the same thing options is going to be options like that menu portal Target is going to be document.body so the reason we're using this menu portal Target is because our Auto Select is inside a model so that causes some problems with Z index and overflowing so that's why I did this fix to Target the document about it great and we just have to give it a style so it's files go ahead and open an object like that menu portal base and open an object like this spread the base inside so these Styles will stay intact and we're just going to modify the Z index of it to 9999 like this great and last thing we're going to add in the Styles uh sorry not in the Styles my bad so that's it for Styles just go ahead and add class names so not class name class names and open an object and write control and just open an arrow function which is going to say text SM like this um and save your file and in a couple of seconds there we go you can see my input and you can see my user so I have new I haven't done it let's like this a great so just make sure when you're testing this uh that you have enough users so I'm going to go ahead and I'm going to create a couple of users so you can get the best experience when creating this so I'm just gonna log out here and I'm gonna create a couple of more users so I'm going to click create an account I'm gonna add I don't know John and I'm going to register so I should have about four users now I think that's enough to create a good group chat so let's just wait a couple of seconds there so we have new Mark Antonio and myself uh which is John right and I'm gonna go now uh in my conversations I'm going to expand everything here and I'm going to open uh my network tab okay I have to expand this a little bit more because I'm just not seeing my whoops excuse me okay I'm gonna open my network tab to see if something accidentally goes wrong I'm gonna click here I'm gonna create this a group chat like that oops so group chat and for the members I'm going to select new Mark and Antonio great and actually we cannot test it because we have not completed the model I'm sorry I forgot to add the buttons okay I'm just gonna collapse everything here and now let's go back into our group chat model so we are done with the select my apologies I forgot that we are missing a couple of things uh we have to add here uh so what you want to do is go just outside uh this last div but still inside the form open your model and go ahead and write div like this give it a class name of nt-6 flex items Dash Center justify Dash and and GAP Dash X-6 like that great and inside we're going to use our button so just make sure you import that from add slash app slash components slash button like this uh and it's going to have a text of cancel so that's going to be the first button and let's go ahead and just give it a disabled of is loading and on click to be on close I type to be button and secondary as a prop like this below that we're gonna have another button and this one is going to have a text I'll create like this and all it's going to have is disabled which is is loading and the type is going to be submit so this is going to be instead of on click so when we submit the form which is wrapping this entire thing is going to be calling this on submit right here so now you can expand this I'm going to open this right here I'm going to open my network tab to see if we're doing everything correctly and you can try and click create right here I'm going to open this to see what my payload is great so what we send is is group true and we send an array of values uh which hold our IDs and the name of the users and the name of group chat great uh and apparently it's been created successfully so I'm just going to refresh this to confirm that great and we have the group chat right here uh one thing we have to modify now is we don't want to display a random persons from the group a random person image from that group chat you can see how we have the group chat here we use four members here great uh but you can see we have no information here because remember we did some conditionals that we only display if it's not a group chat so what we have to do now is we have to create a component called Avatar Group which is going to display three avatars from the group chat and we have to modify this drawer a little bit so we can actually show some information about the group chat great so let's go ahead and let's create that Avatar group component so I'm going to uh just expand this a little bit uh make sure you are in desktop view okay and what I'm going to do I'm going to go into my conversation box component like this and we're gonna find where we use uh our Avatar components so just go ahead uh and find a reuse that so there we go it's line 86 in my case so go ahead and find the Avatar component and what we're going to do is we're going to create a dynamic render of this so we're going to add data.is group question mark open parenthesis and write avatar group like this and otherwise we're going to render the Avatar which we uh are used to seeing by now great and uh what we're going to pass in this Avatar group is not user but users and it's going to use data dot users like this and if you save the file of course you're going to get an error because our group does not exist I mean you're only going to get an error if you have a group chat available great and now let's go into our app folder into components where we have our Avatar and just create a new file called Avatar group dot the SX so group.bsx like this uh I'm going to mark this as use client like that and I'm going to create uh a shorthand Avatar group wait a avatar group like this just to fix the error so go back into conversation box and just import Avatar group from add slash app slash components Avatar group so the same way you did with Avatar great and now the error should go away and you can go back into Avatar group and start developing it so you can see we have this weird text here right now for our group so what we're going to do is write interface Avatar group props users question mark user which you can import from App Prisma slash client and just add an array like that and then you need to write react.fc open the pointy brackets and write avatar group props like that and you can expand them here users like this great so first uh we're only going to use three users from our group chat so we're not going to do more than that we're going to write const sliced users to be equal to users dot slice 0 Dash three like that and uh what I recommend doing is giving this user prop a default value of an empty array so you don't have to use this question mark like that great so once you get that this way we get the first three users and now we're gonna write a const position map which is going to be an object which is going to hold values on how we want the position uh every of our elements so the first avatar is going to have a class of top zero left Dash open square brackets 12 pixels the second is gonna have a bottom Dash zero and the third one is going to have bottom Dash zero and right dash zero like that great so the first one is going to be at the top and kind of a centered um the second one is going to be in the bottom left corner and the last one is going to be in the bottom right corner great and now we can go ahead and remove this text inside like that let's give some class names to this div so class name is going to be relative h-11 whoops and W Dash 11 like that now inside we're gonna map over our sliced users so sliced users.map user and index open uh and immediately return a div like this so go ahead and close the div like that and what you're going to do is going to give it a key of user.id and class name is going to be so Metro use backticks like this and just write absolute inline Dash block rounded Dash full open Flow Dash hidden H dash open square brackets 21 pixel W Dash open square brackets 21 pixel like that and then you're going to use this special object in which we're going to look through the position map and depending on whether the user is first the second or third we're going to assign that class to it so what we're going to do is we're going to write position map inside this special object and we're going to add index and now we just have to fix typescript so as key of type of position map like this and the error should go away so basically what we're doing is we're using a number which is either 0 1 or 2 because there are only three users which we pick and then we map that index to the class name so either 0 1 or 2 great and now inside of this leave go ahead and import the image from next slash image like that so just confirm that you imported it from next slash image like that grade itself closing tag give it an out of Avatar give it a fill property and source which is either user question mark dot image pipe pipe slash Images slash placeholder.jpg like that and go ahead and save your file and now uh you should be able to see uh the three users there we go so I have the Antonio user the mark user and a new one great great job amazing job so I'm gonna go ahead and I'm gonna try and send multiple messages in this chat so I'm gonna write uh what is my name here so John I'm gonna write test John message like this uh we don't have real time yet so I'm not sure when it's been sent so you can go ahead and just refresh until it appears here so there we go so test John message you can see that I've sent it now I'm gonna log out and go back into my other accounts so Antonio I'm gonna go back in now let's just wait a couple of seconds I should also have uh the group chat here since I've been added to that group chat there we go and you can see that I get this test John message here which I've not seen yet great and I'm gonna write best uh Mark message since I renamed this account to Mark if you remember I'm going to refresh here as well to ensure that I've gotten this message so there we go uh test Mark message great and I'm also going to log out and just confirm my last user so new like this if I have that account I do great so I'm gonna go back into my conversations you can see I have test Mark message here okay so it's not oh it did update great okay and here I'm gonna write uh test uh new message like that so now you can see that our group chat is working so these are assigned on the right side and my message is going to be assigned to uh the right side great great great job so now we have to add that our other group back into our header as well uh so what you're gonna do here is go and find your header component so going to a conversation ID components header like this go ahead and find the Avatar so for me it's line 69 and let's just create a conditional so conversation dot is group question mark and in in the first one what we're gonna write is going to be just Avatar Group which you can import from uh add slash app slash components all other groups so the same way you did with Avatar like that and they're gonna pass in the users users sorry I'm gonna pass in conversation dot users like that great and there we go now we have the group chat in the header as well and now let's just go and fix the drawer so we have to add the same thing here so just go ahead and go into profile drawer component in the conversation ID folder right here and what you're going to do is you're going to find the avatar let's see okay so for me it's line 163 and we're gonna create a conditional so data that is group so the same way with it with our previous components like this and if it's group it's going to be Avatar groups you can import from add slash app slash components or whatever group and just passing the user's uh data.users like this make sure you imported Avatar group from App components our group like this and now if you try the drawer you can see that we have um the very uh same thing great so one thing I want to do now I'm just going to expand this make sure your profile drawer is open so let's add some information to this drawer if we actually have a group chat great so go all the way down and you're gonna find where we have these values data is grouped but we put an exclamation point so these are only the values which render if the conversation is not a group so just before um the first one right here so inside this DL elements for me it's line to 130 for you it might be something else so just find this First Data is in group like that where we write the email and what you're gonna do here is open a conditional right data that is grouped like this so this time without the exclamation point at the beginning and end open parentheses like that and open a div inside and just go ahead and write DT element like that give it a class name of text SM font medium backslash gray Dash 500 smw-40 SN let's Dash shrink Dash zero like that and inside just write emails like this okay so now instead of email we have emails like that and outside of this DT element create a DD element like that and give it the class name of mp-1 texts SM backslash gray Dash 900 sm all Dash span-2 and inside we are going to iterate over our data conversation users and display each user's email so go ahead and write data.users.map City user open an arrow function like this and just write user dot email okay this is going to create an array of user emails and at the end all we have to do is write dot join put a comma and put a space inside the string so there is room uh between each email and there we go now we have uh all the emails of the users which are in this group chat great great job and delete will work uh as well great so you have the group chat now um all that's left before we move on to creating real-time communication is to create this model for the image when we click on it and also uh to create some loading States because right now when you click in between stuff when you change stuff it just looks weird it looks very uh slow but we're gonna add some loading States so it looks much much better great and you can try and click create like this it won't allow you you can try and create a name and maybe just add one user and click create and you should get an error back because in our API conversations uh for the group we made sure that there are at least two members in that group so let's uh let's see what happens uh perhaps we need to protect it to three users let's see what happens if we do that great so I I think this is actually a mistake because oh no it's not it's completely correct yes yes sorry my bad it is completely correct uh it's working as intended uh why how how come there are three users if we just created them with two of them well because we are the third user so this code is completely correct great great job so what I'm gonna do now uh make sure you have sent a message with an image somewhere and we're going to create a model which will open on this image so go ahead and open your sidebar go into conversation ID sorry not in the API uh so go into your conversation conversation ID into components and select message box component uh right here where we have the scene by and basically our messages and just go here to the top where we have the session and just below that go ahead and add a state so cons image model open set image model open like that use state which you can import from react and give it a default value of false make sure you import the use State like that great so image model open and set image model open like this so now what I want you to do is I want you to find where we have this image right here and add an on click to this image and just write an arrow function set image model to be true like this great and inside of this div of this data image we're also going to add our model so go ahead and write image model like this which of course does not exist now let's go ahead and just give it some props which we are going to need so source is going to be data dot image is open it's going to be image model open on clothes it's going to be an arrow function set image model open Pulse like this and of course if you save the file um you're going to get an error because image model does not exist so let's quickly go and in the same folder where we have the message box create a new file called image model dot the SX like that Mark it as use client and let's just quickly fix this error so image model I'm going to create a div which is just going to say as always image model great so now that we have that quick fix let's go back into message box and let's just import uh the image model from dot slash image model like this right and you can save this file the error should go away and of course you have the type errors which we're going to fix now so after your error goes away go back into image model component right here and let's start by defining uh the interface for it so I'm gonna go ahead and write interface image model crops is open question mark Boolean on close is going to be an empty void and source is going to be either a string or null like this go ahead and use react.fc to assign image model props like that just extract is open on closed and Source like this go ahead and write if there is no Source we're just going to return null otherwise it's going to be a very simple model so we're going to use the model component which you can import from add slash app slash components model like I did right here and inside of the model we're just going to assign this open to be is open and on close on close like this and we're going to create a small div inside click last name of w Dash 80 and h-80 and we're going to use an image component from next slash image like this let's give it an ALT of image let's give the class name object dash cover let's give it a Field property and source is going to be Source like that great and after you've saved this file you should not have any errors in the image model here and you can go ahead and try click right here I'm just going to refresh to make sure everything uh is um uh Reloaded so let's just wait a couple of seconds and there we go you can see that I have my image in a model so if you got an empty model make sure you refresh uh great great job so all we have to do now is add the loading States and then we are ready to wrap up this tutorial by adding Real Time with Pusher which is going to be very simple and then we we're going to deploy that um to versal great so now let's finish um the uh last part before the real-time notifications and that is the loading model and loading States so I'm going to close everything here I'm gonna go into my app folder into components and I'm going to create a new file called loadingmodel.dsx like this I'm going to mark it as use clients I'm going to import react and fragments from react I'm going to import dialog and transition from at headless UI react and I'm going to import clip loader from reacts Dash Spinners which is a package that we have to install so go and head into your terminal right here and run npn install react Dash Spinners like this wait a couple of seconds for this to install and do npm run Dev again and just refresh your localhost so everything is up to date great and now let's start with our um component so I'm going to write const const loading model like this and it's going to immediately return our whoops just make sure you don't use the invalid brackets so return transition dot root like this show as fragment like this so usually when we do the show we do something like is open but that's not how we're going to use our loading model so our loading model is always going to be open because we're going to render it in a different way and then again is the dialog as Dev with a class name of relative z-50 and the dialogue needs to accept and on close so for that we're just going to give it an empty function like this and close the dialog so I'm just going to collapse this attributes right here so you can clearly see what I've written great now inside of that dialog right here add a transition dot child like that give it an as fragment like that enter is dash out duration Dash 300 enter from is going to be opacity Dash 0 enter 2 is going to be opacity Dash 100 leave is going to be is Dash in duration Dash 200 leave prom is going to be opacity that's 100 and leave 2 is going to be opacity Dash zero like that and now you can just go ahead and write a div inside uh it's going to be a self-closing tag so you can write it like that and we're going to create our overlay now so just give the class name of fixed inset-0 BG Dash gray Dash 1-50 sorry that's 100 BG Dash opacity dash 50 and transition Dash opacity um like this great and now just to test uh this out uh what you can actually do make sure you export default loading model like this great and now you can use this loading model so uh where I'm going to go I'm going to go um into the user box component so just go and make sure you select the users in the sidebar right here so you are not in messages but you should be in users so like this you should see people here great and now inside uh go ahead inside your users inside components and select the user box like this and go ahead and wrap this entire div inside a fragment like that and you can just invent it and what you're going to write is the loading model like this so just make sure you import it from add slash app components loading model uh and if you save this file uh you should just see an active model uh with no way of closing because that's what we want we're going to close it dynamically by just not rendering it uh and we are going to use it in next 13's loading pages so that's why we don't need to create special closed actions for it because we are going to close it ourselves great so I I recommend you do this so you can actually see what you're developing so in the user box component just wrap everything in a fragment and just add the loading model which has no props great so now let's continue uh with uh this development right here and outside of your transition child go ahead and create a div and give this a class name of pix inset there's zero z-10 and overflow Dash Y dash Auto like that inside of that div create another one with a class name of flex Min Dash H dash full like this items Dash is Center justify Dash sender p-4 and text Center like that great uh and now what you can just write its dialog panel sorry dialog dot panel like this uh and inside you're gonna use the clip loader like that with a size of 40 and color of hashtag zero to eight or C7 and make sure it's a self-closing tag um like this and there we go you should see uh your little loader right here and great that's it for our loading model because this is exactly what we want to see uh so now you can go back into your user box right here and remember how we have this is loading but we don't use it anywhere so that's what we're going to use it for so now just go ahead and conditionally render this so inside user box right is loading and end and just render the model like this and now if you save it should go away but then you try and click for example on John for a brief second you should see uh the loading model like this and it should go away when it's loaded and redirected right here great uh and now let's pick some other places where we want this to show so I'm going to close everything and I'm going to go into my app folder I'm going to go into conversations and besides layout uh and page I'm also going to create a new component uh sorry new file called loading that the SX like this and it's just going to be uh called loading like that and it's going to return a loading model which you can import from dot dot slash components loading model like that and just save the file so we're not going to trigger this ourselves this is only going to be triggered uh by next 13 so you can see when I try and load the different messages I can see uh the loading model for a brief Second Great uh and I also want to add this exact thing uh to our users loading as well so make sure you go here and add clothing.tsx uh here as well so just write a quick loading function here like that and just return a loading model which you can input from DOTA slash components loading model you can copy and paste its exact same one great great job so now if you go into users you can see for a brief second we have this nice loading models now it's going to be even quicker in production uh and you can see when I select a new user it shows loading for every second so there are no doubt moments in our application uh great great job uh all that's left to do is to create uh real-time messages which is going to be quite simpler with Pusher and we have to create an active status and also some real time when it comes to adding new conversations or being added in a group chat we want that to show here in real time without as refreshing as well as deleting something we also want that to be reflected here immediately great great job so let's continue with our tutorial and let's create a pusher account and then we're going to use those environment variables to add some Pusher libraries and connect everything and make it real time so going to Google and write Pusher API or just push her and make sure you go to pusher.com leader in real time Technologies and go ahead um and create your account if you haven't already you can use GitHub you can use Google for my case I'm going to use Google and now you should be in this Pusher uh dashboard screen so just uh select channels and click get started right here so you can name your app uh whatever you want uh for the cluster I recommend leaving everything exactly as it is and you can go ahead and choose your Tech stack if you want uh so our front end is going to be react and our backend is going to be node.js but uh this is just optional I think it's gonna help with some code Snippets and just click create app like this uh great and now you have uh this example code right here but we didn't have to use that you can just go in the sidebar and Press app keys right here and there you go you should see all of your keys right here so what I want you to do is I want you to go into your dot environment file where you've written some code for cloud in every Google and GitHub right here and Below all of that I want you to create uh variables for Pusher so first one is going to be next underscore public underscore Pusher underscore app underscore key like this below that we're going to use Pusher underscore app underscore ID like this and below that we're going to use Pusher underscore secret like this great so now we can go ahead and copy your secret and paste it here you can go ahead and copy the app ID and paste it here and you can use the app key from the key variable right here like that perfect so now that we have that you can go ahead and go into the app folder so I'm going to close everything here I'm going to go into the app folder here I'm going to go into Libs and I'm going to create a new file called pusher.es like this right now inside uh first we're gonna install a couple of packages so go ahead and open your terminal here and I'm just going to expand this so you can see what we are installing so go ahead and write npm install pusher and Pusher Dash JS like this so just wait a couple of seconds for this to install great so now that it's back uh I'm gonna do import pusher server from Pusher so make sure you import push your server from Pusher and below that you're going to import Pusher client from Pusher Dash JS like this great and you can go ahead and run npn run Dev again in your project and just make sure you refresh your localhost if you haven't great and now let's go ahead and let's create some utils here so I'm gonna go ahead and write export const Pusher server is equal new Pusher server like this and go ahead and give it an app ID of process.environment dot Pusher underscore app underscore ID like this and for that you can actually go and compare to your environment so just make sure that you don't misspell it if you want to you can copy it from here so Pusher app ID and just paste it here so it's the correct thing and you can put an exclamation point at the end just to protect it against invalid types wait uh and then use the key which is the title process doc environment dot next underscore public underscore Pusher underscore T again you can put this at the end right here and just make sure that it's not misspelled so you can copy and paste uh for example yeah I misspelled it so you can just use it like this great and then below that for the secret you're gonna copy the secret and write process.environment that push your secret like this with an exclamation point at the end for the cluster you're going to use EU EU sorry and use the ls is going to be true like that perfect and you're also going to export const pusher lion which is a type of new pusher client like that and in the first argument you're going to use process.environment and you're going to use this next public uh Pusher app key again and just with exclamation point at the end and open an object for the second argument cluster EU as well great so now that you've done that uh we actually are gonna go ahead and use Pusher libraries to create some real-time Communication in our messages so just prepare uh your conversation any conversation you want right here because that's what we're gonna solve first I think that's the most important part we want to see we want to see real-time messages so let's go ahead and let's go into our API and I want you to select messages route.ds right here and I'm just going to expand this a little bit so we have more space here and in here I want you to import Pusher server from add slash app slash lips Pusher like this great and now that you have The Pusher server you're gonna go ahead um all the way to the bottom here after you after we Define this updated conversation and before we do this next Json response and what you're going to do is await pusher server.trigger conversation ID for the second argument you're going to pass in the Handler which we're sorry like the key which is going to trigger the update and that key in our case is going to be messages new like that and the message you're going to pass is new message like this so we have the conversation ID and we have the new message defined right here great so this is going to add the new message in real time and after that I want you to extract the last message from this conversation so const last message is going to be updated conversation dot messages updated conversation that messages that length minus one so this is how we get the last message great and now that we have this last message you're gonna go uh in your updated conversation remember we have not used it until now so that's why I did it here and we're going to use dot users.map user open a function like this and you're going to write Pusher server that trigger user.email and put a question mark sorry an exclamation point at the end and for the second argument you're going to use the key of conversation update like that and then open an object and just write ID conversation ID and messages is going to be last message like that great excellent job and now we have to assign so this is uh The Pusher on the server after this we have to do the same thing on the client which is going to respond to these messages so our client is going to expect this message dot new and it's going to get this new message object and it's going to assign it to this body element right here in real time and what this is going to serve for well what this is going to serve you will see a bit later so this conversation update is going to serve for this sidebar so we are also going to create a pusher client bind event to this conversation update in this sidebar right here and that's how we're going to append uh a new last message in real time without the need for the user to uh to refresh because if I send a new message here sure we will update it in real time here but we also want to update it here where it says John started the conversation so we want to get the newest message here and not only for John but also if you have a group chat we want to iterate or all of the users in the group chat and send and update the conversation for each and every one of them great so let's go ahead and do that now so let's go in our body component so I'm just going to expand this a little bit right here and I'm gonna go into my uh conversations conversation ID components into body.tsx right here great and beside this use effect that we already have I'm gonna add another use effect so use effect like this and this is the place uh where we're going to subscribe to our pusher and expect all kinds of events so I suggest that you also keep the messages route open right now so you can understand this better so first thing we have to do is we have to realize that the channel which we're sending this message a new key is called conversation ID so every user which is listening to this channel which in our case is the ID so the conversation ID is going to get that update so that's the first thing we have to do we have to use Pusher client which you can import from at slash app slips pusher and we have to write dot subscribe to conversation ID like that so let's immediately also put the conversation ID in the dependency array like this great so now the two uh will be connected great uh the next thing we're gonna do uh Every Time We join the application join a conversation what we have to do is we have to scroll all the way down to the latest message so that's what we're going to use this bottom ref4 so go ahead and do bottom ref question mark dot current question mark dot scroll into view like this great uh and now what we have to do is we have to bind our Pusher client uh to expect this key messages new so let's go ahead and let's do that so I'm gonna go and write pusher client that binds messages new like this and what I have to pass in as the second argument is a function which is going to respond to what happens so for now you can just write an empty function like this but we're going to create this Handler very soon great and important thing what you have to do is you have to unbind and unsubscribe every time you unmount otherwise that might cause an overflow so go ahead and write return so this is an unmount method uh with the use effect great and inside I want you to use Pusher client dot unsubscribe conversation ID and Pusher client that unbind messages new like this perfect great great job and now we can create this Handler right here so let's go ahead and let's replace this with a constant message Handler like this and also make sure in your unbind message new you also pass that message Handler here as well and now right here in still inside this use effect I'm gonna go ahead and write consp message Handler is an arrow function like this and the parameter is going to accept is message and the type of message is going to be pull message type we already have that imported because we use it in the initial messages here great and now what I'm going to do inside uh is first I'm going to install a package called Low Dash so go into your terminal we're going to use low Dash to simplify some comparisons here so go ahead and run mem install low Dash like this wait a couple of seconds for this to uh install and then go ahead and run npm install capital D at types slash low Dash like this okay so I'm just going to expand so you can see so empty install Dash D types low Dash like that and after that's been done you can go ahead and run npm run Dev great and when you run that just as always make sure you refresh uh your Local Host So you you're seeing things up to date great and now go back inside this message Handler where we are developing right here and what you're going to do is you're going to use if binds and go ahead and import find from low Dash so just make sure you import find from low Dash like that so if find open uh parenthesis right here my apologies is not like this so first thing we have to do is write set messages like this so we are finally going to use this set messages usually we just use the messages right here so set messages go ahead and use the current open an arrow function and now write an if find current open an object in the second argument ID is equal to message dot ID in that case return current like that otherwise return spread the current and add the new message so what exactly did we do here so this is a message Handler which is going to receive the new message from The Pusher first thing we're going to do we're going to enter our set messages right here and we are going to uh get access to the current list of messages here and then we're going to compare the current list of messages to this special query which is going to search if there is any message in our current array which already has an ID of this new message that is coming in so we just want to ensure that we don't accidentally make duplicate messages when doing this function great so now uh you can go ahead and save this like that and also inside this message Handler right here I want you to do two more things so I want you to repeat this bottom ref.current dot scroll into view like this and I also want you to repeat this axis post conversations scene so go ahead and copy that and we're going to do that immediately once we receive a new message so when we receive a new message we're gonna alert everyone that we have seen that message great so you can go ahead and save this now I'm going to expand this view I'm going to refresh right here great I'm also going to have my terminal opened just in case we catch any errors and I'm going to write a test message right here and if we did this correctly in a couple of seconds we should see the message right here and there we go you can see that my message has appeared without me refreshing amazing amazing job we can go ahead and try another message so a couple of seconds is going to pass because we need to create the message but then it happens immediately without us refreshing great and you can see that right here we are still using the old started the conversation so we're gonna have to fix that as well but great this was the hard part about uh the body element great great job you can go ahead and try and open two chat applications and try and communicate between one another and you will see that you receive messages instantly so before we do the conversation thing one thing I want to enable is I want to enable real-time updating of the scene status of our message so in order to do that I want you to go inside scene route so your scene route should be located inside app API conversations conversation ID scene folder route.ps right here and I want you to go right here where you have your updated message here and I want you to write a wait Pusher server which you can import from add slash Libs Pusher so just make sure you imported that like here at the top and then just write dot trigger current user dot email and the key you're going to use is conversation update like this and the object which you're going to pass to there is ID conversation ID and messages updated message like this great so we still don't have this conversation update but we are just preparing it for the future and now what I'm going to do is I'm going to check if we already seen this message or not so perhaps we might be the sender of this message but we still triggered this scene route so let's go ahead and write if last message dot scene IDs dot index of current user.id is not equal to one return nextresponse dot Json conversation like that great uh sorry not equal to one but equal to -1 so make sure you don't accidentally put one like I did it's equal to -1 like this great and if this isn't the case so if we did not see the last message that means that we are not in the array scene if you remember that each message has that means that we can go ahead and alert every new user that we have seen that message so go ahead and write a wait Pusher server dot trigger conversation ID like this and you can put an exclamation point here so so the types are okay the key is going to be message update like that and the third argument is going to be updated message like that great and you can just go ahead and save this as well perfect and now that you have that I'm going to go back into my body element right here and we're going to subscribe to another bind right here so go ahead and write pusherclient dot bind message update like that and the Handler is going to be update message Handler like this and for now all you can do just const update message Handler just write an empty function like this and then make sure you also write the unbind for that so go ahead and write Pusher client that unbind message update update message Handler like this perfect so in order to update the message in real time and what exactly do we update real time in a message well we update its scene array so when I'm in a group chat I want to see real-time updates if someone logged in has seen my message so I want that to appear below this message right here so we have to do is we have to get the new message which is a type of full message type go inside I'm just going to expand this so you can see everything I'm writing go inside of here and write set messages current dot map print message like this and open an object sorry a function and now you're going to check if current message.id is equal to new message.ib in that case return new message like this so if we find the exact message we are looking at go ahead and update it or replace it with the new message otherwise you can just return whatever is in the for Loop which we are using which is exactly the same as map Great oh sorry no it's not exactly the same as map but in our case we're using map as a four iteration here great great job and now if you actually try uh well you're not gonna see much right now because I did not open a second video here so I'm just going to prepare that I'm going to open two windows and we're going to try and communicate with one each other great so I've prepared it right here so here I am logged in uh as new and here I'm logged in as Mark and we're going to try and communicate with each other so I'm going to say hello uh Mark like this we're gonna wait a couple of seconds and the messages should appear as long as they're created so there we go I got this hello Mark and you can see how in real time I got this update seen by Mark so I will just zoom this in so it's more visible for you and now here I'm gonna say hello new like that uh let's just wait a second for this to be sent and there we go we got hello new in a couple of seconds here I can see that it's been seen by new amazing so that's what uh that our two functions did the update message sorry the message update and message in your did so now we have to do uh the same thing but for the conversation sidebar great so let's do the conversation thing now so what I want you to do is I want you to go into your API folder so I'm just going to expand everything just a little bit so we can see better all right go into your API folder go into conversations route.s so it's going to be this file where we create our group chats and our individual conversations here great so first I want you to solve the group thing so go into the ifs if is group Clause right here uh and just before we send the new conversation I want you to write in your conversation not users dot for each user we're going to check if there is a user email so if user.email like this go ahead and write pusher server.trigger and make sure you import Pusher server from add slash lib switcher like this so just make sure you have this imported right here great booster server.trigger user dot email conversation new and go ahead and send new conversation like this so again the channel which we are subscribing to is the user's individual email because it's Unique and because we have it in the session which we're going to use in the client the key we are sending is conversation new and the client is going to be listening to this key on this channel and it's going to update our sidebar of conversations right here with that new conversation that's just been created great before we test this we have to do the same thing for individual a one-on-one conversation so just go ahead all the way down and here before we send the new conversation do the same thing so new conversation Dot users.map user go ahead and write if user user dot email like this pusher server.trigger user dot email conversation new and new conversation as a third argument great great job and now we have to go ahead and subscribe to our email on the front end and listened or bind to this key on the front end as well and create a Handler which is going to append this new conversation inside of our list so let's go in our conversationalist component so it's going to be located in conversations and in components conversationalist right here great and now that we have that first let's create The Pusher key so go ahead and create a constant called kosher key which is a used memo add the dependency array and just write the return session and make sure you add the session so cons session is equal use session you can import the session uh from next dash out slash reactor make sure you import that and then when you have the session you can return session dot data question mark dot user and question mark dot email like this and go ahead and put that in the dependency array as well great so we have this Pusher key so we don't have to repeat this a long line uh every single time right now let's create a use effect which you can import from react as well so just of course make sure this user pack has been imported here great first let's check if we have The Pusher key so if there is no Pusher key meaning that the session has not loaded yet you can just return and break this use effect we don't need it uh otherwise we can use kosher client which you can import from add slash app Labs Pusher so just make sure you do that here great and right dot subscribe to Pusher key and our Pusher key is going to be our email why our email well because in our conversations that's where we are going to trigger an update for each user's conversation list so go back into conversation list or if you've stayed here great and the first thing we're going to do is we're going to bind so Pusher client dot bind conversation new like this and it's going to use a new Handler like that so just here create a const new Handler which is just going to be an arrow function for now like this great and make sure you use the Pusher key inside of this dependency array and of course in return function or the unmount function you have to unsubscribe uh and unmount so go ahead and just run with your client that unsubscribe oh sure key like that and Pusher client that unbind conversation new new Handler like this perfect and now we have to actually append uh our new conversation to the list of items that we have right here great so let's go ahead and write that so conversation is going to be a type of full conversation type uh we already have this imported right here great and what we're going to do is we're going to call set items which we have from this state right here we're going to go through the current and first we're going to compare if there is an existing conversation that we are trying to add just to ensure that there are no duplicates so if find which you can import from low Dash right here open parenthesis make sure you don't accidentally close the if close so if there is uh uh so we're going to search for the current array and we're going to find an item with an ID of conversation dot ID like that great so if that exists go ahead and return current like this and I'm just gonna see what is the error here I think I removed my imports so just make sure you import it find yeah so there is something wrong here just make sure you import it find from law Dash like this and there should be no error for you great uh so if there is a current conversation then do nothing with the array otherwise we're going to modify the array by spreading Sorry by putting the conversation first and then spreading the current like this great great job so now that we have that we can actually go ahead uh and a try so what I'm going to do here I'm going to remove this conversation with Mark for example so I don't have one make sure you do that uh great and what I suggest you do is just wait a couple of seconds uh or yeah or you can just manually refresh conversations like this so make sure that Mark is removed like this and now I'm gonna go ahead and try in this other browser that I have where I'm logged in as Mark I'm going to go ahead and try and create a new conversation right here so just wait a couple of seconds I click new here and in a couple of seconds there you go you can see in real time it added a new conversation that we have without refreshing this page which is exactly what we wanted great great job great and now let's create a Handler which is going to update our conversation sidebar but not by adding a new conversation but by editing the last sent message because now for example if I say hey this is the last send message for example sure our Pusher does work here in the body and in a couple of seconds it's going to appear here but you can see that our message here is still an old one same as here so let's go ahead and fix that so we already have everything ready on the server and you can search that by conversation update and where we've written it so we've written to update the conversation every time we seen a message so it's no longer be it won't be bold and every time we create a new message we also send an update to every single user in that conversation we send an update to their Channel email with a conversation update so just make sure you don't actually accidentally misspell this conversation update or conversation new or message new or message update like that great so we actually have everything ready on the server and we can go back into our conversation list right here and alongside the new Handler we're also gonna bind another a key here so pusherclient dot bind conversation update like that and it's going to be called update Handler like this great so just go ahead and write const update Handler is going to be accept a conversation which is a type of full conversation type like that it is an arrow function so just open it like this and all you want to do is write set items uh sorry uh my apologies so just write set items yeah get the current immediately return current dot map get the current conversation and open a function like this so I'm just going to expand so you can see whoops like this and inside let's do a comparison to find uh the one we want to update so if current conversation dot ID is equal to conversation dot ID so this is the conversation the new conversation that came from The Pusher and this is the one from the current list from our current array go ahead and write return spread the current conversation and just write messages conversation dot messages like that because that's what we actually want to update and outside of this if Clause just return current conversation like that great and make sure you also unbind this in the uh unsubscribe so pusherclient.unbind conversation update update Handler like this and while you're developing this always just double check that you didn't actually misspell any of these Keys both on the server and on the client otherwise you might not be getting the results that you want great now that we have this I'm going to refresh both of my pages here and we're gonna try uh and we're gonna send a new message to see uh if we can actually update our sidebar in real time now great so we have uh this message right here but we are the ones who send this if I'm correct and it's going to update in a second when the session loads great and we have it here now let's go ahead and let's try and I'm just going to try and open this now uh and in a couple of seconds there you go you see how it went from Bold to clear that's because we triggered the scene route and our scene route triggers the conversation update and gave us a new conversation with the list of new people who have seen uh this message great so let's go ahead and let's try and send hey let's try start with something else update for example I'm gonna go back here let's see if I'm gonna receive it in real time without refreshing so in a couple of seconds I got update and there we go I got update right here as well in a couple of seconds it also went from unread to read because every time we receive a new message we called the axios scene post great great job so one more thing we want to do with these conversations is we want to remove them from our list in case it's been deleted because right now that does not happen until we refresh so that's the last thing we have to do with the conversations real time so let's go and I'm just going to close everything going to app API conversations conversation ID not inside scene folder but right here great and what I'm going to do I'm going to find this deleted conversation right here and I'm going to use the existing conversation so remember we have this existing conversation here I briefly explained why I did this why did I just not come up with deleted conversation well this is why because we need a list of users before we delete the conversation so I'm going to use this existing conversation inside and I'm going to run dot users dot for each user right here if user.email I'm going to call Pusher server which you can import from ad-libs Pusher like this just make sure you've imported it great push your server dot trigger user dot email the second argument is going to be the key conversation remove so we had conversation new conversation update and now we have conversation removed just make sure you don't misspell anything and the last argument is going to be existing conversation like this perfect uh and now that you have that uh you can go ahead and go back into your conversation list component where you added the new and update and yeah you can already guess the drill so Pusher client dot bind conversation remove remove Handler like this let's just write this Handler so remove Handler is going to be a simple arrow function like this and make sure you do the same thing in the unmount so Pusher client that unbind conversation remove remove Handler like this and inside in the parameter you're gonna get the conversation which came from The Pusher which is going to be a type of full conversation type like this and all you're going to do is write set items get the current open the function and return current but you're getting the filter a single conversation and compare if conversation.id is equal to is not equal to conversation dot ID which we have from Pusher right here so basically we're gonna go over our current list of conversations and we're going to filter out sorry we're only going to leave those in which are not equal uh in the uh of the ID which we received from Pusher great so now that we have this I'm just gonna expand it here and make sure you refresh before you try this great so I have these two examples right here I can zoom in a bit here as well great so let's just wait a second uh until my loading finishes there we go it's finished here it's finished here and I'm gonna go ahead and delete this so I'm going to open my drawer I'm gonna click delete delete and I'm gonna wait here and see if it's going to be removed in real time let's just give it a couple of seconds and there we go it has been removed uh great great job so obviously what we also want to do is we want to redirect the user If he if the user has the conversation open here so I'm just gonna go ahead and add that functionality as well in the remove Handler so to do that all you have to do is go back into your remove Handler right here uh and what you want to do is just write if conversation ID is equal to conversation dot ID router dot push slash conversations like this great and make sure you also add the conversation ID to the list of arrays and also router as well great so now if we get our conversation removed while we while it's open for us it's going to redirect us back to conversations uh like this great so I'm just going ahead and prepare this to see if this didn't create any additional bugs and if it works as intended alright so I have it prepared right here I send a couple of messages I didn't change any code and now I'm gonna go ahead and I'm going to delete this conversation and I'm going to wait here to see if our code works as expected and it does so we noticed that the conversation was correct and it redirected us back to slash conversations here and we can go ahead and immediately try and create a conversation back with that user to see if it's gonna create it again so I click on new here and let's just wait a couple of seconds and there we go it's back here in real time and you can even test and send a message so hello real time in a couple of seconds it's going to appear uh right here it's going to update here and it's here in real time I'm going to answer right here and in a couple of seconds I'm going to get an answer right here and this is going to change to scene great amazing amazing job all that's left to do here uh is to add a functionality to this active status right here so first thing that we have to do here is we have to create a presence Channel where we are going to search for active users in order to know whether we assigned an active status or an offline status so I'm going to expand my code a little bit and for this we're going to have to use our Pages folder because The Pusher does not support the new next 13 yet but don't worry uh Pages folder is going to be supported for a long time it's completely normal and it's actually encouraged to mix and match the two while we are in this migration process so go ahead and create a new folder called pages and we're just going to use it for our API folder and we're going to create a single route called out.ds inside like this uh sorry not not like this so please remove this file inside the app folder create a new folder called Pusher so it's a bit more correct and inside Pusher create a new file out.thes my apologies so just like this great and what you want to do is import next API request next API response from next like this then you're going to import get server session from next out then I'm going to import Pusher server from add apples Pusher and you're going to import out options from ad app API out find your next out route so we already did this in get session if you remember and you can just copy it from there at least this part if you are getting confused by it so this is targeting our special folder of next out basically you just need the auth options great and now just write export default async function Handler first argument is going to be request of next API request second one is going to be response of next API response like this now we're going to write out our session so come to the session is equal await get the server session first argument is a request second is response and last one is out options like this great now let's check if we are authorized or not so if there is no session user email in that case return response dot status 401 like this now I'm going to Define my sockets uh which uh I will explain later how we are going to get so cons socket ID is going to be request.body.socket underscore ID pause the channel it's going to be request dot body dot channel name like this and cons data which we are going to send is going to be user underscore ID session.user.email like this great and in the end just write const out response is equal to Pusher server dot authorize Channel socket ID as the first argument Channel as the second and data as the third argument and in the end just run return response dot send out response like this great so now we have this Handler function right here which is basically our slash API slash Pusher slash auth route so where are we going to put that and how do I know about these fields right here so it's very simple we're going to go back into our app folder into our Libs into pusher.ds right here and we're going to expand our Pusher client a bit so besides this cluster right here we're also going to add something else in this object and that's going to be called Channel authorization and in here we're going to add an endpoint to slash API slash Pusher slash out like this and transport is going to be a type of Ajax like this great so just to confirm that you did this correctly you can open your uh console and if you're getting any errors for that route uh you should get an error right so if you're not getting any errors everything should be fine uh if you're getting a an error for this API Pusher out you will see it uh right here in the console great so what I'm going to create now I'm going to create a global store for our active users in the presence Channel great so I'm going to expand this again and I'm gonna go back into my app folder I'm gonna go into Hooks and I'm gonna create a new file called use sorry let me just focus so use activelist.es like this and we're going to use a hook called sorry a package called to stand so just make sure we import that as well so npm install to stand like this and after it's been installed you can npm run Dev again but just to refresh your page wait so I'm going to go and write this store so import create from to stand like this you begin to write an interface so interface active list store it's going to be members which is an array of a string add is going to be a function which accepts an ID which is a string and it's an empty void and I'm just going to copy this a couple of times we're also going to have a remove and we're also going to have set except the last one is not going to be just single ID it's going to be multiple IDs and it's going to be an array of strings like the initial members great and now I'm going to write const use active list is equal to create from to stand which we already imported open pointy brackets and give it a type of active list store like that and now I'm going to Open brackets here and I'm going to open a function like this the argument inside here is going to be set and instead of just an empty a plane old or a function like this I'm going to open parenthesis and then write an object inside so it returns an immediate object the first argument is going to be members and it's going to be an empty array add function is going to function in a way that I give an ID and then I call the set function I'm going to use the current state I'm going to open an object again and I'm going to write members and I'm going to spread the current state DOT members and I'm going to give it the ID like this great now for the remove function I'm going to get an ID I'm going to call the set again I'm going to get the current state and again open object immediately and we assign the members and in here I'm going to write the state DOT members dot filter member ID go ahead and immediately just compare the member ID is not equal to ID like this great so remove close the set and it opens an immediate object where we modify the members we call state.members.filter hit guess the member ID and it just compares the member ID from that array to make sure it filtered it it's filtered out depending on what the user sent and wants to filter out great and the last one we need is set and that's a simple one so IDs set numbers IDs like this great and make sure you write export people to use active list like this perfect what we have to do now is we have to create a component called active status so let's go into our components and create a new file called active status.psx like this now make sure your Market is used client like this and just write consp active status is equal to an arrow function like this return null and X for default active status like this and we're going to add a hook here uh just as soon as we create it great so now uh what I want you to do is go into your main layout file right here where we add the out context and those are context uh and I just want you to use that component here so active status like this and make sure you import active status from dot slash components active status like this great and now you can go back into this active status here and we're actually gonna go ahead and we're gonna create uh we're gonna quickly create another hook called use active channel so go back into hooks before you do that and create a hook called use active Channel dot DS like this great and I'm just going to make it a very simple one so it comes to use active Channel just like this and Export default use active Channel like this great and now we can go back into active status and you can just import it and execute it so use active Channel like this great make sure you import it from dotto slash hooks uh use active channel right and now we can actually write some stuff inside here so first things first uh what I want to do inside is I want to destruct uh the set add and remove actions from our two-stand store so cons use active list and what we can destructure inside is set add and remove like this great then I'm going to write a state state here active Channel set active Channel like this and we're going to use state and give it a value of either a channel which you can import from Pusher Dash JS like this or now like this and make sure you also import your state great and just make sure it's null by default like that great and now we're going to create a use effect function which is going to listen to all the people joining uh this present Channel or leaving the presence channel uh and we're gonna move them to the global uh active list great so use effect from react like this and let's first get the active channel so let channel is equal active Channel like this now we're going to check if the channel does not exist so if there is no Channel is going to be equal to butcher client which you can import from DOTA slash Libs pusher so push your client dot subscribe and our presence channel has to be named presence and then something so make sure you name this presence otherwise it's not going to be recognized as a presence channel so presence Dash messenger in my case I recommend you do the same thing and then set active channel is going to be the channel like this great and now that we have that I want to go ahead and write a couple of bind functions to this channel so Channel dot bind pusher subscription succeeded like this and for that we get members which you can get the type members from pusher.js like this great and what happens with those members well first let's Define the initial members so const initial numbers it's a type of array of strings and it's an empty array and now what we're going to do is we're going to iterate over these members and just push their emails great so remember members dot each now you might be wondering what is h why not for each why not map because members is a special type for it's a special class from Pusher so don't treat it like a normal array you have to use dot each get the member which is a type of record string any and what you want to do is just write initial members dot push member dot ID great and then you want to call the set function and just write initial members great so what is member dot ID how do we get that what is that what exactly do we save the member as well if you go back uh into the page folder which you just created you can see that we mapped the user ID as the current user email so practically we are working with user emails and we have this presence messenger Channel which only works when we create this authentication so that's why we had to create that authentication here otherwise it won't work and basically on on a special event that Pusher describes in their documentation called subscription succeeded we're going to Define our initial members so when we ourselves subscribe to this presence Channel we're going to list of all active members and we're going to set them in our Global store so then we're going to use that Global store later on to compare who's active and who is not and this is just the initial uh bind event where we load all the active users which might have been even logged in before us great and now we're going to create a couple of binds for when users get removed or when users get added so Channel dot bind pusher member underscore added he's gonna get a member which is Attack of record bring any like this open an arrow function like this and only want to write is ADD member dot ID like this and you have the ad from the use active list great and what you also want to write is remove so Channel dot bind Pusher number removed get the member which is a type of record string any and what you want to write is remove member dot ID like this great and in our return function we have to unsubscribe so if there is an active Channel uh Pusher client that unsubscribe presence messenger like this and set active channel to null like that and in our dependency array we're going to use active Channel set add and remove like this great so we have this very useful hook which we use in the active status component and we use the active status component in our whoops um in our Global layout so make sure you put it in the most root layout of the app folder right here great and now what we have to do is we have to actually use that Global list to change this active status and this little message right here as well as in this drawer right here and we are officially done with the development so first let's use it in our Avatar component where we have this Green Dot so I'm gonna go and find my avatar component and I'm gonna get the members from the use active list to stand hook so I'm gonna write const use active not Channel but use active list like this which you can import from dot dot slash hooks use active list and just export members from it like this great and now I'm gonna write post is active it's going to be members.index of user question mark email is not equal to -1 like this so basically we are confirming that this user email is in the list of members and just put an exclamation point at the end for the typescript error to go away and now that we have this is active right here remember this span that we wrote where now we're gonna make it uh Dynamic so you can just go ahead and write these active and end and just wrap this entire span here so now it's only going to show uh if the user is in the list of active users great so I'm going to expand this and now all of my users have gone away but I recommend you refresh this just to confirm if this is either an error or if uh something else is at play here so just make sure you refresh and then wait a couple of seconds maybe even refresh a few times before you confirm so you can see there we go it works as intended so you can see that I am active so my bottom uh corner is active here and Mark is also active so let's go ahead and let's try and close this and there we go Mark is no longer active in the Avatar great that is exactly what we wanted so our Pusher subscription Works our crucial presence Channel works exactly as we expected and now we have to do the same thing but in the header so we don't want to display active if they are not active so let's go ahead and do that I'm gonna go into my header component I'm just going to expand everything here I'm going to zoom in a bit for you okay uh so we're gonna do the exact same thing here so I'm gonna use the uh active list right here so const use active list like this and I'm going to extract members from it like this make sure you execute the hook and make sure you've imported it from add app hooks use active list well basically the same thing you did in the Avatar and now here I'm going to write const is active and the same thing members dot index off other user so make sure you use other user dot email and put an exclamation point at the end just to fix the type is not equal to -1 like this and now you can use this is active to dynamically change either active or offline so is active active otherwise offline like this and make sure you put is active into the list of dependency arrays as well great and now you can see how it displays offline great and one more place where we have to fix this whoops uh is the uh profile drawer right here so let's go uh there as well I'm gonna go into my profile drawer all right I'm gonna go all the way to the top and I'm gonna do the same thing so const use active list from uh you can import that well the same thing add app hooks use active list right here great make sure you export members like this so get the members and the same thing in the status text uh sorry before yeah you have to define the cost is active so members dot index of other user question mark dot email and just put uh or you don't have to put but you can put this uh exclamation point if you're getting typescript errors uh is not equal to -1 like this and then you can use that is active to display active otherwise uh display offline like this and don't forget to put the is active into the dependency array of our status text right here and there we go it's offline here as well so what I'm gonna do now I'm gonna play around with some online and offline users to see how this is working all right so there we go you can see that I have two accounts here you can see that Mark is active but John is offline same for me here I can click uh on new here for example and it's gonna bring me to the conversation uh that I'm looking here as well you can see that it says active here active here uh drawer the same thing and for example I'm going to log out from here and there we go you can see that Mark just turned offline and I'm offline right here but if I go back so yes the name is marked but my email is Antonio and if I go back inside you can see that that will be added back to the online list perhaps it won't work immediately sometimes it does take a refresh but most of the time The Pusher works great uh in production so if it gets out of sync you can just try refreshing one of the browsers and there we go you can see I didn't have to refer this one but sometimes when logging in logging out Pusher gets out of sync but overall the active status works very well especially in production that I've tested and this is the proper way to do active statuses nevertheless that's it you created an amazing chat application uh you have active Services you have group chats you have images you have settings you have drawers there's a bunch of stuff that you made here excellent excellent job I'm now going to show you how you can display this Universal and that's going to be it for this video so now what we have to do is we have to deploy this to versal so go ahead and open your terminal right here and what I'm going to do I'm going to shut down the application and I'm going to add everything that I've changed I'm going to commit this like this great and now I'm going to go into GitHub if you have not created maybe you already have the repository but I'm going to show you so I'm going to create my messenger video like this I'm going to set it to public for now and I'm going to create the repository like this uh and I'm going to choose this option because it's an existing repository so you can just copy this entire thing paste it here and just press enter like that and when you refresh here there you go you have the repository and then I want you to go into versal.com and click add new project right here and you should have your new repository so I have my messenger video already here I'm going to click import and then in your project go into your environment right here go ahead and you can just copy everything inside and you can click on the environment variables here you can select the first input and just press paste and everything will be transferred here and just click deploy and now I'm going to wait a couple of seconds or maybe minutes and I'm just going to skip to when this is done all right so I got an error during my deployment and perhaps you've gotten it as well uh it's a Prisma client initialization error Prisma has detected the project has been Universal blah blah blah this happens in the new versions of Prisma and it's an easy fix to do all you have to do is go into your project going to package.json right here and in your scripts object go ahead and add another script called post install and what you want to run here is Prisma generate like this and then go into your project right again in terminal and just write git add to get commit fix and get a push again great and now that you've pushed and since you already have this uh the deployment is going to automatically start so there we go I have my messenger video here and you can see that I have this uh deployment building by itself so great I'm just gonna wait a couple of seconds and see if this one is going to succeed if you want to watch the progress of this you can go into deployments right here and you will see this one was the first that got the Prisma error and this is the one that's building right now so let's see if maybe we will have another error or if the uh will will be successful so you can watch that here and there we go after I added the post install script um the uh website successfully uh was assigned and is successfully deployed I'm going to visit it right here uh and there we go but one thing that's not gonna work is our Google and GitHub login you see we have uh an error here so what we have to do is you have to copy uh your url that was just created and first let's fix GitHub so go back into your settings right here uh go to developer settings go into oauth Apps and find your messenger video whatever you used for your project right here and just change your homepage URL to the new URL and authorization to the very same URL and just update your application great and for Google go back into your project go into API and services right here and then you want to go here into credentials and select your web client 1 or if you named it something else I left it as default and what you have to do here is change this localhost with that just make sure you don't accidentally put double slash here so I'm going to zoom in so you can see so don't accidentally put this double slash here make sure you remove one so it's just your url slash API I'll call back Google and you can also add the authorized JavaScript Origins like that but remove the last slash like that and press save like this and now that that is updated you can go back to your messenger clone you can refresh and try Google again for example and there we go uh it works as expected uh great great job so I'm gonna try I'm gonna log in here it is the same database as my local project right here you can see I'm logged in and there we go you can see how app is much much faster in production I'm gonna try and send a new message here and there we go you can see the app is blazing fast in production and I'm just going to refresh so Pusher uh active status gets here and there we go now it's fixed sometimes Pusher gets a bit unsynchronized and you can see that even delete functionality uh is much much faster perfect amazing amazing job uh thank you so much for watching this video uh remember to leave a like share and subscribe if you liked it and see you in the next one
Info
Channel: Code With Antonio
Views: 551,634
Rating: undefined out of 5
Keywords:
Id: PGPGcKBpAk8
Channel Id: undefined
Length: 529min 14sec (31754 seconds)
Published: Sat May 06 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.