Full Stack Web Development With React | 2023 Crash Course with Project

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there my gorgeous friends on the internet in today's episode do you see the length of this video oh my gosh we're gonna be building a full stack application using next 13 Prisma typescript postgres all the good latest Jazz that you see there on the internet and we're going to be building this app called posted that lets you make posts lets you add comments on other people's posts you can delete your posts um we have authentication on the server which is really cool and we're saving all that all the users to a postgres database so there's tons back then this so I really hope you subscribe damn it you could say it's as brilliant as our today's sponsor this episode is brought to you by brilliant I absolutely love brilliant especially as a web developer that always wants to expand his knowledge in computer science I've been avoiding certain topics I'm not gonna lie such as algorithms and data structures because it's really hard to find a fun and easy way to learn and to be honest but brilliant offers you a wide range of these courses including computer science data structures and machine learning I highly recommend you check out one of their computer science courses it's wonderful and not only that the the courses are extremely Visual and interactive which makes learning incredibly incredibly effective the try everything brilliant has to offer free for a full 30 days if you visit brilliant.org developed by Ed or click in the link in the description and I should also mention that the first 200 of you will get a 20 off the Brilliance annual subscription so check it out and let's get into the video okay so let's get up and going shall we so let's get next installed we can run next uh let's let's find the beta docs here really quickly because I always I don't know about you but I always forget this goddamn command here which is this one so let's copy this over there we go cool and then we'll give it a name so let's hop in here enter and then we'll give it to name let's call this post it all right typescript yes please yes no Source directory no because we're gonna be working with the new app directory and import Alias we're gonna keep the default so that's cool so that's gonna get next install for us where is it installing I actually have no idea oh gosh you know what's horrible when you end up making a get uh get directory right in your root file system that's a bit annoying but it's okay so let's just see the answer now that's fine CD post it there we go and we'll say code dot which is going to open us the project up right here alright so just a clean installation of next JS that's fantastic we can go over here let's let's get up and going npm run Dev all right cool so now we can open up the development server yes all right so to start this off let's just clean up all of our folder structures here because I don't want to have loads of the site that we never end up using so let's head over to page right our home page and let's just clean everything up from here everything we'll keep the main section and then we'll just clean up everything from here and that looks fine and let's just add a hello next in here and hit save cool so there we go that works that's perfectly fine and now we can just get rid of this uh page module CSS because we're going to be using Tailwind and that's it that looks good to me we'll keep the CSS that's fine cool so let's get Tailwind up and going so let's head over to detailments yeah I know there's someone uh that posted the comments saying hey you can run this command to automatically add Tailwind as well damn it I wish I had that right now but we're just gonna do it manually so everyone can follow along so let's copy over the second command here that says install tailwind and auto prefixer so let's paste that one in let me switch my there we go so let's paste that in and we're also going to get the second command from here cool so let's paste that one in and then we're just gonna copy over this content bit over from here and paste it in here now what does this do essentially it just says hey take um the app app folder Pages folder and components folder and Source folder which we can remove this last bit as well and just look at all the jsds jsx and TSX files in there and if you recognize any Tailwind well then use it in this case we'll never use the source directory here anymore which was the old next JS so we'll just get rid of that and keep app pages and components all right and that should be it the last bit that we need to do is just add this to our Global CSS so just paste it up here and that should be perfect so now we should be able to just kind of open this up I'm actually going to put it by the side so we can have our website just opened up here okay let's give it a try npm run Dev click on this and let's see so there we go as you can see the styling applied but if I want to change this I can say class name and I can say text large with some padding yf5 and there you go it works cool all right so that is Tailwind set up for us next up what we want to do is get a database and connect to that database and communicate with that database somehow so for that we are going to head over to railway which I think is a fantastic Wii app uh that you can use to just add a database uh you can hit start a new project and do a provision postgresql you can do manga DB as well or MySQL that's going to work just fine but do postgres I already have one here because I made loads of them in the last last bit of time and I'm just gonna I think I'm just gonna use this one here surely it's here somewhere oh and uh I've used it for quite a bit to be honest and it didn't cost you much I mean actually this is free I should clarify wait I don't want to talk about payments this was free I just signed off and they give you credits but I've been using it for a good month now and I it's just been like 70 cents so far as you can see right here uh so it's not bad at all it's really good optionally you can use something like super bass that's gonna work fine as well I'm just gonna quickly delete these just so you can I don't know how to delete them to be honest I've never the latest one let's just make one from scratch okay new project postgres and there you go all right so let this initialize and whilst that's initializing let's head over to Prisma and click here and do a quick start and we'll just need to install a couple of things here so let's do a start from scratch with a relational database that should be fine all right so let's copy over this command here paste that in so we're installing typescript Prisma and TS node oh and I also should mention what Prisma does for us because I haven't so prismo let's us communicate with any type of database pretty much using only one syntax so if you want to use uh I don't know where did they say they say it's somewhere down here if you want to use Bongo DB if you want to use here we go postgres MySQL sqlite [ __ ] cockroach you can do it using uh you can connect to any of these and then the syntax is going to be the same so that's really cool and it's also typescript uh uh has typescript safety and auto completion which makes it really nice okay so we installed that command which is fantastic and then we can run this command down here saying MPX Prisma in it so let's run that and now it's gonna say oh cool a Prisma folder was created with a schema for us next up set up the database URL and the EMV file so not only generated as the Prisma folder it also generated us this dot EMV folder and what does this dot EMV folder is well basically any sensitive information you have here that you don't want to share with anyone uh you want to put in here so basically like a password right um so in this case we basically Railway is going to give us a connection string and if we have access to that connection string we pretty much can communicate with our database so you don't want to give this code to anyone you want to make sure it's nice and safe I'm gonna show it to you now because I need to show you further tutorial but here it is if you go to connect copy this over again don't share this with anyone just add it to your EMV and that's fine and don't copy mine over it because I'm gonna figure it out how to delete this postgres okay so let's paste that in hit save and that's it so now if we head over to our Prisma schema here as you can see we have this data source DB where we basically pass down this EMV database URL from our EMV file so basically when you put push this code up to GitHub or whatever this is all that people are gonna see database URL they don't actually get to see the uh the actual value of it here Okay cool so we have that all set up which is amazing and now what we need to do is essentially make a schema um so let's go down here and if we check here the quick start sorry a model not the schema uh if we go and just go through these steps as you can see we we did these here okay so creating a database schema here we go so you basically make these models which are kind of like a blueprint to how your data looks like so for example a model post here right it says it has an ID and it's a type of end all right so we know it's a number whether it's a float that doesn't matter too much it's a number and then we can specify here with some special keywords that it's an ID and also that by default it should just Auto increment forever one two three four five six seven eight nine blah blah blah okay so you can uh you can put in these special little keywords that Prisma provides you and we're going to get more into those later uh create an ad as you can see we have a default on it now so if it's not provided it's just gonna put the time that's now then we have a title this type string again we can limit uh the number here the the length of the string with varchor 255 and then we have content here and we have an exclamation a question mark which basically shows it's optional you don't need to add this but it's here in case you want it and then we have booleans and then we have a um what's it called the relation setup here with a pro profile or a user or whatever so you can set up these relations as well and the way it works is essentially you just make another um property here so I'll try ID which is end and then you add the special keyword saying at relation and the fields you want to specify here is one of your fields that you made in the post here and then it references the ID from uh the user so if we go to here to user as you can see it's also in there I'm gonna go through it when we do it so don't worry about it too much but essentially what I want to do now is let's just try out one we'll just copy paste over this post here okay and as you can see we use this one syntax as well and at the end it's just gonna output raw SQL for us so so let's just paste that in here for now okay cool and we can remove this relation we don't need it so let's just get rid of that and this okay hit save and let's put this back here cool let's hit next install Prisma client so Prisma also comes with a client that we need to copy over so let's install this as well and with this client we essentially get to make any reads or writes or updates or whatnot so let's install that that's perfectly fine and now what we're going to do is make instantiate this client we're gonna head over here to the Prisma folder and this is from the docs so I just highly encourage you just copy pasting this over to be honest and what we do is we make a new file we'll call this client.js and we're gonna Post in this code right here which I'm going to explain in just a sec so we're importing this Prisma client and then here all we're doing essentially is we're checking if we are in production or not and we're creating One new Prisma client and that's it if it already exists it's going to check on the global like environment if Prisma exists if we already instantiated the client and if it exists we're not going to make a new one so essentially we want to just instantiate this once and Export it and then we can take this client and do client dot whatever get a user and then find any user okay cool so that's all set up that's all nice and dandy uh again you can just copy paste this over if you wish and that's it we are ready to go we have our model in here as well our post model so now here what it's saying is run Prisma DB pool to turn your database schema into Prisma schema so what does that mean well let's say that we have some data already in our database here right um then what you can do is just run the command pull and it's automatically going to create this model for you but in our case it's the reverse right we have the model here but we want to push it up to the DB so we can do exactly that we can run the command Prisma what was that it doesn't show here but it's Prisma MPX Prisma migrate Dev I believe so let's let this load up and see if it works how you doing anyway this is taking a while doesn't it yeah once we have everything set up uh we can just get to it and you're gonna see how fast this workload workflow is oh look at that so it generated something for us which is a new migration uh folder here so essentially every time you make changes to your models here you can push up a new migration and then it's gonna just update it with the new models so let's call this just a post just the posts piece of oatmeal thing okay and there we go and that's it so now if we refresh we should have a post model yay there we go that's pretty cool isn't it all right and that's it and if we want to we can also go here and add a row and we can just add some data if we want to but we'll just leave it right there all right let's also run this command Prisma generate which I think it did by default which essentially is gonna a synchronize the client with our database here so whenever we're trying to fetch something it's going to autocomplete nicely for us and you're gonna see all the data in the client as well you're going to see that in just a bit but okay so that's great we have everything set up now I think the next step would be to set up off because we need specific models here for our off system as well so let's head into next often okay for the next part let's set up off using next off it's fantastic it works so easily so let's head over here and get started and we're going to run this command here npm install next off so let's get that up and going fantastic so that's installed um next up what we want to do is make a new route in our API routes so where is that well if we head over here two pages as you can see we have a one hello TS file we're gonna make a new one here a new folder and call it off and in this folder we're going to make a new file add brackets and dot dot dot next off dot JS like that cool now we're going to copy this over actually we are going to be using Google but you can add your own if you want to add more to it I'm gonna put the GitHub code up and that's going to have GitHub as well in it um so let me just look and find that just so we can keep on going and we don't need to stop for too too long um okay so here's what we're gonna do we're gonna import next off like that and then we're going to import the provider and we can do that with let me make space here we can do that with next stop provider slash whatever in this case we'll import the Google provider like that okay so that's two uh next up what we want to do is also install an adapter and what I mean by that is we need an easy way to set up the Prisma models and make it work with next.js together um so we can head over here actually to Providers and find Prisma so let's see where that is surely it's here at P am I blind let's do a sorry it might not be providers adapters that's what I meant uh where is it where is the Prisma there we go Prisma Okay cool so essentially we are gonna install this adapter see we could have just run this command to be honest and install next off Prisma client and the adapter as well so let's just run this for now npmi prism adapter cool so there we go so we have next stop imported Google provider and now we can do the Prisma provider as well so let's paste that in there let's make this smaller all right there we go we have our Prisma adapter and then what we need to import what is this that's the client that we made in our Prisma folder so let's get that in as well import Prisma from dot slash dot dot slash no dot slash um Prisma slash clients okay cool and then we'll say we can just copy paste this over to be fair like that and now we need to add our Google client and our Google secret here so do you remember how we did the EMV file well next uh also can do EMV but we need to do it a bit differently rather than this the imv we need to make it dot local.emv if I'm not mistaken and you can check that if you head over here oh it's the EMV the local so let's rename it to the EMV dot local cool uh let's close these up and again any environment variables you have for your next app you can do do that in here okay so let's define these we can say Google ID and we can also say Google client secrets cool and let's set that equal to whatever we want so we need to head over to Google I think it's developer console or something like that okay so next up what we're going to do is head over to Google Cloud here and I'll just make a new project full stack react here which is fine uh you can just make one in like a second here and then we're gonna head over to apis and services ah their UI is just so much going on all the time uh but essentially you want to head over to credentials here and then create the new credential oauth client ID and here application type is going to be a web application I'm going to call it post it and then here we're going to add localhost 3000 make sure you remove the slash at the end and the authorize redirect uri's well that's gonna be from let's see because it's going to tell us what to do here here we go it's this one that we need right here so let's copy and paste that over so localhost 3000 API off callback Google and let's create all right and that should be fine it's going to give us a client ID and a client secret which we can paste in here we go and that should essentially be it so let's hit save on that and let's also restart the server which it is so perfect all right so we have that hooked up so our off should be fine for now and next up let's close some of these bits up and let's add the models um that it requires for it to work so here we go I just highly recommend you copy pasting everything over from here so for model account all the way down here to the verification code all right and let's head over to Prisma here and let's simplify this as well uh let's just keep it for now let's paste this in here so essentially what it's doing is every time we go through Google off it's going to automatically make a new account and set up all the sessions for us the verification tokens and all of that good jazz so then we don't need to worry about it anymore so that's fantastic um I just want to quickly update this uh post here uh rather than incrementing it by one so one two three four five I can do ID here and I can do default cuid all right this is going to generate us a random string for us um which I just think it's better than having one two three four five all right we have an error as well um this is a string that's why it's not letting us do that all right create an ad that's fine update to that that's fine then we have a title of string I'm gonna remove this skip it nice and basic um content We're not gonna have content we're just gonna have a title um and that's gonna be it oh and I also want to make a relation between the post and the user all right so basically I want every user to have loads of posts so it's basically what you call it the industry if I might add a one too many relation right you have one user that has many posts all right so again how do we do that well we need to Define just a just the property here on the post so let's head over to post and I'm going to call this user ID all right and this is going to be a string all right and now using this we're going to connect it to our user so all we need to do is say user here um or I can also say author but let's say user is gonna be of type user so I'm specifying here that hey make a connection to user here and the relation here is going to be fields I'm passing the user ID and that references the ID from the user down here all right cool and that should be it it's erroring out not anymore cool all right so we have all of our models set up and now we can run MPA MPX Prisma migrate Def which should set us up and we should be pretty much ready to go and always make sure you commit your changes before you do too many in my case I just have to do all of this in one go because it's a damn tutorial but it's fine life is good I'm taking pills I'm joking I'm not taking pills don't go that would okay uh enter a name for a migration we're gonna call this we have users and post models cool Batman's here if you have anything to throw out pass it to be all right that's it okay so finally we can finally say we have most stuff all set up and ready to go thank God okay so let's get going then shall we let's so let's start off with just fetching all the posts all right no matter what user made the post who made the post let's fetch it um so let's head over here as you can see it updated our our thingy here um we could just make let's go here add a row the problem is though as you can see now every post has to belong to user all right so maybe we're gonna do it a bit in Reverse where we're gonna make a post first and then go from there and retrieve it we'll see how we do it you know what since we actually are on the topic of authentication let's just set up off with um with next stuff okay and we're gonna deal with server side as well which is really fun so how do we how do we how do we get up and going then well here's what we're gonna do we're gonna create a nav all right so let's head over to our folder here cool and let's call yeah let's make a folder I'll call it off and I'll place the nav in here because to be fair this is where we have most of our logic anyway so let's call this nav dot DSX Okay cool so now one thing I want to mention here is we are going to do server side off for this one um because we can and it's easy and we don't get the flickering anymore of uh the user coming in or not we get the user back straight from the server and with that we also have a couple of advantages that we can do on the back end here so yeah that's what we're going to do so let's do an export default function async function nav cool all right and then here we are going to return a nav that has let's say a a link in here and let's also import that has a H1 that says send it dot cool oh also we have to make sure to return everything here so let's do that cut that paste it down here cool and now this is going to take a href that's equal to slash all right and that's it so let's go up here and import link from next link all right so essentially we are just rendering out the H1 and it's gonna send us back to the home page that's it for now okay so where do I want to render this out well I want to render it out pretty much on every page uh so what we're gonna do is actually head over to layout.tsx and we are going to import it right here so let's do Imports nav from dot dot slash or I think it's let's see dot slash off slash nav Ley and then we're gonna take that and just render it out right here above the children all right because Children Here essentially means every page so whether it's a home page on about page we're gonna make them soon but it's going to render out every page now as you can see we have a little error here on our screen saying nav cannot be used as a jsx component as return type promise element is not a valid jsx element I believe that's because uh next is still having a bit of a type hard time or I should say typescript recognizing the server components and then it's just going to throw an error out because it's not going to know how to handle this promise for us so for now just for the layout I'm going to rename it to jsx until it gets fixed or a better solution comes out for it so I'm just going to update this as well and we're just going to remove this child type here as well and whoops let's see I need to remove just this bit here from it and hit save all right and that should be fine for now so now if we try to render the screen out we should be able to get npm run Dev we should be able to get our nav perfect and there it is uh cool next up what I'm gonna do if you want to import a font I'm just going to do it up here import trabato from next font and then I'm gonna Define it down here which you can do like so you make a variable you instantiate this robot Roboto and you can add a subset away to it if you want regular bold and then you can also add it to a variable here um all right cool so let's head over to the body and add some basic styling to this so it's the mx4 which is margin X just push it in a bit and then for medium screens I want MX 48 and for large screens I want MX 96 now what does that do I'll take a look the smaller it gets as you can see the more space we have available but if we go on a larger screen so that's medium and then if we go larger as well then it's going to add 96. so it does nice breaks for us automatically which is really cool next up let's also add the font so let's just change these strings to backthicks like that and that Curly braces around them just so we can add some JavaScript in here so we can do dollar sign curly brackets for bottle variable and hit save cool so that should give us Roboto as well and let's add a background Ray 200 as well cool now what is that all about I think it's something with our Global CSS so let's just sat here and remove a bunch of stuff I'm not going to use this let's get rid of that I don't want this to have a background let's get rid of the body to be honest and yeah that's looking fine cool let's close this up let's hit save on that lovely okay so that is essentially our layout setup and now we can head over to our nav and add even more configuration okay I want to talk about this a little bit because it can be quite confusing so what we want to do next is essentially be able to fetch the user in the server component and then yeah just have the user right the problem is though we're gonna have like a login button right and we're gonna display different kind of information depending if a user is logged in or log logged out the problem is though um I kind of have a button here that has an on click on it because that's going to error out it's going to say hey server components cannot have that only client components so then you might be wondering well how can I get the best of both worlds because I want to get the user on the server but I also want to have the interactivity well the way we can do that is we can have our nav as a server component and then we can render out a client component in here all right so I can have a login and a logged in user in here so let's do that let's make a new file here and the off folder and call it login.tsx and this is going to be a used client so there we go so now we can import sign in from next off slash react and down here we can say export default function login like that and here we can return Let's do an Li and where does that not work Li hey autocomplete why you do this to me okay cool um and this is going to have a class name of okay so I guess all the autocompletes don't work anymore a list style of none this is uppercase as well it just makes you realize how badly you can type if you don't have the auto complete we have a button here cool and this is going to have a class name of uh text small we'll add The Styling later let's just render out the button here it's called sign in cool and then this one has this button also has an on click that's going to run the function here sign in and that's it it's super simple that's all you have to configure up all right so we have that going which is great so now we can go back here and import it and basically here I want to do a check essentially so we have our link and then we'll have a UL here and then we want to check if the user is here and based on the user we want to do the login or not so let's just render it out for now just so we can see it and then let's go back to our uh yeah let's style this up as well we're going to say class name this is going to be Flex justify between like that we're gonna say item Center and py of eight to give some padding on the Y and X all right and then we have our title or what should they call it not title our logo font bold that looks good we'll do a text large on that cool and then the UL is going to have a flex with item Center and a gap of six because we're going to have another item here soon Okay cool so we have our styling let's go over to our login add a bit of styling there too uh I'm just gonna quickly copy paste this over actually not I never like people that copy paste things over class name we're going to do it so you can see all the changes okay so text small just going to make it smaller BG of gray 700 it's going to add the background with that color to it oh I already have a class down here so I just have it there there it is cool so that's small we added the background [Music] um okay let's see what else we'll do text White pyf2 for padding PX of 6 for X and Y we'll do a rounded of excel and disabled of opacity 25 just in case we decide to do something with a Okay cool so there we go and look when I click on it it's going to direct us to sign in with Google so that works that's pretty cool yeah let's do why not click let's see if it goes through and it looks like it did but I think it's gonna actually error out for us we'll see okay never mind looks like we have no errors so what we need to do is actually change this code up here a bit in our next off uh essentially what next off recommends us to do is um Define this file a bit differently so we're going to see const adapter outside here we're gonna pass it the Prisma adapter essentially this line of code here right I just paste that in there like that and then we're gonna say export const off options here and then we're just going to copy these over now so we're going to say adapter well actually I mean we could just leave it like that that's quite silly now I realized we could just actually copy everything over from here like that I just want to have this next off separately here so again if you want to do another off you can just go down here and do it here but what we also need to provide that is a secret it's just gonna bug you about it it's going to say add a secret otherwise it's not going to work so we're going to say process.env dot off secret I don't have this but we'll make it now so let's close the server and go over to our so let's copy off secret go over here pass the off secret and then just type type something whatever like that cool just the secret that we set the password that we set and finally down here what we're going to do is uh we're gonna do export default next off and we're just gonna pass in the off options here like that like that okay cool so that should be all nice and dandy now so now I can just Import in the options here the off options and pass it to let's go here import from next off slash react get believe it's get server session let's see yeah get service session there we go cool so that's nice and dandy let's see if that works then so down here now oops we also need to import the off options as well as you can see they recommended the same way Import off options from not about Slash dot slash Pages slash API off slash next off cool so now to get the actual user we can just say cons session equals await get server session and here we can pass in the off options and that should be nice and dandy let's console log that out npm run Dev so let's go here and look at that we get the user back awesome how cool is that so that's all on the server done uh so yeah you don't really need to worry about anything to be honest let's check our database as well if we head over is this our table is it let's refresh there it is cool so we have everything and if we check under user look at that we logged in so we have it cool isn't that really cool so now here what I can do is essentially check if a user is available or not for me so let's head over down here and all I'm gonna do is say curly brackets if there is no session and oops sorry Dot user like that as you can see it autocompletes for us and login all right so we only want to see this login screen if there's no user currently signed up otherwise session user and I can just do a H1 here for now we'll replace this logged in or I can just say something like user sorry session dot user dot name for example and as you can see we get all the autocomplete which is really nice with typescript so now if we head back here look at that develop I had so we are logged in yay it works and that server side off how simple is that that's really cool um but let's create a new component here so we're going to call this logged.tsx okay so again I can do a use client here it's fine I've done my uh Logic on the server anyway so it's all nice and dandy then we're going to import image from next because we're going to be working with that and of course I want to be able to sign out so let's also import that next off slash react cool and let's also have the link imported from next link fantastic export default let's call this function logged cool so here we're gonna return a li sorry my my thingy is being a bit slow and Li there we go and in here we're gonna have a class name we're gonna say Flex gap of eight and item Center so let's just put one thing in here and then we'll add the rest just so you can actually see it on the screen now what's wrong with my autocomplete I don't get it okay bye what is this buffoonery let me hit save on these files yeah I think by code editor is just running a bit slow unfortunately there we go Okay cool so button and here we'll have a sign out let's just say sign out cool and let's import it here now so Imports logged and rather than saying that we'll just say it logged so now we have a nice little system set up here for us that's quite easy to see let's also remove that so as you can see we have the sign out button so that's fantastic means we're logged in let's customize this as well we'll add a class name to it BG gray of 700 text White cool we'll do text small we'll do a padding X of 6. all right a padding y of Two and a rounded of MD there we go that looks fine enough nothing too crazy and then here again since this is use client right I can just add an on click that says and let's see how do we actually run this code oh yeah we do a callback function here that basically says sign out and that's it and then next off is going to take care of everything else next up we have pretty much our profile image here so I'm going to have a link here that's going to take us to a page which is our dashboard so I'm going to say href equals to dashboard and then here we're going to have an image tag of our profile that's going to have a width of let's do 64 a height of 64. and the source of image what's that I don't have that though that's fine we'll we'll import it now let's import link first of all uh image let's see what image says here I think it's just complaining because there's no image here so what we can do is just pass it down from here from our session right so I can go here to logged the years if the user is logged then pass down the image from session user image and as you can see we have autocomplete as well which is fantastic and it's actually suggesting if we do it like this so session dot as you can see user with a question mark because we're not sure if we're gonna have a user on that session object yet dot image like that cool um yeah amazing so let's see what that says it says image does not exist on type intrinsic it might be because we we get back undefined initially I feel like that might be see it can be a string or null um so I wonder if just adding null here is going to fix that issue looks like it's not what if I try let's say uh let's see an empty string okay I actually think the problem might not be here but in here so let's also specify it in here that the image that we're getting so we're going to get an image and that's going to be I'll just make a quick type here type user is going to have an image that's going to be a string all right and then we can add it here like that okay cool so no errors here yeah there's something with this image attribute that's causing issues for me so I believe the issue was that we didn't have all the properties that it requires configured so I just added them and now it seems to be fine but we have another error message which says invalid Source prop add this to hostname to whatever next JS config file so if you get this error message here what you need to do essentially is head over to the next config file right here and just add here so experimental that's fine add images here domains that we're gonna get them from Google essentially and if you have some from GitHub as well you can specify those as well so that's from Google all right that's where the content is coming from if you want from GitHub you can do this one like that all right so you have both there so just restart the server and then everything should be fine let's see did we get any errors let's hope not yay look at that we have our user yay awesome so that works fine we still seem to have some sort of issue here where image it says is not assignable to type string so let's fix that up as well so to fix this issue here we can just add an or an empty pair of string and that's going to be fine as you can see that's perfectly fine now cool so there we go we have our page all done that's really nice full on nav set up cool so next up what we're gonna do is probably set up the dashboard for us and also an input where we can start making posts so let's do that next okay next up let's try to make a post um and then we'll try to retrieve the data from it okay so let's head over to our let's see how should we make this let's make a folder here we'll call it components for now if this gets too big we'll just uh we'll just make more folders in the end so in the app directory make a components folder like that cool and in here we are gonna make one called at post dot TSX nice so what do we need to do well this is going to be very client heavy so making pose getting them I want them to be all that's the only reason I'm not doing server side rendering for this is because uh we're gonna have posts that are gonna keep coming in every second and then we're gonna have comments which I want all of them to be dynamic and that we get to see the latest data and we can interact with them so it's very client heavy so we're gonna use use client here at the top and next up we're going to say export default function create post fantastic here we're going to return whatever we're going to return in this case it's going to be just a form uh we're going to leave the action out of this like that um and then we'll have a div in here with a text area this is going to be our input um okay we're just gonna have a name here so let's do that title a value of title now what's Title Here I don't have it I'm gonna basically just import you state from react which is going to allow us to save it down here so let's say title and set title use State and we're going to have a string basically here right so I'm basically saying the value of title uh which is nothing should be the value of our text area however on change so if I start typing in it I want to basically just update this title value so on change and we're going to run an arrow function here where we have the event and I can set the title if we just do e Dot Target Dot value there we go that's going to get the text areas input value all right and then we can do a placeholder on it as well I can say what's on your mind there we go and let's import it in our page as well so let's go here and our page and again this is going to be use client as well because I'm gonna do loads of fetching data fetching using a react query all right so we're going to show that off as well okay so let's import add post from dot dot slash dot slash component slash add post cool and then let's just render that out here add post like that ah there it is cool okay so now we can spend some nice time styling this up a little bit making it look nice so let's see what else I'm missing yeah a class name from this so let's do a class name B4 text large rounded oops there we go rounded MD my2 BG Gray f200 there we go and um okay and then on this div here we'll add a class name of Flex with a flex call and a myf4 there we go push it down a bit and then the actual form is going to have a background of white so let's do BG White there we go so we can actually see the form my of eight push it down a bit we'll do a big padding on this so we'll say p8 it's kind of push it in like that and rounded of MD as well cool so there we go we have a Wii input there that's fantastic and then we're basically going to have another big div so we have one big div here and then below it we'll have another big one that's essentially gonna hold the button that says create a post there we go and then we can go here I'm just going to copy these over and then you can paste it in as well so we also have a disabled here which I'm going to make another state of basically when I create a post and I click on it I want to disable the button and wait for it until it finishes it finishes uh making the post so I'm just gonna make an is disabled and set is disabled here we're going to set that equal to U States and by default it's going to be false okay cool so it's disabled so by default it's going to be false so we can see it cool um all right so that's one that's fantastic we have the button up oh the classes so Tech small bgtl text white p y p x rounded Excel and disabled and I just change the opacity cool uh what else are we gonna have in here we're gonna have like that text that shows how many characters we have left um we still need actual actually I think we can just do that now let's go on top here I'll say p um because I do have access to the title so that's actually fantastic so let's do a it's going to be a crazy class name here okay so hold on tight um okay class name let's do it and get rid of this and do backticks okay the symbols next year one on your keyboard like that let's do Flex item Center justify between gap of two my apologies this should go on the div so just cut that out you can leave the structure up here which is fine and just paste that in there class name like that cool and in here then we'll do font bold text of small and then here for the actual content we'll do backticks again dollar sign curly brackets titled all length so we'll take whatever length the title is slash 300 like that so this is just a string and this is we're interpolating the actual number there see cool um so to finish up the styling on this we have the text small and here check this out what we can do dollar sign curly brackets again title the length so if the length of our text is bigger than 300 question mark okay text red 700 so if it's bigger than 300 or there's more characters than 300 turn the text Red otherwise I can add a colon there text Gray 700. if it's lower than that then just make sure it's great so now if I start typing in look at that it works really cool huh um anything else that we need to do I think that's gonna be it for this part here all right cool so we have our input set up and now we can start making uh requests so let's see how that holds the Buckle works out okay so for the next step we are going to start fetching data and posting data so normally if you just work with server components and you don't have data changing that frequently you could just use the fetch API and fetch it directly in the page right here you can mark this as async function do fetch here and that's you're pretty much it um if you want to do with client side I found the best thing to do is really use a good library for that and in our case we're going to be using pen stack react query so if we go here click get started and it's one of those packages that is so useful and it works with different Frameworks as well so you're kind of learning one thing and then you can apply it pretty much everywhere else um okay so let's start installing the sucker shall we so the first thing that we need to do is run the installation command which in our case is npmi 10 stack react query so let's install that cool and that should be it and then to actually Quick Start oh I don't know where this here but I'll show it to you now okay npm run Dev let's run the server back so what we need to do is essentially wrap our application with this react query and to do that uh it's going to be very simple let's head over to um I'm just going to make a new a new file I'm gonna add it in here it's not related to off but it's I mean it's close enough we're gonna call it call this query wrapper.tsx okay so here we're going to say use client because again react queries mostly gonna you're mostly gonna use it on the client and then I'm gonna say const query client equals to new query client like that and that will import from react query and what else we need is a query client provider all right so just import these two things invoke this function here and then essentially what I want to do is just make a wrapper here so query wrapper equals to children like that where we're returning essentially all I want to return is this query client provider like that with whatever children we have in here in this case our whole application pretty much is going to be there and then export default query wrapper cool okay let's hit save now this is complaining it says um type children any is not a site assignable to type intrinsic attributes blah blah blah all right so to fix that all we need to do is let's go up here and we're going to say interface all right I guess we could just do type as well interface props and Children Here question mark is a react note all right this is just to get rid of the typescript error message here uh we can just add props like that essentially just saying hey we have children here which is a type of react node and that's it and here basically we just need to pass in the client that we just made here so query client all right that's essentially kind of the setup file for react query again you can just do a copy paste to be honest and then what we need to do is take this and we'll head over to our layout where's my layout here let's get to our layout and we're just going to wrap our all of our content with this query wrapper so import query oops query wrapper like that and then we can just wrap these two up so let's go here query wrapper cool and that's it all right so that's uh react query all set up for us and that should be working just fine now cool so we can close everything up now and let's head over to our ad post here we go add post let me just make a bit more space here so we can see what's going on uh maybe I'll close this up as well okay so again if you remember we're just basically saving uh whatever we're typing here over to our title and then we have our is disabled which just disables the button whenever we want it to all right so that's all we have right now let's import use mutation and use query client from oops what am I typing from tan stack react query cool use query clients there we go Okay cool so use mutation essentially allows you to make a yeah mutation and you're changing something right whether that's updating or deleting or creating that's a mutation um so what we're going to do is essentially come here I'm just trying to find a good space to do it let's do it here I'm going to say create a post so essentially what we're doing is we're going to invoke this use mutation so we're going to have a mutate here and say use mutation like that and in here what I want to do is fetch whatever data I want to fetch or create a data or posts or whatever sorry I shouldn't say fetch because fetching is not a mutation so here is basically where I'd get an API to send data to right but we don't have any API set up right so essentially we need to set that up so let's get rid of this and we also need to install let me just kind of show you I'll set up a basic version here we need to also install axios because react query doesn't actually go and fetch you the data so you either have to use axios or fetch we're going to use axioms because it's cooler so that's also import that import axios from axios cool um now you might see an error here which is from axios I'm not sure um and we don't have it now they might have fixed it if it pops up I'll tell you so don't worry about it okay so let's set up a basic uh create post here so again you have mutate here from the use mutation and in here basically uh you have options right the first parameter that you have in here is a function that can be async and you can make a call to a API so let's say async we'll have the title in here right I'm going to run an arrow function and actually I don't even need a the curly brackets I can just return it like that I can say await axios dot posts because I want to make a post over to slash API slash posts slash add post now I don't have this again but don't worry and comma uh whatever data I want to send through so in our case it's just going to be the title because we are getting that data live Okay cool so that's that's pretty much it so let's create uh this API route now so let's head over to our pages and you see this hello TS we're gonna modify this one so just make a new folder in here in the API folder and we're going to call this posts and then here we're going to make a new file called add post dot TSX cool and we can just copy over this um boilerplate here from Hello and then we can just delete it cool so we have our all folder and our post folder fantastic okay so essentially what we have in here is a Handler that has a request and response and then we can do whatever we want to do with it here and this is just importing the types that the request and response have and that's it and then we have a data type here defined for the name that we're returning um okay so let's just get rid of this let's get rid of this we don't need those two and let's also get rid of that okay so essentially here what I want to do is check if well if my request dot method was a post well then I know I can do something here right uh what I should check first is hey is the user logged in because if the user is not logged in then they cannot make any posts so essentially what we can do is import um let's see where was it we defined it somewhere oh and our nav correct if we go to our nav we did this well we can do it here in our API routes as well because this is all on the server so let's go here we might need to modify the Imports here so that's fine but this one is not so let's do dot slash dot slash dot slash um what am I looking for I forgot what I was looking for okay off okay so that cool so slash uh where is it oh is it here dot slash off yeah that's it there we go oh gosh okay so there we go essentially what I want to do is well check first of all if if there's a user available here so get server session I'm going to pass in the request and response that's how you did it for the API routes and finally we can pass down the off options cool and we don't oh yeah we can Define this as async as well there we go cool okay so if we can say and well if there's no session then you cannot make any posts so I can just say return response with a status of 401 and a Json of that has a message in here and it just says please sign in to make a post okay cool all right so that's our check there if the user is logged in or not and then we kind of need the data somehow access to the data so okay so we have that line and then in here still in here what we can do is say um yeah let's do console log request dot body because that's where we're gonna have this access to our title so just constantly log it out here Okay so I'll see this error message I'm talking about I don't know every time you import axios you get this error now this might be fixed if you see it just ignore it for now everything still works fine so create a post and nothing happens well there's a few issues one of them is here there's nothing really set up here to make this work when I click on the submit here it just refreshes the page and ignores everything that we're making here so to fix that let's head over back to our ad post and essentially what I want to do is create a submit post here so on submit a submit post all right this doesn't exist yet so let's just go down here let's do it right above here const submit posts equals to async function um what am I doing here there we go where we have an event right there we go cool and it's gonna say he is declared but its value is never used and E is implicitly has a type of any all right so it doesn't know what it is so if I type e dot see it just gives me nothing so we need to specify that this is a like a form event in typescript so we can just say react Dot form events like that cool and now when I type e as you can see it recognizes all the events that a form event would have which is quite helpful so I can do e prevent default and that just stops the refreshing when I press the button and what I can do is also set disabled here to True right so disable the button and finally this doesn't run until we call this mutate so I'm just gonna say mutate and pass in the title all right because this is gonna go in here to this callback function here and then it's going to send it true all right and that's pretty much it let's hit save let's go down here on the button as well I want to make sure it's a type of submit and that's looking that's looking pretty good so hello create a post and as you can see it disables it and let's see and look at that in our API we get this back all right we got an object back with a title of hello all right so yeah that works just fine so in our ad post and our apis we know we have a title here which is fantastic um so let's use it then we can say constitle equals request by the title all right we can get it like that and I can also specify that this is a type of string cool next up what I want to do is do a check on the title let's say if the title the length is bigger than 300 then return response with the status of 403 and the Json message of um let's say please write a shorter post okay and that's essentially kind of how you work you you make a request here and then you can do all your validation here and then you can catch all the errors with the messages that you're sending from the server here to the front end so it's quite a nice system oh we have an error here uh we'll fix this in a bit that's fine it's just the typescript error but yeah that's it and then we can also check uh if there's any length in here so I can do something like if the title the length is just left empty then I can return res dot status of 403 with a Json that has a message of please add please do not leave this empty okay cool so those are all our checks right but if everything goes through our checks then we can actually return something so let's go down here and say create post all right so what we're going to do is try catch we're gonna make a try catch block here so we'll try to get the pose if we don't get the post we're gonna get an error so let's say const result is equal to a weight and we can use Prisma which I believe we might have not imported yet so let's import it now so again this is our client that we generated earlier on we can import Prisma from Bell dot slash Prisma slash client cool so check this out you can see Prisma Dot and this should normally give you an autocomplete here but if you don't get it it might be because you need to generate the Prisma clients so it's up to date with the latest models so let's do MPX Prisma generates generate I think it's just generate and look at that it generates very cool um let's see if it works now npm run Dev cool so that's up and running let's try it now cons result is equal to await Prisma dot ah so that's so strange it's just not giving me any all to complete now anyway we can do user oh what am I doing I don't want to look for the user I want to look for the Post Prisma post and I want to create one all right and this takes in an object here where we have our data and we can pass in the title that we get from the API but we also need to pass in the user right because every post belongs to user so we want to make that Association so for that what we can do is go let's go back here at the top and I'm gonna say get user so let's do const Prisma user is equal to your weight Prisma dot yeah for some reason I'm not getting the autocomplete but you should be able to get it you can write just Prisma Dot and you're going to see user and posts here and we're going to do user I'm going to define unique here all right so whichever user is currently logged in that's what I want to look at pretty much right because if I log in and I'm making a post well I want to associate that user with the post so here I'm just going to say where email is session user oh there we go it recognizes it now see oh that's because it's coming from the session okay cool user and email all right so I'm basically saying find a user with this unique email because there's only one of them um and then that's our user and then down here we can just make that Association if we say user ID is a Prisma user.id all right because when we create a post if you remember if we check our Prisma here there we go where is the post post see the post is going to take in a title but also a user ID which should be associated with the user cool all right and that's it that should be all fine and dandy and now what I can do is if everything is okay there then rest dot state is 200 which is perfect and then send back the result whatever that is if not then there is an error so I'm just going to send the rest that status back with 403.json I'm going to specify an error saying error has occurred whilst making a post all right and that's essentially all of our system set up here for our API okay and now we can just go over to our front end and see what's cracking so let's close this up make some space um okay let's head over to our add post okay so we're passing in the title here I think it's complaining because it says type of string which we never defined here so let's see that's the type of string oh cool a different error message just what I love what am I missing here what am I missing here I feel like I typed this all wrong let me type it again Okay so we have an async function in here that takes in a title which is a type of string and then we'll run a arrow function here and we're going to say await axios dot post slash API slash posts slash add post comma dollar sign sorry curly brackets title all right there we go I think I typed the curly brackets on the outside of it that's why it didn't work okay so that's it uh we can give it a shot but what we can also do here is add a comma at the end and if I had space sorry if I add another curly brackets here like that I'm going to have access to a couple of methods here like on error so that's going to take in an error and I can just catch any error down here if I wanted to um okay I think I'm just not typing stuff correctly because being a bit funny with me let me just make sure I'm doing this all right okay I think it might be yeah it should be after this to be fair okay I believe it's after this so add a comma here curly brackets actually it was in here so in here to see if I hit control space it's going to say look on error on mutate unsettled so you have available all of these different functions and that you can use let me just make this bigger because okay so right after here go down here add a comma after the title making you curly brackets and say on error there we go and here we have an error parameter and I can just console log it out console log error like that and then we can visualize it cool and we also have on success so if our data is done then we can do something cool and here what we can do is just say hey if everything went perfectly fine set the title to empty so reset it right because you don't want to have the content in there anymore and set is disabled to false okay let's just do that for now and we can also do a console log data okay so let's try to type something poop so I didn't type anything let's see what we got back nothing that we can see here oop we do have an error here 400. all right let me do a refresh again just to make sure oh never mind looks like we have loads of Errors anyway extra attributes from server control ID okay let's see what that's about let's have here let's look at our form okay so let's just leave that for now because it looks like we are able to just click this and create the data now see it works without any issues and the title is left empty so we should we should investigate and see what's going on there so let's head over to our um add posts here all right let's make this smaller so what's up with this title because we're never console log title let's see alright so if I hit that oh there we go it's going to return me an empty string ah so what is not catching this I wonder think it's this let's just put this in a curly bracket trying that and see if that works then all right let's just fix that up and let's try again create a post and looks like we might still be able to make them yeah looks like a David okay let's see what's up so we have our Title Here type of title just want to see what I get back because it should be undefined type a type of string yeah but it's empty so that's correct uh but here if the title is bigger or here here title length is left at zero so it should just return this for us but it doesn't if there is no title length goodness sakes that's it let's see there we go now it's stuck that's what I wanted so now if we head over here and we can check our Network uh not Network sorry our where is it here I just click on this as you can see we have a an error it says an axios error and if we check we get to see there are response we have a message here saying please do not leave this empty all right so we have access to that now cool all right so what I'm going to do is just go back here to the database now and just delete these okay I want to get rid of them um okay let's go up here into our ad post and here at the top we have onerror and on success so let's do something with this um I'm gonna just do a we're gonna do react hot toast so that what is react hot toast essentially it allows us to display a Wii pop-up notification message here for us so we're gonna import that and just output the error messages and everything down here um so let's get that installed it is called npmi react hot toast like that cool all right let's get into it okay so we just installed react hot toast for the purpose of outputting these error messages um so what we're gonna do is hook up our react hot toast in our um let's see where do we need that I think we need might need to do it in the layout because it's going to be kind of like a global setup for us going on here um so let's head over to our layout and I'm gonna just import toaster from react hottos and all I need to do is just add it in here like that okay and that's it cool so now I can head over to my ad post component and here when it errors out I can display some message so I can import the toast react hot toast there we go um and then I can just call toast.error and I'm on this error I'm gonna have a response data and remember it's on message that we have so data error response data message what is the okay what's the problem with this it's fine it's a typescript error we'll solve it in a bit and then yeah that's it so let's give that a shot click nothing no hot toast still refresh whoa big ol error messages now okay I think the problem we're having is that we are trying to do toaster here but it's uh our layout is ran on the server it doesn't have used client on it so we need to actually get rid of it from here to be honest um and what we can do is potentially wrap it in the query wrapper here we can return the children but also return see the problem with this is oh this is use clients so let's give yeah let's give it the shot so let's try the render it out in here okay cool and the errors no that looks fine up yay look at that please do not leave this empty cool so it works yay lovely um to get rid of this error message the solution I found online is if you do if error is an instance of axios error which you can import here like that and then you can just render this out and then it's gonna stop that message and finally set disabled should all be set to false as well I don't want the button to be stuck like that and in case it goes true then I can do toes dot success here and say a post has been made fire Emoji of course there we go cool and let's hit save so that's the refresh and test this out Boop please do not leave this empty cool what if I have loads of text here create a post please write a shorter post so how cool is that it works this is a normal post create and if it works fine post has been made awesome so that works let's check our database and take a look and there it is awesome so that works perfectly fine now now what I want to do before we head on is I want to display that the post is loading like it's I'm making the post and then it updates whether it's an error or not so the actual notification so here's a cool little trick that we can do we can go here at the top and Define a toast post ID let's call it for example this is going to be a type string so I'm just going to Define it here like that and what I can do is essentially pass in an ID to these so comma here I'm going to say ID toast post ID I'm just going to copy this over as well and give this toast error the same ID all right cool and as soon as we hit on submit here I want to set up a loading so I'm going to say toast post ID equals to toast not loading and say creating your post and then I'll pass in the ID again okay so by default this is the first thing that's going to run that's going to say loading and then it's going to update to whether it's an error or successful so look at that how cool is that Boop and then if it's if it's all good baby and it's gonna update to post has been made there we go let's react those okay so we're posting data let's actually get back the data and not only that I want to get back the data from everywhere pretty much not only um so here right the timeline should display all of the users posts so we're just gonna do that um so let's head over to our um apis here and to a posts and we're going to say get posts.tsx this time I'm just gonna copy everything over from our ad Post in here and we're just going to update it uh accordingly Okay so we'll import the Prisma client that's fine we're not going to need any off stuff in the back end there um we can also remove and we can change this to get now because we're getting data uh this whole session thing can go this whole title thing can go We're not gonna have a Prisma user because we're just fetching data and we also have a try here let's say fetch all posts and all I'm doing here is saying const result is equal to our data await Prisma dot post dot find many that's how you can get all of them and here I'm gonna say uh that's all I'm going to save for now because I want to show you a couple of things um and here I can just return the data right cool and then if something went wrong then I can throw an error of whatever error fetching posts okay cool so now we can make an API request so let's head over to our home page that's where we're gonna do it cool let's get rid of this hello next I don't want to see that and then let's do it here I'm gonna say fetch all posts I'm gonna say all posts equals to async run the function where we're going to have response await axios I'm going to import that dot get to slash API slash post slash get posts all right cool and then we're gonna return the response.data nice um okay so let's use a react query to actually fetch that data use Query from react there we go query all right now to actually fetch something we can just say data here error and is loading like that is equal to use Query and here we're basically going to pass in two things it takes in a query function it's an object as well my apologies a query function in our case it's going to be all posts right because we have it and a query key and this is going to be an array and you can add a string of whatever you want here in this case I'm gonna say posts now why do we need this query Key Well essentially this is going to allow us to do some very intelligent caching by default um react query is going to cache all the results for you so if you navigate between Pages it's not going to refetch it again unless you want to invalidate the queries yourself and you can have access to this key then and you can invalidate it I'm going to show you in just a bit but that's it and now I can just say if there's an error return error here and if there is a is loading then I can return loading like that all right so if I refresh the page you might see it loading there for a second see it was getting the data and now I have the data down here so if I do a console log data and if we take a look in the browser um console look at that we have an array with two users sorry two posts now the problem here is as you can see I have the post but I only have a user ID here it doesn't really give me anything more about the user so if you want to expand that because we do have a relation between these two between the post and the user what you can do is in the get posts here where you're fetching it so we're saying find many what we can do in here is say include user true so I'm basically expanding it and I can also do order by the created at that we have in here and I'm gonna do in a descending order so let's see refresh open this up whoop and look at that now we have the user included here as well with all the info so that's pretty cool all right so now that we have that going we can use this data dots whatever to Output whatever we want the problem is I don't have any Types on this right I'm typing and data and I'm not getting anything so we're going to solve that in just a bit as well um okay so let's see what else do we need to do here um yeah essentially what we want to do now is just output the data here and I'm gonna make a new component for that which I'm going to call posts so here in the components make a post dot DSX cool so this is going to be a use client again I'm going to import image from next image because we're going to use that let's do link as well and then export default function post cool I'm going to return heat div here and in this div uh uh I'm gonna have a class name of BG white with an m y of eight a p of eight and a rounded of LG all right so that's going to be our post and in here we're going to have another div with a class name of Flex items Center and a gap of two and we'll have the image tag in here which I'm going to copy over all right so you can copy that over we're going to have the Avatar here which we're going to import class of rounded full with 32 Heights and then we're going to have a H3 here that's going to have a name which is our name and then what we're going to have is essentially another div outside here so I'm just going to copy paste this all right so just another div that holds the paragraph for us and then we'll have a last div which is going to hold the comment section for us which we're going to leave empty for just now cool so let's just sort this out let's head over to our home page and say import post from components and here what I want to do is say data if we have the data the map over it and we'll have access to posts here like that and for every post oops for every post I want to make a new post component like that I'm just going to pass in a couple of things here the key which is going to be post.id um and the let's see what else the name post on name and the Avatar that's what we need post.user Dot image that's how you can get that a name here is post uh user .name and let's hit save okay if it errors out don't worry too much about it it might just be typescript uh let's go back here and then just import them Avatar name and post title I don't think we passed down post title so let's do that post title is equal to post dot title there we go there we go yay that's working perfectly fine um again don't worry about this we're gonna fix it in typescript in just a bit um and finally what I want to do is have a weak comment section here that we can output so let's head over to our post and right below this I'm gonna have a div and we're gonna have these class names here that I'm gonna paste then so Flex Gap 4 cursor pointer and item Center and in here we are going to have a link like that that's going to take us over to href um slash post slash ID all right whatever ID that we have in here now I haven't passed down the ID so let's just do ID is post ID all right cool again don't worry if this gives you any error messages for now so we can import that as well here ID and yeah that's fantastic and then here I'm just gonna have a P tag with a class name of Tech small found bold and text Gray 700 and then the actual thingy here is gonna be comments like that cool now that's it we're getting for the next next one we're gonna set up the comments model so we can start leaving comments as well all right so before we get going I just want to update our Prisma model so we have access to comments as well because we currently don't have any comments uh models set up for us okay so we we know let me move this user up here as well just because we're using these two loads so we have our user and post right um okay let's make a comment model so let's go down here I'm going to say model comment there we go I want to have an ID that's of string oh why is this let's see okay that's fine um let's call this ID and the default again is going to be a cuid like that and then we're going to have a um let me have a thing here a title right or like the actual content the actual text that they write I'm going to call it the title I should call it comments right hey message yeah message is fine let's call it string and then what we have is our relations so basically comments needs to be part of a post right every post can have loads of comments however also every user can have loads of comments so we need to set up a relation with both of them so what I can do is just make a like a post ID and call this a string and a user ID which is also string right so now I have these two to set up a relationship between the two other models so let's do let's also do a created at we can say date time default now like that move like that okay and to make our relations we can say post all right as a type of post and the relationship here is Fields I'm just going to pass in this post ID that I made and that post ID references the ID on the post all right so that ID there cool and then we also have a user right which is the type of user again that my relation with this is Fields I'm going to pass in this user ID I just made and that references the ID on the user cool errors errors everywhere I must have mistyped something I must have user that's fine relation fields user ID references ID cool hmm strange oh there we go fixed itself and as you can see by default that's going to automatically add it here as well see and added the comment and the posts and it also added a comment uh type here array see which means there's many of them fantastic all right so that worked perfectly fine and let me just make sure and check to see if there's anything else we want to make oh yeah I should mention this because it's quite important um where is it let's scroll down okay so we are in the future we're gonna get an error message I just don't want to do it again I don't want to send the database up again and do another migrate um if we end up deleting a post it's not gonna work because the post holds all the comments as well for that specific post and it's going to throw an error saying oh sure because that's also gonna Cascade and delete this so it's gonna stop you by default which is great but in our case we want to specify if we delete the post I want to get rid of the comments too on that post so to do that all you need to do is head over here to the post reference and just add a comment and say on delete or on update make sure you Cascade like that and that's it all right so make sure you do that on the post let's close this up MPX Prisma migrate Dev let's run that command so now we have comments available for us which is fantastic so also in the um if we head over to our get posts here where we have user true we can also say comments and set that to true so it expands on that as well um yeah and that's looking all fine and dandy let's have a look so now I believe I still have this console logged out somewhere up npm run oops let's generate that again npm npm run Dev let me give that another look quickly let's head over to our get posts and let's see Prisma Dot oh that's so annoying it doesn't work okay anyway that's the refresh all right there we go it's giving us forbidden now let's see what the actual error message is oh it says objects are not valid uh of yeah Okay cool so I was just looking up to see why this Prisma client doesn't update and some of the people said just try to restore vs code so let's see if that does anything for us right now uh the Prisma client can still stay there uh just want to give it a shot if I go here let's see um Prisma Dot looks like it's still not doing it wait Prisma nah that's not doing it either so restore didn't help um another thing we can do is let's see if we head over and also make this a TSX file because I actually made it a bit differently before so let's head over to the client here and let's rename this to TSX dot DSX like that and we'll just paste this code in here like that again you can copy paste this if you want to pause it it just adds the necessary uh declarations and types interfaces in this case to our Prisma clients so I think that might actually do the trick so let's close that up and look oh we're getting highlighted something here which I think was the reason why this doesn't work out anyway um so it looks like it let's see if this does that do it Prisma dot yeah look at that account common post session user all right so we're it finally works now so that's fantastic okay so just make it the typescript file and that's it now let's see what error do we have here type user true common screw is not assignable to type post include uh object clearer may only specify known properties but comments does not exist in post include did you mean to write comment uh not really but maybe I misnamed it in our schema here so let's have a look that's so annoying look at that see it uppercased it by default when it added it uh okay we're just gonna we're just gonna keep it like that now but anyway the good thing is now that typescript works so you just get to see it anyway so it's hard to actually you know make a mistake now there we go comment true and user true cool so now if we head over back to our page let's see if we have any errors let's do a Refresh on this oop npm run Dev let's get this sucker up and going the refresh loading and look at that we have our posts yes let's go cool um so did you see how we added the types here for uh Prisma we're pretty much gonna do the same thing for our data that we're getting back here wouldn't it be nice to just kind of see the data that we're getting and then we can extract whatever information we need about that well we can do that we can go here to our app and just make a folder and I can call it types and then here I can make a new file and call it posts dot p s and basically I am I just want to Define how my data looks like I'll just show you this quickly I can do an export type of post type that's how you define one and this is going to be an object here so I know I'll have a title on it that I want it to be a type string an ID that's going to be a type string created at that's going to be a type string and then we have our user right so that's going to be an object here that we have a name on and an image on and again you can add more if you want and then we have a comments now we might have this right some people might have no comments I'm just going to specify that this is optional and here I'm going to say created at that's going to be a string and let's do an ID of string and then post an ID of string and user ID of string optionally I mean you could just go here and look at the data that you're getting back if you want type safety between this clients and the back end that's when something like trpc comes in handy because uh the actual data that comes through is going to be type safe on the front and automatically for you but now we're just going to define the type there and we're going to go here and just import it import post type like that and to use it you can go here to the use Query and put it in like that and that's it and now I also want to specify that this is going to be a type array all right and that's it so now if I type data Dot yeah why is it not working data what am I not doing correctly again we should get all to completion here strange let's look at our post type again oh the comments here is also going to be an array so let's just add that like that export type post iPad it's looking fine by me oops let's close that up post type yeah why is this not working let's console log out the data and okay here we go data has one object yeah so that looks fine still refresh yeah so that's working use Query data Dot that's so weird if I go down here because the Gap it gets passed to the post as well so if I do test equals post dot oh there we go it's fine it works there we go so I have access to comments user title ID and whatever else I have cool so that's fantastic what if I go to post Dot user dot yeah look at that cool that's really nice okay so now I can pass in the comments as well so comments equals to post our comments cool question mark no question mark okay and that's going to give us a wee error as well because it can be of type undefined which is fine um Okay cool so now that we passed everything down here let's head over to our posts again and we can just output uh the length of the comments here now so let's do comments and again we can add types to this later on so there we go and here I can just say comments length like that cool so let's have a look we should have zero now do refresh and it doesn't say anything hmm all right do we have any errors console uh it looks like it's trying to get another post somehow but it's not doing it and okay let's see what we're passing here post doc comments we have the comments accessible here that's console log out comments and see what's the big fuss with this console it's type undefined hmm okay um maybe we didn't write the data correctly here so let's see console log data okay so that gives us that it has a comment oh it's uppercase God damn it see that's annoying um so I should probably update the type here then and say I'm gonna have a comments with an uppercase C comments like that yeah that's a bit annoying comments feel free to change this modify it okay now it says oh well that doesn't exist but we have comment cool [ __ ] me okay uh comment we'll just do like this now okay I'm sorry if it looks ugly it is what it is there we go all right and we don't have Consular comments anymore so let's get rid of that why is it still not okay console log comment let's see undefined oh so it's still comments here so let's do comments again oh zero there we go God finally oh okay so even though it's comments I'm actually using this name here right so that's fine cool so common is not length we can leave a little space there and there we go so that's perfectly fine cool so that's gonna be it let's take a wee break alrighty next up I thought would be a really cool idea to be able to go here to our dashboard but only if you're logged in uh so let's give that a shot so we have our components that's fine um again we can add the types here in just a bit let's remove this comments here because this is working all fine and here in our app let's make a new folder called a dashboard like the cool and we'll make a new file call it page without PSX cool okay what do we do here well um let's see we'll export default async function dashboard like that just so we can render something out on the screen okay so let's say Main and we'll just do H1 here with a class name of let's say text to excel font bold and I'm gonna say welcome back so let's just play like welcome back Mr user whoever this is so I'm going to import uh get server session from next off and I'm also going to import the off options uh not from there off options from double slash another slash pages slash API slash off slash next off cool off options like that cool okay so now what I can do is just kind of do the same thing that I did so far is get the session it waits get server session and we can pass in the off options so we have access to the user here so if there's no session then basically I just want them to be redirected so redirect now I don't have redirect so we need to get that from next redirect from next navigation cool there we go so let's say redirect over to slash API slash off sign in all right so if they try to access it and the user is not logged in will get redirected so let's wait for this to load up I honestly don't know why this is so slow now uh but in case we do get it back well then let's just wait so we got the typescript uh Auto completion as well long video isn't it we are going ham today if you like this video drop a subscribe as well stretch when we when we do the chorus we're probably gonna use trpc anyway and just be a bit more careful and a bit more Taro this is quite just go go go right uh just because it's such a long video otherwise um okay session uh user there we go and then we have a name cool so I can just output that let's give it a shot okay so I click on my profile welcome back develop yay it works let's sign out cool we signed out so if we head over back to our home page so we still get to see every post by everyone and if we somehow try to head over to dashboard it's automatically going to send us to sign them with Google so let's do that and then we can just easily go to the dashboard without any issues just like that cool so for the dashboard here I wanna I wanna show only my posts all right and I'm just gonna make a new component we're not going to use this post component that we have here which we could use but to keep it more simple I'm gonna do a custom one that basically is going to have a delete button as well and I'm just going to make a different kind of fetch for that so yeah let's do that then let's head over to let's set up the API first so let's close everything up head over to our posts API route and we're going to call this let's say all off posts okay DSX that makes sense because it's my off post um okay so again we're gonna copy a couple of things over this time let's copy it over from get post sorry um add post because I'm gonna need the off oh what is this another typescript error that we need to fix type string okay cool um yeah let's head over here I'm just going to copy everything and post it here and this is going to be a type of get now we'll leave this here and here we can say a message like if there's no session then please sign in but they're going to be redirected anyway so that's fine we're not gonna have like a title here or any anything uh we are getting the user already here and Ours session and then we're checking it against the Prisma database um which we don't need to do so let's get rid of that let's get rid of all of this and here we'll try to get off users posts okay cool so here let's just get rid of this whole block and I'm just gonna say cons data equals await Prisma the user dot find unique right I want to find the unique user where the email is session the user .email cool and let's hit save on that awesome and then here let me just return data fantastic and now what I want to do is so we're checking for the specific user and I want to include all the users posts right so I'm going to say post include a uppercase it again so let's do Post like that I'm gonna order these by created that and a descending order and I want all the posts to also include the comments so comment like that true all right so basically find the user find the unique user get all the users posts so include the posts that he has and on the posts also include all the comments all right does that make sense cool I wish I would have not written it like this because it makes it look extra annoying because you'd have include comments and include posts but anyway um yeah that should be it and you can update this error message here as well if you want all right so we have our off posts all set up and we can head over to our dashboard page perfect cool um okay let me just catch my Catch My Breath here for a second um okay so we're gonna create another component here in the dashboard we're gonna call it my posts dot TSX cool so this is gonna be a use client cool and I'm gonna import use Query from reacts 10 stack react query cool I'm going to import axios as well let's also import that's it let's keep it like that I'm going to make a new type here and call this off posts as well.ts and I'm just going to copy this over if you want to add the types as well it looks like this cool and then what we're going to do is let's see here let's fetch the data cons fetch off posts is equals to async we're going to run a arrow function we're going to have a response here which is await axios dot get we're going to go to slash API slash posts slash off posts cool is that what we named it that's what we named it and then we're going to return the response.data nice okay and then we have export default function my posts cool and here we're going to return whatever we're gonna return hey div and here we're gonna have our data cool all right so let's do some use Query so I'm going to say data and it's loading equals to use Query and I'm gonna pass in here um the types Imports what is it called off posts there we go pass the type in there it's complaining about something maybe here it's complaining that I don't have any arguments okay cool if you remember we need basically two here one is the query function so query function in our case is going to be fetch off posts and a query key query key which is going to be let's name this of posts cool um okay and then if if it's loading then just put out a return H1 posts are loading Dot otherwise we'll have the data console log data as you can see we have autocomplete on it as well which is fantastic cool let's have a look welcome back David and I should have how many I don't even know one post two posts one uh looks like it's not doing any fetching right now hmm let's see if we have any errors it doesn't look like it console and let's head back here Boop that's loading up oh here's what I mean by uh caching as you can see it didn't do the loading the second time so that's pretty cool isn't it okay why is this not console logging anything out for me oh because I'm never using it that's why uh let's head over here to the page and we're gonna import my posts and let's just render it out down here my posts cool okay so that should do it now let's see let's go back here data there we go cool and we have an object here with all the things that we need we have a post on it as you can see and on this post I have the comments as well cool um all right so what I'm gonna do is essentially we'll make one more component okay and this is going to be specific for editing so dashboard let's make a new one and I'm gonna call it editpost.tsx all right cool so and here let's say use client again all right I'm going to import image from next I'm going to import we're going to use use State as well uh uh okay let's just keep this for now let's say export default function edit post like that cool and then here as well we are gonna have a bunch of stuff uh coming in like Avatar name title comments and ID so let's pass those down right now and if you want to make a quick prop as well for them let me just show you quickly how you can do that so edit props here we go right we have an ID Avatar name title and comments which is optional and then you can just put it like that and add some Dots here and say edit props and there we go that should be just fine now okay cool so then after we got that all nice and going we'll return something a div and let's just do what should we do let's just do a div and in here we're gonna have another div which is going to hold the image tag you know this looks very similar to our other pose but let's just make it from scratch so we have a div I'll just add the classes here as well now with the BG class name BG white m y of eight padding of eight and rounded LG again that's pretty much the same as the other card system that we have going then we have our image here I'll just copy this over it's a bit quicker all right an image where we add the avatar and where we add the name as well so let's just add these two for now cool and then we can go here and just render it out in my post import edit post there we go and then rather than seeing data here what we can do is actually Loop over it now so here I'm gonna say in this div I'm gonna have on my data Dot posts dot map let me add a question mark here as well so map over each post and then return me a edit post which is gonna take in a couple of things as you can see we can see I'm here um Let's do an ID post Dot ID a key of post.id again we can do Avatar equals to data dot image that's where that lives the name is gonna be on data Dot name title of the post is gonna be on post.title and comments is gonna be equal to post doc comments cool so we're passing pretty much all the data that we have down here to render it out on the screen for us so as you can see we got a message there saying posts are loading but we never got anything back so I wonder why that is hmm what's going on and I said hey yeah yeah yeah yeah I should definitely be getting a post popping up here says it's loading up fine as well which is why I'm quite confused what am I not doing for you what is it so for some reason it just seems like it won't render it out and I'm not sure why let me just grab this at the post from here and just output the H1 that's gonna just show us if the problem lies here or not suppose that let's I'll put the title of each post and let's see if that shows up posts are loathing and no it doesn't show up okay so must be something here that we're doing wrong to be honest uh because we're not returning any data so let's console log out data again um and see what's wrong with it console oops so I added another one so we have an object here ah okay so we are getting back an object this time right um yeah and We're looping over the posts basically right so that should be fine but it's not posts is it it's post uppercase I knew this was going to bite me back in the ass I knew it I knew it so the type should be uh if we head over to types it shouldn't be posts it should be post so well since I messed it up so we have our user post type cool um okay so this is gonna be post and again we need to update this because we're using the off post type so let's see what the hell do we have here post like that now this should update too and that should be fine yes that works oh my God be careful with this because prismas automatically gonna generate you once you add the relations it's automatically going to add you these comments uh and the yeah the relation up here so if you want to rename this make sure you do lowercase so it all matches up like here and here as well okay cool so that works so now we know we can just render out our edit post here there we go we can get rid of this that's fine hit save and let's have a look and looks like we get hello twice what is that about uh well cool and hello there that's what we typed and so let's head over into edit post oh I think I know what that's showing to be honest and let's see here we go Okay so We're looping over each post and each post is gonna have a title so cool and hello there so I'm passing that down in here and then here okay so I'm not outputting anything cool title yeah okay there we go so that works fine lovely okay so now we can just complete this uh edit post and yeah so let's get back and going with this then so we had a class name here class name of this one BG White and then here we had another Dev inside here so let's do div and I'll have an image stack here and a H3 tag where we'll just output the name and the image so let's have a look at that cool okay we can keep it nice and small like that and we'll just add a display Flex uh to this diff here with item Center and a bit of Gap just like that and then I'm going to make a section here specifically for the title and I'm going to add break call so if it goes all the way to the end it just jumps down to the other line and then we'll have another section here where we're gonna have the button and the comments that you can click on uh or I should say like a delete button that we can have here so let's do a div it's gonna have a class name a flex oops Flex item Center and gap of four cool and then in here we'll have a P tag with a class name of attack small font bold and text Gray 700. all right and then here we can just output the comments length and we can just say comments are we not getting comments in from here well looks like we are but again here it's going to be probably post Dot comments with a big K so let's just update these again off posts comments it's going to be comment here in like the cool there we go there we go zero comments nice and optionally you can have this link over to the the custom page here again which we're gonna do in just a bit um and yeah that's it so we have our text in there and then let's add a button right below here and we're gonna say delete cool right there I'll add a bit of styling to it feel free to style it any way you want I'm gonna do it like this cool nice cool and I think we're gonna just leave it at that for now so there we go we have our posts and that's only our post there so if you sign in with another user and they're posting you're gonna see all of them here but this is specific to you next up we're gonna hook up the delete functionality and also talk a bit about caching the one little issue that you might notice is when we make a post hey cool post and I click it and you cannot see it here so why is that well I told you that by default it's going to try to Cache the results so it's just gonna cache whatever we have here uh if we head over here as you can see it pops up now and if we head over back here it's gonna pop up again but essentially now everything is cached again so basically when we do a mutation we need to specify the hey take that posts that we have here and just invalidate the cache and just refetch it because we have new data available for us so it's really simple to do actually we can just head over to Let's close some of these up because it's quite chaotic all right there we go uh we can head over to our page here right this is where we're doing all the fetching and as you can see we added the query key of type post to it cool well now we can get over to our ad post here and after we make a post I can specify if I import here at the top oh we did import it use Query client so let me just go here and instantiate it and use Query sorry query client let's call it let's query client equals to use Query client like that and then when I make out a post and it's successful we can go here and say query client Dot and validate queries now which queries do I want to invalidate well we specified that in an array right here oops where is that let's let's find it posts right so I want to invalidate those post queries and that's it so now if I type something in like hey click as you can see it's just automatically going to refetch it for us which is really cool okay and then when we head back here as you can see it's already cached so that's that's perfect okay how can we delete this well let's uh I don't want to just click this and delete it because that's quite bad because they might accidentally click it so let's whenever you click it let's pop up a box here that says hey you sure you want to delete this uh so I'm going to make another component here in the dashboard and we're going to call this toggle.tsx all right what did we do here well we're going to say use client I'm going to say export default function toggle cool this is going to return us a div um and this div is pretty much going to have a class name here a fixed where the BG of black dash 50 V full H full z20 left zero top zero it was that's all all the shape um essentially what we're doing here is we're making this div that's going to cover up the whole screen so it kind of like Fades out the screen for you and trims it a bit darker uh you're gonna see it now so let me just add the H1 and say hey okay so we can head over back to our um are my posts sorry our edit posts and what I'm gonna do is let's see how we're gonna do this I don't want to put it inside here I want it to be on the outside because it's going to be positioned fixed let's add some fragments here like that and then down here I'm just gonna say toggle right let's just see it okay so as you can see it darkens the screen for us which is fantastic and so let's just keep editing on this okay cool and then we'll have a div in here let's have a div with a class name of we'll add position absolute I'm just gonna copy paste this over so you can see okay so we'll add the position absolute a BG of white and then we're going to place the top one dash two which is going to be halfway left halfway and then we're going to do a transform Translate X by half and Translate Y by half all right and then I'm just going to add some padding to it and a rounded LG a flex a flex column and a gap of six all right so essentially I'm just making this diff that I'm centering here on the screen and then here I'm gonna have like a H2 uh with the class name of let's say text Excel so pretty large and then are you sure you want to delete this post cry there it is all right cool and then right below here I'm going to have a H3 I'm just going to add this quickly so you can see there we go that just says pressing the delete button uh will permanently delete this post for you so that's perfect all right and next up I'm just gonna have a button here so I'm going to copy that over um I'm going to move this on click that just says delete post and you can style it again any way you want nice okay that's all we need here but now I want to toggle this on and off basically right because I don't want this to be permanently showing here for me so what we can do is we can head back to our edit post page so let's head back to edit post let's go to the top and as you can see we have a u State here so let's actually use it then so toggle we'll do it here toggle and set toggle is equal to use State and by default this is going to be false which means I can just grab this and if I go all the way down here I can just wrap it and say hey if toggle is exists and if it's true then render it out and that's it yeah so by default as you can see now it's false so that's fantastic okay so what do we need to do well I need to actually mutate this and delete it right so let's do that let's go where should we go yeah and here somewhere delete post like that okay so what we can do is say const mutate again equals use mutation and we can import that if I click it perfect and I want to run again an async function that's going to have an ID of string in here because I want to send the ID over like which post am I deleting right so that's going to be a string and I'm going to say await axios dot delete did I import axios I don't think so okay cool axios dot delete oops did I miss a parentheses there I think so maybe not uh let's do a slash API slash post slash delete post and the data that I'm sending through is going to be the ID that I just passed down here cool so that's fantastic and then here obviously we have the on error and our on success as well Jesus console log error cool comma um on success so here we'll have our data as well and all I want to do is say console log data cool and we'll add our toast as well in a bit anyway I'm sending the data through to my backend which is pretty much all that matters and then let's make a function here called the leads post is equal to an arrow function and I'm going to say mutate the ID for me cool which again I'm getting from here so that's fine okay and I essentially just want to pass it down to to the toggle here right because the toggle is actually the one that's gonna um delete it for me not this component so what we can do is say delete post equals to delete post cool and I also want to set toggle equals to set toggle all right so I'm basically passing down these two functions set toggle and the delete post cool um all right this is going to give us a we error it's going to say delete what is it delete post is type void so it doesn't return anything for us so I can specify that if we head over to our toggle let's just do it here I can do a type toggle props it's not equal to let's say the delete post just a function but it doesn't return us anything so I can just say void and set toggle also doesn't return us anything but it's going to have a toggle in here that's a type of Boolean but it's not going to return us anything so just void as well okay so let's have a look here um oh I never added the toggle props I think that's why it's not working I'm such a silly goose okay so let's head over to our toggle so we're gonna have our deleted post from here delete post and our set toggle which is going to be a type of toggle props cool oh look at that that got rid of the error message cool all right so if I click here on the delete I want to basically toggle the toggle component right Okay so let me just wrap my head around this for a sec um okay so we're sending it down to the toggle so everything should be in the toggle so let's do it on should be on edit post right so here on edit post on this button here let's add an on click and we'll have an event here and all I want to do is say set toggle to true cool that's it so now I click on it and look at that cool it pops up and what I want to do in the toggle here is basically if I click anywhere here it should just close up again so let's do a on click on this it's going to take an event and it's gonna run a set toggle false cool so now if I click somewhere else it's going to stop it nice um okay so that's all nice and dandy what we can do next is actually delete the damn thing right so here on click it's just gonna call this delete post function cool lovely so that's essentially it we have everything hooked up now we can just go over to our Pages post API and make a new one and we're going to call this uh let's call it delete post delete post.js TSX actually should have been just TS actually not TSX I messed these up by the way just rename it all really quickly TS DS I might need to actually restart this so let's just do that head over to delete post let's see what we need here uh probably loads of the off stuff so let's copy over off posts paste it here all right we'll keep everything here the same change this to delete I will get a session which is fine um then uh if you remember I'm sending in the post ID here I'm passing it down so let's get that and let's remove everything here cool the leads a post so let's say const post ID is going to come off the body so request.body and then what we can do is do a try catch which we are we can say const result equals to a weight Prisma Dot post delete where the ID of the post equals to our post ID that we just sent down and that's it and then we can just retire in our result and then again you can update your error message and that should be good to go so let's give it a shot hey delete see if we get any messages here which we are not any errors that we're getting and looks like we are not we get back the object and it's the status 200 so that means that's fine uh and if we refresh you're gonna probably see it go away so remember we have to invalidate that query for it to work and whilst we do that we're also going to hook up react toast so let's just head over to our at the post right and here we get the error back and we can just update these now so we can just import toast from react hot toast and let's say if we have an error just toast the error error deleting that post and we can do the same thing that we did where we have like an update so we can head over here and just add a delete toast ID in this type of string and um we'll just pass it here on success as well so we'll just say toe success post has been deleted with the ID of that and here again we can do the same thing so I'll just copy paste this over comma like that and when we first run the delete post we can add a pending as well so we can do this for that delete toast ID equals toast loading deleting your posts all right cool and here on success as well if the post has been successfully deleted then we'll get the query client so let's import that as well use mutation comma use Query clients all right let me copy that over and we're going to go down here and say cons query client equals use Query client make sure you only have one and on success I want to call query client dot invalidate queries and the name I gave it was off posts I believe um let's check where am I fetching it off posts yeah correct cool so that should be it let's try Lily post deleting post has been deleted and then it should be invalidated as well which it's not hmm I wonder why off posts query client and Melody queries of posts huh let's go back to our is that correct yeah that looks correct to me there we go works perfect lovely and there we go we can delete and create posts how awesome is that for the next one we're probably gonna look into adding comments and then setting up this page as well okay it looks like we are getting pretty close to wrapping this up which is awesome um so what we're gonna do next is um make a page here like a dynamic page because we should be able to go in all of these and comment on it so let's make another page here let's close all of these up make some space cool so let's make a new folder here and we're going to call it post so this is individual post right and here I'm going to add curly brackets like that sorry uh square brackets and say slug oops sorry this should be a folder as well did I just delete all of them I think so okay new folder post already exists oh yeah here it is with a new folder of slug like that and inside here we have a page.tsx essentially if we go over to slash post slash whatever the idea is it's gonna just jump us here which is fantastic all right so let's import a couple of things here we can say use client we'll import the post as well and look at that you can do that now which is quite cool um what else do we need um let's keep it like that for now I'm going to say export default function post detail cool all right and then here what we're gonna have is a return there we go and basically what I want to return here is a div I want to return the actual post that we have like that so that's imported now this is going to take in a couple of parameters that I need to pass it down to so we need to essentially fetch that specific post yeah just fetch that specific post with the actual post and the whatever comments we have there all right so to do that let's import use Query again use Query from react 10 stack there we go cool and axios as well cool and essentially we're gonna do the same thing so I'm gonna just copy paste this over we're gonna say fetch all the details we're going to pass in a slug here that's a type of string and then our response is going to be to slash API posts slug okay cool let's remove this for now so it's empty cool and as you can see when I click on this now it's going to send me back to this page so that's perfect so we're trying to fetch this um inside the post here just have a hello or something cool um we're gonna say const data is loading as use Query and here you can pass in the post type again like that which we imported from App types cool and then this is going to be a function that has curly brackets where we can pass in a query key that's going to say let's call this detail post and then the query function is going to be um I'm gonna run an arrow function because I need to pass it in a parameter here which is going to be URL param slug how do we get this that's the question we have access to it here in our post details so you can just literally take it from here URL like that um and this needs a type as well because it's gonna error out otherwise so I'll just make a quick type here of URL so this is going to have a params in here with the slug that's a type of string cool so I just say URL cool so now if you head down and say URL dot params.slug that's how you can actually get the ID from here all right cool and then finally here after we do all of this fetching we return the data so everything else looks just fine then we can do our checks here if is loading then return loading and we can cancel log out the data cool all right but we don't have this API set up to post um so let's make it we'll go over to where is it public Pages posts and let's just make a new one and we'll call it Dot sorry not DOT we'll just call it details like that.ts okay cool and for this what we're gonna do is import the Prisma client so let's do that dot slash double slash Prisma slash clients cool uh we're gonna say export default let's just copy over from Maybe off posts let's copy off posts over cool so let's get rid of that we'll keep everything else here at the top which is fine um actually we don't need any of this off stuff so let's just get rid of that too okay and then here we're gonna do a get request right because we want that individual post let's get rid of this let's get rid of everything and just keep the try catch function here cool so I'm going to say data equals to await Prisma I want to get the post and find the unique post um where the ID sorry where ID is equal to request dot query dot details all right that's how you can get it from the URL cool all right so next up let's see if that works actually um let's go here and let's do a console log request.query see and we'll check the console and it says it's undefined right now here we go details see there we go oh actually I'm doing it on the server so it's not going to show up in the browser obviously so there we go details right we have request query and then we can access it with details cool and then we're passing an ID here and that's fantastic find the pose find unique with the ID I can be type undefined that's fine and then here of course I want to include a couple of things like the user definitely want to have the user in here and also the comments I want to have in here so I'm just going to say comments and I also want to order the comments by created at cool and then I'm gonna include in the comments which user commented there we go true all right so each comment has a user as well and then I'm just going to return the data here so at the end of this uh blah blah blah return response dot status of 200 everything went okay and the data as well cool so let's see if that works let's do a refresh and we have let's go over there cool okay let's have a look console I think we are already returning the data and there it is so there we go that's our post and that post has a user on it right the guy that made the post and also any other comments in here that we're gonna make okay cool so let's go back over to our special page here our slug page okay cool and since we have the data we can render it out already so I'm gonna say we have a post here like that I'm going to have an ID and we can see the data now so that's easy uh it's data.id something funky is happening here I'm telling you okay so the types are not properly loading up okay that's fine we'll fix this I think because it might be undefined let's also add all of these different ones name it's going to be data Dot user dot name cool I don't think I have a post type actually do I I have a post type I don't have a post type so let's make a post type sorry a post.ts I'm gonna just copy paste this over how the data is going to look like if you want to check it out so again we have the ID and everything and then we have a user here I'm going to uppercase it and the comment as well which is going to be uppercased so just basically checking the data here I'm making sure it all matches um do I get the Stills yet I do comment and a damn user is lowercase so let's just do that okay cool so posts perfect so post type and so let's do import post type from post like that let's see if that works fine equals to data.id now it's still doing some funky stuff post type I wonder if this is just messing it up a bit for me app types post yeah it's getting that one exports I'm exporting it as well I'll just fix this type up now I'm not gonna do it now uh because I need to check it I have it correctly on the other one but since our data changed I just kind of messed it up a little bit so apologies for that but let's just uh get all of this stuff here that we need on our post um okay so ID then we need a name data the user.name Avatar we have as well data the user the image post title is gonna be data.title and comments is gonna be data dot comments all right that should be it that's fine looks like we are still airing out as that isn't it yeah that's it cool so there we go so we got to see the post when we click on and here below we want to see basically like an input where we can add a post and then the rest of the comments so quickly I'm just gonna make a new component here and the components folder and we're going to call it add comment dot TSX cool it's going to be a use client again we're going to import use state we're going to import loads of stuff use mutation use Query client from react 10 stack query let's get axios in here toast as well there we go and then let's do export default function add comments this is going to have an ID here and we're going to return some good stuff some other way I want to return I want to make a form basically it doesn't have any action and in here I'm gonna add just a Wii class name to it and it's going to be my8 and then the H3 saying add a comment let's just get this component in and render it out on the page so here right below the post I'm gonna say add comment like that cool see you can see it okay and the comments then we're gonna have I'm just gonna copy this over then I'll just have a div here uh with an input like that and as you can see I set up a Wii U State here so we can just do that const uh title and set title use state so that fixes that and then I'll have another div uh I think I just basically copy paste it over uh some of the logic from well that's it that's covering everything out maybe I didn't oh yeah just here uh I think I did a copy paste over from the form from our home page here so it's very similar to that and I added as disabled as well again so we can just copy that as well over which is like that cool so there we go so same stuff basically okay so I click here and look at that that's what we're presented with really cool and for the add comment again it's pretty much going to be the same as the add post functionality very very similar to it um so let's do it cons query clients we're going to make a query client is equal to use Query client there we go okay I'm going to say columns mutate equals to use mutation and again here we're going to pass send an async function is going to have some data it's gonna return us axios.post and let's head over to slash API slash post slash add comment and we're gonna pass in the data that we have like like that oh what did I do incorrectly here data like that cool I feel like I messed something up async is not defined what you mean async is not the fine uh-huh cool I don't get it I don't see it where's my mistake use mutation yeah that's correct and then here we have async that takes in one data like that just return well I'm automatically returning it so sometimes I just have I just find it so hard to see what I'm doing bad so I'm just gonna do it like this just gonna type it out again use mutation so I know here we have an async function data that's going to send us back a axio stop post over to slash API slash posts slash add comment comma and then we have our data cool and then after this comma run a curly bracket and essentially we're going to do the same on success we'll have the data right and then we'll have an on error where we'll have our errors cool all right so for now let's just do the set disabled here to false right and then set is able to false and set title to nothing if the data comes true fine and of course we can do our toast as well so if we imported that again I'm just gonna post it down here and I just made a variable called common toast ID alright so if you want to make that uh it's just this right here that we need to push in cool all right cool so that's an uh we have our toast success down there and down here on error again we can copy this and paste it over in case we have an error and let's also import this uh axios error here so again we did this before so you can just pretty much copy paste it over all right so we are doing everything pretty much which is fantastic and the last thing we need is to submit the comments so let's say call and submit comment is equal to an async function that has an event it's going to ask us it's a type of react form event let's run an arrow function where we prevent the default set is disabled to True right because we don't want the user to be able to click on it and the common toast ID is going to be set equal to toes downloading um adding your comment all right and this one also takes in the ID of the comment toast ID cool and then mutate so if everything goes well we'll send in the title and the post ID as ID like that cool now we're not passing it any ID from here so let's head over here and pass in the ID down uh what we can do is say ID equals to data ID like that okay so we're passing that the post ID in here into your add comment and now we have access to this which is fine it says it's implicitly it says it's uh implicitly has an any type so let's just fix that quickly and just mention that it's a type string and that doesn't work because that's not what I want to do I want to do a type up here post props so essentially we'll get the ID in here and I'll just attach it like that you cannot add the type like this if you're extracting it like that but this will work like that that's fine okay anyway so let's see what's up here title so where are we getting the title from here so that's good uh let's see why we're getting all of these typescript errors hmm I wonder if this is just causing us issues here post props let's do a type comment too we can specify how our comment is going to look like so it might have a post ID of string and also a title of string okay cool so the data here right that we're getting back should be a type comment okay that seems to fix it there we go we have a type string and type string or undefined cool yay that works awesome I think that's it honestly I think we set everything up just fine we just need to create the end point did we make that oh look I think we actually made the endpoint as well hmm oh we're just getting the data cool um but we don't really have anything so let's see at comment okay we need to make a add comment API route here cool so what we're going to do is first of all let's get the session stuff in we'll need it for this one so let's go over to maybe delete post that'll be fine copy everything over from the top here and let's let's just copy the whole thing to be honest cool all right so how do we delete a post well not delete the post sorry how do we add a comment oh could you tell that I'm a bit tired um okay so we're checking if the user's here and then add a comment so what I want to do first of all is get the user so we can do that with Prisma user equals to await Prisma Dot user find a unique user and where the email matches the session the user the email so that's I'm just basically checking to see if the user is here cool and if the user is here then I'm gonna pull out all the data from the request.body so we can do const title and post ID remember these are the two things that we're getting because that body that data all right we can pull that out um all right and then what we can do is kind of do the same checks we did before right before yeah let's get rid of all of this actually cool we can say if our title the length so that's equal to zero then we can return status of 401 .json and say message please enter something okay or just like don't leave this empty right and after that what we can do is say const result equals to await Prisma dot comment we'll get the comment dot create and I'm going to pass in this data here so look at that it actually shows me what data goes in here so again the question marks means that they are optional so all I need to pass in is a message and a what else I need to pass in the post ID I'm not sure if I marked that incorrectly but I do need to pass in the post ID and a user ID as well so let's do that title sorry it's gonna be message is going to be title right and then the user ID is gonna be Prisma user the ID and the post ID was going to be just post ID from here lovely oh it's doing that we error out for me uh we'll see why rest.status200.json and we're just gonna pass in the result as well all right why are you complaining I wonder what this is about I might not need the data here am I just going like that no it doesn't because when I post this n here it's going to say data yeah so I need to specify that title yeah something is wrong with our um our Prisma models for sure so let's head over and check really quickly here we go cool so let's check our comment here for now common common comment here we go post ID user ID and message yeah we never specified that they are optional anyway let's give it a shot and see what's up with this let me just write this out quickly again because I feel like I didn't do it properly properly Khan's results await okay Prisma so we want to get all the comments and then I want to create we'll have data here and data takes in a message which is going to be title user ID of Prisma user the ID and also the post ID okay no more uh yeah it's still doing it uh we'll see and let's let's check if that works anyway hey we okay it's refreshes so let's let's check what's up oh submit comment we are never using it so let's go here and say on submit submit comment cool let's try again if yeah please enter something cool we and looks like a comment was added let's refresh and see if we look at that it works perfect um I need to see what these errors are I'm not sure what's the problem with this oh the okay so because we might get back a user ID with a type of undefined on it so that's why I think it just wants me to I don't know what it wants me to do um yeah I think it just wants me to Define um what is this Prisma User it's type of user or null I think that's why it's causing issues because it's looking for a type string here anyway we're gonna leave it like this for now because this is gonna be 10 hours um yeah we're posting a comment which is fantastic so now would be it would be cool to render it out here on the screen as well uh so for that we can just do it here to be honest uh because we are fetching the data here anyway so I just go down here and do it down here data question mark uh let's see how we're getting the data back because we should be able to see it now here so look at that we have a comment with one array yay and we have the text and also the user that made the post awesome so let's just power through this okay data comment like that again it should be comments but whatever the map over each comment cool and then we are gonna return something here so let's do a div um then this step will have another div and let's see let's see let's see let's see and what am I not doing correctly let's go back there we go map comment so for each comment we get to render out a div okay that works um and again this is going to have pretty much the same class name as the other one so I just pop that in there uh it's also gonna have a key of comment dot ID and then in here will basically have another div I'll just copy paste this over so you can see we need the image tag imported here I'll show you in just a sec there we go cool so essentially what I'm doing here is yeah I'm looping over each comment and I'm gonna add an image tag I'm gonna pull out the user that commented and I'm also gonna say I'm gonna put out their name their icon as well and the time the comment was created as well and finally I'm gonna actually put out the message so let's do it down here still another div I'm just gonna say comment dot title or I think message is what we called it yeah we perfect and I'll just add the class name of a bit of padding there cool so there we go we have our comments all done and sorted that is fantastic so now we can leave comments it's checked and cool there we go oh it's not updating and if you remember what to do in case that happens is you need to head over to where you're making your mutation and then the on success we need to call query client that invalidate queries and we need to pass in the query that we want to invalidate in this case it's what what is it um detail post it's not detail post yeah I think it's detailed post actually cool let's see refresh yay oh there we go yay cool so now it adds it perfectly fine nice so there we go so we have loads of stuff already made which is quite nice and I think that's pretty much gonna be it for now I think I added a bit of framer motion to it just to make it a bit more interesting uh but yeah hope you hope you enjoyed it I'll put up the GitHub as well I guess I should show you how to uh upload this on versus Cell as well I might just make a separate video on that um because wow this has taken forever screw it let's do it let's finish it up you can go over to Purcell and essentially what you need to do is push this code up to GitHub right once you have the code pushed up to GitHub you can add the project here and I already have it here so I pushed it up looks like it errored out for some reason with some typescript here and then you basically go over here to settings and you add your environment variables everything that you pretty much set up in your watch me call it in your EMV file and your local file add all of them here right and not only that what you need to do is on Google let's go over to Google Cloud here we go to the console you also need to make sure you get that verse cell link from here so let's say I made this right I'm going to copy this first cell app over here and then remember when we added our callbacks so bubble credentials here you also need to specify that so here and post it add a URI to both of these paste in the Versa one here of course with the https as well so if I go over here let's see there we go so this is a live uh a live server the live version I have currently running I started adding like buttons and everything like that which is quite cool um paste that in like that and then here paste that in again and just add this off callback to it to make sure it works and then hit save and you should be pretty much good to go that should work live now all right that's gonna be it um hope you enjoyed this episode please drop a subscribe wow this has been ages but thank you so much for all the support and I'll catch you in the next one peace
Info
Channel: developedbyed
Views: 164,319
Rating: undefined out of 5
Keywords: web development, web development tutorial, full stack, full stack web development, react, react tutorial, web development react, react crash course, react 2023, web development 2023, prisma, next js, next 13, next js tutorial, javascript, javascript tutorial, full stack project, full stack tutorial, dev ed, developedbyed, next auth
Id: 4xduSsxa5Os
Channel Id: undefined
Length: 216min 18sec (12978 seconds)
Published: Tue Feb 14 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.