Build and Deploy: TWITTER clone with React, Tailwind, Next, Prisma, Mongo, NextAuth & Vercel (2023)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there my name is Antonio and in this video I'm going to show you how to create a full stack Twitter clone using the latest Technologies we're going to be using react for the front end next for routing and server side rendering Tailwind for CSS management Prisma for data management and mongodb for backend storage we will also Implement authentication using next out as well as the image upload and a fully working notification system on top of that the entire website will be fully responsive and written in typescript so whether you're a beginner or an experienced developer there's something in this video for you let's get started creating a full stack Twitter clone is an exciting project that can provide users with the ability to post tweets reply to tweets like tweets follow other users and be notified when their content is liked or replied to users can post tweets that are shown on their profile page as well as in a public feed where all users can see them they can also reply to any tweet on the public feed or on their own profile page additionally users will have the ability to like any tweet which triggers a notification sent to the creator of that tweet following other users triggers notification as well users will also be able to fully edit their name username bio and profile on cover image using file upload and those changes will be reflected in real time when users are not logged in they are able to see the tweets but special actions like following the user or liking the Tweet will trigger a login model to ensure usability across multiple devices and screens we want our website slash app to be built as responsibly as possible so that it works seamlessly on desktop computers as well as mobile devices this kind of build will require extra attention When developing but it is essential in today's world where people use multiple screens throughout the day now that we know what the website looks like let's write some code alright let's start by creating our next JS project go into your terminal and write the following command MPX create snacks Dash app dash dash typescript name your project in my case it's going to be Twitter Dash tutorial say yes for sland no for Source no for app for import Alias just press enter and it should start installing dependencies great next I'm going to go ahead and I'm going to open my newly created folder so I named it Twitter tutorial so that's what I'm going to select your project should look something like this so you should have the pages folder you should have the public folder and the Styles folder right here and you can actually go into your terminal right now and you can run npm run Dev and you should see the next JS welcome screen on localhost 3000. great now let's go ahead this project a bit go into pages and you can remove document.tsx entirely now go into index.dsx and you can remove everything except the main function and just remove everything inside the return method and we're just going to create a div element here which is going to say hello well great and you should have something like this in your browser now let's go ahead and let's uh remove this API folder hello.ts do not remove the folder we just don't need the hello file right here great and now go into Styles right here and you can remove home.module.css and go one more time in Styles in globals.css and you can just remove everything from here great next we're going to go ahead and we're going to install Tailwind so open your terminal again and run the following command npm install the HD L wind CSS host CSS Outlook prefixer great now go ahead and run npx Tailwind CSS init p you should have two new files in your project one called post css.config.js and another one tailwind.config.js you want to open tailwind.config.js right here and go into your content array and we're going to paste the following content here which is a structure for our next JS project so go ahead and write dot slash app slash Asterix Asterix slash Asterix dot open curly braces and let's write the following file extensions JS comma TS comma jsx comma PSX like that copy this three times for the second one write pages and for the last one just write components just like that and now let's go back into our Styles globals.css right here and let's just add some Tailwind directives here so write add Tailwind base at Tailwind components and add Tailwind utilities like that and just go ahead and also add the following two classes so root and just write add apply h-4 BG Dash black and repeat the same thing for body as apply H dash full BG Dash black like that and now open your terminal again and let's run the project again npm run Dev and if you refresh your page you should see a bit of a different styling just like that you actually won't be able to see the hello world because we just changed our background so go back into your pages index.psx and let's add some Styles just to confirm our Tailwind is set up correctly so go ahead and write class name text 3XL text Sky 500. great great job you have successfully set up the environment all right so in this part of the tutorial we're going to add the basic layout of our Twitter clone so go ahead and open your underscore app.tsx and wrap this component inside a layout component just wrap it like this layout and you can indent it a little bit when you save you're going to get an error because layout does not exist yet so just go into components sorry you should not have this folder so create a new folder called components right here and create a file called layout.tsx Great Name the component layout and for now just write an empty div right here go back into underscore app and let's import this from components slash layout like this if you cannot use the ad you can use the dot dot sign like this all right let's go back into layout and let's create an interface interface layout props is going to have children which is type of react dot react node like this go ahead and write react that functional component right here and let's paste this layout props right here and let's extract children from his props like this and now we're gonna paste these children inside this div like this great job now let's style this dip each batch screen BG Dash black let's create another div right here which is also going to wrap children and let's add the following class name here container H dash o mx-auto XL PX 30 and Max W 6 XL great now create another div which is also good for our children and right class name grid grid Dash calls Dash 4 H dash cool all right and now before children we are actually um sorry yeah create another div right here which is also going to wrap children and let's give it some styles all Dash span Dash three LG o dash span Dash two order Dash X curly brackets sorry square brackets one pixel and Border Dash neutral Dash 800. all right and now you can see we have this nice little grid right here all right and now Above This div right here let's add a component called sidebar and we're going to get an error because Sideburn does not exist so create a new folder inside components called layout and inside create a new file called sidebar.psx you can name it sidebar and for now it's just going to return an empty div and go back into layout and let's import the sidebar since it is in the same folder we can just use the dot right here perfect and now you can see we have the sidebar the main content are our follow bar which we will create in the future great great job now let's go into sidebar and let's create some items here so let's start by opening our terminal and let's create let's install a package so npm install react Dash icons great and make sure you run the app again all right and now inside the sidebar let's create a constant called items which is going to be an array of objects it's gonna have a label of home it's gonna have an href which is going to point to slash and it's gonna have an icon which is going to be es House Bill and we're going to import this BS house fill from react items so import BS house fill from react Dash icons slash DS perfect and now let's create another object with a label of notifications which is going to point to slash notifications and it's going to use an icon BS Bell bill great and you can import that from here as well perfect now let's create a another object right here which is going to have a label off profile the href for now is going to be slash users slash one two three the reason we will put one to three is because it needs to lead to a specific ID but for now we cannot fetch our current user ID because we have not set up the API yet so just leave it like this for now and we will come back and fix this all right and the icon is going to be a f8 user and you can import that from react icons as well but it needs to be under another path so import fa user from yak Dash icons slash f8 perfect good job all right now let's go ahead and style our sidebar actually so class name is going to be call Dash span-1 h-4 ER pr-4 and MD er-6 great open up another diving site and let's style it the following way Flex Black slash whole items dot end great and another div with the following class names Y dash 2 LG W Dash open square brackets 230 pixels like that all right and now let's create a component sidebar logo just like this and of course we're gonna have an error because sidebar logo does not exist so you guessed it let's go into components layout and create a new file called sidebar logo.dsx name it sidebar logo like this and just return an empty div for now let's go back into our sidebar and let's import sidebar logo uh just so we remove the error good good job all right now what we're going to do here is first let's import our router so const router it's going to be used router from next slash router like this all right Now open up this div and write in the following class names round that Dash pull h-14w-14b-4 blacks items Dash Center justify Dash Center power BG blue dash 300 cover BG Dash opacity-10 and cursor Dash pointer and also add transition in the end all right and inside the div we're going to import BS Twitter Chrome react icons so go ahead and import BS Twitter from react Dash icons like this react Dash icon slash vs sorry all right and let's add some properties to this so size is going to be 28 and color is going to be white great we have our icon right here great job and we're just going to add an on click to this div so on click it's going to be an arrow function which is going to say router black push like this and we can just import this about indent this sorry all right now let's go back into sidebar and we're going to create an iteration of these items array right here so just write inside curly braces items.map python which is going to return sidebar item and we're going to add some properties so we're going to add T which is item dot href you could technically use label or icon but I think href is always going to be unique then of course add href item.href table item dot label and icon item that icon like this and we're gonna get an error because sidebar item does not exist so let's go into layout and create a new file called sidebar item.dsx let's name it sidebar item and let's just create an empty div as always now let's go back to sidebar and let's import sidebar item the same way we did with sidebar logo and the error should go away now go back into sidebar item and let's create our interface so interface sidebar item props which is going to have a label which is a string is going to have an href which is optional and string is going to have an icon which is a type of Icon type and we're going to import icon type from react icons so import icon type from reacts Dash icons like this all right and we're also going to add on click which is optional and for now you can just write it like this great now let's pass this sidebar item props into a react to that functional component like this and let's extract this items label href icon and on click great all right and now let's style this div so you're gonna write last name Plex Flex Dash row items Dash Center all right now open another div here this is going to be mobile first so last name is going to be relative rounded Dash full h-14 W Dash 14 Flex items Dash Center justify Center e-4 hover BG Dash slate Dash 300 however VG Dash opacity Dash and cursor Dash pointer and on large screens is going to be hidden all right I'm just going to add an icon here now you might be wondering okay where do we get this icon from well we're going to get it from this parameter right here and for that to work we need to add an alias so go here in this icon add a double dot right here and just write capital icon like this great and now we can use it as a component perfect it's going to be a self-closing component and let's give it some attributes size it's going to be 28 and color is going to be white and if you actually uh collapse the screen a bit you're going to be able to see our icons right here great because we are working mobile first now perfect all right and just below this div which we created we're going to create a very similar div which is going to be desktop first all right so write the following class names it's going to be relative given on large screens is going to be Flex items Dash row yeah Dash 4 e-4 rounded Dash full cover BG Dash slate Dash 300 hover VG Dash opacity that's 10. cursor Dash pointer and items Dash Center like this and I made a mistake here it's items Dash Center not items that row so you didn't have you don't need that last one all right and now inside we're gonna do the exact same thing so we're gonna add an icon which is going to have a size of 24 and a color of white but also it's gonna have a label so we can actually stretch the screen a bit now and you should still see these icons right here but we're also going to add a label so write a paragraph right here which is going to use the label in curly brackets you're not going to be able to see it right now because as you can see it's color black so let's style this paragraph last name is going to be hidden but on large screens it's going to be Block it's going to have a text that's right and text Dash XL great great job and now we have our desktop version of the sidebar but we can also collapse the screen and see how it looks on mobile great great job all right now let's go back into sidebar you can click you can close all the other things and we're going to add another sidebar item which is going to be separate from these iteration items so right sidebar item right here and it's going to have the following it's going to have on click which for now is just going to be an empty string an icon is going to be bi log out which we are going to import from react icons so go to the top and just write import VI log out from react react Dash icon slash VI perfect and let's give the label of logout great and now we have the log out as well and when we collapse it is just an icon great great job all right and just below this sidebar item of log out we're going to add another component called sidebar complete button great and we're going to get an error because it doesn't exist so go ahead into your layout and create sidebar create button.psx we can name it sidebar read button and as always let's just create an empty div like this let's go back into sidebar and let's import it so we fix the error it should be imported the same way as the other two items all right now let's import router const Router from use router like this you can import that from next slash router and let's do some styling on this step so actually this first div is not going to have any styling all it's going to do is unclick and it's just gonna redirect to a home page so router that push slash like this run another div inside and this div will have some classes all right so right mp-6 LG hidden so again mobile first rounded Dash full h-14w-14p-4 Plex iPhone Center justify Center BG Dash Sky 500 however pg- opacity Dash 80 transition and cursor Dash pointer all right and the icon we're going to use is fa feather which is going to have a size of 24 and the color of white and of course we have to import fa feather from react icons we go ahead and write import feather from react icon slash f8 like this all right and you can actually collapse your screen and guess what the Tweet icon is right here great and now let's do the same thing for desktop so just below this div right here create another div and we're going to style it again so last name and write mt-6 hidden on large screens it's going to be block PX4 py two rounded Dash full PG Dash Sky 500 cover VG Dash opacity Dash 90. cursor Dash pointer and transition as well great and now we're just going to add a paragraph right here as you can see we have our little button here we will add a paragraph which is just going to say tweet and let's style the paragraph so last name is going to be hidden on large screens it's going to be block text Dash Center font Dash semi bold text Dash white and text Dash square brackets 20 pixels perfect we have our tweet button and if we collapse everything it turns into a nice little mobile button great great job now let's go back into our sidebar and we can close everything else and that's actually it for sidebar for now and we can actually go back into our layout component right here and just below this div right here we can add another component called follow bar like this and it's going to throw an error because it doesn't exist so go ahead and go to your layout and create a new file called Apollo bar.bsx Great Name the component below bar and for now just write an empty div inside go back into layout and let's fix the error perfect it should be imported the same way as you did with the sidebar great and now let's style our follow bar perfect so let's style this did first last name is going to be px-6 P Y dash or hidden but on large screens is going to be visible in the form of block great another div inside of that which is going to have a VG Dash neutral Dash 800 rounded XL mp-4 perfect and now create an H2 element right here which is going to say who to follow and let's add some class names so class 9 is going to be text Dash white text XL and font Dash semi both great and let's just fix the typo so I wrote VG natural it's supposed to be neutral perfect and below this H2 we're actually going to open another div right here and we're going to give you the following class name it's going to be Plex Black slash whole gap-6 nt-4 and we're going to write a comment here to do user list because for now we cannot fetch any users great and now we're going to edit this uh main index page we're going to remove hello world and we're just going to add a simple header component so close everything and go into pages index.psx right here and for now you can remove everything and just write an empty fragment like this and we're going to write a component called header with a label called home and we're going to get an error because header does not exist so go into your components and create a new file called header that bsx name the component header and let's just fix the error by giving it an empty div go back into your pages indexed PSX and import header from add components slash header again if you can't use this you can use dot dot all right and now let's style this header component right here first let's actually import the router again so cons router user router from next slash router and we're going to write a function called const handle back it's going to be a useful back and all we're going to write for now is going to be rather that back like this and just uh make sure you use the router dependency in this handleback function great all right now let's write the interface for header so interface header props it's going to be label which is a string and it should be required so no question mark here and another prop called show back arrow which is optional and it is a Boolean now let's write here react.functional component and let's just paste this header props right here and now we can extract the label and show back arrow props from here perfect and now let's get styling so last name order Dash B Dash square brackets 1 pixel border Dash neutral Dash 800 and padding of 5. and as you can see we have our little header right here great now create another div right here last name Plex Black slash row items Dash Center Gap Dash clip all right and now we're going to create a conditional here showback Arrow and end and open the return function and we're going to write bi Arrow back and let's import this from 3x icons so import bi Arrow back from react icon slash bi all right and we're going to add some properties here we're going to say on click to be handled bot color it's going to be white size is going to be 20. we're going to give it some of the last name cursor Dash pointer other opacity 70 and transition all right and just below this conditional we're going to write an H1 which is going to say a label like this and we're just going to give you the plus name x dash white tax Dash XL semi bold perfect we have our reusable header component and I just want to show you if we go into your index right here and add a prop show back arrow it's actually going to hold this back arrow right here but we do not need this in the index file great great job you just finished the layout and you made the entire thing responsive amazing job all right in this part of the tutorial we're going to create some models so before we start I want to create a component called button so go in your components and create a new file called button with PSX let's name the component button and let's create the interface for this component so interface button props is going to be label which is a string secondary which is an optional Boolean pull width which is also an optional Boolean large which is also an optional Boolean on click which is a type of void disabled if it's an optional Boolean and last one outline which you guessed it is an optional Boolean as well perfect now let's assign this proc to this button so react.fc button props like that great and now we can extract all of this socket label secondary pull with large on click disabled and outline perfect and now in this return we're just going to write a button and we're going to use the label as the text and now let's get to styling so for class name you're gonna open curly brackets and you're going to write template literal strings because we're going to be doing some conditional styling great all right let's add the following classes disabled opacity Dash 70. disabled cursor Dash not Dash allowed rounded Dash o smibold cover opacity Dash 80 transition and Border Dash two and now we're gonna do some conditionals so if we have full width we will get we want to give it a class of w Dash full otherwise it's going to be W bit if we are secondary we're going to give it a class of BG that's right otherwise it's going to be BG Dash sky 500. we want to repeat secondary a few times now so again if it's secondary we're gonna give it a text left otherwise we want to give it a tax Dash White secondary again and we want to repeat the same thing border Dash black otherwise border Dash Sky 500 great now we have to do the same thing for large so if we have a large button we want to say text XL otherwise tax Dash MD repeat large again and now we're gonna do the padding so PX is five if we are large otherwise the x is 4. and one more time or b y so if it's large we're going to use py3 otherwise it's going to be b y dude all right last thing left outline so if we have an outline type of button we want to give it a BG transparent otherwise nothing repeat that and say border Dash white otherwise nothing and one last time outline text Dash white otherwise nothing great and now let's go back into this button here and just give it a couple of attributes so disabled is going to be the disabled prop and on click is gonna be an on click crop perfect great great job all right and now we can create our model component so what I'm going to do is I'm actually going to close everything up and I'm gonna go into underscore app the vsx right here and what I'm gonna write is I'm going to open a fragment for now like this and outside this layout I'm gonna write a model component and now we're going to get an error because this model component does not exist so let's go into components new file model that's bsx let's name the component model and for now let's just return the div and let's go back into our app so we can fix the error great perfect and now we can go into our model and start uh working on it great so let's start by creating our interface so interface model props is going to be is open which is a type of Boolean is going to be on close which is a type of void on submit which is a type of void as well title which is an optional string body which is an optional react dot react element weather which is also an optional react.react element action label which is a required string and disabled which is an optional Boolean perfect now let's assign these props to this model react.fc and let's paste the props great and now we can extract all of this so please open and close on submit title body with her action label and disable perfect good job all right now let's write the handle close action so homes handle close is going to be a used callback which we will import from react right here at the top open an arrow function inside open the dependency array and first we're going to check if the button is disabled so if it's disabled we're just gonna return because we don't want this action to play otherwise we're going to call on close method from the props so we have to add disabled and unclose in our dependency rate disabled and unclosed perfectly now let's handle our submit function so const handle submit use callback again Auto function dependency array and we're going to do a very similar thing so if it's disabled we want to return otherwise we're going to call on submit like this and we need to do the same thing in the dependency array disabled and on submit perfect great great job and one last thing before we start styling our model we're going to say if is open sorry if exclamation point is open so if we are not open return null otherwise return this model great and now let's go back into our app right here and for now all I want to give it is is open like that perfect and now we can start styling our model great so for now remove this div open this return function and write an empty fragment inside and now open the div again all right and now let's create our first container so last name is going to be equal to the following classes justify Dash Center items Dash Center Plex overflow Dash x dash hidden overflow Dash Y dash Auto fixed inset Dash zero Z50 outline Dash none Focus outline Dash none BG Dash neutral Dash 800 nvg Dash opacity Dash 70. great and as you can see you should get a little fade over your entire project again if you're not getting this fade over your website make sure you put the is open Boolean inside this model component right here in the app the reason I hard coded it to is open is because I want to see I want you to see the changes we are doing in real time great now let's write another component right here let's open up a div and let's give it the following classes relative W four LG W Dash 36th my-6 MX slash Auto LG Max w-3 Excel H dash pull and LGH Auto this will make the model responsive great great job all right and now the following day we're going to create is going to be our model content so I'm just going to write a comment called content so it's easier for us to navigate all right create another div right here and let's give it the following class names H dash o LGH Auto order zero rounded LG Shadow LG relative Flex Flex call W full VG black outline Dash none and focus outline Dash none as well perfect now inside this content div we're going to create another one but this is going to be our header so I'm going to write a comment as well great create another div and let's give it the following classics so we're going to give it a Plex item slash Center justify Dash between b-10 rounded Dash t and as you can see we now have a little black box here amazing all right and inside this header I want to give an H3 right here which is going to say title all right and now let's style this H3 so class name is going to be equal to effect Dash 3XL font semi bold and text Dash white all right now let's go back into our underscore app and let's give it a title title is going to be test model great we can see our test model title right here good job all right and now I want to add a close button right here so just below this H3 I'm gonna open a button element and inside I'm going to use AI outline close and we're going to import a outline close from react items so import a outline close make sure it's a lowercase l all right from react icons slash AI great job all right make sure this is a component like this and let's just give it a size of 20. and of course make sure it's lowercase L is here as well wait so AI outline close all right and now let's style this button last name p dash one ml Auto border Dash zero text Dash white hover opacity Dash 70. and transition great and now we have our little close button right here great great job and we're just gonna add another thing to this button which is on click and you guessed it we're going to use the handle close method so just paste that here great great job all right now outside this button outside this div we're going to create another component called body so I'm just going to put a common body here so it's easier to navigate below that create a div we're just gonna use our body prop and let's give it a class name of relative e-10 flat slash out all right and just below that we're going to create our footer open up a div last name Plex Flex slash call Gap Dash two e-10 great and inside here I'm gonna write a button component and it's going to have uh sorry it's a self-closing tag so button like this and let's just import it like this so make sure you input button from dot slash button they can import each other because they are in the same components folder so import button from button let's go back into our footer right here and let's add disable if the model is disabled so disabled is going to be equal to disabled label is going to be equal to action label is going to be secondary and it's going to be equal width and also it's going to be large and unclicked we're going to write handle submit perfect now let's just collapse all of this so you can see better great so what we're doing here is actually we're using all of those props we created while we were developing the button great great job all right and now let's go back into our underscore app right here and let's just give this an action label of subnet for example great our action is right here amazing amazing job and below this button I want to open curly braces and just write further because it's going to be optional great amazing amazing job you finished the entire model component great all right for now you can go back into underscore app and you can actually remove this model component for now and remove the import as well okay now we can write our login model but before we do that I want to create an input component first so go ahead and create input.dsx name the component input and let's define the interface so interface input props it's going to be equal to placeholder which is optional and a type of string value which is also optional and a type of string type also optional and a type of string disabled which is an optional Boolean on change which is going to be a function which accepts an event which is a type of react react that change event open pointy brackets and write HTML input element and it's going to return a POI perfect and label which is an optional string actually we don't need label at all my fault all right now let's pass this props to the input so input props like this and let's extract all of this here baseholder value type disabled and on change great and in here just write an input like this and let's give it some properties so disabled disabled on change on change value placeholder type and now let's style it last name and we're going to write w po e-4 text Dash LG BG that's black border Dash 2 order that's neutral 800 rounded Dash MD outline Dash none text Dash White Focus border Dash Sky 500 talk is border Dash 2 transition and we're going to add some disabled classes now so disabled BG Dash neutral Dash 900 disabled opacity Dash 70 and disabled cursor Dash not allowed perfect you have created the input component and now we can create our login model all right but before we do that let's close everything and let's install a package so open your terminal and install the following package npm install system we're going to use two stand as a lightweight Global State Management Library make sure you remember to run your project if you've closed the app all right and now let's go and create a new folder called hooks and inside here I want to create a new file called use loginmodel.ds and in here we're going to import create from to stand like that and we're going to write an interface for our login model interface login model store is open it is a type of Boolean thank you on open which is a type of function and on close which is a type of function as well that's it and now we're going to create a hook to control our login model so once use const use login model create just pass in the login model store in this curly brackets right here open the function and open an arrow function with the parameter set like this and just return an object again like this all right and inside you want to write is open pulse by default on open is going to be a method which is going to use a set to change is open through and we're also just going to copy this and write on closed which is going to change is open to pulse and that is it that is the entire control we need and remember to export defaults use login model like this perfect great great job all right and now let's go ahead and let's go into our components and let's create a new folder called models perfect and inside models create a new file called login model.bsx all right name the component login model like this and for now all it's going to do is it's going to return a div perfect and what I want to do now is I want to go back into our Pages underscore app and remember when we imported our model here well now we're going to import our login model all right make sure you import it from components slash models slash login model perfect great job okay so what we're going to do now is we're gonna trigger the um controls for our login model so once login model is equal to use login model like this perfect now we want to write some states const email set email is equal to use state on password set password is able to use State as well and const is loading set is loading you state impulse by default Perfect all right now let's create our own submit function it's a const on submit is going to be equal to use callback and here we're going to write a try and catch block so make sure that the use callback Arrow function is actually a synchronous like this let's handle the error for now all we're going to do is console log error all right now in try block first thing we're going to do is set is loading through all right and now I'm just going to write a comment here which says to do add logged in because we currently do not have authentication set great so what I'm going to do after a successful login because here is going to be something like a weight sign in blah blah blah what I'm going to do after that is I'm gonna close the model so I'm going to write login model that unclogs Perfect all right and also we're going to add another block here after catch finally which is just gonna set is loading pause regardless if we succeed the call or not but of course we're going to add an actual login function here later okay now let's look at our dependency array so we are missing the login model dependency so make sure you add the login model dependency right here great great job all right now before we begin styling our model let's write our body content so const about the content is going to be equal to 80. the div is going to have the following class names blacks Plex Dash Paul yeah Dash four and inside I'm gonna put two inputs so input which we can uh of course import from dot dot slash input the reason we are using uh dot dot slash input here is because we are in the components folder but this one is in models so it has to go outside models into an input right here all right and let's give some attributes here placeholder is going to be email foreign is going to take an event and it's going to say set email event.target.value value is going to be email and disabled is going to be is loading so we want to disable the input if we are loading and on change we want to control the email value right here great and you can just copy this entire input and just change email to password right here change set email to set password and change the value to password perfect great job all right and now we're going to replace this div with our model component so go ahead and import the model component again from dot dot slash model perfect and what I'm going to write is disabled is loading is open it's going to be the login model that is open title is going to be login action label it's going to be sign in just to switch it up a little on close it's going to be login model tab on close on submit is going to be on submit function which we have created right here which is going to do an actual authentication in the future all right or body we want to pass our body content perfect and now you are not seeing anything but if you actually go to use login model in our Hooks and change the default is open to true you are actually able to see our login perfect and if you try and click close it's going to work because we have passed the on close function to call login model dot on close which changes it to is open Pulse perfect amazing amazing job all right now I'm going to create another model which is going to be called register model and for that I'm just gonna go ahead and go into our hooks let's just close everything go into your Hooks and you can copy use login model and you can rename it to use register all right and what we're going to change is we're going to rename login model store to register model like this so we're going to have register model store use register model and Export use register model everything else can stay exactly the same great now you can go into your components into models and guess what you can copy login model as well and rename it to register register model perfect let's rename this component into register model export default register model as well all right and we can actually leave this login model control because we're going to need it you're going to see why in a second but below that I also want to import a register model so use register model like this perfect you see how easy it is to control Global state with two stand that's why I prefer it all right now besides email and password we're actually going to need some more Fields here so I'm just going to write const name set name use state and district and cons username set username use State and this ring as well all right and now what I'm going to write is I'm gonna just change this on submit function a little bit so instead of closing the login model we're going to close the register model and we can change the comment to do add login to to do register and login all right and now let's just change our uh body content a little bit so we're going to have an email but before uh we set our password we're going to create an input for our name and here you want to change set name and make sure the value is name as well copy the input again and we're going to do the same or username and again set username right here and make sure you change the value to username as well all right and now if we go down let's just modify this a bit so is open it's going to be controlled by register model is open and on close is going to be controlled by register model and close the title is going to be changed to create an account and the action label is going to be register all right now let's go back into our Pages underscore app and let's import register model just like that all right and as you can see we now have our register model showing up so just quickly let's go back into our Hooks and make sure the default is open is actually false in use login model and also make sure that is open is default pulse in user register model as well we don't want it to be open by default all right but just for now I'm gonna enable it so you can see what we are doing all right so what we have to do now is create a little toggle right here which is going to ask whether we already have an account so we can switch to a login model so let's go into our register model right here and below this body content we're going to create another constant called Twitter contents in here open a div and let's give it the following class name text Dash neutral Dash 400 text batch Center and empty-4 open a paragraph which is going to say already have add an account question mark and after this just give it an empty space and write a span which is uh gonna write I'm gonna say sign in actually just make sure you put like an empty space here uh and write sign in all right all right and now let's style this as fan last name is gonna be text that's white cursor batch pointer cover underline all right now go below and add glitter and use the other content which you just created and great now below this register we have a question asking us if we already have an account and whether we want to sign in instead and what we're going to do now is on click we want to close the register model and open the login model and we're going to do that by creating a useful little function which is going to be called on toggle So Below on submit create a new function called unfollow which is going to be a use callback and what I'm going to do here is first I'm going to disable it if we are loading so if it's loading we're just going to break the function because we don't want to switch if we are in the middle of creating an account and what I'm going to do next is register model that on close and login model that on open just like that and of course remember to pass is loading register model and login model to the dependency array and now we can use this on toggle method which we created and create an on click on this span right here so on click and just pass the on toggle button perfect and now if you actually try and click sign in you can see that we have closed the register model and open the login model all that's left to do now is to create the exact same thing for our login model so let's go back into login model here and first what I want to do is I want to copy the on toggle function from here so copy the on toggle function right here in the register model go back in the login model and just above on submit paste the on toggle we're going to get an error because we don't have register model imported so make sure you do that cons register model use register model like this foreign great great job and now we have to write a footer content right here and for that you can also copy it from the register model so just go here and copy the content for their content and Below body content just paste it right here but we're gonna write some different text so we're gonna say first time using Twitter and instead of sign in it's going to be to create an account right just copy the folder content footer content and just write router equal to their content and make sure you don't misspell so further with two o's great and now our login model has a question uh first time using Twitter create an account great and of course don't remember uh don't forget to modify the on toggle function right so once we click create an account in the login model if we want it to be a little bit different so we're going to close the login model and we want to open the register model so when you compare the two functions on toggle in login model closes the login model and opens the register model but in register it does the opposite in register model we close the register model and open the login model so if you try now you can see that we can switch between our models and of course we can close them as well great great job and now I just want to give you a way to open the login model from this dashboard uh before we do that let's open everything up go back into hooks one more time open both of them and just confirm that the ease open is default to false in all of the models because we don't want them to be open by default all right and for now I'm just gonna say that when we click this tweet function uh let's open a model so for that let's go into components let's go into layout and let's click on sidebar tweet button right here and we're going to change this on click so we're going to say const click please callback and we're just gonna say um okay let's replace this with on click like that and let's just import login model so login model use login model like this and all we're going to do is login model on open great and make sure you pass the login model to the dependency array great and now if you click on tweet it's actually going to open our login model and we can switch to create an account great great job amazing job in the next part of the tutorial we're actually going to create an authentication and create uh our models in the database all right in this part of the tutorial we're going to install and set up Prisma we're going to write our models and finally we're going to connect our authentication to the app so let's head into our terminal and let's run npm install Dash capital D charisma after it's been installed you can go ahead and run the command line interface MPX Prisma in it great now you should see a couple of new files so let's go ahead and let's take a look first of all you should have the new Prisma folder with schema.risma right here and you should also have the environment folder which has the database URL pre-filled we are not going to use this this is just for uh the template which we initialized all right first things first we have to change the provider to mongodb just like that and if you're not seeing this syntax like blue text and uh make basically if it looks plain to you what you need to do is you need to go into your extensions and make sure you have the Prisma extension installed right so add syntax highlighting and formatting and a bunch of other stuff which is useful great so make sure you have the Prisma extension all right so what we have to do now is we have to get our database URL which we are going to fill right here and for that let's go into mongodb Atlas and let's create our database so I'm just going to sign in because I already have an account if you don't you have to create one and once you are in your mongodb you can build a database you might have a button in this up right corner but I have it right here make sure you select the free cluster option uh for me it's right here in the end and you can just confirm it's free on the bottom right here you can leave the name cluster zero and you don't have to change anything here and just click create foreign for username and password uh you can write whatever you want in my case it's going to be Antonio and the password is also going to be uh Antonio uh for production I suggest you use an auto generated secure password and just click create user great and now we have a user and for the environment uh I suggest you you can add your current IP address with this button but you can also add 0.0.0.0 if you want access from everywhere the reason I added that is because I have a dynamic IP address which means that a couple of times in a day my IP address can change and that means that I won't be able to access my database so you can click add my current IP address and most of the time you should be just fine but for production you want to allow access Everywhere by typing 0.0.0 0 in the IP address and click finish and close great once your database is created you want to click the connect button right here and I want you to select Connect using vs code the reason I want you to select that is is it because it gives this specific type of string which is compatible with Prisma you could technically use connect your application but you can see that the string is just a little bit different and for our case we want to use Connect using vs code this type of string great so go ahead and copy that and now I'm going to paste that in this database URL in our newly created dot environment file right here all right perfect and now we have to change this pointy brackets password into our password which in my case is Antonio just like that great and the test is the name of our initial database you can leave the test like this for now all right now you can close the environment and let's go back into our Prisma schema.prisma file and now we're going to write all of our models the reason I want you to write all of them right now with all the fields is because if you work and change the fields later on hot reload can get kind of messy and you might not be up to date and you might get some errors so just for the ease of following this tutorial I'm going to write all of the models now and then we're going to push them to the database and we're not going to modify this file any longer all right so let's start by writing our user model model user first of all every object every model in mongodb needs to have an ID and there is a specific way we need to write our IDs using Prisma when using mongodb so go ahead and write ID string add ID at default in Brackets Auto great and then add map annotations underscore ID at db.object ID perfect and we're not gonna write this any more times we're just going to copy it for our future models all right next thing the user needs to have is name which is a string and optional username which is also a string and optional bio which is also a string and optional and for username you can also put at unique right here so we make sure that only one username per user great email is also a string and optional and of course also email needs to be unique as well email verified is going to be a date time which is optional next we're going to have image which is a pack of string and optional and now we're gonna have cover image which is also a type of string and optional and we're gonna have profile image which is a type of string and optional the reason I separated this profile image and cover image from this image is because this image is used for next out session and the reason we don't want to use this field but we do need it is because the profile image can get pretty large and sometimes that can break the session so that's why we have this duplicate profile image right here because we are going to use this field but this image field is needed for next out all right and then we're going to have hashed password which is a string and also optional we're going to have created that which is a date time and default is going to be now so the moment we create this user model we're going to set the created at date and updated at is going to be date time and we can just use the add updated at Prisma function great then we're going to have following IDs which is going to be an array of string like this and a type is going to be bb.object ID all right and then we're going to have the last field as notification which is a type of optional Boolean like this all right and now we're going to write some relations so user is able to have posts with a relation an array of posts like this comments with an array of comments click this and notifications with an array of notification like this right now everything is underlined because we do not have these models defined yet so let's go ahead and create our post model model post and you can just copy the ID from the user it's going to have a body which is a required string it's going to have created at which again is date time at default now it's gonna have updated ads which is date time at updated at is going to have a user ID which is a type of string which is a type of db.object ID and it's going to have light IDs which is an array of string which is also a db.object ID and lastly uh we're just going to create the relation between the user so go ahead and write user Capital user add relation Open brackets Fields open array user ID references is going to be ID and on delete we're going to write Cascade all right so you can see that now underline for post just went away and that's because we created a proper relation with the user basically what we are saying here is we are creating a user relation using the field user ID which we defined right here and we're going to reference that to the user ID right here and when we delete the user we also want to Cascade this post because the post cannot exist without the user great and I also want to add another relation right here on the bottom comments which is just going to be an array of comments like this right so user will also have a relationship with comment but each post is also going to have a relation with their comments as well all right now let's write the model for comment so model comment you can copy the ID and it's going to be pretty similar to post so body which is a type of required string created at which is date time at default now updated ad which is a date time at updated ads user ID which is a string of db.object ID and post ID which is also a string of db.object ID all right and now we just have to create two relations here so user user add relation and we're going to write the same thing as above so Fields user ID references uh ID and on delete Cascade and you can just copy this and create the same relation for post so post instead of user here is going to be post inside the Visa ready is going to be post ID and the reference is the same because post has the same Field named ID all right and let's create our last Model here so model notification and let's just write an ID actually let's copy the ID from the comments since it is the same everywhere and notification is going to have a body which is a type of string it's going to have a user ID which is also a type of string but db.object ID and it's also going to have created at which which is date time at default now all right and we just have to create a relationship with the user you can see it's still a red right here and for that you can just copy this from the comment since it is exactly the same great you have finished the entire schema for all of our models and now we actually want to see these fields actually these collections uh in our database right now if you go into browse collections you're not going to be able to see anything because we don't have it yet so go ahead and go into your terminal right here and now that we have some stuff in our schema Prisma you can actually go ahead and run npx Prisma DB push as you can see it's successfully connected to our database test using this cluster and now it found all the new collections we created all the new relations we created and is going to push that to the database right here great and now if you refresh you can see that we have comment notification post and user amazing amazing job all right now it's time for us to create our authentication and login and register controllers so to do that let's just install Prisma client so go ahead and install npm install at Prisma slash client great and just remember to run your project npm run Dev all right and we're going to create a new library right here so go ahead and create a new folder called lips and inside of lips you're going to create a new file called Prisma db.ts great and in here we're going to import Prisma client from Prisma slash client like this all right and now we're going to declare global sorry replay global war Prisma is equal to Prisma client type undefined all right and now let's just create our client so cons client is equal equal to Global this Prisma if I type new Prisma client and then we're just going to write a uh environment check so if process.environment dot node environment is not equal to production globalbiz dot Prisma is equal to client and in the end just export the default client perfect so what we're doing here um is we are basically doing kind of like a fix or a hack for uh next JS Hot Wheel loading because what happens is that Nexus can hot reload and create a bunch of new Prisma client instances and then stuff just stops to work because um it's simply breaking stuff because too many instances are active so this prevents it by saving it in the global based variable which is not affected by hot reload all right and now what I want you to do is I want you to close everything and I want you to go into Pages API and create a new folder called Alf and inside this out folder I want you to create a new file open square brackets dot dot dot next out and outside dot DS great all right and now we have to install some packages to start working on our authentication so open your terminal again and let's start by installing bigquip so npm install decrypt we can also also install the types so npm install at types uh sorry enter install Dash D at type slash liquid all right now we have to install next out so npm install next dash out and last thing we need is npm install at next dash out slash Prisma slash adapter make sure you have this app right here I know this looks similar to what we just installed but this is a separate package and we need it for Prisma great now just remember to run the project again all right everything seems to be running and let's write our next out so go ahead import liquid from bitcrypt import next out from next slash out import credentials Provider from next dash out slash providers slash credentials and import curly brackets Prisma adapter from at next slash out slash Prisma adapter great and now we have to import our Prisma which we created right here in the libs so go ahead and write import Prisma from great and just confirm that you can actually load the file great all right now let's write export default next out first let's assign our Prisma adapter so adapter is equal to Prisma adapter and pass in the prismac right here great next uh we need our providers so providers is an array and we're going to start with credentials provider right here and let's open the options object name is going to be credentials uh and our actual credentials are going to be email and password so email is going to be a label email and a type which is text and you can just copy and write password which is a label of password and a type of password all right and now let's write our login function so asynchronous authorize is a function which has the credentials parameter and inside first thing we're going to check if the credentials has email and password so if our credentials does not have email or if our credentials uh does not have password you can just throw new error in the lead credentials all right and yeah credentials can be undefined so let's just use the question mark here so we confirm we don't break the app all right and now let's go ahead and let's find the user with this email because if we're logging in we need to confirm that this user actually exists so const user is equal to await Prisma dot user that find you need if you are by any chance getting an error when writing prisma.user as in it cannot find user that means that you need to run npxdb push because you you might have forgotten it or maybe it did not synchronize you can also try restarting the project or refreshing your vs code all right and in this find unique we want to write where email is equal to prudentials.email so we want to use the credential email to find the existing user all right and now if the user does not exist or if the user does not have hashed password we want to throw new error again in the leads credentials because obviously whatever they typed in does not exist in our database and we cannot use that to log in the user all right and now let's check if the password is correct so const is correct password is equal to await decrypt dot compare and we're going to compare the credentials.password with user that hashed password like this right so we're gonna compare the hash that we have in our database and we're going to compare what bcrypt will hash uh whatever the user passed in the credentials all right great and now if it isn't the correct password which is going to throw a new error which is again going to say invalid credentials great and in the end we just want to return the user because everything went okay great great job all right now outside this uh providers we want to write debug to be equal to process.environment that node node environment identical to development so we want to turn on the debug if we are in development this will help you a lot because you will see a bunch of information in your terminal and it's going to help you debug stop or the session object you want to choose a strategy which is a type of jut and for jvt you want to open and write secret and you're just going to write process dot environment dot next out underscore jvt underscore Secret we do not have this yet we're just going to create it in a moment and the last field here is secret which is process.environment that next out underscore Secret all right now let's go ahead and let's create this next Out jvd secret and next Out secret so go into your dot environment file right here and just add the next Out jvd secret and just add the next out underscore secret here for me this is just going to be uh next underscore out underscorgivity and looks for secret and this is going to be next underscore out underscore Secret all right great we have our uh next out uh completely set up great great job all right now I'm gonna go ahead and we're going to create our register endpoint so let's close everything up and let's go into Pages uh and into API folder right here so make sure you do not create it inside out uh make sure you are creating it in API create a new file called register that's DS like this so the out should not have this register the out is reserved for next out great and in this register we're going to export people asynchronous function called Handler which has a request which is type of next API request and the response which is a type of next API response all right and you can just open the function and first thing we want to do is we want to limit this method to post only so if request that method is not equal post you just want to return response status 405 and end the call great and now we can open our try and catch block and let's handle the error first so we want to log the error I forgot to write the return function so if you want to write it now that's fine but I will also come back and write it later and on catch we want to extract our values and the values we're going to receive are the following so const email username name and password from request.body because that's what we are going to send if you remember in our create an account model right here great all right and now let's uh hash our password so const password is going to be equal to 08 decrypt which of course we have to import so import liquid from decrypt is going to be equal to a weight decrypt dot hash password well make sure you don't misspell password all right now that we have our hash password let's create the user it's a const user is going to be equal to a weight Charisma dot user dot create and don't forget to import Prisma so import Prisma from all right so it's this file we created right here make sure you don't misspell it and you can always check with the command or control hold your control key and press right here so you can see it loads the actual file all right and now you can use this prisma.user.create open an object and let's write some data so the data we're gonna pass is going to be email username name and hash the password great and now it's gonna return response status to 100 that Json user perfect all right and now what I want to do is I want to create uh another Library called the server out so go ahead into your lives right here and create a new file called server out.ps great so go ahead and write const server out it's an asynchronous function which only accepts a request which is a type of next API request and in here um we're gonna get our session using next out so const session is equal to await get session oh make sure you write the arrow function right here so asynchronous open parameters and write an error function get session and in here you're just going to pass an object which accepts a request and we're going to import get session from next out so import get session from next dash out slash react like that all right now we're going to check if we have a logged in user so if we don't have session question dot user question dot email we're gonna throw new error not sign in otherwise if we are signed in let's find our current user using the email it's a cons current user is equal to 08 Prisma dot user and of course let's not forget to import Prisma so import Prisma from at slash lib slash Prisma BB so Prisma that user that find unique where email is equal to session that user that email like this great if we don't have the current user so if we have not found anything with this email we want to throw a new error again and just write not signed in great and just return an object current user like this and don't forget to export Depot server app all right and before we move into our UI I just want to create another API route called current which we're going to use to create a current user sorry to fetch our currently logged in user so go into your API folder and create a new file called current.ds and in here it's going to be pretty similar to register so export default asynchronous function Handler which accepts a request which is next API request and the response which is next API response all right uh and first let's limit this to get only so if requires that method is not equal to get return response status 405 and end the call and now you can open your try and catch block and let's handle the error first so for development we're just going to log the error like this and return response status uh 400 that great and in our try block uh what we're going to do is we're going to extract the current user from the library which we just created right here all right so go ahead and write const current user is equal to to await server out and remember we have to pass the request uh not in curly brackets we just have to pass it like this perfect and what we're going to do now is return response status to 100 .json print user great so what this route is going to do is basically it's going to use this server out to get the current session from the request which we are getting it's going to check if we are logged in and then it's going to find the user by email and it's going to return our user so we can use it um in whatever way we want all right and now I want you to go back into uh API register right here and we forgot to return something if there is an error so after this comes a log just make sure you return response status 400 and end the call perfect all right we are almost ready to create some uh authentication on the front end so what I want you to do now is I want you to go into Hooks and create a new file called use current user.ds and I want you to go into the terminal and let's install another package npm install as we are and remember to run the project again all right and now import use svr from that's VR right this and we also have to create another Library called fetcher so go again into your lips right here and create a file called patcher.ts it's going to be very simple uh we do need another Library here so npm install axios run the project again and import access from axios and we're going to Define our fetcher as the following terms Patcher is equal to a URL which is a type of string and all it's going to do is access that get to the URL and then it's going to use the response and extract response to that data like this and Export can be called pressure perfect and now go back into your hooks use current user and you can import better from add slash lives slash better like this great and now write comes to use current user which is just gonna return uh the svr so it comes data error is loading mutate is equal use as we are and it's going to point to slash ABI slash current y there because that is what we just created in this Pages API current right here right and we also have to pass in it better like this perfect and all we want to do is return all of these fields which have been extracted from the svr library so return beta error is loading and immediate and don't remember to export default use current user all right so uh what svr is going to do is svr is going to fetch this slash API current using the axis fetcher which we created right here and it's going to store it in its Global store so we're going to be able to reuse this use current user hook and it's not going to refetch it every time we use it it's actually going to take a look and see if data already exists and it's also gonna decide whether data Maybe needs to be re-invalidated and fetched again so basically this is going to replace our Global State like Redux so this is an amazing amazing Library which you can use for fetching and we are also provided with stuff like data error is loading and muted if we purposely want to fetch it again great all right so now we can go back into our models so let's close everything up and let's go with the components models register model right here and here we have a comment to to do add register and login so let's go ahead and do that right await axis which you can import from axis at the top right here foreign API slash register why does this route exist best because we created it in Pages API register right here that's why I told you to not put it in the out folder because otherwise it's going to be API slash out slash register and you want to keep the out folder clean because this is reserved for next out so if you actually put any route here you might actually break the authentication all right and remember the body which we are going to pass is going to be emailed password username name and we need to add all of this to our dependency array so they are up to date so email password username and name how do we know that these are the fields we want well again because we Define that in the register controller right here from request.body we're going to extract the email username name and password and we're going to store that in our user right here great and one thing I want to add is I want to add a cool little toast notification when we succeed or when we fail so once again open your terminal and write npm installed react Dash hot Dash toast great and remember to run the project again and now what I want you to do is I want you to go into your um pages underscore app file again and here we're going to add the provider for our react hot toast which we just installed and we're also going to wrap the entire thing in a session provider so we can properly do authentication on the front end so go ahead and import the following packages so import poster from react Dash hot Dash host and import session Provider from next dash out slash react like this and you're going to wrap the whole thing in session provider like this make sure you end the fragment as well and you're gonna pass the session prop from page props dot session like this great and just above register model you're also going to add the toaster just like that perfect and now we can go back into our register model which is in components models register model right here and what we're gonna write now is the following so after this await code has been successful we want to write post that success account created like this now we have to import toast so go to back to the top and just import post from react Dash hold Dash toast all right perfect and we also want to handle the error so if we have an error we want to do toast dot error something went wrong great and after we register we also want to log in immediately so import another field right here sign in from next dash out slash react right here and after we successfully uh toast the success we just want to init the sign in sign in we're going to use credentials and we're going to pass the email password great and that should be it you should can actually try and what I'm gonna do is I'm just gonna expand this a little bit so I can open my network tab on the side and see if we successfully create or if we get an error so go ahead and click to it select create an account and let's create our first account so I'm going to write my email I'm going to write my name code with Antonio my username which is going to be code with Antonio lowercase and my password one two three three two one and let's click register perfect as you can see we got a toast notification that account has been created and we also got signed in and if you go back into your database now and refresh and go into user you can actually see our newly created user right here great great job and now we actually cannot see that we are logged out that we are logged in so let's go ahead and fix that for a second uh what I want you to do now is I want you to go into our sidebar component right here in layout sidebar and I want to use the hook which we created called use current user right here in hooks so in sidebar import cons data Alias current user from use current user like this and you can import that from add slash hooks slash current user and what we're going to do uh is we're going to check if the current user exists and depending on that we're going to show or hide this logout button right here so open color brackets and say current user and end and just wrap the sidebar item of logout inside of that great so our logout is only going to be available if we have the current user and now we're going to add the sign out function uh right here so instead of this Arrow function like this you're just going to rewrite sign out and you're going to import that from next dash out slash react so import sign out from next dash out slash react and make sure you will have an arrow function which Returns the sign out like this great and now let's go back into our sidebar item right here and one thing we're going to write is we actually haven't used this on click at all so just go ahead and write um on click is going to be handle click and now we're going to Define this handle click right here so homes handle click is going to be used callback and we're going to check if onclick exists so if on click in that case just return on click like this otherwise we're going to use our router so go ahead and import the router const Router is equal to use router which you can import from uh next slash router and so if there's an on click we just want to override with on click otherwise we're going to use router that push and we're going to push the a trap right great and just write [Music] um router and on click in the dependency array and just to ensure that this href exists let's write another if here so if href like this and make sure you also put the hrep in the dependency array great so now if you actually go ahead and try and click log out you can see that we are logged out and we cannot see the login uh the uh sorry the log out button right here now let's enable our login model so close everything up and let's go into components models login model right here great and so here we have written to do add login so what we're going to do is await to sign in which we are going to import from next dash out slash react and we're going to use Open brackets and write credentials and we're going to pass the email and password and don't forget to pass it in the dependency array as well so email that's right like this great and now if I actually try you can see that I'm successfully logged in and if I click log out I'm logged out perfect and one thing in which we forgot as you can see in this model we can see our password so let's just go into the body content right here and add a type the password like this and now you cannot see it and we have the same thing for the register model so just go into body content find the password and just add type password perfect and one thing I want to do next is actually protect these notifications and profile sidebar items so if we are logged out we don't want to be able to either to be redirected to these notifications even though it doesn't exist yet so what I'm going to do is I'm going to go back into my sidebar item so components layout sidebar item and I'm going to add another interface Shield called out which is going to be optional to Boolean and extract it here in props and what I'm going to check here is I'm going to check uh if the route is protected so for that we're also going to need our current user so go ahead and write const data Alias current user is equal to use current user which you can import from at slash hooks Slash use current user like this all right and now I'm going to modify this a little bit so I'm going to write if out and we don't have current user what we have to do is we have to open the login model so we also need that const login model is equal use plugin model which you can import from add slash hooks use login model so if we are authentic if this route is protected and we are not logged in or we don't have the current user what we want to do is login model.open sorry again not all that on open and you can just change this if to else it like that all right and now we have to add some stuff to our dependency array we have to add current user and we have to add alph uh is that all and we have to add login model as well Perfect Right nothing's going to change yet because we have to go back into um our sidebar right here and let's just modify these items a bit so for home we want everyone to be able to access it for notifications we want to set out true and we want to do the same thing for profile out screw great and now we also need to pass that in this iteration so alph is equal to item.au great and now if you actually try and click on profile we have our login propped up if you try notifications we have our login popped up but if you try home it works so if I click notifications and try and log in you can see now I can click on notifications now it doesn't exist so it shows 404 but it does not show me the login model but if I log out and click on notifications it opens the login model great great job you successfully finished the Authentication all right so in this part of the tutorial we're going to create routes to fetch our users and to fetch individual user as well and we're also going to fill this component of who to follow since we now created our first account which we tested in the last part of the tutorial so let's go ahead and let's go into our Pages API and let's create a new folder called users and inside for now create an index.ts file great and now we're going to write our Handler so export we both asynchronous function Handler which accepts request which is that both next API request which you can import from next right there at the top and response which is type of next API response great now we can open this function and let's limit it to get requests so hit request that method is not yet we're going to return response status 405 and end the call great now let's open our try and catch block let's handle the error so log the error like this for development and return response status 400 and the call as well great and now what we're gonna do here is we're going to fetch our users so const users is equal Prisma sorry await Prisma dot users the point many and of course we have to import Prisma so go to the top and import Prisma from add slash Clips Prisma DB like that all right and instead of users is going to be prisma.user like this because we are working with an individual entity so prisma.user dot find many and open an object and all we're going to do is we're going to order them by new newest created so order buy and we are going to Target our created at field and we're gonna order it by descending great and all we have to do now is return response status 200.json users Perfect all right and now that this is done we can actually go ahead in our users and create another file called user ID so create a new file and open the square brackets and write user id.ts great great job all right now we're going to do the same thing here so export default synchronous function Handler which accepts a request a type of next API request and response a type of next API response great open the function and we're going to do the same thing we're going to limit it to a get method so if requested method is not equal to get return response status 405 and end the call great now we can open our try and catch block as we did just a minute earlier and let's handle the error in the same way so block the error and return response status 400 and end the call Perfect all right and now in here we are going to have to extract our user ID which we know that we will get because of this syntax which we've written in which we named the file this is a special next JS syntax in which our user ID will be transferred in our request.query so let's go ahead and write const user ID is equal request.query like that and now let's check if the user ID is valid so if we don't have user ID or if type of user ID is not equal the string we're going to throw a new error which is just going to say invalid ID and of course make sure you actually check for user ID and not user all right and now let's find the existing user so const existing user is going to be equal to await Prisma which of course we have to import again so import Prisma from add slash Libs Prisma Maybe prismac.user dot find unique and we're going to write where ID is equal to user ID like this perfect and now we're also going to load the user's followers so const followers count is going to be equal to away Prisma dot user that counts and in the where object we're going to write following IDs as user ID great so we are going to find all the users who follow the current user ID which we are searching for so we can display on the profile how many followers the user has perfect and all we're going to do next is return response status 200.json we're going to open an object and we're going to spread the existing user and we are going to add followers count like this perfect we now have our users route great now let's go ahead and close everything up and let's create a hook called use users.ts great uh all right and you can actually go in the use current user and you can copy the entire thing and paste it here since it's going to be the same let's rename this to use users like this and now let's just I'm just going to collapse this so we can see the entire thing all right so instead of Slash API slash current use users is going to be users like that and that's literally it this is all we need perfect and now let's copy use users and let's create another cook called use user all right let's rename it to use user and this one is going to be a little bit different because it's going to accept a parameter called user ID which is the type of string great and now we're going to add a conditional here depending on whether we have the user ID or not so if we have user ID we're going to open uh the special types of annotations and we're going to do slash and open this special object in which we're going to write user ID otherwise null so the svr won't do any calls if there is a missing user ID perfect and that's it we have created our use user hook we can close everything now and we can now go into components and let's create our Avatar so go into components and create a new file called avatar.psx great let's write the interface for our editor so interface Avatar props is going to be user ID which is a type of string is going to be this large which is an optional Boolean and it's going to be as border which is also an optional grid and now let's write this uh component and let's call it Avatar like this and let's just assign this props so react that functional component will have the other props in its uh pointy brackets and let's just extract all of these props so user ID is large and has border Perfect all right and for now let's just return an empty div here okay uh and now uh I want to I want you to see how we are styling this Avatar so I'm not going to write anything because we cannot see what we're doing so before we finish this Avatar I want to go into layout into follow bar right here and if you remember we were actually written here to do user list so we can actually do that now because we just created our API in Pages API users so we can actually fetch these users using the use users hook all right so let's go ahead and do that uh right here you're gonna write const data give it an alias of users and give it a default value of an empty array and we're just going to write use users like this perfect uh all right and now let's just check whether we want to display this follow bar or not so if users but length is equal to zero we're gonna return now so if there are no users on the site we don't want to display anything all right as you can see it disappeared for a second because uh it did not initiate the call and then it initiated the call and it actually loaded one user here the one that we created last time and now we're gonna iterate these users in this list and actually create it all right so inside this comment right here we can remove it now and we can actually write users for that map user which is going to be a type of record sorry record and in the pointy brackets you can write string comma any all right uh and we're going to immediately return a div for now and let's style this bit so it's going to be class name Flex Flex Dash row yeah four and let's give it a t of user.id great now inside of that we're going to paste our Avatar like this which we're going to import from dot dot editor why can we import it like that well because follow bar is in layout which is in components so we have to escape the layout and go into Avatar right here all right now let's close this Avatar component like this just so we don't have the error and let's give it the user ID user dot ID like this perfect you're not going to see anything now because remember we are just returning an empty div for now all right and just below this Avatar I want to open another div right here and give it the following class names so class name Plex Plex Dash call uh make sure you don't misspell Plex like I did and inside uh we're just going to write good paragraphs uh first now first one is going to be user.name and let's give it the last name of text White on that semi-bold and text SM great and you can actually see that our name appeared here in the who the follow section uh I just want to collapse this so to make sure that you can see everything in one screen all right and below that uh we're gonna write another paragraph and here we're going to write user sorry we're actually going to write the add sign first and then we're gonna open user.username like this great you can actually see my name and code with Antonio right here great now let's style this uh username so text Dash neutral Dash 400 and tax Dash SM and make sure you don't misspell a neutral like this so neutral perfect and now you can actually see our user but we cannot see the Avatar so let's go ahead and let's wrap up our Avatar right here first things first uh we want to fetch the user so let's go ahead and write const data let's give it an alias of patch user and it's going to use the use user hook which we created make sure it's not used users because this one is different and use user needs to accept the user ID which we do have great so let's just pass in user ID like this all right now we're going to write an on click Handler it's a constant click it's going to be a use callback which you can import from react right here all right let's not forget the dependency array and what we're going to do we're actually going to accept an event here which is going to need a type of any for now and what we're going to do is just say event.stop propagation stop a propagation like that the reason we want to do this is because we're going to use this Avatar inside some components which are going to be clickable so we want to make sure that when we click on Avatar we want to override whatever the parent element on click is that's what event ended up stop propagation does all right now let's generate the user URL which we're going to redirect once we click the editor const URL is equal open the annotations and just write slash users slash user ID like this perfect and now you can just write router.push uh URL all right and we have a mistake here so it's not Capital router it's lowercase router and you can import it from const router use router from next slash router like this so import use router from next slash router Perfect all right now let's fill the dependency array so we are missing router and user ID so make sure you write router and user ID like that perfect all right now let's go ahead and let's actually style this div so last name is going to be equal to an object which is going to have template through the row strings inside of it because we are going to do some conditional classes with is large and has border all right so if uh we we have the parameter has border inside of the color brackets we're going to open a question mark and put a class border Dash 4 border Dash black otherwise an empty string below that we're gonna check is large and we're going to give it a height of 32. otherwise a height of 12. and you can copy and paste this and just replace the height uh with with like this great and you can already see we have some space here perfect all right and now it's time to actually put uh our image inside but before we do that sorry let's actually write some more classes here so around that Dash full hover opacity Dash 90 transition cursor Dash pointer and relative great and you can actually try and hover and you see we have a little pointer right there all right and now we're going to use next image so go ahead and write image like this and import it from next slash image like this the same way we did with next slash router Perfect all right now it's time to give some attributes to this image so we're going to give it an attribute of fill and we're going to give it a style which has to be an object and we're going to give it a style of object which is cover and Border radius which is 100 all right give it an avatar on click which is on quick uh and a source which is going to be etched user question mark dot profile image all right and now we're going to get an error because uh there is a chance that this fetched user is not loaded yet so what I want to do is I want to give this a pipe pipe which is going to say slash Images slash placeholder that PNG uh and as you can see we now have this broken image and the reason we have that is because we don't have this slash Images slash holder.png we have to create our uh placeholder now so we're going to put that in public and create a new folder called images and you can either find your own placeholder.png online or you can go into my repository the link will be in the description and you can just go into public right here into images and placeholder.png right click on the file save image as save the file and just drag and drop it into images right here perfect and now if you save again and refresh you actually see that we have our placeholder great great job in the next part of the tutorial we are actually going to create our user profile page and we're going to enable editing of the image and adding a cover image as well as changing our name and you can actually try and click on this image right here and it's going to redirect you to user slash user ID but for now this doesn't exist this is what we're going to do in the next part amazing amazing job well done all right so in this part of the tutorial we're going to create our user profile so when we actually click on this Avatar we can load the information about the user so go ahead and close everything up make sure you have the project running as well and go into pages and create a new folder called users inside this users folder you're going to create a new file open supplier brackets user ID dot PSX great and let's name the component user view like this and let's for now just put an empty div like this and now if you actually click here you can see that we don't get an error anymore because the user view actually exists and you can see our URL is users slash user ID which is the exact structure we have in Pages users user ID so you can actually click on this Avatar right here and you should not get a 404 for example like you would on notifications if you if we were logged in great all right what I want to do now is I want to install a package called react Spinners so open up your terminal and let's run MGM install react Dash spinners foreign remember to run the project again all right and now what we'll do here um is first let's add the header which we can reuse from our already made components so instead of div we're actually going to have a fragment here and our first component is going to be header and you can import header from add slash components slash header and what's missing is a label uh which for now uh will just say user profile and we're going to fill it with the name later and one more thing that we want here is we want to enable the attribute show back arrow so we can actually go back into home so we can click here and we have the back arrow great great job all right and now let's actually fetch our users so we can start working on some data so const user ID from request sorry from router dot query and of course we need a router so of course the router easy to use router from next slash router all right so how do we know that we will get this user ID from router.query well that's because of next JS structure in which we named this user ID right here perfect and now we want to fetch that user using our hooks use user which accepts the ID which we created in the last part of the tutorial so honest data give it an alias of attached user and let's also extract is loading because we installed the react spinners for that is equal to use user and pass the user ID as a string like that all right and now what we want to do is we want to add our loading State first so let's do the following if is loading or there is no fetched user we just want to return a div with the last name Flex justify Dash Center item slash Center and h-4 and inside of that we're just going to use a clip loader which you can import uh from react Dash Spinners right here all right and we want to give this clip loader a color of light blue and a size of 80. all right and you can actually modify this a bit and just say true and you will see that we have our nice loader light here rating now just make sure you return the if cluster is loading or if there is no patched user all right and now we can actually replace this user profile label with the actual fetched user name so go ahead and write patched user question mark dot name and as you can see this just switched to code with Antonio how do we know it's called with Antonio well because we have our ID in the URL here which is reading the fetched username great now I want to create another component here called user hero and it's going to accept a prop called user ID which is going to be equal to user ID as shrimp from our router.query and if you save you're going to get an error because user hero component does not exist so let's go ahead into our components and let's create a new folder called users and inside these users let's create a file called user hero that's DSX name the component user hero and let's just return to live so we fix the error let's go back into our Pages users user ID and let's import this newly created component just like that the error should go away all right and now let's write the interface for our user hero component so the interface user hero prox is equal to user ID which is a type of string and now let's attach these props to this component so react that function components is equal to user 0 procs and right here in the parameters we can extract user ID great and now this error should go away because it actually accepts the user ID all right now what I want to import next is the next image so import image from next slash image like this and I also want to import the use user hook so import use user from add slash slash use user and I also want to import avatar from you can also use add slash components but since we are already in the components folder we just have to escape the users folder and go to this Avatar right here so this should work all right uh and now let's fetch this user using our user hook so cons data give it an alias attached user is equal to use user and just pass user ID right here great all right and now let's get to styling so inside this div you want to give a another div and give it a class name of BG Dash neutral Dash 700 h-44 relative and you should see we have our cover placeholder right here and inside of that we're going to create a conditional which is either going to show the cover image uh if it exists or leave it blank like this if it doesn't so open calling brackets and write attached user question mark dot cover image and end Open brackets and just write image which we imported from next image right here at the top give it a source of patched user dot cover image give it an attribute fill and I'm actually going to collapse these attributes so you can see all of them in one line so fill out is going to be cover image and style is going to be an object of object fit power like this and right now you should not see any changes because we never added the cover image to our user all right and just below that I want to create another div and give you the following class names so class name absolute bottom 16 sorry you can delete this and actually write minus bottom Dash 16 right so this is equal to bottom minus 16. but this is the way you write it in Tailwind you append the minus before the class name so make sure it's minus button 16. and left Dash four all right and inside here I want to add our Avatar so Avatar and we want to give it user ID of user ID we're gonna give it an is large attribute and has border attribute and as you can see we actually have our user image right here and it's using the same placeholder because we never added the image but great this is exactly what we want so again just make sure you have this minus bottom 16 because it's important for positioning as well as left 4. as well as this main container having the relative class and this wrapper around avatar having the absolute class perfect and now let's create the user bio so go back into your pages users user ID and create a new file new component user bio like this and it's going to accept the exact same props so user ID is equal to user ID as string you're going to get an error because it doesn't exist so let's go into our components user and create a new file user bio.tsx and name the component user bio and just return leave for now let's go back into our user profile and just import that component as well as we did with the user hero like this and the error should go away all right now let's write the interface for user bio so interface user bio crops is equal to user ID which is type of string let's attach these props react.functional component is equal to user bio rocks and we can also extract user ID right here all right and now let's actually uh we're going to fetch uh a couple of stuff so first let's fetch our current user thanks data current user is equal to use current user which you can import from add slash hooks Slash use current user we created this in the second or third part of our tutorial and you also want to import the patched user so data is attached user run use user like this and make sure you pass the user ID like this great amazing job uh all right and now I want you to install another package so go into your terminal and run mpm install date Dash FNS all right and let's import that at the top so import formats from data FNS okay and we have the types great you can go ahead and run the project again and close the terminal all right and now let's create our created at uh constant here so once we created add is equal to use memo and it's going to return the following so if there is no fetched user question mark dot created at you're gonna return now otherwise we're going to return format new date patched user dot created at in a format of or Capital M's and or lowercase wise like this and make sure you fill the dependency array so we need patch user question mark dot created at great all right and now let's get into styling our Dev so class name is equal border Dash B Dash square brackets one pixel border Dash neutral Dash make sure you don't misspell neutral Dash 800 DB what and you can already see we have our little container right here but we're gonna extend it even more now so write another div uh right here last name Plex justify Dash and np-2 and in here we're actually going to check uh if we are looking at our own profile page or someone else's profile page so open curly brackets and just write current user underscore sorry question mark dot ID is equal to user ID and open the question mark and open the brackets and you're just going to write the button which is going to say secondary with a label edit and on click for now it's just going to be empty and make sure you import button uh from dot dot slash button all right and now remember after we created this conditional if we are looking at our own profile we want to create another condition right here which is going to be another button foreign attributes so on click again it's just going to be an empty function label for now it's just going to be follow and secondary uh is actually we don't need secondary yeah actually let's just put secondary like this great uh so if we're looking at someone else's profile we will see the follow button but if we are looking at our own profile we will see the edit button uh so let's actually log in so we can see the difference okay great as you can see I'm logged in so I can see the edit button because code with Antonio is my profile but if I log out you can see that I can see the follow button right here great great job all right and now we're going to create uh some other uh stuff right here so just outside this div open another div with a class name empty-8 px-4 and inside another class name Plex Flex Dash call all right and inside of that let's create a paragraph last name of text White text Dash to Excel One semi bulb and the value is going to be patched user question mark dot name and as you can see our name is loaded right here below the image great great job and you can actually write another paragraph below that with a class name of text MD text Dash neutral 500 and here you're gonna write an add sign and then open the curly brackets attached user question mark dot username so now below that you can see what is my username appended with an ad signed great great job all right and now outside this div you want to create another div and give it a class name of the Plex Black slash call empty Dash four again uh and inside you just want to write a paragraph with patched user question mark dot bio and the class name in the paragraph of text Dash white you cannot see any bio right now because we never added the bio but you can go ahead in your database if you want to test it out but we are going to create an edit model very soon all right now just below this paragraph um I want to create another div right here and give it the following class names let's let's that row items Dash Center yak-2 mp-4 and text Dash neutral 500. and in here I want to import Ada calendar from react Dash icons bi so import bi calendar from react Dash icons bi and I want to give it the size of 24 great and now we have our little calendar icon right here and just below that I want to open a paragraph and write joins and use our created at constant which we have created here in this memorization function right here and you can see now we have a little calendar here and says uh in which month in which year we joined uh this clone of Twitter great great job all right now outside this uh div right here you want to create another div with a class name of Plex Flex Dash row item slash Center np-4 gap-6 and inside you can open another div and give it the class name of Plex Black slash row item step Center yeah one and inside of that we're gonna write a paragraph and we're just going to load uh the number of users We are following so patched user question mark dot following IDs question mark dot length and let's give the class name of text Dash White and as you can see we get the number zero because we are not following any IDs yet and just below this paragraph let's write another paragraph which is what you're going to say following and let's also style this class name text neutral Dash 500 like this great uh and now you can actually go ahead and copy this entire div and paste it below and we're just gonna check uh for some different stuff so instead of coloring like this we're gonna check for followers followers count like this and we're going to add that type zero and instead of following we're gonna write followers great amazing amazing job you have completed the user profile uh in the next part of the tutorial we will add the edit model right here all right so in this part of the tutorial we're going to create our edit model and edit button so let's go ahead and close everything up and let's go into Pages API and create a new file called edit.ds and in here let's export the bulb synchronous function Handler I'm just going to accept request which is the type of next API request which you can import from next right here at the top and response next API response which you can import from there as well all right and first let's limit our Handler to patch request only so if request method is not equal patch you're gonna return response status 405 and end the call and now let's open up try and get blocked and let's handle the error so for development let's just log the error right here and return response status 400 and end the call great and now in our dry couch uh try block we want to extract our current user so current user from await server out and pass the request right here you can import server out from add slash Libs slash server out like that all right and now we want to extract values which are available to update so cons name username bio profile image and cover image from request body so these are all the fields we will be able to edit and now we want to create a equals so if it happens that user has not submitted a name or not submitted a username which are required we're going to throw new error missing fields all right and now we can actually update our user so const updated user is equal to 08 Charisma which of course we have to import so import Prisma from add slash lit slash Prisma DB await Prisma that user that update and open an object in first let's uh find the user uh the user is going to be ID current user dot ID like this and we have to pass some data to update so data is going to be name username dial profile image and cover image great and now we can just return response status 200.json and send the updated user like this great great job all right now uh I want you to go and close everything up and let's go in the hooks and let's create our edit model so you can actually copy the use login model model for example and just rename it to use edit model like this and let's just rename everything login related to uh edit model so we have edit model store and use edit model everything else can stay exactly the same and now I want you to go into components in the users into user bio right here uh and right here at the top where we import our users let's also import the edit model so const edit model is equal use edit model like this and you can import that from add slash hooks Slash use edit model and we're actually gonna change this uh edit button uh to do something else on click so what it's going to do is edit model on open like that and let's actually log in so we can uh see the edit button great I now have the edit button but if I click nothing's gonna happen all right and now what I want you to do is I want you to go into your pages underscore app right here and like we edit register model you want to add edit model like this and now you're gonna get an error because edit model does not exist so let's go into our components into models and you just create a new file edit model.tsx and let's just name it edit model like this and for now let's just return an empty div go back into your slash underscore app and just import edit model from add slash components slash models slash edit model and the error should go away all right uh and now what I want to do here is I want to import a couple of things so const data and give it an alias current user is equal to use current user which you can import from user const mutate is going to be equal to mutate patched user from use user and passing the current user question mark dot ID like this and const edit model from use edit model like this so we have imported three hooks so far all right and now let's create some states which we will update so const profile image set profile image from use state which you can import from react right here let's just put that at the top you can copy and paste that and do the same thing for cover image so let's set the cover image do the same thing uh for name username and bio all right and now I just want to create a use effect here so use effect sorry before we do that let's actually just fill all of this use states with an empty string like this all right and now let's create use effect which you can import from react as well so make sure you import use effect right here don't remember the uh don't forget the dependency array right here and what I want to do is I just want to initialize uh all of the existing Fields so set profile image is going to be equal to current user profile image cover image is going to be equal to current user cover image set name it's going to be equal to print user.name and set username is going to be equal to current user that username and last thing set bio is going to be equal current user dot bio like this and now we just have to add current user to our dependency array objects are actually not the recommended thing to add in the dependency array and I would prefer if you add individual Fields because it's going to cause less errors along the way right here all right and now let's create a loading state so cons is loading and set is loading new state and report is going to be false all right and now let's actually create our own submit function so const on submit is equal to use callback [Music] and what we're going to do inside is open a try and catch block so just make sure that this is an asynchronous arrow function right here and in this error let's handle that first I want to do toast which you can import from react Dash code that Dash toast right here all right you want to toast the error and just say something went wrong all right and finally uh in which we're going to just reset the loading so set is loading is going to be false and now in the try block first things first let's enable the loading so set is floating is going to be true and then we're just going to initiate the update API so await axis which you can import from axis right here at the top dot patch if you remember we limited our uh Pages API edit to patch only so it expects a patch call so patch is going to point to slash API slash edit and let's just pass the body name username bio profile image and color image all right and after that all we're going to do is mutate patched user so after we successfully edit our user we want to make sure that we call this load user again so it's up to date with the newest updated data right all right and after that we can just say close to that success update and let's at the end just close the model so edit model Dot and close all right and let's fill our dependency array so we are missing uh bio name username profile profile image cover image edit model uh what else are we missing and new date patched user like this all right uh all right what we're gonna do now is we're gonna uh actually replace this div with a model so let's go and just write a model which we can import from uh dot dot slash model because we are in the components folder here and what we're going to do in this model is we're gonna I'll add some Fields so disabled if it's loading is open it's going to be edit model that is open title is going to be edit your profile action label it's going to be saved close it's going to be edit model dot on close on submit it's going to be on submit uh and for now that's all and you can actually click edit now and you should see that the model should open uh if you're not seeing anything unedited just make sure you went into your uh components into your uh user's user bio and that you imported the edit model here and added the on click edit model dot on open on the edit button great and now let's create the body content for this model const body content is equal to the following so div class name Lex Flex Dash call gap-4 and first things first let's add some inputs so input which you can import from uh dot dot slash input because we are in the components folder and let's give it a couple of props so placeholder is going to be named on change uh it's going to be an event which is going to trigger set name event the target value is going to be name and disabled is going to be is loading like this and let's just uh copy this three times like this and let's actually open the model so we can see what we're doing uh we're going to replace this name with username for the second one also replace set username and value is going to be username and you also want to do the same thing for Bio set bio and change this to bio as well great and now you can add the body content sorry body is equal to body content to the model and you should see that we have pre-filled values right here and our bio is of course empty now let's try and save our bio so this is my bio as you can see uh it's updated and it reloaded the user and now we have this is my bio right here great and we can change it again and it's updated again great great job all right now we have to handle image and cover image upload so for that we're gonna need another component so what you're gonna do right here uh you're going to want to go into your components and create a new component called image upload.tsx let's name the component image upload and let's just return an empty div right here and for now just above this input in body content let's import the image upload so image upload like this uh it's gonna have a couple of props so let's give it a value of profile image let's give it a disabled oh it's loading let's do the unchange which is going to accept an image which is going to do set profile image and give it an image let's do the label which is just going to be um upload a profile image like this and don't worry about all of these errors we're going to fix all of that when we created the image component and you can just copy and paste this and replace the value with cover image and this just needs to say set cover image and upload our image here as well all right now let's go into our image upload and let's create the interface so interface image upload props are going to be on change which is a base 64. which is a type of string and that's going to print a void label is string value is an optional string and disabled is an optional Boolean all right and now let's append this props right here so react FC image upload props and let's extract all of this here so unchanged label value and disable great uh and now what I want you to do is I want you to install another package so let's go into our terminal and let's run npm install react Dash Drop Zone all right and make sure you run the project again actually before you do that let's just see if we have the types so import use Drop Zone from uh react Drop Zone all right we have the types you can go ahead and run your project you and close the terminal all right and now let's add some State here so cons uh base is 64 and set base 64 from use State and the default value of the C state is going to be value and make sure you import the use state from react right here at the top all right now let's write our handle change function so comes handle change is going to be equal to use callback which you can also import from react at the top it's going to accept base 64 parameter which is a type of string and we're going to do a very simple thing we're just going to call the on change and pass the base 64 like this and make sure you add the on change to the dependency array like that and now we have to create our handle drop function where we're going to actually convert the uploaded image to base64 so const handle drop use callback it's going to accept files because now you can just set a type of any and just open the independency array so now we have to turn these files into a base64 so first let's extract the only file we have from the array const file is going to be equal to files and just choose the first one we know we are only going to have one but the files is always on array now let's initiate our readers on reader is we here is equal to new file reader you don't have to import anything this already exists in the JavaScript ecosystem and now we're just going to say either dot unload event give it the value of any and open a function and what we're going to do is we're going to set base 64 which we have declared right here and we're going to give the property of events dot Target that result and we're also going to trigger the handle change to events.target that result like this all right and in the end just remember the good reader that read as data URL and pass the file right here and now don't forget to put handle change in your dependency array right here great all right and now let's initiate our use Drop Zone hook right here so we're gonna write and extract get root root props and get input props prompt use Drop Zone open the array sorry open the object and let's write some properties so max files is going to be one on drop we're going to do this function called handle drop to pass like this disabled is going to be equal to disabled which we have in our props but you can just write the shorthand disabled like this uh and now let's accept only images so accept open an object and just write image slash jpeg is equal to an empty array and image slash PNG is equal to an empty array as well great now let's uh style our image upload you can actually go ahead and click the edit button and you see we have our space for our image upload but nothing here yet so let's go ahead and write that so in here uh what you're going to do is you're actually going to open square brackets and spread the get root props which we have extracted from this use drops and hook right here and open the executive function and open an object and just write class name uh which is equal to W who b-4 text Dash White text Dash Center border Dash 2 border Dash dotted rounded MD and Border Dash neutral Dash 700. all right and now you can see we have uh the little uh dotted borders uh two times here great and now let's style the in inside of it so here we want to write the input but just make sure this is the native HTML element input not our input component so this needs to be a native HTML element and all you want to do here is open the square brackets and just spread dot dot get input props like this all right and now we're actually going to do a conditional here so if we have base 64 meaning if we uploaded an image or an image exists we're actually going to display the image so open a div and write a class name of Plex item slash Center you justify Dash Center and inside we're gonna use the next image so make sure you import image from next slash image at the top and let's give it some properties here so it's going to have a source which is base 64. I is going to be 100 with it's going to be 100 as well and up is going to be uploaded image like this all right and now let's write the other option here which is just going to be a paragraph which is going to say label and let's give it some class names so class name great and now you can see we have an option to upload profile image and option to upload the cover image so let's go ahead and try that I'm going to click upload profile image and it's going to open my uh file browser right here uh and let's see if I can find something I like all right so I'm going to use this image right here and I'm going to click open and as you can see I have my profile image here so let's click save and just like that you can see my image has been updated in my profile and also in the sidebar right here because every instance of use user hook has been updated as well and now let's add the cover image uh for that I don't know uh I'm gonna try something like this great and you can see I have my cover image as well uh just make sure your files that you're uploading are not too big otherwise it's not going to work and as you can see uh I have my uh cover image set here as well perfect uh you finish the entire uh user profile what we'll do next is we're actually gonna learn how to create posts and how to load them all right so in this part of the tutorial we're going to create our posts and we're going to create hooks which will load the API routes all right so before we continue with that I just want to fix one thing in our sidebar right here right now if you click on profile it leads to this slash one two three which which we hard coded in the sidebar so let's go into uh components layout sidebar right here and let's replace this users one to three with template literal and let's just write slash users slash open special object print user question mark dot ID and if you're logged in and click on profile now it is going to load your profile Perfect all right now let's close everything up and let's create uh Pages API and let's create a folder called posts right here and inside let's create a new file index.ps all right and let's create our Handler so export default a synchronous function Handler which accepts a request of next API request and the response of index API response which are both important from next and let's limit our routes to two methods so if request that method is not equal The Host and requested method is not equal to get so if it's neither post or get we're going to return sponsor status 405 and end the call because we want to allow this to be both for creating our posts and to fetch all posts at once now let's open the try and catch block and let's handle the error so log the error and return response status 400 and end the call all right now in this try first let's handle the post method so if request method is equal to post we're going to do the following we're going to extract current user from server out so const server sorry current user is equal a weight server out which you can import import from ads lips slash server out like this and remember to pass in the request right here and while we are here let's also import Prisma so import Prisma from add slash lives Prisma DB all right and now let's extract the body from request body const body is equal to requested body be aware that this body is not the same as request value so what this body is referring to is this schema uh field body in post so just make sure you don't do this on accident right so it's a different body and now let's just create the post so cons post is equal await uh prisma.post dot create and we're gonna give it the data of body and we need the author which is user ID and the user ID is the current user which is creating the post so current user question mark sorry no need for question mark dot ID all right and let's just return the post so return response status 200.json post like that perfect all right and now let's handle the get method so if request method is equal to get we're gonna do a couple of things so first things first let's extract our optional user ID const user ID from request.query this is going to be optional depending on whether we want to load only the user profile posts or if we are on the home page and want to load all of the posts so first let's handle what happens if we have the user ID for that let's define this changeable posts constant uh actually it's not the constant it's a let and let's check if we have the user ID so it user ID and pipe off user ID is equal to string so if it is a proper user ID in that case posts are going to be equal to away Prisma that post that find many and we're going to use the where object in which we're going to fetch the user ID like this so if we have these already we're only going to find posts from that author right here and we are going to add an object include because we also want to populate uh user which is the owner and we also want to populate comments great and we want to order this post by descending so order by created at descending so we load the newest posts great and we're just going to add an else to this if clause so uh in this case we're gonna set posts are equal to 08 Charisma that posts that find many and no need for the wearfield in that case so we're just going to say include user through comments true and we are also going to order them by created ad so order 5. created at the sending grade and outside of this if Clauses we are just going to return response that'll status 200 Json posts like this perfect uh all right so we handled uh both the get method and the post method here perfect now let's create our use posts hook so go into uh Hooks and create a new file use post.tx great and you can actually go to uh use users for example and copy it and just paste everything here and rename it to use posts like this all right and now our route will be able to be dynamic because there is a chance that we are going to pass the user ID here because we want to load only posts from that user so this use post is actually going to accept a parameter user ID which is an optional string like this and now let's create our Dynamic URL so it comes URL is equal to template liberals in which we are going to sorry outside of that we're going to check user ID if there is a user ID we're going to say slash API slash posts question mark user ID is equal to open the special object user ID otherwise it's just going to be slash API posts like this all right so if we have these already we're going to load slash API slash post question mark user ID user ID otherwise API posts all right and now you can use this URL to replace this hard-coded slash API users right here Perfect all right and now let's go into our index so close everything and go into pages index.psx and just below this header we're going to add a form and this form is going to have a placeholder of what's Happening all right and if we say we're going to get an error because the form doesn't exist so let's go into our components and create a new file on the PSX great let's name it form and let's just fix the error by returning an empty div let's go back into our pages index.csx and let's import form the same way we did with header all right and now let's write interface for the form so interface phone prox is going to be placebooger which is required string it's going to have an optional Boolean please comment which we are going to use later when we Implement comments and it's going to have an optional post ID which is the type of string all right and now let's assign this interface so form react functional component click on props and let's extract these values placeholder is comment and post ID all right and now let's add some Hooks and some functions before we start writing the form so cons register model use register model which you can import from add slash hooks user register model and do the same thing for login model use plugin model like this and then we're going to need our current user so const data with an alias current user from use current user which you can also import the same way with it with the login and register model and we're also going to call our newly created use posts hook here but we're only going to extract mutate so const mutate give it an alias of new data posts is equal to use both like this and we're also going to pass this optional post ID right here so post IB as string I made a mistake here there is no need to pass the optional post ID into this hook in fact you can just use the empty use posts as in the picture I will find this out later when we make comments all right and now let's create our body field so once body set body is equal to use state which you will import from react let's just put it at the top so our Imports are nicely ordered and let's give the default value of an empty string and let's also add the is loading state so const it's loading set it's loading use State Balls by default all right and now let's create our own submit function on submit easy use all back which you can also import from react right here at the top is going to be an asynchronous parallel function don't forget the dependency array and let's open our try and catch block let's handle the error so for the error we are just going to toast the error message so toast which you can import from react Dash hot Dash toast like this and we're going to toast an error with the text something went wrong all right let's handle the finally Block in here we are just going to reset our loading so set is loading is going to be pulse regardless of whether we failed or succeeded and in try first let's initiate the loading so set is loading is true and then what we're going to do is await axios which you can import from axios right here that post slash API slash posts and let's give it a body like this so this state body right here all right and if that is successful we're going to toast that success with created all right and we're going to clear our body so if it's successful we want to reset the body so set body is going to be equal to an empty string and we are also going to call mutate posts right here so mutate posts basically what this will do once we successfully create a new post we want to mutate our existing posts so it loads all the new ones including this newly created one all right and now let's fill our dependency array so we are missing body and mutate posts so add body and new date posts like this all right and now we can go ahead and create our form so all right let's give this a class name of Border Dash B Dash square brackets one pixel border Dash neutral Dash 800 px-5 and py-2 and you actually see our little space right here all right inside of that uh first thing I want to do is I want to create uh the form which is going to show if the user is logged out so let's create that first because it's easier so it did give it a class name of e.y-8 and inside of that uh create an H1 tag which is going to say welcome to Twitter as you can see it's right here but it's not visible because the text is black so let's go ahead and style the text a little bit so class name is text white tax Dash 2 itself that's Dash sampler mb-4 the endpoint Dash bulb and now it looks much much better and all we have to do is add some buttons below so create a div right here with a class name of wax Flex Dash bro item slash Center justify their Center and GAP dashboard all right and we're going to add two buttons here which you can import uh from dot slash button because we are in the components folder right here and the button is right here all right and let's give the label for the first one login and for the second one register all right uh and now let's give the on click for the login to be login model on open and for the register on click into the login sorry register model that's on open all right and now they look the same so all I want to do is I want to add another property to this register button right here called secondary great so now we have our login and register and if we click you can actually see that we open our models great but since we are logged in we obviously want to show something different so for that we're going to use our current user hook right here so just above this py-8 model right here create a conditional print user and here just write an empty Loop for now otherwise just wrap this entire div of py-8 um like this great so now if we are logged out we're going to see this welcome to Twitter screen but if we are logged in we're not going to see anything because that's what we are going to create right now all right so in this newly created div right here we have a class name four and inside of that create another div and create an avatar component right here so Avatar like this and you can import editor from dot slash editor the same way we did with button and let's give it a user ID so the user ID is going to be equal to the current user underscore sorry question mark dot ID and we have our user right here all right now below that create another div with the class name of w Dash full and let's create an element text area and for now you can remove all of these properties right here and we're just going to start by adding some attributes so disabled if it's loading on change it's going to modify our body state so we're gonna have an event and we're gonna set set body event the Target that value like this all right you can see our little text area right here now we're going to style it a bit but before that let's just give it a value of body as well and now let's write some class names so class name disabled it's going to be opacity 80. it's going to be here because we are going to do something with the sibling element right next to it in just a moment precise Dash none empty that's three uh w o b g dot black ring Dash zero outline Dash none text Dash opens for brackets 20 pixels placeholder Dash neutral Dash 500 neutral 100 and Text slash white and also let's add the last attribute placeholder you can see that we now have the what's happening placeholder right here which we have in our props perfect all right and below this text area let's just create an HR element which is going to have some class names as well so class name so first of all opacity 0 by default but on pure Focus so when we focus on the text area because text area has to appear class name we're going to give it an opacity of 100 h Prime brackets one pixel w order Dash neutral Dash 800. and transition so now if you actually hover on the sorry if you focus on the text area you will see our little HR appearing right here all right and just below this HR create additive with the following class names so class name mp-4 Flex Black slash row and justify Dash and and inside of that we're just going to put our button uh which is going to have a label of wheat and you can see it's appearing right here perfect and now let's just give it some other attributes here let's give it a disabled if it's loading and uh let's give it an on click submit and I also want to disable the Tweet button if we have not written anything so just add is loading pipe pipe question mark exclamation mark body like this so now it's disabled if we have nothing here but if we start typing you can see that we actually are able to tweet so you can actually go ahead and I'm going to collapse this a little bit and we're going to test if we are able to create our tweet so I'm going to go into the network tab right here I'm going to zoom in and I'm gonna say all I can just tweet this and as you can see we are initiating the call right here and we get the success tweet created and if I actually go inside you can see that we have created a tweet with the body of our value created that ID like IDs updated ad and user ID perfect great job all right uh and now it's time to create our Post Feed right here so we can actually see the posts which we have created so close everything up and go back into your pages index.tsx and just below this form create a new component called uh Post Feed just like this and you're going to get an error because Post Feed does not exist so let's go ahead and create that so we're going to go into components uh and create a new folder called posts and inside of that create a new file post feed.dsx let's name the component postpaid and let's just return an empty div so we can fix the arrow quickly go back into your pages index.psx and just import Post Feed from add slash components slash boats Post Feed it's great the error should go away now let's write some interface for postpaid supports with props is going to be equal to user ID question mark string so it is an optional prop let's assign the props Post Feed props let's just extract this user ID here and let's load our posts using the use posts hook so cons data post is equal to an empty array and it's using the use Close book right here and it's going to accept the optional user ID if it exists so why are we sending this user ID well right here in our index file we are sending the post ID and we want to load all of the posts but we're going to reuse this post ID on the profile page as well in which we are going to pass the user ID prop for example but for this one we don't need it all right so this is going to load all posts for now and all I want to do here is I want to reiterate through these posts so open an empty fragment here and just write post that map post which is a type of record string comma any and just return uh post item it does not exist yet but let's give it some values it's a user ID again user ID if it exists he post that ID and data which is post and if you save of course we're gonna get an error so let's go ahead into our components into our posts folder and let's create a new file post item.vsx name the component post item like this and as always just create an empty div so we fix the error go back into your post feed and just import it right here from dot slash post item because they are in the same folder and the error should go away great and now let's create the interface for this post item so interface post item props data which is a type of record string comma any and user ID which is an optional string now let's assign these props so react functional component post item props and let's extract this so data and user ID great uh okay now let's add some cooks and some functions so first of all we're going to need our router so const router is equal to use router you can import router from next slash router we're going to use the login model as well as login model is equal to use plugin model you can import plugin model from hooks slash using model all right and now let's fetch our current user cell phones data Alias current user use current user hook which you can import from hooks current user all right now let's create our go to user method which you're going to reuse a few times so first go to user is equal to use callback which you can import from react don't forget the uh dependency array and the go to user is actually going to accept an event which is a type of any and let's stop the propagation so event stop propagation we already did this in the Avatar component if you remember so when we click on the Avatar component we also accept an event and we stop the propagation what that is doing uh basically the card post item is going to be clickable so this main div is going to be clickable but this go to user is going to be used for some inner child elements so when we click on those inner child elements we want to stop event bubbling event propagation so go to user is going to override the global on click of the parents all right and all we want to do here is router that push open template literals and just write slash users slash open the special object data.user.id and fill the dependency array router and data.user.idp all right now let's create our go to post method once we go to post which is also going to be used fallback it's not going to accept any event and all it's going to do is router that push also template rules slash posts slash data dot ID and don't forget to put router and data.id in the dependency array just to remind you so our data is our post and that's because in Post Feed we send data as our post just so you don't get confused while we're looking for these fields all right and now let's create our own like function it's not going to work currently because we don't have the APR for that so all we're going to do for now is open the login model when we click on like self const on like is going to be equal to use callback um it's going to accept an event which is a type of any don't forget the dependency array and uh we're gonna stop the propagation again so event let's stop propagation like this and for now all we're going to do is login model that on open like this so our dependency now needs the login model all right and now let's create our uh created add constant so constant created add is equal to use memo so we use memo however you pronounce it which you can import from react as well and first of all we're going to check uh if we have a valid data so if there is no data question mark you got created at all you're going to do is return now otherwise you're going to return format the distance now strict and you can import that from date FNS which we installed in one of the previous parts all right so format distance to now strict Open brackets and just write a new date data.created at like this all right and just pass data question mark we have created sorry I misspelled created app like this all right and now let's actually um style our div all right so first of all let's add on click go to post like this and now let's add some class names so last name is equal to border Dash b square brackets one pixel order Dash neutral Dash 800 either five or third Dash pointer cover BG Dash neutral Dash 900. and transition so okay I have two Fields right here because I created two posts you can just go ahead and write another one uh and you will see that we now have three posts right here so you can play around with it a little bit just so you see how we are getting a new posts loaded if you try and click you're gonna get uh get a 404 all right so now let's go inside of here and let's create a div with a class name of flex let's Dash row items Dash start yeah Dash three and let's add our Avatar first so Avatar you can import avatar from dot dot slash Avatar because we are in the folder and as you can see we now have our Avatar right here but we are missing these already so let's pass user ID from data.user.id and as you can see it has loaded four of my tweets and all of them have the correct Avatar amazing uh all right now glove this div create a new div which is not going to have any class names uh but the first div inside is so another div last name it's going to be uh Flex Flex Dash row item slash Center yeah all right and inside of that let's create a paragraph right here which is just going to say data that user that name all right and now we have to style this paragraph a bit so last name is going to be equal to text that's right on their semi Bolt cursor Dash pointer over underline great so now if I actually try and however you can see uh that I get an underlying and a nice effect all right and just below that I want to add our span so underneath this paragraph Just Add a span which is going to say an at sign and then open an object which is going to say data that you learned that username and let's style that as well so last name is equal to text Dash uh sorry I'm gonna open it like this so text Dash neutral batch 500 all right cursor Dash pointer cover underline hidden button MD is going to be visible right so when I Collapse I actually want to hide it because it's taking too much space all right and as you can see it's also underlined as well uh great amazing and now I just want to add on click on both this paragraph and this span so add an unclick here which is going to say go to profile sorry go go to user all right which we have created right here and you want to do the same thing for this span so one click go to user like this all right okay and now below this fan uh let's create another one span and let's give it a class name of backslash neutral that's 500 that's SM and we're going to paste created at right here so you can see that we have created this three minutes ago this one three minutes ago this one 12 minutes ago this one 48 minutes ago and if I create another one you can see that this one was one second ago amazing all right uh and now uh outside of this div which we have created So Below this span outside of this div create another dip which is gonna have our data dot body and let's give it a plus name of that slash White m3-1 great we now see our tweets amazing all right and now outside of this div uh create another dip which is going to have the following class name so last name Flex Flex Dash row item slash Center mt-3 gap-10 right so right out below this data that body div create a new div like this and inside of that we're gonna create our likes and comments so open up I did and let's open last name and we're just going to write Plex Black slash row item store Center text Dash neutral Dash 500 gap-2 cursor Dash pointer transition cover text Dash Sky 500 all right and what I'm gonna just write inside is an item so IR AI outline message you can import AI outline message from react Dash icons slash AI like this alright so let's go right here to our AR outline message and let's give it a size of 20. great and you can see we have our little comment icon here and if we hover it gets a nice little blue effect now uh inside this div just below this AI outline message create a paragraph which is going to say data dot comments question mark dot length and just give it a pipe of zero if it doesn't exist great and as you can see if we hover the number becomes blue as well amazing all right uh and now uh we can actually copy this tip and just paste it like this and now we have two comments and we are just going to uh replace it so first let's replace the icon so the icon of the second one is going to be a outline message is going to be AI outline part and you can import a outline heart uh from react Dash icon slash AI as well all right and now we just have to play with colors a little bit so everything can mostly say the same but instead of text Sky 500 we're gonna give it a red 500. so if we hover now you can see that we get a nice little red effect when we hover Perfect all right and I just want to add an on click to this div right here for likes on quick for now it's just gonna say unlike and if you remember all we did is we triggered the login model so if you click right here it's going to open the login model all right uh and that's actually it for our post item uh we're gonna go back uh later to actually implement the like functionality uh and some comments all right all I want to do now is I want to add this exact feed right here to my profile right here so what we're going to do is we're going to go and close everything up and we are going to go into pages into users user ID right here and just below this user view bio you're going to add Post Feed and you're going to import that from add slash components slash posts Post Feed and remember here we have to pass the user ID because right now we're going to get all of the tweets but we just want the tweets from our user so user ID is equal to user ID as shrink and nothing has changed because we only have one user so just to test things out I'm gonna log out and I'm going to create a new user all right and now I have this new user and I'm going to try and tweet something this is uh my words all right so on the global feed we can see all of the tweets but if we go into code with Antonio as you can see we can only see code with Antonia tweets and if I go to a new user I can only see new user to it amazing amazing job all right in this part of the tutorial we're going to create our like function as well as our follow function right here all right so let's start and let's wrap everything up and let's go into Pages API and create a new file follow.ds let's create our Handler so export default synchronous function Handler which accepts a request up next API request and a response of the next API response right and first let's limit this to post and delete so if request method is not equal to post and if request method is also not equal to delete in that case we're going to return response status 405 and end the call all right now let's open our try and catch block and let's handle the error as always so log for development and return response status 400 and end the call all right and now in our dry block first let's extract the user ID which we will get from the query so once user ID is equal to request.body sorry not query body like this all right and now let's get the current user so const and extract current user from a weight server out which you can import from at slash Libs slash server alph like this and remember to pass the request parameter right here now let's check if the user ID is correct so if there is no user ID or if type of user ID is not equal the string in that case throw new error invalid ID all right and now let's find our user so const user is equal to await Prisma and now we have to import Prisma so import Prisma from add slash lit slash Prisma DB all right and just write Prisma this user find unique where ID is equal to user ID like this all right so now we have the user which we want to update uh in our case in which we want to follow all right so let's check if we have the user so if there is no user Pro new error again invalid ID because if we have not found any user by this ID obviously it means that the ID is invalid all right now let's Define the initial uh following IDs select updated the following IDs is equal to spread and just open uh parenthesis like this user dot following IDs pipe pipe and the array like this all right and now let's handle uh if the request method is post so it will cast that method is equal to post so if we are adding a follow in that case we want to do updated following ideas dot push user ID like this and now let's do the delete so if request method is equal to delete we want to do updated following IDs to be equal to updated following ideas dot filter uh where we are going to accept following ID and we're just going to return um let me just collapse this so you can see better like this we're going to return following ID uh following ID is not equal to user ID right so basically we want to filter through this entire following IDs and remove the one uh and only leave the ones uh which are not the current user ID all right and in the end we have to update our users so const updated user is equal to await Prisma dot user dot update where ID is equal to current user.id and the data is going to be following IDs updated following IDs like this great and all we have to do at the end is just return response status um 200.json updated user like this great all right now let's create our use follow hook so go in the hooks and create a new hook use to follow the DS all right so uh let's write our hook first subconscious follow is equal to user ID which is a type of string and it's required and in here we're going to fetch our current user so const beta current user and mutate mutate current user like this from use current user like that all right and below that we are going to do the same thing for one user so const mutate mutate fetched user is it will be used user and pass the user ID inside and don't forget to import the hook use user which we have created in one of the previous tutorials all right now let's trigger the login model silicon login model is equal use login model right and now let's establish if we are already following the user here so const is following is equal to use memo which you can import from react right here at the top all right open the function create the dependency array and in here let's write our list first so const list is equal to current user question mark dot following IDs pipe pipe empty array all right and all we want to do is return list that includes uh user ID like this all right and we have to pass in user ID and current user question mark lot the following IDs uh yeah make sure you don't misspell this so it's following IDs so cons list is equal to current user question mark dot following IDs multiple all right and now let's create our toggle follow function so const toggle follow is equal to use callback which you can import from react right here at the top uh and inside first let's check whether we are logged in or not so if there is no current user all we want to do is return login model dot on open like this great and now let's write our try and catch block so try catch and let's handle the error first so if there is an error when we are following the user we want to do toast which can import from react Dash code dash toast and just error something went wrong all right and in our try block uh what I'm going to do is I'm gonna create a let request and now we're gonna differentiate whether we are already following the user so if we want to unfollow or follow the user so if it's following which we have defined right here in this use memo again just make sure I made a mistake here that it is following ID is not following ID so following IDs like this all right so if it is following in that case the request is equal to an arrow function which returns axis dot delete make sure you import axis which you can import from axis right here at the top so axis dot delete slash API slash follow and just pass in data and inside user ID like this all right and else it we are not following the user we want to follow them so the request is going to be an arrow function again but this time access that post slash API slash follow and you can just pass in user ID without the data so in this case we need data because this is a delete request so this is how it accepts the body but in post request you can just pass the body like this all right and what you want to do now is await request like this uh yep I made a mistake here so it cannot do a weight because we cannot Define that our toggle follow use callback Arrow function is a synchronous so just wait async right here at the top great and the error should go away now so make sure the function is asynchronous all right so after we await the request we want to mutate current user and we're going to mutate patched user as well and let's just toast success success all right and now let's fill our dependency array so we are missing the current user is following user ID new tape current user and I'm just going to collapse this so you can see what we're writing all right so mutate current user uh mutate with a depressed user and a login like this great all right and all we want to do at the end is just return an object is following and toggle follow like this all right so this is our is following sorry use follow hook right here and just don't forget to export Depot use follow at the end right here perfect and now let's actually go into components if the users into user bio right here and what we want to do here uh just above this created at between this model we want to import our use follow-ons and let's extract is following and toggle follow from use follow hook which you can import uh at books Slash use follow right here open the parenthesis in the use follow and pass in user ID great and now we have our is following and double follow great and now let's go into this button right here so instead of empty function right here on this follow button we're going to write toggle follow instead of static Apollo we're gonna have uh Dynamic text so is following we're gonna write unfollow otherwise we're going to write follow like this now secondary is going to also be dynamic so secondary if it is not following so exclamation mark is following like this and outline is following all right so now let's go ahead and let's try and click follow on code with Antonio here or with every user you created and as you can see it gets success the one follower gets appended right here and I have the unfollow button and if I actually go to my profile you can see that I have one following right here and if I try to unfollow you can see that it works there is zero followers for this user and if I go back to my profile it says zero following following as well great great job all right so in this part of the tutorial we're going to implement liking our post but before we do that I want to implement something else first right now if you try and click on any post you're gonna get a 404 page because our slash posts slash ID does not exist yet so let's go ahead and let's create a route for that so let's close everything up and let's handle the API first so go into Pages API and create actually we already have a folder posts so inside of that just create a new file and open square brackets and write post ID dot DS like that great and now let's write our Handler so export default synchronous function Handler which accepts a request next API request and the response of the next API response all right and now let's limit the route to get only so if request method is not equal to get return response status 405 and end the call great now let's open our try and catch block let's handle the error so for development we're going to log the error and just return response status 400 and end the call great now in our try block let's extract the post ID from request query which we are going to have because of this special syntax that next.js will recognize so we know we're going to have post ID in our query so const the structure post ID from request.query like that great now let's check if our post ID is valid so if there is no post ID or its type of post ID it's not equal to string let's return uh response sorry bro new error invalid ID like this all right and now let's find our post so cons toast is equal to 08 Prisma which we have to import so go ahead and write import Prisma from add slash Libs Prisma DB so await Prisma that posts that post that find unique where ID is equal to post ID and we're just gonna include some stuff so let's include user and now let's also in write comments include the comments but we're going to open an object because we also want to populate a comments user so also write include inside of that user true and outside include just write order by made it at the sending great so we want to load this individual post we want to populate its user and we also want to load all of the comments for this post but we also want to populate the user who created that comment and we want to order all of the comments by newest great all right and all we have to do now is return response status 200 that Json post like this great and now let's create our use post hook so go into Hooks and you can just copy use posts and rename it to use post like this instead of user ID first let's actually rename the hook so the hook is named use post so make sure you rename the hook we use post as well instead of user ID is going to accept a post ID which is a required string and in this case the URL is going to be checking for post ID and it's going to go to slash API slash posts but it said this already is going to be slash post ID in this special object right here and if there is no post ID we are not going to touch anything so our URL for use post Hook is going to check if we have a post ID and if it is it's going to go to slash API slash post slash post ID because that is how we defined in post post ID route right here and if there is no post ID we are not going to fetch anything great and you can leave everything exactly as it is all right and now what I want to create is I want to create this actual page which is going to fix this 404 so let's close everything up and let's go into pages and let's create a folder posts great and inside this posts create a new file again square brackets post ID but this time dot ESX all right and let's name this poster View and let's just return an empty div and now if you actually refresh right here you can see we no longer get a 404 we just get an empty page um because there's nothing here yet all right so let's add our router const Router in the use router and let's get the post ID from router.query again we can get the post ID because of this special uh next.js structure so cons and this structure post ID from router.query all right and now let's fetch our post so const data is equal to patch post and let's also add is loading right here from our newly created hook use post so make sure you don't import use posts we need use post our newly created hooked and we have to pass the required post ID here all right and make sure you just write it as string great so just you can command or control click on this to make sure that is this new hook right here all right uh and now let's handle the loading so if it's loading or if there is no fetched post you want to return this with the class name or Flex justify Dash Center item slash Center and H dash full and inside of that we're going to add our clip loader from uh react Dash spinners all right and we're just going to give some color to this clip loader so color is going to be light blue and size is going to be 80. and as you can see we have our little loader there for a second and now it's actually a style our post view so write an empty fragment like this and first of all we're going to add our header components you can import header from add slash components slash header all right and let's give it a label uh the label is going to be bit like this and also add show back arrow like this great and now we have this tweet and if you actually click back you're gonna get back to where you came from in our case is the users and if I click again you can see that I load for a second and then we load the header all right and now we're going to reuse our post item component which we created uh last time here so we have this post item right here so let's just import post item from add slash components slash posts post item right here and we have to give it a data or patched post like this and if you save you will actually see that we have uh the view of our post item great now below this I want to add a form which we will use to reply to this post so below that just add form which you can import from add slash components slash form and let's give it a couple of values so it's going to have a post ID post ID as a string it's going to have its comment attribute which we are not actually going to be able to see why yet but we're going to add that once we implement the common functionality and add a placeholder tweet your reply and great now we have an option to tweet our reply and if you try right now it's actually not going to create a reply it's going to create another post here on the global pages but we're going to fix that uh in the following the tutorial all right and now I want to implement the liking functionality all right so let's close everything up and let's go into Pages API and create a new file like dot DS all right and let's export be called a synchronous function Handler is going to accept a request of next API request and the response of next API response all right and let's limit this to two methods so if request method is not equal to post and if request method is not equal to get sorry to delete either in that case return response status 405 and end the call if this seems similar is because this like endpoint is going to be very similar to our follow endpoint as well it's going to use pretty much the same logic I think we're going to write it one more time just to confirm our knowledge so now let's open F5 and get blocked and let's handle the error to log the error and return response status 400 and end the call all right and now in our try and get Block let's extract post ID from request.body so const post ID requested body like this and let's also extract our current user so const current user from away server out which you can import from add slash lips slash server out and don't remember to pass in requests in the parenthesis right here and I also want to import Prisma while we're here so import Prisma from add slash lid slash Prisma BB like this all right and now let's check if our post ID is valid so if there is no post ID or if typo post ID is not equal a string Pro new error invalid post sorry you can just email it write invalid ID like this all right now let's find our post so conspost is equal to await Prisma dot post dot Pine unique where ID is equal to post ID all right great job now let's check if this post actually exists so if there is no post we're gonna throw new error ID again all right and now let's create a our light IDs list so let update it like IDs is equal to an array in which we will spread uh an open parenthesis right here in which we'll spread posts that like IDs like this and just give it a pipe pipe of an empty array all right now let's handle what will happen if this is a post request so if request method is equal to post we are going to use updated light IDs and push the current user.id because the current user which initiated this call is the one that is liking this post so we want to add this current user ID to the list of light that is of this post right here great and now let's handle delete so click request method is equal to delete we want to return uh updated like IDs is equal to updated like IDs that filter collect ID and we are going and we just want to filter everything that is not the current is ready so like the ID is not equal current user dot ID like this great so if it's post request we're going to add the ID to the list of live titles if it is a delete request that means that user has unliked this post and we want to remove it from the array great and let's just update the post here so const updated post is equal away please map that post that update where ID is equal to post ID and the data is like IDs and it's equal to updated life like this which we have modified here that depending on whether it's a post or a delete request great and in the end just return response status 200 Json updated post Perfect all right and now let's create our use like hook so let's close everything up let's go into Hooks and create a new file used like the PS great so const use like um is going to accept a couple of uh props right here so it's going to accept post ID and user ID and we can just write types for that right here post ID is a type of string and user ID is an optional type of string like that and you can just return the function right here all right so in here let's get our current user once data current user so you could use current user which you can import from dot Slash use current user now let's import the individual post which we are liking so cons data patched post and mutate is going to be equal to mutate batch post and that's going to be equal to use post and post ID right here and you can import use post from dot Slash use posts great I'm just going to expand this a little bit so you can see what we're doing all right and now let's also import our use posts so we can also refresh all of the posts if they're liked so const we just need mutate mutate fetch posts like this is equal to use posts and you also want to pass user ID so the reason we have we're having this user ID right here is for a chance that we are just liking individual user tweets like this and we're not going to have this ready if you are liking public tweets like this great now let's add the login models the console login model is equal to use uh login model you can also import that from dot Slash use login model right here and now let's define our has liked constant so const as like is equal to use Myanmar which you can import from react right here at the top all right and let's create our list so cons list is equal to patched post question mark dot like IDs by pipe empty array like that great and we're just going to return list that includes Uh current user question mark dot ID so you want to check if the current user which we are logged in has liked this loaded post right here fetched post which we have Alias here great and let's add the dependency array so we are missing current user question mark dot ID and fetched post Benchmark dot like Ibis all right now below that let's add our toggle like a method it's a const toggle like is equal to use callback which you can import from react right here and we're going to write an asynchronous arrow function don't forget the dependency array right here and in here first we're going to check whether we are logged in or not so if we are not logged in or if we don't have current user we're just going to open our login model so return login model that on open like this great otherwise we're going to create a request so open a try and catch block and let's handle the catch first so we want to toast an error so post which you can import from react Dash code dash toast dot error and just write something went wrong all right and now let's handle our tribe so first Define let request right here let's check uh first if as liked so if you already like this post we want to unlike it so the request is going to be an arrow function which points to axis which you can import from axis right here at the top dot delete slash API slash like and we're going to pass in data with a post ID like this and otherwise if we don't if we haven't liked this and we're gonna like it for the first time the request is going to be accessed at post slash API like and we can just pass the post ID like this again we have to pass in data here because this is a delete request and it accepts body a little bit different so very simple if we already like the post we wanna unlike it otherwise we want to like it for the first time great and now let's just write a wait request and after that let's mutate attached posts like this and let's mutate patched post individually just like this so mutate fetched post and muted fetched post which we have imported from this use post hook and use posts right here and at the end let's just toast success with success or you can write something like successfully like if you want to now let's fill our dependency array right here so current user has like post ID mutate attached post mutate fetch posts and login model great and in the end let's just return has liked and toggle like like this and don't forget to export default use like hook all right perfect great job and now let's close everything and let's go into our components posts post item right here and let's make use of this like hook right here so uh what I want to do now is just below this current user I'm gonna go and import as liked and toggle like and I'm gonna open use like hook which you can import from add slash hooks Slash use like which we just created and inside I'm going to pass post ID which is equal to data.id because remember data is the post in post item component and we're also in pass user ID great and now we can actually go back into this unlike right here uh and modify it a little bit so first let's check if we have the current user so if there is no current user in that case we're going to call login model dot on open and make sure you um return this like this so we want to break the call and open a login model if there is no current user and otherwise we're going to do toggle like great and now we have to add the current user and toggle like to the dependency array as well great and now we have to make use of this has liked a hook right here so for that first I want to import another icon right here so we have a AI outline hard but I also want to add AI build part like this great all right and now just below this created ad let's create a constant called like icon so cons like icon is going to be equal to has light so if we already liked it we want to create we want to show the filled heart icon so AI feel hard otherwise AI outline hard like this and now we're going to use this like icon in place of this AI outline heart right here so replace a outline heart with this Dynamic like icon nothing should change right now but if you go ahead and try and like something you should see a change in which we just hearted an icon like this and of course uh we are still loading comments here so let's just change that and instead of comments here underneath the like icon we're gonna say like IDs dot length and just like that you see that we now have um loaded how many uh people have liked this post so you can go ahead and click on this one it's gonna turn to full uh and it's going to turn to number one and I want to add another styling here so I want to keep it red by default if we have liked this so I'm gonna add a color option right here and I'm going to say as like question mark red otherwise empty great so if you selected it's going to be read by default great and you can actually go into my profile and check if it's the same here as you can see it is you can even click here and try and unlike here as you can see it's going to remove and go back it's going to remove here either you can even go further back and it removed it right here great amazing amazing job in the next part of tutorial we are going to create our comments functionality all right in this part of the tutorial we're going to implement our comments and replies in individual posts so let's go ahead and let's close everything and let's go into Pages API and let's create a new file called comments.ds let's create our Handler so X will be called a synchronous function Handler to selects a request of next API request in the response of next API fonts which you can both import from next first let's limit this method to post only so we will only use this to create comments so if request method is not equal the post you can just return response status 405 and end the call all right now let's open Archway and catch block let's handle the error and return response status 400 and end the ball great all right now let's first protect this route and extract our current user so const the structure the current user from await server out and pass the request and you can import server out from ads Libs server auth great below that we're going to extract our body from request.body so destruct your body from request red body again keep in mind this body and this body is not the same thing this body is going to be equal to our Prisma schema for the comment model right here where we defined body so I just don't want you to do this for example because it's not correct and I also want to extract the post ID for which we will attach this command to so const cost ID is going to be equal to request.query all right now let's check if the post ID is valid so if there is no post ID or if post ID is not equal to string you can just return excuse me you can throw new error invalid ID great and now let's create our comment so const comment is equal await Prisma and let's import Prisma so import Prisma from add slash clip slash Prisma DB and then go back away to Prisma dot comment dot create open an object and write some data here and for that we're going to use body we're gonna use user ID which is current user.id and we also need post ID which is post ID and you can just use the shorthand like this great and now we just have to return this comment so return response status 200 that Json comment all right and now I actually want to go back into our form so go into components form right here and we're actually gonna my bad so go into form and we're actually going to make use of this is comment prop right here so we're gonna go in our on submit right here and we're gonna separate this URL and make it a bit Dynamic depending on if this is a form for the global feed right here or if this is a form for a reply right here so const URL is going to be equal to is comment question mark open annotations slash API slash comments question mark post ID is going to be equal the special object post ID like this so I'm just going to write it like this so you can see oh my bad otherwise it's just going to be slash API slash posts like this great and then you can use this URL instead of this hard-coded slash API posts and just remember to use the is comment right here and we also need the post ID great so the new URL will check if this current form is a comment or reply right here and in that case it's going to use our newly created route API comments which also accepts the body but also a post ID right here so we can reuse it like this and if it's not a comment if we're just on our Global feed then it's just going to use slash API slash posts so you can have to try it at now and let's say this is my global Post and let's tweet that and you should see that it's now appearing here but now I'm gonna go into this uh reply right here and try and write this is my comment and we should not be able to see this anywhere for now so I'm just gonna tweet and it says tweet has been created but if I go back there is nowhere to be seen this comment but it's going to be loaded right here so that's what we're gonna do next so let's go back and close everything and let's go into Pages posts post ID right here and just below this form we're going to add a new component comment feed like this and we're gonna pass the parameter comments which is going to be patched post question mark dot comments like this if you save we're going to get an error because this component does not exist so let's go into components posts and let's create comment comment feed.psx let's name the component component speed let's create some interface here so interface comment feed props is equal to comments which are optional and they are an array of objects so record string comma any and just an empty array at the end right here and let's pass these props here so comment P rocks and in here let's just extract comments like this all right and we can just return an empty fragment like this and let's just write moments that map and let's select a comment and let's return for now just an empty div and let's give it a e of comment dot ID like this uh and yeah so we here we have the right comments question mark.map but if you want to improve that you can just default this to an array and then you don't have to use the question mark So if you write comments and default uh give it a default value of an empty array you can just safely write comments.map all right and now let's go back into our post ID here and let's just import the comment feed which we created from add slash components slash both slash comment feed all right now we're not seeing anything here because we're actually not loading uh any comments so for that we're gonna replace this div actually and we're gonna write comment item right here and we're going to invest e this comment dot ID and we're going to pass data which is comment like this and we're going to get an error because comment item component does not exist so let's go ahead let's go into posts and let's just create a file comment item.dsx so in components posts create a file comment item that's DSX well let's name it common item like this and let's just return an empty div to fix this error so go back into common feed and just import the comment item from comment item all right now let's create the interface for this comment item so interface comment item props will have data which is a type of record string any otherwise known as an object so let's assign this props here comment item props and let's extract the data right here all right and now let's add some Hooks and some methods so first let's add our router construther is equal to use router you can import that from next slash router right here at the top after that let's create our go to user method so can't scale to User it's going to be equal to use callback we're just going to accept an event of any let's not forget the dependency array and let's prevent propagation so event dot stop propagation like this we already explained a few times what this is basically it will override the parents on click and now let's just write the router.push and let's open template literals like this and write slash users slash open special object data.user.id like this perfect and let's just pass in router and data.user.id as our items in the dependency array and now let's uh you create our created add constant so cons created at is equal to use memo which you can import from react right here at the top where we imported use callback as well and first let's check if we have the created ad field so if there is no data question mark dot created at you're just going to return no otherwise return format distance to now strict from date FNS which you can import right here at the top so format distance the now strict we already use this in the post item and in here just pass new date data dot created just like that and in the dependency rate make sure you pass data question mark dot created at like this great and now let's get to styling so I'm just going to collapse this all right and let's write some class names for this div order Dash b square brackets one pixel order Dash neutral Dash 800 e.5 cursor batch pointer hover BG neutral 900 and transition and as you can see we have the field for our existing comment right here if you haven't created any comment you can actually go ahead and tweet and you can see that we will soon get another one here I think if we refresh because we have not added mutations actually yeah like this all right um and now inside create another div and let's give it a class name up let's Flex Dash row item slash start yeah three and inside of that I want you to add our Avatar component which you can import from dot dot slash Avatar and just pass in the user ID so user ID is equal to data.user.id all right um and now let's uh go outside of this div right here sorry uh below the Avatar let's just write a in div and let's write another div inside let's give it a last name of flex Flex slash row items Center the app dash two all right inside of that let's write a paragraph which is just going to write data dot user that name I'll write and give it a class name the following backstage right font semi-load cursor Dash pointer and hover underline all right so we have this underline right here as you can see and we have the new user image here all right and let's add a paragraph uh let's sorry let's add an unclick for this paragraph So on click is equal to go to user all right and just below this paragraph let's create a span which is going to uh have data.user.username but before that I just want to append an add sign like this all right and let's style this span now so open last name and let's just write x dash neutral dashboard 100 cursor Dash pointer power underline hidden MD block so pretty much the same as the post item so if we collapse you can see uh how the username will disappear all right and now below this span I just want to create another span which will have a class name of backslash neutral 500 and backslash SM and the value is going to be created as like this and now we can see when the comment was created all right and just outside the span outside this div create another div right here and we're just going to give data that body right here and give it a class name of backslash White mt-1 great and we can now actually see our comments so if I tweet another reply this is another reply and tweet for now I'm going to refresh because we forgot to mutate comments and as you can see we have three replies now and if we actually go back uh you can see that they're not appearing here and you can actually see we have three comments right here amazing and now we just have to fix that this replies are happening here in real time so let's go ahead and do that so let's go back into our form component right here and just uh below this use posts we're going to import mutate mutate post from use post which you can import from add slash hooks Slash use post so we're going to find our individual post right here and give it a value of post ID as string right here and we actually don't need to pass this in this posts up here anymore so you can remove it from here and just make use of it here in use post and just use this mutate post right here and make sure you include it after we successfully comment or create a tweet so mutate post here and make sure you add it to the dependency array all right and if we actually try now is this real time and tweet you can see that we can now see comments in real time as well amazing amazing job and we can actually click a new user and load the new user and we can even go from here and create a reply like this and tweet something great great job all that's left is to create the notifications so that's what we will be doing in the next part of the tutorial all right so in this part of the tutorial we are going to create our notifications so I want to start by adding the little icon to the notifications right here so let's close everything up and let's go in the components layout sidebar item right here and let's import right here BS Dot from from react Dash icons slash BS like this and let's add another property here in our props called alert which is an optional Boolean all right and let's extract that into a props right here so below out let's add alert like this all right and that's now let's scroll here and this is the mobile version first so inside of here open square brackets and write alert question mark BS dot like this otherwise render nothing all right and what we're gonna give it is a class name of textlash Sky 500 absolute minus top minus four left zero like this and give it a size of 70. all right so you're not going to see anything now we can just copy this right here and just paste it after this uh right here and just make the size 70. I accidentally put 80 my bad all right so it can uh stay exactly the same so just make sure you have the alert below this label here and an alert below this icon here and you can actually go into your sidebar right here component and you can go into notifications and add a field Alert in this items to true and just go right here in the iteration and ADD alert is equal to item.alert and if you see we got a little blue dot right here and it can collapse and see that it's here on mobile as well all right and now we're actually just going to modify um this alert through hardcoded value to current user question mark dot has notification like this so it's only going to be triggered if there is a has notification field in our current user which means we have to alert our current user all right now let's close everything up and let's write our notifications API so let's go into Pages the API and create a new file notifications sorry create a new folder in the API called notifications and inside of that create a new file square brackets user id.es all right and let's export default async function Handler request next API request response next API response and let's limit this to get route so if request method is not equal to get return response status 405 and end the call now let's open our try and catch block and let's handle the error so log for development and return response status 400 and the call all right inside of here let's fetch our user ID from the query which we have because of the special next JS syntax right here so it comes user ID is equal to request.query and let's check if the user ID is correct so if there is no user ID or the type of user ID is not equal to string let's throw new error invalid ID all right and now let's find our notifications cell constant applications is equal to await charisma and now let's go ahead and import Prisma so import Prisma from add slash live slash Prisma so await Prisma dot notification dot find many where user ID like this and let's just order by created at sending so we always get the newest notifications and now let's also uh update the user so whenever we load this slash notifications we want to reset our uh has notification field to false so await Prisma dot user that update where ID user ID data as notification is going to be false like this and just return response status 200 Json notifications foreign so close everything and go into Hooks and just create used specifications SDS like this import views as we are from svr import Patcher from add slash slip slash fetcher and const use notifications will accept a user ID which is an optional string and now let's define our Dynamic URL so cons URL is equal to user ID if there is Israeli ID open the template literal strings slash API slash notifications slash user ID like this otherwise null and then let's just add that to the svr so cons data error is loading mutate use svr URL and patcher like that and let's just return data there you go error is loading and new date like this and Export default used notifications great all right and now let's actually create this notifications route which right now is giving uh 404 so let's close everything up and let's go into pages and create a new file notifications that's PSX let's name it notifications like this and let's just return an empty do for now and if you refresh there is no more 404 errors here great uh instead of this div let's open an MP fragment and let's add a header component from add slash components slash header and let's give it a label of applications and let's enable the showback arrow so we can go back from where we came from all right and what I want to do here is I want to protect this slash notifications so it cannot be accessed by unauthorized users because I can technically log out now and yes if I click on notifications I will get a login but if I go slash notifications I can still load them so we want to protect that so let's just go ahead and write export async function get server side procs which accepts context which is type of next page context open this function and let's get our session so concession is equal await get session from next slash next dash out slash react like this get session and testing the context like this if there is no session you want the return redirect destination oops destiny destination slash permanent pulse and just outside this if remember to return props session like this and now if you try and refresh here you can see that I'm actually redirected back to homepage because I'm not logged in so if I try to manually go to slash notifications I'm not allowed to great so but if I actually log in okay and try and go to Notifications now you can see that I can go to my notifications great and now below this header let's add notifications speed which we will have to create so let's go into components and create a new file notification security.psx right here let's name the uh the components notifications bid and let's just return an empty div let's go back into our Pages slash notifications and let's just import this from slash components classifications feed to fix the error all right and now let's add some hooks here so const data current user and mutate mutate current user is equal use current user from add slash hooks Slash use current user below that bonus data attached notifications is equal to an empty array from use notifications hook which we just created and the ID we're going to pass is current user question mark dot ID like this and now we're going to create a use effect here so use effect in which we're just going to re-patch our user so new date current user right here the reason we are doing this is because every time we make a hit to slash API slash notifications uh remember I'm just gonna open its low slash API notifications right here we reset our has notifications to false for our user so what we do here is once we hit that I just want to refetch our current user so the alert is removed every time we click on it on these notifications so we know that we have read the newest notifications so that's how that system is going to work all right and now let's uh create our empty state so if patched notifications dot length is equal to zero let's just return a div the following class names backslash neutral Dash 600 backslash Center e-6 text Excel and let's just write no notifications all right and you will see actually that is our default uh right here so no notifications all right and now for this main function right here uh for this main div let's give it the following class name let's let's call and inside uh open uh curly brackets and right let's notifications that map multiplication which is a type of record string or not any and inside you're gonna return a div which is going to have a key or multiplication dot ID and the class name of the following so it's going to have Flex Black slash row sorry like the show item slash Center p dash six yeah four border Dash b square brackets one pixel and Border Dash neutral Dash 800 all right inside of that we want to add a an icon BS Twitter which you can import uh from react slash items react Dash icons vs like this at the top so BS Twitter right here and let's give it a color of white and let's give it a size of 32 and just below that I'm going to open a paragraph in which I'm going to write the notification that body all right and let's give this a class name oh that's Dash wait all right and now you're not gonna be able to see anything because again we have no notifications so now we're gonna go back into some of our routes like follow like and comment and we're going to trigger notifications so let's go into our like API so close everything and go into Pages API like right here and we are only going to trigger the notification if there is a new like so we are going to focus on this post if Clause right here all right so below this let's open a try and catch block and let's handle the error here just while the error like this the reason I want this to be in a try and catch block is because there is no reason that a failure failure of our notification creation should break the entire API call that's why I want to encapsulate this in its own try and catch block inside our big trying cache block all right so inside this smaller try block right here what I want you to do is fetch our current post so let's go ahead and write on post is equal to await Prisma that posts that find unique and we're just going to write where ID is equal to post ID and now let's see if we have the user ID from this post so if post question mark dot user ID in that case let's create our notification so I'll wait Prisma dot notification dot create beta body someone liked your beat oh and we are also missing the user ID which is post that user ID like this great uh and now outside of this weight right here just let's update our users so await prisma.user.update where ID post that user ID let's just add data has notification true all right so now I'm gonna go ahead uh I'm gonna go to my profile right here and I'm gonna like my own tweet right and after I've liked this I'm just going to refresh for now and as you can see I have a notification alert because someone liked my tweet and if I go here you can see someone liked your Tweet and you can see that because of the use effect my notification has been removed great and now you can actually copy this try and catch for notifications so this field right here and let's go into our comments so comments right here and it's actually going to be the same thing so after we create this comment right here you can just taste this entire thing so we're going to open another try and catch block after we create our comment here we are going to find the post using post ID we are going to find the user using that post and instead of someone liked your Tweet we're going to write someone replied to your Tweet like that and you can just save that and now I'm gonna go again into my profile I'm gonna select one of my tweets and I'm gonna reply to get notification all right and I'm going to refresh actually you can see that we got our notification right here and if I click you can see that we get someone replied to your Tweet notification great amazing and now our notifications are cleared and one more place where we have to add this is the follow so let's close everything up and let's go into Pages API follow right here and again in the post method right here it's actually going to be a bit simpler because we already have the user ID so what we're going to do right here is again open our try and catch clock for the notifications so just log the notification error you don't need to break the entire call because something failed here and let's create our notifications so await charisma.netification dot create data body someone followed you exclamation mark and user ID is equal to user ID but you can just use the shorthand like this and let's update our user so I'll wait charisma.user.update where ID is equal to user ID and data is has notification through and for this one to test we actually need to log out uh actually let's let's actually follow this new user right here so I'm gonna follow him all right and I'm going to log out and I'm going to uh login and as you can see in my profile new user I have a new notification someone followed you amazing amazing job you finished notifications good job you completed the entire project all right to end the video I just want to show you how you can deploy this on Virtual but before you do that I would advise you that you do not use the name Twitter in your URLs because it might be misunderstood as a phishing website this video is purely made for educational purposes and in no way intended to be used for hacking or phishing so creating new repository as you can say I Rene I renamed my repository to glitter instead of Twitter because we don't want our site to appear as a phishing website and you can also go ahead and search for Twitter instances in your app and maybe rename uh welcome to Twitter to welcome to Twitter for example just so you don't get targeted for um phishing so I'm gonna rename this to glitter as well you didn't have to do this if it's just for personal use but if you plan on sharing this with someone it will be nice if you would change and remove Twitter uh instances from your app all right so now just create this repository since this already exists I'm going to use this second option right now I have the splitter deploy right here and I'm gonna go into versal and I'm gonna click add new project and here I have my repository splitter Dash deploy and I will click import and now uh you have to go in your environment variables and you have to add the database URL to your environment variables right here so add database URL and copy the link paste it in the value and click add and do the same thing for next Out jvt secret and next Out secret and just click deploy and just like that our project has been deployed if you had any errors you might want to go to your terminal and just confirm with npm run lint that you have no warnings or errors in your project because any of those can prevent the CI from building and you can visit the website by clicking on the icon and right here we have our deploy great thank you so much for watching this video if you liked it please remember to like And subscribe and see you in the next one
Info
Channel: Code With Antonio
Views: 153,837
Rating: undefined out of 5
Keywords:
Id: ytkG7RT6SvU
Channel Id: undefined
Length: 273min 25sec (16405 seconds)
Published: Fri Mar 10 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.