Build a Fullstack E-commerce using Next.js (react.js, mongo, tailwind, styled components)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today we are going to build a full stack eCommerce store with an admin panel using next JS it will be two projects the first one e-commerce admin where we are going to use Tailwind CSS for styling and the other project e-commerce front where we are going to use tight components both of them will be built from scratch using next.js react and Mongoose for our database when we log into our eCommerce admin here we can see some dashboard and some statistics then we have products here where we can add edit and delete products let me for example open this iPhone 14 pro black here as you can see we have name category some custom properties then we have photos and we can upload more photos and we have description and the price then we have a categories where we can add edit and delete categories let me open for example mobiles inside mobiles we have some custom properties those properties are used to create filters on categories page then we have orders and here we can just see all the incoming orders then we have admins so we can decide who can actually log into our e-commerce Hub in then we have settings where we can decide what should be the featured product on our homepage here and then we have also shipping price here on our e-commerce front we see the featured product on the whole page then we have the latest products here and as you can see I can add and remove products from my watchlist that I can find inside my account page we can also add products to the card from here with this cool animation now let me show you the categories page here as you can see we have Max free products per category and those links to show all products for this category here we have on a single category page we have those filters that we have created inside our e-commerce admin so I can filter for example to show only black mobiles and we have also sorting here so I can sort by price and stuff like this now let me show you all products here we are just showing all the products let me open for example this MacBook here we can see all the photos for this MacBook some description title and here we have reviews I can add a review using those Stars title and description now let me open this account page here as you can see I can see all my orders and my wishlist here I have my account details that is used inside the cart page here inside order information on the left side we have just our card with all the products I can add and remove them here I see the products total shipping and the total here I can continue to the payment to just go to the stripe checkout page and the last thing here on the right side is just a search functionality so I can search for for example iPhone and here as you can see it found two different iPhones and of course both of the projects are responsive so they look good on both mobiles and desktops this tutorial may look like it's very long because it's almost 12 hours but that's because I wanted to explain as much as possible to make it easy to follow the whole project is built from scratch so there is no starter code or anything I will put the timestamps and the source code in the description and as always all I ask for is that will smash that like button to give me some extra motivation for the future projects and if you have questions or anything let me know in the comments and now without further Ado let's dive into the all right so today we are going to build an e-commerce store and this will be actually two projects because when we are going to build an e-commerce we need to have products and stuff like this so we will need also an admin panel so I will have two projects here and the first one is e-commerce front and this will be for our e-commerce store and I also have this e-commerce admin project where we will have all admin dashboards and administration to create edit and update products see our orders and stuff like this so we are going to actually start with this e-commerce admin because to build e-commerce we need to have some kind of products in our database first so that's why we are going to start with e-commerce admin and both projects will be built with next.js but for e-commerce admin I will use Tailwind CSS and but in e-commerce front so our e-commerce store I will use standard components to make things different and so you can guys learn different ways of styling things right so let's start with our e-commerce admin so as you remember this will be a nexjs project so we can actually put our products into database and this will be an xjs project and as you can see for now for both projects I only have an empty directory empty folder here e-commerce admin and there's nothing here inside and I'm opening here at Terminal just to install NX JS project here so I will do yarn you can use npm if you want yarn create and let's do next up and let's do just dot so it will be installed here in the current directory and now it's asking if I want to use typescript and I will click no because we can add typescript later if you want as linked yes why not would you like to use Source no I don't need Source directory and experimental app no I don't want experimental staff import Alias let's just click default and now it's installing everything all right now it's installed so I can just hit yarn Dev to get a URL for my app and I will just copy this and I will put it into my browser and we have nec.js13 up working so I will hide my terminal for now and let's go into pages and our index.js page because this file shows this page for us all right so as you remember for our e-commerce admin we are going to use statewind but for eCommerce store we are going to start components so for now I will start by putting Tailwind CSS for next.js so I will just do Tailwind next JS so we can grab all the comments and I have already created my project so I just need to install those three I'll open new tab in my terminal here and I will do yarn add those three later we just need to run MPX television CSS in it so let's do this yes and then we need to add this statement config file so let's see Tailwind config yes and we need to put content to be like this so let's do content this and we are not using Source directory so I can just get rid of this and let's see now inside Global CSS and C Styles Global CSS let's remove everything from here and let's just put those three here all right so now we should try to see if it works and we'll restart here with my running yarn Dev again and I will refresh here we don't have any styles for now but let's go to index and let's see I will remove everything from here we'll just leave an empty return and I will just do div um we have some class name is like background red 500 and let's put test here and it looks like it works so we don't need this enter thing or fonts so let's just remove everything from here and we just have an home function and that's it so now the main thing that we need for our e-commerce admin panel is so we can be able to log in so um let's start by creating a login page right so I will maybe put a div with a class name to make it a dark background so let's do maybe background blue and let's do maybe 900 and let's make it width of width of screen same with have yeah and now on the middle I want to have a button logging with Google something like this so I'll create a button W say login with Google something like this and now I need some class names on this as well so let's do let's make it white so let's do a background white let's add some padding of two yeah and I I want it to be centered so let's add here Flex and let's put this button in a separate div here and now let's put also items Center senator yeah and now for this div let's add the class names to make it text Center and width of full yeah so now our button is on The Middle maybe we can add some rounded Corners rounded medium yeah so it will look better maybe even we can change it to large and let's add the bigger padding on the sides of four yeah I think that's much better I will make this a little bigger in my browser I will zoom in so you guys can see it better right so we have login with Google and this doesn't do anything if I'm clicking on it because now now we need to be able to add some kind of authentication and I think this is why would be to use next out for this so I will open next oh and let's see it's super easy we just need to add those three files or those three code Snippets so um let's start with this one on the left side inside Pages API out we need to put this file so let's go to our Pages API and here we need to create the directory oh off and inside out we need to create a directory called square brackets dot dot next out and that JS here on the end and this is because those parentheses are or so all requests that go to off will go to this specific file right so now we can copy this but before we paste anything I will add this Library here so let's do yarn and next off yeah and we will probably have all those providers so that's it let's just paste this here I will hide my terminal and sidebar and we have a lot of providers here and I will just leave one provider Google provider so I can remove apple and Facebook and so let's just leave it and remove this and in my provider yeah and we need two things for our Google provider Google ID and Google secret so um and should be inside the NV file so first let's create an EnV file inside our Ecommerce admin let's do a new file and let's do that EnV right and here we need Google ID and Google and sorry Google secret yeah and I think that's it let's see yeah Google ID and Google secret right and to get those we need to go to our Google search console um I think it's this one Google Cloud the console and we would create a new project here I'm already logged in you may need to log in here right I'll click new project and let's call our project and next e-commerce Eco Merce like this let's create it now it's created I will select this project all right and let's see here inside our navigation we have API and services let's see what's inside here we need to go to credentials and first we need to configure this content screen so let's do this and we can here only select external so let's do this create app nameless just do next e-commerce support email I will just pick my email and let's see do we need something else here yeah one time more my email address and let's click save and continue and here same thing save and continue save and continue back to dashboard and now we have it let's go back to credentials and I'm going to create credentials and it will be oauth client ID so let's pick this one application type web application and authorize redirect URLs and this needs to be our Local Host 3000 but with a specific uh URL so I will go to documentation quickly to go to providers and let's scroll down to Google and this is what we need to use so I will copy this one and let's put it here so localhost 3000 slash API slash out slash callback slash Google and URL we don't need any more referrals let's create it and now we have our client ID and client secret so I will copy it and I will put it here maybe inside those so let's do it like this and for client secret it will be this one yeah I prefer to put it inside ample serves here so well let's do this now I think we are done here so let's click ok now let's see here still nothing works but we just put our first file so let's go back to next of Js and let's see and we have our provider configuration here and next thing is that inside our Pages up jsx we need to put session provider so let's go here and let's see inside the pages app.js we need to put our session provider went to import session provider so let's do this and let's see and we need to change this up so we will provide our session to the main component we have here because we haven't changed anything here I would just copy and paste it so it will be faster like this and it looks a bit of old so I will try to reformat it and now I think it looks better yeah right so we have our app component here and we have main component here as a property and we have page props that this session and the rest right and this should just work let's go to our client page which will be our index.js I guess and there are a few things we need to add the first is this import so let's um select this and on the top I will put this import so we are importing your session sign in and sign out all right so now we can grab um data from use session so let's do this and now let's see and use session returns uh session for us it's renamed from data to session and now we can as you can see here in the example we can check if we have session then it means that the user is logged in otherwise we are not logged in so if um let's do it like this if we don't have any session let's return just not log the uh in like this and let's see inside our app we are not logged in all right so if we are not logged in we should actually see all this so I will do return parenthesis and let's put this button to login otherwise here we will be actually logged in so let's do just return parenthesis and maybe just a div logged in all right and we can probably just grab some more stuff here like session user email so let's do this logged in and let's print session session user email right but for now we are not logged in and as you can see for logging it logging in button we can use our sign in method that we are importing here so let's use it and we'll put here on click and here I will put Arrow function and let's put here sign in like this and now let's see if this worked I will refresh login yes it works but the problem is it's redirecting us to a specific next of page now I don't want to have it I want to have it on my button here so to fix it you just need to add a provider id here and the param and for Google is just Google so if I save it like this and then let's see I will click login with Google I'm redirected to a login page all right and now I can pick my user and I'm logged in as my user if I refresh I'm still logged in so that is really nice all right but now I'm logged in but the problem is I don't have any database I'm just logged in and I don't know what type of user information I have and stuff like this so we should be able to put all the users in a database when they log in I want to have information about every user so and I will create a database on Atlas so let's open Manga Atlas and we'll hear sign in with my Google account yes and for next out they have actually inside documentation they have adapters for mongodb here as well so let's see here mongodb and we just need to yarn add this so let's do this yarn add those things and we need to add a lib mongodb.ts this is typescript file but we can just for now get rid of a typescript part right so I will just select all of this let's copy and we need to put it they say we need to put inside the lib DB so let's do this inside we don't have any lib directory so our created here lib and we don't use typescript yet for this project so I will just do mongodb.js and here inside I will just paste this and we have some errors like we don't have client here typescript thing and we don't need this either this is a promise and yeah I think that's it now we can use it and if you are wondering what this file is doing it's basically a wrapper for a mongodb connection so the problem is that for serverless functions and we try to have we try to reuse existing connections so if we are if we are running the same maybe not even the same code but the same project again we send another request we try to find first an active connection to the database that we can reuse instead of connecting again so this is what this file is doing all right so uh now and let's see we have this one now we can go to our next auf file so let's go to Pages API off and next off and here we need to put mongodb adapter so let's add uh adapter here param adapter and now let's do DB adapter and it has been imported for me here if it doesn't automatically import for you you just need to add it manually and we have mongodb ad up there and let's see here we just need to put client promise so now the client client promise as you can see the client promise is actually the export of our lib mongodb file so this will just reuse an active connection to the database if we don't if we have an active connection if it doesn't it just creates a new connection here mongodb client and it creates just a connection right so now we have it let's go back to the next half let's see I think that's all we need and we are just a comma here and well let's open our app looks like we need to log in again so let's log in with Google there's an error here and it's because we didn't provide the mongodb url url so let's see here inside and they want to have a URL here to the database but we didn't create it in the database yet so let's create inside at last I'll create a new project new project here and let's call this one again next e-commerce like this and here I'll just click next create project let's build our database and we'll use a free version and let's see I think that's all we need let's create it and now we need to create a user and password my user will be e-commerce and the password will be I will do for now e-commerce one two three and I will change it later so you guys cannot reuse it let's create user and now we need to add IPS that will be able to access the database and for just local development it's the only IP you need is your local IP so I'll put my local IP if you put the application to production and you publish this application you need to pick you need to put all and you need to put a mask for all IPS I will show you in a minute I will just click here finish and close go to database and here inside the network access you can actually add more IP addresses and you can click this one allow access from anywhere in case you publish your app all right now it's creating my database here but I can put my mongodb URL so I will go to my DOT in v file and let's add a new row DB URL s here and now I need to wait for this database to be created all right so now our database is created I will click connect here connect your application and here we get our URL here for our manga database connection so I'll just paste it here I just need to replace password with my password e-commerce one two three I would change it later now let's see we have an error let's see why it will open Terminal here I will just restart our app so let's do your Dev again and let's go to localhost 3000 and let's see if it works I will log in with Google I will log in with my user and we are logged in let's check the database I'll close this one let's see browse Collections and we have accounts sessions and users and sessions is self-explanatory but users and accounts what's the difference between those and the thing is that when one user logs in with different providers for example Twitter and Google they will have two accounts so one user can have different many accounts so for now I have only one account and one user but that's because I have only one provider all right so here we have the basic information about the user so email and name and here inside accounts we have information about um our users that logged in with a specific provider like Google all right so let's see we have information about our user here we have email and stab so now we can continue we are logged in and we can now design our admin panel so let's go to our index.js here and let's see here we have just logged in as session user email right so the first thing I want to do is to add this dark skin so I will do a div with some class names and let's do background and Below 900 I want to have this dark blue and I will put this logged in as this user and let's see here now I'll add the minimum half of screen so it will take the full screen and now I would like to have a navigation on the left side and then the content on the right side so for our navigation for our navigation I will create a separate component so let's see I will close this API and inside the not inside Pages I'll create a separate directory for components let's go directory components yes and inside I will put maybe just nav.js all right and here just export default function navigation now and it will just return let's say it will just return a div with navigation just text here inside and inside the index.js let's just use this component let's use NAB yeah and it has been imported here for me and we can see navigation here right so now let's go inside navigation and let's put everything inside our side oops it should be a side like this and so here we will have all the everything that should be on the left side so I will put maybe first a logo or something like this on the top so we'll have first the logo and then our navigation so for logo I would like to use some kind of Icon let's see store yeah I will take this one copy jsx and let's put the div with or maybe not a link let's make it an a for now and I will put this icon and let's put maybe also a span with some class names and inside this pen we will say next or maybe just e-commerce admin with capital A so I'm going to end this let's see how it looks like it looks really bad but for this a we can add some class names here as well so let's do Flex here this is mirror but now one thing I want to change all the texts here should be white so let's do aside class name and let's put text white yeah that's better let's add maybe even some padding and as the padding of four yeah why not now under this a tag and I will put navigation so let's do this NAB and then let's see we need first maybe our home page for admin panel will be a dashboard so uh let's do a link but we shouldn't use a tags so I will use actually a link from next next.js link and here the first link will be just dashboard and let's see this didn't work because we need to have ref and just do just slash we have dashboard but I want to have an icon for each link so let's go to icons here let's search for home I think this one work let's put it here yeah let's see here we have home and maybe we should change this one to a link as well so let's do a link and let's do graph it's required craft just slash and it works so now I would just put more links here and I think we need another link for orders that we will need later and we will need one for products so we can have products maybe I will put products above orders right and maybe one more for like a general settings so let's do settings here the last one will be settings and I want to have a cog icon on this one so let's search for Cog this one will work let's put it here yeah and now who orders I would like to have a list something like this will work maybe we can take this one let's take this one for orders yes and then let's see for products I want to have some kind of package or a box I think this one work yeah and let's see now how it looks like yeah we have something but now we need to make some spacing and stuff so for all links here one two three four links I will add the class names on all of those and I want to make them Flex I want to add a gap of at least two or maybe one and I think this will work for now so now for this whole navigation thing I will add here Flex as well but I will change it to flex column so there will be under each other and I'll add Gap here of maybe two yeah so we have some spacing and now for this for our logo I want to add some more spacing here as well so let's add Gap one and some margin bottom of at least four all right so this will work for now let's go back to index.js and as you remember on the right side I would like to have a Content over specific page so let's say or dashboard now I want to have like my latest order or something like this or statistics so here we have this div logged in as blah blah blah but we need to actually add a flex here so those two will be next to each other right so we have this logged in as me I will add some more class names here so uh let's uh make it let's make the content Part White so let's do background to White yes and this one should grow all the way to the right side so let's do grow or maybe it should be Flex grow Flex grow yes and I want to have a little bit of spacing from the top and from the right so let's try with Martin top one yes and margin right off one yes maybe we can do more two and two right and now I will add the rounded corners large and let's add some padding of or yeah something like this and for the margin I will even put margin from the bottom margin bottom zero sorry bottom two all right so now we have a white box for our content and let's see now I would like to make this first one selected so let's go back to our navigation and let's see all the links have the same class names here Flex Gap One Flex Gap one but I'll put those as a constant so we'll copy this I'll put a constant here const and let's say inactive link equals a string and let's put those let's put const active link and here I will post everything that is inside inactive link a space and I will add background of white and let's now use it somewhere those two's those two those two so here here here and here let's add current brackets and let's put inactive link but on the first one we will make it active all right something like this now for active link we will change the text color to let's say this dark blue blue and 900 yeah and I would like to have a little bit of panning on all of those so let's do panning one here and let's do rounded corners on the left side so let's do rounded run the left and then let's do large yeah something like this and now I would like to get rid of this spacing here so as you can see the spacing comes from this padding four on the other side and I will just remove it by doing padding right of zero yeah now this works but for our here logo here we need to add some more spacing so let's say this is the first link here and I will just put a margin right of two yeah so we have some spacing maybe four so that's better so right now let's fix maybe other links so the first will be just slashed the home page then we'll have products yeah and the third one will be orders yes and the fourth one will be just settings yeah and then another thing now if I click this one and we are at products but nothing is shown because we don't have any page for products yet right so I will go back for now and maybe let's create a page for products and let's see how our index looks like looks like and we have we have too much stuff going on here so we need to refactor this first so the thing is that I don't want to put all of this on every page because it will be too much of copy paste so instead I will create a layout component here inside components new file layout dot JS and I'll put everything inside layout so I can reuse it so I will just copy all of this and I will put it inside layout like this but I will rename it to layout and we are using session but it's not imported same in the same with sign in so let's go to index.js and we forgot about the top line here so let's put it even inside our layout yes now let's go back to our index.js and we don't need all of this code so I will just put an empty home function and we can get rid of all of this and our home function will just return layout layout but inside layout we'll say test all right and now I would like to see this test here instead of this logged in as blah blah blah so let's go inside layout and let's grab our children from here and instead of showing this logged in as blah blah blah I'll get rid of this and here inside I will just put our children yeah and we have our test here so this means that we can use the same instruction for products page so let's do new page here new file and let's do products.js all right and here let's do just export default function products and let's see how it looks inside the index it's home with capital uh H so let's do maybe Capital P4 products and it should just return uh layout but let's put it inside parenthesis just for just in case layout inside layout let's just say products page here all right now if I click products we have products page here right but I'm clicking here and it's still the dashboard link that is active so let's fix it now inside navigation as you can see we have active link always on the first one so to know what type link we should make active and active classes on I need to know what the what's the URL and to check it I will use location sir it's not location it's actually really use a router so let's use router from next router I guess and as the const router equals this and let's just constant lock this our router here so we can see how it looks like inside what type of data we have I'll make it a little bigger and as you can see here we have an object with router and we have S path and let's see do we have something more we have path name yeah I guess we can just use path name so so now by checking the path name we can we can say if it's products and then the products link should be should have the active link classes so let's grab the path name now so let's do const path name equals the router and now for the here for products we'll remove this inactive link and we'll check that path name includes and in it includes slash products then we'll add active link classes otherwise inactive link right so now we have products and dashboard active all right so let's fix some more dashboard link here that is always active and now let's see here we have active link and the thing is we need to check if the path name let's see if we go to here let's open or clear here let's refresh and I think I removed the console log but we can check that path name is just exactly only slash then we know we should make it active otherwise inactively right let's go to products and as you can see only products is active now right and we should probably make the same thing we did for products for other links so let's do now four orders and let's change it to orders because it should be active only for orders now for settings let's just change this to settings all right and let's see we don't have Pages for those so that's why we'll get 404 but otherwise it just works right so maybe for the home page let's maybe just put some kind of hello and username so here I will just let's put the div and here I will add some class names to make for example the text color blue 900 and inside I will just say hello and the email address so let's do session but we need to grab the session first on the accounts session and but as you remember it just renamed from data to session use session so let's use session and here we here we are renaming and data to session and the session user email and this will be only if we have session so let's add a question mark here and here session is not defined all right so if we if we don't have any session let's just return nothing sorry it's session with 2s like this and now it works so on the beginning on the first render this can be that's why we need this one but probably we don't need this anymore because we have this those question marks here inside we'll also have a set of email we can use just name so I will have my name and we have an image there I think so the console log to see let's console log a session and let's see what we have inside session user we have image that we can use so I will use this image and I'll put an image here and and the source will be actually just session user and image let's see and this is my image from my Google account so um that is really nice I will put this image on the right side so let's put maybe here a flex and the first part will be inside the let's put um H1 or maybe H2 here for this hello part and the second part will be inside and div so let's put it like this and this image I want to make it smaller so let's do maybe a wave of 6 and a half of six as well yeah this will work and next to this I want to print the name so let's do session and user name like this and on this diff I will do Flex as well so it will be next to each other and this whole div I want to add some background colors so in the background let's do gray and let's do 200. should be probably gray with a yeah maybe 300 yes and the text inside should be black yeah and let's add some gap of at least one yeah and now I want to put this on the right side so for this Flex I want to add a space between space and between no try with space around no the flex sorry it should be justify and between yeah now it works now for this session username here I put a span and I will add some padding on the sides of or maybe on the top and the bottom of one and on the sides of two and now I'll put my name here yes but but I will make this uh my image a little bigger let's do eight here and now uh maybe I can just maybe I can even remove this from the top and the bottom it doesn't need to be that big and let's put it back to six yeah I want to make it rounded so it would be like a widget rounded large and the image hasn't been rounded so I need to add actually here on the image or not on the image on this div overflow a hidden yeah so now even the image is rounded right here maybe my name I will put it as a bold text yeah so it will be prettier and and I think that will be it for now for our dashboard later we will add maybe some kind of Statistics here and latest products here something like this but now for now we just need to add products for our e-commerce store so let's do this let's go to products yes and to our products we need to add a button that will say like add a product so let's do and this button will be actually a link so let's do link and it will go to slash products Slash new let's say something like this and it will say add new product yeah now we need to add some class names so it will look like a button so let's add maybe background green of let's see 700 and let's do text right and let's see yeah let's add some padding uh on the top and on the top and the bottom of one and on the sides of at least two I don't like this green so I think I would change it to background off and gray 200 and the text will be default black maybe darker gray 300 here and the important part let's do a rounded mediums that will be here so it will have rounded corners maybe we can change the background color to the same as we have this dark blue so let's try with a text white here and background blue 900 I think this this looks nice so now we'll go with this one for now right so when we click this it will go to slash products slash new but again we have 4 4 because we don't have page for this one so inside Pages let's create directory called pages pages and inside we need to create a file called new DOT Js sorry it shouldn't be pages and it should be products refactor rename products and now to new file new.js and here let's do export default function and let's call this one new product and parenthesis here and it will just return we need to return our layout and aside let's say just new product yeah we have layout but it hasn't been imported for me so let's try again layout now it's imported I try to refresh yeah we have new product we can go back a new product a new product page all right and well now we need to create a form for all new products so we will need an input for product name let's add the placeholder product name yeah something like this we don't have any Borders or anything on this but I think we can add the global styling for all our inputs so we don't need to add classes on every element so on input let's say like this I will add border or I can just do like this apply and I can apply now and classes from Tailwind so let's do apply border and border and the Border let's say what color can we do as the border and blue 900. yes I think I can make it wider as the Border too now around that corner so let's do rounded medium yes now we need some padding so it's the padding on the sides of two maybe just one yeah um all right but I think this blue border should be only if it's focused so the input Focus like this and let's apply and let's apply border of the blue 900 like this but here we will do like a gray color gray 400. yeah or maybe 200. 300 maybe yeah so if I click here it's blue yeah and by default it should be width of all yeah and let's maybe even add another apply for margin bottom of two something like this so when we pull put sandwich so when we will pull put more inputs there will be spacing between those so the input here and we can have more information actually here I think we need to put text area for description so I'll get rid of all of this and then we have text area and I will add the placeholder here that will say description all right and I want to have the same styling for the text area so the text area and here same thing text area Focus yeah so this will work maybe on the top on this page I will put an H1 that will say new product product like this and here I will add some class names that will say for example let's add text to B and blue 900 and that's the modern bottom of four maybe less two yeah and let's make it bigger so let's do text large and like this yeah thanks a lot worked or maybe text XL yeah I think this will work better maybe we can even for H1 put those classes as defaults so let's do H1 and let's apply all of those and then now we can get rid of those classes because it will be default that H1 looks like this one so for other Pages like orders and settings we will have this H1 that looks like this right the next thing is actually that we need a price so let's add one more input and let's add the placeholder of price like this and I think it would be nice to have like labels for each for each input here so I will actually maybe just put a label for each input here and the first label will be just a product name and then I'll put more labels for a description description and let's add the label for a price as well that's the price in your US dollars yes and no for this input I will put the type to be number yeah so it will be easier to put price and now for the label I will make also some Global styling here that label will have the color of the as the apply text blue 900 and I think this will work like this so now the last part here is a button for now that will just save a new product for us so let's add it let's go back to new Js and let's put a button and let's call this one just save and would be nice maybe to add the class name for this um but instead of adding a lot of class names I will just add button primary here so I can style it here as the button primary and I will just apply Styles like for example background blue blue 5 900 and text white let's see let's add padding on the sides of four let's add around the medium Corners yeah and maybe some padding on the top and the bottom of one yeah I think this this will work let's see how it looks like here on products yeah even here we can change to button primary so it will look the same way as this one right but now let's try to save our first product so um let's go back to new Js and the first thing is actually we need the state for all of those inputs so that's the const and let's do title set title equals use State empty string as default same for description and same for let's see price and that's it for now now we need to put the value here to be a title or name and then well let's see then we need also set or sorry on change and on change on this input we will get event and we will just run set title to event Target value all right maybe I can put it in different lines so it will be easier to read right and now same thing for text area and other and then this other input for the price let's do the text area first so when let's do on first value either we can put value here or we can put value here I think I will put value here so let's do value and let's do a description I put into separate lines so it will be easier to read and then on change event set description event Target value yeah let's see if this works yes it does and now the last input same thing just a different input so as the value equals and here price and on change event set Target asset price event Target value like this right so now what should happen when we click on this button um we can either add on click on this button or we can actually make this button type of submit and we can put the whole thing all the inputs inside the form and we can add on submit on this form instead that way when we hit enter on the last let's say on the last input it will be submitted as well without clicking the button so that is really helpful so let's put everything here and let's put this here and this failed to come fine let's see because on submit is empty let's say that on submit we will have a function that will do create product yes and let's just put this function here create product yes and no um to create a product we need to send a request to our API so how can we do this we can either use fetch or axios I think it would be easier with axios so I'm going to install it let's do yarn add axios yeah and now let's do axios and it has been imported for me let's do Post because we want to send the post request to create stuff and then let's post to slash API slash products and now data that we want to post and let's define it here cons data and let's just put title and description and price inside and let's just send this data like this and this is an async function so I'm going to add a weight here and I'll Sync here on this function declaration right and that should work but now we need to Define this endpoint so let's do this let's go to API here and let's create the inside API I'll call the products dot Js and same that they are doing it here we just need to export a default function with requests and response so let's do this export default function the name doesn't really matter I will do handle because this is the same name they are using and let's grab request response and let's maybe just respond with Json and all the information that we have inside request so now if I hit save um well it it got redirected but this is because I need to go back to New and for this function I get an event that I need to do is a prevent default on because the default behavior of the form is using get requests and passing all the parameters to the URL and then and we don't want to do this so let's try again let's put test here let's open network to see if we get anything yeah and we get 500 error let's see something gross wrong let's see panel the preview response and see where it has been sent API slash products let's see here and we get an error that says okay it has problems with converting response to Json so we cannot just send the whole request so here we cannot transfer this to a Json so let me try with a request method like this and now let's see if this will work yes it does preview and it says it's a post request right so let's grab it let's do const method from request now in case it is method is post then we will create a product so let's say create a product here so the problem here is actually that to create a product go ahead and to put it inside the database we need to have some kind of database layer connection and I think we are going to use this time Mongoose again so I'm going to yarn add mongoose and now I will create models here for products inside our database let's go and create new directory models and here inside models I'll create new file called the let's call this one product and here we have the definition of a product model so let's do first we need the schema so let's do a const model schema equals new schema from Mongoose and here we Define our schema so for now each product needs title or name that's the running manner how we are going to call it description and price so let's do title it will be a string then we have a description will be a string as well and we have a price that will be a number but the thing is that I want to put more information here I want to make it type of number and I want to be sure that this one is required so that's the required trigger and then well the title should be required as well so let's put type string here and required to true as well and that's it for our model for now model schema so maybe let's call it product schema instead and then now let's create a model so it's the const and then let's do product equals new and not new just model model and this function has been imported for me as well and first is the name of the model so let's say product and then and then the schema so just product schema all right now we will just export this const and let's go to our products all right and here we need to First connect to our database so maybe here on the top and let's do mongoose and let's import Among Us from Mongoose yes and let's do connect and here we need this Euro for our database so we can do either this or maybe we can actually use this database here but actually this returns a client and not Mongoose client so I don't know if this will work but we can try let's see how what is the name client promise okay let's try to use it client promise and if we can grab URL yeah we can grab your role even from this and let's see I will respond with response Json post here let's see yeah it worked so we can actually connect or maybe we can just in if we do like this Mongoose connect we are just creating another connection but here inside we can probably have a A Working Connection so let's try to use it let's do mongoose and let's put a promise here maybe with capital P yes promise equals and that's the client promise like this and now here let's uh when we have a post request let's try to create a product so let's import our product model so it has been imported for me and now let's try to hit create and then well to create we need to build all the data and the data we have actually in the payload so let's grab it from here or maybe here inside our post sorry the const and let's grab a title and description and price from request body yeah and now let's put it here title description price and this is an async function so I'm going to add a weight here and I will also add a Sync here export default async function all right and this will return our new product from the database the product document we can call it like this and let's just put it here product document yeah and now let's see if we can create it as the test one and that price one let's just save it and let's see it says it's pending and that means something went wrong yeah it failed let's see what happened so it looks like our connection didn't work so and to fix it I'm not going to use this promise that we have here instead I will add another lip called the manga Mongoose here.js and here inside I will create my own connection and I will try to reconnect if it if we have a connection if we don't I will just create a new connection so let's do export default function maybe just export function so we can have a nice name on it let's call it Mongoose connect and let's do something like this let's grab the URL or a URI and it's process.env dot URI and now we can check if we have mongoose connection connection and we can check the ready state and the ready State can be as you can see Zero disconnected when connected let's check if it's one if if it's one then it means we have a connection so if it's one let's just return mongoose and let's let's do mongoose uh connection as promise otherwise else and let's just connect so if we don't have any connected connection then let's do just Mongoose connect like this until I so we can actually put this here right here only when we need this right and now we can use our Mongoose connect function inside our API products JS so let's put it here Mongoose connect like this and we are connected I will add a weight here and because it's an async function and now let's try again I will hit save here and we get an error again let's see again test let's put one here and test even here let's see if we will get an error let's hit save yeah we get an error cannot overwrite product model once compiled let's see what's wrong here so it should be inside the models product let's see here inside maybe it should be with capital P let's try again I will refresh here let's put test here test here and one here and now let's hit save and now it worked so as you can see here we get a document with ID and all the information so now it worked I will hide my terminal and yeah I forgot it should be with capital P the names of the models right back to our um products API and let's see we can get rid of this Mongoose thing and well now let's go to the products page and then we should be able to display this one product here right and other thing is that here inside new Js when we create a product after it's created we should redirect back to this products page so to do this and let's add the redirect so let's put a state first and go back and set go back and or maybe go to products go to products and set go to products and the default will be false all right and here after we created the product let's do set go to products to true right and here before we will do render let's check if we have the go to products if it's true and if it's true let's return a redirect so let's do redirect redirect it's not a component I think it's just a function yes redirect to just slash slash products yes now if I create a test to test and the two save and then we get an error and why is that and let's try again try with to save and get an error let's see why let's try to refresh and let's try again test two test two and just do save now we get still the same error you cannot of right product model once combined and I think this is because we need to fix our model here so first before we will create a model for product we will check if it's already created so let's do models plural and let's grab it from here models and let's check if we have product like this otherwise we will create a new model right now I will refresh let's see test two test two and two and hit save and now we get a small error on next redirect so that's better let's go back to new Js and let's see and maybe instead the redirect let's just do router so import this one and let's just do we need to use router 3 instead so let's do const router equals use router from next router yes and then let's return router and let's do just push and let's push to slash products yes now I'll just refresh and let's see test 3 test 3 and just free save and it worked but it shouldn't be it should be without return here all right and refresh let's try again let's do test four test four and adjust for Save and we are back at products page right so now let's go back to products and Pages products and here we want to list all the products from our database if I refresh here all the connections we can see our products here that I created test two test three and test four so let's list them here so first we want to grab all the products and for this I'm going to use a use effect so this effect Arrow function like this and the empty square brackets here because it should run only once when we Mount our component and now here axios axios get and let's say slash products and let's do 10 because it's async function and we don't want to put a weight here because then we will have some warning um because um obvious effect let's do it then and as the response and with this response and we have a data inside so let's do just console log response dot data right so now I will go back to product xjs inside the pages API and if it get request if method is actually a get request then I'm going to respond with Json and just all the products products product yeah dot get and here we need to put a weight because it's async function but that's basically it right so I will save this and then now let's open console here to see how it works um let's go to network products preview okay it didn't work and I think it's because it shouldn't be just slash products it should be slash API slash products and we get a 500 error let's see why API products product get maybe I think it should be just fine instead of get let's try again refresh and I think it worked let's see console yes we have an array of four objects so let's go back to previous Pages products instead of console login let's put it inside state so let's do products set products equals use State default will be an empty array and now let's see here we want to instead the console log we will do set products so we'll have our products array inside the state and now let's just uh let's show the products so I think I want I can put I can put it inside that table it will be a table with the head and then let's put one TR here and the First Column will be uh product name and uh then we will have a empty column no title and inside tea body let's just Loop through all the products here so let's do products that map and for each product here I'll put parenthesis and for each output new row here table row and inside the First Column I will put the I will put the name so let's do product title and on the second we will have a buttons here so I'll put just buttons here all right and we have test test two test three test four and will be nice with some basic styling for this table so let's do class name and basic on this table and I will add some simple CSS here table basic and then I want to add on uh on the cells so trtd and let's add some let's apply some styling here let's put the Border yeah something like this and the table itself should be uh let's do apply and let's do um with a full yeah so it will take all the space and I want to have some padding of one on the cells and let's see I want to make the Border darker so let's do border and gray and 200 maybe darker 300 I think this will work and maybe the head of the table so let's do table basic T head trtd let's make it a grayish so let's do apply and let's do background and maybe let's do blue 100 yeah so we have something like this and instead of gray border maybe we can do blue border of 700. let's do right let's do 200. I think this will work right now let's go back to Pages uh products and I want to add even some Modern top of of two from the top and for the buttons instead of the buttons I want to put some links or maybe buttons to edit the product and to delete it so first button for deleting so or maybe editing so let's do link and here we need to add a ref and the ref will be to just slash products slash and then let's add the ID of this product to the underscore ID to the URL and let's put edit here and put it in different line yeah and maybe I will quickly even style here links inside this table table basic a tag and I want to make it I want to make it buttons so let's do apply and let's do background blue 900 text white let's see yeah something like this and let's do a text small text SM yeah let's add padding of one on every side let's do rounded Corners medium something like this and I want to increase on the side spotting out to make it two uh yeah this will work and I want this to be Flex right and now I will also or maybe inline Flex yeah and now I will also add the gap of one in case there's something more inside and I will add actually some icons inside so for this link edit I want to put an icon of a pen or something like this so as the pen yeah I think this will work copy j6 let's put it here and let's see yeah and it's too big so let's change it to four by four even this is to me let's do three times three now four is good yeah and now we need also another ring so let's do a link and link to deleting this and but maybe we can first pick so we can edit when I click on this it goes to slash products slash and then ID uh maybe instead of this it should be edit so slash product slash and it and then the ID so let's go back let's click edit now it goes to edit slash and then ID but we need a page for this so inside pages inside products let's add a new file here and even here we will put and not fine actually we'll put a new directory here called edit inside edit we will create this magic file called the dot inside square brackets and here let's put edit and product.js let's make it with capital P right and here let's do just export default function and add it product page something like this and it will just return a parenthesis and let's put layout here like this edit product form here and let's see if this will work yes it did so now here we need to fetch the product of this ID so let's do this first we need a router so let's do cons router equals use router from next router yes and then we need to and grab the idea of the products let's do const ID equals router and there we have params no but let's see what do we have inside our router so let's do console log router and inside the router we have as path and we have route we have path name let's see query and here inside query we have edit product to be this I think that would be much better to edit this file name to be just a dot dot dot and ID like this and this way it will be renamed to let's see I will scroll down here let's see query and we have ID right so I can grab ID from router query yeah and now I can use effect and first form is an arrow function second param is a dependencies so I'll put ID here and now let's fetch product of this this ID so um let's use axios let's use get and now slash API slash products we can do something like this and Slash the ID or maybe we can just do a regular get but with um with some query like ID equals and then the ID from the URL so maybe let's do it this way and let's do then and then we will get a response so let's put it as Arrow function and with this response let's just console log our response data yes and let's now fix that the query patterns will work because for now if you get if you do a get request to API products it will just return all the products so here all the four products and we want only one so let's go to API slash products and let's see here we have a get request let's see if we have and let's see headers if we have a query param like this so let's do if we have request query ID I will put the question mark here in case something doesn't exist if we have this IDE then let's just respond with Json and here we want to just await to do product find one and we want to find one by ID so let's do find one and we need to put underscore ID to be this so let's do put it here and we don't need this question mark here because we know that here it will exist and that's it for the else we will put this thing if we don't have an ID inside the query so now if I refresh here let's see here it failed we have find one by ID we have a Wade so let's see what went wrong let's see how this looks like right here as you can see we are passing undefined to this to this request so let's go back to products edit and here first we will check if we don't have an ID then we'll just return here and not ask for a product so now it should work let's see payload and preview and we get our product here right so now we can actually show the form show the form um probably the same form that we have for a new product so we can edit an existing product so inside new product products new we have this form here and state and everything so I think we can just move it I can just copy this like this and maybe even including no I don't need the whole function I'll just grab this return and all the states and I will create a separate component for this and I will call it products form or maybe just product form singular that is and here I will just export default product form and let's just Place everything here we don't need a layout we just want to have this form so let's put it like this and Export default should be function product form and let's see uh I think it looks fine now let's go back to New and we don't need all of this we just need to return this uh product form product form but we want to have an empty form here so that should be correct and we want to get rid of those unused Imports let's see if that page works let's go add new product and it works but here we actually need a layout so I will put parenthesis here and let's put layout and this and here product form like this right but when we are editing and when we are editing we want to have the same thing so let's do go to this page Pages products edit and the ID and here inside layout I want to put product form as well but I want to send all the information about this product and I have it inside response data so let's save it inside the state first so the const product info set product info equals use state and let's say default will be no yeah and here we will do set product info response data yes and here we will just pass this product info and we will just spread it like this product info and this way we'll have all the properties here so um let's go here inside and let's grab those properties from here it's title it's description and its price and it's started wrapping so I will put those into separate lines like this maybe more to the left yeah and I think this will work I'll put it here this thing here and output defaults maybe here okay now we have a problem because we have same property names as state names so uh I can rename those properties to for example a previous title or existing or maybe current title existing existing title and this to existing description and this to existing price and that's why this way instead of doing empty string here I will do existing title if it exists otherwise empty string same here existing description otherwise empty string here for the price existing price otherwise empty string now it works now as you can see we get this form that is filled but the problem is it says new product and this is because inside this component product form we get this H1 here that we should move outside so let's go to products add new product let's go to this page new Js let's put this H1 here but when we are on editing page for a specific product let's go to this page and let's put H1 here edit product like this and let's see if I go to products edit I don't see anything here so something is wrong let's go to product form okay we have a product info with spread like this so something didn't work if I go here and I click edit I don't see the information of this product so something's wrong Let's see we don't need the layout here we have title okay I think I know what's the problem here we shouldn't display the form if this product info is not loaded so let's do if we have product info then let's do end as the parenthesis then we'll put this right now if I go to products edit this one now I see the data if I go to this one I see the data I don't know why it's minus two but doesn't matter let's see under Test free yeah test four yeah I think it looks fine and test yeah I think it works but now we should be able to save a product but inside this product form we have axios request to always post to post a new product and we don't want to post if we have an ID here passed so here I will check if we have an ID and let's maybe console log it console log underscore ID and now let's see console here and we have underscore ID here but when we go to add new product the underscore ID is undefined so this way we can check here inside this function for create product if we have underscore ID then we should save update product update otherwise if we don't have an ID and we want to create the product and this function should be named create product because it can either update or create so let's rename it to save product yes and now here we have create so we can actually put this their code that we had and even this redirection I guess but let's see what do we want to do when we want to update we want to send a request so let's do a weight axios but we want to set a port request to slash API slash products and we want to put data but the data here will be actually the same data that we have here except we want to put an ID to it so I can copy it paste it to here and then add the ID or I can put it here at the top and I'm going to need here I don't need it here because it's defined here on the top but here instead of just returning this data without ID we will need this ID because we want to update a specific product so I will spread the data like this create a new project of from data and I will add underscore ID yes and this way when we will go now to API products here we can check if the method method is actually put and if it is we can grab stuff like this but we will also have our underscore ID so when we get underscore ID and this is a put request first we need to fetch the product right so as the const or maybe we don't even need to fetch the bread we just need to update the product so let's do product and let's do update one and parenthesis and first part is a filter and the filter is an object so our filter will be just ID we can do ID equals ID like this ID to building but the name is the same so we can do just object of underscore ID the second part is what we want to update so we want to want to update Title description and price like this and this is async function so I'll add a weight here and this is an object of title being a title being title description being description but because the name of the property is the same as the variables here I can do just title but you should know what this creates this object here all right and what the property names come from and the values so I encourage you to test and maybe hear even um I can show you that let's define A to B four or five and then we can create an object of a being a and that this way we get an object A5 or we can create an object just a and this will be the same result a being 5. right but now we updated this product then what then let's respond with Json official to just say here it's updated everything is fine right now let's go to product form and let's see after we updated the product what do we want to do maybe we will tell that it's updated and everything works and let's say that update was successful and or maybe we can redirect to our products maybe let's do redirect part so again we will just do copy this and we can put it here or we can get rid of those both and just after this itself we can put it like this right so let's go to products let's test this one let's do a test uh old or maybe test space old and let's save and as you can see we have a new name here test on so everything worked but now we should also add a delete button so let's go to our products page and let's see here we have a link to edit let's add a link to delete let's say this links go to products edit let's create a link that will go to um product products delete delete sorry delete because on this page I want to have let's put delete here I want to have like a separate page or a pop-up I think it will be very fat page do you really want to delete this product so I'll put it like this yes and now we need to make so it will not be 4 4 but before we will do this let's add an icon trash icon as the trash I'll copy jsx I will put it here it should be four by four four by four and here let's put some spacing between those so let's go to back to our Global styling and let's add margin right of one yeah now if we click on this button it will go just the products slash delete slash this and it gives four four so we need to create a new director here called delete yes why not and let's let's do a new file same way let's just do ID dot JS yes and here as always just exports default default function delete delete product page and here we will just return a layout inside this layout let's say we'll have the you really want to delete product X do your really want to delete product X and then two buttons and button that will say yes and button that will say no right and this button with no it will just run go back it will go back to the products so the function go back and this go back we need a router so it's the const router equals use router and here we'll just do a router push and slash products and let's put it here on click it will run go back yeah and but this delete um let's fix this x first and let's see yeah do you really want to delete product X I will I will put it inside H1 like this and now I will instead of doing product X I want to fetch the product name from this URL so um as always I will need first the ID so the const ID from router query and then I need use effect to the arrow function here and the second param is array of dependencies and I need ID here if we don't have if ID is undefined then we'll just do return here but if we have an ID I want to do axios get request to slash API slash products and as you remember we can pass ID like this and let's do plus ID then let's do then we get response here let's do Arrow function inside response data we will have all the information about the product but we need to put it inside the state so it's the product info and set a product info equals use state and default can be undefined and here we would set product info to this yes and access is not defined let's import it uh cos enter now it should be okay right and here before we will return um here we want to instead of product X let's do we want to do product info and that title but in case this is null uh I want to uh the end question mark here so do you really want to delete test all I will I need to add a space here let's do nbsp no breaking space and I will put the name of this product inside of a series like this or maybe like this yeah and yeah this should work and now we have two buttons um I want to create some class names here so I can reuse them so it's the button red and here maybe class name of button default yeah and let's see I'll put it in separate lines so it will be easier to read yes no all right and those two buttons I'll put inside the div with flex class name and I will add a gap of two between the buttons so let's put those buttons here and now we need to fix the styling for button red button default I can add a Tailwind class names on those but I would prefer to Define it once and use it even for orders and other parts so let's go to Global CSS and let's see let's do button red and let's make it apply a background red let's maybe try with 800 text White and better not begin yeah and now for the button default but on default I want to apply gray color so let's do background gray 200 yeah something like this and now on those both so let's do button default and button um red on those both I want to apply a padding padding on the sides the before and padding on the top on the bottom of one and the rounded Corners so it's the rounded medium yeah something like this I paint this default button can be a little darker so it's the 400 here maybe 300 400 500 yeah and let's just do a text right here yeah I think this will work all right and let's maybe make it centered the button so let's go and to delete and here we have this div let's do justify and Center here and even for this title I would like it to be centered so I will add some class names like uh text Center yeah and that should work and now when we click on as we need to add the on click so I'll put it here here I'll put on click and click we will do delete product and just like this let's put this function here delete product and we will just take this ID and we'll do axios dot delete it will be a delete request not a post not a get not a put it will be a delete request too slash API slash products and the question mark ID and I will put ID like this and we will do then or maybe we can do a weight here because it's not inside a usfx so the await and I will make this one I think uh await and after we are done we are going to the router we can go to router push products or we can just run this function go back so it will be easier we can reuse it right so uh on click listener to be a function let's see here it should be without parenthesis here yeah so we have the really want to delete and now let's go to our API products and let's add a handle if method is actually delete then we want to do the same thing that we have for query we want to sorry we want to check if we have this ID inside URL so let's grab it if we have it if we have it then we are going to delete it so let's do and wait um product delete one and we want to delete where ID is this where underscore ID because in the Mongoose in the database they are using underscore IDs for there it is so if the I want to delete one where underscore ID is this ID and then I would do response Json true all right and as you can see here for all products we have underscore like this inside our database so now let's try with hitting this yes let's see if this will work yes as you can see we don't have our old product let's try again with test2 delete yes and we don't have test two anymore all right so this works we can now edit our products let's do test 3.1 and let's save it here and we have 3.1 so the next part will be actually not here inside our product we need a one imported thing which is images we need Pro we need photos of our products so and this is what we are going to fix now so let's go to our products form product form sorry and here this product form as you remember it's used for both adding new product and then dating existing products so here we have a safe product here we have some state for description price go to Pro and description price and title and here we have our form and somewhere here in between maybe under the product name we want to add the photos so let's add a label without html4 and in this label we will put Jazz photos and all right and under let's put the div and under this we want to have we want to show all the photos and we want to have a button upload new photo so I think next to this photos I want to have a small button that will be upload more photos so let's do something like this in this div I want to display all the photos so how can I know if we have photos we should have this as the property here so let's call this property of those maybe images images product images yes so we are going to hold images and here inside this div let's check if we don't have images length length then let's do and parenthesis and here and I will just print string saying or maybe a div saying no no photos in this product yeah so we have no photos in this product and under this div I want to add margin bottom of two so we'll have some spacing and next to this photos thing I want to have maybe a button here next to these photos or we can maybe put a button here and I think it will be better to put it here and so we'll have like a squares of photos and the last Square will be a button to to add to add the new more photos so we're here let's add a div or not that if it should be a button right so let's do a button and let's add some class names here so each Square should be a width of let's say eight and a half of 8 as well and let's add some small border yeah so as you can see it's this small and we should probably make it bigger so let's do 32 32 and 32. yes so now it's this big maybe it's too big let's change it to 24. yeah now I think it looks better inside this button I want to have like upload text and I want to have an icon or maybe only a icon as the upload yeah this one and let's put it here and let's see how it looks like yeah uh okay okay let's put it text Center send enter and then work maybe if we do next and let's do items Center Center yes but now I also want to do justify Center yeah something like this but I think that this text upload can be inside a separate line so I'll put it inside the div let's see didn't work maybe because we can just change this to Lex uh call to column and now we have something like this is it better I don't know let's put it back and let's make the text smaller so let's do text SM yeah and let's add some gap between those two Gap one yeah and let's make the text and gray gray 300 maybe darker so we can see it 500 yeah something like this and we want to make it rounded so let's do a rounded medium medium so each Square will have rounded Corners maybe we can do actually Lord right and let's add some background color let's do background gray of 300 or 200. and we probably don't need a border anymore so let's get rid of this border yeah and I think it looks fine now when I click on this upload I would like to open uh window to actually pick a file so um to fix it I will actually change this button to a label like this nothing have changed because we have a lot of classes here and inside this label or this button this Square I will put an input of type file and now we have this input of type file here but now I'll make it hidden that's your class name and the class name hidden right so now it's not visible but because we have this label outside of this input of type file when I click on this label it will open this file picking thing window so now to upload photos I will go here on the top and I will Define the function function upload photo upload image sorry upload image but it's just an empty function and this function will be run when our input of type file will change so let's add on the maybe somewhere here on change on change we will do upload image maybe images so let's rename it here as well upload images yeah in case there are several files selected right and we will get an event here right so now I will first console log this event to see what do we have inside I need to select files so let's do upload and one thing I want to have an hand icon when I hover with my mouse here so here and let's do cursor pointer and that should work let's see yes it does right so here upload the images now let's see I will select this this frog and here we have our event and we have Target and inside Target we should have all the files here somewhere here files so I'll grab it let's do const files equals event Target files that's on the question mark in case it doesn't exist and then let's check if we have any files here so it's the files dot length let's change that length is bigger than zero then we know we have something to upload our other question mark here in case files is undefined or null and now we want to upload those files so how can we do this so to send all those files and we'll send them as form data so instead of sending jsons as we always do I will Define here data that will be not a Json not an object it will be well it will be an object but it will be an object of new form data form data like this so it will be easier to parse it on the backend side so let's do a new form data and let's now put inside the all the all the files so let's do four um as the const file of files so for each file let's put it inside or maybe we can do files for each for each for each and for each file we'll just do data append file to be file yes and then we want to after we added all the files we want to uh send them access request and well we want to just upload this those images so I think we can create a separate API route for this called upload so the new file here inside API it will be just upload.js all right but let's go back to product form for now axios it will be let's say it will be a post request to a slash API slash upload and this endpoint is going to just give us links links to those images after we have uploaded them we are not going to update our update our product here we are just uploading photos all right and after we upload the photos we want to show them here and after we hit save those photos will be saved to this product so let's do this uh we want to do access post with our data here but this is async function so I'll add a weight here and I will mark this one as async and we actually want to grab data from the response so let's do const response equals this and let's just console log and maybe not the whole we don't need the whole response but I will grab only data from here or maybe let's do response and as the response data here all right and now and let's see now we need to fix this upload endpoint so let's go here now here the upload is a little bit complicated but not that much so stay with me so let's do as always uh just a Handler for this API endpoint so let's do export default we can put async function and let's do handle and here just request and response like this and what's the next part the next part is actually we want to tell next.js to don't parse our request instead we want to power set ourselves so let's do export const export cons I think it was config equals object and we want to pass to API a config on the API we want to do both the parser to a false like this yes and now we should have a row of data inside our request so it will not try to parse our request to Json all right now to get files from our request we are going to use Library called multi-party sounds really awesome it's for parsing multi-part form data parser which supports the streaming so as you remember we have this form data that we used here for and Gathering our files from data and here for data so now this is what we are going to use for upload so let's do open here and let's do yarn add multi party so it's really awesome now let's go back here to our handle and then let's use multi multi-party I think we need to we need to put it here so let's do import multi party from multi-party like this now it's important and now on multi-party we have a function called form we just need to hold like this and it will be let's return it to F1 right so this is kind of initiation and now on this form we can do parse parse like this and we want to parse our request and here we'll have an uh and I think a callback I'm asking because I don't need to put I think for now but we will do async stuff here inside so that's why I put it but I can put it later and in this callback we'll have an errors and the fields and the files in this callback so uh so let's maybe just put a console log here and in case we have any files let's see how many files we have here so let's do files dot length yeah that's it and here I will just do response Json okay yes and here I forgot to put new right and here I will refresh and let's see I will put this upload this part and let's see for each is not a function all right so it looks like files is not actually an array so let's see let's go to products form and we have files here we have length on on this but let's change that we'll do for a loop so let's do four file of files and the const file of files and let's do just uh this data append file to be this so I can put it like this and I can remove this right I will refresh and I will try to upload again let's see maybe that's wrong open it says okay let's see if we have anything here we get undefined let's see why upload files length looks like is undefined let's maybe put length colon and let's add a comma here and let's try again I will try again I will upload this one let me get OK length is undefined all right and just in case we will check if we have any errors if we have an error then we will throw this error yeah I will try to upload once again let's see here and we don't have anything inside the files let's maybe see if we have anything inside our fields yeah let's see upload open length is undefined and this is an empty empty object let's see how we are sending this upload and we have a payload the file is binary so everything looks fine here let's see if we have any error here okay it says API result without sending a response let's see why we are sending a response let's do even a return here and I will try to upload something once again API result without sending a response or API upload but here when we open upload we have preview of ok so this is kind of wrong but I don't mind this warning I think that in the way to actually to actually hide this message will be to return a promise here so let's see I would return new promise and here I will have result and reject and we will put all this here inside and if we have an error we will do reject with this error otherwise we will do resolve with um fields and files as an object right and like this now um instead of returning this promise I will just grab it grab the fields and the files from new promise and we'll remove it from here so I can put it here and now we shouldn't have this warning so let's see I will refresh upload this and something didn't worked let's see files from new promise okay I forgot about weight here um and now let's try again upload this open and we are back here without this warning all right so we're looks like our files is empty maybe we need to restart it so I'll try again and now if I will upload anything let's see upload I'll upload this do we have anything no length is still undefined I think this is a wrong because inside our product form we need to tell axios to not try to send it as Json let's see here we have this upload we have payload it's a form data but we need to probably add some extra headers here so instead of doing the request like this I will add the extra headers here so let's do extra param here and I will put headers and it will be an object as well here I will put content content uh content Dash type and I will put content type of multi-part from data I think this is the thing that we need for our multi-part it work so let's go back here and I think this is the only header we need so let's try to upload again hello and it didn't work I will try maybe to send it with fetch instead so let's do fetch and it will go to slash API slash upload and he will have a lot of more info how the weight here as well and the method will be post and the body will be data and you will get the response and here we will not have and the data will have only response but let's try to upload as a patch but still undefined anyway goes to slash API slash upload let's see upload price length is undefined let's maybe try with only files yes I will do upload here of this one okay and here we have some information so we have path to this file and it's inside the this files so there is actually information about this file but I don't know why it was undefined maybe because we checked for the object and object length is undefined we would need to check files dot file that [Music] um length and then it will work let's see let's see I will upload this one then we will have length of 1. all right so um inside our file or maybe it should be named files and by Design file we have an array of files so uh let's grab it let's maybe put let's maybe do a for it here so we don't need to console log fields we want to do only upload so um we already uploaded here this photo and I can probably open it in my browser but the problem is we don't want to have it like in the temporary temporary storage like VAR or TMP and instead we want to upload it to a persistent storage like S3 so I will go to my console on AWS and I'll create a bucket to upload to S3 so I will just quickly login and I will go to S3 packets and I will create a new bucket call the maybe and next e-commerce e-commerce yes and create new bucket and this looks fine I need to do ACLS enabled and let's see I will not block all public access Peter because I want those files to be publicly available and yes and that's it I'll create this packet okay this one already exists I will do next JS e-commerce okay it needs to be unique so I will name it and David next e-commerce now I'll create the bucket right now I need to create a user for this bucket so I can upload from the code so I will go to here and the security credentials and now I will create a new user for my for my bucket only for this one bucket I will do add users and let's call this user same let's do David next e-commerce and this and let's do next and I want to just attach a policy that I'm going to create now I want to create a policy specifically for this one bucket so for services I will find just S3 actions let's do all actions and let's close this one resources I will select any for now but only for now on almost everything except the bucket because on this bucket I want to specify that it should be only David next e-commerce bucket that this uh not this a policy should apply on that's the next next and the name of the policy will be policy let's call it S3 now with the next e-commerce yeah let's create this policy and now it's created so now we can go here and we can refresh policies and let's search for David next and we have that with or we have policy S3 David next it's this one I will just double check is it this one next create user and now we have our user so it's this one David next e-commerce I will open it and now we have a security credentials here and we have access keys and I want to generate access keys here we have many different options but many of those will give give us the same result and I will select here I guess third-party service and maybe not application running outside and LS yes let's do next and just create access key and we have access key and secret access key now we need to put those inside our EnV file so here let's add S3 access key access key equals string and let's copy this one like this and now S3 and let's do Secret access key and and I will copy this one and let's put inside parenthesis like this and now we have everything let's click down here and continue and now let's try to to upload to our S3 bucket I will go back to our Pages API upload and as you remember here inside this files file we have um information about our files that we want to put now inside the S3 so I will open our new packet here let's do S3 I'll open this and let's go to our bucket it was called something David next e-commerce as you can see it's empty but now we are going to upload some stuff inside so to upload to S3 client we are going to need to install more things and it will be S3 client that we that we need here so let's do yarn add and let's do here at sign AWS SDK slash client S3 because we need only client S3 let's hit enter and I can actually grab it like this to to import to import this here so as the import and we are going to import from this and the thing that we are going to need is actually S3 client and now we can Define using this function so here let's define our client let's do a const client equals new as free client and here just options inside and the options that we need is region and I think I picked the region of I think the region was default U.S us is one and maybe we can even check it here I don't know if it's somewhere here or here on the buckets and let's do David and let's say next e-commerce yes Us East one so that's correct we have region what else do we need we need the credentials so the credentials will be an object and here inside credentials we need access key ID and that will be a string and we need also secret access key and both of those where we have them inside dot Envy so we can just do a process.env DOT S3 access key and here we can do process that in V secret access key yeah so we have our client ready and now we can use our client to do stuff and the only thing we want to do with our client is to send and we want to send actually a command this is the way they they call it your sending command to your with your client so here we will just do new and we will do new put up object and the way I have so much here object command yes let's import it from client three and this has been imported here for me put object command and here we need to put an object of information and here first we need to put the name of the bucket and the name of the bucket will be done with the next e-commerce but I think we can put it somewhere else maybe here on the top maybe here here on the top the const and that's the bucket name to be a string of this and this way we can do just a bucket name like this all right so we have bucket now we need a name of our file so to put name we use a key that is fine all right so how we want our name to look like we have our original name hello that jpeg but we don't want to use original name why because if we upload two files with the same file name then it will then we'll have a problem we want to have unique file names so from the original file name I'm going to pick only the extension and this part I'm going to Generate random random string all right so to do this I will first here create a loop for all files so here we have the fines let's do four four five little const file of files dot file and now let's just put we can put this client actually here above we can Define it only once when it comes to sending we need to send this for every file right and now I will put a weight here because it's a sync function and now we want to define the key so inside this file we have the object of file information and we want to put get original file name first so from the original file name we want to get the extension this jpeg so how we can do this we need to grab original file name and we want to split it by a DOT and we want to take the second part so let's do something like this that's the const extension equals file dot original let's see original file name file name dot split but using Dot and let's take the last part I think we can do this with pop let's see what pop is doing a pop method removes the last element from an array and returns that element that's awesome right so maybe we can now just do console log of extension and file to see if everything works and we'll just comment this put command for now we want to see if if it works so I will just quickly refresh here as you upload hello jpeg let's open here let's see we have extension jpeg so this worked and we have file with all this information so that is really nice all right so let's uncomment this part and let's continue with our key which will be our new file name let's define our new file name and we want something random string and then we want to add the dot and then we want to add the extension but here on the beginning we want to have a random random numbers or something so I will actually use just a date dot now it will give us a timestamp and maybe I will also add the egg Dash and I will oh I think date now will be good enough I don't think it's really that possible that two people will upload files in the same millisecond so well this will this will work or you can also add something from here this is Scenic as well so we could maybe do md5 of the string but date now will be good enough with just timestamp in case you need something even more unique you can maybe add a md5 of this so it will be even more unique Define naming will be even more unique all right but now we can use new file name here as a key to Define so we have a bucket we have a key but we need to tell what uh what's the content of the of the file so let's do body body of the file and to grab the body we need to read this file and to read this file we need we need to use we need to import FS from FS file system Library so we'll do FS read file sync we don't want to read it asynchronously we just want to do it synchronously and let's read this file and we need path to this file and path is here so we can just do find that path yes okay so we have a packet key body we want to also add ACL to be public read so the file will be publicly available and we can just return a link directly to this bucket file and the last thing that we need here is actually content type content type because S3 likes to have the information more information about the fine what type of file it is if it's a JPEG or what it is the problem here is I cannot guess if it's always a JPEG or if it's always an image so I'm going to add another Library and this library is called the mime types mime types and let's see yarn add mime types and what it does it just it just reads the file and checks the mime types so let's do import mime let's call just mime from mime types mime mime types yeah like we will call it mime here and here content type and just do mime and let's do lookup and just file that path all right and this should work now after we uploaded the file let's maybe grab a link to this file so the const link equals and now to get link here it will be just https slash the name of the bucket so let's put here bucket name and Dot S3 dot Amazon aws.com slash Amazon AWS slash and here then you find them so let's do just new my name yeah and now we want to grab all the links in case we have several files so let's do the const links equals array and here let's just do links push New link and this and here instead of okay let's just do links yeah and now let's see if this will work um I'll clear this let's upload the one photo of this part open and it says it's pending okay I think it worked now let's see preview we have links we have this one link let's let me select it let's open new tab let's see and we have parrot with our link here all right so this worked now uh when we are done with the upload part and we can display every uploaded file right so let's go back to product form and we are doing this response here with the response we are consoling the response actually we don't need this fetch here we can change it back to axios post and we don't need this and we can just put the data like this data and this should still work and now inside response we have this data that we can that we can check but we need to add a weight here I will just try again to see if everything works let's upload this frog and yeah we got something here we have one link yeah everything works so inside data we have links so we can just grab it and add it to our state so let's create a state for our photos let's put maybe here is the const for those I'm sorry it should be called images images set images use State and the default will be nmpt array but as you can see here we are also passing this as a property in case we are editing an existing product so let's rename this property to existing images and let's put it here existing images or empty array right and now we can actually use it here after uploading and let's see here here we'll do set images we will grab the old images images and we'll do Arrow function like this and here we will just return old images as an array like this and we will also spread new links here all right but Links come from response data links like this this way it will create a new array with all the images inside and new links here so all the links and new links right so now let's scroll down here and let's see here we have those squares and here we have this upload button this big let's maybe go here and before this upload button let's check if we have images link I will do question mark here and I will check if it's bigger than zero or maybe I don't even need to check if it's bigger than zero because if it's bigger than zero then this will be true and and then I can do images map to map through those images and every image it will be actually just a link so I'll put link this and let's put the div with the link right and now it says it's zero because this thing returns zero I can change it to Boolean by just doing bang bang here converting this to Boolean false because length is zero and now let's see if I select one let's do hello jpeg I picked this image and now it's uploading it's the it takes few seconds and but now as you can see I get this link and I get here and warning because I forgot about key here so I'll put key to be actually this link so we will not have this warning anymore but now instead of showing this on the link I would like to show this us as as an image so instead of Link let's just do EMG and the source will be just link like this and now we'll have like a big image here but to fix it I will just make this div class name to let's make it half of 24 like this and now the image inside should have styling of Max wave 100 but I will put it here inside globals so globals and let's put that for all images Max have should be 100 yeah so now it's here let's go back and let's see I will also add that this div should be in line block yes and this label here should be inline block as well but now there are not next to each other and I'm not really sure why maybe it will be easier to just change those to to regular elements but I will add here instead Flex and I will also add Flex wrap in case there are too many elements and I will add a gap of two so there will be some spacing between those and then for each image that we are displaying I will do rounded corners on the images so it's the class name let's do around that I think it should be medium or maybe large let's do large the same that we did for the button here this upload button and well this this looks fine so now when I have this one image here when I hit save here I want to add this link of this photo to my products to my product where is it it's here to my test free for example product but I don't have it inside my schema here so let's add it let's add that that images will be of type string uh wave capital S like this it will not be required it will be just type string that's it all right and now and now images will be actually a Json here inside so uh yeah or maybe I can even change this to type array of string like this but now let's go to our API slash products and here where we are putting this or where we are creating um where we are creating a product we need to grab images here and we need to grab images even here right and we just need to add those right so let's do images here and the images here and let's see if this will work so now if I hit save here and I don't know if it worked I think it was this one uh I will check the database maybe first so let's refresh this one and let's see products we have two products we don't have any images here I think this is because we are not sending this from product form here we have this uh save product but we don't have any images so let's do images like this and it's the same as our state so we so we should work like this I can close probably some tabs here without um let's try to upload some photos for example this frog I'll click open and even when I'm uploading it takes um it takes some time um maybe we can add information about this um that it's uploading so we will know here we have this upload images function but before we'll do this upload let's check if it works I will click save I'll go back here and I don't know if it worked I would do refresh and products and let's see no and we don't have it and let's see here inside network if we actually send it and we have here products put let's see payload we have images here and we have one one image one link here let's see if everything here inside product is okay and maybe it shouldn't be like this but instead it should be an array of a type string let's try this way I think it should be this way let's do upload let's take this one and then now it should be uploaded yes it's uploaded let's save it let's go back I don't see it but let's check our database here still nothing here inside images let's see our API products here we have our put here we have our images and we are putting this as images here but just in case I will first do console log and print images here to be sure that we are getting this so here let's try to I will refresh here I will upload maybe this part and let's hit save and we have images and one link maybe it's because I need to restore this and I would yarn Dev again I have only I have also here let's see let's edit here let's upload let's pick this file and now I will click save and then let's check our database I will do refresh somewhere here here refresh and let's see yes now we have images yeah so it worked we just needed to restart so I can remove this console log and I can remove console log from upload that I forgot about let's remove this one right now let's see if I open this one I see the current images and I see also upload button and I can upload more photos um let's maybe go to this one and maybe you can get rid of this text so let's go back to uh product form and let's see no no photos we can remove this part we don't need this and the next thing is actually that we wanted to have an indicator when we are about uploading something so here we have upload images and when something is uploading um what do we want to do let's say that we will have a a box here on the beginning or maybe on the end here but Windows between the last image and the upload a box with a spinner all right so let's see if we are uploading something Let's do let's update state let's go here and let's define state is uploading and set is uploading default will be false and here inside our upload function on the beginning we will do set is uploading to true and on the end here set is uploading to false right and now here in between let's go here we are looping through the existing images here in between we'll check if we have is uploading to be true then array div and we want to have something like this so I will just do let's see I will do just have of 24 last name let's do class name and like this and text inside will be uploading uploading or maybe we should have a pre preload or something like this so a spinner so let's do react Spinners I think it's this one let's check demo page yeah I think I will use this and well you can use what type of spinner you want to to use and I think I will go with this path yeah I'll go with this path loader maybe something more basic bounce loader all right so let's add react spinners so let's do yarn add react Spinners Spinners and this and there are um let's see react Spinners yes and there are I guess some type of uh I will use bounce loader but there are some things that you can pass like a size color speed so I will actually create a separate component for this and create a component called spinner dot JS and here let's there's the export default function spinner and it will just re return parenthesis and I think it was mine was bounce loader you can pick different one and I want to pass information like color so let's do color and to pick the color I will just pick the color from my page here I want to use the same color so it should be black something went wrong here I should be it should be this one so let's put it like this and let's put speed multiplier too so maybe it will be faster or something and let's now put it back here so if we have an upload let's see now here is the button to upload here is uploading here I will just show our spinner yes and let's see how it looks like I will upload I will upload maybe my parrot here yeah it's something like this I want to add some padding and gray box to this so let's do the same background Gray thing here and I will also want to add panning of one I want to make it legs and I want to do items Center so it will be centered and let's try again let's pick this frog yeah I forgot about rounded corners and maybe I don't need this gray background so I will put it like this I will not save it and we'll just go back here and I will try to put again but before I want this space to be a little smaller so I would just do Gap one instead yeah let's see now I will pick maybe this product again let's see yeah and it's uploading so I guess I guess it looks fine and we get a part here so everything looks fine so we have an indication that we are uploading so this works all right now it would be nice to be able to sort those images with drag and drop so for example let me try to upload another image for example this rug and I would like this rock to be the first picture here image and it would be nice to just drag and drop it to the first place so to do this we will install unload their dependency I will go to my terminal and I will yarn the react Source table JS all right and now let's see let's see here we have our images and we want to be able to sort them so first let's import our react sortable and we'll go here and I will do import react sortable from react searchable.js and now let's put it here above our images so here we have the Deep for images for each specific image here we have a main day before images and the spinner and the battle for upload so somewhere here let's use our react sortable yes and the closing tag should go underneath and now let's see can't resolve searchable.js let's see here okay it's because we need both re-exertable and searchable.js so and this one as well yeah now the problem is that we need to pass the list of elements so let's put list and our list of elements will be just images yeah now we need a set list so it's the for now set list will be a function that will create it will be called update images images order something like this and of course we need to create it so maybe here let's do a function update images order and we will just do a console log arguments to see what we get inside right and now as you can see the CSS looks weird because on our react sortable maybe I will put this into separate nine and I will add some indentation here and we need some styling here so for our react searchable I will add some class names here as well and let's start with Lex and flex wrap and let's see now it's better now we will just add our Gap one now it looks better and now as you can see we can kinda and we can kinda sort them and we just need to handle this function that we are just console logging stuff so let's see we get three arguments in this function inside arguments and the first is elements and then the second is just a div that is above and the third is just dragging some information about about what's happening so basically we just need the first argument so let's put it here images and let's just print images right and I will refresh let's see yeah now we just we are just getting images so I guess we just need to take this images as a param and we need to set it back to our images here to set images first let's see how the images look like so I will go to let's see here we have edit product page and edit product page and let's see here we have product form and here we have props images and it's just two links and that's it so we can just go back here and we can just set images with those new images so let's do set images and new this new images that are sorted now right and I will just refresh just in case and now let's see let's work yes I can put it as a second I will add this frog back here yes so now we have three images and let's say I will make this Frog as the first image I will save it and then let's go back to our product our frog is first let's now put for our part first and the Frog should be the last one let's save it and let's go back and looks like everything just works and one error we have here each child uh analyst should have a key and I think it's about it's inside the products so let's go to our products not here it should be inside here inside our component we are listing our products and here we need a key so let's say it will be just product underscore ID so now if we go to products we don't get any error and it's underscore ID because from database it's always underscore it is here all right now another thing that we need to add here in our dashboard panel is actually categories because each product needs to have a category so I will create a separate navigation item here so let's go to components navigation and let's see here we have many different links and I think I will just copy the products part cop and copy the products link I'll just rename it to categories categories and I will change the icon so I'll open back hero icons and let's see let's search for maybe a list and I think we can just take this one and then we just paste it here and let's see it should work yeah we have products and categories but let's see categories should have a slash categories and the link and the it should be um it should have actively in class only if the path name includes categories categories yeah and now let's see if we go to categories of course we get an all four error because because we didn't create the page yet but let's do this now let's go to Pages new Define categorys.js and the same way we have with products let's see we just need here layout and that's basically it so let's go to categories and let's create a function here export default function category let's add page here I think we are doing this page in all other now we are just doing products right let's just do it in categories categories here let's do return and here inside as always just layout and it has been imported for me so that's nice and here maybe on the top let's just do categories categories like this and then now we have our categories page and now the first form and the first thing we need is a phone to create a new category so I guess we can just have an input so let's say input it will be a text and then let's say that will have a placeholder but inside placeholder we will have just category category name yeah something like this will be maybe nicer to have also a label like here so let me quickly check here product form and we just have a label and that's it so let's do this categories and let's add a label here but under this neat one and we don't need this html4 let's do just label and category name yes let's go to categories uh maybe just new category name yeah and we need a save button maybe next to our input here on the right side so I'll just do a div with class name Flex and let's put this input here and a button and that will just to save yeah so we have our button but on our button we need to add some class names let's add our button primary class name that we created before so we have a big button here and let's add a small gap of one here and let's fix the padding on our button padding on the top and the bottom to be just one right looks like this didn't change anything let's see our button here okay now our button looks really weird but I guess it's because our input has a margin bottom here so let's remove this on our input let's do a class name and let's do modern bottom of zero okay now our input is the same have as the button so that's fine let's put our form in actually a form tag so it will be easier to add on submit here and then the button will be type of submit here just in case and then we can of course just do like this so I mean it doesn't really matter and but we need to add here on submit and just we will have a function called save category and let's add it here function save category just an empty function for now now if we want to save a new category we just need a name from here so let's add the first state for our input because as you can see inside our input we don't have an estate so let's do this so as the const name and set name equals use State and default will be empty string now for our input we will just need to add value name and well I can put those into separate nine so it will be easier to read or underwrite otherwise we need also set sorry on change on change we will do event with event we'll do set name of event Target value so now we have state it's updating and it's inside our name and then when we click save or when we hit enter this save category will run and let's try to save our first category name so the same way we did it with product form as you can see we are just doing axios and put our post and we will use pose because it's for creating and let's go back to categories and just do axios and that's the post to slash API slash categories and then we need to put data let's just put our name here and that's basically it so now we can add a weight here and async here because then it will be an async function and then let's think what do we want to do after it's created well after it's created maybe for now let's just remove the the category name so the input will be empty again so let's do just set name to empty string and that's it and later we will also print all the categories here and we will also refresh this list when we create a new category but for now let's just create a category so of course we need to First add this endpoint so let's go to Pages API and here let's do a new file cutter is the address and here inside just do export default function and it will be handle as for all the API handlers and as always we just get here request and response right and let's quickly check for the products as you can see we can just grab the method from the request and then we just connect to the database right so let's do the same thing here inside categories let's grab method from request method so we can do this like this or we can just put this method inside this curly brackets all right and then if the method is actually a post then what do you want to do we want to create a new category so let's grab the name that we are sending so as the cones name equals request body so we are grabbing name from request body and then what then we want to create a category inside our database so inside our models we need to create a new model for categories so what is this and let's do new fine and let's call this one just cut Curry dot JS and first we need to create schema so the const category schema equals a new schema and it has been imported for me so that's nice and now let's put an object with schema so the only thing that we need for now is just a name and the name will be just a string and that's that's it we can actually just make it type string and we can add that it's required just to be sure it's not empty but that's basically it now we can Define model and same way we did with our product let's just do const and the category equals and first we need to check it if it's already defined inside models models let's check if we have cut the go right here got the Gory otherwise we will just call the model function with first param is the name of the model so just category and the second param is just the schema so category schema and that's it we can now just export it like this and now we can use it inside our categories API endpoint so now let's see let's import it let's I would cut a category and has been imported for me and now we want to just do create and we want to create with our name so we want to put a new put a new category with just a name we just have one a property there and we need to add weight here and I will also add a Sync here because we need because when we use a weight we need to add async on the parent function and then this will actually just return a new category and new category document from our database so I'll do like this and I will just respond with this category document from the database and now let's see if it works so I'll put here test C for test category I will open network to see how it works I will hit save and this didn't work let's see why I know why because inside our categories page on submit we are running this function but we forgot to grab event and do prevent default and now I'm going to just let's try again test C2 save and I think it worked as you can see inside the response we get our category document from database so let's see I will refresh here our database let's go to categories and as you can see we have two categories here so maybe I can just delete one of those or maybe not let's maybe just display them both here underneath so under the form let's maybe just create a table with existing categories so first let's add the T head and the first row will be just a row with category name as a column name here and we had some basic standings for tables so let's go to globos and let's see it we have this called basic so I will use it now so back to categories I'll add here class name and basic yeah and maybe even more than top off to from the top maybe four right and now I would like to fetch categories from the database and put them into state so I want to like the axios get request and just grab all the categories so let's add this here inside categories I want to check maybe somewhere here if the method is a get request then I want to then I want to grab all the categories and from the other ways but before we do this I forgot about one thing here and it's about mongoose connection so I will add Mongoose connect Mongoose connect and I'm gonna wait here and it worked even without this Mongoose connect but that's because only we were doing other requests at the same time so if you are using a database in any function you need to always add Mongoose connect to connect to the database in case you are not connected alright but now back to our get we want to just grab all the categories so let's do response Json and here we just want to grab all the categories so let's do a category find without any problems but here we just need to add a weight and that's basically it and this should work now let's go back to our Pages categories and when this component mounts we want to fetch all the categories so for this we are going to use use effect so the use effect first param is an arrow function or just a function and the second pronoun is dependencies we want this to run when this component mounts so that's why our dependencies will be just an empty array but here we just we will do axios get slash API slash categories and that's basically it then we will get result and with this result let's add an arrow function and inside the result we have this data and inside this data we should give we should get the Json with all the categories so now let's put them inside the onward State maybe here cut go race and set categories you state and let's say default will be empty array and now here we can just do set categories and let's put them inside right now we should be able to list them here so let's put the body element here and here let's map through our categories so let's do if categories length is bigger than zero and then let's do categories map and here we want to do jazz category category arrow and I will put parenthesis here and here inside that we just put the div but Dr sorry it should be TR like this if I make this window bigger you can see how it looks like so if we have categories with length bigger than zero then we are doing the goris.map and with category we are just doing parenthesis inside parenthesis we are just doing TR so table row and we have one column with only category name so let's do this category dot name and let's see looks like we are getting our categories here so um another thing we need to do is to able to actually edit and delete them but before we do this and there is another thing that we need to our to add to our categories and it's a parent category so let's say we are and we want to add a category called the headsets had set head set or maybe just iPhone maybe let's start with phones mobiles as the mobiles let's save it yeah and the first thing we want to refresh our table when we create new categories because now I need to refresh manually to see mobiles so let's fix this first here where we create our where we create our colors we are just setting the name to empty to clear this input but we want also to run this so the easiest thing will be just to remove this from here and let's create a new function called the Edge categories and inside I will just paste it and this should run here fetch categories and it should run also here underneath so it's the fetch categories right and now I created mobiles but let's say I want to also add the iPhones and I want iPhones to be actually the child category of members so the iPhone should go below mobiles so the thing that we actually need is to have a select here drop down to select a parent category and we need to add a select box somewhere here so maybe between this input and this button so let's do this here here we have our input here we have a button that's between let's put a select box and I will remove this name and ID and the first default option or maybe we shouldn't put options like this or maybe let's put options here the first option will be no parent category category and let's say the value will be zero so now we have no parent category and The Styling doesn't work here but we can go to our Global styling and let's see here we have input texture let's add select so now it looks a little better let's also added here so select Focus now as you can see this select got this margin button to as well so I will go back to Pages categories and on our select I will add last names as well and it will be modern bottom uh margin bottom zero so it will have the same have here right but now we need to add more options here and here our options will be actually all the categories that we have here inside our list so let's do if we have a categories or maybe we can just copy paste what we have here so let's put it here but inside instead of TR we will just put an option and the option value will be category dot underscore ID and he will put category dot name all right and has been interrupting my code but let's see as you can see we have everything here inside and if I open this select here we are getting those IDs and the first as value of 0. maybe we can just remove the make it empty so the value will be empty but now we need to have this as a value as well on our select so let's put a state here for our we have four name now we need to have a state for our parent parent category and set parent category use State and the default will be just an empty string and when we change we need to add here value will be parent category and I'll put it into different line and here I'll also add on change we grab the event and with your set parent category with event Target value right now let's see if this works if I can change it yes but now when I hit save with a category name here and a selected parent category here I need to have I need to send this parent category as well so let's see here we have saved category let's add parent category here as well to our endpoint and now we need to handle it inside our API categories so let's see here when we do a post request we are grabbing name let's also grab parent category yes and let's just put it here parent category and of course we need to add that inside our category model and so we can just put parent category here or maybe because we know it's a category collection maybe we can just call it parent so it's the parent will be type of uh well the type here will be special because it will be in another ID so it's the mongoose types and here we will do object ID and let's say it's not required yeah and that should be it now let's go back to API categories and because we have it as a name parent we need to do here parent cool on parent category put this into separate lines like this so it will be easier to read and now I will try to add iPhones here iPhones as a child category of mobiles and if I click save we get iPhones but let's see how it looks inside our database I will refresh here to see our categories and here we have iPhones but without any power and category let's see inside Network here here we posted a new category but inside payload we have parent category with this ID so let's see parent category we get the ID we set it as parent maybe because we needed to refresh our restart our server so let's restart here and I will put Maybe uh iPhones too as a parent uh oops here I will put iPhones too and it will be the parent category will be mobiles let's hit save and we have iPhones too now I'll refresh and let's see here we have iPhones 2 and we have permanent category all right so now let's print our parent category here inside our table so let's go to Pages categories and here we have our table here but if we just add a parent here or maybe parent category and we print category category dot parent inside curly brackets it will just show the ID and the problem is we don't want to show just in LED instead we want to grab and a category of this ID and we want to grab the name and display the name so to do this first I will go to category our model and and here I would like to add a reference so reference here will be actually what this ID is about and this ID is just an another category so I'll add this and now let's go back to API categories and here as you can see we are fetching all the categories but instead of just doing find I will also add populate and I will add here parent right and now let's see if I refresh and here we are grabbing let's see all the categories I'll make this a little bigger categories we are fetching all the categories we have a parent here let's see parent as an ID maybe we need to restart the server once again to refresh the models now if I refresh and as you can see we have an error that the objects are not valid react and a child and this is because now inside categories inside parent we don't have an ID that we can print instead we get an object so let's go back to our categories and here where we printed the Jazz parent we cannot print it anymore because now we need to this is an object so let's just print a name instead so now I will just to be sure I will refresh looks like this can be undefined because for categories that don't have a parent this will be undefined so I'll add a question mark here just to know if we have a parent and maybe another question mark here so let's see and now we can see iPhones too has a parent category of mobiles so that works really nice and now actually we can add those buttons to edit and delete categories so we can edit this to just iPhones and maybe delete this one and delete those two all right so let's create here and then the column and here in column we will create a button with class name and button primary that we created before and the first one will be here edit and the second will be delete so there delete and here I put the div here above with a class name of Plex and I can add Gap one between those maybe it will be easier to just add margin left one sorry margin right one on this button yes I will also have some spacing here all right but now when I click for example on this button I would like to edit this category and we can put it into another page the same way we did with products but I think because this form will be only decimal maybe we can put the data here above so let's do this when I click on this button I want to put the name here and the parent category here and then that's it and maybe I will change new category name to something else so here on this edit button let's see the let's say that when we click on it on click we will run a function called the I will put Arrow function here and we'll run edit category category and I will put the ID of the category from our category that we are looping here so as the category that underscore ID and that's it now we just need to add this function or maybe you know what let's send the whole category so we'll remove this and then I'll put this into separate line same with this and maybe even this let's put it like this so it will be easier to read but basically when we click on this edit button we will run function edit category with the whole category object so we will have all the data so let's put this function here as the function edit category we don't get the event here we get a category category object with all the data inside and what do you want to do first let's maybe change this change this title here so we have a new category name but when we click on edit we want to edit a category so first maybe we can put the stay into the state that now we are editing this category so let's maybe put it here I will put a state called the we can call it a category we are editing or something like this but I want a simpler name so I will just do edited category category category and set edited edited category something like this and we use State default let's say will be no right and now when we click on this edit here I will set edited category to our category that we get as a parent and this way we can check if this is not empty and we can change this title here so here let's put the that if we have something inside so let's do edited category if we have something here that is kind of true let's let's put a title of edit category otherwise we will put back this new category name or maybe let's rename this one as well to create new category that's it and this now looks messy but I will put those two separate nice maybe something like this would be easier to read now let's see if I click this edit we have this edit category but maybe let's add some more information here let's do edit category and let's also add the category name so let's do edit the category dot name so now we have edit category test C now we should propagate the name here and the parent here so let's do this here we will do set name to our category name and we will do set parent category to just our category dot parent category or maybe not it just called parent inside our database so I'll do this now if I click test C it doesn't have an important category so that's correct let's see if I click iPhone store well this change to iPhones too but this is still no parent category and that's kind of wrong let's see here we have set parent category so this should work yeah I know what's the problem we have a parent here but parent can be actually an object instead we should check if we have an underscore ID here instead and and this should work now so I will refresh if I edit test C we don't have any parent category but if I add that iPhones too it changes to iPhone 2 and here we it changes to mobiles so now it works but now if I click save if I click save we will run this save category and this save category function it always creates it always creates a new category so it always runs this post request and our post request always creates here as you can see creates a new category instead I would like to see if we have something here inside then I should know we should update the category and not create a new one so first I will maybe put this into to make it prettier and now here I can check if we have edited category in the state then we then I know we are inside edit mode if we are edit mode we don't want to run this and we want to run this only if it's not edit mode so let's put it inside and else here but if we are inside edit mode Let's do a weight axios and let's do put requests here to slash API slash categories yeah and we want to send the same data so I can just put a object like this but to make things a little simpler and because the data here and here is the same I can grab it here and I can Define it here above as data and I will put it as an object here this way I can just reuse this data here and I can put this data here as well because it doesn't matter if we are updating or creating a new one we are just grabbing information from this input and this select right now we don't have this put Handler inside our categories API we we can only handle post so now let's maybe add a method equals put so we can also update the category so basically we are going to do the same thing that we are doing for creating but we want to update so instead of crate let's put update here update 1 because we want to update only one category but we want to know what type of category which one we want to update and when we send a new name and the new parent we don't know this we know this we need to have the ID of the category that we want to update so back to categories here as you can no not here to back to categories here here we have the data but we are sending only name and parent category both to put and the post but for put we need also an an ID that we have inside edited category so to put ID here I will do something like this I will change this to dot data and this way this will be just a copy of data that's it but we can also add and comma here and we can add the underscore ID to be edited category underscore ID yeah this will work um but there's also I can show you how it looks like it looks like this it would be just a copy of data plus we will add a property of underscore ID to be edited category underscore ID so we will put also the ID of the category that we clicked here or here so we will get the data that we already fetched the underscore ID but there is I guess also easier way of adding this ID let's try with just data underscore ID just added a category underscore ID and here we can just put back data and I guess the result will be the same right here we have the C test the C2 maybe I will refresh and I will edit this one and I will change it to test C1 but let's go to our API categories and here our put is exactly the same as posed but actually now we can also here grab underscore ID and now when we have the ID of our category that we want to update and we need to put it inside our update one so when we create the only thing that we need to pass is an object of all the properties that we want to create in your document with here for update first we want to specify an object of what do we want to update and then the object of the data that we want to update with so and the first object will Define how we can find this document inside our database and the second part on the second object will be the new data for this object for this document so we can find it by just checking that underscore ID is the underscore ID from our request and then we just want to update both the name and the parent to be parent category so let's check if this will work I will just refresh just to be sure I would end this test C I will add one here I will try to save and as you can see we got test C1 here but we are staying still in this edit mode of test C and after we are done editing after we saved a category I would like to disable edit mode for the specific category so here after we updated a category I will do set edited category back to null so we can actually create a new categories so let's edit this one I will add more ones save and now it went back to create new category so again that's good and let's now change for example this one and let's check change parent category to maybe this one test c one on one let's see hit save and as you can see it worked nice if I refresh the page we should get the same data data and yes we do so now the last part will be our delete button so the delete button for products was a separate page but now I think for categories we can make it a little simpler maybe we can just do a pop-out with a confirmation or maybe a confirmation here underneath not as a separate page so as you remember if we go to products and we hit delete here we have a separate page to confirm this the deletion do you really want to delete if we click no it just goes back if we click yes it will delete the product and send us back to the table for categories we can make it simpler if we click delete we can have a pop-up with yes or no or maybe pop up here inside the table and I think power inside the table a small are you sure will be enough but I think it will be much prettier with like a pretty box or pop-up here that we can reuse so that's why I'm going to open yarn package repository here and let's search for react sweet alert too yes this will work so I will just yarn and this one let's do yarn add this one and it's just a prettier form of a confirmation so we need to have a state for our suite alert so I'm going to put it on the top or we can actually also use this as injected so we don't need properties let's see here they are showing us properties with properties but here we can also use it as an injection so we can just do this fall and just do small fire and that's it no State no nothing or actually we have here with swallow but but I guess this way will be simpler so let's do this with spawn so I will copy this part and here on the top I will just place it and as you can see we need to export our our function here but we want to export with small so let's add this part here and I will open uh parenthesis here and I need to close another parenthesis here on the bottom yes but we need to have we need to get rid of these categories we don't need this and instead this with will be will be a function that we are calling so we can remove this function thing here so we have wave S4 and well maybe to make things simpler I can put back our our categories page somewhere at the top so let's do a function categories categories like this and inside I will just put all this and so we have our function categories and it's just a water component that we were exporting before but now we are going to use it with small and we are going to export it the way they do this so here we need to put parenthesis and here we need to grab this small thing and a reference in case we need this and here inside we can just use our categories as component and this should work so now let's see yes it works we don't have any errors but now we can use this file this fall to for your to fire alerts this way so maybe I can just pass it so let's do small equals small so we can pass it back down to our categories and here inside the categories our page I can just grab it here and let me use it when we click this delete button and delete button is here I put this into separate line and now I will add on click and I will put an arrow function here or maybe I will just create a delete category and I will pass this category object to know what category we want to delete now I will go back to here I'll create the function delete category and as you remember we passed this category object and we have this all information here inside category the ID and everything and we have this fall that we can fire things with so maybe let's first see if this will work this hello world example and we are not deleting or anything let's see if I click delete with this we get this example hello world but now we want to change some things and here for title let's put are you sure and question mark and therefore the text I will put backticks and do you want to delete and let's put here category name and question mark and let's see and we don't need these handles to when it opened or when it closed we just want to handle the result of this uh of this confirmation but it should be just okay it should be a prompt so I guess it's just a type of confirm so I will refresh and let's see no it's not confirmed maybe it should be prompt so it should be confirmed maybe we don't need to have delete but instead we want to have a show console button to true and let's see cancel button we have console button title [Music] um let's say it will just say cancel and let's see we do have button in labels more more button labels confirm button text confirm button text let's do this one confirm button text and let's put it as yes delete with exclamation mark should be this should be title show button cancel button text like this so both of console cancel button text and confirm button text now if I hit delete we have yes delete and cancel and I would like to have this yes delete on the right side so there is a property called reverse buttons to true and let's see now if I refresh and hit delete we have yes delete would be nice maybe to make this yes delete button red or something so let's do a confirm button color and let's put some kind of red color here so let's maybe do d55 so it will be this red and let's see how it looks like I think I think it looks fine so now when we click it it will run this function then with the result so let's just do a console log and let's print this result I guess we don't need this catch part and I will do inspect here to see console and I will hit delete here here's the lid and as you can see we get result and inside the result we have object of is confirmed true is the Knight false and the value true so we will only check if it's confirmed because if I hit cancel we get another result with instant confirmed false so from the result we just need to grab is confirmed and needs to be true so let's do if result is confirmed and if it's confirmed then we want to delete our our category so and basically we just need to run access request and let's put it as time delete let's go to slash API slash categories and let's put some data object here and the only data that we need here is the ID of the ID of the category we want to delete and we can grab it from here from category so let's do underscore ID equals category category and Dot underscore ID and that's basically it we can do this like this or we can grab the underscore ID underscore ID from category and we can just put it here as a param so um but the problem here as you can see is that we get this warning and that the delete actually doesn't have any body so if we not if we can send it as a body let's see well how we did this with products here and the wave products we are sending this inside the query so let's send it as a query as well from our categories so to send us a query we will just do a question mark underscore ID equals and we will just add the value underscore ID here and that that's it we will add the weight here and the then we need to Mark the parent function here as async and after we are done with deletion we just want to refer the table and this table we want to see that it disappeared so we will just run this Finch categories and that's it now we need to handle this endpoint inside our API categories so let's check here if the method is delete then we want to grab the underscore ID from the query so let's do a const underscore ID from request query yes and with this underscore ID we just want to delete things so let's do category and we want to do delete one and we just want to delete one by this underscore ID so the first param here is just an object about how we can find it and we want to find it by checking that underscore ID is actually underscore ID but because the those two are the same we can just do on this credit this is accessing async function so I'll do a weight and after it's done it's done I will just do response Json wave okay and that's it and now I will try to make this window bigger as the inspect here Network and let's maybe try to delete the iPhones I will click delete here or do you refer do you want to delete iPhones and maybe I should add an iPhone's category yes delete and it's deleted and it refetched categories and as you can see we don't have iPhones anymore we just have iPhones too so I can rename this one to iPhones and it will be under mobiles so that's uh so that's perfect everything works I can now delete this test seat here yes and I can delete this test one-on-one yes delete and we have now only mobiles and only phones and iPhones is the child of mobiles we can also add the Android that will be also mobile under category let's hit save now we have Android mobiles iPhones mobiles and mobiles so now we can create new categories we can update existing ones and we can delete them so I guess we are now done with categories and products but the last thing that we need inside products is actually to be able to assign a category here so let's say that test 3.1 3.1 product should be is actually an iPhone or under mobile so an Android phone so now we should have a select here with to be able to select a category for this product right but let's maybe start by creating a real product so I will go to products I will hit new product and I want to add iPhone 14 pro I will upload some images I downloaded some iPhone images here and I can only select one by one so I will first upload them all all right and now I have all the images I can maybe sell this iPhone 4. and one thousand two hundred dollars and let's put maybe test iPhone description here and let's hit save so we have our iPhone 14 pro here and we should be able to change them position of the images and now the only thing that we are missing here is to be able to add a category so I think that we can put the category under this product name so let's go to our product form and let's see I will make it a little bigger and let's see here we have photos here we have product name we need also a label and a select for category so let's do label here and it will just say a category category and underneath we need to have a select select and the first option will be just empty value and it will be uncategorized and got a go rice in case of If the product doesn't have any category then it will be uncategorized and but then we need to list all the possible categories but for now we don't have any categories here inside our state so we we need to fetch it here as well so let's hear let's see here we are definitely fetching information about this specific product so let's see for use effect that we can reuse um looks like we don't have any use effect here instead we are passing permission from the product page edit product to this product form so let's see where this component is used and it's used or for new products and for new product page and for editing an existing product with an ID so we can either put fetching categories for those two or we can put it here in one place I think it would be better to have to put it here in one place that's why I will go maybe somewhere here and I will add use effect and as always the first will be just an empty out of empty Arrow function for now and the second will be empty array because we don't have any dependencies because we want to run this function when this component mounts right and what do we want to do we want to do axios get and we want to run slash API slash categories so we can grab all the categories we have inside our database and then we get result and it will run this Arrow function with result and with result data here inside the result data we have our Json with categories so we need to prepare state state for this so it's the categories cut and goris category sorry category set categories you state default will be empty and let's say it will be just empty array and now here we can just do set categories set categories like this and that's it for now we should be able to use these categories to list them as options inside our select so let's put the let's check if we have a categories the length of the categories is bigger than zero then let's do and let's do categories map categories map and this will be a function with specific category let's just show this down to C and the parenthesis here and for each category which will be C we will just print an option and the value will be just C dot underscore ID and here the label will be C dot name right so now we have uncategorized but we have all categories here all right now we are printing printing all the possible options here but we don't have any state for this select and as you can see we have it for title description and so on and so and for the price on that just put another state for and our category so let's do category and set category use State and default will be let's say empty string so it will so this empty string will match our empty string here for uncategorized as default all right so now we can use this category here down inside our select let's do value equals category and on change we will just do with event we will just do set category and we will grab the new value from event Target value that's it and so now we should be able to change those yes but now when we are when we hit save with for example iPhones we should send it as well to our API endpoint here inside save product so let's do this and here we are sending the data and but we also need to add category and the category will be of course just the ID of the category because we are setting this here and from our option value we are setting it back to category right so we are sending category as an ID now we need to handle it inside API products so let's go to Pages API products and both for post and put for posts we are creating for put we are updating and here we need to grab category category and here we need to grab category category as well and what we want to do with category here and here we just want to pass it along to pass it along with to create a new product or to update an existing product and that's it so now let's see if I refresh here just to be sure and I change this to mobiles that's not my best to iPhones if I click save let's check the database for products and the latest product should be iPhone 14 with we don't have any category here and why is that I think it's because we forgot to out to add it to our product model so let's put it here so category category and we want to Define this property to be type of ID so let's do a mongoose Mongoose types object ID and we want to add reference as well and the reference is just category the name of the model and that's it let's now try to save it again iPhone 14 pro let's change this to iPhones let's save and let's refresh our database here for products let's scroll down here and we don't have any category I guess this is because we need to restart here our environment our app so I will refresh here and let's go to iPhone 14 pro and let's change this to iPhones save database refresh products and for iPhone 14 pro now we have a category so that is really nice but let's open it back and as you can see it's still uncategorized uh and it is uncategorized because if we go to Pages product form sorry components product form and the default will be always for category the default will be always empty string here instead we should use as the as we are doing with an existing title that we are grabbing from the properties here so let's grab category category and let's just rename it to existing category or maybe we can name it a signed category yeah and let's just put it as a default here for assigned category or default if in case this is empty or something default will be empty string right so now as you can see I saved and it changed this to iPhones let's check if something crashes for all the older products no it looks like everything just works so now we can change categories I can put it to Android and if I edit you can see it's Android but I can put it back to iPhones as it should be so everything now is fine so now we are done with products we can add the title and category we can upload images description and price and we can of course edit also those categories now another thing I would like to have for our products is properties so let's see here we have an iPhone 14 pro but this is a black version and let's say it's a version with a 100 gigabytes of memory so we should be able to put this information and we can put this information here in the description but the thing is if we have a properties as a separate input somewhere here maybe then on the front of our store we can be able to sort and filter the products we have so let's for example say that inside the all the mobile phones we will have a memory property and then when we open a mobile phones category on inside our e-commerce store we will have a filter okay how much memory do you need for your phone or how big the camera should be or something like this the screen size or the color let's say this one will be black and you can filter depending on the color so I think we can go to a categories then and I think properties should be assigned to categories first so let's say that when we open mobiles we should see filters for price of course like for older products but also like color and maybe memory and yeah the storage something like this and the color so when we edit when we click edit here on mobiles we can only edit the the name here of the category and what is the parent category but the thing is that I would like to add more information here more properties to this category let's say that mobiles will have also properties like color and storage and stuff like this so um I think we can go now to categories inside here categories page let's see and and first let's say that we want to have those properties here underneath so let's first move this button here also under and we'll have like properties here in between so here we have this form for editing and properties we have this save button here as you can see this form is flex so we need to create the another div that will be actually Flex with gap one so we can move the input and the select inside so let's move this select and input let's put them here and we don't need this effects and GAP one on the form part now the save is underneath we can also remove this module bottom zero on the input and on the select so we will have some spacing here and now let's see now between this those two inputs and the save button I would like to have a properties here in between so here under this main div I will put another div and the first here I will put the label that will say let's say um properties properties yes and under I will have a div or maybe first we need the button to to add the to add the new property so it's at the button with a class name and button secondary secondary and this button will say add a new property property yeah we need to start this button and so let's go to our Global CSS and we can style it with just the classes and here in the component but I think we can reuse this button secondary later so um so let's see we have button default maybe we can use this one instead of secondary let's use button default okay and we have something like this maybe we can just make it smaller so let's do padding of on the top of and the bottom of zero this doesn't change anything so let's do text smaller yeah now the button is smaller so I think maybe we can maybe we can maybe put it under this properties so let's put property with properties and let's make this as a block block yeah so we have this button underneath and now for this div let's also add margin bottom of at least four I guess so we have some spacing maybe two will be enough yeah um so we have this pattern add new property it doesn't do anything I just add that it's type of button otherwise it could just hit the save on our form here and it would submit that category and so now it's type button so it will not submit the form and let's see now we will need the on click event on this button I will just put it into separate night so it will be easier to read and but now I will add one click sorry it's not here and it's not less save button it should be this one that we need on click so I will put it maybe like this and this one here let's do on click and on click of this add new property we want to put a property maybe here so to create properties we need to have a state for them so let's scroll up here and let's see we have categories so let's add also here underneath proper this and let's do set properties use State and will be empty array for now right now we have error because we have this empty on click part here and we need to define a function let's maybe call that add property property yeah now we need to create this function so maybe here under delete category let's do function add property yes so um now let's see when we click this button we need to create the new property we need to put a new property here inside our properties so let's do this um we will just do set properties and remember this is category properties not properties that are inside the react component just category properties like color and stuff like this and then with this we can just grab a previous value and run an arrow function like this and we want to return all the previous previous properties so we can make a copy like this and but we will also add an object of new property and every property will have a name or maybe yeah let's go to name and the name will be empty stringed and then we will have also values and values will be also an empty string right and now if we have something inside properties we should list it as the maybe inputs here so let's see here under this button I will put uh I will try to list the properties so let's see and let's do properties length is bigger than zero then we will do end properties map and for it property we will do parenthesis and that will make it bigger so it will not wrap and therefore each property I will print a div and inside each div each div will have this flex and GAP maybe one and inside each we will have an input for let's say property name um for example color example color and another input will be for let's say values values and comma separated yes and that's it now let's see if I click add new property then we have property name and we have we have values here all right so now we can click to add more properties and this should work and now we need to also be able to update them and as you can see the problem is here that we don't have any state for them yet we don't have any values and we need to add them so values will be actually simple because we can just do value equal and property that value I think it was values yeah values and well it should be here and property values and above should be named property values and above should be just a name but I will put it also into separate line so it will be easier to read but the problem now will be with update function because when we change text inside the specific input property name and we need to update properties and we need to find in properties first which one we should update so let's start here with a property name let's add on change function and well here let's maybe add a function called update property name or maybe let's call it better handle property and name change name change right and I'll put it actually inside Arrow function here so we can pass the property as an object but now I will put this function here maybe somewhere at the top as the function and this handle property name change and in the first problem we'll have our property right but now if we if we are updating property then we need to have also the new name right that we want to update this property to so let's see we need to pass also the new value so from this event that we'll get here let's also pass here event Target value all right but now the problem is that we will have the new name and we know what this uh what's the property object and that we want to update so we will have the name the all the name and the value so let's say here we will have a test property and values like one two three and when we added this input we will change the test one the new value so this event Target value will be test one and inside property we will have above the test the old name and the values so we can just in this function we can just Loop through all the properties and we can find the one that has the name test but the problem is what if we have Pro several properties with the same name then we don't know which one we should change to test one here we know because we say it's the first but we don't know it inside this function so to fix it I will also pass the index here that we can grab so I'll put this into parenthesis and I think that the the second part second param here that we can grab is actually index and I'm going to pass it here as well and now in this function let's jump to this function and we will have different params here we will have index property and new name so let's do index property and new name new name that we want to have for this property and first I will just console log everything so let's do index property and the new name and so we can see if this works I will open here my console and I will add it for example this one test and let's see we have index 2 because this is the third property so and the new name should be just t all right so we can update it we can fix it so let's see um we will do set properties and we can just set properties with just an array of properties here but it's better to use the previous value so I will do Arrow function here um and inside previous value we have all the properties so now with this properties um we will create a clone of this array here with all the properties so let's maybe call it props maybe props is not correct way to call it so I will do properties equals and I want to do a copy of this array so I'll just do array dot previous and now I want to do properties and of our index that we have as a param and I want to change the name so let's do dot name equals new name yes and here I will just return properties yes and now let's see if this will work test one two three yes I can add it here I can put test three to one here and then for now it works I can edit this input so now we need to have the same thing for values so I will just copy this and paste here handle property values change and here I will put new values and here of course we need to change as well values and of course new values and that's it then we can use this function for our other input so let's do on change on change and with the event we will run handle and handle property value change with the index of this property so 0 1 or 2 and then we will pass the property and then the new value the new values the new value of this input so it's the event here event Target value so that should be it maybe I can put it into separate lines so it'd be easier to read but then I need to put every property into separate line so I don't know if this will help match but yeah all right so now I should be able to edit those inputs as well yes and they do work um so I can edit inputs I can edit properties and I would like to add the margin bottom here on this pattern so here I will do modern bottom of two and I want to be able to remove property properties as well so we have two inputs but I will also add a small button that will have this class button default I think it was and it will just say remove so we have this remove and well we don't have any space in between them but this is because our inputs have margin bottom of two and I'll remove it let's do class names and let's do modern bottom of 0 here and let's do the same thing for other input and now for this each div I will add margin bottom of two so we'll have a modern bottom of the div and not on the input right and so and now we should fix this remove button right so um here on this button I will put it maybe like this I will add here on click on click and it will just run the function called the remove broad party and we actually need only the index of of this property that we want to remove so and here we'll have index 0 index 1 index two so let's create this function here above our return as the function remove property and we get the index and we want to run set properties we'll grab the previous values here and inside this function let's just do new properties it will be just a copy of previous properties but now from this properties we want to we want to remove and the property of this index so how we can do this well the easiest way would be to just return new properties as they are so we are returning all the properties but here we'll also add filter and we will filter out the the property that we don't want to have so the first param here we need to put it as in as a function but the first param here in this function will be the property itself but the second will be actually a property index so I will call it maybe let's call it property index and here if if we will return true and then it will this filter will and give back this property to this return otherwise and it will not anyway so it will be easier to understand I'll put it here and and instead I will just do here return new properties right so new properties will have the copy of the previous properties and then but then before returning to new properties we'll filter them to check if the property index is the same as index to remove let's call that index to remove so it should return true only if property index is different than index to remove all right and that should be it we can just escape this part and we can actually just do return here right so now let's see if this will work I will do I can see that a new property doesn't do anything anymore and let's see maybe because this is yeah we need to put it as an arrow function here so now let's see one two three let's say yeah that will have a color and a brand and maybe a size and then here we'll have red and blue and brand size will be and let's say 14 and 12 but now we want to remove the size yeah so it worked right um so I can remove those properties and we get an error if we remove the last property that is weird so let's fix it let's see we are getting 500 error no that was strange let's just refresh a new property I will add the three I will click this one in case it tries to run categories endpoint post because we are removing properties that's weird remove property okay I think this is because we need to add here on this button that it's type of a button otherwise it can try to send this form with our submit function here save category and we don't want this all right but when we click for example edit on this one it should reload those properties as well so and maybe if we are editing a category for example Android or something I will hide this table so let's see where do we have this table this table is here and if there is an category that we are editing I think it's called edited category and I would check that we don't have it and then parenthesis and here inside I will put our table so let's grab this table and let's put it here inside so now we don't have any because we are editing but we should have also a cancel button here so let's see here we have the properties so underneath somewhere here we have save button but I want to also have a cancel button in case we are editing a category so if edited category and then parenthesis another button here and it will say yes cancel and it will have a class name of button default yes I want to have some spacing between those so I will put a div with class name flex and GAP one and I'll put both both of those buttons here inside and for this button that is cancel I will add the on click and then we will Define this function here on click I just want to do set edited category to null yes and this way if I click cancel I will also add sorry I also add type of button just to be sure we will not save this form if I click cancel we see all everything here but the inputs are not cleared so I will actually put this into parentheses and I'll put it inside new line like this let's see not here I will put it enter here and now I will just edit the edited category to null set name to empty string and set parent category two no or maybe empty string yes so now if I edit the iPhones and I click cancel it clears the form all right and but now let's see if we can put some properties right so uh well let's do test property and let's put a property with color and we'll have red and blue and maybe green right what happens if we click save now let's scroll to our function that's saving our category and let's see we have this save category but the problem here is that we don't have any properties that we send so let's send along inside our data properties and of course we need to fix so we can handle it inside the API categories so let's go to API categories and now let's see for both post and put we need to grab categories okay sorry not categories properties properties and same here proper this and the properties will be an array of of objects and each object will have a name and values and both name and values Will Be Strings so first let's do this for a post so we will just do properties to be properties but this way we will have values as the values as string with comma separated instead I would like this this values to be chopped to an array so I can either do this here or maybe I can send those properties already prepared I think it will be better to send them prepared so here I will just do properties so we are going to save it as they are here I will add them also to our category model so let's do here properties properties will be type of let's say object this should work and but it should be actually type of an array of objects all right and I don't know if this should array be here or maybe it should be here I think it would be should be here it should be properties will be an array and inside each it should be type of object let's try it like this but first before we will send this properties we will not send them as they are here because then each property will be an object of name and the values that are comma separated and we don't want this so here for our data I'll put this into separate lines here and therefore properties will not send them as they are here from the state and instead I will do properties and I'll run map function on it and for each property I want to return a new object with property name so it's the name equals property name but the values I don't want to just do property values I want to do property values and I want to split them using comma right so let's see here maybe I will put those two into separate lines so it will be easier to read and now let's see I will try to send it let's hit inspect here Network I will add I'll click save here and let's see it failed let's see the payload and the payload looks fine we have properties with name color and values those but we get an error so let's see here inside the inside our console here for our server category validation fade all right let's see what was wrong with our category object failed for Value blah blah object ID fade for value right let's see what was it was a post request I will close this error here we have both the name and everything and the error is cast the object ID failed for Value blah blah type stringed path parent right so um let's go to our API categories and it looks like it's failing because our parent category will be an empty string here so I think we need to fix it for above put and the post and the best way to fix it will be just to check if the parent category is empty string then we will just return undefined here otherwise we'll just do parent category otherwise parent category yes and this should work but it can be simplified so let's say we will just return here parents to be parent category or if it's falsy just undefined so let's now do the same thing here yes and now let's click save again I'll clear here save and looks like it worked and the one thing that didn't work or we forget about is to clear this properties after you after we save so let's go to Pages categories and after we save we are resetting the name and we should also we should also reset the parent category to empty string and we should also reset the properties to just empty array and now it should work let's do categories let's go to products back to categories as the test P2 test properties too with mobile transparent I will put new two new properties property one property two and value 1 value 2 and here maybe value 2 value value free let's try to save it and looks like it worked let's check it inside our database database refresh and the categories and let's see here we have a test P2 we have parent but we don't have any properties and I think this is because we need to restart our server here so it will reload the models so I can delete this one and delete and delete test P2 as well yeah and now let's try again so I would do test p and the parent will be let's say mobiles I'll put property one property2 and value 1 value 2 and here value two value three let's hit save let's refresh our database to see if we have it and we have properties and each has the the name and values as array so this worked now let's see if we can edit them if I click edit here we don't have the properties that we added so this is because here on the top we have properties let's see our what happens when we click the edit button so we have edit category here we are setting the edited category to this category the name parent category but we are not setting our properties to category dot properties so let's do this like this and I will hit refresh here and let's see if we added test p so it looks like a worked let's go back to products categories and test P looks like it just works I will maybe add here a comma V4 and the comma V5 and I will click save and now we have a problem and the problem is split is not a function so I think that the underlying problem is let me just refresh if I edit click edit here doors are listed here as as strings but the properties that we are setting here are object this is an array of objects where each object has a name as the strength but the values is not a string it's just magically converted here so we want to set it here back to Strings and the values here so I would do here map and inside this map I will do that for each property I want to maybe let's grab the name and values for each property and we will return an object a new object for each property where the name will be the same as name but the values I forgot about the S and the values values and we want to change the values and if we are grabbing like this I need to have another pair of parentheses here but for values the values will be an array so we want to join each element by column right so now it didn't change anything here it just still works but now if we do comma V4 we should be able to save it yes if I add it back yes we have this and let me go to products categories and this one yeah and everything works all right so this works now and the thing is that after I click cancel I want to clear the properties as well so we have this console button somewhere here here we have the cancel button I will add set properties to empty array here let's go to products categories test P cancel yeah everything works fine now so now I can remove this test properties category delete yes and now let's maybe add a real properties so let's say that for mobiles I will click edit here I will add the at least two properties a color will be the first one and we will have black red blue yellow and well that's it for now and maybe brand brand will be maybe not brand but maybe we'll have storage and for storage um storage will be with gigabytes and for storage we'll have six sixty two 128 and 512 and one terabyte something like this and let's save it and let's edit so we can see here we still have it so now when we go to products and we go to iPhone 14 pro it's under iPhones category but the iPhone's category as you can see inside categories is the chart category of mobiles sure so I want to do something like this that when we are on products iPhone 14 even if it's iPhone's category and I want to get the properties from both iPhones and mobiles because iPhones isn't a child of mobiles so um let's go to our product form component that we have and let's see here we have all the categories here so we can just Loop through them and check if we have any properties inside and we should just check for the categories that we have selected all right so we're the selected category is here and it's just an ID so this should be pretty simple and let's scroll down to our return and let's see here we have photos so above the photos we have the select so between the select we can check if we have a categories categories so if the categories information is loaded I will check if categories length is bigger than uh bigger than zero and we have a selected category so just category then I would do parenthesis and then we put the div here and inside this div we will have properties but I will here check also if we have inside this category if we have proper this with length bigger than zero as well here I'll put some spaces here and let's see it should look like this and now we have a error here and this is because some categories don't have any and the properties so well maybe we can just get rid of this because we need to anyway just check the above the category and the parent category so I think I would just skip it here right but now I want to get inside both the category that we selected and the parent category and grab all the properties that we need to fill for this product so maybe I can prepare it here above the return so let's say um it will be const properties and yeah just properties and it will be an empty empty array and now let's check if we have a category selected and as you remember this is just an IDE so then we will find this category inside categories using this category ID so let's do a cafe goris and check also if we have categories right categories length is bigger than zero and then and the category right and inside this category I want to find them by ID by underscore ID that underscore IDE should be underscore this should be the same as category so this is category.com category ID that comes from the select right so here sorry um here we are finding the category that is selected so it's the const category info or maybe selected category info and maybe I can just console log it console log a selected category info so we can see that it actually works and here we have as you can see object a selected category info and for now it's iPhones but if I change the mobiles it will change to name mobiles and so on and the properties inside but if it's iPhones and we should also check for parent category or for all categories we should check if if we have parent so let me scroll down here and we need to check if the selected category like for now it's iPhones we need to check if it has a parent and if it has a parent we want to find it so um and for parent let's see where I can close properties and here it's iPhones I can see the parent we have mobiles and we have the ID of the parent so um let's do something like this for this that we found selected category info iPhones I can find properties and I can say it's empty but I can add them here to my array properties to fill let's call it this way and so let's do properties to fill and I will add push and I can push many items here so let's dot selected category info that uh dot properties yes and now let's maybe use it so here under let's do properties to fill if it's bigger than zero then then we will just do a map on it is to end properties to fill map and for each property let's call just p parenthesis and for each I want to put the div and let's for now just do property name so uh now we don't see anything because we have properties only on mobiles color and storage but we should also when we select iPhones we should also get the parent from mobas so here underneath let's check while while we have a selected category info and parent parent ID let's just maybe add the question marks here then we should add more properties to fill let's do properties to fill push and then we should grab the properties from the parent so let's do a conspirant and we can find it by looping through the categories like this and we can just check that the ID is the same as parent I parent underscore ID so let's put it here and now we can push it push more properties soon as the push and the push what properties from parent category parent category all right let's call it parent cat power and CAD properties yes and now this can go wrong because it checks why we have a selected parent ID and we have it all the time so what this is not good instead we should check and maybe rename this to a category info and change it to let and now let's check that here category info category info while category info has a parent with ID then we should find this parent category and then we should add the current category properties as well but after we are done with this category info we should change it to that category info will be actually this be this parent category and now let's see now I will hit refresh here and we get an error selected category info is not defined and let's see it should be just category info yes here and now let's see if I change to mobiles we have color and storage but for iPhones we get nothing and this is because I forgot about three dots here yeah so now for both the iPhones and the mobiles we have the same properties but those properties color and storage are registered only on mobiles and not on the iPhones so if I change it to Android we also have it but if I change the uncategorized we don't have any properties on uncategorized so let's select bunked iPhones and let me explain how it works now if we select iPhones then we go through this Loop and we are checking if we have categories information if it's length bigger than zero so we have categories information all the array of objects of all categories and this category is the ID here we have the string of the idea of the selected category so this is idea of iPhones right then we go inside here and then what we are doing we are finding as first the selected category and we are assigning this to category info so we are looping through the categories and we try to find the category where underscore ID is the same as our selected so here we will have an object of information about iPhone's category so name properties and so on then we are just grabbing all the properties from this selected category and we are pushing this to properties to fill our array here that we are defining but this this will work only for the properties that I assigned on the selected category and not on the parent categories here we have a magic while loop that we are checking okay is selected category here does it have an apparent ID and if it has a parent ID then we know that this category has a parent if we know that this category has a parent then we are trying to find the information about it the same way we did it here from categories array we are assigning it to a parent category and we are trying to see if it has any properties if it has we are adding this properties to our array properties to fill all right so um so this will add properties to fill with parent category properties but in case uh just in case we are assigning this parent category to category info and what it does is it runs this while loop again after we are done with our mobiles uh the mobiles will will become our parent category we are grabbing properties like color and storage we are putting them into properties to fill but then we are assigning this mobiles mobile is a category to category info and we are running this uh while again and we are checking do mobiles category have an important no mobiles doesn't have any parent but just in case there is a deeper deeper apparent child structure we can check for infinite infinitive number infinite number of a yeah so we can check we can have like unlimited structure and we will check for all the all the parent and the grandparent properties this way so I guess you understand how it works but now we are only listing the names and no values or no inputs so here we are just listing the name instead I will put this as a flex with a small gap of one and here we will have the name and maybe let's put it into this name into a separate div and I will put an input for above as you can see color and Storage so um so we can put what's the color or what's the storage but it should be an input it should be actually be select so we'll put select and for each select we should have options here and those options should come from our property values so let's do a property values and let's do map and for each value I will just call it V I would do parenthes here and I will just print an option with value to be just value and here we'll just put value as well so now we can select the colors and sizes and but now we need to also have on change here and for each product for each property we should also have this product properties stayed somewhere here at the top so let's see we have category and then but we don't have any properties information here so is the const and let's maybe call it a product uh Pro properties and the set product properties use State and default will be just an empty object for now so now we have an error because we have this on chain that is empty but let's say that on change we will have an arrow function and we will just run a function that will be called change product prop correct or maybe set product prop and we want to just pass the property and maybe just property name because that's all we need and the value that we choose here the value that we choose will grab it from event and we'll just do a here event Target value as the second pattern I'll put it maybe like this so it will be easier to read and now we need to create this function and where parents will be property name and our value that we picked from the select so let's do maybe here function and let's do set a product property the first is prop name and second will be value right and we want to only update this state so let's grab this Setter function and well what do we want to do let's grab the previous values in case there is anything and let's do new product props equals just a copy of previous properties of this product and then let's just do that new props of prop name will be this new value and now let's just return new product props and that's it so now let's see we have this sect or category here we have select for props and but I need to add value on this select as well and well let's see I'll put this here and but this doesn't look that good I'll put this into new line and yeah maybe something like this it's not perfect but it it works here we need to fix the value now because we have an error and how we can know if we have a new value here we need to go to our product properties and we need to change check this product properties of index of this property name so let's do property dot name right so now we should be able to sorry to change those properties let's see red black yes it works and as always we had with this form we need to now check when we are updating this product let's see save product we need to add to the data that we want also to send product properties yes and now we need to go to API products and we need to make sure that we are saving this so let's see um here we have post we need to grab properties product properties maybe let's rename let's pass it other way and we'll put this like this and put it into a separate line and instead of putting this with this name I will just do properties colon product properties so this way I can grab it with just properties yes and the same way we need we need to do this here for put but let's focus on the post first and we have product properties here inside properties and we just want to save it to our model so let's see if this will work this way we will just create a product with this properties and let's do the same thing here yes column and let's put this data here now let's edit our product model so we need to add the properties here so the proper this and well what's the properties should be it should be an array so let's put an array here and here an object and this will not be actually in an array this will be an object so I will just put type of object and that's it now let's see if we can save this iPhone with a selected properties it's black let's say it will be 128 and 128 gigabytes let's click save and now I will check my database for products and iPhone we don't have any properties but that's because we need to restart here so let's see now it's restarted let's save our iPhone again so I'll pick yes it's black 128 save let's go to data products and let's refresh and the iPhone we have properties we have storage 128 but we don't have any color I think we don't have any color because we it didn't change anything here so let's see black save database and refresh and inside products we have our iPhone with properties but we have now only the color okay it looks like we forgot in our form to grab the old properties let's see a product form here we are grabbing the old ones so let's do pro per this Con and let's call them assigned properties and we want to put them inside our state here product properties so let's do assigned Properties or in case it's empty empty and then we will do just empty object right now let's click edit here and let's change this to 128 and maybe this to Yellow let's save it if I go back does it have yellow and 128 yes it does now I can do refresh and let's see our product iPhone 14 pro properties yellow 128. so yes it worked so now we have products with properties so when now I can stop recording for for a few minutes and I can add some fake I can add some fake products and put prices so we can have some some more products to display on our store right so now I created more categories mobiles iPhone Samsung headphones and laptops show me and also more products so we have like headsets and everything we have two different iPhones and we have a xiaomi phone and we have different laptops and so on so we are done with the categories and products but one more thing that we need is actually admins page so for now if I log out yeah first I don't have any logout button but I need to have a logout button and even if I log out anyone can actually log in and edit the products and so on so we need to create a page for for creating and removing admins so first let's start with a logout button I will go to my navigation component and let's see maybe here at the bottom and let's put I will just copy this settings link and well we don't need any active or inactive link because it will always be inactive I can just put here um of the string inactive inactive like this and we don't need any link here graph and it doesn't need to be a link I will just change it to button let's see closing tag button yes instead of settings it will be log out and then well now let's fix the icon so let's go to Hero icons um let's search for sign out or log out yeah maybe maybe this one so I will select this SVG and double paste this one and now let's see how it looks like um almost fine but it looks a bit a little bit weird here let's see um we have this SVG here log out it's inactive but the content looks a little odd and I think maybe we can just change this to span and well this helped a little bit now we have this inactive let's see and what classes do we have here it should be flanks yeah but it's not next to each other let's see why it's not next to each other because it should be inactive link as class names so let's fix it and we can probably just put back this to spawn and let's do just inactive link and it should be a variable so let's put it as a variable like this inactive link now let's see and it's a button and it looks just fine so when we click on it let's add on click we want to run we want to log out I think there's a simple function for this sign out yes so I'm going to import it from Excel and I will just use Arrow function here to sign out and yeah let's see what will happen now if I click on it I will refresh and click and well everything worked so now I'm not logged in anymore but even if I logging back with my user and the problem is I can log in with any Gmail account and it shouldn't be possible so we need to have a page for all admins or we should at least and select who can log in or who cannot so for this let's go first to our API off and next off and let's see here here in our configuration we have providers we have adapter but we can also assign callbacks and the one on the Callback that we are going to use is a JW token and it will be a function and here inside we will have we can grab Properties or params like token we will have also account and the profile and the default the only thing we need to do to so it will still work is that we just need to return token and that's it now we can maybe console log everything to see what's inside so as the console log and let's print everything I will open console here now let's try to log out and I try to log in again I will log in as my user and now let's see what do we have here and now although they say in the documentation that this function should run and every time we assign a token JWT token it looks for me that it's not run so instead I'm going to use a session which should be run every time a session is checked so that's a perfect for us we have session here and we can have also use token and user and we need to just return session to make it work but let's print everything let's maybe print session token end user to see if this will work now I will log out and I will log in again with my user and we have we are now logged in and as you can see we have some console logs here like for example token is undefined but that's okay we have some session and with my email and here we have the user and maybe we can check something here um inside let's say inside session we can check that that the session user has a specific email and then we can validate the the user this way so um let's change this to check if we have a session user and this email so um let's do something like this and we will check that either session user email is my email or user email is mine but let's start with session user email and let's see if this will work I will Define admin image here let's do const admin emails and I would here put an array and for now it will be only my email and and let's see here we will do if session um user and the email and we want to see if this email is inside this array so let's check this way and admin emails includes if it includes this email inside session user remain then the email is correct and we can do return session otherwise let's say it will just return false so I guess we will not the we will not be logged in right and now let's see if this still works I can log out and let's see if I can log in yes looks like everything works now I will log out and let's see what happens if I will change this image to Gmail something like this let's login let's try with my user and we cannot log in so this doesn't work anymore I cannot log in but if I put this back then everything everything works I can still log in and everything works now there are a few more things that we need to secure and let's go to for example categories here we are connecting to the database and then we have a get request post request and so on but the problem is here in this handle function we are not checking if we are a proper admin we are not checking if and the person that we we are not even checking that we are logged in so to fix it we can maybe just grab a session so let's get server session yeah like this and as the const session equals a weight gets the recession and let's just do a console log and let's see what's inside this session so now if we open a terminal here let's go to yeah categories and looks like we get a small error here and we get this error because I forgot that we need to pass some information here and we need to pass request I guess here inside so let's put requests here so we are going to pass now a request and we also need to pass a response and we need to pass the config for our authentication so all this config we need to put it first into a constant here so let's call it maybe of options equals this and let's export it as well and now we are going to use it here so let's do like this and now we can use those options even here of options yeah and it has been imported for me so and now let's see if we have any session here so if I go back to products categories yeah as you can see we have some information here and we get the user and we get when the session expires so um inside the user we get the email so this way we can check inside every function every Handler that the session has the user with with emails that are inside admin emails but to make this simpler I will make a separate function maybe here and I will do something like this let's do export function is admin request let's call it this way and it will take request and response because we need this from every request every Handler and it will just grab the session so it's the cost session equals get server session here as always request response and of options so let's use it here we need to add a weight and async here I think async function and let's see then we will have a session and inside session we need to check that user email is inside admin image so let's do if if admin emails includes and now let's do a session user email then everything is correct but if it doesn't then let's throw an error let's draw an error not and not admin yeah something like this and then we can now reuse is admin request instead of this so let's do this await is admin request request response all right and now if I comment this out let's see if we can call this function to get all the all the categories I will open this in new tab we get Json and even if I log out I can still refresh this page and I can see all the categories or I can show you the products and it will work for products as well but let's see what happens if I uncomment this a weight is admin request if I refresh I get an error not admin and maybe I should change it so it will be not an admin but yeah you understand you will get an error and on the production environment it will not be and you will not see all this stack like this but it will just be an error and like 500 and something went wrong and you will not see this Json but if I log in back to my user I can refresh here and I can see the Json so we should put this protection inside every um every API Handler so let's see we have it inside categories now we need to put it to products as well and even for upload so here for upload let's see here we need to First connect to the database so it's the await Mongoose connect and then we can do a weight Ace admin request and that should be it for our production if you want you can easily add a sub page here for admins where you can create and delete admins and when you have admins inside the database and then you can check here inside authentication next off and here instead of getting an array you can change this to function like is admin and then you can do a request to the database with all the admins that you put it to the database right but um now let's go back to our admin so we have products categories and everything works and we can even log out and sign in with different with different user or at least we can try but let's see we have a problem here and this is because we are trying to get the categories even if we are not logged in so the problem is that actually we shouldn't be on a specific page when we are signing out instead it takes it should take us to a different page right let's see maybe first inside our layout and here we have components layout yeah here we have a data here we are checking for the session and if we don't have any session then it will just say login with Google button but even if we have session but the URL is weird we shouldn't be at this URL so let's go to our navigation and instead of calling this just sign out I will Define a function here somewhere at the top function and let's call this one log out and I will use router to push us to different location to just slash and then I will call this sign out and I will add a weight here and here and I will make this async function and now let's try to use this function instead so I can put it like this or I can actually just put log out it should work as well let's go to categories and now let's log out and now everything works it redirected us to the start page because if we go to categories we will get an error because we are not logged in that's why we have a 500 error but if we login with proper account we can go back to categories and everything works we can maybe also try to change the 500 error to something else so let's go back to next elf as you remember we have this response here so let's maybe do response and let's do status as the status and let's say this status will be here because if we are not an admin then we want to have a status of let's say 4 1. 41 and not an admin and if we are done with the request it's good to do just response and and like this and now let's see if we log out and if I go to slash categories we get the request failed with code for one that's because we are not logged in so now we don't even see this message but that's not a problem so if someone tries to hack now the our admin panel and goes to directory to categories that person will not see anything even here for API request for to see the Json if I refresh as you can see this page is not working HTTP error for one so you cannot see anything it just it's just it just doesn't work you get for one on category so if I go back I can log in but you need to have a specific account so I can log in with this user but I cannot log in with other users because this email is defined here right so now our admin panel is secure so now I guess we can go to our front and we can try to list all of those products and build something that we can actually create orders so we can later see them here inside orders but before we do this there is one more important thing to do with our e-commerce admin panel and this is that it should be mobile responsive so it should look better than this so for example here the an important part would be to make this site navigation hidden when it's on mobile with an extra hamburger navigation and button somewhere here maybe so when we click on it it will show the navigation and by default it should be hidden so we should see only the content of the page so and this is what we are going to do now so we need to add some adjustments for mobile so we can use that panel use this panel comfortably even when on mobile so I'll start by editing our layout to make it look maybe a little better instead of this blue I think I will just make it gray so let's do a gray 200 here for no session and let's do the same here if we have a session grade 200 so now it looks like this and but now we can fix our navigation so let's go to navjs and let's see here here we have a text to White that's why it looks a little bit off I will change it to text and gray let's say 500 and now it should look a little better yes it does now for the selected the item let's say it's here I would like to make this a color text below 900 a little bit different I don't want to have this dark dark blue instead I would like to use a another blue but the blue they want to use is not inside defined class names here so I'm going to actually Define mine oh my own blue color and for this I will go to tadewindconfig.js and let's see here I have extend all right so I can add my own colors here and then the color I'm going to add will be just I will call it primary and it will be this so it's a pretty um blue here right now I will go back to navigation and let's see I have this text blue for an active navigation item and I will change this to just text primary now we should have a prettier color yes we do and now instead of this white background here I would like to end this background somewhere here so it will not connect with the rest of the page so let's see here we have ponding right of zero I will get rid of this yeah so now it looks a little bit mirror now there is something wrong with this those Corners here are not rounded so let's see how we can fix it here we have the rounded I think we can just do rounded and let's change it to small and I think it looks now better but I think I will change it to medium let's see yeah it's better but I will change it back to rounded small right and now instead of this white background here I want to make it light blue so let's see here instead of background white I will add background let's do blue and let's do 800 I think now it will be super dark yes if I change it to just 100 yeah it's lighter let's try with 200 yeah it's better but it's not the blue that I actually want and I will try to use a custom color for this so I'll go to my tailwind and config and we have primary color and I will add the color called The Highlight highlight and it will be this so now I will try to use my highlight color let's see here we have background blue I will change it to background and highlight highlight highlight yeah let's see a little better but not exactly what I wanted let me go back to our Tailwind config try to replace this and now let's see how it looks here and I think it looks good but I want to also change this gray background to something else also a custom color so um let's define my background gray and it will be this so almost white now let's go back to navigation or maybe better let's go to our layout to fix our background Gray and I will do background will be background Gray and now the same for a color when we have session right and then we have something like this all right let's go back to our navigation and let's see will be probably better to make the text darker or maybe even black here inside this so let's see active link and it text primary I will change this to text black yeah but the icon I would like the icon to be actually blue or primary blue so let's do this we have a classes for links but we don't have the classes for SVG icons here here we have our logo then we have a link to a dashboard but uh would be nice to have also classes for SVG so we can paint them differently depending if they are selected or not so our constants here and the first will be inactive icon it will be just let's see the default classes will be those and then let's do active icon it will be inactive icon plus um and let's add space here and let's make it feel um primary primary yeah and now let's try to use those classes for our icons so the same way we did here for our class names I will just copy this and I will put it for our class names inside this SVG instead of inactive and active link we will have active icon and here will be inactive icon yeah so let's see here we have now active icon um so this worked maybe it shouldn't be filled but there should be text let's see here now only the borders are blue I think that's uh that's much better now I will fix the other icons so let's see here we have four products and class names for products class 94 icon here active icon and here otherwise inactive icon yeah now for the categories categories class names let's put it even here and sorry I forgot about to copy the C now let's paste it here here active icon and here inactive icon then we have orders let's copy the class names here and let's put them also here but we'll do inactive sorry first active icon then inactive icon then we have the last one I think settings so let's say copy this and let's paste it here with an active icon and inactive icon yeah now we have a different icon colors if we are if we selected a page here so that is good but there's one more thing I would like to make a printer here and it will be to use a field icons if we have that if I search for home we have outline and we have solid icons and everything will be much better to have solid icons here so I will fix it so let's just copy jsx for home and let's test it so here we have products here we have our home I guess so let's paste this SVG and now for the classes we need to copy and paste them again so let's do this oops that's too big should be actively should be active icon and inactive icon let's see well I don't know if this measures that much so I will just put it back as it was yeah the previous icon I think this one works fine if you want you can change it to solid icons and not outline right but now the most important thing will be to put a hamburger button somewhere somewhere here on the top so we can toggle this navigation but before we do this let's go to our layout and let's see how it's built so as you can see here for our layout where we have our navigation we have this flex and here we have our navigation so our navigation is just a flex item on the left side so what can we do about this we can make it maybe hidden if we don't have enough space so let's open our navigation yes and here let's see our main element here and it doesn't have any display property display class but I think we can we can add it so let's see what happens if we make it fixed fixed and let's see now it's fixed to the top left Page and top left top left corner as you can see the other part the other Flex item just takes the rest of the space and so we are making this fixed and by default and let's also pull it pull it left so it will be outside of the screen so let's see let's do minus and left and let's see what do we have here we can do minus 20 let's do minus left full and let's see now now our navigation is outside of the screen but if we remove this glass then it's visible it takes amount around this amount of space but for mobiles that should be our default we would like to take so it will take all the all the width so let's put it here I will say it will be with off let's say it will be width of all yes and let's add some background color let's say it will be this background of our default background will be background Gray yeah so now it is available here but the have the have should be full so let's see hey full and now it takes the whole behave right so let's add bank that it should be hidden on the left side so let's do minus left pull so now it's hidden and we will fix so it will be toggled by uh by a button let's go to our layout I will put it inside layout so it will be on every page and see here we have our main component for layout and flex maybe I will add another div here I put here everything inside but on the first element I will just put a button and let's say it will be a test for now let's see do we have our test button yes we do it does nothing and that's correct and this background Gray I think and this minimum half we should add it on our most current div so let's put it here and yeah now it's better but now for our button here I would like to style it a little bit let's fix the icon of hamburger and here we have bars three and well let's just copy three lines here and instead of this test I will put this SVG here and now it should look a little better and yes it does now when I click on this button I would like to show my navigation so here we have our navigation element and here we have our button and let's say that we want to toggle this navigation so for this I will put a state somewhere here at the top let's do cons and let's say show nav and set show nav and default will be use State here and default will be false all right and maybe we should rename it so it will be only for mobile I don't know if it's important but let's put our on clickback action here when we click our button I will put Arrow function here and then let's see on click we want to do set show navigation and we want to make it to true so it will be visible now we want to use this thing inside our navigation so let's do a show to show navigation and now we can use this as an attribute here inside so let's use show let's grab our show here and let's see here we have some class names for our side and I will put those as a string and now and on the beginning I will add here parenthesis and if we have show then I want to add the then I want to add the left to be zero so let's do left zero otherwise if we don't want to show I will use this minus left full and so let's put it here yes then let's add plus here so it will be join it together let's add space and now let's see if I click on it yeah it kind of works so um I wanted this navigation to start from the top so it should even hide this so it should even hide this button that we created so let's just do top and let's do zero yeah and now now we can click categories we can click products and now this kind of works right but to make it a little prettier I would like this to be hidden when it's a desktop so to make it work we will add the classes here for desktop and I will start by doing medium and in case it's a medium screen I want this to be not fixed but let's say static static the position should be static and then now let's see yeah as you can see now it's static and it looks much better but the width of this is too big and this is because we have this with full and let's change it for medium screens let's say let's do this width of Auto so now it's much better so it's this big for medium screens and for mobiles it's for width and well so this works if I click products we are on products and I can open navigation I can all orders is not ready I can go to dashboard and stuff like this movie may be better to add some transition so let's do this let's add transition transition and let's see now this didn't help and because it should be only transition it should be let's do a transition all and now let's see if I click on this as you can see our navigation just slides in from the left to the right and that is Mother Bearer and if I click dashboard it will go to dashboard if I click products it will go to products yeah but now this navigation button here it shouldn't be visible for a medium screens so let's go back to our layout because if I have a screen this big our navigation invisible so I don't need this button so we have this button here I will put it into separate div and this button let's cut it from here and let's put it here inside and for this div I want to make it a display block but for medium screens I wanted to um to hide it so let's do hidden and let's see now yeah I think that's that's much better if I have screen that is this small I can see the button but I think it looks weird with just a button here and we should have at least our logo that we have here also with the button so I'm going to copy from the navigation our logo let's see where it is it's inside navigation here we have our link with with our logo so I will copy this and I will create a separate component inside the components so let's do new file here and let's just do logo.js like this and I would just do export default function let's do logo and the and as you do return here and it will be just this link right and let's see the link has been imported for us so now we can use our logo here instead of this link so let's just do logo yeah and let's see it has been imported for us and this works but I want to put the logo here as well so let's go to our layout and next to our button let's put our logo yeah so now we have logo and the button and for this div let's make it blacks so the uh so the logo will be next to our button and now I would like our logo to be on The Middle so let's see first I want it to make it items items Center so it will be um aligned I hope it will be aligned by its node let's see why here we have our link here we have our button and well let's see there's something inside the button that makes it uh go to the middle I think it's our logo link it has a margin bottom of four and margin right of four we should go and remove it and it should be only inside the navigation so let's remove it from here modern bottom 4 and margin right 4 and let's put it only inside our navigation let's see here we have our logo let's put the div with class names that we just removed and this logo should be inside yeah let's see if this looks fine yes it does so and now we can put our logo in the middle here so let's go back to our layout and let's see we have item Center let's add justify Center so now everything is in the middle that's not what I wanted so I will remove it and instead I will put my logo inside the separat div so let's put logo inside this separate div and now for this div I will make it Flex as well and I will make it grow so now um this div that our logo sits inside should take all the width yes it does and now let's make it justify Center justify Center so now it is on the middle but it is on the middle of our div not in the middle of screen so to fix it I will add a small margin from the right that's the margin right of net try with eight yeah let's see if the margin is around the same as the button size yeah maybe we can make it a little smaller let's do six and now I think it works it works fine so if I make it this small it works yes it's fine but it will be maybe better to add some padding from the top and from the sides so for our and for this and deep here let's add some padding of let's say four yeah so we have some spacing so to look better let's see yeah I think it looks just fine and if I make it this big then it disappears yeah so I think it looks fine our navigation now works I can toggle it and I can go to products I can go back to dashboard everything works but now I would like to fix this page content so for example for our products it looks like this for mobile it will look like this and it just sits inside this white div and now if you can see but we have a white container that grabs everything here and now with this gray background it doesn't look that good anymore and this blue button is not that pretty anymore so I will go to our Global CSS here we have some basic classes that we can reuse so for example for this button we have button primary and this is because and we created this class because we don't want to copy paste all those classes for every primary button but this way I can now reuse my for example background primary here to make this pattern a little prettier let's see and background primary let's see if I refresh and I'm not sure if this worked and let's maybe go to our products page let's see page products and let's search for our button here we have instead of those classes we should actually use button primary so I will get rid of those classes and I will just do button primary and now I think this pattern looks much better than those for example so now we are going to fix also this maybe this white box so we can get rid of it let's go to our layout JS and let's see our content sits inside this div with this white background so let's remove it and let's see we have margin top two margin right margin bottom let's get rid of it and it's rounded it doesn't need to be rounded let's just leave the padding right so now our content sits in the same gray background that we have our side navigation and I think that's fine we can just make our buttons uh prettier so let's go back to our globals and let's see we have rounded medium let's change it to small yeah and now let's maybe make our tables a little bit pretty right so we have the stable basic that we were using to style all those basic tables for categories and products and again to not reuse all those classes to all the tables to both of those tables I'm going to just apply new styling for the headers and the cells and to make those the stable a little bit prettier so first I want to get rid of this light blue so let's see here we have this light blue I think I will just remove it and instead um I want the header text to be smaller so I will put text SM to make the text smaller yes it is and I want to make it gray so let's do text gray and let's do maybe 400. it's too too light let's do 600 so we can see something yeah I think that's uh that's better and then maybe the the labels here should be uppercase so let's see upper upper case and we have this class here yeah this is much better and now would be nice to fix this blue border now that we have everywhere so let's see here we have this border blue and we just get rid get rid of it so we have something like this now and the only border I want is from this from those labels to our from the labels to our body so here we have it for the table head I will add border and bottom border B and then let's make it a light gray so it's the border and the color of the Border will be gray let's say maybe 300 yeah so we have this line here here maybe we can do border grade 200 yeah I think this will work great now for the whole table and the background here is a white-ish gray but it's gray so for the table I will make background of white background white let's see I don't see any any different it should be not here background white you should go to our table sorry yeah now I see a small difference but I will also add the rounded rounded SM here to make rounded Corners a little bit and now I would like to add a small Shadow so let's do a shadow shadow small yeah so it will be easier to distinct the table from the from the rest maybe we can do medium so it will be more visible yeah I think this I think this will work fine all right so uh now we can maybe add some more spacing inside there inside the cells here so for the header cells and we don't have any spacing at all so I will I will add spacing padding on the sides to let's say two maybe yeah so we have some small spacing here maybe we can do more less than four yeah and now let's try with the same spacing side spacing for the cells so let's do this now let's add some spacing from the top and the bottom so let's maybe do padding top and the bottom to two and let's do the same for the cells inside the body so now we have something like this and that's too much spacing here between so I will change it back to one and I think that looks uh really nice yeah so now the only problem is those buttons inside are don't look like our button primary so let's go to our products and here we have our table and we have some links here and I think they are styled because we have this Global styling here and we have links inside the table let's see here table basic a and we have all those classes here maybe let's see if we can reuse our button primary here let's see reuse apply button primary and well kinda worked almost let's see if we are missing something it should be inline flex and other than this I think it should work maybe let's remove all of the classes and let's just add them one by one to see what what is broken and so this looks odd I think this is because we need this Flex inline Flex so let's put this back button primary and now let's do inline Flex let's see here now it's better let's add margin on the sides margin X of 1. so we'll have some spacing and yeah it looks much better let's also add items Center so it the icon will be on the same level as the text yes and now a small gap between the text and the icon Gap one here now I think it looks uh much much better so if I click edit here on the product we can see this and that is fine I think that those buttons shouldn't be blue so I will change the background color for those so let's change here I would do a background of let's say gray and let's see I would do gray 700. and this didn't change the background color let's see yeah looks like we still get the background primary so instead of doing this button primary I would just copy the classes that I need to have here and let's paste them here and now they are gray and I think it they look better when they are gray so let's try with categories here we have some buttons as well well maybe we can remove the padding from the top and the bottom to make them a little bit smaller yeah I think now now they look much uh much better maybe we can just make the text inside them smaller so let's do a text as M and let's add some padding from the top and the bottom back yeah and uh I think it looks fine if I zoom out it looks like this so I I would say it it works fine I will zoom in again so it will be so you can guys see yeah I think it looks fine award table for for now would be nice to fix this those forms and the inputs so they don't look that ugly and then to fix this we have some basic classes here as well basic stunning for inputs Let's see we have here border of two let's change it to border of just border so it will be a thin border here and we don't want to make it rounded medium I think we can be okay with rounded small and this gray is too dark for the border so I think I will just do 200 yeah and now I would like to add some spacing here inside we don't have any spacing padding so I will do just Panic on the top and the bottom of maybe just as depending everywhere too so let's see yeah and but I think it looks just fine for the for the selects but for the inputs I would like to add the more spacing from the left and the right so padding from the top and the bottom will be two padding on the sides will be four so let's see now yeah I think I think now it looks fine maybe it could be smaller like free yeah I think now it's uh now it's right maybe we can add a little bit of Shadow here so let's do apply and let's do shadow shadow medium and well that's a lot of shadow in case it's the same amount of Shadow we get on our table yes it is I would change it to small let's see well I don't think we need the shadow on the inputs the borders is just enough well but now I think we should have this title to look a little bit better so let's see if we have any basic stunning for this no we don't so let's go to our products and let's find this we have this table here we have this button but that is for add new product button and not for our form for our form we need to go inside product form and let's see here here inside the render we have this form here then we have a photos where do we have edit product let's scroll here product name form category I don't see the edit the product so let's go back to products Js or sorry we have products here then we have edit and then we have this file here and then we have edit product H1 so let's see if we have any basic styling for H1 do we have here no here we have it it's text blue maybe let's change it from Blue to dark gray gray 800. and now let's see yes maybe we can add more margin bottom so we have more spacing here yeah I think it looks fine now for those labels I would like to change them as well so let's see here we have labels text blue 900 I want to make them gray 800 and I want them to be smaller so let's do text SM yeah I think that is that is much better maybe I will make them lighter so let's do 600 not the H1 on the label let's do 600 so it will be lighter yeah I think that's all right now um I would also like to fix the space in here because it looks weird and we have color and then we have this storage and we have this and this is our properties that we have inside product form so let's scroll down here to our properties here we have properties to fill and we have Flex with gap one and so we have a text on the left and this is this div and then we have a select which is the right part I think we should put select into separate div so I will take this select and I will put it here and this will just make our selects smaller but now maybe instead of having text on the left and select on the right we can make it the same way we have with category and stuff so let's remove this flex and Gap and let's see now it looks better but those texts should be actually labels so as the label on this and now let's see if it looks better yes I think it does but for the for the name here I would like to be this with the first letter capitalized or the first letter should be uppercase so let's see instead of printing the name I will print just the first letter like this index of zero and then I will make it two uppercase let's see yes we have C and S and now I'll add the plus I will join strings I would do take the name and I will take the substring sub string of the name it will start from one let's see and we have the full name with first uppercase so this did the trick first we are just grabbing the first letter and we are doing the uppercase then we are adding the name again but as a substring starting from the second character so index of one right now I think our form looks much better let's see for mobiles for mobile devices it looks like this I think it looks fine and one more thing I would like to fix here is this upload button so let's scroll down to photos and here we have photos here we have our label for upload button I would like to change the color on it to White and add some Shadow or something like this so let's see background I would like to be white and let's add some shadow of medium why not yes and maybe a small border so it's the border and Border color of Gray 400 something like this maybe it's too dark let's do 200 yeah I think now it looks much better maybe the shadow is too big so I will actually change it to Shadow small and yeah so now it looks more like a button but now for the photos photos we have those images here I would like to add some some background or something to them and some spacing so let's add the background of white Let's see we I not see any big difference but if I add a padding of let's say four now we should see some difference yes we do and let's order also a small Shadow so it's the shadow SM so small shadow here and let's do a run that SMS as well rounded corners of small yeah and let's add a small border so let's do border and border and gray at 200. yeah now I think they look better and the only thing is that I want to run the corners here on this button make them smaller so let's do a rounded LG let's do rounded small and yeah and I think it looks better maybe the text here can be blue so let's try this with our primary color here we have item Center tech center we have text Gray 500 let's do a text primary so it looks like this maybe even the Border can be primary let's try and border um as the Border primary and it looks now like this well I think it looks just fine maybe instead of upload it should say add more photos add more images or maybe just add image and so we have ADD image and well it's flex but it doesn't need to be Flex or maybe let's put the flex but let's do a flex row not relaxed Flex column and let's remove this links here so we have it like this should be calling I think it should be just flex and flex call yeah now it's uh now it's better so we have this and image with upload icon I think it looks fine and we have photos and we have save button and I think everything here looks just fine and now the next thing is I would like to fix this signing on this page for example this add new property and it's inside our categories page not inside API but inside here right and then now let's see where here we have some button that has a class name button default so let's go to Globus see here somewhere we have our button primary classes and I want to apply the same for our button default but the background should be gray 800 let's say so now it looks like this maybe it's too dark so I will do 600 yeah I think now it looks now it looks better and so we can add properties and we can remove them and and this looks fine but maybe it will be better to for delete and remove buttons to make them kind of red so let's do or sorry we have button red class names here so let's put the same classes on those and but instead of pattern red let instead of background gray let's do background red and let's do maybe 300. yes and now let's see where we have them I would just search for this and looks like we have it on where we want to delete a product so let's see if I want to delete our iPhone we have this red button here one small thing I would like to fix here is to make it brighter brighter red but the tanks should be dark red so let's do red 800 so now we have something like this maybe it's that's too dark let's do 600. yeah I think this will work maybe let's try with red 300 here no 200 works just fine and would be nice probably to have the same stunning four delete buttons here so um let's go for example to our um products or categories so let's go back to let's see here categories here we have button remove and we have button default here and let's change it to button red and same on the not on the save but inside the table let's see here we have a button for edit category let's change this to uh here we have delete let's do button red so we have something like this and on the edit let's maybe do a button default so it will be this dark gray let's see here now for products I'll open our products page here as well here we have some table rows and we here we have some links so I'll add class name on those links to be here first button default and here let's add class name of button red this didn't change much because inside our globals we have this definition for um all the links inside the table basic I think we can just remove some of those classes like for a text color and the background color and to see if this will help yes it does so now the colors work it didn't work because here we have more specific definition but that's right I think now our admin panel looks really nicely and the last thing I would like to fix would be default buttons I would like to make them more not that dark so let's scroll to our button default maybe instead of this gray 600 maybe we can make them white so let's do background white white and text should be well it should be gray let's say 800 now let's see how they look like I think they look fine but we need to add some border and the Border should have a color of gray let's say at least 600 maybe that's uh that's too dark let's do 400 still to Darkness the 200 I think this will and work fine but the color can be lighter let's do 600 text Gray 600 maybe let's put back 800 I think it works uh just fine but for default buttons maybe we can add some small Shadows let's do Shadow small so that will look a little bit better but maybe for the even for the red button and for the primer let's add shadow of small so it will be more visible that those are clickable buttons same for the prime array let's do primary button Shadow or small yeah and now I think we we are done so let's see products looks fine we can edit products here looks fine let's go to categories we have edit and delete buttons here and let's end it to edit category we can add new property and everything looks fine everything works we have cancel yeah I think now everything looks fine and it's even responsive so if I make it this small we can toggle here and we can change pages so yeah now everything looks uh fine let's see even for products we can edit products and the form looks fine let's see for categories you can edit categories here and everything looks fine so now I guess we can continue to build our front part our main e-commerce part where we can display our products and where we can order products when our customers can order products so later we can see our orders here inside orders page that we will create so now let's do this all right so now we are going to build the front part of our store and as you can see this will be a separate project so for now inside my IDE I have a Another Empty directory and this project will be called e-commerce front for me and here we had this e-commerce admin so this will be two separate projects well it will be one project but it will be two different apps the one will be for admin panel and another one will be for our front part where we will show the front of our e-commerce store and in the front part I'm going to use a style components in the admin part we were doing this with Tailwind CSS but on front we can use the style components so you guys can learn how to use it and there are many big companies that are using this Spotify wish Reddit Tinder GIF Vimeo BBC News emdb and so on so it's really popular library for styling components and here as well we are going to use next.js for our e-commerce front so this is what we are going to start with we are going to install a new nxjs app here so let's do yarn create and here next up and the dot so it will be installed in the current directory here in my terminal and now it's installing and also we are going to of course use the same database where we have all of our pro products categories and so on so we can display them in our e-commerce front so e-commerce front and the e-commerce admin those two projects will have the same database and here let's see typescript no not this time eslint yes why not Source directory no we don't need this an experimental app directory no no experiments for me and that will be it okay now it's installed so let's do just yarn Dev and we get this link that we can use to see some previews so let's open it here yeah and it looks fine so now I will go to pages let's go to index.js and I will just remove everything from here I will just yeah let's remove everything and I will just export default function and let's just do home page and that's it let's just return inside and a div we have test inside and we have test here and same with styling I will remove all the globals and everything from this home module that we don't need anymore all right now let's see let's go back to our index.js to our home page and let's see well the first thing we are going to start with will be some kind of header right because we need to have a logo and navigation and here maybe a card button so we can see selected products and so on so let's start with this I'll create a separate directory for our components let's do a components like this and well the first thing will be our header so let's do header dot JS and inside let's just do export default default function header and well it will return it will return a header HTML element yes and well what do we need inside header we need a logo so let's do let's put a link and it has been imported for me here if if it doesn't do it automatically for you you need to add this line we have a link and the link will be just to our home page so just slash and now let's see what should be name what should be the name of our store let's say just e-commerce e-commerce yes and okay we have a link inside our header what else do we need we need some kind of navigation and inside navigation and let's say we will have um let's say we'll have a link sorry it should be a link with and that will be to home we want the link to have to all products and we want to have a link to maybe categories cut the goris and then well we want also to have a link to and register login or maybe account let's just go to the account and and then the last item we need will be a shopping cart so let's put this for now for now let's put it here as the link and let's put cart and let's put zero inside yeah so now we need to have add some kind of links here so for home it will be just slash or all products it will be just let's say slash products F4 categories well it will be just categories categories and for account well let's say it will be a slash account for now and for cart it will be just a card yes and we have our header here so now let's use it inside our home page and let's put it maybe here header it has been imported yeah it's really ugly but now we can use our style component that we planned to use to style it a little a little bit right so I will open Terminal and I'll put a new tab here and here I will just do yarn add and let's do styled components all right now style components is installed so let's create a first style component maybe inside the head instead of doing this header we can create a style header so let's do a cons styled header equals and now to use style commands we will just do styled and yes let's import styled and here let's do header and then we do backticks and here a semicolon and inside back the XP will just build all of our CSS so and I want our header to be dark so I will do background color and let's do two to two yeah and now as you can see nothing can change because style header is not used so let's use it here instead instead of header so now as you can see we have some we have some bark dark color here but you can directly see that we have a small problem here and the problem is with this white padding here that we get from our body so we need to have some kind of a global Styles but instead of doing using those globals here I'm going to actually delete those two files let's delete them delete anyway we get an error because this file is still used inside here not here not inside index.js it's inside here here we have our um sorry Global CSS that is used so I'm going to remove it let's remove it and now we have only our app and but now to create Global Styles I will go to here inside my app and I will create the global Styles so let's do jazz const and Global styles Styles and let's call it this way and let's just use create Global style and as you can see it has been imported for me from style components and here let's just do backticks the same way and here inside for our CSS we can use selectors so I'm going to use body and here I'm going to do just padding zero yeah and now let's use our Global Styles so here we have our app but I will cut this thing I'll put parenthesis here I'll put it back and this thing I will put inside react fragment so this empty tank here I will put this thing inside and here I will put also our Global Styles and but I will call it with capital G and let's do Global Styles and now let's see if I refresh number change let's also remove a margin yeah and now we don't have any white spacing here so Global Styles worked all right so now let's go back to our header.js and let's see what's the next part we need to fix I guess we need to have some kind of um prettier logo here and we need to have a better font so I think for this for the font we can use Google fonts so let's go fonts Google and the fonts and now let's see let's maybe take Roboto why not and I'm going to use regular and well let's just grab the regular for now and I will use import and I'm going to just copy this style part and let's see let's go to our defaults inside the app.js and well I'm going to put my import here and inside body I will just do font family family or maybe I can just copy this part and I can put it here inside my body to use this robot effect so now let's see yeah the font looks much better let's go back to our header.js and let's see the next thing is uh actually um the logo we want to make it let's say white and we want to style this link but link is not a regular HTML element it's a component so to fix standing for this Let's do let's call it maybe logo and let's do equals and it will be styled here parenthesis and we'll put a link here and then backticks and here inside let's put color color white FFF and now let's see if this will worked instead of this link we'll put logo and let's see here yeah it's white so now we can add the like text decoration to be known and yeah it worked for our header let's maybe add the let's maybe add some spacing right so let's put padding and well I would like this to be centered so if it's this one it should be centered it should start maybe here and and somewhere here so we need a component that will just Center everything and I think I will put it as a separate component so here inside components I want the new file and I will this will be called let's call it Center dot Js and here as always export default function Center and it will return well it will return and just a regular HTML element it will be a div and inside we want to put all the children and we want to grab them from their properties let's do children and let's display them right but now we want to have we want to style this div so this way will be just to the const styled and it's called styled div equals and here styled in let's import this dot div backticks and here inside backticks let's just do let's say Max a wave will be let's say 800 pixels for now and let's add maybe some margin on the sides so let's do margin and zero on the top and the bottom and maybe 20 on the pixels on the sides and now let's use our style div here so let's do styled div yes and inside our header let's just use our styled div or sorry our Center so here inside let's put the Center Center yes and not like this like this because we want to put everything inside our Navigation logo and so on I will reform a distance inverter now let's see as you can see now um now we don't have our background anymore so that's weird let's see here inside how it looks like we have our header and looks like header doesn't have any color that's weird so we get this small error that after we refresh we don't have this CSS from those generated classes and we don't have any CSS styles that we created here so to fix it we need to go to next config and here we just need to add the compiler options so it's a compiler colon and let's put an object here and inside this object we'll just need to add the style components to true and that's basically it and now as you can see it works if I refresh well it still doesn't work but that's because I need to restart my environment here so let's do just yarn Dev again and now let's see now if I refresh everything works and if I keep reversing it still works so now let's go back to our header CSS header JS and let's continue with our header as you can see now this looks this looks better now it is centered well it looks like it's centered it's has this Max width of 800 pixels well but it's not the fully centered it has this modern 20 on the sides and instead we want to do margin margin out on the side so that's the margin uh here Auto and now let's see now it looks like this if I make it wider then it is Center so you can see that this div here inside is centered yeah so this works now but if I make it smaller well maybe let's add some padding on the sides so let's do 0 20 pixels so so we will have 20 pixels padding inside our Center component here Center and well as you can see now we have this 20 pixels here on the sides just to have like a small spacing on the on the sides right and it will be mostly for mobiles right now we have our e-commerce here let's go back to header.js so we have a logo and then we have our navigation but now I would like this navigation to be next to our logo and how can I do this well we can put those two things inside another component so let's create it maybe here and I will just call it a wrapper wrapper and let's just do const sorry not const just tied div backticks and here inside I will just put and display to be flex and now let's use our wrapper and here inside let's put our logo and navigation and it should be next to each other yes it is now I will just put the justify content let's do maybe a space between yeah so now we have e-commerce logo on the left side and the links on the right side so that's good we have started our logo link here and well it looks like it worked so let's see now now we need to add some styling on those links but before we do this let's add some more padding to our to the bottom and the top of our wrapper so we have some spacing here so let's do padding and well let's add the 30 pixels on the top and the bottom and zero on the sides yeah I think that's better maybe 20 will be enough yeah and now let's time our navigation links so we can call it styled link or we can call it just navigation link so let's call it navigation link it will be simpler and it will be a style link and backticks and now here inside hsd color white or maybe let's do a color and grayish so let's do AAA it will be gray and now instead of all the of all those links I will put another link yes and now as you can see those are gray let's add the um some let's remove text decoration turn on yeah and now I would like to add some spacing between those links and for this I will style this navigation so let's do a const and let's just call it styled nav every time I don't know how to call an element I will just add the style and then the name of the HTML element so let's do styled Dot and nav and tactics and let's see now instead of this HTML element now we can do styled NAB yes and here now let's do display of type Flex and now let's also add the small gap of let's say five pixels yeah maybe a little bit more let's do 10 yeah I think 10 is more better but I don't know if it's enough let's do 15. yeah that's much better and if I zoom out it looks like this in hundred percent Zoom but I will zoom in so you guys can see this better right so what should we have here underneath on the rest of our home page well I think that first I want to show like a featured product let's say MacBook Pro with some text here and then underneath I will show the the latest products this will be on the home page and then we will fix the rest of the pages so here one featured product and then underneath a list of latest products or new arrivals something like this so let's go back to our index.js and we have on the header here on our home page so the next component would be just a featured product so let's do new file and let's do featured dot JS export default function so it should be default function a featured featured and it will just return let's say for now it will be a div but here inside our div well inside this I want to have a header like H1 and it will say yeah well I will take the same title that they are using let's say Pro anywhere something like this and well then let's maybe add underneath a description of the product so for now we'll just put Laura mipsim but we will load the description for this product and well let's see I want to have this feature product here so let's maybe start displaying this inside our index.js let's just use featured featured yes so we have this Pro anywhere well I want to make this centered as well so let's uh inside this div let's put Center yes and let's put this inside so now it's centered well I would like to have dark background even on this featured product so instead of this div I will put a I will Define background so let's do BG equals it will be styled div but we need to import standard components or just stand let's import from style from style components that div backticks inside here let's put Maybe let's put it a background color let's do the same as the header 222 and let's use our background instead of this div background and well now it worked all right so now we probably need to fix this header right so instead of this H1 let's put let's call it title so that's the title uh title equals styled H1 and well inside here I want to get rid of the margins and I would font wave of normal so and now let's use this Title Here title let's see yeah it looks better but inside this background I will also add that all text colors inside should be white but yeah I think that's much better and I want to add some padding on the top and the bottom so on the top and the bottom I will add the 50 pixels and zero on the sides yeah so we have some spacing let's see let's zoom out yeah I think it looks fine but for this paragraph for the description I will type desk as description let's do style p and I want this to be a gray color so it's the color and let's do AAA and here is the instead of this P let's do desk for description yeah so now it's grayish and I want this to be smaller so let's do font size and let's do 0.8 Ram so it will be 20 smaller yeah I think this will work now I would like to have an image on the right side and I think as always I will use a some kind of wrapper here so let's define it here const wrapper or maybe let's call it the columns now let's do wrapper wrapper and it will be styled div and then let's put here inside it will be display off type let's do grid this time that's the grid and inside let's do grid template columns and let's just do one for R1 f r so we'll have two columns of the same size and here let's do now just wrapper and inside wrapper we'll have two columns so let's put two divs on the left side we'll have this title and description so let's put it inside the first div and on the second we'll put an image here that we don't have yet but well let's see how it looks like I think it looks just fine maybe we can add some spacing here more spacing so I will put actually here some gap of well at least 40 pixels just in case now on the right side I would like to have an MacBook image I think for now I will just copy paste an image URL that we have for here inside our admin I'll just take this one copy image address and then well let's go here and let's put an image here a source will be this and well it's almost okay so to to fix it we need to put the width and half of this image and so we can make a styled version of this or for our wrapper we can do something like this and we can do that all images here inside our wrapper should have a Max width of 100 and as you can see this worked well the only problem is that we have this white background on this MacBook but I have also other image that we can use so I will go to our here admin panel I will upload another image I have this MacBook Pro without any background color so I'm going to upload it Now it's uploaded I will copy the image address here and I will save it they will have it for later now let's go back to our front and here instead of this URL I'll put this new one and well now I think it's uh it looks much better maybe we could make this image a little bigger so let's see let's remove part of this description so we can make it smaller and now let's go back to our columns Let's see we have two columns of the same size let's instead do that the first will be 0.1 FR and the second will be 1.2 F4 so it will be bigger yeah and but now inside our columns and let's say inside our columns I would like to make this text here centered so let's see we can make it here let's say that for divs that we have inside wrapper all the devs should have align items Center well this didn't help because we would need to have a flex here as well so I will remove it for now and instead instead I will add a style the component for this column or maybe for those two continuous so it's the const colion equals style the div and here inside let's do that it will be just a display of a type flex and well let's save it for now let's add also online items Center and now let's see instead of those divs let's put column here and call him on the second div yeah now let's see now the problem is that we have um for the First Column because we are doing Flex it's putting those things next to each other and then to fix this I would deflex direction to column now it's uh now it's better but we actually don't need the flex Direction column either way would be just to put a separat div and let's put those two things here inside and we have the same thing and we get this it's centered vertically so we have the same spacing from the top and the bottom and it's centered according to this MacBook image yeah so this works uh really nice now the only thing we need here that is left is we need like read more and add the two card button so to fix it and well I would like to use the same color that we have here so I'm going to actually grab it from here yeah and well now let's see we need two buttons uh here inside our div and the first will be for read more and the second will be to add to cart so let's maybe put here just two buttons and first will be first will be read the read more read more and the second will be add to cart yeah so we have two buttons but we want to have stunning photos and I think that styling for those two is two buttons will be reused so maybe it will be better to Define this styling somewhere else inside the separate components so I think I will put it as a styled component inside components so as the uh the two card that or maybe not add the card but let's do primary button primary BTN the JS that's the export default and function and the primary BTN and it's a function let's do return and it will export a button sorry not like this it will be a button like this and inside we can have some children like text or something I have misspelled here it should be primary button so let's put children here and now we want to style this button so let's do const and let's just type the button equals styled let's import styles for from style components let's do this button and back ticks and let's see now I want to add the background color of this and now let's use this type button instead of button styled button and now let's use our primary button so here should be children primary button inside our um featured product here so let's do it here primary button and let's see here it's blue so it's better let's add some more styling here so we want this to be blue we want to remove the border so as the Border zero yeah that's better I want the text color to be white so let's do FFF yeah that's better and I want to have some run that the corners and a lot of padding so let's do padding and let's say it will be five on the top and the bottom and 15 on the sides and I want to rounded Corners so let's do border radius of let's say 5 pixels let's see yes that's uh that's much better now I would like this one to be bigger but not the primary button to be always bigger but just this button so a cool feature here is that we can add some property here and let's call this property size and let's put a large here we can do even just large like this and then inside primary button let's see here and we can grab here size as well and we can put this size here so we can do size equals size or we can just grab all the props like this rest of the props we can call it something else but I think rest sounds sounds nice and here let's just do rest like this and now we can use this property here inside our styling so to do this as you can see here in the documentation we need to do something like this so when we need to do props and then props primary or the name of the property so let's do a dollar let's put the curly brackets here and here inside so you can see we need to check for it will be a function so the props and then let's do if we have props size and let's check that props size is large so l and then and and here we just need to do CSS function from style components and let's import this way and backticks here as well and inside those backticks we just add some styling here so let's say we will have a bigger bigger text so let's open preview and let's do text size okay sorry it should be font size let's do 1.2 Ram and uh as you can see it's bigger we can even add bigger padding let's say we'll have 10 pixels on the top and the bottom and 20 on the sides let's see I don't know if this became bigger yes it did and so that is really nice now for all the buttons I want to have cursor of type pointer so I will have this hand and well I think this button looks nice now and now I would like to add standing on this read more so for this read more I would like this to be white so uh maybe let's go to our featured and here we have read more button and I want to create a white button component but maybe instead of creating different components for different buttons we can reuse this one primary button but we can for example rename it so I think we can rename it to just button and same for this for this file name here let's just call it button now it failed here because we need to rename it inside our Imports as well okay here is button let's call it button with uppercase B so it's not HTML element and here we'll just do button let's see now it works let's do the same here let's do button yes and this one doesn't have this size large but we can add it as well so let's do button size large yeah but now I want this to be to be not primary only this should be primary so I'm going to add the property primary on this one but I'm not on this one and then inside our button I will check for primary here primary property so let's do here as always props and let's check props primary and CSS backticks and inside the here inside backticks I'm going to put this background color now let's see here I think this worked and now this white color should go here inside yeah I think now it's uh now it's better now our patterns look better but I want to add other styling for this y button here and I will call it white so let's do props Arrow and let's do props white and CSS backticks and here inside backticks I'm going to put background color of white and the color of the text should be black so let's do zero zero zero yeah now let's add this white thing here so let's do white now let's see yeah it's white so I think it worked let's see props white yes and if we change it to something here this will be yellow then right so everything works but now I would like this one to be actually outline so I'm going to add this outline thing here and well now let's go to our button and then let's check here we have our white button but let's say it will be white only if and those background Colony color only if it's white and not outline so let's do not props outline yeah so now we have default styling I guess but now I will just copy this and I will do the same styling for white but with outline so no exclamation mark and now I'm going to the background color to transparent yeah background color transparent the color of the text to White yes and now I'm going to add also border color border let's do maybe one pixel solid and white and we have our outline yeah so now I like those buttons to be next to each other so I think we can make the First Column a little bit wider let's maybe do a 0.9 and 1 1.1 yeah so we have buttons next to each other but because this one has the Border it makes it bigger by one pixel on the top and the bottom and to fix it I'm going to add here box sizing border box now let's see if they are the same size I will zoom in or I would just check like inspect 44 and this one has 42 in half so box sizing border box didn't help instead I will just add the same border thing but on this one with this primary color so now those are the same size right but I want to add some spacing between those let's go to featured and let's see here here we have those two buttons and well I want to have some kind of wrapper for those buttons but we have rubber here for the columns maybe we should rename this wrapper to columns wrapper so let's put this here convince wrapper and here we will create a let's call them buttons wrapper buttons wrapper will be also a styled div and inside here backticks let's do display of flex and let's add a gap of five pixels yeah now let's use our um buttons wrapper yes and let's put two of our buttons inside yeah so we have our buttons here and well I think it looks fine so we have read more and add additive card maybe we can add an icon here to this additive card yeah I think that would be a cool thing so let's go to Hero icons and let's search for card I will go with solid maybe not let's do outline Let's uh take let's maybe see I will go with socket solid I would take this chord copy j6 and here inside add to card and put it like this and here I'll put this SVG let's see now how it looks like well it's too big so um let's go to button and let's say that all the buttons will have display of inline Flex inline Flex now let's see yeah that's a little better but we want the icon to be smaller right so let's put here that all svgs should be small so let's do half of let's say 10 pixels let's see yeah it's this small let's maybe increase it to 16 by default but for the for the XL version or large version let's put this SVG should have a half of 26 let's see and that's too big let's just do 20. let's see yeah I think that's much better now and we want to add some spacing here I think the easiest way would be just to add margin on the right side of 5 pixels let's see yeah I think this this will be and this will be enough maybe we can add more spacing here between the buttons so let's go to back to featured and then let's see and buttons wrapper let's maybe increase the Gap to 10 pixels yeah I think this will work well the buttons maybe don't need to be that big so I will remove this size large from them and let's see how they will look like now yeah I think this is fine I will just add some maybe spacing from the buttons wrapper so let's do margin top and Let's do let's do 15 pixels yeah and maybe more or less the 25 yeah I think this will be better then for this header here I would like this title to be bigger so let's do font size and let's do free Ram let's see here I think this this looks nice I will also check if this is centered here for our buttons so let's see inline Flex let's do online items Center yeah I don't know if this is better now let's see yeah now it's centered so that is really nice all right right now we have this featured product here and well as you can see it's just hard code that the content here and we want to load this content actually from a database right so let's go to our index.js to our home page where we use our featured product here and I think that would be nice to read this product from our database we previously created this product here is where MacBook 14 pro and here we have even our image here we have some description so maybe let's uh let's read it so we're here inside my home page I will export as well a function called get server side crops yes and now let's see here inside I would like to fetch this product from my database and then I would like to pass it this product information to this featured component but before we do this we need to connect to our database right and here inside e-commerce front project we don't have any Mongoose staff and models and stuff like this that we had here inside our e-commerce admin so basically we could just copy for example this Mongoose JS so we can grab the connection so I'm going to take it from here I will create the same directory as we had here lib so I'll do new directory lib and here inside let's create mongoose among Goose that is let's put this code here so we have our Mongoose connect and as you can see now we need also to install Mongoose here inside our e-commerce front as well so let's do yarn add Mongoose right now it's installed and Mongoose is installed so now we can connect to our database inside the apis and get server side props but now we need also our models right so let's see we have all of the models here product and the category and for now I'll just copy this product part and I'll create compo models as well here inside our e-commerce front so as the models and inside let's do product in the ideal scenario you would like to have this uh those models in a shared repository but for now I'm going to just copy paste it so I have my product here and then now I can use this model inside index.js here inside getzero side props so let's do something like this let's do const and I want to grab this specific product to do this I'm going to copy the ID of this product which is this and I'm going to assign it here to a constant MacBook or maybe let's call it featured featured product ID equals this and now let's do const product or maybe we can call it Twitter product doesn't really matter and let's grab it let's do product and let's do a find by ID and let's use our featured product ID we need to add an a weight here because this is an async function and then we need to add a thing here as well and because we are using database we need to put here Mongoose connect and I wait here as well right but now we have our product here and then we can return we can return props and then inside our props let's just put this product right now we can grab this product here let's do product and we will grab it as a property here and then let's just do a console log product here to see if this will work let's see console we get undefined let's see if I refresh we get a error on Monger connect and this is because as you can see here we are trying to use this mongodb URI that we don't have so let's add it here we need to have an.tnv file and so we can connect to our database and let's close pages here and I can see we have this mongodb URI so let's uh copy this and let's put it as well here now if I refresh we get a problem with our get server side drops so let's see I will go to index page and now the problem here it's also discussed on GitHub and stuff and if you pass something to props from get server side props to the props that will be passed to the page there are objects here needs to be compatible with jsons and the problem is that Mongoose models and Goose objects documents are not compatible to just serialize with Json so to fix it I'm going to do this trick and call the I'm going to stringify this stringify um sorry it should be like this it should be the product and now let's do Json and now let's do stringify and we are going to put our product here but this way if I refresh you can see that our product will be just a string here inside our console you can see that this is now a string and we don't want to have our product constant as a string so I'm going to parse it back from the stringify so let's do Json and let's do parts and I'm going to enclose it like this and now we have our product as an object so that's uh so that's okay now let's put let's remove this console log and let's pass our product here product equals product now inside featured we can grab this product here so the product and let's see maybe we can change this Pro anywhere to a title so let's do product title and let's see now we get this MacBook 14 pro and maybe we can update the title to to Pro like this so if I refresh here you should go to a smaller Pro yeah that's correct we can make this left column a little bit uh wider maybe we can do again 1 4 1fr or maybe even more here 1.1 and 0.9 here yeah and so we get the full title and for this description I can fix it as well for this description we can put the product and description description and yeah we'll get the description here for the read more I want to make it a link so let's see here we have button outline white read more let's see how our button looks like it's a styled button but here inside the our featured product we would like to actually use a link instead of a button so how can we do this we can do a stale Style Style link component with the same things as this button has and let's do this so well because this would be in easy solution so we want a styled link here or button link let's call it button link the link.js and here let's just export default button link and well it will just return stuff it will just return a link with all the props from here let's do props maybe we can sorry just do props like this and then it will do a link with all the props that we pass and it's a function that I forgot to put here all right but the thing is that I want to have the same stunning that we have on our button here all right so this style button thing I would like this to be uh I would like to this to be exported as well so I will add just an export here so this button file now exports both a button like this and it exports this style Button as well but the problem is uh this will always be a button and I don't want this style the button to be exported for a link because then it will be always a button so we need to find another way to grab all of this styling and and putting this somewhere else so both the button can use it and the button link so how can we do this I can show you the easy way of doing this I'm going to select everything that we have inside those backticks and I'm going to cut it out from here and I'm going to define a different constant here and this constant will be called a button Style and I'm going to do equals and here I'm going to use this CSS backticks yeah and here inside those backdicks I'm going to paste this everything that I copied so now I'm going to use this button Style to our style button so I'm going to put it like this and button a style so now our buttons work but I can also export this constant with our CSS to our for example button link so let's define our button link here and let's call it const styled link and it will be equals styled yes and let's call it as a function with a link inside because we want to style a link then backticks and here inside we can just reuse our style the button let's do styled button button and we need to import it from here sorry it should be button style button style yeah and now it's imported for me here if I save it and if I have changed because this is not used then yet so I'm going to put it here style the link yes and now inside our featured instead of doing button we can do a button link something like this now we get an error because we need to provide a graph here for our button link so let's do a craft empty string and now it works but now let's fix this graph so it will go somewhere let's say it will go to slash products slash and the ID of this product so let's do plus here product dot underscore ID all right let's see yeah now as you can see the URL is this product slash and then the ID right but I also want to get rid of this underline so let's go to maybe button here and let's do text decoration decoration none yeah works fine let's refresh we get a small error here let's see I receive the truth or non-billion attribute white and here we have received three for non-bullion attribute outline right let's go to our feature and let's see here we have outline here here we have white well we can change this to equal 1 and this equal white equals one to to disable this warning let's see if I refresh yeah then it's uh we don't have this warning anymore right so let's see now we have now we are done with our MacBook 14 pro we have this read more button we will fix products page later and we have this add to cart button that we're also going to fix later for now let's leave this a filtered product and let's focus on the next part which will be a new releases or recent products something like this so here inside our index.js I want to have like latest products so I'm going to create a new component here called the new products let's do new products sorry should be just new products dot JS and here as always just export default function new products and it will just return let's say it will be just a div with new products inside and let's put it inside our index.js page a new products yeah and the same way we did with our featured product we would like to have like all the recent products so let's see how our products are created here inside our e-commerce admin we have our product here and we have title description price images but we don't have the creation date so to fix it to our schema I'm going to add timestamps here to true and both here inside admin and inside our models here inside the e-commerce front I'm going to add timestamps to true and so our products will get the timestamp I'm going to update them first so let's go back here and let's say I'm going to go to every single product and I'm going just to save it and I know probably I need to restart my development here so let's do yarn Dev again and let's edit product and let's save it now and let's check if we will get this information inside our database so let's go to products and here inside let's scroll down we have this updated ad that we can reuse so I'm going to now update every product so we'll get some timestamps inside our database okay now I think I hit just save the the save button on every product now let's refresh it somewhere here inside our database so we can check if we have timestamps on our products yes we do so now we can sort products by last updated that um so let's go to our uh index.js page here and here we are fetching this featured product maybe we can rename those variables here so let's grab product and let's rename it to featured product and here we need to rename it as well featured product feature product and now we also want to grab recent products right so it's the const re or maybe new products let's do new products equals a weight and here we do product find and here here we can filter what kind of products we want to find it will be just empty object because we want to find all possible products then we have after the filter we have projection we don't need this I can just Skip and put an empty object but here I can add that and I can add sort maybe not here because they will be sorted after but right here first we have filter then we have production which means in what type of fields we want to select and let's say it will be no so by default null and it will just select all the fields all the data about each product but the third is options and here I think we can just do sort yes and we can tell what how we want to sort I'll put an object to Define our sorting and then well we can sort by updated ad which will be the timestamp about when this when every document has been updated the last time or we can maybe try to um sort by IDs so let's try let's put a string here underscore underscore ID and here minus one y minus one so it will be descending so we want the last product xiaomi phone as the first one here so now let's maybe try to pass those products as well we have featured product here and we want to pass new products as well so the new products and here again we need to do this Json thing so let's do Json parse inside here let's do Json stringify new products yes so we can grab new products here new products and let's do a console log to see how it looks like on the console log um new products but before we do this maybe let's add here also some more things like limit limit let's for the new products we want to only select the last 10 new products and we have only like I don't know eight products but just in case we will have more products in the future we are okay with only 10 the latest ones now let's see console here we have object object of new products so that is awesome and here as you can see the last one is actually xiaomi and we could sort by either updated that but then we would get an array of latest last updated products and but basically we want to only have the latest products so sorting by the with good enough all right so we have our new products so let's pass it to our newly created new products component here so let's do just products products equals and let's pass this new products right so this component is now empty but we can grab new products from here and then well now we can do something with this information with all this information that we have here so first we want to have like a grid of products so like squares with products right so we need some style components here I will start by putting maybe a products grid so the const as their products and grid equals styled let's import this from style components tied Diva yeah and backticks here and now let's just do display of type grid and let's put grid template columns let's say that we will have a um one of r one of r one of R so we'll be three products in each row right now let's try to put this products grid here and here inside we want to just um list those products so let's do a new products let's try to map Rhythm so it's the map and for each product we want to do parentheses here and here maybe for now let's just put the product title and see if this will work now this will not work because this can be undefined on the beginning so we need to check here first that way inside new products we have length and it's bigger than zero and then new products map let's see now you cannot read a reading length of undefined let's just add a question mark here now let's see okay now it looks like it's empty so we don't have any new products here let's see why let's go to ins index.js we don't get because it's called products the property is called products so let's rename this to products yeah and then now as you can see we get the products in three rows right so now um this grid should be centered and it should start somewhere here somewhere here inside let's put our Center thing and let's put our products inside yeah so now the economies start here and they will end here yeah so that's correct now each product should be a little bit prettier right so um let's maybe put it as a product box let's put it as a separate component instead of this div with product title let's put a product box component new file product box.js and let's do export default function and pro dact box yes and it will just return for now it will just return a div but here we will grab product information and well let's see we can pass the product like this let's see here and let's go to new products we can now reuse our product product box and we can pass the product like this product equals product or we can pass the product information like this product and the advantage will be that this way we can just grab all the properties separately here so we can the underscore ID title and description and the price and yeah it will be a little bit simpler if we spread all the properties inside new products like this right now let's see and let's go to new products let's go to our product box and well let's put back our uh title so we have Title Here now let's style this product box let's define const and let's define box equals it will be a styled component let's import the style it will be a div and well here inside for our box and let's maybe add the let's maybe add some add some color that's the background color and let's make it red for now now let's put this box here so we can see yeah and we have red boxes I want to make it actually white so let's do FFF so now those are white but the background I would like to be gray so light gray so to do this I will go to rjs and here for body I will put background color to be something like f 0 0 f 0. so yeah so now we have uh maybe I can make it a little bit dark let's do ee yeah I think this will work and now let's go back to our product box and well let's see those products are really next to each other so let's go to our new products and here we have products grid for products grid let's add some Gap here let's put gap of 20 pixels yeah so now we have some spacing between the products and well let's add also some padding from the top expanding top of 20 pixels as well yeah that's better let's go back to our product box and well let's add maybe let's start with a padding there's a padding 20 pixels yeah so we have the boxes like those for now and let's think here what do we want to show in each box we want to show an an image right so we can grab here images as well so let's do images yeah and I want to show the first image here so over here maybe let's do this EMG and therefore the source let's just show images of zero and I think this should work yeah except that those images will be huge so um let's see here inside this box let's do that images should have marks width of hundred percent and now it's fixed the only problem that the phone is really long here in half so uh we need to fix it by doing a Max have of um we need to Define have of let's say a 150 pixels yeah that is better so we have but now the text goes next to each next to the image and I think I would like to put this title under under the image under under this white box so we have this box and I will um I will actually rename it to white white box yes and I want the title to be outside of this white box so I'm going to put another component here let's put it here const and let's define it as a product wrapper wrapper equals styled div X and here inside the let's just put for now nothing and let's just use it here product wrapper and here inside we will put our white box but the title let's grab it from white box and let's put it outside underneath so now we have a title here underneath right now when it comes to this white box and let's fix some things I want white boxes to be the same have and here they are not here they are not as well so I'm going to do have and I will do a half of 150 pixels so now all white boxes are the same have now for the image we have a Max save of 150 pixels and we have this padding of 20 pixels maybe we can do just 10. yeah I think this this is not enough so I'm going to put it back to 20. now I would like those images to be centered so let's do let's try with text align Center yeah and this works but I think this MacBook should be pulled down a little bit so to fix it I'm going to do display of flex here and let's see yeah but now as you can see this MacBook looks really really weird so let's try to put this um image here that we have inside a div so I'm going to put this like this now this MacBook looks okay but it's not centered and to center it I will do align items center now let's see yes MacBook is centered but those images that are really narrow are not centered here vertically or sorry horizontally so um let's now hear the flex Direction sorry it's not Flex Direction it's Flex no it's not Lex it's um align content I think align content Center so no not align content justify content Center yeah now everything is centered right so we have this and now let's add some rounded corners on those white boxes so let's do border radius of let's do maybe 10 pixels yeah so we have rounded Corners here and then maybe we can put more rows here so let's go to new products and let's add one more column one FR so now we have four products in each row right let's go to product box and let's see we have Max wave here 200 percent um a Max have of 150 pixels I guess that's all right now let's fix all the things that Gore that go under under the image so um let's fix this product title let's define it maybe somewhere here let's do const title equals styled let's call the just style the div the title will be inside so D4 maybe you can do H2 right and here our style the H2 title will be just well what do we want here of this title we want to make it maybe bigger maybe wider I don't know but let's put this title here so maybe we can style it in a moment title title and let's put Title Here and now it's big because it's H2 but we can make it the font wave of normal and we can put the font size to just one ram yeah now it's better we only have some margins that we need to get rid of let's put more than zero so it's back to normal but now the thing is well I would like to add a small button here maybe here on the right side of this under the title and let me see if I zoom out it looks like this maybe I can make the titles a little bit uh smaller and the squares as well so I'm going to do 120 but not on the images on the images it doesn't really matter let's do have here 120 but the padding is well let's see let's change this to 100 as well okay it shouldn't be it should go like this so here for Max have we need to do 100 minus 20 on both sides so it will be 80 pixels yeah so now it looks better now let's see here we have our title let's make it smaller 0.9 Ram yeah and on the right side here under the title I would like to have a button added to cart button the same we had here all right so um here under this uh title let's put a button button and let's put add to cart yeah so we have a button here add the card but I want to add the same styling as we have here I'm going to put primary and yeah now it's uh better but maybe instead of this we can get only this card icon that would be cool right so this card icon we have it let's see we have it inside our filter product and it's this SVG but I think instead of instead of copy pasting we can save it inside our components let's put directory icons so we can reuse this icon that's the new file and let's say it will be uh card dot Js and here as well let's just do export default function cart icon maybe just let's do card and now I think it should be cart icon all right and even this should be renamed to a cart icon and here we will just return the thing that I copied here and maybe the class name should be editable so I'm going to cut it from here here we are going to grab a class name and but default will be this oops this so now class name here and I can reuse it here so let's put the card icon like this let's see if this works yes it does and now I want only the card icon here for our product box so now instead of add to cart I'm going to add a card icon yeah now let's see yes it worked so that is good right but now I would like also to have the price maybe on the left and then on the right it will be this button so um those three things the title price and the button should be inside the separate box uh like product info box so let's define it here const product let's just do a product info box equals styled and div and let's grab all of them here so let's do a product info box and let's put this thing here and we want to add the margin top of let's say 10 pixels so we have some small spacing yeah that's cool and now we want to put the price here right every price for us will be in US dollars so I'm going to put just dollar sign and then the price so let's do price let's see yeah but for this second row with the price and the button I want to style it differently so I'm going to call it the price row and it will be a styled div as well I'm going to add here backticks and let's do this play Flow display sorry Flex and let's put it now here for the price and the and the button so let's do and price row yeah and let's add one div for the price and the second div for our button right maybe we can put the button without this div so let's put it like this and now the first thing it will we want to Center this price so let's do align items align um items items Center so the price is centered and we want to do justify content space between so the button is on the right side and that's all right and now for the pricer let's add some small margin from the top as well let's say at least five pixels and well I think this this looks good now let's make the price a little a little bigger so let's do const a price equals uh let's do it as a style of the span or maybe install the div why not doesn't really matter and well for the price let's make it font size of the 1.5 gram so it will be big and let's make it bold so let's do a font wave of bone and now let's put this price inside our price component here so now the price is much bigger let me zoom in so you guys can see this better so we have something like this I think that the spacing between products is not big enough so I'm going to go back to new products and let's see here we have a gap of 20 that's maybe the 30. and that is bearable I think we need even more so let's do 40 yeah and I think that is where let's zoom out yeah I think that is better maybe we can go with smaller like 30. but we need to also do a padding top here to 30 as well and but now the title I think it should be a little bit closer to the product so let's go to product box let's see here price zero prac info let's change this 10 to just five yeah and even this price should go a little bit up so let's see price row margin top I just do two pixels should be enough yeah I think this will this will work maybe instead of making them primary we can make them a primary but outline so it's the primary outline and looks like we don't have styling for primary outline so let's fix it and here we have just for primary and but we need to fix that this primer is for primary and not props outline and let's add the same styling but for primary with outline and for primary outline this blue will be the the Border here we have this border but the background color will be transparent so let's add transparent here and the color of the text should be the same as this blue yeah so now it's it's like this maybe it will be better to put this add card text here so let's do add to cart and now it looks like this sometimes we don't have enough spacing to show all the information maybe we can decrease the Gap here let's go to new products let's put Gap back to 20 well not enough maybe let's get rid of this icon it will make a lot of more space here yeah and I think this looks this looks fine well maybe this blue is too bright and we could use something a little bit darker so well let's see for our button here we have this blue that is defined everywhere and maybe we should first Define it as a constant somewhere so we can reuse it later and so I think that we can add a maybe something here inside our lab and inside lib I will just put colors dot Js and here I will just do export a const primary and I will Define the primary color that we get inside this button so I'm going to copy this let's go to colors and let's put it here and now instead of doing copy pasting this color let's remove it from here and now let's try to put it with primary yeah let's see it has been imported for me and now I can just copy this and I can replace in every part where we are using this right so now everything is fine but now I can try with um darker color so let's try with oops I'm going to try with this purple-ish to see how it looks like I think it looks better let them out a little bit Yeah but it doesn't work here here I think we should have a white and white button just white button or maybe we can go with something like dark green so let me try with dark green let's do dark green let's see it doesn't really change that much here um well I think that for outline buttons I will make the Border wider so let's do a border one pixel we have it in three places so let's do a border two pixels here and now let's see now we have something like this maybe that's not good so I'm going to put it back and here for this feature I want to make it full white button so and this is primary I'm going to make I want to this to be white button yeah I think this looks uh better and now for doors buttons well I don't know but maybe let's try to make those bold so inside button let's add the font wave of bold yeah and I think this looks a little better but now we need this border to change it back to uh two pixels so the two pixels here now it looks like this maybe this to be close was too big and this looks fine and this I would like to be actually like semi bold but to fix this we need to go to our app and here we have our Roboto font and we are grabbing only the regular version of this font but I want to grab more sizes here we have a regular but I want to have Medium as well so I'm going to grab medium and let's grab bold as well so I'm going to grab this import and let's put it here yeah now let's go back here to our website and now we can use this 500 inside our Pro buttons let's see font wave we have ball Legend into 500 yeah and let's see if how it looks like with 400 not that much of a difference Let's see we have 400 500 and 700. maybe we can even use different font so let's search for let's maybe use this one Poppins so I'm going to grab the regular version the medium version and the Bold version yeah and now let's see here is the import but we don't need Roboto and just import this one Poppins let's put it back inside our index app.js here for our import we're going to import this one and let's just put pop-ins here now let's see if this will look better with pop-ins yeah I think I think it does now let's go back to our pattern and let's see for our button we have this 500 info actually to 400 well I don't see that much of a difference that's the 700 yes 700 is visible if I zoom in a lot let's see here 400 now there's no difference so I'm going to inspect this one and I think this is because all the map tones got this font family Ariel and I want to have my own so let's define it here font family and I'm going to use my Poppins Poppins and the default will be some serve yeah so now we have something like this add to cart I will Zoom it back and let's see how it looks with 400 no difference 500 well I don't see any differences between 400 and 500 but well let's leave it as it is so we have buttons like those I think they look okay so let's continue now and now I would like every box every product every image and the titles to be links to their products so let's go to product box and let's see I would like um the white box to be a link so let's change this div to be actually a link link from next link and then I need to pass to the white box the craft attribute and the graph attribute will Define it here I will Define the link or maybe the URL here and I to be slash product slash and plus underscore ID plus underscore ID so I can put it here let's put it as URL let's name it URL URL and let's see now also for the title let's see I will change it to a link link and let's see here where we have the title here I'm going to put ref and URL yeah and then we need to make it so it doesn't have this uh white and blue color so let's see here title a color let's do inherit and takes decoration To None yeah I think that's better maybe we could make the prices a little bit smaller so let's try with 500 yeah I think this will work but for Poppins maybe we can grab 700 as well we have 700 let's try with 700 and let's see how it looks like then it's super bold what else do we have we have 500 and 700 but we can add 600 as well maybe this will change something let's go to app and we have 500 and let's also add here 600 semicolon and let's use it inside our product box let's change this 700 to 600 well nothing really changed let's see what type of font is used here computed family we have Poppins let's do font wave 600 let's see here yeah yeah let's leave it as it is all right uh so now we can click on those images on those boxes and on the on the titles as well and uh well we have this added to cart button that we need to fix alongside with this one but before we fix those buttons we need to put a title here new arrivals or something like this that we forget about let's go here and let's put here an H2 and called the new array balls Ari Wells yeah and this looks nice I want this title to be almost the same as this one so let's see I will put here const title equals styled H2 and let's do on the size the B2 Ram so now let's put it here title should be capital T here I forgot yeah a new arrivals now the spacing here is too big so let's try with the margin 0 Let's see now we still have a lot of spacing from the grid padding top we have 30 pixels let's see now I think that is a little better but now let's put some margin on the on the title let's do that 30 pixels on the top 0 on the sides 20 on the bottom let's see yeah I think this is better let's try here font wave to be a 500 yeah I think here it works nice and let's see if I make it this more and let's see now 400 no no no difference so it's just a regular as the same as regular here or normal yeah so it doesn't do any difference here right so we have the title here and what should be the next part I think that the next part should be actually that we can add those products to our card that is empty right so let's do this now so I'm going to create a component called the cart context context.js because we need to have some kind of context for our card yes and here uh we will do const a card context equals create context and the create context as the let's import create context from react default will be here empty object but now here we want to create a function or a component for our context so let's do const or maybe let's do function instead a cart context provider and here we want to return and we want to return um card context and pro wider like this with children inside so let's do children here and what else do we need here and we want to export it and here we need to pass value and for us the value let's say will be for now just an empty object but later we will need to add this anyway so let's put it here let's put the US state so let's do cart products and Set Card products equals use state Rich fault will be empty array and now let's put it here cart products it's not as a single value let's put it as an object like this let's reformat this a little better and yeah this should work now inside our app let's um let's use our contacts here and so let's put a card context provider and let's put our component here inside and now let's let's see inside our page for example featured we want this button to add the add this product to our cart so um let's see here on our inside our featured file we want to inside feature component we want to add on click on this button on click and add featured to cart why not add featured featured two card and we will put it as a function here inside let the function add the feature to cart and well we need to use our context so let's use context and here we need card context I think we forgot to export it let's export it here as the card context yeah it has been imported for me here at the top so that is cool and we want to grab some information from cart context right we want to grab the only thing we can grab for now we are providing card products but we want also to have a set card products so let's provide this as well this way we can grab Set Card products and we can use it here so now let's use Set Card products and let's grab previous value and let's put it as a new array with all the previous products and we want to add the new ID of of this product so let's do just product dot underscore ID yeah and so now if I click here nothing will happen but we added this ID of this product to our context and basically we can go now to our card zero let's see header here and instead of card 0 we can print the number here so let's do a const card products from use context and here card context yes and here we will just do a cart products dot link yeah so now we have one here and if I click more here it will be more and now let's do the same for those buttons um but because this function will be reused uh let's see here feature for adding products I'm going to Define it here inside the card context so let's put a function here called add product the product and he will just take a product ID and the only thing we are going to do this to do it with it is Set Card products and the same that we did with our featured we will do we will return here a new array with all the previous plus the new product ID here and we need to pass it here to our provider yeah and now let's use it here inside featured we want to grab it from here and product so we can do just add product with only this product ID let's see if it still works yes it does but now we can use it as well inside our product box let's see here here we have this button let's do on click on click we want to do add product but we want to grab it from the context so as the const add product equals use context and here cart context yeah and now let's do here Arrow function add product with uh ID I will reformat this a little better and here we want to put product ID let's just underscore ID because we get the ID here right so if I click here we get even more products to our card right so now the next step will be to actually um fix this card page so for now we get 4 4. so let's go to pages and let's do new file and let's do a card that maybe with smaller core.js and here let's do export default function and let's do jazz card page and that's it let's do here return and here inside we will return almost the same thing we did with our index.js we are going to return header so let's uh do maybe first a react fragment and here let's do header so we have header the only problem is here as you can see we lost the count on the products so if we go here and then reload the context is empty so how can we fix it we can go to our um card context and let's see we have this state here and the problem is this problem is with all the react apps because when you add something here when you click here you have still the context and but when you reload the context is lost because you just reload to the page and JavaScript ripped is reloaded from zero but here we can actually use effect and we can do Arrow function here for now it will be an empty function here for the dependencies we will grab card products and inside we can tell what should be done when this changes and the thing is that when this changes I want to save it inside local storage first I want to check if we have something inside card products let's say let's check the length is bigger than zero and let's add the question mark here just in case then I will do local storage set item and cart and here I will just do Json stringify and our card products all right and here instead of this array here I will first do Json parse or empty array and here I will try to parse from local storage so let's do local storage and get item and here cart so now it looks a little bit odd so I'll try to put it like this so it will be easier to read now let's see local storage is not defined this is because when the next JS loads the page and tries to render it the server side we don't have the local storage so maybe we can just add this question mark let's see no this question mark will not help instead we can do something like this and we can take this from here maybe we can just Define local storage let's put local storage here const LS as local storage and here we will first check if type of window is different than undefined then we will return window then we will just return local storage otherwise we will just return an empty object now instead of local storage we'll do LS same here LS oops LS now if I refresh we get an error here let's see here we should be an question mark if the window is different than undefined then we can return local storage maybe we can do window.local storage on the rice empty let's see and let's get item is not a function so we can just add the question marks here and question mark here let's refresh this doesn't work work either so maybe here instead of this we can return null and this way we can check first here let's see if this will work no but we can do something like this now we have problem with this Json parse and so let's define it here above const default product default products equals and we want to take this and now let's do something like this if we have local storage then we are going to try to grab it otherwise there we are going to try to grab it and parse it otherwise so cool on empty array yeah so now we have problem with car products length and we don't use our default products here so let's put it here still problem with card products length so let's maybe put it and let's maybe use a question mark here right we are grabbing here default product maybe let's also add an empty array here as well so now if I refresh yeah I think now we now we got this I will add a few products five products to card if I refresh we get a small error because the server got zero but the client got four and the problem is when the next JS server loads the page it got zero but the content the client side got third got five and because of this mismatch and we get this error so how can we fix it we can maybe add another use effect that will run after we Mount this after we Mount this component so let's add an empty Arrow function here here no dependencies so it will be run after we load this load the app and let's see here let's put here the default will be just an empty empty array but here inside our use effect we will try to grab the products from local storage so let's do if we'll have LS and the ls get item of cart then what we will do then we will do Set Card products and here we want to parse it so let's do Json parse and here is LS get item cart all right let's see so now we have five everything works if I refresh I still get five if I got if I go here I still get five I can add some more like yeah now I have 13 now I have 16 so everything works so now let's go back to our card and well let's go to our card page here and now we want to display our products here right all right so here we want to show all the products we have in car inside our card so like a table with the product quantity product quantity and so on so we have all of our products that we added here so we can have them listed here all the ones that are inside our card so let's maybe put this as two boxes first with the products inside the cart and here maybe some small checkout box right so here we will need to actually have two boxes or two cards let's call them cards and the styling of the boxes should be the same as this product box that we have here so here as you can see we get this white box styling and basically we want something similar here inside our cart so let's see here first under this header we want to have a wrapper to have two columns so I'm going to define a wrapper here let's do const wrapper and or maybe let's call it the wrapper and it will be a style the as the styled div and it will be display of type let's do grid yeah and let's do a grid template columns and well the First Column should be much wider so as the 1.3 FR and the second let's do zero point seven FR something like this let's add a gap of at least 40 pixels yeah and now we can use um did here down there but let's also first do a box so a box will be styled div as well but we want the same styling that we get from product box so let's say let me grab the background color and we will need border radius of 10 as well so that's the Border radius of 10 pixels here and now we can put this columns wrapper and the two boxes here box one let's put one here and the box too so let's put two here now let's see what we got and we get two boxes yeah and then first this thing should be centered so let's import our our Center component and then this columns wrapper should go inside it now we want to have some spacing as well so as the margin top of at least 40 pixels as well yeah now let's add some padding inside the boxes right so inside each box let's put padding off let's say at least 30 pixels so now we have something like this I think this looks now good enough now on the left side we will print all the products that we have inside card and here inside two we will put the checkout buttons so inside two and we will put a header that will say let's say H2 your or maybe just order information something like this and then there will be some inputs and stuff and on the bottom we will have a button button that will just be continue to payment something like this and but this button should be actually a primary yeah I think this looks fine and I want this to be blocked so I'll add block here on this button let's add it here inside our buttons that let's do the same thing props props and props dot block the and CSS backticks and let's do here display um block yes and let's also add the with 100 yeah now it's better and I want this to be size of large so it's the size large so now it's bigger maybe it's even too big so I will change this to um make it like this I don't know maybe it doesn't need to be bigger I will remove this size large we have this just this continued the payment but maybe we I would like to make it the black as the black I don't think we have styling for black so I'm going to to edit the same thing we have for white but we will just change the white to black and black to white here we have outline version so let's do a color of the text should be black and the Border should be blank as well yeah and those two should be black all right so now let's see let's go back to card and instead of the primary we have only black all right so now we have something like this all right and here in between we'll have some inputs and that should do let's put maybe one input here in between input for placeholder of address and the input for um placeholder of address too yeah why not and we can style it later for now let's just release our a card right so let's go here and here we want to grab all the products so let's grab the products or I think it's called card products from use context a card context yeah so now let's here check if we have if card products is is if we don't have any length a change if we don't have any length then let's say it will say your card is empty that's it and the second box so the there are the Box on the right side should be visible only if we have something some length inside the card product so if we have products inside our cart so if I do length and let's do here bang bang so this will be converted to billion and parenthesis and inside let's put this second box right so now I can probably go to inspect and see how this will look like let's go to up and let's go to local storage and let's remove products from cart if I refresh your card is empty right and I think that's that's good let's add a product maybe this laptop here so we have something inside our card now here let's check if we have a card products length that is bigger than zero and parenthesis maybe not parenthesis and let's do chord uh or maybe let's do parenthesis as the parenthesis and here let's put um react fragment let's put H2 first and let's say it will say a card so we should have cards here yes we do now under the card we want to look through the product so let's do card products map and for each product well in general this will be only the product ID so we should rename it to product ID because we push only product IDs right right so that is a problem I can print product ID but then we have only IDs here and the thing is we don't want to put every information about every product to our cart instead we want to grab those IDs here and we want to fetch the information about our products so here let's do use context sorry not to use context yes effect and let's put empty Arrow function and here as dependency I will put card products all right and here I will check if we have a card products length bigger than zero and then I'm going to check to grab the information about our products and then I'm going to put it inside state so let's put the products and set products equals use State default will be empty array right and now I want to use API here so I need an API endpoint let's do a new file here inside our Pages API and let's call this one the card.js here as always just export default function I think it should be async so let's put a sync function here and here let's just name it handle all handle Handler doesn't really matter first we need to connect to our database always the await Mongoose connect yes then we want to grab the information so let's put let's grab request and response params and well let's say that inside the request we will have we will have an array of IDs so let's do a request body and IDs and the const like this equals this and now let's just do response Json and here let's adjust the await product product find and we want to find where ID is inside or where it is so that's that should be it so now let's go back to our card page and here let's just do axios by the way I don't think we have access installed here so let's do just yarn add axios so let's do axios let's import it let's see axios is it imported yes it is now as the axios get slash API slash card and we want to send the IDS right so it shouldn't be get it should be post because we want to send the body and the body will be IDs and then the those IDs that we have here right and then we get all the information about our products or first we get actually response here uh so we can do set products and we can do response data yeah and that should work so now we can list our products so here instead of checking card products we'll just check for products and then we will list the those products as product because we'll have full info about each product and let's do product title now let's see and we get the title of our product instead of only the ID right but I have this MSI laptop here and I will add two more so now we have three of those and so that's all right so I should here on the right side display how many of those IDs we have here so let's say that I will add cool on here and now after the coulon I want to display the number of how many so we need to check for card products for product ID from this product so let's do card products filter where ID will be the same as product dot underscore ID and then let's just print the link so now I have pre but I can add some more products let's say I will get this headset so now I have one headset and this MSI laptop times three right but it will be better to display it better so I'll put this here this TV will end here and now I would also like to create a separate style component for this so this will be actually nice to show as the as a table right so let's print a table here and inside the head will will have one table row and we will have a product and we will have um quantity quantity and we will have let's enable calculate the price as well and then let's put tea body here and inside the body we want to look through all those products but yeah all those products so let's put it here and I will just add one more indentation here but instead of those H2 I will put instead of this it will we will have table row and table cell will be just this card can be moved actually above the table let's see here about the table and or above this your card is empty so we understand we have this table and here we are checking if we have any products well I'm not sure if we can if we need to check it here let's check it for the whole table here above the table let's check if we have products and this thing sorry not this thing this thing needs to be put here after the table now we can put more indentation inside this table so it will look better now we have this we look through products here we should Loop it inside tea body here add some indentation here I will remove this table row mesh inside this div for each product we'll put put table row and first we will do product title so let's put it inside the first table cell the second will be as you can see quantity so we can just put this thing inside and the second the third will be price let's put price for now so let's see um looks like it kind of worked except that the styling is a little bit off but other than that I think it looks fine for now here it would be nice to have some basic styling for our table so let's Maybe Define it inside components let's do new file and let's do styled let's we will just do stable that JS and let's do export export default or maybe let's do export default default function table and we will just grab all the children here and we want to have as tight component for the table let's do const style the table equals style and it will be a styled table right and now here inside let's just use it styled table we've um with all the properties and all the children maybe let's instead of doing children like this let's do props props and let's pass them here props yeah let's close this and this should work we just need a return here yeah and for our style table let's make it wave of 100 100 percent and now let's try to use it let's go to Pages card and here let's use table with capital T now let's see yes it's hundred percent let's go back to our table and let's see we have wave of hundred percent let's add also that th should be and text align left yeah so it's line to left and I want this to make it in grayish and uppercase so the text transform uppercase and I want the color to be let's say a yeah so we have now something like this I don't need this to be bold so let's do font wave of let's say normal let's see how it looks like something like this I want this to be smaller font size let's do 0.7 Ram something like this product yeah I think this will work maybe we can make it 500 let's see I don't know if this change anything 600 yeah maybe we can make it even lighter let's do CCC yeah I think we will go with this all right so we have product maybe here instead of saying just product we can display an image as well right so uh here on the beginning here we have product and here we are displaying the product title but maybe I would like to display an image as well so it's the image and the source will be product images of zero and now we should get some huge images but to style this a little bit I will put the I will start this cell for example let's say and I will call this cell product infoso so let's define it here const product info cell and it will be a styled TD and well let's say that images inside should have Max width of Max width of 100 percent now let's use it product info cell let's use it here so now the images look a little better but I will just also make it a let's do Max wave will be 150 pixels and Max have will be the same so now I think that is better I think we may be nicer to put every image inside the box or something like this so uh let's see here we have this image and maybe we'll be better to put a separate start component for this as the const and let's call it product image product image box equals styled div and it should be product product image box type div and I want this to be maxed with of let's say 150 and by Max have of 150 as well I want to add some small padding of 10 pixels and I want the background color to be a light gray so let's say it will be F0 f0f0 and I want rounded Corners so let's double radius of 10 pixels and well let's test it product info box product image box and let's see where we have our image here let's put product in image box and let's put the image inside and let's see now it looks like this maybe instead of gray because the images have this white backgrounds we can make it white but we will add some box Shadow instead that's the Box shadow 0 0 10 pixels and let's do black shadow to see how it looks like black is too dark so let's do rgba here I would do 0 0 and 0.1 10 of black I don't know maybe we can just do a small border instead solid rgba and let's do one one tenth of blank let's see yeah I think this looks better and now this product image box I want this to be the image to be centered right so let's do a display of flex online item Center and justify content Center as well yeah and then we can grab the image from here and we can put it here and well let's say that Max wave will be 130 same for Max have 130 so we have something like this but the width and have here will be fixed so let's do with 150 150 so the boxes will have the same size I think we can make them smaller so let's do them 100 by 100 but after removing the padding those need to be 80 the images needs to be 80 by 80. and then we have something like this so that is better but now we have this product info cell and I think we can add some spacing in the cells so let's put padding and I will put 10 pixels on the top and the bottom and zero on the sides so now let's see here now we have some small spacing maybe we can add the Border as well so that's the Border I will do border top one pixel solid and let's do rgba I want to do RGB a I want to do zero zero zero and ten percent of black yeah so we have something like this but we have it only on the product info cell and but actually I think this border should be on the table as the default so let's do TD and let's put this table uh let's put it here yeah so we have this border we have quantity and we need to now calculate price as well so calculating price will be really easy let's go to our card and the price is actually only the quantity that we have here times the price of a product so in general we can do just quantity so this this times and now the pro duct dot price so let's see yeah it worked and we just need to add dollar sign on the beginning so it will be in dollars right now it would be nice to have a plus and minus buttons we can increase and decrease quantities on the on our products so let's see here inside our card component we have our cart page here and let's scroll down to our quantity here as we can see we have price and here I guess we have a quantity all right so now let's add some buttons and before the quantity let's add a minus button so I will use our button component it will be with a minus label let's add another button component button component with a plus button let's see how it looks well it looks fine for now but for our quantity I would like to have some spacing here inside so I will add some padding and let's define quantity label here so that the const quantity quantity label label it will be as tied let's say span and let's add a styling of let's say just some padding zero on the top and the bottom but let's do three pixels on the sides so now I will use it and now let's do a quantity label and let's put this inside so we can have some spacing here so we have some small spacing now we need to fix so those buttons will work and so I will add functions on on both of those first let's maybe do the plus it will be easier so let's do on click and let's put a function here let's call this function more or I would do Arrow functions like this and now let's do more of this product this will be the name of the function and we are going to pass a product ID so we'll just pass this ID it's the same as the product ID no sorry I cannot use this ID because it's inside our filter I need to use this product on dot underscore ID and I will put this on click in a separate line yeah and now this should work I need to just add this function somewhere here at the top so it's the function inside our component here more of this product and we get product ID I can just call it idy why not and if we want more of this product with this ID we need to just add a product so as you remember inside here card context we are providing also this add product that we have here so um maybe we can just use it so let's grab it from here add product and that just is it here add product and of this ID all right now let's see if I click plus you can see it increases yeah so this works minus doesn't work yet but I will fix it now and as you can see the price total price increases as well so that's cool and the card here also increases so now let's fix the minus button let's see here button let's do on click and then let's do Arrow function and let's call our function less of uh this or maybe yeah less of this product and let's pass our product dot underscore ID I put it in a separate line like this and yeah this should this should work now let's define this function here somewhere on the top and the function less of this product we get an ID and now we want to remove a product let's see if we have such function inside our card context Let's see we have ADD product and we don't have any removed products so let's do function remove product and let's see if you want to remove a product with a specific product ID what do we need to do and we need to update our card products so we need to use the Set Card products so let's do this Set Card products and now and we will get the previous value of our card products and we will get it here as previous and now let's see we want to grab this this is an array of IDs and we want to remove this product let's say we will do this only once so in case there are more we will remove only one ID so first let's find the I the ID the position of the ID so let's see we can do this by checking previous that's fine index off insert element will be product ID and this way inside this position we will have the position inside the array where our product ID is located so now let's see if position is different than -1 so we know it exists we will just remove it so let's do previous and we can just filter and let's filter the first inside our callback device will be value but the second will be index and now we can check that index is different than the position sorry post position here and this will be the result so we can just do return here so it will be set to our card products otherwise if it doesn't exist if a product ID doesn't exist inside our card products what do we want to do let's just return the previous value and then that's it now let's provide this function here so I'll add a comma remove product and now let's see and let's go to our cart page and let's grab remove product yeah and now let's use this function here less of this product with this ID and now let's see can I remove yeah everything works so that's uh perfect now the next thing we need to have here is to have like the last line here and I want to see the total price of everything I have in my shopping cart so let's see and we have all those products here wave IDs we have only IDs here and but then we have here the prices and the names of the products so using this as amounts we can grab prices we can calculate total so let's do something like this let's do let total equals zero and now I want to do something like this four inch product let's do it const product ID of card products and for each product ID I want to grab the price from the products so let's do const price equals and the price is inside our products but first we need to inside this products fine a specific product of this ID so I'll do this let's check that and let's check that product dot underscore ID will be the same as our product ID and then if we find a product we will just do that price so we'll grab the price in case this doesn't this price doesn't exist I will just in case add this question mark and I will add default zero just in case so we have price of this product and we'll just add price to the total so it's the total plus equals price all right now let's try to print this total somewhere here inside this table here we are looping through the products let's add another row here and in this last row I will just add um let's see we should have three columns I will just put two empty cells and in the last cell I will just put total and let's see if this will work and looks like it works so I'm going just to add a dollar sign here and well looks like it works if I remove the last product the last quantity here it has been removed now yeah everything works right so I think we are done with this part now let's fix and this part so we have order information here and we have just two a simple inputs here maybe we can create a predator inputs the same way we did with button so I'm going to create a component here inside components and let's do just input dot JS yeah and here as always let's do export default function and let's do just input with capital i and it will just return an input with all the props so let's grab the props from here and let's pass them here so we have all of our props now and we want to let's use it maybe let's use it so go back to our card and let's use input this input yeah it should be just input like this capital I yeah and now let's see if this has been imported for me yes so now everything just still works now let's go to our input and let's style it a little bit so let's do const and const and let's call this one styled styled input equals styled let's import this one from style components start input and now for styling and let's see what we want to add let's add some small border maybe and let's make it full wave so let's do with a hundred percent and let's add some padding of 5 pixels and now we can use it here so we can see the previous type input yes so now it looks like this let's add some more in bottom margin bottom of 5 pixels yeah and for the Border that's the Border one pixel solid and let's do light gray so let's do a a that's too dark let's do CCC yeah that's better let's run that corner so let's do border radius of let's say maybe five pixel yeah that is really good now let's see I need to add a box sizing border box yeah so the width will be correct and now I think everything is correct so now let's go back to our card page and to the bottom and let's see what type of uh of of inputs we need first we need name so let's do a name here name yeah then we will need email as well so let's do email and then I will do also as the city and we will need also postal code so the postal code yeah another one will be street address Street address and the country yeah so we will know where to send a where to send the package right I would also like to put the city and postal code next to each other so I'll create a component quickly somewhere here let's call this const oops const I will call it just City holder and let's do styled div and it will be just display flex and I will add a gap of 5 pixels and that's it and I will use this city holder here let's put City holder and inside let's put City and postal code yeah so we have City and postal code here all right now we need some state for those inputs so let's scroll up and let's see where our components start here we need to add state for let's see name set name your state default will be empty string same thing for email set email default will be a use State empty string and let's see then we need City set City default will be your state and empty string then we have postal code as the postal code same thing and street address street address and this is the set rate address equals your state and default empty string and the last one will be country so the const not count sorry country country set a country default will be used as state and empty string now we can use those State variables down here so let's do this so here first value equals name and on change we will do grab event and we will do set name of event Target value same thing here maybe I can just grab both value and and on change so let's do so let's put it here let's put it here let's put it here and I forgot about the space here and here as well so let's put it also here and here now we just need to we have copy paste so everything is in sync so now let's fix it instead of uh naming we need to do email here and here we will need set email here we need the city so the city and here on change and set City here we have postal code so let's do postal code and the on change set postal code here we have street address so let's do street address and on change let's do set street address here we go and Country so the country and on change set country and that's it I will just make it more readable let's add enter um maybe before the placeholder placeholder placeholder let's add enter here and yeah now let's go to grab every value let's put enter here as well and let's do the same on change on change let's add enter and that should work right so now we have working inputs so we can basically fix the continue to payment and button all right so let's see if I remove this it's empty your cart is empty but we see still the we still see this product let's maybe fix this before we go further so we are looping through the products we are looping through the products and we have products from our uh here from our axios request so to get rid of those here we are not getting ring of those if it's if card products is bigger than zero let's add else here else if let's say if card products length is zero then we want to update this and we want to set the adjuster and empty array so now it's empty let's quickly add some products so the this one this one this one yeah so we have some products here and now I will maybe get rid of this one so you have only two products and now let's see let's um let's fix this button continue to payment so let's scroll down here here we have our button let's add on click and then click we want to and we want to go to a stripe payment so to fix a strike payment we will not do on click but instead I will make it type of submit and I will put this form inside a form here so I will put a regular form element it will be at a method with as post and action will be actually just let's say it will go to slash API slash checkout yeah and I need to put those inputs inside and the button as well so let's put it like this and I will put identity more so it will be inside and now let's see we have a type and placeholder and stuff but we don't have a name on those input so I'm going to grab the value on every input and see one more and I'm going to copy what's inside the value now I will hit enter I'll put name and for the name I will just paste what was what I copied so now we have for placeholder name we have name of this input will be just name for the email it will be an email with lowercase e and City and so on and postal code right so we can send it to our API checkup so I need to create this endpoint and I know you guys can wonder why we are sending it this way with as a regular form and not with uh not with the axios request but it would be just easier to do this this way all right so now we are sending we will send to API checkout uh the name the email City and stuff like this but we are not sending we will not send the information of our products or the most important what we have inside our card so let's see how here we have car products and we need to send it as well inside our form so to do this I will just add and empty input and here and I will make it hidden so as the input type hidden and the value will be let's say it will be just the card products but this is an array and I want the array of IDs so I will add comma a comma sign between IDs see and now let's save it and let's see if it's inside here yeah we have type hidden value and we have those IDs and let's say we have two different IDs if I add one more here we will have a two of the same yes so we have here we have eight zero you have 62 and here we have another 62. all right now we just need to add a name here for this input as well let's call it name and let's call it products input this in a separate line and this as well and now we can fix our API checkup so here inside Pages API and let's see inside Pages API we have cart and it just returns products let's create a new file and let's call it the checkout.js and let's do just export default function Handler yeah and that's always inside Hunter we'll get a request and response right so now the first thing is we want to check if and the request method is different than post then we will just respond with an error let's say should be a post request yeah and return here so nothing more will happen now um if you have something let's grab everything so as the const and let's grab Let's see we will need the name email and so on so let's do name email and we will need the city we will need postal code and we will need the street address let's do street address I think that's how we call it there and Country yeah and we are going to grab it from request body right so we get all this and we maybe put half half of it into a new line let's put it maybe like this right and we have everything except I forgot that we need also products here inside products we just have an uh string of IDs separated by a comma so now let's maybe get products like this so the const products IDs equals let's do just products and let's do split by a comma right so now if we have several if we have duplicates that means that we want more of this product so if we have two IDs but those are the same it means that we want to have two of those product two items right but I want also to find unique ideas so the const unique like this and to find the unique ideas in this array we will just do first put the asset new set and let's put products IDs here inside and to convert set to an array and we just do spread operator to a new array like this and now when we have unique IDs we can grab products information so the const const and that's the that's the products infos equals and now we need to connect to our manga database and we need to use product model so let's connect the our database maybe here let's do mongoose connect yeah and let's add a weight here and we need to add export default async function and now let's see we are connected to the database so we can use product our product model imported yes let's do find and we want to find where underscore ID is inside the unique IDs so let's do just maybe unique IDs and I think it should be work like this right and we need to add a weight here as well because it's a query to add to our database and and now we can we have our products the IDS of the products we have inside our cart we have information about those products so we have the prices and stuff like this so now we can prepare data we can we need to send it to our stripe so let's do let's prepare maybe let's do something in this line items line items so everything we every product we are sending let's do let line items it will be empty array and now for each of the unique ID so let's do four uh let's do const ID off um unique IDs unique IDs and maybe let's call this product ID first we want to for every product inside product ID inside unique and this first we want to grab product information so let's do a const maybe just let's do info equals and inside products infos we want to find a specific product where the product product underscore ID and just in case I will do two string because this can be an object of an ID I want to check that product underscore ID is the same as product ID that's that way I will get the information about the product and now I will where when I have the info I can now add the stuff to line items so the online items push and here we will need to push some information about the product so I have info from the database about this product maybe let's call this product info but I need also quantity cost quantity and to have quantity of this product ID I just need to check how many times it occurs inside products so let's do um Let's Do products products and let's do filter and let's check that ID inside products needs to be the same as product ID we have inside our Loop and then when we get only the IDS from product with this specific product ID we will check the length here and I will just add a question mark just in case and default will be zero just in case now I will just check if quantity is bigger than zero and if it is over there I'll put this inside and now let's see I will make here let's check that quantity is bigger than zero and we have product info and when we have those two we can push information to our nine items you can call it something else I think it can be like a line item the same way we have it here nine item all right and that's how they call it on stripe so for here we need to push the quantity with the it's the same name and then we need to send also an object of price uh price data and here inside we need to put the currency so let's put currency for us it will be always US Dollars and then we need to put the product and data and for our product data we will put only the name of our product so let's do Name colon and product info uh product info that name and this amount here let's do unit unit amount and for the amount we will just take the quantity times the price of our product so the product info dot price right and that should work now I will just try to do and see if it works so let's do response Json and let's print our line items 9 items like this and nine items yes and now let's check it if I click continue to payment the products filter is not the function let's see um products filter is not a function all right it should maybe products because products is a string instead I should use products like this yeah so now let's refresh should be a post request okay let's go back let's hit continue to payment and now we have some data here right so let's see we have nine items we have two lines we have two products let's see the product data looks like it's empty and it shouldn't be let's see it should be product data we should have name but maybe it's let's see how it's called it should be called title so let's go back to checkout instead of product info name that's the title now I will go back and hit continue to payment again yeah so now everything works and let's see unit amount four seven nine eight four seven nine eight because we have two of those if I change to one it should be two three nine nine yeah and one quantity so now everything is correct here I can go back to my shopping cart and let's see now it will be good to probably save it as an order inside our database so we need the model folders so I will do a new file let's call it order dot JS yeah and now as always and the same way we did with our product and we need first our schema so let's do const order schema schema equals and the same way we did with product we just do a new schema new schema yeah from Mongoose it will be an object and now let's see what do we need here inside when you want to put line items right so as the line and that's called maybe yeah nine items and what will be it will be just let's call just it would be an object right for now and then we need the beside products we need all the information from here so name immensity and stuff like this so the name CT sorry I forgot that we need to put as a string same here City string and then we need the email email string City postal code string and what else street address street address string and then country country string yeah and we want to probably know if it's paid or not so is the paid I will put that this is type of Boolean and the default or maybe we don't need the default let's just put that it's a Boolean and that's it now let's use our order schema let's go to back to checkout and here that's the Jazz instead of this response Json we will do first and we want to create an order so let's do order order sorry we are we were not done with our model here we have only schema and nothing exported so uh first let's create a model so let's do const order equals model model yeah and it could be with the name of the order with order schema but in case we have it already inside models we will check if we have order otherwise we will create it and let's export it now we can use it here or there yes let's do create and we will just put all the information here so let's do line items and we want to have also name email and the City City postal code and what else street address street address and the country and I think that's all yeah of course paid paid will be just false for now and this is an async function so we need to add a weight here and we can just grab our order document as a result so we'll get an ID right so we have this uh now what else do we need we created an order we have a information prepare information for stripe and so now let's see I have created a test account for on stripe and but we will also need the stripe lib here so I will go here and I will do yarn add the stripe so it will be installed add stripe now okay yarn add stripe is done so now let's import stripe here so as the const maybe just to require a stripe like this but this will return a function I can show you here yarn as the stripe and then this is how we need to use it so require stripe and we need a secret key passed here so I will just copy paste it here and let's grab our secret key so I will go to here is my test e-commerce I will go to developers let's grab API Keys here is secret key I will change it later so you guys cannot use it and of course my test Ecommerce is with test mode enabled and I have copied this secret key I think will be much nicer to have it somewhere here in our DOT EnV so let's put it stripe stripe uh secret key equals this yeah and maybe we will need a public key as well so I will add it in as well so let's do stripe stripe underscore public key equals this yeah so we have it now let's go back to our checkout and let's see if we need this a secret key so let's use process dot in V Dot stripe secret key so we have it and let's see now we can use our stripe to create a payment so let's scroll down here and let's continue so let's do stripe and we can do here session and just maybe not Stripes right check out check out check out yeah and then sessions yes and then create right and here we have power arms and for our parents will be line items that we have prepared before mode will be payment so let's do it just payment and now we will need also customer email so it's the customer customer email and because this is required and we have it inside email then we need also uh two URLs and the first one will be success URL and this is the URL the user will be redirected after everything is correct so for now it's just localhost 3001 for us but I think I can put it as an environment variable as well so let's do just URL and let's do just for now HTTP localhost 3001 and after maybe I can call it a public Ural and after we are publishing this Universal or summer you need to change it to Universal URL but for now it will be just public URL localhost free download one for us so let's do here process and process dot environment Dot Public URL and I will add here that we will go to we'll go to slash let's say it will go to slash cart slash cart but with information like success equals to True something like this and we need also cancel URL and it will be the same but with uh just canceled equals true yeah this should work or maybe we can just do one here and one here it would be simpler right and one last thing I need to I want to have will be metadata and the metadata will be just the extra data we want to send and it's just one thing here I want to pass order ID so let's do a order document order document underscore ID and just in case I will just do on this ID I will do to string because this will be actually an object and I think that's it um now this is and I think so we need to do a weight here and the result of it we can just call it session for now session and the thing now we just want to do um redirect to session URL so we can do either response redirect redirect like this or or we can just change it back to just response Json and do this and the default way so let's just repair response with Json and let's do session dot URL yeah and now let's see what will happen if I click continue to payment invalid email address we this is an error from stripe so I need to fill some info here as the example.com city Stockholm right and hit continue to payment and now I get this URL let's see if I open it I see what's to be paid but as you can see it's 32 dollars that's 98 so something is wrong let's go back here it should be 32.98 the dollars not just 32 and 98 cents so we need to do times 100 on the price here so I do times 100 so this should be actually with cents in cents right and now for our continue to payment I don't want this to go to through this checkout instead I want to grab this URL first so let's go to API not API card just do a cart component card page here and instead of doing this form we can just call it manually with our button so let's remove this form and we don't need this time submit we will just do on click and let's say that the function name will be called do payment do payment or maybe go to payment and go to go to payment yeah now I will put this into separate line same here same here and we can remove one indentation here so let's do like this and let's see we need to Define this function here on the top let's see here we have some functions let's do function and go to payment and then we just want to do axios and we want to call slash API slash checkout check out and with all the data that we will do the same way we would do with having a form here so we need name email stuff like this and we want to have a products as products like this like this joint with join with a comma but we can just compute it inside the function so we don't need it here let's scroll up here and let's see first let's send everything from here from the form so let's do name email and we need the city city postal code and we need so also C Street address street address and Country and I think that's a ring two four six one two three four five six now we need products um but we need products from card products so I think I would just send us card products and inside our backend inside our checkout and we will just fix it so it it doesn't come with commas it just comes as in the right all right so let's go here on the top and here we'll get card products yeah and the card products will be the same as products IDs so let's just put it here we don't need to do any splitting it should just work and let's go back to our Pages card it's an access request but it should be a post request and yeah now we'll go away here and I think here and then we will grab a response or the response response and with this response and we will get information so let's do now if we have response data let's see what's what was it it was URL all right so I've seen if we have a inside response data we have URL then we want to go to this URL and this is a URL outside of our react app so we will just do window location equals this URL so let's do and this yeah and now it should work so let's see I will fill this form now I will click continue to payment and it redirected me to this test to this test and I can use my card or something like this and then I click pay there is a test there are test credit cards we can use let's see here let's go to overview successful payment yes let's copy let's put this card here and if I click pay everything is fine and it redirected me to my success URL and with this card on this card page we get the success equals one so um here let's see we have our card and products and stuff like this and but before we will return all of this let's check if we have the success one so maybe I will do something like this if we have window location and we will check that graph and have index or maybe includes it includes success then I will just do something else I will return and we'll return a header and return empty react fragment with header yes and let's see what else do we have we have Center columns wrapper and let's do Center and I will just put one box inside and I will just put H1 saying your payment your payment is successful or maybe your thanks for your order thanks for your order and let's add more text here we will email you you when your order will be sent yeah we'll order you the details it doesn't remember so now let's see thanks for your order we have some information here so that is cool maybe we can also put this columns wrapper and let's put only one box here inside yeah thanks for your order we will email you when your order will be send and so we have this so now if I go to my stripe and I will go to payments I can see that this last payment um it's 3298. it's paid but I would like to have this information that it's paid inside my database so I don't need to like check for my orders everything I have inside my orders database and check okay and the ID of this order is it paid or not and start with this but before we fix it would be nice to have here orders working so if we go to orders I want to see my latest orders that I get a new order from from my e-commerce front right so now we are going back to our e-commerce admin project and let's see here now here inside our e-commerce admin I want to fix this orders page so now it doesn't work but let's fix it so here inside Pages that's the new file and here we will just need orders.js and now let's see how we're doing with other Pages yeah we just need to return a function with a layout so let's go to our owners and let's do export default function let's call it maybe orders page yeah and let's return here and we are going to return a layout layout component we are using here and let's say it will have H1 with giant sync orders and now we have orders let's see for categories yeah we can just have this H1 here but underneath I would like to have like a table with with my orders so I need an orders model we have a model for it here inside the e-commerce front so I think I can just copy paste it right but there's something else I would like to add here we have all this data but I want to add here a second param a second object and I will add only timestamps so this time tons will do that we will have some more information about where when the when this order has been created or updated so I'm going to add those Titans let's go back to back to Let's copy this and let's just create an order here inside our models inside our e-commerce admin project order.js let's put it like this and now it should work so let's see here here we have our orders and let's print maybe a pretty table like this so we want the same table we have with categories let's see categories it's a table with constant basic let's remember here inside the e-commerce admin we are using not styled components but instead we are using Tailwind so let's go to orders and let's do a table and with class name basic yeah and then what do we need to know about orders what do we want to know we want to have like the head with all the headers let's put one header line here and th the first will be maybe order ID and then we want to know who ordered so let's do recipient and we want to know also we have the id id of our order recipient and let's do also our products let's do products yes and we have now something like this let's see categories something is off here with the head TR and th let's see here for categories uh okay it's because we have TD here there's something wrong with because this should be th as well but let's let's fix it inside the globals let's see here we have it let's do that the same thing should go for th t h here inside the head yeah that's better now back to orders and let's put the body here and we want to have all of our orders fetched here so we need to add the here use effect so let's do use effect Arrow function here and the default will here dependency will be empty array and now we need to have an API endpoint for our orders right so let's fix it API new file orders.js and here just export default function maybe we can do sync function we will need this and let's call it just Handler and here we will just have requests and response first we need to connect to our database so let's do just a weight Mongoose connect and then let's use our order model to grab everything so let's do just fine and let's do response Json and let's respond with all the orders we will not do any pagination here for now and let's do just wait here because it's a database query so we have it have this maybe we can do order buy or maybe it should be sort and the sort and here we will just do and created at and minus one so it will be descending and that's it now let's go back to Pages orders and let's see I would do axios and get request to slash API slash orders and into import access I think let's access yeah and let's do then we will get the response let's do Arrow function here with this response we have data and it will be our orders but let's put let's put it inside the state through the const orders and orders and set orders equals use State default will be empty array and we will put it here set orders and let's do put it inside the array like this and now we can use orders here so let's do and that let's check that orders length is bigger than zero then end orders.map and let's hear the orders map for each order let's just call it o maybe let's do order so it'll be easier to understand and parenthesis and let's do just a table row not sure it should be table row and for the first one will be TD now first the ID so as the order dot underscore ID and yeah the next will be table cell and we want all the information about the recipient of the order so let's do order dot name and the order that the email and that's the break line here and then now some address information so let's do order a city city let's put order a postal code postal code break line now um maybe before we break line I will put also country here order that country country yeah break line and now let's do order dot uh we need City address sorry it was street address and I think that should be it now let's see we can get four four because why we go to slash API slash orders it should be orders right now we get this info here um so that is nice if I make it wider this ID is super wide I don't know if I like it and we need to also put information about our products right so let's do this um so here we have products and I think I would like to have a date as well and I guess we don't need this ID so instead of this ID let's put a date and here instead of this ID let's put created at yeah so now those dates are empty and here but we will fix it in a moment and now let's put products information here so let's do last table cell and now let's see for order and we want to grab the order lines order lines like this and let's map through those and for each line let's call it just l i will do Arrow here parenthesis and let's put just react fragment and for each I will put let's put it just as Json stringify L and break line and now let's see properties of undefined so order lines is not a map so let's first check it let's go to order we have line items it should be line items let's go back to our order page it should be it shouldn't be all the lines it should be line items all right now let's see so we have like quantity and and the name product data name so we can use it so let's use it here let's print line product uh product data product data dot name and the time so let's do X and quantity so let's do l quantity right now let's see and cannot read of undefined looks like L is undefined in some cases Let's see we are reading name but product data looks like it's undefined so let's do just question mark here and as the quantity price data okay it's price digital not product data um so let's see if I refresh it's still X here uh so let's see quantity one so we have just an empty X here let's see L quantity I think I have misspelled quantity because it has one t all right now we have X1 now let's do product data name so let's do not price data product data name and product data name and it should be xiaomi product data and inside we have name uh let's refresh we still don't have a product data name so that is wrong I will put one more break line here so we have a quantity that works but we need also the name and that we have here name this product data name this so let's see product data product data and we need name let's see if I remove this question mark reading name on undefined so let's see I will add back this question mark looks like product data is undefined here let's see how it looks inside our database so inside our orders let's see how it looks like we have the line items we have let's check this one we have price data okay looks like it's a price data that we should check okay we have price data here orders for each order we have nine items yes 9 items then inside the line items let's see nine items for each nine item we are looping with map and for each of those we need to grab price data let's see not product data it's price data price data and it should be then the product data inside so as the another dot here product data and then this so now let's see now we have xiaomi redmi note 11 times 1. so we can get rid of this Json stringify yeah now it's much better as you can see we have three orders that are the same and we don't have timestamps so I think I will just delete all of those so I will just click here delete delete and the last one Let's do let's delete it as well and now it should be empty yeah and I will just create a new empty order so let's go to here home and back to our e-commerce front and one more thing here as you can see if we go back to cart even if we were done with our order we still have it we still have all the information inside our card so let's fix it let's go to a card JS here and well let's see here we are checking if it's success and if it's success we should have some kind of use effect so let's add another use effect here uh Arrow function and the dependencies will be empty array because we want to run it only once when our component mounts and here I want to check the same thing so I want to check if we have success inside URL that means I want to clear the card so we don't have any function for this but I can create it here let's do function and clear card and it will just do Set Card products to empty array Set Card products and let's do empty array and now let's just add it here our function clear card so we can reuse it here that's the clear card yes and so we can use it here let's just clear card so now now it's not empty but if we are on URL with success it has been cleared so now we need to go back to home and let's say I will add this headset and so let's go to cart we have this headset and we'll fill this information yeah now I will go to continue to payment I'll put this test credit card as you want to free your test and let's play it okay looks like we have a problem here window is not defined so here I will just check if a type of window or maybe we can just check like this let's do window question mark let's see window is not defined right I will just check here if type of type of window is is undefined it's undefined then we will just to return nothing here yeah window is still undefined in line 100 okay so let's scroll down here and let's do the same thing here if window if type type of window is not undefined here and and undefined and the window location blah blah hydration failed because the initial URL does not match what was rendered on the server all right that is because we cannot use this window thing here inside our render part so instead let's put it inside the let's put it inside the use effect so I will copy this part if it's success and here we have if it's success then we are doing clear card but let's also add set is success to true and I'm going to add this as a state somewhere here above const is is Success his success is Success default will be false and then let's go here and instead of this long div let's just check is Success like this and now we have thanks for the order so now everything works now let's go back to our e-commerce admin and let's see if we will have this order we have new order and here if I refresh I get order as well but I don't have the timestamps let's see here we should get the timestamps timestamps true but maybe because I just need to restart my environment so I'm going to delete this order and I'm going to just recreate it I'm going to recreate this order so I will go here and then we just put this and let's see one okay continue okay now it has been created let's now see here if I refresh if it has the timestamps and let's see yeah we have created that and updated that so that is cool now let's see here if I refresh here we get the date here so that is really nice maybe we don't need the to have this type of date and we want to make it prettier so let's see here we have this create that and let's make it prettier so we I will do I will split this T instead of T I will do a space so here dot replace instead of T I will do space yeah and here we should have a space over there here like this and so we have a space and well after the dot I don't want to have anything let's say I want to have this part it's let's say around let's do something like this Sub sub string I want to start from 0 to 11 characters let's see no that's not enough let's do 16 yeah maybe we want to have seconds as well that's 19 yeah so we have minutes and seconds I think that is good we have name email and under staff yeah so now we have all the information about our orders so we can just mail this so we can prepare the products and we can mail this person hey your product is on your way but before we do this and then we need to go to payments I will go refresh it payments let's refresh this is the latest order as you can see it's my email here I can go here inside we have this one item here so we can compare it with items here product items here even we can see where it has been created so it's 4 21 pm and it's the same that almost the same date that we have here but in here I have a 1420 because it's in UTC so it should be two more hours added here so this date is not actually correct um instead I will do something like this I will remove it and I will put parenthesis let's do new date and then let's put all order that created Created at with a lowercase D and now I will call to let's do two E7 string and let's see and we have something like this let's see what else do we have to to UTC string let's see this one now we don't want you to see so let's do two local date to local to local string yeah so we have something like this and we can check that for 20 55 and here for our orders 321 so yeah so we can check the date and the time for our orders here so we will know that okay someone bought some about someone has bought this Sony and headset here and we can find okay it's this order and if the time is correct yeah it's around correct so that's the same order so we can check okay let's grab it and let's send it to this person but checking orders like this is is annoying let's say so instead we had this paid Boolean and when we create an order let's see here inside our checkout and we are saying that let's see all the document pay defaults would be nice to display paid true somewhere here so we know the order is paid and we can send it there send the products right and the way they want us to do this I can go to developer and is to use webhooks and we are sending this invoice let's say we are sending this order to stripe and they want to send information back to our to an endpoint but the problem here is that the this will not work as an endpoint right because this is not a public URL so they cannot access it they cannot access my localhost 3001. because they don't know where where it is so to fix it they want us to let's say test in local environment they want us to use a stripe stripe CLI and download the cni and they want us to log in and forward requests to let's say localhost 4040 4242 for us it will be logos for 3001. so that's what we are going to do this and this way when they they will send when the order is paid they will send the information back to our endpoint with with information that it's paid so we are going to create a web hook now for this inside API inside the e-commerce front I'm going to put a new file here and let's call it just webhook.js and here as always just to export default function let's maybe put a default async function Handler and let's just grab requests and response and here we'll just do a weight in it uh Mongoose not any Mongoose sorry it's a mongoose connect yeah and then let's see what the we need to do here let's not use Ruby we need to use node.js and here you can see we have an example for Express but we are not using Express we are using uh we are using uh necess but I will just copy and this part everything that is inside this web hook endpoint let me just put it here so as you can see we need to fix some things um and the first thing is they are sending stripe signature so instead of requests we will just direct headers stripe signature yes this should work then they have this stripe that we need to import here so let's do same way with it here let's see check out to the top stripe I just copy paste it to here so we have stripe construct event request body uh yes they take all the body but let's see here they are passing information to express that this is a row request and for next JS they are parsing requests by default so to to prevent this I will do something like this I will do export const config and inside this config I will tell an xjs API to disable the body part so as well as the Border parser and to be false yes and that way we can disable body parts there so it will not try to Json the call Json and code the request body right now now instead of this request body we need to put a buffer of this so and for this we are going to call to use something called micro small thing for microservices yeah I'm going to just add it so let's do our new yarn add micro and from our micro we are going to just import thing called buffer and buffer from micro and this way we can put this our request as a as a buffer because this is the way they want to have it so as the await and let's do just buffer and our request yeah so that should work we have endpoint secret here and let's see here I think it's not not defined here here it is endpoint Secret this is your CLI webhook secret for testing and your endpoints locally all right I'm going to just copy this and let's put it maybe here on the top so we have endpoint Secret yeah and then yeah so we are try cutting this in case something is wrong let's just do response status 400 webhook error yeah and here we are let's see here we have payment entered succeeded and the here we have then Define and call function to handle the event payment in that succeeded right and handle other events we don't need other events only when it's paid all right let's see what do we have here inside this payment succeeded I will do just console log unless the payment event succeeded or maybe we can check here let's see received events let's see add an end point no test in local environment sample endpoint let's see I don't know what's here inside but we can console log it so I will bring now terminal and let's do stripe login so the stripe login press the enter to open browser now we have this stripe login let's allow access maybe I need to copy this verify let's allow access yeah I don't know if I need this key so I will just put it here and the stripe CLA is configured for test e-commerce with account ID blah blah I will just grab this account ID just in case we will need this and well let's see now let's maybe try to do a an order so we can see if this will work so let's see here I will go to cart and yes there that's the order I will change the products to something else I will take maybe airpods yeah let's fill it thank you let's continue to payment credit card and let's pay it now let's see our endpoint nothing has happened probably because we need to put more yeah I forgot about this stripe lesson thing so let's put it here uh let's see here no let's put it here stripe listen and but we are going to use 3001 let's see yes 3001 and slash API slash web hook web hook enter and here we have a signing Secret uh same we had here let's see if it's the same 78d here it's the same I think so now I will try to do now I will try to do another uh order let's pay it and let's see if we have some information here yeah we have some information here that we console logged here console log and we have information here let's see we have charges and method options and I'm looking for our order ID that we should have created URL looks like metadata is empty here okay I will try to do another one let's go to checkout and to our metadata let's put maybe test to be okay something like this but we should have order ID as well I don't know why it didn't work let's see we should have ordered the document and we should have underscore ID so that is really odd we should have metadata that shouldn't be empty or maybe do we have some more information let's see no I will try to do another order okay looks like metadata is still empty that is really weird I think that maybe we can check something else we have even the date object that we are checking and there are other events that we are um not resolving a handled event type and handled event type charge succeed right what we are and doing we are doing payment intent succeed let's do instead charge succeed so as the chart succeed so we know it has been charged and then let's try again okay even on this chart to succeed it looks like metadata is empty but it's maybe not the correct metadata that we should look for let's see here we have a switch and of event type let's see if there are other events that we are not handling we have unhandled event type for checkout session completed the payment instead succeed I will check this one maybe session completed um let's see because before we had the payment in the this was succeeded let's see session completed I will do one more order foreign thanks for your order let's see here inside our console log um let's see what type of data do we have we have metadata we have test OK and Order ID this is what we are going to need because then we want to check if it has been paid right so in this event we can grab metadata and Order ID so here from this let's grab order ID order ID equals payment intend maybe let's call just data data yeah from the data we want to grab meta data and we want to grab order order ID I think it's correct order with lowercase o yeah like this and it's metadata right that yes copy this and yeah that should work now um how we can know if it has been paid so we need to have a payment status here somewhere and here we have some payment payment intent payment status paid okay so we need to check that payment status is paid as the const paid equals data payment I would just say copy this part and then I'll paste it here and we want to check that data payment status is paid yeah and now instead of doing console log we'll do just if if it's paid if we have order ID and it's paid then we want to update our order so it's the order import and update one let's see find we can Define by ID and update the order ID is here Order ID and what do we want to update we want to do paid to be true here because we know it's it's paid all right and we need to do a weight here and I think that's all and we just need to do response status 200 and let's say let's send just okay all right and now I will do one more order I will do another airpods why not to see if we will get our paid to be true if this will be updated inside our database countries me then let's continue to payment I will use uh test the credit card here from a stripe let's click pay see if I would see it doesn't matter okay now it's paid thanks for the order let's go to our database and we'll refresh the orders and let's scroll to the bottom and we can see we have paid true so inside our e-commerce admin and we have products and yes let's add another column here after the date saying if it's paid or not so let's do paid and let's add a cell here let's do TD and if it's paid or order that paid then we will do yes otherwise it will be no so now we see that this one is paid maybe we can make it prettier like green and red so that would be nice instead of this table cell I will do yes no cell or sorry here we are using actually um here we are using not style components here we are using um Tailwind so here I will add the class name and if it's order dot paid then I will do a text green and let's do maybe 600 otherwise I will do text red and let's do maybe 600. now we should have yes and no so that is really nice so we know which one we can send which order we can send without checking the order here in stripe payments so we don't need to check this we can just check here and we know it's paid then we can grab airpods pack it up and send to this person and we can image this person hey yo your order is on your way so now I guess we have the all the basics ready so we have our e-commerce we can add products and only from new arrivals we don't have all products page but the card and orders and web Hooks and stripe everything works for now and the last thing is that we just need to disable this test mode when we go live but for now we have a working working webshop all right now it would be nice to have the X this all products page fixed so as you can see here we have a link products and we get four four so let's create a page for this here on your file and let's just say products.js yeah and here we will just return sorry export default function and let's call this just products page and here let's just return and let's see how we are doing this here in index we just have a header and that's it so let's put a react fragment and here let's just put header yeah and let's put maybe H1 with all products now let's see here we have all products now we need to make it prettier so I would like this H1 to be and the same size as this and so let's maybe Define it here that the const title equals style the H1 and I need to import styled let's do styled styles from style components yes and therefore our H1 I would like it to be the same size as this one so let's see 1.5 mm so let's do font size 1.5 em and we have all products but we need to use this title I will make it uppercase because this will be a a component so let's do title title and we have now same sizing here now let's see here inside index or maybe new products we have this Center component that would be nice to reuse so let's go here products and let's put Center and side Center we'll put our title so now it's centered and now maybe we can just reuse our components and we are going to use the product box but first we will need our products the same way we get them from featured products as you can see here we here we have a featured product sorry one product here inside new products we are grabbing products this way and this is passed from index so let's see here we get a new products from get server side props and this is the same way we are going to do for our all products page so um let's do here export function get server side props yes and now we want to return props here uh for now we don't have them but let's prepare them here so first we need to connect to the database so let's do mongoose Mongoose connect yeah we need to add the weight here and let's add the export uh sync function here and now if we are connected to the database we want to just return all the products all the products so um maybe let's put it this way and let's put enter here and here let's do products products and for our products we are going to use product a model yes and let's see if this has been imported yes imported from Models now let's do find all maybe just fine and then we want to find we want to find all the products so we don't need any params here and but I will just put a weight here and well here we don't need any parents I can put empty object if I want but on the second the param I can probably put here A Sort and let's sort it by let's sort it by underscore ID let's see the latest products here here we have new products we are grabbing all the products this way and we are also sorting by ID and but we want to reverse the Sorting so let's put it as minus one so instead of just ID let's put an object of underscore ID to be -1 like this but now let's put those products as a constant as a const products equals this and here we have products then but as you remember here we need to do a Json stringify and then on top of it we need to do Json and parts so it's the Json that parse because otherwise there will be problems with those object document Mongoose document objects all right now we can grab our products here that's the products and now we can let's print how many products we have the products that length yeah and now let's see looks like length is undefined let's see products and we are putting products let's put maybe question mark here we don't have any products that's maybe um here inside products let's maybe do console log products to see what's inside if I inspect here console and inside products we have products that these products is actually undefined so maybe let's check products here if we get anything let's do a console log and let's do products to see if we will get anything let's go to the bottom here and if I refresh yeah we get some products so let's hide this and I think here is the problem uh we are doing this empty program but for example here yeah it shouldn't be the second param for sorting and other information should be third because the first problem is filtering like definition what kind of products we want to find but we want to find all the products so that's why we just passed an empty object the second object the second param should be actually what type of information we want to select and we don't have any sort property on the products and so that's why it's empty instead we should put no here so everything will be selected so now let's see now we have nine products and now everything works right so um we have nine products but we want to Loop through them and display in the same way we do with new products so we just have these products grid and we are printing product books here for the grid we had the four uh four columns with this Gap and and the grid I think that inside this new products we can maybe export this products grid as a separate component so so we can reuse it and no copy paste this products Grid or creating something similar inside our products so um let's create a new component new file here inside components Let's Do products grid dot Js yeah and here let's just do export default default function and product and products grid yes and he will just return um nothing for now let's maybe put a div and we want this grid from new products so let's grab it from here I will copy it and I'll put it into products grid but I need to rename it because now we have the same names here and here and let's maybe name it the side products grid and now instead of this div let's put Here style the products green and let's say that here we'll get the products as param property and then we will just Loop through them and display them here the same way we do this with new products so I'm going just to copy this and I'm going to put it here yes and we have product box as a component imported for us and now we can use this products grid inside our new products here so we can get rid of this products grid from here and from here and we don't need to import product box for now and here we can just do products grid and we want to pass products to be products and now we can reuse the same thing in side our products page so here instead of showing the length of the products let's just put this products grid and let's see if it works cannot read properties of undefined reading zero okay looks like we have a product without images let's see here let's go inside products grid we have a product box here and we have here and we are displaying an image for a product let's add question mark it and Dot so in case this doesn't exist it won't be shown all right so now we have all the products but as you can see we don't have all the information so let's see here we get looks like we get only the IDS so that's not good let's see here products and we are getting this maybe we are getting only at this because of this null here let's see here inside index no this is saying the same thing here with no let's see here yeah maybe I will just try to console log all of our products here to see what type of data we get if I refresh okay now everything works maybe it was just some weird cache so now it looks like everything works um we don't have a key property inside the products grid so let's fix it products grid and here we want to have a key property and we can set it to be products that underscore ID so now we don't have this warning let's get rid of this console log inside products let's see here we have this console log let's remove it yeah so now we have a page with all the products yeah so we can add the products even from here but one more page that we actually need to add that is really important is a page for a specific product for example when I click here I want to see the page of this specific product with this specific ID so let's fix it as you can see we have structural product slash and then the ID so inside Pages let's do new directory product and inside product directory we're going to put a new file and here we are going to put square brackets ID dot Js and now here as always let's just do export default function and let's call it product page yes and well let's return and let's return react fragment here let's put a center component here and the first thing I would like to add is a title if I refresh here I can see an empty page maybe before the center I will put our header so we have the header and I would like to have the title but I would like to reuse the same title we have here on the products so we have the style tool with this font size and I think maybe I will put it as a separate component so I don't need to copy paste this styled thing so I will just copy this and let's do a new component here new file and let's call it just title that Js and we can do the same way we do this with let's say for example input that we are exporting a function we've styled input but let's try something new here with title and we have this we have title that is type H1 with this font size and we are importing the style from style components but let's just export this one export this one as a default export default let's do title now this will not work as you can see I have some error here let's just Define it first so let's do const title equals this and now let's just do export default and now let's do a title yeah now it should work and let's go back to for example products where we have all the products and see all products and now instead of doing this title and having this title or products let's import our title component so let's do title title and let's do all products now nothing should change yeah and that's correct so now let's fix the product page let's go to product and ID and let's maybe put here title yeah and now we would like to have information about this product so let's put it maybe here as a product we can put it like this for now this will be empty but I will add here export function and get server side props and we can do this this way with get server side props or we could use API endpoint with use effect that we were doing in other places but I think it will be better with get server side props because this way in case and Google will visit a specific page it will be a pre-rendered with all the information so let's do now Mongoose connect first Mongoose connect and we need to add the Sync here and away it here and now we want to return object with props and our props should be should include product so let's put product and the product will be just well product will be product but we need to Define our product so let's do const product equals and now let's just do a weight and let's use product model see here it is and now let's do that and let's see we need to do find find we want to find my ID well but here we need to know what is the ID so we don't know yet we need to grab it from the URL so to do this here we can grab something called context and let's print this context so we can see what we have inside so I would console log and let's do context yeah and now if I was let's go to the bottom let's refresh uh what does product acting valid schema well let's see here here we have some context and there is a lot of information here let's scroll maybe to the top there's too much of the of the information but I think there should be something called the query yeah so do like this let's scroll to the bottom and if I refresh I think it's this one I get query ID to be this but just to be sure I will put it as an object and I will put query here to be this and now if I refresh I get query and ID and this right so now I can grab a ID there's a const ID or maybe let's do like this const ID from Context query all right and now we have ID so we can grab the product as the product find by the this ID and let's provide props product to be this product but the same we have the same name here so we can just do product right and let's see return the server side props blah blah blah cannot be serialized to Json please only turn Json serviceable data types yeah this is the same thing we need to serialize and unserilize a product first so let's do a Json parse and then Json stringify inside here let's just build our product now let's see it looks like it worked so inside title we have our product here let's print product title and let's see here so we have xiaomi redmi note 11. so that works let's check other product let's see maybe this MacBook 14 pro yeah this works so now I would like to appear to maybe images here and here may be description and the title and stuff like this and the button to add the two cards all right so here I need to define something like columns wrapper because we'll have the same layout as we have here but the left column will be smaller so let's do let's define this columns wrapper and the const or maybe let's just put call wrap wrapper and this will be a styled that's important from styled components style the div and I want to put it as display not in line it will be in Grid and let's put grid template columns let's say the First Column will be just one zero point six FR and the second will be 1.4 fr maybe we can make this one smaller and this one a little bigger yeah and now let's put here uh columns uh call wrapper so we should have two columns so the first will be the first the left side will be uh like a chord with images and the right will be information so I want the images to be in something like a chord or something like this the same way we have for card page so here as you can see we have this box with background color water radius and stuff maybe I will just copy this and I will put it inside the inside the component inside the separate component as the new file let's call it just box maybe let's put it as whitebox.js and let's paste it here we are doing cons the Box let's just put white box instead and let's just do export default white box yeah and now we can reuse it here inside our product ID so and the First Column will be a white box white box and inside white box we will put an image let's put word image for now and the second the right column for now it will be just a div with a title inside and underneath let's put paragraph for now with product description yeah so now let's see we have the MSI laptop LED and we need some spacing and stuff so for now let's start with spacing between the columns so we'll have the same Gap as we have here let's check here for the card we have gap of 40 pixels let's do the same here Gap 40 pixels and now we need also this spacing here so let's see inside card with margin top of 40 let's do the same for our product for call wrapper and now let's go to all products let's see MacBook 14 pro yeah this looks much better now here we should fix the images and here we should have add to cart button yeah so let's see here and well first let's fix the images um I want to hear show the first image so let's do EMG source and let's just do product images and let's do first image so just a zero like this but in case it doesn't exist I will add the question mark in that dot right and now we should have the image yes we do but it's really big so uh let's put styling for now here I want to test something so for stunning I will put Max whip to be 100 yeah so it will look okay but now we have only one image here but there is something more I would like to fix for our product page and it will be with to show other images because here as you can see inside our admin let's go to products iPhone uh MacBook 14 pro let's do end it and we have more images for products and if I will select the other product let's see iPhone 14 we have three images and the seven so I want to show all the images for each product so here I would like to have a component that will show all the images and when we click on the images it will change this main image so uh so here I would like to create the new component and maybe let's call it the product images something like something like this so here inside new components of the new file and let's do product images dot JS and let's just do export default product images images we don't need any import here and this should be actually a function export default function product images and we want to have a property passed here called images and this will be an array of images it links to images right and for now let's do the same thing we were doing here so let's just return one image so from the images we will just grab the first image so let's do and this will return and let's do parenthesis here let's put react fragment and here for now I will just do image source and from images images I want to grab the first image in case it doesn't exist I will add the question mark and the DOT and we should see an image right now let's go back here instead of showing this image let's use our component called the product images and we want to pass images to be product.images yeah now let's see it's super huge but we want to fix it let's go back to product images and let's call this one the main image it will be called the Big Image so it's the const big image equals styled let's import styled from style components style the image and now let's do something like this let's do Max wave wave to be 100 percent and now instead of image like this we will do big image so now this looks fine but now underneath under the big image I would like to see show the rest of the images or all the images so let's see I will put the div maybe here underneath and now for each image so let's do images dot map and let's see for each EMG maybe let's call it image let's do Arrow function parenthesis and here let's put maybe a div with an image inside inside inside this div I will put just an regular image tag with let's put it as a source will be image and let's see so now everything is huge but we will fix it first we have this div and we have this image here this image is uh also really big and I can not see the image that should be small but don't worry we will fix it first let's maybe fix the first let's maybe fix the images so we have this big image but let's rename it to Jazz image so we have Jazz image and here let's put this uh just image as well so now we have Max width of a hundred percent on all the images so this is the first image that is here and then we have a div with those two images as you see here we are showing the first image and then inside this div we are showing all the images so even the first one but this is because I want to show those two side by side and so we can click on them and change the main image here somewhere to do this I will change this div to let's call this one let's call this the image buttons equals and let's do style div and this will be just a display as a grid yes and let's do grid template columns let's maybe do three columns of the 1fr1fr1fr and now let's put it here so image buttons now let's see yes so now they are next to each other um let's do that this div will be an image button not buttons so singular so the const image button equals styled maybe let's do yeah let's do div as well and let's do that image pattern we have a border of one pixel solid unless the gray AAA so now let's do a image button let's see yes we have some borders let's put maybe a gap here of at least 10 pixels let's see yeah that's better now for those images I would like that they will take they should take the same have so I think instead of defining columns I will remove these columns and I will change it to flex yeah so now they just take the same they just take the whole width and to fix it so they don't take the whole width I will do Flex grow here grow to zero now let's see now we have changed let's put this Flex grow here maybe on image buttons still nothing change right let's see let's maybe Define the have here on a specific image button let's put half of 20 pixels now it will be super small and the images are too big but let's fix it let's put maybe 40 so it will be a little bigger and now for the images here let's put Max half of 100 as well so now so now it works as you can see they have the same have and they don't take the 100 wave so that worked now I would like to add a little bit of padding inside each so let's do padding 10 pixels but now there are and they are smaller maybe let's add here 60 pixels maybe that's too much let's do padding though just 5 pixels here but I think that's still too big I will decrease it back to 50 or maybe even 40 let's see and we don't need that big padding I just do two pixels yeah I think that's fine so now I would like to add some margin here so let's do margin top here too that's the 10 pixels for now yeah I think this is fine and now I'd like to have cursor cursor of pointer Here chord server the cursor pointer so I will have this hand cursor here and yeah now I would like to have a different border so I want this to be rounded here the corners should be rounded let's see here image button that's the Border radius that's the maybe five pixels yeah I think that's better and instead of border I will put the background color of gray so let's do maybe CCC light gray yeah and we still have some kind of okay so here we have a gray background on both of those this is just because we have white background on this image and there are many products that we have a white background on let's see for example this iPhone 14 yeah so uh I think background will not work that well for those images instead I think we should use actually border so let's put it back as border one pixel solid and let's do CCC yeah that's better maybe we can put the make it bigger so it's the two pixels border yeah I think that looks fine but now I would like to fix that when we click on those images this main image should change so and to do this let's scroll down here as we can see we always have this zero image as an active image so let's put it as a as a state so let's see here well first we want to get rid of this style things and we should put them outside of our component here yes then let's put our state here so the const and let's use square brackets here let's put active image and set active active image and equals use State and here default value will be empty string yeah or maybe we can put directly images of zero in case it doesn't exist we'll adjust the question mark and the dot yeah so now we can use active image here for a source let's see yeah it still works and for now for our image button we can add on click and then on click I will do Arrow function here and let's do just set active image to image because here we have the source that we are using for a specific image so now if I click yes it it changes I don't like that it jumps um up and down because of the half of the image so for this big image I will also add the max have and so let's define it maybe here of the const let's put back Big Image equals style the EMG and for Big Image I'll put Max width of 100 percent and I will put also Max have to be 200 pixels right now let's instead of image let's do big image now let's see and now it's this big but will be much better to have it centered here in the in the middle so uh so I need to add some kind of main image wrapper so the const Big Image wrapper wrapper equals styled div and then here inside this div I will just do text align center now let's put this big image wrapper inside let's put this big image now let's see yeah that's much better and if we click on other images we see other images so that's nice but I would like to have the Border only on the on the selected one so let's scroll down here and we have this image button let's add the property of active and property active will be true if the image if the image is the same as active image right now we'll just put it here in a different line same here so it'll be easier to read now and let's open just console to see if we have any errors now we don't or we actually do and we don't have a key property so let's add it here key equals I just put image of the key let's refresh let's click here everything works now this active property let's use it here inside image button so here I will put the let's put dollar query brackets here let's do props and let's do props that active question mark and here for active and here for non-active so for active I will put it I'll put it like this and therefore active I will put that we will put border color to be red yeah and this border I will put on the top yeah and for not active I'll put border color to be transparent with lower T now let's see if this will work yeah looks like this worked but now another thing I would like to add and will be to probably change this color to back to CCC for a selected one but another thing is that for non-active I would like to do opacity of 0.8 or maybe 0.7 so those will be semi-transparent yeah I think that is that is good I don't know if I lag this opacity I will remove it for now so for now we have only this border for selected and I think this looks good enough now let's go back to our products and let's maybe select the MacBook 14 pro let's see yeah I think this this looks nice and we have this uh title here and we have description so now the last part that is really important for a product page will be add to cart button so let's go to our product ID that JS and here for the under the description let's put just maybe let's put a button so let's do button yeah and then let's put add to cart yeah let's see here we have add to card and we can add some extra classes on this button let's see what do we have on the home page can be this it can be done I think that I would like it to be a primary something like this let's see what do we have here it can be black or primary so let's do a primary to see how this will work primary see yeah add two cards I would like to have add this icon cart icon so let's add it here and cart icon yeah yeah so we have this I need to show the price here as well so let's maybe put those two things inside the div we have a button here let's put the price so the dollars and let's do product dot price let's see here so we have price here and what I would like to style this a little bit so instead of this div I will put it as price zero so let's do price row equals styled div and now let's see here inside I will put the that we will have a small gap of 20 pixels yes and this will be display of flex all right so let's put price inside separative and this button also other separate div yeah so we have something like this now now instead of this div I will put a price row let's see here now it's like this now let's add the Align items Center so I hope this price will be centered yes it is now for the price I would like to add a span so it's the price equals side span and let's just make it bigger so let's do font size and let's do maybe two Ram let's see if this will work let's put this as a price and let's close this price oops price here maybe I will put it into different line so it will be easier to read now let's see yeah maybe it's too big let's change it to 1.4 Ram yeah I think that is better and I think this will work so let's see we have card here let's remove everything your card is empty let's go to all products let's see MacBook 14 pro let's add the card no it doesn't work for now because we need to do the same thing that we have for example inside our new products let's open products grid product box and here we have on click when you want to add the product and add product is a function from our context so we need to use a card context let's go to product here ID and let's grab it from here so it's the const add product and we want to grab it from use context and here I think it was card context yeah so now we can use this add product so here pattern primary let's add on click I will put inside several lines so to be easier to read now on cling I will do Arrow function and let's do add product uh the product and now product ID we have inside product dot underscore ID so now let's see if I click it we have cards now one if I click another one we have chord two and go here cart and we have two MacBook function Pros so that's uh that's correct and the price is updated as well here and here if I decrease yeah everything works and this is updated as well so now I think we have all the basic functionality we have new products here we have all products here on this page we have a product page images and we can add it to card so yeah now we have like all the basic functionality that any e-commerce website needs now another important thing that we need to fix here as well is to make our e-commerce front responsive so mobile responsive for now if I make it small like this as you can see I get some horizontal Scrolls here and it doesn't look good it's it's not mobile responsive and while our e-commerce admin is so if I make it this small it's actually fine we have this navigation here and well it works and I can edit a product and even if I'm on mobile everything works fine here and I would like to do this mobile responsive as well so let's start with our home page so let's go to our index and see our home page is actually just header featured products featured products and new products so maybe we can start with a header so let's open header and the header is just some bunch of links but to make it easier I would like to just copy paste some things from here because here we have some cool navigation that we can just reuse so we can either maybe reuse this one or maybe we can create from scratch so you guys can learn some things maybe let's uh let's do this from scratch here because on our e-commerce admin we were using we were using tailwind and here we are using styled components so this not B this will not be compatible here we need to write our CSS ourselves so let's do this so let's say that for small screens we don't want to show this uh those links like this and we want to show a button for navigation maybe here on the top right corner so let's put maybe let's put it maybe here after the style navigation let's put the component called the nav button and as you can see it will be just just another button and but I would like to have an icon here inside so let's put closing and here uh let's define this nav button for now let's do const nav navigation button to be styled button for now we just type button so we have something and we want to put an icon here inside so I will go to Hero icons because I don't think we have this icon here and the navigation sorry menu yeah let's copy this bar 3 copy jsx let's put it the same we did with our card icon icons new file and let's do bars.js export default function default function and let's do bars icon and let's do return re turn parenthesis and let's paste it here uh let's say card icon we have a class name here at the param so let's do the same thing with this so let's put a class name and default will be this and let's put class name here yeah and now let's go back to our header here let's see here let's put our bars icon bars not bars content bars icon yeah so let's see how it looks like looks really bad let's uh Define some Styles here for our button let's do background color to be transparent yeah and see the bars but we'll fix it soon that's the wave of as the width 200 pixels have to be 200 pixels we'll fix it soon yeah now we see our bars at least let's remove this border to be zero and then well now let's make it a little bit smaller so the 100 pixels here and 100 pixels away for half like the even smaller is the 50 by 50. yeah now the color inside the color of the text should be white so let's do color white yeah I think that is much better and let's add the cursor to be pointer right yeah now and now it's much better we can make it even smaller let's do 20 by 20 okay now it's too small let's do 30. um by 30 yeah I think this will work and it should be visible on mobile so let's scroll yeah I hope it's summer here I don't see this maybe let's the color red let's see if it's somewhere here I cannot see this I cannot see the button um so that is not good but well first let's fix that those links shouldn't be visible by default those links should be visible only only for this up right or maybe let's change them that this style navigation should be should look different should not be should not put the links next to each other we flex but instead it should put the links one by one so let's put here let's put this display to block so now they are well they are still next to each other and is because every link is a inline element but if we do display block on them now there are under each other and if we change this to flex they are next to each other yep so now let's change this to block yeah but now we want to do some media screen and minimum wave of this and let's do that if the screen is big enough we want the display to be Flex yeah now let's see if I make the screen here bigger they're next to each other if the screen is smaller they are not next to each other right but if they are not next to each other I would like them to take much more space they should go from left to the right so um let's put here for mobile it should have a position of type fixed and it should go from top 50 pixels to bottom 0 pixels and from left zero let's put zero like this and right to write zero now let's see yes that's better maybe we can add from the left to be 50 pixels let's see now that's too much let's do just 20 yeah I think that's good or maybe we can change this left to zero as well but we will add a padding of 20 pixels all right and let's add background color as well background color will be the same that we have here so let's just two to two let's put background color 22 yeah and that is really nice and if the screen is big enough well now we have some problems because we added this position fixed and so on as default but now if the screen is big enough we need to change position to a static back to static so if the screen is big enough it looks fine but now we should also remove this padding for bigger screens let's see yeah I think now everything is correct except this button this button shouldn't be visible if it's mobile if it's big screen so here let's grab this big screen thing here we have navigation button let's put if we have big screen then let's do display to none so now we don't have this navigation button but if we have a smaller screen we have it here this button now doesn't do anything so we need to fix it first let's maybe change the color of this button to White and then we should fix that this button will open and close our navigation all right so um let's add maybe a constant or state here so the const navigation active and set navigation active default will be used State and default will be true or maybe default will be false and let's rename it to a mobile navigation active and set mobile navigation active and it will be use State default will be false all right now for this side nav let's add the mobile navigation active to be mobile navigation active and for our navigation button let's add on click it will just toggle as the arrow function and this will toggle set mobile navigation active let's grab the previous value and let's just do the opposite all right so now nothing happens because we are not using this let's see this mobile navigation active here it's time now we are not using this so let's use it now so let's do and dollar let's do props and let's do props dot mobile navigation active and now if it is active then something otherwise something else uh if it is active I will put this display block if it's not active I'll put display none yeah so let's see now yeah now I can toggle this navigation and there's one more thing I would like to fix and it's this header so first I would like to add the change the stop to zero and I would like to add padding padding top to be 50 pixels uh yes let's put those two together so it will be 50 pixels here and 20 here and this way we don't need this one so let's see yeah and uh it should show the logo here so let's see where we have logo here so it's the position and position relative and let's add that index of let's put maybe as free so we have it above here same with the and the navigation button so let's copy this and let's put it here position relative so we can still click it yeah that is nice now let's see yeah I think this looks fine and let's see yeah if you want you can add some animation or something like this but I think we this is good for basic um mobile navigation maybe we can make the links prettier here we have navigation link let's maybe grab let's maybe add some more padding let's put padding of 10 pixels on the top and the bottom and on the sides zero here so we have more padding here and more here from the top let's do 70 pixels oops 70 pixels yeah so we have more spacing but if it's a big screen we should remove this huge padding that we added let's see navigation link here we have 10 pixels extra and we want to remove it for big screens so let's add padding yes zero yeah let's see now I think it looks fine and I can toggle here yeah it looks fine so now I think we are done with this header we have some basic support for mobiles now we need to fix this featured product so let's go to feature product let's see uh product box no no it's not this featured right and here inside we have coins wrapper we have two columns but we want to make it just one column if it's uh if it's small so I will copy the same media query from our header let's see I will copy this and I will put it inside featured I'll put it here and now let's see we want those columns only for bigger screens and for smaller screens I want only one column to be 1fr so we have something like this but for small screens I would like this image to go first so here let's put the columns order no it's just order order let's do one two I don't know if this will change anything maybe we should just do minus one no it shouldn't be here it should be on a specific column all right I will remove it from here but there is something else we can try here I think it's uh column order or sort something like this column span no grid outer columns no let's see grid and grade the column start let's see and let's do revert and let's see no let's do start let's see auto revert and set no this will not help so we need to point specific columns so let's see here inside the coin with wrapper we have two columns and they don't have any differences here let's see if I make it bigger the text is on the left the image is on the right I think that's correct but now we want to do something else so here I will put maybe div and let's do end of child of one and I will put order to B2 and now as you can see it have changed but it changed even for for the big screen and for the big screen I would like this to be something else as the div infjed one let's do order zero let's see yeah and now it's correct so now it looks really nice but the we have the max width of hundred percent here maybe let's put this uh here for big screens but for small screens I would like also to add Max half of uh 100 pixels so it will be smaller yeah that's correct maybe we can make it a little bigger 200 pixels and I would like this to be centered so let's see here maybe we can just add that the First Column um or maybe actually the second column that is shown as first so let's do here div and child of two so the second column the column with the image that is actually shown first let's do text align to be Center this didn't help much let's see why we have colium with image maybe we can just remove this text line Center and let's see maybe we can adjust display inline or maybe we can do this display block and let's do origin of zero Auto yeah now it's centered let's see if I make it this big yeah it looks fine so uh I think this looks now good enough maybe we can make the title smaller let's see title here it's super big free Ram it should be only this big for big screens so let's add big screens query and let's put font size here otherwise let's put it 1.5 yeah so now it's just this big yeah and then we have this new arrivals so we have new products products grid and let's go into products grid then and let's see for products grid we have the style product grid with four columns so that's why we have this horizontal scroll here and I would like to fix it by doing that we will have Let's see we can have either two products in a row or maybe four I think we can have two products so I will just grab this query let's go to featured I'll grab this let's go back to products grid and for big screens I will put this so let's put this here but for small screens I want only two products yeah this is better now we don't have horizontal scroll and let's see this as well inside all products yeah I think this looks fine accept those buttons so we want to make it a little bit prettier for a mobile so let's go inside product box and we have this white box here we have image we have price and price zero so let's see we can either do a price smaller or we can make those things under each other I think we'll be better to put the price and then under the price we'll have this at the card button so we'll see here we have price row with display Flex let's add the sorry let's add media screen and minimum wave this so display Flex should be only for big screens otherwise we should have display off type block so now as you can see we have this we have the price here and then we have add to cart but now for the price well I think on mobile it shouldn't be that big so let's go here and I will put this media query here so uh for the big screens it should be this big but for regular screens for mobiles let's do just one ram yes and and I think this looks good but um I would like this to be on the right side so let's do text align not Center or maybe let's try with center now I think it should be to the right and it should be to the left for big screens let's do left yeah now it's to the right but the button should take all the width so let's scroll to the button let's see price row white box uh I think we don't have any styling for the button here so let's see here we have a price button let's see if I add just block here here now it takes all the width and if I make it this big yeah I think it I think it looks fine yeah and uh yeah I think it looks alright we could put the price inside the bottom I think it's not that important here I think now we don't have any spacing so let's add it and price row let's add for big screens let's add the gap of at least 5 pixels now let's see yeah I think that is that is better let's see for small screens yeah I think it looks it looks alright or maybe to make it look even better I would like to put the price inside the button so let's scroll down here and let's add the dash and let's put the price here so let's put product and let's see do we have product info no it just price that we should use let's put price yeah so we have prices like this let's see how this will look like for uh desktop now I think we should have the price outside of the button I think this is uh this is better let's go back yeah I think this is good the only problem is that for example here that we don't have enough spacing but we can fix it let's see price row price uh let's maybe make it smaller 1.2 yeah I think now it's a much better and if I make it smaller yes it's uh it looks good as well yeah maybe it doesn't need to be this uh 600 wave let's do 400 and I think this looks good enough and if I make it this big yeah I think it looks fine so now we have um our home page done and mobile responsive let's see yeah I think everything looks fine now if I click a specific product let's maybe do MacBook 14 pro this doesn't look good so let's go to our product ID and now let's see we have this conference wrapper and the thing here we just need to add media screen minimum width 768 why not and this is when we should have two columns otherwise we should just have one column yeah something like this and as you can see now everything just works so that is really nice maybe we can add some margin bottom here as well so let's do maybe just margin 40 pixels and zero on the sides we have some 40 pixels on the bottom as well yeah and let's add the bar onto the card yes if I go to card and here we have a problem as well because as you can see we have this horizontal scroll here so let's jump to the card and let's see here we have two columns as well so let's do media screen yes and let's put those columns here but if it's small screen by default it should be just one column so yeah this looks better and we have order information here yeah maybe except this table here let's see how we can make this smaller we can decrease the padding here let's see product info box I'll grab this media query and let's see we have padding of 10. I will add media query here on the bottom and let's say padding 10 pixels will be here for big screens but for small screens it will be just two pixels yeah so we have something like this and now let's see this looks fine now we have only problem with quantity so let's scroll down here and let's see what if it's a separate component table table buddy we have buttons here and then we have quantity label and here we have um yes button and Baton and quantity label maybe we can do a quantity label as block so let's see here quantity label let's copy this media query for big screens it will be empty for now here by default it will be display block yeah and for big screens it will be display inline block right let's add some padding for small screens it will be on the sides it will be let's say 10 pixels yeah or maybe let's do a 15 so it will be centered kinda and let's copy this here for big screens as well let's see for big screen yeah I think it looks good even for big screens maybe we can decrease it a little bit as a 10 here unless the screen bigger yeah I think it looks fine um so here maybe the image can be a little smaller let's see product image box let's put this image even here for big screens for big screens can be 80 by 80 but for small screens let's put 40 by 40 as a maximum yeah so now it's this big let's maybe change that the max save should be 50 and same here Max width will be 50. let's see how we are getting this big padding here uh make this a little bigger let's see Dave we have image that is this big okay it looks like we have width and half of 100 pixels so this width and half of 100 pixels let's put it here for big screens for smaller screens let's put the width of 50. yeah so now it is smaller uh maybe we can make it a little big let's do 60 here uh we have actually it looks fine maybe we can do 70 and well this can be bigger as well let's increase it to 60. yeah I think this uh this looks fine and if I make it bigger it looks like this and if I make it smaller it looks like this I think it looks fine we have card product product with the title we can increase and decrease here it's in the wrong order right right but that's not that big of an issue Let's uh see now under buttons here I think that's correct if we go to home page and let's see this link is wrong so let's fix it featured product featured product let's scroll here we have a link to read more and it will go to product slash let's see yeah now it's now it's all right yeah now everything works so we have a both this website is responsive and even this e-commerce admin is also responsive so both of our products are now responsive all right so now we have built all the main functionality of this full stack e-commerce so congratulations on completing this project if you are interested I've made an extended version of this course where we build much more features you can check it at david.link with W e-commerce or you can find the link in the description anyway I hope you enjoyed this video and if you did make sure to hit that like button and don't forget to subscribe that's it for today so have a nice day and see you in the next video
Info
Channel: Coding With Dawid
Views: 320,494
Rating: undefined out of 5
Keywords: next js, next project, next js project, next js tutorial, next js ecommerce, next js webshop, next js ecommerce project, next js webshop project, next.js, next js online store, next js course, next js ecommerce app tutorial, next js project for resume, next js project tutorial, next js ecommerce app, next tutorial, next js app, ecommerce app, ecommerce app javascript, ecommerce app react next, fullstack javascript app, fullstack javascript, next app, js, e-commerce
Id: dTFXufTgfOE
Channel Id: undefined
Length: 709min 44sec (42584 seconds)
Published: Tue Apr 11 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.