Real Time Chat App with React and Node.js | JWT, Socket.io, MongoDB | Beginner Friendly Full Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome to the course today we're building a full stack realtime chat app that has iOS notification sound built into it just like this one not only does it have realtime messages but also realtime online status next to each user we will build this beautiful looking glass morphism effect with Tailwind CSS and daui but it's not only that we will build a complete authentication system with Json web tokens and we will use middle wees for authorization our API will handle every single error and return an appropriate error message which we can grab and display in our user interface we will separate every single service into its own folder and this way we will have a super clean codebase that is organized and modularized you will be able to see these different folders and their usages in a mer stack app for the database we'll be using mongodb and we will learn how to build models how to add relationships between them and most importantly we will learn how to design models for this chat app for the front end we'll be using react and we will create custom hooks for each operation such as sign up login log out send message and much more and these custom hooks not only will make our code base look super clean but also will make our code reusable and maintainable we will learn two different State Management Solutions which are react context and zand and the most exciting part will be the end which is Sako this Library will allow our application to have this realtime communication and you will see how easy it is to integrate a pych server into your Express server after this app you should be able to build a chat app from scratch by yourself and after we successfully built our application we will learn how to deploy it for free and this deployment process will be applicable to all of your other M stch projects this might be my most beginner friendly course the only prerequisites are are a basic understanding of JavaScript and react such as hooks components and props so that's going to be it for this demo and just before we get started I am trying to achieve something this year if you think this content is cool consider subscribing and liking this video thanks for watching and let's get started okay so as always I have created an empty folder on my desktop and then I just open it up in vs code now we need two different folders one is for our front end and the other one is for the back end now let's start with the FR end and then we'll just focus on the back end so let's open up a new terminal and then CD into the front end now we will say mpm create V at latest now this will give us a react application and we'll click the add dot at the end that will indicate um install this react application under the front end folder and this means the current folder which is this one right so if we press that it's going to ask us some questions uh we would like to go with react and JavaScript now under the fronted folder we have this folders and files now it says run mpm install and we could do mpm install or I for short um let's just run this that's going to give us the not modules folder which is our packages that we need or the dependencies so this is going to take a bit time and now it's been installed let's type mpm runev as they say just above so this will spin up a server for us at this URL let's control click to it and now it has been opened in our browser so this is the react application that we have now later in the course we're going to add uh tailin CSS and D UI but uh for now let's just uh terminate this process and focus on the back end and then later in the course we'll just focus on the so I will kill this terminal and just shrink this now for the back end you might think that we're going to open up a new terminal and just CD into the back end and do something like mpm in it Das y but this is not what we'll be doing instead we're going to go into the root okay so not in the back end not in the front end but in the root and the reason is we'll doing we are doing this just because for deployment so that we could have a better developer experience and it'll just be easier for us to run both the back end and front end from the route so type mpm init Dy um that will give us a package.json file and here we can see let's change this main entry point to be server.js and we're going to create that file under the back end now we would like to create an Express server so if we do something like con require uh okay I'm sorry that should be cost Express require the express uh currently this is not going to work we need to install that package and in fact we're going to need uh multiple packages so let's install all of them at once and when we use them I will explain every single one of them um let's install all of them now so that we don't waste any time so mpm install uh Express let's say EMV um so cookie parser then we're going to need the bcrypt JS and then mongus psyched and then Json web token and I think that's going to be it now we'll be using Express to initialize a Express server we'll be using DMV to be able to read environment VAR variables under this EMV file and quickie parser as the name suggest to pars the cookies then to be able to Hash passwords we'll be using this package to be able to connect our database and just interact with it uh we'll be using Mangus then let me just take it like this so we'll be using psycho to be able to have that realtime communication and then Json web tokens um Json web token package to be able to create those tokens and install them under the root I will press enter that's going to override the packages file so let's wait for this now okay so installation has been completed now and let's just try to create an Express server so I'll say const app and just call the Express uh function and then we could say app. listen and we could listen this port and we'll just say console log that the server is running on this port now let's save this file and we would like to run this file so inside the package ag. Json we are going to create another script let's just delete this and let's say something like server and to be able to run this we'll say no and then we're going to go into the back end right because our server.js file is under this folder so we could save this now and let's run this I will clear up my terminal and in root I will say mpm run server and and if that works it is going to print out it this server running on Port 5000 and in fact it is it is working now let's just create a test route so app. get um so when we go into the homepage of this route or the Home Route that we call Root route okay this is the root route which is HTTP Local Host 5,000 and just this direct route this is called as rotra we could say something like res us and server is ready or maybe hello world let's save and in our browser if we now visit we cannot see anything let's go 5,000 we cannot see anything and the reason is whenever we update this file we need to terminate this process and then just type it again or run this again now if you visit then you'll see we see the hello world text and it is really annoying to just uh whenever we do some changes you just scale this and then open up again and for this we have um a package so let's just say CLS we could install that package which is nman and we could say D- save Dev so this will indicate this is a de dependency so let's install that now installation has been completed if we take a look at here we have this Dev dependency called notman and we can fix this by saying maybe uh nman if we go now here in the server.js say mpm run server now this will run the server but with the not man script so or the notm package now let's wait for this so it is going to run it and this is the server that we have now whenever we do some change let's say hello world with double exclamation point now it is going to restart this automatically and if we refresh now we see this update we didn't need to uh terminate this process and then open up again okay now that we have a server that is up and running on this port let's just try to expand this now the first thing that we' like to fix is this port number we don't really put this as a hardcoded value but instead we just create a variable for this let's uppercase port and we're going to get this from the process. EMV port or it's going to be this value now what is this value is coming from will be aemv file that is in the root so EMV and if you cannot get this highlighting then I have this extension called DMV that you need to install and once you install this now you can you can get this highlighting and I'll give this port value to be this 8,000 and I'll save this file now we say the port value should be either that Port value under this file or it's going to be 5,000 now if you save this now this is not going to work let's just put Port here and then update this Ser we running on this port and I'll just put back Texs and use this variable but this is not good going to work and the reason is so it didn't get the uh 8,000 right it's it see that this is undefined now we're using this value and the reason is by default you cannot get this EMV variables and we call this as environment variables and for this we installed this package called EMV now we will say import that con. EMV from EMV and then we're going to call a function so EMV doc config okay just call this now we able to use that value that is coming from that file and I don't really want to use this require but instead I want to do something like oops okay I'll just do contrl Z so instead of this I would like to use import Express from Express and to be able to do it we need to go into the package Json maybe under the scripts we will get this type and and by default it is commonjs but we'll like to make it module now if we save we're going to get some errors because we're using require so let's um change them with import so I will delete this and I'll say import EMV from EMV now this should fix it the error in our console now let's add some routes for our authentication uh we could do something like app.get uh um when we get to let's say API oath and sign up we could run this controller uh maybe we'll just say console.log sign up route and then we could do something like app. get API off login and we'll say login route and then we could have something like log out but now imagine if we have so we're going to have all of these authentication routes and then we have this much of user routes and this file will look really ugly because we're going to have different things it is not going to be only routes and the solution that Express gives us that we can use the middleware for this so I will delete all of them but instead we'll do something like app.use that's how we use middlewares um so SL API SL oath and whenever we visit that something starts with with this route we're going to call our oath routes and now let's create this we don't have it inside the back end we're going to create routes folder and then oath. routes.js now this is not really required that could be something like OJs but just to to know this file is about um this is a route file I'll I will just put it and this is some convention that we do in nodejs so I will uh accept this create this file now we will import the express from Express and then we're going to create a router so express. router and this R should be uppercased and let's say export default this and now we'll just say if router do getet if it is a get method to let's say login then run this controller or this call back function rest. send login rout so now what is going on here I'll just put them side by side if we visit app.use I I mean sorry if we visit SL apiou SL login then this function will run and to be able to make this work we need to inut import this um let's get it import oath routes from this file that we have and you need to put this. JS at the end otherwise it is not going to work because we are using this import syntax so now I will just save this and let's test it out if you visit API o/ login we're going to get this response let's go SL API SL oath slash login yeah was it login okay let's see I think we have some problems okay API out and login if it is a get request then it should give us oh okay I think our Rod is 8,000 that's the problem okay and let's just fix that um under the MV file I want to have this rout to be 5,000 okay so let's visit 5,000 SL API of login that's going to give us this login route and now our code is a lot more organized as it before now we only have this route whenever we go into this oath route we're going to call our routes now here we could have different routes one for login one for sign up and one for the log out let's up upate them one by one so sign up log in and then log out and again we could even organize this more by removing this functions from here and just put them in their own files because now imagine this function is about let's say 25 lines and then this function is about maybe 50 lines and this one as well so this file look see and instead we can use controllers so I'll just delete all these okay so let's just create controllers for them I will delete this delete this and this functions now let's save this file we're going to go into the backend again controllers and we're going to have oath. controller.js and again this is just optional that I would like to put because it's a convention that we generally do so uh create this now we can put our controllers so I'll say export con login uh maybe yeah login user and then just console log something like login user and we'll do for sign up so export con um maybe a log out user and then we can do the sign up now here we don't really want to put the user um so I'll just delete that in all of them and let's put the sign up at the top and then log in and then log out and we'll be adding all those Logics one by one so let's first install I mean import that functions so it is sign up but from o controllers but we need to add DJs at the end and then one from login and then the log out function so let's quickly reiterate what we did um by putting those side by side let's close this and showing this okay now when we visit this route API O then we're going to call this o routes which is this file and we have sign up login and log out routes so this will be prefixed just like this API o sign up API o login and log out so when we visit this rod in our browser or when we send a request that is get we're going to call these functions which are our controllers that we have created in this file and now it is time to add those functions one by one but first let's just test it out I will save this file now let's go into this route and if we open up our terminal um let's go and refresh we're going to see that login user run which is this function uh I mean this one and then if we visit the log out that's also going to give us the logout user and if we visit sign up that's going to give us the signup user function and which means this is actually working as expected we visit this route it called the signup function log L function logout function but you see this is hanging is because we are not returning anything if we say something like press. send sign up user and that's just going to stop from hanging because we got a response and now let's create this signup function so there is one thing that we need to change that is those will not be get method but rather all of them will be post and this is how we can update the method so it's going to be either post delete you could put update patch just all methods that you would like to have but in our case we would like those to be in the post method and for this to be testing out we will be using Postman so this is the desktop application that I have uh I would recommend you to install this as well um let's create a new workspace this is the one that I have created while I was testing out out so we're going to go here and let's create another workspace I will say next and name could be chat app YouTube and create this one now so it's going to create this and we could add different collections one blank collection and let's just rename this to be oath and later in the course we're going to have another one let's duplicate this now and this is going to be for users so to get user profiles and then duplicate this one this is going to be for messages we're going to put our requests into these collections but now we would like to start with the oath so let's say um create or maybe add request that is going to be sign up if you save it is going to update here and then we would like to have the post method and our URL will be HTTP or actually let's just copy this quickly paste it okay API o sign up we would like to send some data that is going to be type of Json not text and here we're going to put our data but first let's add this function now so I'll shink this and open up this panel um let's close this we're going to go into o controller and this function will be an Asing function so let's delete this it's going to have try catch and for the try let's just do uh step by step so we would like to get some values from request. body so cost request. body and this will be the actually the inputs that we will pass from our our friend end so let's get them one by one um they're going to be something like full name uh username so we are signing up our user so we like to their full name uh username their password their confirm password so that we will check if passwords match or not and we'll get their gender but to be able to sign up a user first we need to create a database and then a model so that we could sign up this user into that database and for this we'll be using mongodb and let's go and set that up so here I am in the mongod db.com I will say sign in and if you don't have an account you can sign up for free that is uh no credit card required so I will sign up with my Google account or sign in basically and here we need to create a project um so let's wait for this okay I will create uh under my organization I will so I have one project that was the threads and I think this one as well okay we have two projects but that doesn't really matter we'll like to create new one and I will call this as chat Dasa and I'll just I just put this suffix that is YouTube so I'll just say next and project owner is going to be me so I'll create the project and that's going to take a bit time so they redirected me to this page I will create a M and I will use the fre here um the cluster name can be like this this is not really important and let's create that now and here we would like to have username and password they already gives us so this is really important you need to copy this and just take it as a note because we'll be using it so I will put it uh for now to my DMV file and just say create this user and and that's going to put my current IP address and so if you don't really want to have any other problems while while developing so you could put an IP address that is access from anywhere that is uh these zero IP addresses and once you add that just say add entry and so this is only for development when you uh take your application to production you really want you don't really want to have this and I think we could do that and just delete it once we deploy our app so let's see finish and close um that says go overview and that's going to take a bit time to create this cluster and now we will click the connect from our application and we're not going to be using mongodb but instead we'll be using mongus and we already installed that package so let's copy this connection string and we're going to go into the EMV and just create another uh variable so mangore DB and U so I will paste that now we would like to update this password field with the one that we have I will copy this and then replace it with this one and then this is the database name if you don't really put anything that's going to be the test database but I would like to have one called chat app DB and if we save now when we use this mongodb URI we will be connected to our mongodb database now let's go and create another folder called DB and we could say connect to mongod db.jpg say console log something like error connecting I mean connecting to mongodb and we could just pass the error. message and then in the try we would like to say await mango. connect and we'll just put our URI which is this one copy this and just paste it process. EMV mongodb and we could say something like connected to mongod DP now let's export this export default D function and in our server.js once our applications start to listen so I will cut this curly braces paste that and then I'll say something like um and we forgot to close that off I will say um connect to mongodb function and we have an extra Okay so so app. listen this port and then connect to mongodb then just console log server is running on this port let's save this file and maybe this one and let's see now in the console if we can connect to our database so server running on this port and we are connecting so we are connected to mongodb now we need to create a user model as well so that we can interact with our users in our database and you'll understand what the model is in a second let's close this and if we go into our database we can browse our Collections and a collection is just like a table so here we don't have any collections or databases sometimes mongodb by default might give you a database that is called as sample but in our case uh I don't have it and if you see someone I mean if you see that sample database uh just don't worry about that at all uh you could even ignore that so now we would like to add our models and we're going to have user models as well as message models and let's go into the back end we're going to have that folder called models and let's just shring everything for now um inside the models we will have the user model and again I would like to put model extension um just a preference so user model. JS and now inside this user model we're going to have a couple of different fields such as full name username password U gender as well as the profile picture so this is how you would create a model so import Mangus from Mangus then we will say const user schema so first you create a schema and let's say new mongus schema and just open up an object and now this is the place that we will put our Fields so we'll take to have the full name that is going to be type of string and let's let's just say type will be string and then let's say it is going to be required every user should have a full name and then we will put the username so this is going to be same type string required and unique so it should be unique so that every user has only uh that unique username and then we would like to have the password so it is going to be type of string uh required and minimum length of six and that's how you can add it and then the other thing that we like to have will be gender so we'll say type will be string it is going to be required and we could use something like enam and this will uh so let's just have it enum so it is either going to be let's say male or female we use this enum field when you would like to have some certain values and this is our application we'll be using these values now we could add something like profile uh pick I'll just put it into the next line profile pick and then this is going to be type of string and it shouldn't be required and by default it's going to be this empty field and let's save uh so that was our schema now we'd like to create a model based off of this schema so we'll say const model I mean that's going to be user not model mango. model um user and user schema now here we just put this user that should be not plural but that should be singular and then you don't say something like user but just try to make it uppercased or capitalize and mongodb will figure out or mongus will figure out and just make it to be something like users and if you would like to create people uh model you would say person and that will just figure out okay this user would like to create a people collection and I don't know why this is being implemented like this but that's how they decided and now let say export default the user model and that's going to be it for this file we have all these fields we create the model depending on the schema that we have and now we we are able to use this user model in our files so with this I think we can go and work with this controller so here we need to update something else so here we can't just go and get these values from request. body to be able to do it we need to use a middleware so let's first update this file a bit um maybe just organize this so I will put my variables to up here and then call that uh so this config call and then take this midal lay and just put it here um this going to be a route we could maybe just delete it um or let's just have it but I'll just comment this out and then so that was our middleware these are these are our package Imports file Imports variables DMV config and then we'll click to add another middleware so let's say app. use express Json so this will allow you to get the extract this fields from request app body and if we have to put some comments we we got some from co-pilot to Parts the incoming request with Json payloads so from request. body okay that was our middleware as well now here we'll just go ahead and try to sign up a user so let's say if password is not equal to the confirm password that means passwords do not match so return rest that status of 400 which means there was an error and and Json an object with the error field that says passwords do not match and after this if check we can say const user await now we will we will call the user model and we need to add this. JS at the end so that we don't get any errors and we'll say dot find one with this username so this will check if this user is a exist in our database with this username so we'll say if username I mean if this user existed then just return this error that says username already exists but if um if it isn't so which means we still continuing with this function there is not any errors there is one thing that we need to do so we would like to take this password and hash it and I'll I'll show you what that means but let's for now just skip that and let's say hash password here and then we would like to put some random profile picture and for this I have found an API again I will put the comment here it is this one now let's copy this and visit that API so this API gives us uh placeholder avatars now there you can see we have some boys and we have some girls as well and if you would like to get some unique ones there is this I think if we collect to this document okay we're going to get this uh URL now let's just copy this boy and if you paste it now every time you refresh that's going to give you a different profile picture okay so it's just randomly gives you and same goes for the girls now every time you refresh there's a different profile pick and to be able to get a unique one so they tell us you you could use something like username so if you go with this Scott every time we refresh it's going to be the same user profile picture and that's what we'll be using um I will copy this so you use boy for boys and then girl for girls I copy that now I will say const boy uh profile pick and then I will just open up back text paste it now the username will not be Scot but this username that we are getting from the user and then I will duplicate this and that's going to be um girl profile pick and then we will update this okay and now we'll just use this uh depending on the user gender so let's say const new user await so we could use this user model and we need to not AIT but new user and put pass an object now we're going to pass the full name so the full name of this user will be the full name that we get from user inputs but since they are the same thing we could just uh shorten this with only adding the key so we'll have the full name the username uh the password right and we will have the gender and lastly we'll say the profile pick will be dynamic so if the gender is equal to male then we will use boy profile picture but if it is female then we will use this profile picture and that should not be okay so we have a typo here let's just fix it and now we will say um new user. saave we're just going to save it to the database um so yeah and let's just say reside status of 2011 which means um the created okay successfully created um status code this is and then we'll say Json and just pass the user so in mongodb we got a field that is underscore ID that will that will be put automatically and we'll say new user undor ID we will say full name new user. full name and then we will have the user name as well as the profile pick and for the catch we can go and say something like pr. status of 500 and we could say something like maybe internal server error and we could say console log um error in sign up controller and then just pass the error message so that we can debug this in our terminal and now if we save this we can test it out I will go into my Postman so we have this sign up route and we will pass some data and those data will be these fields so full name username I'll just actually copy all of them and then just paste it one by one okay so I will comment this out and just put it so full name let's say something like John do and then duplicate this so this will be the username and then we will have the password so let's say from one to six and then confirm password and I'll just zoom in a bit sorry I didn't even realize so I am zooming in from these uh View and zoom in okay maybe this is a bit too much I'll just zoom out once okay now I think that should be readable from the video uh we got the confirm password and lastly we'll have the gender let's say this is going to be a male and now if we send this hopefully that should work and it says passwords don't match so 1 two 3 4 5 6 1 2 3 4 5 6 and let's see why that is so if password is not equal to confirm password right passwords do not match so confirm password one 126 again one to6 let's send it again okay that should be password I had a typo here um let's save and send it again okay so user has been created there you can see we have this status code that means we passed all those if checks and we were able to make it until this line and we saved the user to database now let's check it out if we refresh here we should be able to see the users collection in in our database and here is the user and we got this underscore ID field as well I just zoom in a bit and this has been generated by mongus or mongod DP and I said that we'll be hashing these passwords and the reason is now you shouldn't be able to see your users passwords imagine if someone steal your database they will be able to just get so access uh to every user in your database so for this we'll be using that bcrypt JS Library so let's say import bcrypt Js from bcrypt JS and let's put it at the top and give a bit space then before we try to okay we even put comment here so we're going to Hash the password and this is how we would do it so const first you need to create something called salt so a wait bcjs gen salt and most of the time we put this value Val as being 10 so the higher it is it'll be more secure but the higher it is it'll be slower as well so if you put something like 50 that will take a long time to create the salt and the number 10 is the default that we generally do now we created Thea and let's call this as bcrypt not the bcrypt JS so let's update it um so we'll say const hashed password and we'll say a a bcrypt do has so we're going to Hash the password the user sends us so it is this password we are getting we're just going to Hash it with this so and instead of saving this user with this password now we'll say hashed password and now if we save this uh hopefully it's going to work let's go into the postman and create another user let's say Bob and we could just leave the password as it is I will send this now we got the new user let's check it out refresh and now the password should be hashed as we can see now it is not one to six right and that's something that you should keep in mind when building applications now let's take a look at this file um just retrade quickly so we got the inputs from the user we check if password do not match we return this error with this status code and then we check if this user exists in our database depending on this username if user exists then we return this error that says username already exists but if user is not exist then we are going to try to create this user so we hash the password then we determined the user profile uh the profile picture and then we just uh create the user with the full name that is being passed so the all these inputs and then we try to save this user to the database and just send it as a response now I will cut this for a second and I will just even optimize this I will say if there is new user um just paste this part but else we could return something like um invalid user data now I will save this file and I think that looks a bit cleaner and there is one more thing that we'd like to do that is to actually generate GWT token and let's do it now we are going to go into the back end and let's create a folder uh what should we call it let's go with UTS and we'll say generate token and set quickie or maybe just generate token. JS let me just fix this that should be a lowercase JS and now in this function we will try to just create a JWT and set it in the um set it into the cookie so let's say import JWT from Json web token package that we installed previously and let's have this function generate okay so we'll have this function called generate token and set quickie so we are going to get the response as well as let's say the user ID and as an argument and then inside this we'll try to create the token so const token that will be JWT sign and that's how you create a token and we will say um so it needs a payload and we pass the user ID let's just type this function out and then I will explain uh once more so the other thing that we need to add the secret or private key and we can have it in our uhv file so here we'll just add that field JWT secret and that could be any random value but let's just create one in our terminal so I will open up a new terminal and then I will make it type of bash git bash and then open SSL Rand uh so Dash base 64 uh 32 and if we just press enter that's going to give us this kind of secure uh secret I will copy this and just close this and this one okay so we could put this secret into here now we'll be using this um GWT secret to sign this token and the other thing that we need is just options and we could say something like expires in let's say 15 days not 30d I'll update this with 15D and now that we have created the token we would like to set it into cookie so r. cookie with the name of JWT that could be anything maybe token or JWT token I'll go with JWT then we'll pass the token and then some options so here basically we call this method that is JW uh JWT do sign so this takes the payload and this is the information that will be embedded in the JWT token and there is this JWT secret and this is the key that is used to sign the token so it'll create a digital signature and when we want to verify this token we will use this payload and that's how JWT Works in simple terms and then we created the token we also want to set it as a cookie so we use res cookie JWT pass the token and some options just to make this a bit secure so first let's just say max age and we'll say 15 days but we can't really put it as a string that should be in the format of milliseconds so we'll just say 15 days 24 hours um 16 minutes I mean 60 Minutes 60 seconds and 1,000 milliseconds I think that's the uh order that we just added so let's say that should be in the milliseconds format and we will say it should be HTTP only true and this says this cookie should only be accessible uh so only HTTP only so users cannot access this cookie via JavaScript and this is used to let's let me just put a comment so prevent uh xss attacks which is also known as cross side scripting attacks so if you wanted to check that out just pause the video here and take a look at this attack but basically we add this so that this cookie is not accessible via JavaScript and then we have this same site attribute as well so we could say strict and again this is something that we use to prevent some attacks and so csrf attacks cross site request forgery attacks in long so this is the function that we have lastly just say export default this function so we created the token by calling this sign method and we need to um send a payload to this method and then and as well as our secret and we said that this token should expires in 15 days then we sent this in our response by adding this options just to make this a bit secure and just say this is the maximum age that should cookie live and then we just uh export default this function now we're going to go here and just call that function so that should be I think a wait and generate token and set cookie we're going to import that let's see it should be from this file. JS now we have an error I think um let's save and I'll just try to see we have U Tails so we need to go one up U tails and then generate token. JS so for some reason it says this is the file extension but it isn't um I updated that right so I'll just um preload my my vs code control shift p I'll say uh reload window hopefully it should fix now and here we go now it is working fine I'll say he'll just delete this A8 because it is not an eing function um we'll send the response as well as the user ID so that's going to be new user underscore ID and then the response and if we save and we can test it out now in our browser let's go and create a new user I'll say Jano and then password could be same and we'll say female now let's save and send this one this has been created now we can get a quickie that is JWT and it has been created successfully and also we can see that it says HTTP only is true and it says secure is false because we are in uh Local Host so it is not https and we can add it if we go into the options we could say secure field and we could say um so either true or false but we'll make it Dynamic so process. EMV if uh we are in the development it is not going to be true and if you are in the production then that will be true okay so currently it is false and let's create this uh environment variable so that's going to be development for now and when we deploy it we could update it let's save all these files and if we try to sign up again so still it is uh not secure but that's going to change in production now that we have the sign up functionality we can go ahead and try to just to log in the user so I will duplicate this one now and call it as login and we'll change the url that will be or the endpoint that's going to be login we're going to again send some body um so we will just send the username and let's delete this comment and username as well as the password let's delete this comment and save this also this one okay so that should be like this we have the username and password now in our signup function let's shrink this I mean in our login function I'm sorry that should be async we're going to have the TR catch again and in the catch we could basically copy this and then paste it so instead of error in signup controller we'll just say login controller and then sharing this now in the try again we're going to get our username and password from request. body so username password and then we will just say const user a user. find one with this username if this user is not exist or maybe let's first check again for the password so is password correct and we need to decode this password so await bcrypt compare method so we'll say the password as well as the user. password so we say um the password from the input and then the password this user has in the database just compare them and if it is true then this value will be true but now what happens if this user is not existed so this will throw us an error and we could back it off with within empty string now we say to bcrypt compare this password and this password and if it is undefined or null uh compared with an empty string and that will not throw us any errors so let's say if there is not user or if password is not correct then return this error that says invalid credentials or let's say invalid username or password so we don't say which one is uh not correct and then after we do this we will say generate token and set cookie again send the payload as well as the response and if that was successful as well we'll just say rest. status 200 and just return these values so get the inputs from user check if this user exists or not check if the password is correct or not and if any of them fals then just return turn this error generate the token and set quickie and then just um send this response let's save and try to login so this is the user that we have created in our database if we put something like a wrong password we're going to get this error that says invalid username or password if you put the correct one um it is just going to log Us in and if we delete this part I think we're going to get an error um so let's say J Jano X which is a user that does not exist in our database if we sent now we have this error that says internal server error and if we take a look at the console we will see that illegal arguments string and undefined so this is something bcrypt um JS package uh returns you that's why you need to add this part and I have explained this just a couple of seconds ago so I will save this file and now let's try to add the log out function and that's going to be pretty basic or simple so try catch let's get this part oops we're going to put it into the catch error in log out controller internal server eror and then that's going to be async so res. cookie JWT and we would like to just take this value to be nothing and maximum age will be zero so max AG zero and then we will say rest. status so 200 loged out successfully if we save now let's try to log out duplicate this that should be a log out log out route we don't need anybody so let's say none and now if we sent this it says logged out successfully and now we don't have any cookies because we just clear them out right so just like here and we could delete this async we don't really need it so that's going to be it for our authentication routes now we can sign up uh by getting this inputs we run some if checks and handle the errors otherwise we hash the password generate the profile pick and then just save this user to our data base and send um just generate a token and set it as a quickie and then we do the same thing for login if there is uh these errors then we just handle it otherwise we log the user in by creating this token and setting the cookie and we send it as a response and then in the log out we just clear out them and as the next step we would like to create a message model and then a message controller so that we could send messages and get messages from our dat database okay so this is going to be our database design we're going to have two different collections one for messages and one for conversations each message will have this underscore ID field that will be generated by mongod DP automatically and then each message will have the sender ID receiver ID as well as the message content then we have the conversations model or collection so each conversation will have this underscore ID field the participants array as well as messages array so participants array will contain the ID of the users that is in this conversation and then the messages array will contain the ID of messages that is in this conversation now here we have an example let's take a look at that we have two users in our database which is John with the ID of one and then we have Jane with the ID of two when John sends Hello message to Jane this message will be created in our database so ID it was 90 that is created automatically and then we have the sender ID which is John receiver ID is two which is Jane and then the message content is hello as we can see here and after this message we will create a conversation inside this conversation Collections and then it's going to have just a default ID and then it's going to have the participants array that is between John and Jane and the messages array will contain this messages ID which is D90 and now let's say Jane sends message back back to John that says Hi um and the ID of this let's say 91 this ID will also be added into this messages array as well so this is the approach that we'll have now let's try to create this message model as well as this conversation model so now in our backend folder we will create two different models let's start with the message so message. model. JS and we could import Mangus from Mangus and then first we need need to create the message schema so const message schema and that's going to be new mongus do schema and then as we said we're going to have a couple of different fields which is send id reive id and then the message itself now the sender ID we said that it's going to be type of ID and we could do it like this so type will be mongus do schema. types and object ID and that's how we say this will be a reference okay this is just an ID that will be inside the user model and we can say ref to be this user model now this basically says this sender ID will be an ID from the user model or the user collection then this is going to be required let's say true and then we're going to have the rece ready it's basically going to be the same thing I will duplicate this and I'll just change the name receiver ID it is going to be type of ID and reference to the user collection and lastly we're going to have the message and type of string and it is just going to be required now there is one more thing that we forgot to add in the user model so after this first object you put a comma and this is optional but I always would like to have this it is time stamp will be true so when we create a message we will have the created that and update that fields and it is because of this field called time stamps true mongus will automatically try to create this fields for us so that we can show uh the time that this message has been sent so in our front end will do something like message. created at and this will give us the time that this message has sent so let's say maybe 15 30 and you will see uh and you will understand this better when we get into that part so I will go here now we have the schema we'll like to create the model so const that's something we already done so message mongus do model create this messages uh collection with this schema and then just export default D message now we would like to create another model I'll say conversation. model. JS and now we'll basically try to do the exact same thing so import Mangus from Mangus and then we will say con conversation schema and just call this and first object and the second one will just be time stamped to be true and then we're going to go and add the participants array as well as the messages array so let's say participants and that's going to be an array and each object or each fi will be type of so let's say type of this mango op object ID and reference will be to the user model and after the participants we're going to have the messages array so let's create that and each field again will be type of uh this object ID that is coming from Mangus and then reference will be to the message model so we will store message IDs inside the messages array and user IDs inside this participants array and I think we could also say by default so when we first start this conversation it is going to be this empty array and we will just push our message message IDs when we create the messages and I think we could save this now and just export this model so let's say const conversation create it with this schema and then just export default the conversation so I will save this file now and let's not forget to add this time stamps to our user model and for now if we check our database let's refresh now as you can see we don't really have um any of those created that and updated that fields in our database right so let's try to add it and test it out inside the user model we will just put this object that is Tim stamps through so let's put a comment I didn't mean to open that up so create that and updated that let's try to sign up with a different account so I will go and just change this Fields so I'll say maybe ja like John now if we try to sign up with this user we got this uh response that is 2001 created and let's refresh in our database now none of those users has the created that and updated that Fields but this one has so we could use this field in our application to show something like um this user so we could have something like member s and then this created at date this is most of the time why you use this created ad field and so basically I will just leave this as a comment here and now let's try to add our message routes in the server.js I will duplicate this that is/ API SL messages and we will create message routes not the message model sorry message routes and let's duplicate this one that is going to be from message. routes.js file that we'll create in a second and this should be the name so let's go into our routes folder and create that message. routes.js so here we need to import Express from Express and just create a router so const router Express router and then export default this router now so we could create some methods let's say maybe um router. poost and let's create the send message route first we'll say slash send slash so this will take the user ID and this will be the user that would like to send the message and we will put our controller so let's actually say send message and we will create this function now inside our controllers um let's say message. controller.js and Export const this function that's going to be async and let's say console log message sent now save this file import this from controller.js so message controller.js don't forget the extension and then inside the server JS save this file now when we go to SL API SL messages slash send slash the user ID we will call this function and let's test it out now I will go into the messages collection and add a request I will copy the URL from here and then just paste it I will re rename this to be sent message make this to be post and this is going to be API messages slent and then an ID that could be 1 two 3 for now and if we send this now this will be hanging it's because we are not returning any response but rather in the console we see this message sent let's send it again so say cancel and send it again now we can see that message sent again and how do we get this ID from the URL this is where this request comes into play so let's say request. prems doid now this is called as ID because in our Rod we said that this is an ID if that was something like user ID then we would say request. prems do user ID okay it should be like this but what I would like to have is just to be ID I will save this now and let's send another request okay if we just send it uh request has been sent and it says message sent and this is the ID and this is how we will take the user ID and then just send a message to him so let's do it now actually we will delete this and just open up a try catch in the catch let's send some errors so we could send something like res. status 500 and then not the message but let's say error that is going to be internal server error and then here we would like to just console lock this so that we could debug this error and send message control and we could say error. message now we can get the message ID or I'm sorry we could get the message um content so we'll say const the message itself from request. body and and then we would like to get the ID so const ID from request. prems so it is same thing as if doing ID and then just putting ID here so instead instead of putting this we just destructure that so some basic JavaScript and now after this uh we need to get the sender ID which is us right the current uh So currently authenticated user so let's say cost sender ID and request. user ID and if we do something like this this is not going to work because in the request we haven't set this and now let's try to add it and for this we'll be using a middleware so inside our message routes we will say before you run this function just check if a user is logged in or not and we could say Protect route so protect this route before you act so protect this rout before you run this function so this is kind of like authorization not kind of but literally this is the authorization process that we are adding so not every user in our database will be able to uh just send a message but only those that can pass this uh function so let's create this now we could add it into a folder let's say middle lare and then we will just add that function protect route. J JS and here we need to import the Json map token so I'll say JWT from Json map token and then we will do a couple of things in this function so protect route this is how I will call it now this takes the request response and then the next and you'll understand what that is so here we'll have a try catch in the catch let's say res. status now this is something uh something that we do 100 times and just return that and let's say console log error in protected rout protect rod middleware and just um show the message and now what you would like to do is get the cookies so const token we would like to get the token from cookies so we'll say request. cookies. JWT and if you do it like this you're not able to get the cookie and to be able to do it we're we're going to go inside the server.js and we have installed a package at the beginning of the course which was this cookie parser let's go and import it now so import cookie parser from cookie parser package and we need to just call it as a middleware so app.use cookie parser so before we run any of these routes we would like to call this middleware so that we'll be able to um just act access the cookies and that was inside the protect route so get the token from our cookies and if this is undefined so if there is not token then we could just return something like unauthorized and there is no token so I will copy it and maybe just paste it so return rest that is 4001 and that means unauthorized and our error is unauthorized no token provided now if there is a token that means we pass this if check and we'll just say decode this so con decoded and we'll say jw. verify we call this verify uh function or method to be able to verify this token so pass the token and if you remember I said that we use this JWT secret to be able to sign this JWT token right when we were building this function I said that this token is used to I mean this secret is being used to sign this JWT token and now with the same secret we are trying to verify or decode this token and that's why we need this secret so we'll say if there is not decoded value then again we will return some error so again I will just paste it so return rest status 4001 which means it is unauthorized and now you have the token but it is invalid but if we pass this if check as well then we will just say const user in our database so await user model let's import that um so import it user model. JS don't forget the extension we will just say find by ID and we will pass this decoded. user ID and it is called user ready is because what we have called it when we sign this token and then now we will We would like to return this user but let's just uh remove the password so we'll just say select minus password and this is the user that we have in our database now so we could even optimize this so let's say if there is not user then just uh return user not found let's make this an async function so that we can use a weight and and lastly if we just pass all those checks we will say request. user should be equal to this user now in our request field we have this user that is the user that we have in our database so this is the currently authenticated user where we can just access it and we will say call the next function so this is the next that we have so we got it as an argument let's shink this and this will basically okay I will explain this in a second let's just say export default this function so after we run all these all this thing we'll just say call the next function and that is going to be this sent message now let's import it and we will see this in a better way okay so when we have a post request to this route we will run this function and if this is successful up until here then we will just call the next function which is this one so this request still continues until we uh return a response and we will send it on inside this function now we can get the user ID under request. user doore ID and it's because we have added this in this protect Rod middleware right now we have request. user which is our user in our database now we can close these files and then just continue with this file now this is the send ready and let's just rename this to be something like receiver ID and save this file to get this formatting and first we need to find the conversation between these two users so for this I will say await call my conversation model let's import it at the uh I mean add the JS extension at the end now conversation dot will we'll say find one so we'll just find one conversation that is between these two users and now this is how you would do it you will say the participants so participants and object where we'll just put a dollar sign all so this is Mongo's syntax so we say find a conversation where participants array includes all these fields so sender ID and receiver ID this will give us the conversation between these two users and we could set it into a variable so let's say equal sign oops if I can type so const conversation and we'll in fact just make it as let because we will change it in a second now we need to have an if check here so let's say if there is not conversation then we need to create this first right so maybe we try to find the conversation between these two users and it is null because they are maybe just sending uh sending a message for the first time and and that's why this will be null and if this is the case let's create one so we will say set this conversation variable and let's create one conversation. create and the participants will be sender ID and the receiver ID and for the messages array let's take a look at that so we are in the conversation so if this is not being created by default it is going to be an empty array so we don't really need to say and messages will be an empty array so we don't really need it so we create the conversation between these two users now let's create the message that is coming from the user so we'll say const new message we'll say new message let's call the message model it is coming from uh this file we have the JS at the end and let's create it so it is going to have the sender ID field you could say sender ID will be sender ID and receiver ID and then the message itself and let's shorten this by deleting this part and then this part then this so it is the exact same thing and now we will say if there is new message if this is successfully created then let's say conversation. messages and just push this message ID into that array and after this we could basically just return the message so r. status 2011 and instead of this let's just say send the new message and let's save this file save this one as well and let's test it out actually now before we test it out let's take a look at so let's take a look at that what is going on we are getting the message from user as an input and then we get the user ID or the receiver ID from prems and we just rename it to be receiver ID we got the sender ID that is coming from request. user because we added this protect route middleware and then we check to find this conversation that is between these two users so if it does not exist then we create one with this participants and then we create a new message and put this message into the messages array in this conversation and just send it as response now let's test it out um so we have logged in as Jack Jon this is our ID and let's try to get the IDE of maybe this user so we will send the message to DAC so under the send message let's save this so that we can get this post method and under the body so first let's update the URL we will put the ID of Daisy and then roll we have the Json and let's say the message will be something like hello Daisy it's me Jack John and now if we send this hopefully that's going to work and there we go now message has been created this is the sender ID and this is the receiver ID that we put in the URL which is the ID of these see now let's check it out in our database if we refresh now we should we should be able to see that conversation and messages um models or collections now we have one message that is oops so we cannot get it actually we have the conversations but the messages okay we don't have the message but we have the conversation okay so we're going to fix it and let's see what is what is going on here so we say new message we created it and we push the message ID into the conversation but we never saved it into our database right okay so that should be a wait conversation. save in our database just update it and then await message. save and that should fix our problem let's delete those collections in our database so I'll say messages delete this and then we'll like to delete delete the conversations as well just copy this paste it and drop this and let's try to send this message again hello Daisy it is me Jack John and if we send this hopefully that's going to work now it has created that and updated that fields and let's refresh now so we have the conversations and messages so the message here this is the content it is uh sent by this user which is Jack John and this is the receiver ID which is Daisy ID and if we go into the conversations we have one message that is this ID and then participants are these two users and now it is working fine and we could optimize this so the optimization that we could add would be instead of doing it like this that will take longer if we do it something like this promise.all and conversation. saave and new message that save now this will run in parallel so I'm just put this will run in parallel and this will not run so first this will be done in the background and then this will start to run so if this takes 1 seconds then uh this needs to wait 1 second to be able to run but here this is not the case this and this will run at the exact same time okay just to have this comment and yeah that's going to be basically it for uh message so send message controller later in the course we will add so let's say socket IO functionality we will go here later in the course we will add it to make it real time but for now it's okay now the other thing that we'd like to have to get messages between two users I will duplicate this route and I'll say this will be a get method and we will say get messages between the current user and then the this user ID that will pass to get messages between those and we would like to call this function as get messages and let's create it inside the message controller um I will go into here shrink this one or even before I shrink that I would like to copy this and then say export const um get messages asnc function it's going to have try catch and in the catch let's put it and error and get messages controller so inside the try let's get the from the prems let's say request. prems that's going to give us the ID field and I would like to rename this to be user to chat ID okay this is the user that we're chatting with and we'll click to get messages between between us and him so we will say const the sender ID we could get it from request. user doore ID and that was coming from protect Rod function that we talked about and again we would we would like to find the conversation between them I will give a bit space so conversation and await conversation model. findind one and again it's going to be where the participants is so the participants are the sender as well as this user that we like to chat with we will find this conversation and now inside the conversation if we remember we had only the message IDs right it's it is the message ID of 90 91 but we don't know the message content and to be able to get this message so now we'll CLI to get every message in this messages array and for this mongus gives us a method called populate so we'll just say populate the messages field now instead of returning us this um ID of arrays that will actually return us array of objects and just put each message into that object so you'll see you'll understand this in a second um if we just now go and say res. status of 200 um um let's just return the conversation. messages and let's save save this file as well but first import the function and now we would like to get messages between um so let's create another request I will duplicate this so send message copy that should be get messages and that's going to be get uh get request and this URL we could say get messages between us and if I can update okay get the messages between logged in user and this user I will send it um okay so we have an error um let's see what that is so we said that's going to be get okay the URL is wrong it is not going to be sent we'll just delete that part now let's send it again and here we can see we got the messages between us and Daisy now instead of getting references we have an object that is the message itself and it is because of this populate method that we are using we say inside this conversation don't just give us the messages array but rather give us each message one by one so it is not reference but the message itself I'll just put a comment not reference but actual messages and we could optimize this code by adding some error handling so let's say if there is not any so if this conversation does not exist then we could just say return rest status of 200 but the array will be empty and then maybe instead of saying conversation. messages we could just say messages and conversation. messages and just up update this field with the variable and with this I think our function has been completed now let's try to send a message to a different user inside the users um I would like to send a message to John I will copy his ID and remember we are logged in as this Jack John user I will try to send another message to this user I'll will say hello John it's me Jack and send it now message has been sent there we can see it's been created and let's double check this so that message is here now it has been created inside the conversation as well now that was the conversation between us and Daisy but now this is the conversation that is between us and John do now let's get the messages between us in this J so I'll copy this ID and then if we pass this we're going to get um the array of messages and if we had multiple messages so hello John it's me Jack John um two so this is the second message and if we say get messages now we have the other message as well so the second message and the first message and now with this we have completed our message controllers as well and I hope you're able to see how easy it is to actually build this if you know the fundamentals now the next thing that we like to add will be uh user controllers and user routes and for the user routes again you'll go into the server.js and just duplicate one of those and let's say this will be API SL users and we could say user routes and we will just duplicate this now let's give it a bit space so this is our routes this is our packaging ports and this is data database import now we will click to create this so let's say this will be user routes that is coming from this file user route dot okay so user. routes.js just like these files we'll go into the routes and create that so I'll just copy this file name and say create this file paste it now here we'll like to create a router as always import the express from Express and we will say const router Express router and then just export default this and now what we' like to do we'll just have one route that is to get users for sidebar so router. getet and that could be the root route for this so when we we'll just visit SL API SL users and this slash doesn't change anything so so we would like to call a function called get users for sidebar so this function will be called to get users for our sidebar so here we can see we fetch these users we get their profile pigs as well as their um full name so this is that function that we that we need to create and before we try to run this function we would like to call that middleware which was the protect rod and this ensures that unauthenticated users will not be able to call this function and let's put the extension here and we'll like to create this function now inside the controllers we could say user. controller.js and here we have um separated the oath controller from user controller the reason is authentication itself is just a service right we did we don't really want to mix it with anything else because it is really important and we would like to have it as a different controller or different service so that our application code looks uh clean and organized so now inside user controller we will just build that function so export const this function and that's going to be asnc function and as always we will have the TR catch in the catch which you just say press. status and this error it's not going to be error. message but internal server error and then console log it let's say error in get users for sidebar function and just console log the error or maybe if you wanted to you could do something like console error and that'll just be better now first we'll like to get the current uh currently authenticated users ID so I think I'll just say const logged in user ID and we'll just get it from request. user uncore ID and that was so we're able to use this again just because of this middleware let's import this function and save this file save this file as well and let's continue with this function so first we'll like to fetch all users from the database so const all users and we could say await user. find and here we have um so here we have an autocomplete from copilot I'll just accept this and I will explain now let's say user get the user model at the extension and here we basically say we here we are basically basically saying that find every user in our database but the one that is not equal to this logged in user ID and the reason is when we um display this users on the left hand side we don't really want to see ourselves so now zo John's logged in but we cannot see her in this sidebar it is because we don't really want to send messages to ourselves if you wanted to do it then uh don't add this part if you just do it like this this is going to find all users in the database but if you add it this will just be the filtered users so every user in our database but not the current authenticated user and after this we will just return let's say res. status Json filtered users and let's try to send the request so I will actually let's create this add request that's going to be get method let's say get users and I will copy this route paste it API that's going to be users and that's it now if we send this this will give us every user but we don't want to get their password so I think we could do something like select and maybe will this work I'm not sure because we're getting an array um let's test it out and yeah actually it worked now we don't have the passwords so that's going to be it for our user routes where we just have only one controller to get users for sidebar so we try to fetch every single user in our database but not the logged in user and we just return this as a response and I think we have completed everything in our back end the only thing that is missing is psyched Dio which is something that we'll be adding before the deployment and now the next thing that would like the add is designing the front end so let's take a 5 minute break and then we'll continue okay now it is actually time to work on this front end folder so before we even get started with it I would like to just um initialize a g report story so I am in the root again not in the front end not in the back end but in the root I'll say get in it and this will initialize in an empty uh git repository now here we can see there are a lot of changes it's because of this note modules folder so we need a do G ignore file in the root I will take this one and put it into the root and now in this way uh both this not modules has been ignored and this one so let's go here and maybe we should say I mean inside the get ignore and we'll just add the MV let's add this one as well so MV will also uh will be ignored okay so here we can see uh other other than those files and folders everything is been added into the has been added into the kit now let's just add our first commit I'll say git add all and we could do something like get commit and for the message we could say something like uh first part completed and we'll just say back end so the first uh first part is back end and now commit this and then later in the course I will just push this into a kab repo okay with that in mind now let's go into the uh front end folder so CD front end and now we'll like this just say mpm run Dev that will open up this development server um let's click to this so here is the react application that we have now we would like to use Tailwind CSS so let's say Tailwind CSS V installation so we'll go with this one so we already created a project now we just want to install Tailwind so I will copy this and then let's go and open up a new terminal so we are in the front end I I'll just paste it and I'll just press enter now it's going to install these packages and then the next step is we will just uh paste this file into our Tailwind config.js so I will copy this entire file okay now this has been completed um we will go into DET tailwind config.js and then just paste this now um I think we can save and now the other thing that we like to add will be the UI so let's say the UI and let's see if there is any other things okay uh we forgot to add these directives so we need to copy this paste it into the index. CSS okay so I'll just delete everything in this file and then paste this now that should be okay and now let's see what is this theis so it is a component library for Tailwind CSS so let's take a look at that now instead of writing all these CSS classes just to get this button we will just say this will be a button button primary and we will just get this result now let's go and try to install this and here are some more examples now just to get this output we need to write all these CSS classes if we use Tailwind only but if we add the UI on top of it um just with this uh HTML markup and CSS classes we could get this output so now that we know the reason why we're using these UI let's go and install it so we would like to copy this and paste it into our [Music] terminal again inside the front end it should be paste it and press enter now then we need to just take this so I'll copy this plugin plugins line and then it says addit into your tailin config.js so here I'll just overwrite it and now we have an esent um problem I'll just say disable this so that we don't get those errors and with this I think we are ready to use Tailwind CSS and D UI so let's get a component just test it out um so inside the components let's copy this button maybe from GSX we would like to just get the primary button or let's get all of them we will go into the app.jsx here let's just delete everything for now and then paste those now let's delete these we don't need state for now and let's delete the app. CSS uh content okay so hopefully now we should be able to see this buttons in the browser okay so here we have the buttons but it doesn't work for the tail in CSS part and let's see what is the reason so we have added our directives we installed the packages so tailin CSS TC UI maybe we should just kill this terminal and then open it up again mpm runev okay so now you if you just refresh the page that's going to work the only thing that you need to do just um just start your application uh from scratch and now we uh we are able to use this uh tailin CSS classes as well as these UI components now there is one extension that I use so if you hover over this you will see the content what is the CSS classes that has been implemented to this class and for this the extension is Tailwind intelligence so it is this one uh if you wanted to you should install this and now we could even get some so autocompletes I'll just say text and here you can see there's a lot of CSS classes that that is available in Tailwind CSS and we get this Auto completes because of this extension and now we didn't mind let's start to work on our pages so we could delete everything for now in this page and here let's just put some div so we're going to give a couple of different classes such as pading for let's say height will be screen and then Flex items Center and justify Center enter so as the name suggests it just gives display Flags align item Center and justify content to be Center and then height screen is just going to make it full height and then ping for it just gives us um 16 pixels from all directions and now we would like to build our pages and let's first build our login page so we will display it uh in here for now and then later we'll add uh react router Dum so that we'll have uh client side routing so inside the source we'll have Pages folder and then we will have the components now inside the pages we're going to have uh three different pages so let's say the sign up page and then we will have the login page and then we will have the homepage where we just have that um chat chat box where we could just send messages now inside the login let's say login. jsx and for the sign up let's say sign up. jsx as well as for the home now I have an extension that is called es7 I think everyone use this nowadays I don't need to even mention it but okay you need to install this one and that that will give you this different scripts so if I type something like RFC I will get this Auto imported code or there things like RFC maybe RFC that just gives you these uh autocom completed code so let's import this one which is for login let's get this one for sign up page and let's make it to be uppercase sign up and I'll just paste this to here as well okay now we have the sign up page and we'll have the homepage and here let's just import the login page first now I will provide you a file that is background image it'll be so let me just push it into this public folder so I have added this background image that we'll be using for our entire application let's go into the index. CSS and we will just paste these um styles so I'll just paste this now here we have a background image that is this one and then we are giving some gradient on top of it so that it it is not this um um shining and then we have the background repeat this is not going to repeat in background size of cover position from the center and just fix it or maybe we could even delete this line now let's save and save this file let's go into our browser to see what we have so this is the output that we have now we are in the login page and this is the background um that we have now if we go into here and if we delete the linear gradient then it is going to be a lot more a lot more bright or shiny so we'll go and just say contrl Z so that we have this linear gradient and that's going to be it for now for this file we could close this now let's go into the login page and just try to design it okay so we are in this file now um let's delete this now we'll have a couple of different class names so let's say class name we'll have Flex Flex colume items will be Center then justify Center minimum width of 96 and then MX will be Auto margin X on the horizontal Direction and then we'll have another div inside of this one let's say div um well this again will have a couple of different classes width will be full petting will be six rounded LG and this gives border radius as we can see from the left hand side and then it's going to have the shadow MD this will give us the bul Shadow and we'll say background gray 400 then we'll have background clip padding and then backdrop filter as well as backdrop blur large and then lastly background opacity of zero now this will give us that uh glass um so the glass effect and I'll show you that in a second and then here we'll just add one heading so let's say this will say login and this is going to have a couple of different classes so text 3x large and font semi Boldt then text will be centered as well as text color will be gray 300 now if we save this let's see the output that we have now we have this here we can see this is that glass effect that we have on this stff now how do I get this kind of uh thing so I visit this website I'll just say Tailwind CSS glass morphism and I think it's going to be this one so here you could just change the glass opacity and you could give uh large backdrop blur change the saturation just do everything that you wanted to and then copy this class name so that's what I have done and I've just changed it a little bit to make it look like this and that's website that you can uh take those classes as well and next to this login I would like to put a span that has this chat app and it's going to have a couple of class names let's say text will be belue 500 and I think that that's it now if we save here we can see it's just been updated with this text and if you wanted to just give this a brand name I couldn't come up with anything so I just said this will be chat up now we will like to have a form after this H1 we don't want any actions at least for now so we'll say div and here we're going to have a label so I think at this point I'll just copy and paste line by line so we have this class of label and this is coming from thei if you hover over this here you can see there's a lot of classes styles that has been added to a label now it has pedding two from every direction and then label text text base that's says username and below this we're going to have one input after this label and if you just paste so type is text placeholder it says enter username and the class name is with full the input again this is coming from dcui then input bordered height will be 10 and if we save now this will be the output that we have okay so we have the username and here you can see it is accessible it has the Border outline on Focus state so that's another reason why we're using Daisy so if you wanted to just say contrl K and just search for any input that you would like to have and this is the one that we're using so so it just has the input class input bordered with full and any styles that you would like to add now let's move on we're going to have one more input um so below this div and again I will just say one more div and I will copy paste it so this is the password um label password and then we'll have the input for it so input type of password the placeholder is enter password and again these same classes now if you take a look at that it is the exact same thing now we would like to have a button or even before that we'll like to have a link so below this div we're going to have one H and later we will change it with react uh link now it says don't have an account and if you don't put this so this whole es L will give you a warning so that's why I just put them inside this and just get rid of that error so Cur Braes and codes so don't have an account this is a link if we save now it looks like this and when you hover over this you get this link styling and below this you would like to just have a button that is inside a diff so after the htag I'll just say div and then paste the button now it has the button button block which gives withd of full so button small and margin top of two if you save now this is the open put that we have and that's going to be it for this file and now I would like to just copy this and paste it once more if you don't really want to write all those classes and if you just want to copy and paste it so you could grab it at the end of this login. jsx file I will say starter code for this file and I'll be doing the same thing for the incoming pages and F files now let's go and try to build the sign up page now so here let's change this to be sign up and import it from this file okay so this is the um so file content we have and here we can see now this is the output and again we will be writing a lot of uh different classes so inside this sign up do sign up. jsx we will have oops so let's delete this we will have class name on this stff and let's give a bit space now this stff will have Flex Flex colume again item Center justify Center is going to have minimum width of 96 and then it's going to have MX Auto the exact same classes that we have previously and then diff again I think that's going to be the same to give that glass morphism effect so let me just type it at least for this one so class name is going to have width of full padding of six and then round it will be LG so we'll have the shadow MD background gray of 400 okay that's this one and then we will have background col padding and then backdrop filter as well as backdrop blur and that's going to be a large and lastly background opacity will be zero now again we will have one hitting that says sign up to the chat app if we save this is the output that we have now we have the background as well as this heading one now let's move on after this heading one we will have a form and let's delete the action give a bit space here we'll have div for the first input and this will have a label as well as an input let's copy the label and paste it if we save we're going to get this full name label and we'll like to get the input now here we we are just pasting some basic CSS classes and I don't really want to waste time writing all of them so that's why I'm just faing and I hope you guys don't mind it so after this div we will put another input and by the way let's let's take a look at that now we have the full name and full name input so under this full name we will have the username again one label and one input and type of them is text so let's paste this and we will have another one for password now again I will just copy it below this div paste it and this is the password password and here is the current output and then we'll like to have the confirm password so I will copy it and then below this St we will paste it and okay this is the output now we will like to put a component here and I'll just put a comment for now let's say gender checkbox goes here and we'll create that in a second and below this we will have another link so a tag that says already have an account and we could just give a bit spacing or formatting and after this aack we'll just have a div that's hold that holds our button that says sign up so that's the output now we have and just just before this link we'll like to have that component that allows us to uh check the gender so for this we will create that component under this sign up page because that's the only only place we're using this component so I'll say gender um maybe checkbox. jsx and now here we will paste our classes now we will have one class name here that's going to be flex and below this we will have one div and another one after that so let's say is going to have the class name of form control and I think this is coming from thei as well or maybe from tail in CSS and then inside this form we will just have one label that holds the span of uh the label text as well as the input now below this we will put the other um checkbox so inside this div let's give the same class class name form control and that's going to hold the female input or checkbox now if we save here we can see input type of checkbox it has these classes this is coming from again from these UI and here if we render this delete this line and let's say gender checkbox now if we save and this is the output that we have now and let during the course we will add the logic But Here There is a bit too much spacing and let's try to delete it maybe margin top of two or from here margin top of two okay this looks a bit cleaner and if you'll like to see that component just go here and search let's say the input or maybe checkbox that's going to be this component here you can have different colors and if you want to get the codee click to here for react applications and for HTML CSS just get this part um okay that's going to be it now let's see what you'd like to add uh next I think that's going to be the homepage so let's go into the and again I'll just copy this paste it at the bottom of our file and I'll will comment this out in case you would like to get this file because uh later in the course we will be adding we will be changing this file and I would like you to have this um as a starter code so starter code for the sign up component and I'll do the same thing for this one paste it okay now we could close this sign up page login page and let's create the homepage now inside the homepage uh let me just show you a picture so that's going to be the homepage design that we'll have on the left hand side we have the sidebar and on the right hand side we have the message container so depending on that let's try to build this page now here we'll have a lot of different class names again and I will copy and paste it because it is going to be mostly the same thing that we had in sign up and login pages so it is these classes just to give this kind of a glass effect and here we say uh smaller screens and above the height will be 450 pixels and medium screens and above it's going to be uh 550 pixels and this medium means um minimum width of uh this number of pixels and above and this uh smaller break point means let's see uh 640 pixels and above so that's something uh tailn CSS uses just to give some uh responsiveness now here we said that we'll have two different components the sidebar that we'll create in a second and the other one will be the message container and since this is flex this will be on the left and this will be on the right just like we had here this is the sidebar and message container now let's comment this out and first we'll bu build the sidebar so let's go here inside the components we will create the sidebar folder and then sidebar. jsx now inside the sidebar again we will have um three different components so this is the sidebar we have the search input right and then we have the conversations and at the bottom we have the log out button so we will just split it into three different components so that our code base looks um cleaner okay inside here we will first have the search input and then below this component we will have a divider here we can see I don't know if it is visible from the video but we have a divider here that just gives a bit um cleaner UI and here how we can get a divider with table CSS so class name divider and padding X of three I think this is coming from Daisy okay and below this we will have conversations and these are the components that we will create in a second and below this we will have the log out button and let's create all of them one by one now let's comment this out first and we'll build the search input and since we're going to be using it inside the site bar I'll just put them inside this folder so search input . jsx and let's create it now here U that's going to be pretty basic component we'll have a for and then here we'll just have an input so again um I'll just paste the classes it is coming from shats I mean uh these UI so placeholder that's a search input input bordered rounded full and this form will have this class name so Flex and items Center as well as gap of two so it is flex so that input and this button will be next to each other right and input on the left and the button will be on the right now let's paste this and inside the button we will put an icon and for this we'll be using react icons now let's save this file and inside the home let's import the sidebar um inside the app we will delete this actually and render the homepage now let's say home and if we save now and save the sidebar first import this okay now inside the app we have the home inside the home we have the sidebar inside the sidebar we have the search input if we refresh and that's the current output that we have now let's import the react icons so let's go into home and that's how we install this copy it and then inside the front end uh paste it okay so it has been installed now the icon that we'd like to use is a search icon and for this what we generally do we just go here and search for the icon name so now it is search and here you could just click one of those and copy the import so the one that we'll be using is this one so IO search sharp and that's how we import it let's say iio search sharp okay T this one and we'll just import this now it is coming from react icons and iio 5 and it has these class names withth of um 24 pixels height of 24 pixels and no outline let's save and and this is the output that we have now below the search input we said that we'll be having the conversations component and let's create that so again inside the sidebar and now instead of putting every conversation here let's create one more component called conversation and now here we will just put those conversation components now this going to have class name of ping y of two Flex Flex column and overflow Auto um okay it's going to be at the top now here we'll just put those conversation components let's say you will have four of them or maybe two four six and each conversation is this component okay this one this is a conversation this is a conversation Etc so we will go into the conversation. Js X and let's delete this one and I think we'll have a fragment and then at the top we will have a diff and at the bottom we will have another diff let's first start with this one now this diff is going to have a class name so Flex gap of two items will be centered and on Hover so that's how you would add it in tailin CSS on Hover State we would like to change the background to be Sky 500 and then rounded that's going to give us some border radius so it is going to be rounded so border radius of uh four pixels from each Direction so petting of two and then petting y of one then it's going to have the cursor to be pointer and now inside we will have an avatar so on the left we will have the Avatar and on the right we will just have the uh full name as well as the Emoji and and below it we will have this divider there we can see for each one now let's go and try to add all of them one by one and if you search for Avatar so here you will see that there is a component and you could just copy it and paste it and that's what I do so there is even online status and offline status and that's what we'll be doing now inside here we will have a Dev let's say class name will be Avatar and let's say it's going to be online but later when we add the functionality we will not addit this as a hardcoded but it will be dynamic depending on the user if it is online that's be online but if it is offline then this will be offline so just to keep in mind and then we will have another div and that's going to have an image with some classes at the stff so with of 12 rounded full so that's going to be rounded full and this image is going to have a source and ALT let's say user Avatar and as far as for the source I will just copy and paste this um URL for now and then it will update it later in the course and after this so after this Avatar we will add another div let's say it's going to have the class name Flex flex colume and then Flex of one so that it will take the entire space um other than this one so inside we will have one div and one P tag and then one span tag and inside this span we will have an emoji let's put this one and say class name of text x large and here we'll have the username say jandoo and we're going to have some class names font bolt text Gray of 200 and then this is going to be Flex I don't know why I went from at the very bottom to the top but Flex gap of three and then justify between now with this I think that's going to be it the last thing that you would like to have is going to be this div where we'll just have the divider class so class name divider margin y of zero ping y of zero and then height will be one and that could be even a self closing tag and let's save and let's see the output now so I just refresh you cannot see anything inside conversations okay we imported this one but inside the sidebar we need to just take this above oops so we need to copy it and then just paste it now and let's import the conversations now it is inside the sidebar and okay so this is the output that we have now um so it shows the same username the same online status for every single user but we'll be updating that later in the course now we have the conversations and the very last thing that we need to add will be this log out button and let's import it so I will just copy the log out button and maybe before that I will copy this so I'll copy this oops and then just paste it so that you could have the starter code for this file so I just add starter code cipit for this file and let's do the same thing for this one so I'll just copy this and then paste it and let's do the same thing for this one okay so this is the starter code for conversation. jsx and this one we did we did the search input and now um here we forgot to add some classes and let's add them so class name let's say border right and Border slate by 500 that's going to be the color of the border and padding of four uh from all directions flex and flex colume and with this now we are able to build the log up button and it's going to be inside this component let's say logout button. jsx and that's going to be nothing but just an icon so let's say class name of margin top of Auto so that it'll be pushed to the very bottom so if we say margin Top Auto it'll be pushed from here to here and we'll like to get this icon and we have an error let's save and import this and the icon that You' like to have will be this icon um so import bi logout from react icons bi and then inside here let's just say give us this uh log up button or the icon and that's going to have a couple of class names such as width of six height of six and text white as well as so let's say text white cursor will be pointer let's save and with this I think our UI should be ready but we have some errors let's see inside this sidebar we don't have the log out so we have it log out button com positions let's see it from the console so it says there is not this icon there isn't oh okay so this all should be uppercased if you save now hopefully that should work I'll refresh and here we have the log Up Button as well now let's go and try to add this message container component I will comment out this this and inside the components let's say messages and inside we will have that's going to be a file message container. jsx and let's close these files we don't need them we could close the sidebar but first I will again just copy and paste it so starter code for this file now inside this component we will have again a couple of different components so this is the message container here we have the header and then we have each message right this is going to be the messages component and then we have the message input so again we need to create uh three different components and let's add them one by one so here we'll just first let's give some class names medium screens and above minimum width let's say will be 400 150 pixels and then flx Flex colume now here we'll have the header and let's put a fragment for this and let's just have the header where we just have this two text from jando so we just added this one and it has a background color as well so it is this one now below the header we will have the messages so this say messages component and then we will have the message input and let's start with the messages now here for the messages um again we will do the same thing that we did for the conversation we will just put each message one by one so that it has its own component and our code base looks cleaner so here here we will have some class names such as petting X of four and then Flex of one overflow will be Auto and you'll see why this is needed but basically if messages overflows we will have a scroll bar and that's why we added the same thing for this conversations container and I think we'll see that uh later in the video so let's say we will have the message component that we will have a couple of couple of these so let's create them so message. jsx and for the markup again this is not going to be any complicated so here there is a component that is coming from daui so if you search for chat bubble so here you can see this is the one that we are using we have the profile pick and then this chat bubble and if you use chat start um it gives you uh as if message coming from the other user but if you add the chat in class it is as if you sent the message now here this is chat end this is chat start and this is chat start so on and so forth and that's what we'll be doing now here let's just say class um we'll have the chat and for now let's add chat in and again we'll be changing this dynamically to depending on the message so we will have one div and that's going to have class name of chat image and Avatar so this is going to have another div that will have the class name of with 10 grounded B and inside we will have an image where I'll just copy and paste it so this is coming from again um this URL that we put that is just temporary and we will change it and below this div and even below this div we're going to have one that says uh the message content maybe I could copy and paste it so I will just delete this one and above this I will paste this okay it says hey how's it going and then we will paste one more that is the time so here where we can see we have the chat bubble class chat footer and all of them are coming from daui so I I don't know these classes by heart I just copy and paste them and that's generally what we do and I will save now here this import te message and inside the message container let's Import in messages and now hopefully it should work inside the homepage we will import the message container as well and now that's what we have so if if we just make this a so if we just duplicate this one a couple of more times that's going to overflow our container and since we have this class we're going to have this scroll bar here you can see but if we didn't have this class so I'll just delete that now we can't really scroll it so that's why you add this class and this scroll bar looks pretty ugly and I want to change it so I will go into the index. CSS and I will add a couple of more classes so let's go into the index CSS So Below this so here uh that's what we have so this is going to give us a dark mode looking scroll bar so we say uh change the width and make the cursor to be pointer and I think this is not needed so we say make the WID to be 8 pixel change the background and for the truck for the thumb and change CH the hover state so that's something uh how we change the scroll bar let's go and this is the output that we have and with that in mind let's continue with our page so we could close this now we have the message component and we will like to create the message input so this component will have a form let's delete this and it's going to have a form let's say class name of pting xo4 and margin y of three now here we would like to have one div that's going to have the class name of let's say with all and then inside this we will have an input that is type of text and we'll add a couple of more classes so I think at this point I will copy and paste it so it's going to have a border width of one t small rounded LG block with full and this other colored classes and below this we could give a placeholder let's say just sent a message and after this Dev I think we could have a button let's copy it and paste it now this is going to be our icon BS sent that is coming from react icons and so we will just import it react icons slbs this is the icon that we have and we have mix tabs error so let's see what that is okay now it's it's just been fixed when I save it and after this I think that's going to be it for this component let's save and I would like to copy and paste this one as well in case some of you want to have the starter code so starter code snippet and we could do the same thing for this file and and maybe this one lastly okay so let's save and hopefully everything should work fine on this page so okay here we have our message header uh message container header so we have messages and then the message input but we cannot see the button right let's see what why that is uh okay so we're using uh position absolute so this has to be I think relative so if we give the relative class on this one so that's going to be positioned absolutely inside the St so it's going to be end of zero and inside I mean inside y of zero so top zero bottom zero that will just position it on the bottom right corner and with this now we have completed most of our design part but now what happens if we are in this kind of situation where we just refresh the page p and we didn't select any chat now here we should see something like this so welcome in the username and then it says select the chat to start messaging and for this we could add a component and that's going to be inside I think the message container so here we could go here and then just P paste this so no chat selected then we will show this component so let's just have a variable for this let's say const no no chat selected and for now let's say true and here I will just cut this part for a second and I'll say if no chat selected then we will show this component but otherwise we will return this part where I'll just paste it and now let's see the output but we need to import this from react icons I'll say import and let's save this now if we go here okay so no chat selected we see this component where we just have two paragraphs in this icon and then if we say chat is selected so if we say pulse then we will see this component and later in the course we'll make this to be dynamic and let's just take a look at this component so we have two P tags that has two different uh div containers that has these different class es just to make it look cool and then we have this icon that is text 3x large and here you can just change it uh depending on the responsiveness so in smaller screens that's going to be 3x large but in the medium screens and above so that's going to be 6X large where the phone size will be 60 pixels but here it's just going to be 30 pixels and then we have the text to be centered uh this class now now these are the most of the design that we have and I think that's enough for now we would like to just um add the functionalities now one by one so we have one error inside app jsx um okay so let's delete these and delete this one now we would like to I would like to just add this as a commit and then and then we'll just uh move on with the next section so I'll say get at everything so we have 21 different files here we can see so we have added all of these and we change these files that we can see M next to it now we could either add the commit message from here and just commit it so I'll say something like second part completed and I'll just say design or maybe UI design and I'll just commit this changes and now with that we are ready to move on with the next section so now we are in the most exciting section where we will connect the back end to front end so here um the first thing we would like to do is just add some setup so that we can so that we can have routing in our application let's open up a new terminal now my application is running I haven't closed it so I will open up a new one and I will CD into the front end and I'll say mpm install react router Dom and we'll just press enter that's going to install this package for us and what we' like to do we'll go into the main. jsx and to be able to use components that is that is coming from this um this package we need to wrap our application with this component Now browser router from react rou D and now I cannot get auto complete for some reason so I'll say control shift p and reload this window and that's generally fix it now let's try to get this so it is still not working so I'll just I think import it manually so import browser router from react router D now that we have our application that is wrapped with this component we can use any component that is coming from this package and that's something we need to add and generally we add it inside the main. jsx now let's shrink this we're going to go into the app and let's delete this for now we will add this component called routes okay now we are getting this from react r d and we're going to have three different routes so let's say one route and that is generally is being as self-closed so we'll say path if we visit the homepage then our component let's see the element will be this homepage okay now let's just duplicate this twice if we visit the login page then we would like to see the login component that is coming from pages so let's say login from the login page and that should be login component and same for the sign up if you visit signup path then you'll like to see the sign up component and let's duplicate this that's going to be sign up so this is the sign up okay now if you paste that should hopefully work let's go into the homepage so this is the homepage that we see now if you visit login we see the login page component and if you visit the sign up we see the sign up now I would like to change this port and it is just a preference and I am used to see the 3,000 port on local host for the client and for this we go into the V config and we say server that's going to have the um I think port and that's going to be this number and let's save and now if you refresh this is not going to work we need to visit this port and here we can see it is just working as expected so now here when we click to this don't have an account link nothing happens and what I'd like to do when we click to this you'll like to go into the sign up page so we'll go into the um login component where we had this a tag and we will replace it with link that is coming from react router down and instead of HRA we will have a two uh property and we'll just say um that should go into the sign up page or to prop okay so we will add the same thing to the sign up page let's go into the signup and we had this a tag let's say this is going to be a link from R router Dom and that's going to take us to the login page let's save and if we click to this now we're in the signup page and if we click to this we are in the login page and now let's first try to add the signup functionality and for this we will go into this component and let's close this now we will have some inputs right so we would like to keep track of these input Fields that's why we'll just have some use state so let say inputs and set inputs so we'll have a use State and that's going to be an object where we'll just have the full name that's going to be empty string as initial value we'll have the username we'll have the password and we'll have the confirm password as well as the gender we'll have so let's add all of them one by one um we need to add comma here so on this input which is the full name we'll like to add the value prop so let's say value is going to be inputs. full name and then we would like to have the on change listener where we'll only update the full name that is coming from this input so we spread the inputs state but we only change the full name and then we'll do the same thing for this one okay value of input username and then this one so value of input side password and on change we will only update the password same goes for this one and okay so we will we'll come back to this now let's say form on submit let's have this handle submit function handle submit and now if let's say console uh log the inputs and if we do it like this that's going to refresh the page so I'll just put some random value here and open up the console if I uh submit this it's going to refresh the page and that's why we use event. prevent default so it's prevented default Behavior which is submitting the page inside the form now if you do it like this then let's add these values so I just put username for this and full name value one two three Just some name uh random values and if I submit this form now here we can see we have the confirm password password username full name and gender is missing and let's try to add it now so for the gender we will have a function here um I'll I think put it here so I'll say const handle checkbox change and that's going to take the not event but it'll take the gender so this is either going to be male or female and inside we will just say set inputs it's going to separate the inputs and it's just going to add this gender field so that should be handle and we are going to go into the gender checkbox and we will just add it as a callback now I'll say on checkbox change we will call this function and and then for the selected gender we will add this inputs. gender field now let's implement this and we'll understand better let's get this props which was the on checkbox change as well as this selected gender field now for this male input we will just say uh this will be checked if the selected gender is equal to male so let's say selected gender if it is equal to male and then on change onto this input we will just call this function so it is going to be like this where this function was accepting a prop or argument that was the gender so we will call it on checkbox change and we will pass the mail and we'll do the same thing for this input so let's say this this will be checked if the selected gender is female and on change we will just send this to be female now if we save that's going to work fine um so we have some esent esent uh error so we need to fix this so we'll do it in a second but just know that this is not an error actually and the last thing we'll like to add will be a class name so we will just say now inside the back text we'll say if selected gender is equal to male then we will add this selected class and otherwise we're not going to add anything so I will copy this and paste it into here as well we will say if the selected gender is equal to female then this should be selected um it's going to have this class name so that we know it is actually selected now let's um save this and test it out so let's refresh and we shouldn't have any errors okay now this is selected and now this one is selected let's say full name will be jandoo username password will be from 1 to six and the gender is male so let's sign up and here we can see we just got all the values if that was female now that will be female and it is working fine now let's fix this problem where it is coming from yes l so it says you had to add the prop types where we don't really want it so for this we'll go into the I think es length file it's going to be this one and inside the rules we will just add this so inside the rules after this if we add this now uh we shouldn't get that error and yeah now that's going to be working fine and when we submit this form we would like to actually sign up the user and we could add the sign up functionality here into this file but this will get really messy and instead I would like to just make it organized and modularized and for this we'll be using hooks so I'll create hooks folder and I'll call this as use signup do jsx so I'm sorry that should be use sign up. JS but not jsx because we'll just return values from this uh hook so let's get the rafc and here instead of returning some HTML markup or jsx we will actually return some State and functions so let's say we'll have the loading State set loading and we will have so it's going to be use state by default that's going to be false and let's have our function so let's say sign up and that's going to be the async function that's going to take our inputs so this is how it will look like when we submit this form um that's going to be an async function we will say a wait sign up and we will just pass our inputs now this sign up will be the function so this will be the sign up function that we are returning from this file and we will pass these inputs and it's going to sign up us so here we'll just take all those values so full name we had so we had the username password so we had the confirm password and then we had the gender so here first we'll like to have some validation and for this we could create a function so let's say handle so handle input errors and we will just pass all these values into that function and this will return us either success or not so we'll say success or not if it is not successfully completed then you'll just return out of this function and that means there are some problems and for this let's first create this function and I think we could create this at the bottom of our file so let's say function handle input errors that's going to take all these fields so I I think I'll just paste it and then here we'll just have some validations so we could say if there is not full name or if there is not username that is provided or if there is not password so if there is not confirm password and let's give a bit spacing from here and let's say or if the gender field is empty then we will just return some errors and for this we could use a library called let's say react hot toast so it is these kind of things that you get so it'll it'll just give us some error states that says um please F all the fields and let's import this so we'll say mpm install react hot toast so inside the front end um let's just give CLS mpm in CLS just clear out your console so PM install react hot toast that's going to install it under the front end and then we need to add this thing into our into our code base so we could add it I think to somewhere into this file so it is coming from react hot toast and here now we can basically consume that Library so so if you want to use error then I'll just say toast. error and pass our error state so if any of those are empty we'll say toast. error and please fail all the fields and then we'll return false so that um this will be false and function will not continue right so we would like to say also if password is not equal to the confirm password then we'll say passwords do not match and return false now here we are handling the errors both on the client side and we are handling this also in the server site so let's go into the controllers so here even we are checking if passwords match or not and if this is the case we do not sign up the user and this is more important so that you have your security rules and you just check everything both in the back end and in the client even if they pass the client so maybe they will just cheat your client code but they cannot pass this checks because they cannot reach your server code so this is just something to keep in mind and then if passwords do not match we'll show this error and we'll say if passwords do password. length is less than six we'll say password must be at least six characters and just return false but if we pass all those if checks that means everything was successfully completed so let's say return true and now that this value is true we're not going to hit that if check so after this we'll have try catch and this is an Asing function so in the catch we could just say toast. error and just error. message and in the try we will just try to handle this signup logic but even before we try to do it let's say loading State should be true and finally that's going to be false so either this is successfully completed or there was some errors we should still set this loading state to false now here send a fetch request so let's say await Fetch and then we will put our back and endpoint so it was API out and sign up and let's make sure that our server is up and running so let's say mpm run server and that's going to try to connect to mongodb and just um run the server on the port and now since this is a post method we need to say method is post and then we need to say our headers is application Json and lastly we will send the body and this body content we should first jason. stringify it and the content will be these inputs so I'll just pass all these fields which are coming from our input States right and one once this is done we will get a response pack or data so cons data and to extract them we will use this Json method and let's say console log data but if we use it like this we're going to get a course error and let's try to see that now inside this use signup uh hook we need to return this function as well as the loading state so sign up and loading and I will save this file now we're going to go here and we will try to call this function and we're going to get that from the use signup hook so we will say const give us the loading and sign up and this sign up is this function this one we Rec calling it with this input object which is this one and let's now save it and try to test it out so we'll go here um we could close this one now and react icons as well let's say I'll just refresh this page and I'll say John client because we are trying to sign up from the client and I'll say John client password from 1 to six as always and then that's going to be mail now if we try to sign up it's going to have you have a course error and we need to fix this only in the client because when we deploy this app we will just have it on the same uh domain so for this we'll go into the V config and we need to add a proxy field so under here we'll just say proxy and we will add this/ API and I think that's going to be an object as well let me just double check that okay so this is going to have the Target Field which is our local host 5,000 so now if we save it like this we're not going to have any errors but I think we need to just um start up our front end from scratch so I will kill this and I'll say mpm runev now our front front end app will be started and here now instead of just putting this entire URL we could just put SL API and that will forward us I mean it'll just going to prefix it with this one so as if now as if we have this entire thing for the API but we could just put it like this and now let's save this file and hopefully it's going to work so let's refresh and I'll just try to sign up again and I'll just open up my mongodb account now if we take a look at this users collection we cannot see that John client because we had an error but let's just try to sign up with the with that user again so full name John client so John from client that's going to be the same username and password from 1 to six and let's say this going to be mail and now let's say if we had the confirm password is wrong it is going to say passwords do not match and if you just leave this place empty so it's going to say please fill all the fields and so all of these if checks are actually working now so this function is checking for these validations but now let's put everything correctly and if we say sign up and we don't have any errors so this is the response that we got from the back end and let's refresh here we should be able to see that John client user at the end and here it is and now we have just successfully connected our front end to our back end and this is the response that we are sending from the back end so if we go into our o controller if we sign up successfully we return um so if new user is created successfully we returned this Json object where we have the ID full name username and profile pck and that's what we see in our console ID username profile pick and full name but now how how are we going to make sure that this user is logged in I when we just refresh this page now we shouldn't be see this page because now we are logged in right for this we're going to be using context and before that let's update this function a bit so we will say if data. error if there is any errors so maybe we hit some this uh we hit this catch block here we just return an error and if our response con contains some errors then we will just say Throw new error that is this error and we will catch P it here and just show a toast so that's going to be it and here we would like to set this user to the local storage and then we will We would like to update our context and the reason is uh we will save it to the local storage so that when we refresh the page we can get that value from the local storage that we know if we are logged in or not and with this context value we will make sure to just navigate this user to homepage when they log in and when we implement this you will understand that better so inside the front end inside the source we will have a context file for the context folder and we will have a file called oath context. jsx and let's just try to create a react context so export const I'll say oath context and let's just call the create context from react and then we will say export const then oath context provider so here inside this provider we will provide some values that we can use through our throughout our application so once we use it I think that's going to be clear and this is going to take the children as a prop and then we will return this oath context. provider with some value and for now that could be an empty object we will fill it and so basically we will WAP our application with this oath context provider so that our entire application will be able to use these values and this value will be const it's going to be a state so let's call it as oath um oath user and set oath user and we will say this going to be use State and by the default value we could uh just get it from local storage so local storage get item and I will call it as chat user but if you wanted to you could just have it something like maybe oath user or user info that doesn't really matter I just want to make sure this is the chat app and I'll just say chat user and now we will say if this value is empty then just return null we'll just add it explicitly and if you return it like this this will be a string but you'll like to have it as an object so I will just cut this for a second and I'll wrap it with json. parse and this will take the string value and convert it into an object now here we'll pass this oath user as well as the set o set o user Setter function now with this I think we are able to use this o context provider so we'll go let's save this file and we will go into the main jsx we will wrap our application with this oath context provider that is coming from that file and now in our application we are able to use these values so the O user State as well as the set function and here let's create another hook so let's say export const use oath context and we'll be using this hook so context and that's going to be an arrow function and that will just return us to use context so if I can type correctly so that's going to be use context and just pass this oath context and again we have some es errors let's just disable it for this line so basically we have created a oath context and then we have this oath context provider that wrap our application with this values so we have the oath user and set o user that is coming from here and then to be able to consume this value we'll be using this hook which is O use context now let's save and we wrapped our application with this provider and that means we'll be able to use those values and here once we sign up we will say um set the local storage and then update that o context value so let's just do it step by step local storage set item and we will say that's going to be chat D user and you'll say json. stringify and that's just going to be data and this data is so this is that object that we return from the back end so it is that thing that we see in the console so we got the user we set it in our local storage and now we would like to update our context so let's say use oath context and that that was going to give us two different values so let say const the oath user as well as the set oath user so those are these values now we will just call the set out fuser and then just pass the data that we have and I think we don't need this value at least in this file so we could delete that and let's save it now remove this comments and let's just tested out now here um so how should we do it let's go into the app.jsx now let's get that oath user value so const get it from the use oath context that's going to give us the oath user right and then we will say if we visit the homepage and if there is let's actually do it for sign up okay I'm sorry we're going to go into the sign up page okay okay if you visit signup page and we will say if oath user is authenticated then navigate us navigate us to the let's say homepage but if authenticated user so user is not logged in then just show us the sign up page and let's just test it out now since we are loged then it is going to navigate us to the homepage now we cannot visit the signup page and if we just refresh here inside the sign up page and it looks like we can because we need to sign up again let's take a look at our local storage so inside the application and here we can see now we just we just don't have anything about this chat user so let's sign up I will put my name so from 1 to six it's a mail and let's sign up now we have this user in our um local storage and we are immediately in the homepage and the reason is when we sign up we uh update this state and then inside our app jsx now since this has a value it is going to render this part and it is going to navigate us to the homepage now we are not going to see the signup page and I hope that makes sense now and we could add the same thing to here so just say if there is authenticated user then navigate the user to the homepage but if user is not logged in or not authenticated then just show the login page we'll do the same thing for here um let's delete this for a second you will say if there is oath user then just show the homepage but now if user is not authentic at it then navigate it to the let's say login page so slash log in and now with this we have our protected routes we just check depending on this state we either navigate them to the related page or we just let them to continue with the current one so that's how we ADD protected rods and then we would like to add the log out functionality so use log out. JS so that's going to be mostly same and let's just do it step by step again we will have a loading State let's say const loading and set loading use state by default it is going to be false and we would like to have a function called log out that will be async and then we'll have TR catch and finally and the finally we'll say set loading to be false and even before we try we'll say set loading to be true even though loga just takes less than uh loading state so we don't really need the state but just in case because Lo log out functionality is super quick and then in the try we'll say con a wait patch to our endpoint so API o log out that's going to be a post method and we'll just had the we'll just have the headers and then let's say con data and await r. Json if there is any errors so data. error just throw new error but if this is not the case then just remove item from the local storage which is this chat user and then we would like to update our context value which is O user and so that we could navigate to the login page so let's say con you'll get some values from use o context and then here on the left hand side we will just say give us the set o user function so set o user and here we're going to go after the after removing the local storage we just say set o user that's going to be this null value and in the catch we could show the toast so say toast. error error. message and after here it will just say return the loading State as well as the log out and now we just save this file now we would like to call this function inside the log out button so let's go into the log out button component and now here we'll just say const called the use logout hook that's going to give us two different values which was the loading State as well as the log out function we don't really need this loading state but just in case you want to use it so when we click to this um this icon let's add it up here so on click just call the log out function and in case you want to use this loading State I'll just cut this and add it so even though we will not be able to see that because loading functionality is just super quick you don't even see that and then if it is not loading show this part but if it is loading show this part so if it is not loading we will have this button but if we have something that is loading if this state is true then we will just show this loading spinner that is coming from um dcui so let's save and let's test it out now we will go into our application if we click to this this function will run and it is going to clear out the uh local storage as well as update the state to be null and and since this is going to be null so we are in the homepage this will be null then this part will run where we will navigate to the login page let's test it out so here we have something on the local storage and I will just clict this log up button now here we can see that has been cleared out and we are in the login page now we cannot go to the this homepage it's because it is just navigating us we would like to go to the homepage it's says you are not authenticated because this value is null then you'll go to the login page and now let's try to add the login functionality and even before that again in the sign up we would like to use this loading state so we're going to be adding that and I think that's going to be inside the button so we will go at the very end into this button now we will say this button will be disabled if the loading state is true and this is not going to be disabled if this is false so instead of showing this sign up uh text we'll go inside and we will just do something like this so we'll say if it is loading show this spinner the loading spinner but if it is not loading then show this sign up text now let's save and that should work fine now let's try to sign up I will say test account and say test one and let's say that's going to be female and if we sign up now we will have a loading State I just take a look at here this button now it is disabled and we have that loading state for a second and now we have this user in our local storage and we are logged in into our application let's log out and let's try to add the login functionality now now let's just close everything so that it is not really annoying so we will go and let's just just open the app jsx and the login page now we would like to have two different inputs one for username and one for the password so let's say username and the password that's going to be an empty string in the initial State and whenever we type something into this inputs let's say value will be this username and on change just update this state and we'll do the same thing for this one so value will be password unchange will only update the password and when we uh submit this form let's say on submit handle submit function and we'll just create that so con handle submit that's going to take the event and let's say event. prevent default and we'll like to call a function called login and we will pass our inputs which is username and password so let's say say username and the password and then You' like to create this hook to log a user in so use login.js and again that's going to be mostly the same but let's just type it out so const loading and set loading initially it's going to be false and import use State now we'll have that function called login that's going to be async that's going to take the email and password I'm sorry not email but that was the username right okay we'll take the username and password that's going to have TR catch and finally oops not four but finally and inside the finally we'll say set loading should be false and before we try we'll say set loading will be true and then in the try let's say in the catch first so toast. error just show the error. message and and in the try we'll say con rest and just send a f request to our endpoint so API off login and we'll have this method to be post and then we'll have our headers right content type application Json and we need to send body because we have some inputs so we say Json stringify send the username and password and we need to extract the data so cons data aate r. Json and then we'll say if there is any errors let's just handle it if data. error then throw that error so that we could catch it and show it inside the toast but if this is not the case let's set this user to our local storage and then um just update our context let's get the context first so let's say use o context and that's going to give us two different values con oath user but we would like to just get the set state so set o user and then here we'll just say local storage set item and the place that we like the add or the key was chat user and then it'll say Json stringify this data which is the user and then I think we just say set o user to be this data and with this that's going to be our function right and we'll just return the loading and login function so let's just save this file and then we'll go into the login. jsx and just get that function so from the let's give a bit space from the use login hook you will get this state which is I say const it was the loing and the login function so we call it with username and password it's it's going to take it try to log Us in and then in the loading State we'll take to just copy it and we'll do the same thing so this button will be disabled depending on that state and instead of showing the login text we will just add that loading spinner so if it is loading show this loading spinner from the UI but otherwise just show the loading text I mean show the login text and now let's test it out so we'll go here and let's refresh now I put my name that was the user that I have signed up so if we refresh this page we'll just see that user because we signed up let's see now this is the test account this is uh this is me that I have signed up with my username and that was the John client now I will try to log in with this user and if I put wrong password it's going to just just say um invalid username or password which is coming from our oath controller from the login function so if there is not user of or the uh password is not correct then you will return this error and if there is an error we throw it so that we could catch it here and then we just show it inside this toast and that's how it works and if you wanted to we could add some client um client validation to here as well so I think I will copy this function and paste it at the bottom and I will say handle input errors and we'll be using it like this so I will copy this and then before we even try to do anything so we will just pass the let's say username and password so let's get the username and password only so let's say if username is empty or password is empty we'll just say please fa all the fields and if you wanted to you could make this function reusable so that you don't really copy and paste it but I want to it so that we don't waste time that's something such an easy task so here we just say if it is not successfully uh handled just return out of this function but if we don't have any error just try to log Us in and now if we just leave this empty that's just going to say please feel all the fields and let's put the correct password now we're going to have this loading spinner for a second here we can see and now we are logged in this is the user and we have the user in our um so in the react context as well so that we are navigated to the homepage so it is going to be this line where where it will take us to the homepage now we are able to sign up log in and log out the next thing that you would like the add just fetch these users for our sidebar and we will call all of them as conversations now for this we would like to use a global State and for this we could use something called zent so let's search for it and it is this one so the reason that we we'll like to use this is just to have have a global state that we could use in our entire application so that's what we did while we using this context so here we are able to get this value in in our entire application but I just want to show you there is other uh Alternatives other than context that's why I will be using this so let's go into the documentation so here's the installation let's grab grab this command copy it and paste it into our terminal so I'll just create new one that'll be inside the front end and just paste this so mpm install Z tend and while it is happening let's create a file inside the source call it as zent or maybe we could call it as store but I'll go with zent and then here we'll like to have a global State and this is how it works now we will have a file called use conversation. JS and here we need to first get the create function from zent and then we'll say const use conversation that's called the create function and it gets the set as an argument in this callback and then we will just return an object and that's going to be our Global State now that should be an object where we'll just say selected conversation by default it's going to be null and we'll have a Setter function for this so let's say set selected conversation and this is going to take the selected conversation as an argument and then it is going to call the setter function and just update this state with it so basically this is the exact same thing where we just use something like use State we have the state and Setter function and that's basically the same thing and then we will have the messages state by default it's going to be uh an empty array and then set messages that will take the messages and then set this state uh with the new messages and then at the end of this file we could just say export default this use conversation and once we use it I think that's going to be pretty clear now we would like to create a hook to fetch these conversations from our database and we have created a controller for this which was this one right get users for sidebar that's going to get us every single user but not um the authenticated user so we are going to go into the sitebar first and we have this conversations and that's going to be the place we would like to call our hook so it's going to be something like use maybe get conversations and let's create this hook now I'll will just go into my hooks folder and create it use um get conversations. JS and here we'll have again loading State Etc so let's say rafc and delete this part so we have the alluding state by default or the initial value will be false and then we will have let's say const conversations and then set conversations we'll say and that's going to be an empty array for now and then inside the use effect so this will immediately run and send a fet request and this will run only once that's why we just put this as an empty dependency array and then inside here let's create a function const get conversations that's going to be an async function and then here we will just have a try catch and even before we try let's say set loading to be true so that we could show a loading spinner and in the try we'll say const press and we'll just send a fetch request to our endpoint so it was SL API um slash users and that's going to be a get request so we don't need to put any uh options then we'll get the data pr. Json and we'll say if there is any errors just throw it so that we could um so that we could just catch it in our catch block so we just say toast. eror and error. message and finally we'll say set loading to be false and here we'll just say set this state to be the data and we need to call this function so that we could execute this code and I think that's going to be it for this hook we'll just return the loading State as well as the conversations now let's go here U import this one and you'll get the loading State as well as the conversations now if we just console log it and let's just say conversations and let's try to see that in console if you just refresh now we have the conversations so we have eight users in our database right in total we have eight users but we got only seven it's because it is not it is uh excluding the current authenticated user so we just see every single user in this array but not ourselves and we would like to now show their full name as well as their profile pick on this left hand side so let's go and do it and also we have this loading state for a second and for this we could show some loading spinner so I will delete this part for now and I will say actually I'll just copy and paste it so I will just say if it is loading show this loading spinner for a second but if it is not loading then just return null and here we'll just say conversations that should be a lowercased do map get each conversation and for all of them return this conversation component that we had so we need to pass a key so key conversation. ID so this key has to be unique that's why if we just pass the ID that's going to be unique for each conversation and then we would like to just send the conversation itself which is going to be this object I mean yeah it's going to be this object where we have the full name gender and profile pick as well as the username and then we could go and just say something like we would like to show some Emoji for all of them that's going to be autogenerated and I just wanted to add this so that this application look looks a bit uh fun or exciting whatever you want to call it and for this I have created a function so let's go inside the source and create a folder called UTS and inside this UTS I'll just say file called emojis JS and now if we just paste this you can grab this from gab repo so we have about 55 or 50 emojis um so they are generated by chat GPT and this B basically gets you a random Emoji uh depending on this random function so you could save this one and then we'll just send an emoji and we could call that function now so we'll say return an emoji for each conversation and just say get random Emoji that's going to give us um a random emoji and we also need to uh return something called last index and the reason is now I'll show you in a second so let's say let's get the index so if index is equal to the conversations. length minus one that means this is the last index and the reason is that we're using this last index if you carefully take a look at here we have this divider after each conversation but not the last one so for this we will check if this is the last index we are not going to show that divider and T reason we have it now let's go into the conversation and just take this props so we will save this file and let's close everything to the right and we'll open up this conversation now we would like to get those uh props which was the conversation and I think the last index as well as the Emoji and here we'll just return that emoji that was the prop that we have and for the full name we'll just say conversation. full name and then we will update the profile pick so I will delete this source and that's going to be the conversation. profile pick and that was not URL but that's how we call it in our back end and then at the very end I will just wrap this so I'll just cut this for a second and I'll say if it is not last index only then show this part so if it is not last index and I will paste it okay it is this thing that we have which was that divider and if we save now hopefully every everything should work fine and here we can see we have John Bob Jane just every user and we even have this um sort of scroll bar when they just overflows and we got uh random emojis for each of them and now we have this online status even though that's not correct but we will fix it when we implement the socet and now what I want to add is when I click to this I would like to have this background as this color and for this we could use our state that we just created so let's go here um that was the use conversation that is coming from our zo stand folder and now here is how we can extract values so we'll just say const and select it conversation and set selected conversation so these are these values that we have in this file so selected Conversation Set function of it and messages set messages these are the values that we can get and now we will basically just check so let's say const is selected and we will say if the selected conversation ID is equal to the current conversation ID then this is going to be true and if this is true we will just update the background color so for this we'll just go into this St I will first make this back text and we need to add Cur braces then make this back text and then just make it just close the Cur braces and then people will here just say if this is selected I'll say dollar sign if it is selected then add the class where it's going to be BG Sky of 500 but if it is not selected then just leave um just skip that class and if we save this now hopefully that's going to work but how are we going to make it selected because currently this is empty right by default that value is null we need to somehow call this function and we will be calling this when we collected this div so we'll say on collect um we'll just call the selected conversation uh method the setter function and just pass the conversation now let's save this and we'll understand that in a second now if I collect this then this function will run and it is going to set this conversation to be this one and then this will be true because the selected conversation ID will be equal to this conversation ID and it is going to give us this background of Skye 500 and now if I collect this this has been selected if I collect this it's is going to switch and it is just working as expected so now what we would like to do uh when there is a selected conversation we would like to change this view where we'll like to fetch our messages between us and this user so whoever the selected user that is going to fetch the messages between us so let's try to do it and hopefully now you see the advantage of using this Global state in any file we just call this hook and we're able to use any values that we'd like to have so we don't really need to pass this as a props in different components so whatever you want to use it we just call this hook and just get the values and now let's try to fetch messages so before we try to fetch messages actually let's go into the message container component that we have so it is going to be this one where for now we are just uh having this hardcoded value but instead we will use our Global state that we had so we will say use conversation that is coming from zent folder that we had and then that's going to give us the selected conversation as well as the setter function now instead of this hardcoded value we'll just say if there is not selected conversation then show this uh placeholder component that we had but if it is not the case then just show this um this part of the file so let's save and let's go here now there is selected conversation that's why we see this see this part now I'll refresh now there is no selected conversation we see this component if I select one it is going to update and if I select this one here we see that um this part doesn't change so let's update it instead of this hardcoded value you'll just say um let's close the Cur braces and we just say selected conversation. full name and now if we save it hopefully it's going to work so now is Bob is selected John is Jane is selected Daisy John and it just uh changed depending on that state now we have one problem so when I log out I would like to this state um just to reset and now it doesn't so now Jack is selected and if I log out and if I log back in Jack is still selected and I want to fix it I just want to reset it when this component unmounts and unmounting means basically when this component no longer is in the is in the browser so no longer it is in the view so we'll say use effect and and let's initialize it now in order to have this uh unmount state or to use it we use this return function and this is called as cleanup function so I'll just say set selected conversation to be null on cleanup so and I'll just put a comment that says unmounts and let's have this set selected conversation and now if we save that's going to fix it now John or let's say Jane is selected I log out now this will run because component unmounted right it is not in the view so this function run and now our selected conversation is null and if we try to log back in we are not going to see that so state has been reseted so we see this part and now what we'd like to do is add this functionality where we can add send messages and for this I will create one hook so let's say use send message. and then we will be calling this inside the message input component so first let's close these maybe the sidebar login and the conversations we will open up the input so message input and when we submit this we're going to call uh the function that we'll have in this file so here we're going to have again the loading State loading set loading and let's get the use State and then we'll like to use that uh zent um the global State use conversation and we would like to get a couple of different values so we we would like to get the messages set messages Setter function and then the selected conversation now we'll be using all of them in this file so we're going to have this function called send message it's going to be an Asing function and now this is going to take the message as an argument so we will um when we call this function inside our message input we will add this input value which which is going to be our message and we're just grabbing it here so we'll say try C catch and finally as always Now set loading will be true and the finally that's going to be false in the catch to. error message and then in the try we will actually try to call our endpoint so cost R A8 Fetch and our endpoint was let's open up back Texs because that's going to be some Dynamic value so it was SL API slm messages and slash sent if you remember and then we need to pass an ID here and that ID will be the selected conversation ID which is the user ID so whatever we select here it is going to give us the selected conversation and inside that state we had the user ID and that's what we'll be calling so we will say selected conversation doore a then this is going to be the post method so method will be Post in headers application Json and then body will be this message where we just stringify it and that's going to be it we will say const data and just extract it and if there is data. error as always we'll just throw that and we'll catch it under this uh inside the catch block but otherwise we'll just say set messages and here this is how we would use it so inside the use conversation this was accepting messages the new state and we will just pass it and that's going to update our state so we will have all the previous messages and then we will just add the new message which is this data and or data so that's going to be it I think we under this file we'll just say return send message function in the loading State and I have a typo here and with this I think that should be completed let's go here and just try to consume this function so form we will say on submit we'll like to call the handle submit function that will create and let's create it and let's say event. prevent default we' like to have one state let's say message set message and we will bind it to this input so value and on change then we will like to call our hook that's going to give us the values so const give us the loading and send message function this is going to be an async function and let's say first let's just say if this input is empty so user shouldn't be able to just U leave it empty and then just Spam messages so we're not going to um allow it so we'll say if there is not message then just return don't run this function so but if there is message let's say a wait send message call this function with the um input message and if this is successfully completed then set message to the empty string again and we would like to use the loading State again we could go into this button and here I think I'll just copy and paste it so we say if it is loading show this loading spinner but else show the um this icon let's save and test it out and it's going to work now so I would like to send a message to John I will say hello John it's me from or let's just say hello hello from client and if I send it now we have the loading State and now it has been successfully completed let's just double check it inside the messages in our database we said hello from client and it has just been sent and now I hope it is really clear that our code base is super clean where we just have a function that does everything for us and our code is really readable so we say when we submit when we submit this form call this handle submit where it is going to just send the message for us and if it is successfully completed then we will set this state to be empty and that's the beauty of hooks that's why we always use it in our projects and now the other hook that You' like to add will be getting messages so use get messages. JS and we'll add our logic now so RFC and and then I'll just do the boiler plate thing that we always do so we have the loading State and now again we will We would like to use the messages but this time it is going to be coming from use conversation and let's get those values it is going to be the messages set messages and then selected conversation so I think we just did the exact same thing in this file right because we used all those uh values and now we will have not a function but this time we'll have a use effect because this should immediately run when we call this hook so here we'll just say a function con get messages let's say it's going to be async and then try catch and let's sa a finally and then we would like to say set loading to be true and set loading will be false to. error error. message and in the try let's just say const as await fetch so it's going to be API messages and we didn't have the get but it was just the ID so do you remember how we have it so API SL messages slash the ID to get the messages and this ID was the user that would like to fetch our messages so we'll just say let's close this close this one and then so that's going to be the selected conversation doore ID and this is a get method so we don't need to add any options so clost data a wait R Json and if there is any errors we'll just throw that and catch it in the catch blog but other otherwise we'll just say set messages to be this um data and then let's call this function but we will only call this if there is a selected conversation so if selected conversation doore a and since this can be null let's put a question mark so that our application doesn't break and then we will just go and say selected conversation doore ID whenever this selected conversation ID changes run this use effect and this want us to add the set messages and this is never going to change but it still wants it so lastly at the end of this file we'll just say return the messages as well as the loading State and now we could save this file and let's close this we're going to go into the let's say message container we had and inside we have the messages so it's going to be this component component where we will call our hook so let's say const and just get the use get messages now that's going to return us the messages as well as the loading State and before we do anything let's just console log the messages so let's say console log messages and we could say something like messages and then let's just save it let's go I will re refresh this page open up my console now we don't have anything but if we collect this now we have one message that we sent from client now I'll say hello John I'll just send the sanket message and let's send another one now do you see how it has been updated immediately here we can see hello John to and then let's send another one and then let's say hello John 4 now let's refresh refesh this page again here we can see we got all of the messages and now we'll like to just render them so let's go into the messages and here instead of returning these let's delete them and now we have the loading State and for this we would like to show a loading skeleton so when it is in the loading State we could have this kind of loading skeleton and for this we could check the the UI where they have the skeleton and that's basically the component that we have you could copy the code and paste it but I already prepared one for you so you can grab that from Thea preo and I will go and just create that component so I will say skeletons and I'll say message skeleton. jsx and I'll just paste that file so now I will paste it and we will try to consume it inside this file so we'll say if it is loading then we are going to call this skeleton file three times so I think I could copy that line and just paste it so here we just say if it is loading three times just so this is basically three four Loops just map this message skeleton and now if we save let's refresh let's see the output let's refresh this page if I clict that we have 1 second of that loading State and we see that three times it's because so this one and this one is in that file and we render this three times so that we got one two and then three so that's the gist of it then we could also show something like if it is not loading and there is not any messages we will just say send them message to start the conversation so it is going to be just like this where we select the Felix we don't have any messages so in this chat we don't have any messages so we just show send a message to start the conversation and for this again I will copy one line and just paste it so we say if it is not loading and there is not any messages so just show this paragraph and let's save and if we click to this now it says send a message to start the conversation and again we have one second of loading State and then it says send a message to start the conversation now um other side I mean other than these if checks we are going to render our messages so I think I could copy and paste it or let's just type it out okay so after the loading or maybe before them okay we have the alloing states in this edge cases it will say if it is not loading and messages length is greater than zero then we'll just return our messages so we'll say but first we need to say messages. map and okay sorry about that that should be something like this messages. map and get each message this co-pilot can get a bit annoying so we will return a message component let's get this we're going to have a key as well as the message itself and we're going to go into the message component and just take it as a prop and just render it now so we will get the message so we will check if this message is from us or from the other user and for this we can use our oath state so that's going to be from that's going to be coming from use o context and let's say oath user and then inside so that was the authenticated user we were getting from the context I just wanted to mention now we will say also get the use conversation that was the Z uh state so let's say selected conversation and now we'll just check if this message is from me so const from me so we will say um so this going to be equal to if message. sender ID is equal to the oath user uncore ID and if we check the console here we can see inside each message we have that field called sender ID receiver ID and that's because we have populated this when we were building the backend part I hope you guys remember that and now we have the from me this is going to be true if this condition is correct now we will add one class name that is either going to be so it's going to be like this so it is going to be either in the chat start or end and we will check it depending on this class so let's say const so chat class name and we'll just say if it is from me then it is going to be chat end but if it is not from me then it's going to be chat start and then we will show the profile pick but again that's going to be dynamic so if message is from me then we're going to show our profile picture but otherwise the other user profile picture so we could say const profile pick and we will say if it is from me then o user. profile pick but otherwise we will just say selected conversation. profile pick and let's just put this optional chaining and then what should we add next we are going to add the background color so if the message is from us we're going to show this blue color so let's say bubble BG color so it is from me then I'll just show background below 500 but otherwise it is not going to have any any background color and we're getting to the end and lastly now we will fix this timing and I think I'll do that in a second but for now we could just add everything step by step so instead of this chat end value let's make it Dynamic I will delete this part open up Cur braces back Tex that was chat and then this part will be dynamic where we have the chat class name and then for the image source we will delete this part and we'll just say it is going to going to be this profile pick so let's delete this part format it and then for this chat bubble um we will add this let's see it's going to be this bubble BG color so again Dynamic value paste it and then we have this value as the message content and that's going to be message. message and again if we just check it from the console here we can see um so sender ID receiver ID and then we have the message that is the message content and that's same for each message okay we're going to get that and we are just returning that inside here and I think that's going to be it for now let's save and hopefully that's going to work fine so these are all of our messages let's send another and here we can see it is also here and now let's log in as John and let's try to send message to this user let's say joho and that was our password oh okay so I think our password is wrong I'll just do it again okay we cannot log in maybe that username is not correct let's see um inside the users we had the jandoo and for some reason it doesn't take us to inside so jandoo H that's strange so it says invalid username or password and it's maybe because we didn't hash this and now we are trying to compare this by hashing okay so if we try to log in as Bob now that's going to work so it is currently we're having a a problem uh while trying to log in is because we didn't hash this password and now we are trying to compare a hash with a non-h hased password and that's the reason so I'll log in as Bob and here we have logged in let's send message to this user hey okay so we have all of our messages and let's go back into this account and that was Bob Bob now we'll say hello oh okay so we have still the same background color but we'll fix it okay so why that is we say chat class name uh okay it is this one bubble PG color or we need to just delete it okay if we delete this one now it is going to be dynamic okay so if it is from us we see this color but otherwise we see this color and now if we try to just render this time let's go and delete this one if we say something like message. created at field that's going to look a bit ugly and it's because this is how mongodb stores our data or they create that field and for this we could create a function called extract time so I will go into the U tails and create that file extract time.js and I will provide this function to you so basically copy it and paste it from the G preo and that's going to be it I just got this from chat gbt so you just call this function with the uh mongodb date string and it returns you in this format hours and minutes now we will go into our message and here let's just say formatted date formatted time let's say and then we'll call the extract time and message. created that and now this has been formatted and we will just return this value and if we save now here we can see this is the time that message has been sent it is 400 a.m. in the morning yeah we're still recording but um yeah that's going to be it okay so we have this problem now um so let's send some messages okay we already have now I'll just send a couple of more now here when we send a message it doesn't scroll for us till the very end or when we um select this chat it should scroll us uh automatically until the end and we can do this by using use effect now we will go into the messages component so here let's just delete this comment and we will say use effect now here we would like to have a reference so let's say con last message ref and we'll just say use ref and call it by default it could be null so here instead of returning the message immediately let's return actually a div so that we could put that ref into it so you will understand in a second now I will send this message inside and instead of passing the key into the message we'll just pass it to the div and we will just say last or the ra will be just last message ref and so since this has been added to each message we could do something like last message dot last message ra. current scroll into view and behavior should be smooth and if we save now and it's going to automatically just scroll for us till the very end um it didn't work work is because sometimes it is because of the rendering timing and I'll just cut this if we put it into a set timeout this is the solution that I came up with and that's I think something common so we'll just put something like 100 milliseconds or maybe 50 milliseconds we'll just delay this and that should hopefully work now let's go here if we click that okay it still didn't work out let's see see why that is so we will say whenever the messages changes run this use effect and let's do it now okay it Scrolls for us and what happens if we delete this set timeout is it still going to work so it doesn't that's why that set time out is actually needed and now it actually works for us and even if we sent another one that's going to scroll for us till the very end but now we can't really see the sent date of this message and we could fix it by adding some padding so into the message let's say padding bottom of one or maybe two how that's going to look like okay now that just fix it and we are able to see the latest messages time and now let's not forget the search functionality for this we're going to go into the search input component and here we have an input so let's create a state for this so that could be search and we will import the use state so let's just bind it value will be search and on change we'll just update this state and then we'll like to have an onsubmit event so handle submit function so I'll copy this and create it I'll just say event. prevent default and here we're going to be using the zent global state so cons that was used conversation and we're going to get the set selected conversation and we'll see why and also we would like to get the use get conversations and you'll just get all of them so cost we'll say conversations so when we submit this form first let's just check if there is not search then we could just return we will not do anything and we'll say if search. length is less than three then we could say toast. error and we'll do something like search term must be at least three characters long and let's import this and return turn out of this function after we show the toast and but if it is was if it was successful then we will try to find this conversation so if I search something like John then I would like to find John in this chat and the first one that match I would like to select it and for this we could use a search algorithm that is super basic so let's say const conversation we're going to go and find inside the entire conversations array so conversations. find get to each conversation and each conversation had a full name value right so we're going to say full name and just lowercase it and um the reason that we are lowercasing it is because let's say if we search something like John but this part is uppercased but this one is lowercased then this is not going to match with this one and that's why we just make this entirely lowercased and also we lowercase this one so that they match so that's going to be something like J do if we even if we type it like this oops so if we type it like this our code will make it to look like this and then it is going to do the exact same thing for this one and it's is going to compare them so that's the idea I hope I could I explain this uh clearly and then let's say if it includes the search case and we're just going to lowercase that as well so that they're going to match and then lastly will say if there is conversation we will update our state so set selected conversation to this one and we could update the search with an empty string but else case we'll just say to. error and no such user f and let's test it out now we're going to go here and if we just put something like less than three characters it's going to give us this error and if we just put something that is not in our database it's going to say no site user found but if we search for something like test account and search it it's going to update it and select this conversation for us and let's select Daisy and it's going to get us this one and it's just going to work for for each user and that wraps our search functionality so with this we have completed this part as well I will commit the changes and in the next part we will add a psych Dio into our application and that's going to be for realtime events so I will see you in the next section okay now in this section we would like to add psyo into our application so this is the current state what we have we had an Express server that is connected to our database which is mongodb and then we had different users in our application now if this user currently wants to send a message to his friend what is going to happen is that he is going to send a request to our server and we will take that message and send it to the database but we are not going to send that message back to this user if this user wants to see that message he just needs to refresh his page but this is not optimal and this is not real time and to be able to fix this we will add another server on which is going to be pyit server and we will just add it on top of our Express server now in this way we will be able to just send the message to our server it is going to save it to the database and then just immediately it is going to send send it back to this user and now this user didn't need to refresh his page and this communication is now just real time and this is possible just because of the psycho Library so now that we know the workflow let's just try to implement that okay so this is where we left our application we had some changes and I have committed them now now we'll like to create a sucket server that's going to be inside the backend folder so we'll have this sucket and then we'll have a file called pit. JS and at the beginning of this course we have installed this package which is pit. and it is time to use it now we'll get the server from this package let's say server from psycho and then we will get the HTTP from HTTP which is a nodejs built-in njs module and then and we'll get the express from Express and the reason that we have this Express we will actually delete it from here and create here okay and then we'll say export this app and we will just import it so get this from the psych. JS file and I think we'll understand the reason in a second now we have this Express app we would like to have a server that is going to be an http server and we will pass this Express app into it and then we will have IO that's going to be new server and we will pass our server into it now what we see here is basically we have done this so we had the express server and on top of it we have added the psych server so that's how we would do it and from this file we will export the io and server now socket gives us some course errors that's why we could go here and just say course and that's going to be an object we'll just say origin we could put an array and the first value could be our front end application and for the methods we could say that's going to be get and post and here we could listen for connections and this is how you would do it in socket so io. on connection we're going to get a callback which is Socket so this is going to be the user that is connected and this socket has ID and different prop properties but most of the time you use ID so we will say console log a user connected and we could maybe show the pyet ID next to it and then how are we going to check for disconnections we could use s.on and we'll say disconnect we'll just console log a user disconnected and we could show the psyit ID and so here I'll just put a comment so here is the comment py. on method is used to listen to the events and this can be used both on client and on the server side so we'll be using the py. on on our front end as well in the incoming minutes now that's going to be our minimal setup at least for now we could save this so here we're listening for connections and we just console log it in our server and same thing goes for disc connections so we are going to go here and we need to just uh update this with the server that we have created so we have the app and server that is coming from this file and that's going to be it for our back end at least for now so let's do this setup for our front end we will have inside the source inside the hooks I'm sorry inside the context we will have socket context. jsx file and here we'll create that socket context now let's try to create it so we'll say export const socket cont context and we will call this that is coming from react we don't can we cannot get um Auto Imports so let's say create context from react and then we'll say export con we need to just create a provider so I'll say sucket context provider and that's going to take the children and we'll like to just return the psyched context provider the value could be empty for now and inside we will just put our ch children so here we'll say children and now let's save this file we're going to go into the main. jsx and wrap our application with pyit context provider and we'll put our put the app inside now let's save this file and we're going to go here and we'll have a couple of States so con socket set socket and that's going to be our socket connection and we'll like to import use state so use State as well as the use effect so by default our connection is null and you would like to have the online users that's something that we'll be looking in a second and then I think we could now initialize the user effect so here we need to install another package so let's go into the front end so inside the root CD into the front end and you like to install a package called p-c Cent now we have used this psyed IO for backend this is the backend package and this is for client um so that we could have some communication to our socket server now inside the use effect let's get the first oath user from our use oath context and inside use effect we will say if there is an authenticated user then you would like to create a connection so say pyet you'll like to get the io method so import iio from py iio client and then we would like to pass our backend URL which is Local Host uh 5000 Port now we're going to have an object but for now we could skip that and we will say set this socket so once this connection completed set this socket state to this connection and then what we can do um in the else case if there is not authenticated users I mean if this is empty then we'll hit the else check and we'll like to close the existing pyc connection so we could say if there is a pyc connection then we just want to py. close and then set this state to be null and for performance reasons we could also say return so that's going to be our cleanup function I'll just say py. close and this will will close the pyet connection when the component is unmounted so with this I think we could save now and hopefully it should work so we'll like to here pass the socket as well as the online users and we'll be using those values later in our application now let's save and in our back end in the console we cannot see anything for now let's try to log in now I am logged in as Bob and here in the console we cannot see anything let's refresh now here it says a user connected and this is the psyched ID that we have now how are we going to get the online user status um for this inside our back end we're going to have an object so let's say const user socket map and that's going to be an object where we will have the user ID as being the key and then p ID will be the value so I'll just put this as a comment now when we logged in we would like to take the user ID and for this we could send it as an argument so here we'll say query we'll like to have the user ID that's going to be authenticated users ID and to be able to get this ID let's first save this file we're going to go into the pyet and here we'll just say const user ID where we could say cy. handshake do query and do user ID so we got into the query and got the user ID now so we'll say if this user ID is not equal to undefined value then we would like to just set it into this user pyed map so I will say user pyed map user ID will be equal to this py. ID and since we update this user socket map we would like to send an event to all connected clients so for this we'll be using io. emit so again I'll just put a comment here so here is my comment io. emit is used to send events to all connected clients so we could give any name here I'll just say get online users and we will just pass this object. keys of this user socket map so whenever a user connects it will will immediately send this um who is online and who is offline and we can grab it with this event name so that's going to be it for now and let's do the same thing when a user disconnects so once we disconnect we will just delete this user ID from the user pyet map and since we updated this now we would like to again call this io. Emit and so I will just copy this line and then paste it so again since because we um disconnected we delete that from the socket map and this has been updated now we would like to send it to the all clients so we call i.it with this event name so we'll be using this event name to get the online users in the client so here I'll just save this file and we will say once we connect it we would like to see who is online and who is not so we will say PSY it.on and we'll just say get online users now this is going to return us the users and we'll just say set online users to the to these users and here we can see now Psy it.on can be used both in the client and on the server and it is used to listen to the events just like we said here so I will copy this command and paste it to here as well just because so just in case if you want to have it so now with this setup we are able to use the online users in our application and we can just show it in our sidebar so here let's go and create a hook so that we could consume this just like we did um right here so I will copy this and just paste it here I'll say export const use pcket context and we'll say use context it is coming from react and then we will pass this pych context into it and we could delete this export so what we have done here is basically the same thing that we do here so we have created the context and then to be able to uh consume it we created this hook which calls the use context Hook from react now in order to see this online status we're going to go into the conversation component so let's say conversation. jsx and here we will get the online users let's say const online users from use socket context and we could have this const is online variable where we'll just say online users if it includes the conversation doore ID so if this is the case then it means this user is online and we could use this value to show this online status so I will put C Braes back Tex and again back Tex Cur Braes I will delete this online and I'll say if is online we would like to add the online class but else we don't want to add add it so let's save hopefully that's going to work so now no one is online here we can see and here this value is wrong let's fix it so that was inside the message container I believe okay so here if there is no chat selected we just put this hardcoded value but you'll like the update it with oath contexts value right so I'll just say oath user and we will just show the full name so o user. full name if we save now it's going to say welcome Bob do and I'll just open up a new tab so that's going to be in incal mode mode let's visit this login page and I'll just shrink this a bit and here I'll just log in as Jane So Jane do and the password was from 1 to six and if we now log in okay so it didn't work so let's see I think we're missing something um so let's close this first so we had the pyet context once we connected we got the online users and oh okay we didn't update here so just say oath user whenever this changes run this use effect so that was the only part that you were missing now let's save and let's try to do it again and it's already updated but I just want to see that from scratch now I will log out from this account this is Jane if I click to that now Jane is offline and the reason is inside our py. JS this this function has run and then we deleted that from our soet map and we just send it to every client and that's why we cannot see that online status so if we just log in again so this time I'll just log in as Daisy if I click the login that's going to update immediately and here we can see Bob is also online if I just uh log out from this account so I'll just log out and here we can see B is not online anymore so now that we have the online users um functionality out of the way we would like to add the next thing which is going to be um so real time messages for this let's go into our back end and specifically for the socket. JS we are going to add a function so maybe just above here let's say const and Export it because we'll be using it in a controller so we'll say get receiver pyet ID and here we will pass a receiver ID that's going to be the user ID and that's going to give us the psyched ID of that user and we'll see why now let's say return uh from this map um the psych ID so that's going to give us the user psych ID when we pass this receiver ID okay so we're going to save this file and we're going to go into the message controller now so when we sent the message message that was inside this function and we said that we will add psycho functionality into here and now it is time to do it and actually let's take all this into here and we'll add the psyo here so we take the message save it into our database and as well as the conversation here we can see now that the message is in the database let's save it uh let's send it to the other user and for this we can use a method but first let's let's get the receiver pyed ID so I'll say const receiver psyched ID and we will call this function so get receiver psyched ID and this will be the receiver ID so we will say if this user is online so we'll say if receiver psyched ID if it is not undefined we'll hit this if check and IO do instead of emit we will use io. 2 and then and then we'll use emit now it's because we only want to send this send the event to this user so we'll say a.2 receiver py id. Emit and we could have this new message event and you will send the new message so I'll just put a comment here so here is the comment a.2 so this soet id. image this method is used to send events to specific client so it is not like this io. emit where we just send it to every user but in in that only to one specific client now with that this is going to be it for um pyit message functionality we take the message save it to our database and then just send it to this user with this uh new message event name and now it is time to catch it in our client so I will create a hook for this let's first save this file and we could close all these and Shing this we're going to go into the hooks and I will create this as use listen messages. JS and now it is time to just create this hook so again ource as we do always and instead of returning this actually I think we are not going to return anything it's because we will be listening for messages so we would like to get the socket from our context so let's say use socket context and that was returning the online users as well as the pyet and we'll take this value and we'll say const get the messages as well as the set messages function from use conversation that was the Z and uh Global state that we have now inside use effect we will just listen for it so when we say we would like to listen for for an event the only thing that I can think of is s.on Method and let's import this use effect from react and I'll just put it at the top okay so we want to listen for events and as we said before we would like to use socket. on method and just in case this is empty let's put a question mark so that our so that our application doesn't crash so we are going to be listening for new message event and we will take the new message as an argument inside this callback now we'll be doing a couple of things here uh for now let's just say set messages we will add all previous messages and then new message going to be at the end now here um under this we'll say return We would like to just inside this cleanup function we will say socket. off this new message event so when this component unmounts we don't really want to listen for this and this is something really necessary that you need to add and I will explain that in a second so here we need to add the socket the set messages as well as the messages and if we just call this hook inside the I think messages okay so we'll just call this hook use listen messages now this will basically listen for any incoming messages from the pyet let's save and let's test it out now I will go here and just log in as Bob and then I will open up a new tab and I will log in as Jane from here okay now Jane and Bob are online and let me just put this tab side by side now I will select this conversation and select this one now from here Bob will say hey Jane and now if we send it here we can see it is immediately being shown here it's because we are listening for messages and I'll just say hey Bob and here we can see it is immediately has been shown it's because we are listening for messages inside this use effect and now what I would like to do when there is a new message so when there is a new message I'll just say hey so I would like this message to just shake a little bit and for this will add a shake class and that's going to have some animation in CSS so for this we'll just add one class and one animation in our index.css file so open up the index. CSS file and just paste this value or this classes that you can get from the GitHub repo we have a shake class that is Shake animation on horizontal Direction and this is something that again you can just get it from chat GPT and we'll we're going to save this file and we will say inside this use um listen messages so once there is a new message we will like to say this message should shake so new message. should shake will be equal to true and then in our message component we will add a class we'll say const should shake actually let's say shake class and we will say if message should shake then we will add this shake class but else we will not add it so we'll just skip that and this is something that we only add for incoming messages so real time messages we add this shake class and inside this chat bubble here we could just say so dollar sign Cur Braes at the shake class now let's save this and test it out so here I'll just send another message hey and if I send it now here we can see we have this shake animation that is going on and if we send from here it is going to be here message will be here and here it just shakes and I think this looks a lot cleaner and the very last thing that we'd like to do is just play a sound that's going to be notification sound and for this again I will provide you a file that you can grab from GitHub preo so inside the assets I will will create a folder called sounds and here I'll just drag and drop that file so I have added the sound I don't know if you can hear it but that's going to be this sound that's classic um iOS notification sound and here now we like to play it once we have the message so that's going to be inside this hook we got the message we add the shake class and just before we update this state and we could just say const sound and we will click to import it now I'll just say import I'll say notification sound from is this correct okay we can go into the assets inside the sounds and then notification MP3 and we'll just import this now here we'll just say new audio and we'll just pass the notification sound into it and we'll just say sound sound. playay and that's going to play this sound once there is a new message so we could save and let's test that now so here I'll just say hello chain and here we can see we can hear the sound so hey and that's immediate as well so whatever we just sent both it Shakes as well as we can hear that sound so now here I just want to mention something if you don't really add this line what is going to happen is that there is going to be a lot of this um event that has been listening from our socket and whenever you send a new message so you will hear that notification sound multiple times so it'll be multiplied by the number of listeners that you have that's why inside the cleanup we actually remove it so here this line is really important so that you are not listening for this event more than than once and now with this I think we have completed our entire application so we could save and I would like to just commit all these changes and then we'll go into the deployment part so in case you want to see the commit workflow so here I'll just add everything to this staging area so here are all the changes that we have and I will add it and then we would like to just add oops so I'll just add all of them so stage all changes okay now all of them are in this staging area and what you see m is modified files and the a that you see they are added so we're going to go here and I'll just put my commit message so I'll just say something like fourth part completed and I'll just say sck it now let's Commit This and we will now try to deploy this app so now in this section we would like to deploy our application but we cannot just go ahead and drag and drop this files to the server that's not going to work we need to set this up so so we're going to go into the back end where we have this server.js and here we need to do a couple of things now we're going to get a variable let's say concore uncore de name and we'll say path. resolve and this path is going to be coming from node.js let's import it now we'll say import path from path and I'll just put it at the top now after our routes we would like to have a middleware so let's say app.use we'll say express. static so this is a static middleware that Express gives us and this basically is used to serve static files such as HTML CSS JavaScript uh image files sounds files that we had in our front end application and we'll be using this so let's say path. join and what this does that it gives us the um the absolute path to the root folder so we'll be using it so let's say path. join uncore uncore their name and we are going to join this with the front end folder that we have so we'll say slash front end oops so front end slash this and now what is going on here is that we will go into this de name which is the root okay and then slash front end okay now we are inside this and and we are going to go into the this folder but we don't really have it and this will be something when we try to build this front end application and that will be done in the server when we deploy this application so now if we go into the front end so see the front end and if we say something like mpm Brun built V will build this front and application for us and it'll just put everything into this disc folder and when we deploy our application we typically build and bundle our front end code for optimization and performance reasons so this will be put into the this folder and we just use this um Express static middleware so that this will be served as static files and then we will say any routes that that is other than these so we will say app.get so we'll put a wild card and we will say we'll take have this request and response so we we're going to have this call back function so we'll say rest. send file and we will send this index HTML that we have in the front end folder so let's say path. join again underscore their name so that's going to be double underscore their name and then we could just have it as separated so we're going to go into the front end and then we're going to go into the dist and then we will have this index.html so now with this we are able to run our front end from our server as well now let's save this file and I think we'll understand what all this means in a second we could delete this now and we would like to go into the package Json we would like to add a script so let's say put a comment first we'll have a start script that that's going to be node backend server.js and then we would like to have another script that's going to be building our application so first we'll like to use mpm install so that's going to install every package that is Need for our back end because this is being running on the rout so that's going to take a look at the package Json file and then we'll say end you'll say npm install but this time for front end and here we we could do something like CD into the front end and then run mpm install but instead we can say-- prefix front end folder so this says go into the front end folder and run this mpm installed and then once this has been completed now we'll like to build our front end application so mpm run build and we'll like to run this again inside this folder so we'll say prefix front end and now if we save this and let's just try to build our application now so I'll say CD into the root and we'll say mpm run buildt now this is going to install every package for our backend for front end and it's going to build our front end application now we already have these packages in our uh workspace but uh when we deploy deoy our code we are not going to have these node modules in the server so we need to First install them and then build our application and now everything looks like has been completed successfully if we go into the front end folder here we can see there is this this folder has been created and it has this index. HTML and that's going to be having our JavaScript code in the bundle now if we say mpm I think it was start right mpm start oops so from here mpm start and now we could visit our server let's go and test it out so now if you visit a local host 3000 it is not going to work because our client is not running on this port anymore it is running on 5,000 so both our client and server now is running on this port and the reason is here in the server.js file we said that any route that are accept from these can you just render the index. HTML that is under this front end and this folder and that's what is going to happen in our back end as well so now we could still log in I'll say Bobo from 1 to 6 so we could still log in send our fetch request send messages online status and every Real Time Communication works and now the difference is we are able to connect our front-end application from our server just because of that Express static middleware and that path now with that in mind we can go ahead and try to deploy this app and for this we'll be using render so go into the just put my latest um changes I'll just say get add all and get commit dasm and I'll say deployment and now I would like to copy this line and I'll just paste it into my terminal so I'll just paste it and that's going to push my code to my GitHub repo so now I just refresh this and here is our code and we would like to uh just deploy this so this is the one that I have deployed for demo purposes now I will create a new one web service and we will say build and deploy from a git repo let's say next and here you need to connect to your uh GitHub account so here it says um M chat app I'll say connect and for this I'll just say chat app production and and or maybe I'll just say YouTube then here this is my Branch name which is Master in your case that could be main so don't uh touch it just leave it as it is now the build command that we had was mpm run buildt and then start comand was mpm Run start or mpm start that's the same thing now we could use the free tier um the only problem is so it three instances spin down after periods of inactivity and that means for the first time when you visit your app that's going to be a bit slow but that's okay as long as it is free for site projects now we don't need to forget our environment variables and we're going to go and take all of them one by one so here I will take these environment variables and just paste them one by one so here I'll just take the JWT secret and pass it as a key and then now we'll add the value so I will copy the value and then again come back to here paste it and you like to add another one so that's going to be mongodb I will copy it paste it and then we are going to grab the value and then just paste it and lastly we would like to get the port and that's going to be 5,000 and here um okay so the last one is going to be node EMV so where did we use this okay so when we use this generate token we said that's going to be secure if it is not development so we would like to just make it as production so here I'll just say it was nodecore EMV so not EMV and I'll say that's going to be product ction and now let's make this bigger and let's say create web service so deployment has been started now I think that's going to take about one or two minutes and once this done I'll be right back so I got an error for some reason that says beat not found and build failed I'll just try to manual deploy this again so I'll say deploy latest commit so it failed again and I think the reason is if we go under this environment is because of this not EMV is equal to production so for now let's just delete this and since this is production it doesn't install the dev dependency packages and our V is under the dev dependency that's why it it cannot find this when it tries to run this mpm build so let's try to um just deploy this again so we have deleted that not DMV field and let's say manual deploy with this latest commit again and let's see if this time is going to work or not so build was successful now it is trying to deploy this and again it's going to take a bit time so let's just wait for it and here we go now your service is live connected to mongodb and server is running on this port now let's try to visit it it's going to be on this um URL let's click that so here we have this is our application now it is live let's try to log in so now we are logged in and we can fetch the users from our database but here I think we are going to have errors on P.O so let's say I'll just open up another tab so here I just put them side by side it I will put this link from here I'll try to log in so I will go with Daisy or maybe Jano from 1 to six and now we are logged in but psych Dio is not going to work now we cannot see the online status and we will not be able to see the messages okay it is not all a real time and it is because in our code base we say that so let's go under the context so we are trying to connect to this uh route but we would like to just change it to our URL because there is not Local Host running anymore so I will take this URL from our application and then replace it here and if we just save this file we just need to uh deploy this again so I'll put a commit so I'll say get add all get commit socket URL updated and if we just get push this and hopefully render will try to just deploy this now let's go and test it out if it is going to deploy it so sometimes it doesn't do and normally it should just automatically deploy that so I will go into the here okay it's deploying as you can see here so whenever you add n it it is going to see that from your GitHub account and it's going to try to deploy that so let's wait for logs and hopefully that's going to be successfully deployed okay so I click to this events and it says deploy is live and let's again check for this I will refresh this page and I will just test them out so I put them side by side now I will Refresh on both pages and here we can see now now we have the online status and let's test it out the real time messages and here we can see here is the message and we got the notification sound and if we just send another one it it just works as expected so I think that's going to be it for this course I hope you were able to follow along until here and you were able to learn these Concepts that we have covered in this course now you could extend this chat app by adding a lot of different features such as sending images as messages and having this seen and unseen messages in just like WhatsApp and for these features I have dedicated videos on the channel feel free to check them out and if you have any questions just come and ask in our Discord server um with that being said I think I'll wrap up this video here thanks for watching and I'll see you in the next one
Info
Channel: As a Programmer
Views: 62,479
Rating: undefined out of 5
Keywords:
Id: HwCqsOis894
Channel Id: undefined
Length: 280min 30sec (16830 seconds)
Published: Wed Jan 31 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.