Full Stack Restaurant Food Ordering App Tutorial | Next.js 13 Project (Prisma PostgreSQL Stripe)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hello friends today we are gonna complete the full stack food ordering application using next.js and Prisma this is the home page we will fetch all these items from a database let's choose a product I can select a new Option and quantity let's add it to the cart as you can see there is a notification here and our state management tool increases this number immediately let's add some other products and open up the card page on this page I can remove any item and when I click on this button the login page shows up let's sign in with Google and right now I can log out or complete the payment process let's write the cut information and address and after the successful payment we will see this page it's gonna update our order and redirect us to the orders page all the order history of the user is here and if you are an admin you will be able to see all the orders and change their status and in the stripe dashboard you can see the payment details in the nail bar we have a button that is only visible to admins let's create a new product and here we can delete the item in this project we will be using postgres but you can choose any database provider you want because thanks to Prisma we will use the same structure regardless of in a database to make crude operations also we are going to use the Prisma adapter in next auth and you will see how easy to handle authentication and authorization in both client and server-side components and you will learn many other Technologies like Docker suchtan State Management tool stripe payment Gateway and more if you didn't watch the design part of this project I recommend you watch it first at least just check the folder structure and the pages I've created because in this tutorial I will drag this start creating the backend API OK if you want to see more projects like this one please like the video and we are ready to start before starting let me introduce you one of my favorite Chrome extensions Tango it's the sponsor of the video but I also use it in my daily workflow it's a free extension that allows you to create step-by-step documentation easily start capturing and click through your steps and Tango will create screenshots and write description for each step it saves a lot of time when creating guides or explaining to people how to use your application you can easily edit your steps and share them as HTML or PDF visit tango.us or search for it in the Chrome web store okay let's open up the s-code and create here any folder and inside this folder I will clone my next application from the previous tutorial let's open up GitHub repository and clone this UI design to do that you can directly download this project or if you are using git just copy this URL come back to the terminal and git clone paste your url dot enter okay let's install our libraries npm install or yarn okay they are here and we are ready to start our application I will say yarn down okay it's here let's open up okay our design is ready all these pages and components and they are ready to communicate with a backend server but before starting let me explain you the structure of the application let's say this is our next.js app router and in the previous tutorial we have created our pages let's say pages and in this tutorial we will create our API router and communicate with pages we will be able to send requests and get responses and we will patch products orders or whatever or create a new product and of course to do that we are gonna need a database in this project we will be using postgres database but if you want to use another database don't worry you can still use them because we will be using Prisma it's an open source orm and it allows us to make crude operations easily with any given database in the API we'll make a request let's say products find by ID and Prisma is going to create the actual database code in this case it's going to be an SQL code and it will search for this item and send that item to our API so it really doesn't matter which database you are using we are going to use exactly the same queries thanks to Prisma so let's see which tables we are going to use I'm going to add here relationship let's remove them and open up our application firstly we are gonna need a user when we login we are going to save that user to our DB and this user is going to have a name email image and is admin by default it's going to be false we are going to have only one admin and after that we will have some categories and they are going to have this title description color this image and when I click here as you can see there is a slack we are going to use it also like that and after creating category we are ready to create our products let's open up it's gonna have this image title description price and also we have some options here and to create those options we are going to need an object array let's see our structure as you can see there is an object array here and there's an is featured field here because remember in the home page we have these featured products and each product has one category but a single category can have multiple products to connect these two tables I'm gonna be using category slack of course you can store here the category ID but in our application it's much easier to take this where is our slack as you can see it's here we can reactive HR data using this Slack so I'll keep it like that as soon as it's Unique it doesn't matter which foreign key you are using and finally a user can create an order let's see we have its ID price products and status let's create here and to connect these two tables I'm gonna use this email address because in our application we are going to be using stripe as a payment Gateway and it's gonna store the user email and it will be easier to fetch that user's orders quickly here is the payment Gateway here is the crude operations and we are gonna send this information to our pages speaking of pages as you know we have two kinds of components the first one is server-side components let's say server-side rendering and the second one is client-side rendering and then we fetch any data for the server-side components we are going to be using next.js async components and for the client-side components when we need any user interaction we are going to be using react query let's say react query or the regular JavaScript fetch method so you are gonna learn both server side fetching and client-side fetching and you'll understand when you should use server site or client-side components and that's all for now so let's create our API route and see how to send data but before starting I want to remind you that if you are a beginner and don't know the next JS Basics you should probably watch my next chess tutorial first after watching that video everything will be much easier for you okay let's close this terminal and open up our app folder right now I'm going to create another folder here and it's going to be API and I'm gonna create my first endpoint and it's going to be categories and we should create here a route file remember when we create any page we are naming it page dot jsx or TSX and when we create a new API route its name should be route.ts or JS this is how next.js knows this is not a page this is a API route okay let's create our first method and see how it works I will say export const and I'm going to create a get function and let's send our response here to do that we are going to be using next response I can write here any message and I can send any status let's say 200 which means successful let's use this endpoint and see our response here I will say API categories and as you can see it's here and this is how we are using our route methods it's a get method but also you can create a post method or a put method or delete method but to do that firstly we are going to need a database we are going to store our items and after we will be able to fetch or create a new one I'm going to open up my terminal and let's install Prisma I will say yarn at Prisma and also to make crude operations we are going to need Prisma client let's install them and during this process let's open up the prismat documentation and here as you can see we have already installed our library and after that we are going to initialize Prisma using any database so let's copy here and change here and as you can see there is a new file here if I open up you're gonna see that our database provider is postgres and we are going to add here our database URL the easiest way to create a postgres database is using docker of course you can install postgres directly on your computer but when you try to deploy your application you have to install it from scratch or when you share your code with someone else they will have to install it on their computers also if you don't know what the docker is or how to use it don't worry it's really easy basically it provides us reusable environments for example we will just create a postgres instance and we will be able to run that in any other computers or servers easily using Docker to do that let's install Docker first just choose your operating system and download and after that you are going to see this interface and right now you should go ahead and create a Docker account I'm gonna open up hub.doctor.com you can create your own account here and after that you can search for postgres and as you can see this is the official image of postgres let's open up this one you can directly install this image to your computer and run it using this command let me zoom in by the way okay but the best way is to create a dedicated file just for this instance as you can see we are going to create this file and inside this file we will write our configurations the image name and inside we can write our database password username and database name you can find all of these here as you can see I said this is the best way to create because when you use your applications in a server or in other computer you are just gonna run this file and it's going to install everything you need so let's create this file and copy this configuration and after I'm going to explain you I'm going to open up my menu and inside source folder let's say docker and inside Docker compost and I'm gonna paste my configuration this is the image name basically we are going to install postgres in this container and after that we can give our database name let's create two more first one will be database user let's say my user my password and my DP like that of course you should use them in an environment file dot eme file but I'm just going to show you how you can use it and what else we can do we can give any port number and it's going to run on this port number on my computer and this is the actual port number where postgres working on let's give a tap here and we don't need adminer I can delete this basically it's like PHP in my admin so we can actually see the tables but I'm removing this because we will be using Prisma studio and we will be able to see our database and all its tables okay right now we are ready to run our database to do that I'm going to open up my source folder and Docker folder and if I say Docker compost up oops I didn't save here let's try again and as you can see it's installing our database with all its configuration and after that we are gonna reach it using this port number let's come back here as you can see our URL is in this emu file let's open up dot eme it's here right now I'm gonna change this username remember my user my password and my DB that's all I'm Gonna Save and we are ready to go right now I can create my tables I'm not creating users right now because we are going to handle this when we create authentication API route I'm gonna start with categories I will say model category and we are going to have an ID it's going to be string and we are going to say it's an ID and by default it's going to generate an ID like that and we are going to have created add date it's going to be a date time and by default the time will be now it's going to be the current time let me shrink here by the way and what else we are going to have a title is going to be a string I'm going to duplicate here we are going to have a description I will say color image and Slack I can delete others and remember in the product we are going to use this select string so it has to be unique otherwise it's not going to work and let's create products I will say product again ID created that title description and image we are going to have a product price and I will say it's a decimal because price can be like 29.99 so I'm not writing here integer it should be decimal and I will say is featured and it will be Boolean and by default is going to be false let me create any product we don't have to give this field by default it's going to be false and remember options is going to be object array this is how we are defining in Prisma and right now I can give the relationship between my tables we are going to be using this slack firstly I will say category its type will be category I'm taking this type and I'm going to write my relationship firstly I should give here a field name in the product model and it's going to represent this slack name in the category so let's create here first category slack for example whatever you say it doesn't matter it's going to be string and right now I can use it here the field name will be category slack and the references will be the slack this field is in our model and this field is in the category model but as you can see there is a warning here that because in the category model you don't have any product let's create I will say products that because a category can have multiple products in this case it's going to be a product array right now we don't have any warning again a product has only one category and we are storing its unique Slack and in the category model we have products list and its type is the array of products okay let's create orders model order again ID created at I'm going to copy this and it's going to have a price decimal yeah we're gonna have products let's say Json array I'm not writing here this product model that because we are going to store something different we are not storing great today's products instead we are storing let's see our cart as you can see we have products but it has only image title this option and price not all products basically we can use this object array and we are going to have status and we should write here a user and it should be a user model but we didn't create that so it can stay like that and what else I can give I can give stripe intent id and it's going to be string and unique then we take care of payments you are going to understand here better but for now don't worry about that it's basically stripe ID by the way it can be not required you can do it by using this question mark for this product for example I can say image is not required and that's all I think let's save and come here I'm going to open up a new terminal and I'm gonna run my SQL code let's open up menu and as you can see we have only this file but if I say MPX Prisma migrate though let's give a name as you can see we have a new folder here and inside we have our SQL code as you can see it creates all these tables and the relationship between our tables so we don't have to write any SQL code using Prisma everything is much much easier I want to show you one more thing if I write here MPX Prisma and Studio let's open up this link and as you can see all our models are here and they are empty for now let's create a category for example using Prisma studio and after we are going to use our API and as you can see by default it's creating an ID and date we don't have to worry about them and let's give a title actually let's open up our data I will shrink here or close and I will search for menu if you remember it was our menu data we can use them let's give Slack title description image and color is white I will save and let's create others quickly okay we have three items and right now using Prisma let's try to fetch them in our API let's come here if you remember it's our categories rather and I'm gonna fetch all these categories that's right here and right now it's going to be an async function that's because we are fetching our data and I will write here try catch block if there is an error we can send here let's say 500 and here we can send any message but instead of just text I'm going to send an object to do that we can use Json stringify and let's say message something went wrong and we can console log this here and in this try block I'm gonna say categories it's going to be await and here we should use here is my client let's check after creating these models we are migrating and after yeah I'm gonna use this choose my client let's call it here and import and I will say Prisma I'm going to write here my model name it's gonna be category and I will say find many and it's gonna fetch all the categories let's send this as a response let's duplicate this and move it here status will be 200 successful and inside this object I'm gonna send my categories I'm going to write here API categories and as you can see it sends all these data so using this API endpoint we can fetch our menu inside this menu page by the way let's zoom out a hundred percent okay this is how it looks let's open up menu and here I will close everything and open up this menu page and right now I'm gonna turn my component into async component because we are graphite data and remember it says server side component we can fetch our data directly so I'm gonna create here a function get data it's going to be an async function I'll say cons response wait we are going to fetch from our endpoint API and categories and you can write here any option and I will say cache and no store because by default it's going to Cache our data it's actually really good but for the development purpose to see our items better I'm not going to Cache anything and I can write here a condition I will say if response is not okay if there is a problem we can throw any error and let's say failed and finally if everything is okay it's going to return this response I will say return response to our Json let's use this function here right now let me render our component it's going to directly call this function I will say menu is going to be get data of course await and right now I can delete my dummy data we were fetching our items from this data file we don't need this anymore I'm gonna remove and there's a problem here that because we don't have any menu type right now so what I'm gonna do is creating here types folder and let's say types dot TS and I'm going to paste my menu type of course you can use it like that and you can create different folders here but I'm just gonna keep everything beginner friendly let's use it like that and I will import and that's all let's save and see I will refresh and as you can see it's exactly the same let's open up this studio and change this title for example I will save let's refresh and as you can see it has changed it means we are using our database right now let's take this back and Save and this is how it works guys it's really easy just use your Prisma client and make your crude operations let's do the same thing for products but it's going to be a little bit more complex let's create new API endpoint and it's going to be products let's create our route actually I will copy this and paste here and let's close others and this menu I will say fetch all products by the way instead of creating new Prisma client again and again I can create a special file for this Prisma client and I can initialize it only once because for the development modes it's going to create new client again and again so what I'm gonna do is creating here a new folder let's say utils and I will say connect let's actually open up the documentation as you can see the problem is initialize a new client each time because of the hot reload to prevent this we are gonna first check if there is an instance or not if there is we are gonna use it if there is not we are going to create a new client let's copy this and paste here export cons Prisma right now we can use it I'm gonna remove here and here and let's import okay let's do the same thing here okay right now we are gonna fetch all products only thing I should do is right here products and search for our product model and sand it here but there is something different here if I do that it's going to return all our products but we have to filter them first what I mean by that for the home page as you remember we have our featured products and we have another option if we choose any menu here it's going to take this category slack and it's going to search for products belong this slack ID so we have two options here firstly we are going to take this category name and if there is no category name it means we are in the home page we are going to return those featured items how I'm gonna take this category name if you watch my next Jazz video you already know this I'm gonna write here request it's typo B next yes request and I'm gonna take the search params I will say new URL request dot URL and we are going to search for any category search params I'm going to explain this right now just wait I'm gonna write it first search params get and category basically we are going to make a request and our endpoint is localhost 3000 API and products I'm gonna send here any category name like that and it's going to be for example pizzas and it's gonna take this parameter here it's going to take its value and using this value we can filter our products let's do that I'm going to delete here Prisma products and this time I can write here a condition and I will say where so I can write here any condition for example cat Slack is going to be only pizzas or price let's say 30 dollars or whatever you can write here any condition and I will say if there is a category fetch those products if there is no category fetch featured products to do that I'm going to be using spreads and I will say if there's a category cat slack will be category if there is not his featured will be true and finally we are going to return those products let's try I'm gonna open up this studio and let's add some products first let me make this bigger I will say Pizza one description there is no image price will be 22 it's going to be featured I will say true as you can see those are red because we have to choose a category and I'm gonna be choosing Pizza let's save and number pizza too 33 it's not going to be featured and the category will be again Pizza let's actually add one more and this category will be Burger again it can be featured let's give it a price Burger one burger what okay I will save and let's see I'm gonna open up to home page oops I zoomed in and in this component I'm gonna fetch my data let's open up featured and fetch our data let's open up category I will do exactly the same thing I will copy here and paste is going to be an async function and I'm going to call this data here and if you remember we are using this dummy data right now we don't need this I will do it and let's define it here I'll say const feature data sorry featured products and get data and again we don't have any type let's create I'm going to open up my type file and I'm going to create the product type remember previous video we have done all of this I'm not going to explain again and again let's use it here but remember it's a single product in this case it's going to be product array let's import okay let's see oops I returned categories is going to be products and perfect as you can see featured pizza and burger but if I open up the menu page and choose any menu here we are going to take this parameter and fetch our products let's open up menu page but remember it's the category of this menu I will say params of course we should write here A type let's define it here type props is going to be params category and it's going to be string let's use it here okay right now we have our category name using this name we can make request let's copy this data and paste here it's going to be a product but this time we are going to use this category name so let's take it here I'll say category and I will say category and I will paste it here let's turn this to a backtick if you don't know how I am doing this you can watch my via Squad video there are many useful vs code extensions and let's use this data here this function firstly it should be async let me close this menu and I will say const products awaits get data and we are going to pass this category we have params and it's category okay right now I can delete this dummy data and use these products and again I will give product type and array as you can see it's empty because we don't have any pasta but if I choose Pizza okay they are not here there is something wrong let's open up our route and our terminal okay we made the same request but inside our route there should be something wrong let's consolidate this cat I will refresh that's actually right category is cat okay what's that I don't know there's a mistake here let's try again and as you can see it's here we don't have any image we have only this title let's open up home page okay our featured products are here and let's open up pizzas and perfect if you don't know how to use spread when writing condition basically we are saying here if there's a cat spread this object in this case this item is going to go out from this function and if there is no cut it's going to take only this item okay let's remove this and I can show you how to create but we are going to do this at the end of the video because in the previous video I forgot creating an add new product page so we are going to create from scratch in this tutorial but it's not gonna be now so what can we do right now if you want to Let's create our authentication endpoint and take care of next.js auth I'm going to come here close everything I'm going to open up my menu and create a new API endpoint and it's going to be auth and right now we are going to be use auth.js let me zoom in if you remember my next JS video we should create another folder inside auth folder and let's open up next.js documentation firstly we should install next auth let's copy this create another terminal and I will say yarn at next auth and after that we are creating this next auth folder and it handles all our sub endpoints like sign in sign out session providers so on so we don't have to write them one by one we are just using this folder and it takes care of everything and this documentation is for next year's Pages folder but we are using app folder so instead of creating this file I'm going to create this folder and inside this folder I'm going to create my route file let's create route TS and I'm going to create and Handler here and it's going to handle all the get and pause methods so I will say const Handler is going to be next off and I'm going to export this Handler as get method and pause method and inside next auth we should give some options let's see as you can see firstly we should give next off secret we are using this to generate token let's open up emu file and add this here of course you should give any random text here but it can stay like that and after that we should wrap our application with this session provider that it uses context API under the hood it means we can use it in only client-side component of course we are not going to turn our entire application into client-side component instead I can create a special component just for this session provider and using that component I can wrap my application let's come here and create auth provider and I will say use client and I'm gonna take children remember how we are doing this I'll say props children will be react react not let's use it here by the way if you are not confident about typescript you can watch my typescript tutorial it's just a one hour tutorial and it shows everything you need to know about typescript and react so let's use these children here and I'm gonna use this session provider just like this so let's use this provider in our application remember we have a layout here by the way let's change our title llama restaurant okay this is the worst description ever but anyway and right now I'm gonna wrap my application after this body I will say auth provider and drop all these items let's import and that's all right now we are ready to use it but before let's give our options here you can directly give your options but I prefer using another file let's come here and find utils and I will say oh dot yes let's open up to documentation let's go back and as you can see we can use any provider in our example in our project we are using Google provider and Facebook provider let's create this Google first I will copy this and let's say export const auth options and its type will be next of options and I'm gonna paste providers of course it's gonna be Google provider like that let's import this and there's a problem here it says it can be string or undefined but it should be a string so you can come here and say as string you are basically saying that we are sure that it's a string or you can do the same thing by let's comment them out and like that okay let's call this here and import and that's all let's close here and let's try by the way I will save here we will add something else but before Let's test it I'm going to open up the login page and I'm gonna use use session hook I will say const data status it comes from you session and let's see what we have console log data equals data and status and when I click on this Google button I'm gonna sign in to do that I will say on click and we are going to call sign in and it comes from next auth and inside I'm gonna write my provider name which is Google okay if you remember we gave here some secret IDs Google ID and Google script to use this Google provider you should create an account on Google Cloud let's do that Cloud google.com I'm going to open up my console and here if you don't have any application just create a new one and after that you are going to see this page and if you open up apis and services you will see your information here and I'm gonna come here credentials and create a new credential yeah I'm going to be using Authentication another application is a web application let's give it a name and I'm going to write here my application URL three thousand if you deploy your application just change here and redirect URL will be let's copy this API endpoint auth and callback Google this is the main structure for our providers call back Google callback GitHub or whatever you use okay I will save and right now we have an ID and client secret let's copy this Google ID Google secret let's create them let's copy this and that's all let's try I'm gonna open my app there is a problem your session is using context API but our login page is a server component let's open up our login page and it should be of course use client right now I'm going to click here and as you can see it opens Google authentication page if I click it turns back to the application if I open my console let me zoom in by the way those errors comes from reactive tools don't worry about them there is an warning about our image there is a fill but sizes are missing okay we are going to take care of them but for now let's focus on this authentication at the beginning as you can see data is undefined and status is loading and after that it loads our data and it's an object and in this object we have our user information and status is authenticated it works so right now we are authenticated but we still keep seeing this page we shouldn't see this page to do that I'm going to create here another react hook and it's going to be rather used router by the way it shouldn't be next Rudder instead it should be next navigation because it's the newest version and I'm gonna create a condition we have status here let's remove them and I will say if status equals loading return let's say A P tag and I will say loading and one more and it's going to be if it's authenticated we shouldn't see this page anymore using this rather I'm gonna navigate to home page of course rather dot push Let's see we are in the home page let's click perfect it works right now let's change this Nail Bar instead of this login I want to see my orders let's close everything and open up nail bar and if you remember in the previous lesson we just created here a temporary user and it's just says true or false but right now we can use use session but in this case I have to make this component client-side component I don't want to do that to prevent this I'm going to create another component let's say user links it's gonna be use client and right now I can use this condition there let's cut this and call our component user links and I will paste it here let's actually say a div and inside this condition let's import this link next link and of course we don't have user instead we are going to be using use session hook I'll say const data and status use session actually we don't need this data we can just use this status and I will say if status equals authenticated show the orders let's change them and after orders I will also add another item let's say span and it's going to be logout button of course we should create here a parent like that and what's wrong here oh if it's authenticated you are gonna see this logout button if it's not it means we are not logged in yet we can see this thing let's create here on click event and we are going to be using next of sign out function and that's all let's see okay there is no space between them I will come here and say class name margin Left 4 and cursor will be pointer of course we can click okay as you can see we have a user but if I click here we are not logged in anymore let's try again perfect it's that easy guys by the way you don't have to use it in only your client components you can also use it for Server components or in your API to do that we will be using get server session function if you remember we have created here a dedicated file inside this file I can create another function export const get all session and we are going to be using get server session and inside we will pass these options like that right now using this function we can get our user and status in our server components and API let's save okay right now we have our user but how we are going to add this into our database if you are using Prisma and next authentication it's really easy let's search for Prisma adapter okay they are changing their websites because next auth is changing to auth.js so this kind of mistakes are normal let's open up next all.js it's exactly the same thing they are just changing the name and here adapters and Prisma let's install our library but if you don't want any trouble I recommend you to use next of Prisma adapter instead of off because it's not ready yet you can run into some errors so what I'm gonna do is let's open up terminal I'll say yarn at Prisma adapter and I'm Gonna Change here it's gonna be next auth and after that as you can see we are going to use this field and we are going to pass our client let's open up our option file and I'm going to write here adapter let's import and the client and what else in the Prisma schema we have to add some additional models as you can see we have user session and account it's a standard schema I will just copy paste here but I'm going to explain why we are using this let's copy here we already have our provider and client we don't need to copy here let's open up our schema and let's paste it here basically when we're logging with Google it's going to create a new user and also it's going to create an account and a session this session includes a token and it has a lifespan when it expires we are not going to be logged in anymore and we have an account here where we create a user it's going to create an account also and it stores our user ID and the provider refresh and access token basically let's log out if I log in with Google accounts and log out and after a comeback and sign in with Facebook it's not going to create any other user it's just gonna add this account to our user this is why it's important don't delete anything here but you can add any additional information for example I'm gonna add here is admin field and it's going to be Boolean and by default it's going to be false you can add whatever you want but it's enough for our application we are just gonna need to check if it's admin or not so I'm Gonna Save here and here let's open up terminal and if you remember here we are running our Prisma Studio I'm gonna kill this process and I'm gonna migrate again I will say MPX Prisma migrate and depth another name let's say add user and let's run our studio I will come back here and refresh and right now as you can see we have other models we don't have any user or account yet or session let's come back here by the way I'm gonna close everything it can be confusing for you I'm gonna sign in okay there's a problem probably it's using our cache data let's close our application and delete this next folder and start again yarn there let's try I'm gonna come back click here and as you can see we are logged in if I refresh here you are going to see that we have session user and account and it says we used Google our token and the user and this user is the user model that we have created let's check okay name email as you can see by default it's false and it works as we expected it's that easy guys you don't have to worry about authentication sessions tokens just use your adapter and that's all it's gonna create everything for you right now let's take care of orders if you remember we have some orders here and we should fetch those orders according to our user email but if we are the admin we are going to fetch all orders independent from any email and we will be able to update this status or we can delete those orders we can do whatever we want as an admin and to do that we are going to be using This Server session okay let's close them and open up all those endpoint okay we didn't create let's create I'll say orders let's copy these routes I'll say orders let's close here and this menu and I can delete here and I will check the user session I will say const session this is how we are using service sessions I will say get all session there is a space here and I will import my function by the way there is no bracket here it's going to be only session and I'm gonna write here my condition firstly if you are not authenticated we shouldn't fetch any of these items so I can come here and say if there's a session make here whatever you want if it's not else I'm gonna return an error let's move this here and it's going to be 401 which means you are not authenticated let's write it here and let's decide what we are gonna do I will say if the user is not admin use the user email and fetch all these data if it's admin fetch all orders so let's remove here and I will write my condition I will say if session user is admin of course by default it has only email image and name but also I want to add the is admin properly inside my session to do that we are going to add some additional configuration let's open up our config file or start yes and here firstly I'm gonna say session and I'm gonna give a strategy and it's going to be JWT we are going to check users token and after that I will write a callback function the first one will be session async session as you can see it takes those properties I'm gonna take here the token and session and I'm gonna return here a new session we are going to add is admin properly I'll say if there's a token session user is admin it's going to be token dot is admin and if there is no token we are going to drag the return the session and there's a problem here because as I said by default it includes only those items let's declare our new session type here I will come here and say declare module next auth and I'm going to change its interface session interface and I will say User it's going to take the user type again as you can see it comes from next off and additionally I'm gonna write is admin and its type will be login and again a problem because we should do the same thing for this token there is no is admin yet let's duplicate this and I'm going to change here it's gonna be JWT and here I will say JWT and right now we don't need user it's going to be only is admin like that right now we are taking this properly from token but inside this token we don't have is admin properly yet we should add this field into token I'm going to add another callback and it's going to be JWT it's going to take the token and firstly I'm gonna search my user in my database and I'm gonna check if the user is admin or not and I'm gonna take that Boolean and put inside my token let's say user in DB I wait Prisma dot user and I'll say find unique and I'm gonna write here my condition and I will say its email will be token dot email oops there is a column here and I will say my typescript I'm sure that it exists and I'm gonna edit my token right now I can update this is admin and it's going to be user in DB is admin now finally I'm going to return this token okay so again when we call our next authentication it's going to run our Prisma adapter but by default it's storing our sessions using username email and image but we are saying here we also need this admin properly we are doing this because we are gonna just write session get off session and we will be able to use this is admin otherwise we have to come here say const user await Prisma user and we will find unique and we will write here where condition and we are going to search for the email it's gonna come from our session user dot email and after finding user we are going to take the is admin purpley and continue our crude operation and writing this again and again is gonna cost you a lot of database query instead we are going to be using our session and our token and it's going to be ready to use and we are not going to make any additional query okay I will say if there's an admin send all orders I will say const orders Prisma order find mini and we are gonna return this orders and if it's not it means we are a regular user and we are gonna find only our orders so let's copy this in this case I'm going to write here a condition where the user email will be by the way I didn't add our user email here as you can see order doesn't have any user let's add I'll say user is going to be user when I enter as you can see it gives the user ID but as I said I'm not gonna use it instead I'm gonna use the user email as you can see it's Unique so there is no problem so let's say user email is going to be email let's create this okay that's all if you make any changes you have to migrate your Prisma schema again and let's say migrate that I'll say add user to order okay that's all let's open up our studio by the way okay I can use user email right now as you can see there is no problem and it's going to be our session user and its email and again I'm gonna send these orders let's open up our studio and create some orders I'm going to refresh and let's add a record it's going to be any price I will add a product here title Pizza one and Status will be being prepared and I'm going to choose a user it's going to be our user let's save and let's create other user I will say regular user user gmail.com we don't need to change anything I will save and let's create another order using this email address add record any price here any product and the user will be the second user okay let's save and let's open up our orders page of course we didn't fetch our data yet let's open up our orders page this is our API and or this page and if you want to Let's transform this page into a client-side component that because search engines cannot see this page and also if we are admin we are going to add here an input and we will be able to change this status so basically using server-side rendering is not a good idea here let's say use client and I'm gonna fetch my data using react query because when we change these status it's gonna automatically change those orders without refreshing the page let's open up its documentation okay let's get started and this is our library let's copy this and paste here yarn add 10 stack react query and after that as we did for Prisma we are going to create query client and as we did for authentication provider we are gonna wrap our application with this provider so you can use react query in all components and pages in your app in our example we are just going to use it here but in any case we are going to wrap our application because in the future we can add other components or pages and we will be able to use it in anywhere so let's create our provider I will save here and open up components and I will say query provider again use client I'm going to create this query client like that and again I'm going to take a children from props let's create this quickly it's going to be children react dot react not okay so let's wrap our children oops okay inside this I will say children and I'm going to import this provider okay that's all so let's use it in our layout after this auth provider I'm gonna say query provider and I'm gonna import it and that's all right now I'm able to use it in my orders page as you can see this is how we are fetching data and it returns is loading error and our data you don't have to worry about any State Management tool it's also caching your data and as I said if you edit or delete your data without refreshing page it refetches your own list here and let's copy this and I will say if there is loading return this loading text let's find our orders page and close them and I'm gonna paste it here let's import as you can see we should give here any unique key and it's going to be orders and I'm going to write here my endpoint http localhost three thousand API orders and that's all after that I can use this data as you can see we have some items here let's delete these two and I'm gonna wrap this one data.map for each item I'm gonna return this table row and don't forget giving your unique key here item dot ID let's create our type by the way I'm going to open up types and paste here by type let's copy this and take it here and let's see if there is a problem or not okay there is a problem let's see oh it returns 401 it means we are not authenticated of course we should verify our session here I will say const data but we are using exactly the same name here so I'm going to call it as session and status from use session hook and again I can use router hook const rather use rather comes from next navigation and I'm gonna write here my condition I will say if status unauthenticated we are gonna be redirected to home page I will say rather dot push home page and here I can write one more condition if it's loading or status is loading I'm just going to write this text if I don't write this here it's going to search for data directly and it's going to cause a problem but if it's looting firstly it's going to show up this text if there is no User it's going to redirect us to home page if there is User it's gonna fetch our data we are in the home page okay let's login okay let's open up orders okay there is still problem it says data map is not a function there must be something wrong here let's comment this out and let's see what's inside our data oh it's an object by the way let's close this Dev tool I can stop this anyway it can stay let's open up our backend oh I didn't write here await and it's sending us a promise object that's right here wait and let's see right now I'm going to open my page and let's take this back okay there is still something wrong that's right here a console log orders I'm gonna open up my terminal and there is something with this user email in our order let's open up schema okay we have user the user email field is a string and the reference is email let's open up our user okay string and unique I didn't save this or let's open Terminal again destroy this command and migrate that okay I saved it didn't ask me any name it can be something wrong with our cache again I'm gonna come here and kill my application delete here and run again no it works okay this caching is a really big problem for next Jazz because I have to delete this again and again it tries to make your development faster but also it causes some problems and it's not the first time but in the future I'm sure we are gonna have better versions let's do this here and as you can see there is only one item and it belongs us but if I come here and change my user let's open up user by the way I didn't run Studio let's come back uh refresh and I'm gonna come here make this is admin true all right now let's see as you can see there are two items we can see all orders right now what I'm gonna do is I'm gonna add here an input and we will be able to change the status of the product sorry order let's do that again too many files let's close everything and open up orders page before that let's add our Fields here I will say item dot ID it's gonna be item dot created add date but its type is date I'm gonna basically change this to a string in this case as you can see it shows the full date but I'm gonna take only this part here month and day so I can use slice method and it's going to start from zero and it's going to take the first 10 items like that item price and it's going to be product title item dot products but remember it's an array to not FaceTime let's write the first item and its title there is a problem here let's open up our type as you can see I said object but change its type to explain this better I'm going to open up the card component and we are going to add exactly the same products here because when we check out I'm gonna push those items into order products and it's going to include this image title option title and price if you want to Let's create our cut item type and after put it into our order products so let's come here and create cart item type as you can see title image price option title and quantity because we are going to add here quantity inside brackets we don't have here but we are going to create and let's use it here it's going to be cut item type array in this case we are not going to have any problem what else we have status here item dot status okay and for this status actually let's create our condition if we are in admin we are going to show an input instead of this text so I will come here and say if session user dot is admin we are going to show an input if it's not we are going to show this status and inside this input let's make this self-closed and I will say placeholder will be item status and let's give a class name I'm going to give some padding inside it's going to be ring remember last tutorial ring color is going to be red A hundred and rounded will be empty that of course it's going to be inside TD like that and right now I can create here a button and when I click on that button I can change my status to do that I can create a parent form I will say form is going to be this input and a button and let's say delete or we can add here an image Source it's going to be edit.png Alt I will give width and height let's say 20 you can find this image in the public folder by the way okay it's here but we don't have any background color and we cannot see it so I will say class name red 500 of course we need a padding and rounded will be full it's going to be a circle maybe 400 okay let's separate those items to do that I can give class name for the parent it's going to be a flexbox items will be Center just by Center and gap between items will be four okay when I click on this button we are gonna submit our new status to do that I'm gonna write here on click event sorry on submit event because it's a form and we are going to create a function and pass our item id let's say handle update yeah I'm gonna pass here Order ID of course do not refresh the page we should try it event prevent default so I'm gonna pass event also by the way it's not order it's going to be item let's create this function I can delete here we are going to have events and ID is going to be a string and this is gonna be let's check its type as you can see form events I can delete this Handler it's going to be event and right now I can use it here and Dot prevent default okay and after that I'm gonna take this value and make an API request of course you can create here input set input use State you can change it but I'm gonna directly reach that value using event how I'm gonna do that I will say const form will be event Target and its type is HTML form element and I'm going to take input and it's the first child of form because in form we have two elements input and button and the first one is input so if I say form elements and the first one and it's going to be HTML input element and I'm gonna take its value let's say status input dot value right now we have our new text so let's create a put method inside our route and push these new status into our order so I'm going to open up my menu API orders and here I'm going to create a new folder because we are going to need the order ID to update this let's see ID and new route let's create quickly our function export const is going to be put method async we are going to take the params we are going to need our ID let's write our type here directly params and it's going to include our ID which is a string so let's structure this ID it's going to be params and using this ID I can update my order let's say try catch block firstly I'm going to console log and after I'm gonna return new response let's say Json stringify it's gonna be a message something went wrong and that's right status and it's going to be 500. and let's update I will say Prisma is going to be order and update method I'm going to write my condition firstly I will find my order and its ID will be this ID and after that I'm gonna write my data which I want to change and we are going to take this from request buddy so let's write it here request is going to be next request and let's take the body here it's going to be await request.json okay I can use it here and remember we are going to send only this value we are not going to change anything else so I can drag the right here the status of this order will be body and that's all if everything is okay we are gonna return a response it's going to be 200 and order has been updated okay let's use this endpoint and remember we are using use Query and when I sent this new status it's gonna automatically refresh our list here basically we are going to use this query key and we will say update refresh this list so let's come here and say const mutation is going to be react query use mutation hook and I'm going to write here my rotation function and remember what we are going to need we are going to need an ID and Status let's write our types here ID will be string status will be string and we should return our fetch method I'm going to write my endpoint API orders and I'm going to pass here my ID and we are going to send a Json file to do that I will say headers content type is going to be application Json and inside body I'm gonna send my status let's say Json stringify and status by the way there is a problem here it says it's called conditionally because we said if it's loading return something else so I'm gonna move this here okay and I will say if it's successful we are going to revalidate our list here these orders data it's not going to take anything I need to use here query client so I will say query clients use Query client so let's use it here email did queries its key will be orders if you don't know react query it can be a little bit confusing but watch my other projects and make some practice and you are going to understand better so using this mutation I can send my ID and Status here mutation mutates and ID will be ID status will be stairs of course I should send them inside an object like we did here and that's all by the way I forgot here my method it's gonna be a put method let's check I'm gonna come here and change this status and as you can see something has changed here if I delete this input and as you can see test if I refresh the page you are gonna see that our status has changed but it's hard to see these updates what we can do we can add here a notification to do that we are going to be using react host file Library let's open up our console and I will say yarn add react toastify so I can use this library in all my components it means I'm gonna Define this in my layout let's write somewhere here after this footer I will say toast container and I can give its position you can choose anything you want but I want to see it on the bottom right like that team will be dark and I'm gonna close this notification after three seconds which means 3 000 milliseconds okay of course to give some style I'm gonna import its default style here so whenever I run these libraries function this container is gonna show up here and it's gonna show our message let's try I will say after this mutation success message and here the order status has been changed let's see I will change and perfect and I can write here another condition I can say if the status is delivered I'm gonna change its color it's gonna be white let's come here where is r row here as you can see its color is red so I'm going to write here a condition I will say if item status equals delivered is gonna be white actually let's write here directly it's not delivered in this case it's gonna be red otherwise it's going to be white let's fix this okay and as you can see it's white right now if I change here it's red again okay so right now we can take care of our cart let's remove our items here and use a state management Library let's open up a product by the way we didn't fetch a single product let's do that quickly you already know how to do that we have products and I'm gonna do exactly the same thing here I can copy this ID and paste here and instead of put I will say get let's say get single products and using its ID we are gonna fetch our product let's do that we don't need anybody it's going to be product I'll say find unique and its ID will be ID I can delete here let's say const product and finally I'm gonna pass it here Json stringify product okay let's use it where is our product here ID and its page again I can quickly fetch my item as we did here let's copy this and paste here and point will be products we are going to take an ID and pass it here okay let's call this function here of course it's going to be async const single products awaits get data and I'm gonna pass here my ID let's take it here it's going to be params params is going to include an ID which is a string oops perhaps okay let's use it here params.id and right now I can delete this dummy data and there's something wrong because in the design part we used a string for this total number let's fix it as you remember we are using this component let's open up I'm gonna delete this and its type will be product type let's open up our types here I'm gonna use it where is our page here let's import and there is something wrong here let's check oh I said number but its ID will be string actually we are going to change here part four now it can stay okay we cannot see our product let's close them and where is our product here oh what I did here products and as you can see there is something wrong with this price we are gonna change it I'm gonna show you why this is happening but for now let's open up our page and comment this out and as you can see our title and description and let's see what's wrong with this price if you remember we have some options and its type is title string additional price number but in our example I just created some random products and they don't have any options let's go and fix it I'm gonna come here and I will write a condition I will say if options and length it's gonna show it and again inside use effect there is the same problem I will say if length is going to add this price if not it's not going to add any additional price okay perfect actually let's add here some image and we can see better which one is that pizza two and I'm going to change this description and title and let's give some options I will say title small additional price let's say zero and let's copy this and add here others medium is going to be two and large okay let's see perfect okay what's this Zero by the way okay there's something wrong here actually what I'm gonna do is removing all those props and passing my product directly in this page I'm not gonna pass those one by one I'm gonna directly past my product and it's gonna be single products let's create our type I'm gonna remove this and it's gonna be product and its type will be product type okay right now I will say product dot price product dot options again price in this case I can drag to pass my product and here again product options okay but why it shows d0 here product Price Plus let's say two okay it's acting like a string if I delete here interesting there is something wrong with our condition here let's actually right here if block and I will say if product options length I will set my state set total and it's going to be quantity multiplied by product price additional number oh okay it's working right now I don't know what was wrong there but this is what we want I import this product instead of just ID price and options because when we add this product to cart we are gonna need this product it's image title and its option because remember in type we have cut item type and it includes title image price and option title and quantity but how we are going to do this when I click on this button I'm gonna increase this number at beginning is going to be zero and I'm gonna add this product into my cart and it's going to show it here and it's going to make this calculation to do that we are gonna need a state management tool of course you can use context API but the better idea is using a state management tool because it's not like authentication or changing dark mode light mode discard store changes all the time if your state changes often it's better to use State Management tool and in this video I'm going to show you something different it's not going to be Redux we are going to be using the Strand it's an open source tool and it's actually a German word and it means State and the pronunciation of this word in German is zushtant but I'm not going to be using German pronunciation I'm just gonna say suspend it's really easy to use I think it's easier than react toolkit let's actually install this Library first I'm going to open up my terminal yarn at star stand and after that we are going to create our state store as you can see we are going to give here our state and after our actions using set method we will be able to update our state and there is also a get method and it's going to call our state let me start using you are going to understand better as you can see this is how we are using our State field we will use our hook in our cart page and we are going to fetch all these data and in the initial State what we are going to need firstly we are going to need this total item and we are going to show it here also and we are going to need this total price and those items let's create I'm going to open up my menu let's close here and inside utils I'm going to create new file and it's going to be stored let's create our initial state we will have products empty array total items it's going to be zero and total price so let's create our store I will say export const use cut store create methods and I'm gonna write here my types remember in the example we are passing here our state first and after our functions so what I'm going to say here I'll say card type and my actions but we don't have yet let's create I will say types and I'm going to create my action types let's say action types we are going to have two actions first one will be add to cart action when I click here we are going to add our product and the second one will be removed from cart action when I click here we are going to delete this product so I'm gonna send my product as a payload and I will do the same thing here so I will say add two cards it's going to take a payload let's say item and its type will be cart item type and it's going to be a function oops I didn't say type here let's make this capital and one more and it's going to be removed from cart again we are going to take an item a product and we are going to return a function let's use it and I will import and we are going to have get and set methods let's write our state first and inside those actions we are going to update our state let's say products is going to be initial State products of course it's going to be products not product total items and total price and now I can write my actions first one will be add to cart let's add this item into our state to do that we are going to be using the set method we are going to take the state the current state and we are going to return something else and it's going to be products we are going to get the previous products state DOT products and I'm going to increase the quantity State total items plus item quantity and finally I'm going to increase the total price and it's going to be State total price and item price it shows warning because we didn't add remove ROM cart let's add that and after I'm gonna explain again you are going to understand don't worry I will say remove from cards and it's gonna take a payload and remove this from our current state so I will say set method I'm going to take my state and products will be State dots products are previous products and I'm gonna filter this let's say products and the product ID shouldn't be our Item ID if they are equal we are going to remove this product and again I'm going to copy here and this time is going to be minus by the way I'm gonna close here and remove from here and I set quantity of course it's going to be total items okay there is still something wrong I think the order of this set and get should be like this oh okay the order is important just like Express server you cannot put requests after response and that's pretty much all we are going to change something here but before let me explain again by using Sun stand we should pass inside our state and our actions you can directly distract your initial state but it should be every single state item here and after that we are adding our actions we are taking an item and its type is a cart item type remember this basically when I click here I'm gonna send this image title this option title and this number this price and quantity and I'm gonna take that item and push inside my products of course I didn't push this is our previous products I just added here one more item and additionally I'm going to increase this total items at the beginning is going to be zero when I click it's going to be 1. I'm saying take the previous number and add here item quantity if we add more than one item I'm gonna increase here it's gonna be two instead of one and exactly the same thing we are going to increase the total price and here we are doing exactly the same thing we are taking the item and filtering our products if the IDS are equal we are going to remove that product at the same time we are going to decrease this number and price let's use this and I'm going to show you one more thing I'm Gonna Save and let's open up our cart page and I'm gonna use my store hook and I'll say const products total items total price and what else we need here we can delete those items so let's say remove from cart and I will come from use cardstock okay let's use this item total items is here I will change it and this price let's change them it's gonna be total price and let's delete those items I'm gonna use only the first one and I'm gonna map through my products dot map for each item we are going to return this div let's add our key unique key will be item dot ID it's gonna be item dot image but it's optional remember let's write here a condition and I will say if item dot image exists and let's change here item dot title and it's going to be item dot option title and finally its price okay and when I click on this button I'm gonna remove my item let's use our function on click event I will say remove from cart and we are going to pass here our product which is item and to use this card store our components will be a client-side component sorry use client and let's see as you can see there is nothing inside zero items total is zero we don't have any product let's do the same thing for the Nail Bar I'm gonna copy here and open up my nail bar but I'm not gonna turn this snare bar into a client component if you remember we are using this cut icon component let's open up and it's going to be a client component and I'm going to call my hook here and we are gonna need only total items let's remove them and use it here okay it's that easy so let's open up any product and Q here a click event let's open up our price component remember it's a client component we can use it here directly let's call it first I'll say const use cart store and I'm just gonna take add to cart function let's use it here on click add to cart and I'm gonna push my item but remember its type is cut item type and it should be the ID title image price option title and quantity actually I'm gonna copy here and paste let's change those semicolons and it's going to be comma and I will say product dot ID let's copy this and product dot title image price but it's going to be the total price let's remove this and option title will be product options and the selected number but remember it says string so I'm gonna take only its title and the quantity will be currency but of course it can be possibly undefined to prevent this I can write a condition and I will say if it exists remember how we are doing this I will just say like and let's move this into an object and we are gonna distracture this if it exists okay and finally when I click here I can show here a notification so what I'm gonna do is take this function and right here handle card for example let's create this function const handle cards like that and finally I will say tossed success message and my message will be the product added to the cut let's see I hope everything is all right I'm gonna click here as you can see card is one and our notification is here let's check inside and perfect it's that easy and if I click here it's gonna remove and our card is zero again and one more thing if I add this product into my cart and if I refresh the page as as you can see it's gone but I want to persist my card to do that we are going to be using the persist middleware let's open up our store and after this create let's drop our function here and I will say persist let's import and after that there is a warning because we didn't pass any option let's pass I will come here and say the name will be cart basically we are gonna store this into our local storage and the name will be cart let's do that I will add and refresh the page as you can see it's working but there is an error and it says there was an error while hydrating to prevent this error I'm going to add here one more option and it's going to be skip hydration and it will be true it's happening because at the beginning next.js is trying to change the component type by default remember next.js is using server side components but since we use here use client it's trying to change this component but while that changing that error is happening to prevent this we should skip this hydration to do that I'm gonna open my component uh I will say use effect use card store persist and rehydrate and the dependency area will be empty so I will do the same thing wherever I use my card store for example in the cart page and in this component what was the name let's see okay cart icon okay let's see right now as you can see there is no error let's add medium pizza and I'm going to increase this quantity I will add as you can see four items and there's a problem here because we are adding exactly the same item but it shows like it's a different item to prevent this I'm gonna write a condition and I will say if the item is exists in the cut product we are gonna just increase this number and the item quantity by the way let's add it here next to this title foreign page and after this title I will say X and item quantity okay there is one item we added here three more items and instead of adding two items we are gonna make this four and increase this number let's remove this as you can see this is another effect I removed only one item but it removes all of them because it's exactly the same item so let's open up our store and for this function I'm gonna write a condition firstly I'm gonna find the item inside my products and I'm gonna check if it exists or not to do that I will say const product I can use the get method it's gonna get our state and I'm gonna take products inside this state let's check I'll say product in state products of course it's going to be products and I'm gonna try to find my item I will say find check each product inside and if it's ID equals our Item ID it means this product exists instead of adding new item we are going to change our product so let's write here a condition if product in state exists we are gonna do something if it's not we are going to set our state like that yes so what I'm gonna do here firstly I'm going to change my product I'm going to increase its price and quantity and I'm gonna add to my state let's update our products list so I will say const updated products products dot map I'm going to take to each product and if product ID equals product instead we are going to change that item if it's not we are going to directly return that item yeah I'm not going to change other items and each information of this item will stay but I'm gonna change its currently and price it's going to be item dot quantity plus product dot quantity I will do the same thing for price and that's all right now I can add my updated product into the state so I will say set state and the products will be the updated products total items will be State total items plus item dot quantity and price okay okay let's try I'm gonna add this to cart and I'm going to add one more time as you can see the total item is two but we see here only one product and we just increase this quantity and its price if I do it it's gonna delete all these items and it's zero let's add three items five more and perfect and you can consider this option also but I think you understood how it works and what else let's get back and I'm gonna add here a button that we can delete this item of course if we are the admin it's going to be an user interaction so I can separate my component let's close them and I'm going to add here a new file and it's going to be delete button let's say use client I'm just gonna return a button let's give class name is gonna be background thread I'm gonna give some padding round that will be full it's gonna be a circle and I'm gonna make it position absolute because when I add it into my single product component this page is gonna show up somewhere here so let's say top four right four sorry it should be like that right and top and let's use it in our product page after this deal I'm just gonna say delete and as you can see it's here because the parent is not relative so I'm gonna come here and it's going to be relative okay perfect right now instead of this text I can show my icon let's say image Source will be delete dot PNG it will be 20 height will be 20 okay perfect so firstly I should write here a condition because when we are not admin we shouldn't see this button to do that we are going to be using use session hook const data let's take this as session and status is going to be your session hook and I'm going to be using rather and let's write our condition remember what we are doing if it's loading we are gonna return loading text and number if it's unauthenticated we are not going to return any button finally if everything is okay and by the way I should say if it's not admin of course session dot user is admin okay if it's not authenticated or if it's not admin we are not going to return anything and if we are the admin we are gonna see this button and when I click on this button we are going to delete this product to do that we are gonna need our ID product ID let's take that I'm going to open up the product page and pass here ID it's going to be single product dot ID let's take this as a prop ID and it's going to be a string okay I will say on click event and I will say handle delete let's create const handle delete and I'm going to take this ID and make an API call but we didn't create these endpoint let's open up products ID it's here and as you can see we have get single product let's create one more and I will say delete single products and it's going to be a delete method and we are going to take the ID and if you want to Let's validate our user to do that we can use server side session and it's going to be 08 get auth session and I will say if session user is admin we are going to make some operation here we are going to delete our product if it's not we are going to return an error let's copy this paste here I will say for all three and you are not allowed okay what if we are to admin I will say product delete method and we are going to pass here the ID and if it's successful product has been deleted and that's all we don't need this product and let's check is admin we are going to do it and return this message if there is an error we are going to show it and if it's not admin we are going to return this it looks okay let's try it's gonna be an async function and I will say const response weight patch let's write here our endpoint http localhost 3000 API products and the product ID and it's going to be an delete method by the way you can use react query but we don't need we are not going to refresh anything when I click here it's gonna do it and we are going to open up let's say menu page I will say methods delete so let's check this response I will say if respawn status equals 200 it means it's successful we can be redirected to other Pages let's use rather and push and let's say menu and I'm going to write here a notification the product has been deleted or we can show the response message but whatever it can stay like that if there is a problem we are going to show the message let's say constata wait response.json and we are going to take that error this one or this one and we are going to send this message let's see error message and the message will be data Dot message okay let's try I don't want to remove this one let's try other one this burger I will click oh it should be inside our button let's try okay it's still not working because our endpoint is not correct 3000 API products and ID let's try and it's gone perfect and it's gone okay so what about this payment we are going to be using stripe as a payment method I know guys some of you don't have stripe in your country but it's the most popular payment Gateway if I use another method just special for your country other people will be mad so if you can't use stripe you can try to use something else but even if your country doesn't allow using stripe I highly recommend you still learn it because if you want to get an international job opportunity you should probably learn stripe also so let's close them it can stay and I'm going to open up stripe documentation okay this is the scrap dashboard after the login process you are going to see this page and here you're going to have your publishable key and secret key let's copy them and open up our EMV file and I will say stripe public key and stripe secret key let's see it is key I will copy and paste here I will save and right now we can install our libraries but before let's open up the documentation and see what we are gonna need we are going to accept online payments you can use this preview checkout page but everything will be in our application so I'm going to choose custom payment flow so let's come here and choose next.js so right now we are ready to install our libraries let's copy them subscribe and stripe.js yarn at stripe this is for our backend server and to see this page these payment methods we are going to need react stripe.js also I'm going to copy here so I will say yarn add react stripe okay I can close here and let me explain you what we are gonna do let's come here and create our Pages related to strike payments basically we are going to have three pages the first one is our cart page basically this page and when I click on this button it's going to open up the payment page we are gonna see our user information here and the payment methods and when I click on this button finally we are going to complete our payment and we will be redirected to a success page let's create one more it's going to be success so let's write our API here and this type Gateway and this is our API so let's see what we are going to do when I click on checkout button I'm gonna make an API request and basically we are going to create a new order so our endpoint will be orders and we are going to create a new order and it's going to include our user email and its status will be not paid it's not completed yet and after this request it's gonna return us our order ID and we are going to take that ID and pass it to payment page let's say order ID and as soon as this payment page shows up we are gonna make another request and we are going to create a stripe intent I'm gonna pass here my order ID and in our API we are going to be connected to stripe and we are going to create a new intent and it's going to return us a client secret using that client secret stripe is going to listen the user interaction and according to cart information we write here it's going to return an error or success message let's write here payment process and using this API we are going to be redirected to success or failure URL it can be also failure let's move this here fail page if something goes wrong we are going to see this page in our case it's going to be just our home page and we can show here some notification Maybe and if it's successful we are going to be redirected to success page and this URL is going to include our intent id it will be something like success ID and it's going to be intent id and using this ID we are gonna make the last API request foreign if you remember we have created here a new order but the status of that order was not paid and in this case using this intent id we are gonna find our order and we are going to confirm our order so let's say confirm and point and if everything is okay it's gonna return us a successful response and will be redirected to the orders page okay let me start coding you are going to understand better this is the main structure of our payment process so let's create those pages we already have cart I'm just going to create payment page and the success page and for this failure I'm just gonna use my home page and we already have orders okay let's open up our menu and I'm going to close everything here and let's create two more pages inside app directory I will say pay page payment page and I will say use client because we are gonna need the user interaction here and let's copy here and create another page and it's going to be success okay what about our endpoints we are going to have two main endpoints for the checkout create intent and confirm let's come here inside API I will say check out and the first endpoint will be create intent route dot TS and one more I will just copy this and paste here and it's going to be confirm okay let's come here and I'm gonna close this preview and as you can see this is create intent endpoint firstly we are going to initialize stripe but before let's handle our checkout button when I click here I'm going to create a new order let's open up cart page and I'm gonna write here on click event handle check out let's create const handle checkout is going to be an async function we are going to create a new order but firstly I'm gonna check if the user is logged in or not to do that remember what we are doing we are using use session hook and I will say if there is no session you use router and redirect user to home page I'll say const rather it was rather hook that it's gonna be next navigation and rather push and home page okay if there is a user finally we can use try catch block just console lock this error and what I'm gonna do here I will say const response wait I'm gonna make a request using hatch method localhost 3000 API and orders and it's going to be a post method and remember how we are sending data I'll say headers content type application Json and finally I can pass my data using body Json stringify and let's write our object let's remember what we have inside we are going to have price products and the status will be not paid we are not going to have any intent now but we are going to pass our user email so price will be total price remember it comes from the card store we are going to pass our products again from card store status will be not paid and the user email will be session user dot email and finally it's going to return us the order ID let's say constata await response Json I can use my router and push to payment page I'll say pay and we are going to pass here our order ID okay let's check our endpoint where is our API here orders and as you can see there is a post method here but it's empty let's say create order again we can do exactly the same thing we can check our session first like that if there is no session by the way let's make this async if there is no session we are going to set this error and if there is a session we can take the body request and Json of course we don't have requests let's get this here next request and using this body I can create a new order so I'm going to come here and say create and inside I'm gonna pass my data and it's going to be this body and it's going to turn us the New Order finally I can pass its ID let's check here okay we are using data ID so I can drag the sentence order I don't have to say ID and it's gonna be successfully created okay let's remove this let's try I'm gonna click here and there is an error that because we just created pay page but we didn't add here the order ID so let's come here and inside pay page of course it's going to be an ID you can say ID or order ID and I'm gonna move this page here okay let's open up and we are going to take this ID let's say params is gonna be params ID and string let's take this ID here it comes from params and right now using this ID we can create a new intent to that I'm gonna be using use effect hook because as soon as we open this page it's gonna make the request and it's going to connect to stripe and we will be able to make our payment so I will say use effect dependency array and it's going to be ID of course and let's say make request async function I'm creating a new function because we cannot make use effect async is going to give an error so I can create here my own function and call it here okay let's try catch if there is an error we are going to write it here and I will say const response await we are going to be using fetch method and my endpoint API create intent and I'm gonna pass here my ID the order ID so using this ID we are going to find our order and we are going to update this intent id and it's going to be a pause method and it's going to return us a client secret let's say const data await response dot Json and inside this data we are going to have the client secret let's check actually by the way we are using use effect okay it should be space of course did I do the same thing here okay it's gonna be space and let's see let's initialize our stripe first this is the order I can close here and open up create entire route let's paste it here and let's create our post method async and we are going to get the order ID params ID will be string let's take this ID quickly and using this ID firstly I'm gonna find my order because I'm gonna need the price I'll say const order it's going to be 08 Prisma order I'll say find unique and I'm gonna say where ID will be ID and I will say if there's an order create a new intent using stripe else we are going to return an error return new response Json stringify and I'm gonna send my message here order not found and after that is status 404 not found okay right now let's see how we can create a payment intent as you can see stripe payment intents and create method and here we are going to pass the price we can give any currency and payment methods it basically shows other payment methods it can be the card information or Bank code or whatever it might be depending on your country let's copy this and as you can see finally we are sending this client Secret let's firstly create our intent here we can calculate amounts but for now let's say a hundred dollars of course to do that you can multiply this by a hundred because by default this price is a cent if you multiply by 100 it's going to be a hundred dollars let's say USD and after that we can take this payment intent and return a client Secret let's duplicate this and move it here is going to be 200 and inside this object I'm gonna send client script it's going to be payment intent client secrets either way there will be a bracket here and that's all of course we didn't update our order let's update wait order update where ID will be ID and as data we are going to update our intent id let's open up our schema we are going to update this and it's going to be a payment intent dot ID I didn't say Prisma okay right now we have our client secret using this client Secret we are going to create our checkout form okay this is our payment page if you remember we made our request and here as you can see they created a used State let's actually do the same thing I'm going to open up my payment page and I will say use statehook I will directly use it like that and we have our data here and I'm going to say sets client secrets it's going to be data dot client Secret finally we can create our payment form let's see we are going to have some options here and using stripe elements we are going to pass our options here and we will create a checkout form but before we are gonna need this stripe promise let's check as you can see we are using our public key let's write it here it's going to be next public stripe publishable key let's change this actually yeah view file and I will change here okay and I'm gonna say it exists and let's create our element I will say if there is client Secret create a stripe element let's import this and we are going to create our options cons options each type will be stripe elements options and it's going to include our client script and we can change our theme Here you can choose dark mode light mode and this default one I'm going to use it and let's pass it here okay it's already here and let's create our checkout form I'm going to create a new component here again I will say use client and I'm gonna use it here okay let's see what we are gonna need I'm gonna scroll down and this is our checkout form so what we have here we have some states we are going to listen the user interaction and set our States but before this use effect let's come here as you can see this is our checkout form it includes our card information and other payment methods and when we click on the pay button this type is gonna listen our payment process and if everything is okay it's gonna create this message if it's the processing it will say loading or processing whatever you want and if there is something wrong it's gonna set our message with an error and here if everything is okay if there is no problem we are gonna be redirected to this URL and in our case it's going to be the success page okay let's copy here it's basically the standard code I don't want to touch anything here let's paste use effect use stripe hook elements hook and use state okay there are some warnings here I will say if it exists and they can be null also so I can come here and give my generics it can be a string or null and we are going to have handle submit but before let's create our form I'm gonna copy this and paste here let's import I can actually directly write it here and let's remove this and here there's a problem actually we don't need this email we are not going to send it anywhere we already have email in our order if there is an error it's going to be our error message or if there is no message I'll say something went wrong and here there is a problem let's check as you can see it's a form event and the generic is HTML form element that's right react form event and HTML form element okay let's see by the way if everything is okay we are going to be redirected to success page and this URL is going to include our intent id and using that ID we are going to update our order and it sends 404 because we are directly calling this route inside create intent I should give here my order ID like that let's change this ID it's going to be order ID and let's try okay it's here Let's test I'm gonna give the test numbers you can give a number actually here and I will say pay now and as you can see we are in the success page and we have payment entered here using this ID finally I can confirm my order let's open up confirm and again I can create here my ID and it's going to be intent id and I'm gonna move this here export const it's going to be a put method because we are going to update our order async let's take our intent id I'll do this quickly and try catch also lock this error let's update I will say oh wait Prisma order updates and we are going to take this intent id and find our order let's say where the intent id will be this intent id and finally we are going to send our data and it's going to be status let's say being prepared and let's send a message order has been updated and if there is an error is going to be something went wrong 500. okay let's use it in our success page if you remember our payment intent is here but we are going to reach this value it's really easy I will say const search params we are going to be using use search params hook basically it's the URL after this question mark If I say get payment intent it's going to return me this number so I will say const payment intent search params get and payment intent let's use router and I'm going to be using use effects as soon as we run this page we are going to run this user fact and if this payment in time changes we are gonna make our final API request I will say const make request async try catch and I will say await hatch method http localhost API confirm and I'm going to pass here my intent id and remember it's a put method let's call it here and if it's successful we are going to be redirected to the orders page push orders in this case we are going to need this router here and let's write here a message I will say it's successful please do not close the page and as you can see we are here and they are not paid let's actually delete everything here I'm going to refresh and let's create any one okay it's here but we don't have our address information to do that let's create another component and it's going to be address form it's going to be a form and let's give a title it's gravy address and we are going to be using stripe address element and I'm going to give my options mod will be shipping and we are going to have a custom on change event I will just copy paste from documentation you can check for details in stripe documentation but it's pretty much all let's use it in our checkout form before this button I will say address form and as you can see it's here let's try one more time another test the card number let's choose country if I don't give any address it's going to give me this error let's say test okay there are some options let's choose one of them and again if I click here and this is our order okay for the payment page I didn't give any class name and style this video is already too long and it's not the design part but you can find it in the GitHub repository don't worry I will give some style but for this video let's focus on functionality and what else we have we can see items or delete items but we cannot add new one let's do that in the menu page or actually we can use it here if you are the admin instead of this cut component we can show a button that says add new product and when I click that button I can open up add product page and it can validate the user if it's the admin it can show a form that we can add new product let's do that I'm gonna close them so I'm gonna create a new page I will say at page.tsx I'll say add page is going to be on client-side component and let's create our form inside this div let's add here a title add new product let's create our view and it's going to include a label let's say title and input and the name will be title let's create others description but it's not going to be input it's going to be a text area it will be a little bit bigger let's say description price it will be a number and category and finally we will be able to add some options let's say options and I'm going to create a do and inside this deal we are going to have two inputs the first one will be title option title let's say name title and one more and it's going to be additional price I will say number price and additional price let's actually add here additional and after this input I'm going to create a button that we can submit this option so I will say add option and after that I can show these options if we add a new option we are going to show it here let's create an option it's going to include to span first one will be the title let's say small for example and the other one will be let's say two dollars okay let's use our session and if you are not the admin I'm going to be using use router hook and navigate user to the home page I will say const use session data will be session and status I'm gonna create my router I'm pasting here because you already know how to use it and I'm going to create some inputs here the first one will be our product inputs I'll say const inputs set inputs I will say use state by the way I'm gonna keep this page really basic I'm not going to give any style but as I said in the repository you can find the better version of this ad page so let's write here empty inputs price is going to be zero category slack and after that I'm going to create option state option and it's going to have a title option title and additional price let's open I'll say add okay it's here maybe I can give some small styling so we can see better firstly for this form I'm gonna give some shadow I will say Flex Flags wrap gap between each item will be 4 and P will be 8. and for each div each item I will say with full Flex Flex column cap will be 2. and what about inputs I'm gonna give a ring ring color will be red 200 P2 and around it will be small okay I can do the same thing for description I can copy here and paste for this text area okay it doesn't look good but it can stay like that let's take care of this button let's give a width background color and text color and I can give a padding and finally for this option again I'm gonna give a ring let's give padding green color and rounded and finally our submit button type will be submit and let's give cast name padding two with full background color red and text color will be white of course I'm gonna change it but for now for the visibility I think is okay so let's update our state when I change these inputs I'm going to update my state to do that I'm going to be using handle change method let's use it for our inputs not for them it's an option I will say on change handle change okay since we are using name for each input we can update our state easily I'm gonna write here my type it will be change event and the element can be input or text area so I will say set inputs I'm going to take the previous value and return previous event Target name and it's going to equal you run Target value if you don't know why I am setting my state like that you can watch my use State video and after watching that video you will understand everything here of course you can create different view States for each item and change them one by one but also you can change them in one function like that so I can do the same thing for option let's say Change option when I enter any title and price I'm gonna update my state is ready set option and it will be just input element let's use it here on change Change option right now I can show my options here so what I'm gonna do is adding New View State and when I click on this button I'm gonna add this option into options array let's create I'll say const options set options use state it's going to be an empty array let's create our option type is going to be a title string and additional price let's use it here and here it's going to be option array by the way I can do the same thing for inputs like that oops I said 0 is going to be this string and right now I can update my options so I will come here and say on click Grant set options I will take the previous and return a new array and I'm going to add the option here right now I can use it here I'm gonna map through my options and show every single option here options map item and return this div of course we need a unique key we can use its title item.title and it's going to be item dot title item dot additional price by the way let's change this button I will just make this do I don't want to see any conflict because we are using form let's try I will say test I'm gonna add and as you can see it's here if I add one more perfect and when I click one of them I'm going to delete that option basically I'm gonna filter my options let's find out our single option it's here and when I click on this set options and options dot filter I'm gonna check its title if it equals our option title actually we are using same name let's change it I will say option like that if it doesn't equal our item title we are going to take those items just like that okay perfect and right now we can take all these fields and send them to our API using this button so I will come here and say on click handle submit actually we can use it directly on our form let's come here and I will say on submit okay let's create const handle submit you and its type will be react form event I will say prevent default I don't want to refresh the page and after that we can use try catch and send our data to our API it's going to be async const response 08 fetch method localhost API products methods and I'm gonna send here body let's say Json stringify and now that I'm gonna pass here firstly I'm gonna pass everything inside inputs and also I'm gonna add my options options will be options and if everything is okay we can take that product ID and use a router I will say cons data await response dot Json let's create use router oh we already have because we are using session and I will say rather push product and its ID it's product or products okay product and ID let's create our endpoint API products I'm going to open up this route file and we are fetching data about the post method is empty let's copy this and paste here I will take the body Here Comes buddy wait request and Json of course we don't have let's create and make this async next request and I will say Prisma product create I can delete here and I can pass my data and it's going to be body and finally I'm going to return this product 201 okay let's comment this out for now to make sure everything is okay or not actually let's open up our API and see if there's an error okay it's here let's create I will say test pizzas I'll add this option and submit and let's check okay there's something wrong okay we didn't add category Slack oh its name is still title I didn't change here it's going to be category Slack and what about others additional price title price description and title let's try and there is no warning let's open up our studio uh products and it's here and our option here test option and price but there is no description because I didn't add your own change event let's delete this and try one more time let's refresh actually I will refresh and it's here perfect so it works as you aspected let's see how we can add an image I'm going to come here and I will create one more div yeah it's going to be image input title will be file and I'm going to create one more use State here and it's going to be a file file set file use state and when I change this from change I will say set file event Target and files let's give this type okay there is no problem anymore and right now when I click on this button firstly I'm gonna upload my image and then take the image URL and add it to my body here to do that we can use cloudinary let's open up cloudonary.com and after the login process you are going to see your dashboard I'm going to open media library and let's create a new folder and I'm gonna say my app name and I'm going to open up my settings I'm going to choose upload I'm going to add a new preset give the name I'm going to choose exactly the same folder and the signing mode will be unsigned right now I can use this folder to upload my images to do that I'm going to open up upload API and copy this link and let's create here any function I'll say const upload it will be async and I will say const response await fetch method and I'm gonna paste this URL and the cloud name will be your username in this case it's going to be La model you will write here your own cloud name and it's gonna be image and it's going to be a post method post and body will be our file to do that I'm gonna create here a new form data cons data is going to be new form data data dot append the file name will be file and I'm going to add here R file by the way there is an error here that because we said it's going to be a file list but actually we are going to upload only single file it's not going to be multiple I'm going to come here and say handle change image I will create this function here event and the event name will be change event and I will say const Target it's going to be event Target and I will say as HTML input element by the way it's going to be event not Handler and I'm gonna take the first file first item I will say Target dot files as file list and its first element like that finally I can update my state I will say set file it's going to be item in this case its type will be just file and I'm going to add file and also I'm gonna add my upload preset app and upload preset is going to be my folder name and finally I can pass this data here and finally it's going to turn us a URL to image URL and we can return it I'll say const data await response.json oops we are using exactly the same name let's say response data and I will return response data dot URL so using this function we can upload our file let's write it here const URL is going to be upload function and after that I'm going to add here my image okay and I'm gonna write here header and the contact type will be form data and I forgot wait here let's try I will choose this image title description price category option and submit let's check I will refresh and it's here let's see menu burgers and of course next.js doesn't allow us to see this image to prevent this error I should add this URL into my next.js options okay let's add I'll come here next config and insights I will say images domains and I'm gonna add here what plus that let's check res claudinary.com oops I said array it's going to be an object okay let's see and it's here foreign so we finished our project of course I didn't add some realistic products but I hope you understood everything of course you can add some more features if you have any questions just use the Lama Dev social media accounts I hope you liked it if you learned something new today please like the video you can support Lama Day by joining to Channel or using the link in the description below don't forget to follow La modelo's social media accounts I hope I will see you in the next tutorial goodbye
Info
Channel: Lama Dev
Views: 59,208
Rating: undefined out of 5
Keywords: react, react tutorial, react project, react course, react next.js, next.js tutorial, next.js, next.js project, fullstack next.js project, next.js prisma, next.js postgresql, next prisma postgresql, docker, zustand, stripe, food delivery app, restaurant app, fullstack restaurant app, fullstack next.js website, auth.js, next.js app directory
Id: aYzT06aQkGI
Channel Id: undefined
Length: 195min 23sec (11723 seconds)
Published: Mon Aug 07 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.