Getting started with Prisma, Next.js & Postgres | FullStack Application

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
- [Narrator] Hey guys, welcome back to CodingAndCaffeine Channel. And today, we're gonna build a simple NextJS full stack application with Prisma. So this would be a basic application. So that way you can get started with Prisma and understanding the basics of this Node.js and TypeScript ORM. And so we'll use NextJS with this project and for the front-end UI, we're gonna use Semantic UI React and we'll connect the database with a postgres container in a Docker container. And let's get started creating the project and adding a few dependencies. Okay, so I'm on my desktop and the first thing that I want to do is that I want to create a new NextJS application with the command npx create next application. And I wanna give it a name as my-next-prisma-app. Let's create this one. Okay, so I'm in the project so let's add dependencies. So in yarnpkg.com, let's find. First thing, I'm gonna use TypeScript so I want to add typescript. Then I want to find a Prisma client. It will be prisma/client. I wanna also add prisma. I will need types/node. types/react. I will need semantic ui css and semantic ui react. When I open project with this code and these are our dependencies. And since we are working with TypeScript, I wanna quick rename my index and app.js files, and also the api. Or the cancel and make sure you want to run yarn dev and see if everything is going correctly, it's detecting TypeScript. Project and localhost 3000 We have the project. Okay, now we are ready to actually initialize Prisma in our projects. So I want to stop the server and type npx prisma in it. So what we have now in the project is the prisma folder where the schema prisma and environment variables. So actually we want to create our schema that we need for that. So I want to actually create a model called User. So this will have an id of type Int. Just a couple of annotations. Default autoincrement. We will have a firstName of type String. lastName as well, type string. We will have a role of type of Role that we don't have, but we will have in a moment, so these will be default. We'll use like developer. Email of type string and an avatar. This will be actually githubrepostory.png url for creating the avatar. Here we can have the enum Role. So this is user, admin, developer. Before pushing these migrations actually in the database, I want to create actually the docker compose for initializing our Docker containers. I will maybe accelerate the speed when I wrote these and you can follow the docker compose. (lofi music) (lofi upbeat music) Okay, this is the docker compose yml. Let's create the container in the batch. docker compose up in detached mode. So I was going to create my next prisma app in the dashboard of every containers. So as you can see here, is up and running the my next prisma app in the Docker dashboard. Make sure you grab this username and password in the environment variable here. So instead of johndoe, random password. You copy and paste this. This will be the database URL that Prisma is going to use for the connection. So now we can do the migration with the prisma migrate dev --preview-feature and is going to. Actually, I had another container, but in your case, it will be your first migration so I will type yes. So in this case, you will have the name of migration and I just wanna type init. And now in your project here, the migrations here of init. Okay, let's move on and create our first API. So actually I want to rename this create. So this will be our first API for Prisma, for creating the user. So this will be exported default async. So request, it will be, I would just wanna actually zoom a little bit. Request will be of type NextApiRequest and the response, NextApiResponse. This is the function and instead of doing this. Just wanna write so if req.method is different from POST. I want to return status, res.status, this will be 405 and give it a json, a message, method not allowed. We'll have a trycatch block. In trycatch, I want to actually create a body. So this will be req.body. I get used to do this, but I realized that I have some arrays actually. So if you import this and you do, UserCreateInput and you parse actually with this. Maybe it's going to work initially but then if you want to create complex objects, but suppose we put this in common. So for me actually, it's working also this one. So conts user the structuring the variable req.body. So let's create another variable. savedUser equal await, because we are in sync function. So prisma.user.create, but as you can see is not going to recognize the user because we have to run this command, npx prisma. Actually, it's npx not npm. Okay, so now. So instead of using the prisma import like this. If you have a lot of connections is going to give an error. Actually I want to create a new folder here called lib and in this folder, I will have a prisma file for having the prisma client globally so I want to write declare. (lofi upbeat music) Okay, so now we can import prisma from lib. Prisma. So we have the user and let's create first query and give it data and this will be the user. And actually, I can cut this one and pass actually the savedUser. And in case of error, I want to response that status of 400.json, our body will have a message of something went wrong and I wanna save this one. Okay, now we can close all of this files. Now we want to focus on the index that we have here so we can delete these main and also the footer here. We can actually so delete. We can have the Head and actually we want to use the cdn for Semantic UI so this will be the link. I want to save this one. Okay, so we will have a container importing from semantic UI react and this container, just want to give it a style for having a little bit of space so margin of 20. Of course, I want to close my container. So we'll have a header as well. So it would be an h3, so this is the syntax for Semantic UI for having the h3 title. So you can write, this app is powered by NextJS, Semantic UI and we can also import package.version, and you can import the package version from semantic ui react package. So now it's complaining that we should have one parent element. So I want to actually close all of this stuff with this and it's not longer complaining. This is pkg.version. So as you can see, we have details. So let's move on and we want to start under the Header to build the Form. I want to close the Form and this will have onSubmit. So we'll have async method. We can start to build the body. They will pass to the query so Prisma.UserCreateInput. So we'll have a firstName, the lastName, a role, email, avatar. So all of the properties are inside here in the node modules of the Prisma user model. Okay, so now I want to create actually another lib here, but I will put this one in the folder called utils, and this utils will have a file called fetcher. So everything they will fetch, it will be here. Fetcher. This will have the url and data as parameter. So fetch. We have the location.origin + url. We can pass the method. Not this but this one. Data or POST, GET. We have the credentials, include. I want to pass headers for avoiding course problems. You can write Content-Type, applications/json. And finally the body. We can JSON.stringify. What am I writing? I don't know. The data. And then, lastly, callback response to JSON and this are fetch lib. So in the index, I want to continue writing our query so since we are in async method, await fetcher so you import fetcher from the lib. This will be the URL, so in our case api/create then we'll pass the data, so it will be user and we want to pass the body. So this stuff are complaining because of course, we have to create a hoax. Just after the home, I want to create a parameter of initialUser. The way we can fetch from the Prisma every user. The first thing that I want to do, I want to create outside the home here. I want to create an async function. Actually, I just want to call it getServerSideProps. Even if this normal this function, you write this in the dedicated dynamic api, but just want to call it for the love of the meaning that this is a kind of a reset prompts, 'cause it's going to interrogate the prisma actually query for find the many user. Our users will have a type of Prisma.UserUncheckedCreateInput. And this because in this one, we have also the id. We're gonna grab this and this will be equal to await prisma. So from with prisma user.findMany. So this is it. This will be the function for actually interrogate Prisma, giving our users. So return, props of initialUsers and this will be returning the users. So I wanna create hoax for that. Let's destruct to write this so users, setUsers equal useState import from types of react index, Prisma., actually is the same of this. Well, I'm actually wrong because this is UserUncheckedCreateInputs. And so, again, complaining because the import here, we should have @. And this will be the initialUsers. Okay, so other hoax will be firstName, so setFirstName, useState. I want this string. Actually, I want to copy this and paste. This will be lastName, setLastName. This will be the email, setEmail. Avatar, setAvatar, useState. And finally, the role of setRole. So we save this one. This is actually just empty and it's not longer complaining. So under these fetcher, we have the await. So I want to use the setUsers state. So our users and the body. The rest the operator. Set firstName, because you want to emptied the inputs when we save the first user. LastName. The role null. Set email of empty. Okay, we can move on. Under the Form tag, we can start to build the Form.Group. Form.Group will have widths of equal. We'll have a Form.Input. This will have fluid the property, the label, FirstName. So just wanna save this one and give it a look. Okay, it seems to work. We can have also a placeholder. Same thing. The value of firstName. Lastly, the method, onChange when we type some input and event as parameter and set firstName e.target.value. Actually, we can close this Form.Input. Actually I want to just give it a empty lines so copy this one. This will be the second. Last Name. Last name. How do you call the last name? And setLastName e.target.value. And we will also have the avatar. This will be the avatar. setAvatar e.target.value. Okay, so now instead of having Form.Input, we can have Form.Select. It's gonna be the drop down actually for selecting. So the value, it will be the role. onChange, just write handleChange and we are going to create this function. So before the return, const handleChange equal, I wanna have a perimeter of event and the value as object. Use the setRole state and will pass the value. So the handleChange is calling here. So it's complaining because as you can see, property options is missing in type. So this type Form.Select. So we want to also create outside the home here. Couple of options in the array. You can also use key for that. I don't know, m, text, developer and value, developer. So I can copy and paste this for our three roles. So it will be the user. And a lock, admin. So now I can pass the options to our Form.Select. So options equal options. I wanna save this so we have the value. Actually you can also fluid the property and label Role. We can also have a placeholder Role. I want to save this. Let's take a look to our page what it's look like. So it seems that we have a few prominent suite, the CSS and we should take a look to our head. And of course, instead of using a rel in the link, we should put a stylesheet like this. So if I save this one, as you can see, we have a nice and better UI here. Okay, so let's now create a save button. So under the Form.Group, we can have Form.Button and this will be the Submit. And we have here the Submit's button. And I'm noticing that I have problem because this input should be aligned on the same line. So let's take a look and of course, these Form tag should surround everything until here before the container. And as you can see, we have a better looks. We have John Doe, first user again and let's grab a URL and add .png. Let's say I'm an admin and let's see what happened if I click on submit. It seems that we have a here a good response. So I want to actually open tablePlus, this is a free tool for creating your own PostgreSQL Connection. This was actually my awesome prisma-next. Connect and let's see what we have here. Okay, I forgot to add an email input. It's because we fix this. You can download the tablePlus for Mac OS and install and having this kind of motherboard for checking your user. So let's fix the email that we have here, so we can put this before the avatar. This will be the Email. The email and set the email. Okay, so if you want, we can cover another user, GitHub. I don't know, John Doe if we have something. Yeah, you know, we don't mind because it's just empty. Maybe like this or not, but actually Jane Dane. No matter what kind of Jane Dane. prisma.io. .png. She'll be a developer. Submit this. We have find a nice response. So as you can see the first one email was empty. So we have here, Jane Dane developer. Jane Dane prisma.io and this will be our avatar. So the next part is to create here a simple table and you can find this in Semantic UI. I'm skipping actually the part where I show you where we can find the components of a Semantic UI because the aim of this is just to showing you how we can have knowledge about Prisma. So in this case, we are creating user, but we can have also a delete because this we will need the delete for deleting also the users. So in this case, will be an export default async, request, response. So trycatch block. And again, as the body of here, we can log this but this one will be the id, because you have to find the user id for deleting actually. And the first condition, if there is no id, response that. What am I writing? Okay, so we'll have an error, you should have an id. I don't know, you customize your error message. And return or we create a user in a variable, prisma. Yeah, our imported user, delete. Where the id. So you don't need to do something like id. And res.status will be 200, return our user. And in case of error, res.status of 400, json, body message, something went wrong. So we have the delete api method. I guess we can move on and create a table under the Form actually. So the first thing is a called Divider and the Divider could have also title in the middle so horizontal and we can write Users. We have this kind of code line for a separate table with title users. And under this line, we can start to create the Table and a Table will have a basic property. They call this very, celled collapsing. And inside this table, we can have Table.Header and the Table.Row. And we can have actually three cell so Table.Cell, we can copy and paste twice times. Actually Table.Row, this will be HeaderCell. So I have to copy and paste again. So Table.HeaderCell so capital User, Email and we'll create an Action for, I think, a cool button here. Okay. Outside the Table.Header, we can have Table.Body and we can start to map into our users here. That way we can show, because we have already two users. Open the current braises and users.map. This will be our function for mapping. You wanna have a user and an index actually. And now we start to create the row. So Table.Row will have a key of index because that should separate the children. A Table.Cell and in the Table.Cell, we will have a Header as. There'll be an h4. We can pass an image. And the image, should import this one actually. We can take it from user avatar. This could be rounded size, mini if we have one. So we actually have our avatars here because these, we grabbed before the last one was the John Doe. So let's continue this and under the image, we can have the Header.Content. In the content, we can have user.firstName plus empty, space plus user.lastName. We can have here, Header.Subheader and I want to create a function for capitalizing. Actually, I want to show you what it looks like if you put just u.ROLE. So like this admin, so you want to just capitalize the first letter. The function of capitalizing will look like this. So under the handleChange function, we can have const capitalize and this will s as parameter. So, if typeof s different from a string or return empty actually. Otherwise, return s.charAt 0 .toUpperCase plus s.sli. Yeah, I think, it's slice 1 toLowercase . I want to save this and now we can have this function in the SubHeader. So I want to surround this, capitalize. This is sad, actually. As you can see, we have the code admin. Just want some letter big texture in admin and developer. Okay, so let's go ahead and we are under this first Table.Cell. Actually we can have another Table.Cell here and we can have actually user.email. And first one doesn't have because I forgot to put a twin if made the first request. Actually, let's copy and paste this one. Start to create our third cell. Okay so we can have a Button. I did fast but you should import all of this stuff here. So don't forget to import everything from Semantic UI React. So I am on the Button so the Button, we can also have you take a look in Button here. We can also have some kind of animations, like, you know, this you have these free animations here. So I'm gonna use just the fade, so animated. Fade, we will have a color of red and the onClick. This is the interesting part for us, so async. No parameters. So again, await, call the fetcher lib that we have here. And as you can, we have the api/delete as the URL. We can pass an id and this will be our user.id. So user.id. Okay, so await setUsers and make sure you want to then filter our users, because I want to be able to delete the line and having the other users. User. Let's go usr different from u. Gonna call a naming but you should follow the convention. Okay, so under the Button actually, I think I have to be here like. Button.Content visible and this will be Delete. Just take a look until now what we have. It's kinda like a cool. We're missing the other icon. And this will be the Button I forgot to put. Content hidden. Inside of here, we can have an Icon name, user delete. Okay, so we have our user delete here. So actually we are done. We should test the button here so let's clear the console and the network. And if I delete this one. We're good. So we have did delete, but we actually a problem here. So as you can see, the set user work but if I refresh, I didn't actually deleted this one. Just want to try to restart. So maybe just a matter of restarting the server. Refresh this and delete and delete. Okay, so in this case, it's successful. Let's grab another user. I don't know, Jacob? Some random name just for having a postery. Sorry for you, man, but just for. jacoba@gmail.com. The avatar .png. User. He has no visible 'cause. Daniel Key. Just some danielk@prisma.io. The avatar .png. Let me sync. Yeah. Oh, I forgot. Yeah, but we have here. We have this. Oh, this was before. Well, we have as user, three users. So if I delete this one, we now have. Okay, something, yeah. I delete this one and this was deleted. Our APIs works well. So I'm sorry that I didn't explain maybe a lot of stuff about the Semantic UI, but this is fine. I found this UI framework very cool. So I hope you guys enjoyed the video. And if you have questions, don't forget to subscribe to my channel and leave a comment below and thank you again for watching, and I'll see you in the next tutorial.
Info
Channel: Daniel Laera
Views: 2,620
Rating: 4.878788 out of 5
Keywords: Getting started with PRISMA, NEXTJS & POSTGRES, getting started with prisma nextjs postgres, prisma tutorial, prisma orm tutorial, postgresql, postgres tutorial, next js, next js prisma, next js postgresql, postgresql next js, next js tutorial, prisma postgres, react tutorial, postgres docker, prisma 2, prisma 2 tutorial, next js prisma 2, typescript graphql server from scratch, graphql server, postgresql remote connection, typescript graphql server
Id: 2rslnyHksqg
Channel Id: undefined
Length: 57min 3sec (3423 seconds)
Published: Thu Jun 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.