So our online shop is taking shape,
and if we log in now with the admin account.
That's important.
If you log in with that account,
then indeed we can see the manage products,
and manage orders, items here.
Now, what we can't see yet,
is the actual site or the pages
that belong to these navigation items.
And that's exactly what we'll work on now.
And I'll start with the administration area,
where we can manage products,
before then in a next step,
we, of course, also work on the customer facing part
where customers can browse products
and add them to their carts.
But we, first of all, need to be able to create products
before it makes sense to work on the customer pages.
So, therefore, we get this managed products link here.
And if we take a look at our nav items,
we can see that this leads to /admin/products.
Of course, it's up to you to set your own path here,
but whichever path you choose,
you need to register it as a route.
And for that, we could go to products.routes.js
and work on the route there,
but actually I'll create a dedicated file admin.routes.js
where I want to group
all the administration related routes together.
So the routes for the products, for managing the products,
and then also later the routes for managing the orders.
for that, of course, we can copy the base setup
from one of the other routes files and add it in there.
And now just register different routes here,
To be precise here,
I want to have a route for /admin/products.
And then that should be, first of all, a get route
for showing us the page
with all the products that we created
and showing us options to add new products.
But then I also want to have another route
where I, for example, have /products/new
for loading a page where we can add a new product.
And as you can tell all these routes here,
we'll start with /admin.
Now we can repeat /admin over and over again
in the admin.routes.js file,
but it would be even more convenient
if we would load this routes file such that
all the routes in there
are automatically prefixed with /admin.
So that in this file, we just have /products
or /products/new and so on.
And the /admin is added in another place.
And that's very easy and also common to do
in Express.js or with Express.js in App.js,
where we set up our basic request flow and our main app,
we can now include these admin routes here
by requiring ./routes/admin.
Whoops, not auth, admin.routes like this.
And then in the place where we register those routes,
let's say here,
we register the admin routes, but not just like this,
but instead by using a different version of app.use.
A version which I also showed you earlier in the course.
You can just start using middlewares like this,
but you can also add an optional first parameter,
which then actually is a path that will act as a filter.
In this case, for example, /admin.
What this will do is that only paths that start with /admin
will make it into the adminRoutes route configuration.
So any request with a path that does not start with /admin,
won't make it in there.
And this starting path is then removed
from the path of the request,
so that inside of this file,
we can look at the rest of that path,
which is what I'm doing here.
So this will handle requests at /admin/products,
even though I just have /products here,
because I have to /admin in the App.js file.
We could have done something similar for products,
and for example, only handled /products/something here.
That is something we could consider doing for the future.
For the moment, I will leave it as it is,
and just filter my admin routes like this.
Now back in the admin.routes.js file,
I now do have these two routes,
but, of course,
I have no controller actions for these routes,
and that's there for the next part, the next important part.
In the controllers folder,
I'll add a new admin.controller.js file,
and in here, I want to define all the functions
that we'll use for managing administration related pages,
for showing pages or for handling posts or other requests.
For example, we need a function
for showing us the products page, the admin products page.
And hence, I'll name this function getProducts.
I will also already add a function
where I choose a name of getNewProduct,
because this will be the action that's responsible
for showing us to page for adding a new product,
and we will then later also have functions
for submitting a new product.
So here we could add createNewProduct function for example.
The function name is up to you.
We will add more functions
because we'll have more administration actions
that I to handle in this controller,
but this is a good start, and of course, as always,
you want to export them with this syntax
to make them available outside of this file as well.
And here I'll use the function names as keys
and then point at the respective functions.
So here, I'll make them available
outside of this file like this.
And back in the admin.routes.js file,
this of course means that here we can import
the adminController by requiring,
going up one level, controllers/admin.controller like this.
And here for this first get route,
where I want to load a page
with all the products that we can manage,
I point at adminController.getProducts.
For the second route,
where I want to load a page for adding a new product,
I will load getNewProduct, and that is that.
Now we can add a fitting template,
and then add the logic for rendering the template
in the adminController file.
So therefore in views under admin,
I'll add a products sub folder.
I also have a products sub folder under customer,
but here I'm talking about the views
that are exclusive to the admin.
That's why I have this specific product sub folder
in the admin sub folder.
And here I'll add all-products.ejs file.
That is the same name as here in the customer facing part,
but we will show different products,
and different options for the products.
And in that same products folder, I will also add
new-product.ejs file,
which will be the viewed that holds the form
for adding a new product.
Now, I will start with all products,
and for this I'll copy the code
from the all-products.ejs file
in the customer products folder,
and add that into my admin products folder,
all-products.ejs file.
And I still want to include the shared head and so on,
that is all fine, I will keep that.
I will keep the header.
I'll keep that dummy content for now.
I'll just add admin in parentheses after all products,
so that we can see that we are on this page,
the admin specific all products page.
And now to render this for the given route,
I'll go to admin controller,
and they are in get products.
Of course, as always, I get my request and my response,
and the next function, if I would need it.
And on the response we can call render,
and then render admin/products/all-products.
That's the path to view we just added.
And in the future we'll, of course, also get products
from the database and pass them to the template,
for the moment we don't have that yet though.
But with that, if I now reload,
and I click on manage products,
you see I'm switching to this admin page,
and that's the first step.
Now on this admin page,
I also want to provide a link
that takes us to the new product page,
so that we can add a new product.
And for this, in this main area here,
I'll actually add a section and add another section,
and take this h1 tag,
and actually move that above those sections,
but move this paragraph into the second section, like this.
And then in the first section here there,
I will add another title where I say product management,
and actually the title of the h1 element here
can become Product Administration.
And then here in this section, as I just said,
I have Product Management,
or maybe actually Manage Products as a title.
And then below that, that's the important part,
I'll have a paragraph where I add an anchor tag,
an anchor element that leads to /admin/products/new.
So to this page where we will have a form
for adding a new product.
And hence, I'll say Add Product as a caption on that link,
and I'll give it a class of btn
to give it that button look.
With those changes made,
if we save everything and reload,
now we've got this Add Product button.
And if we click that, because it's actually a link,
we'll be taken to the page for adding a new product.
At the moment, though, that will fail
because whilst I have connected the route in admin routes,
I connected it to getNewProduct,
this getNewProduct function in my admin controller
doesn't do anything yet
There, we want to make sure
that we also get the request and response,
and we also render a template here.
In this case, the template for adding a new product.
And the path to that template file was
/admin/products/new-product
That was the name of the template.
However, that is an empty template right now.
It's this new-product.ejs file, which is empty.
And therefore for now, I'll just copy all-products.ejs,
and add that here into new-product.ejs,
And in there, I now want to get rid of those sections,
and say Add new Product as a title.
And now in here, we want to add the form
for adding a new product.
Now for this new product form,
we start of course, by adding the form element,
and there we'll have a certain action and a method,
we'll set the those later.
And in that form,
we, of course, have all the different form controls,
Now I'll wrap every control into a paragraph here,
and every form input then has a label
with a human readable text.
And that label is connected to the actual input
with the for attribute, as you learned before,
in this course and in this project,
and here, we could say that every product
should have a title.
Now that title should be entered with an input element,
and it is a regular text input.
Now I'll point at a element with ID title here,
hence we have to add this ID to input,
so that the label is connected to the input
for accessibility reasons through that for attribute.
And we add a name attribute
so that we have a key that we can use on the server side
for extracting the entered data.
And I'll choose title as identifier here as well.
Now I will also add required here to make sure
that we have this front-end validation,
and the that is actually it for now.
Then thereafter, we can add another form control
in another paragraph, where I actually want to choose
an image for the product.
And that, of course, should be pickable by the user,
by the administrator.
Hence here again, I'll add an input,
but now it's of type file.
Which is one of the built in supported input types.
Still, We want to connect it to the label,
so here I'll choose image as an identifier,
and hence add that as an ID here, also use that as a name,
which we can then use on the server side for extracting it.
And I'll add the accept attribute to control
which types of data are accepted.
And here I explained that you can, for example,
specify the file extensions you want to accept
as a comma separated list like this,
or more general image/png,
and image/jpg
to support all valid PNG and JPG images.
Now we'll work on making the file upload work later,
we'll also add an image preview.
For the moment, that is it.
Now I will add another paragraph here,
which now should allow the user to enter a summary text,
which is simply a short summary that shows up
on the all products page.
And that can be a regular text input,
nothing too fancy here.
We just also might want to enforce a maximum length
of let's say 250 characters,
but ultimately that is up to you.
Now we also need a price input to set the product price.
And hence I choose price here and here.
And as a name and the type here then is actually number
because the price that we enter is a number.
We don't have a max length here,
but now I want to have a min value.
Min now doesn't control the minimum amount of characters,
but the minimum value that has to be entered.
And that should be at least $0.01 let's say,
if we use dollar as a currency,
and I will also add the step attribute,
which we can add on any input that's of type number,
which controls,
which step will be used for incrementing or decrementing
the value when using the arrow buttons that will be added
automatically by the browser
whenever you choose type number.
You'll see them in a second.
And I'll set this to $0.01 as the smallest unit as well.
Now there's another of paragraph, another form control,
which I want to add.
And that's for the actual description,
which is a longer text describing the product.
This will be shown on the product detail page later.
Hence, I'll choose description here,
and also as an ID and as a name,
but I don't want a input here of type anything,
but actually a text area,
which is another default HTML form element.
We don't have a min or a step attribute,
but we do have the required attribute,
and text area is not a wide element,
but has an opening and closing tag.
So you need to write it like this.
Now on text area, you can add the rows attribute
to control how many rows are shown by default.
So how big this input will be.
And I'll set this to seven here,
and with that, last but not least,
I'll add a last paragraph at the bottom
where I just want to add two buttons.
The first button will be of type reset,
and it will say reset.
This allows the user to reset all the inputs
to their starting values.
And the second button is of type submit,
or you don't choose any type at all
since submit is the default,
which will then actually save that product you entered.
Now it is second button gets a class of btn.
The first button will get a class of btn and then btn-alt,
which we have yet to add,
which is a slightly alternative button look.
With all that added though,
if you saved this and you reload that product new page,
it should look something like this.
Now of course, all the form styles are missing
the form styles we already had
on the log in and sign up pages.
And the reason for that
is that we defined all those styles into forms.css file,
but, of course,
we're not including that in the new-product.ejs file.
That, of course, is something we can change though.
Right after including the head area,
and actually here,
we could change this to add new product as a title,
but right after including this,
we can now add a link here and link to styles/forms.css.
Now we can reuse all the form styles we defined before
for this form.
And of course you can tweak this and ensure that it looks
the way you want it to look,
but I am quite happy with that look I set up before,
and therefore, I'll stick to it like that.
The only thing I want to change is the reset button look,
There, indeed,
I wanted to find such a button alt class look.
Now, to do that,
We can quickly go back into the base.css file,
where I also defined the main button styles,
and after defining those button styles,
I'll add button-alt as a rule
or as a selector for this rule.
And here,
I just want to set the background color to transparent,
but change the text color to var --color-primary-500,
which otherwise would have been the background color.
And then the hover style should change as well
for btn-alt:hover and btn-alt:active
There, we now also want to ensure that this looks good,
so therefore, here I'll then give it
a little bit of background color,
and I'll choose --color-primary-500-bg
which is a special CSS variable we defined before.
If you save that and reload, this is the reset button look.
But that's now the finished form for adding a new product,
of course,
it's lacking all the logic for adding a product though.
At the moment, submitting the form, won't be handled,
the file upload won't work,
and we have no file upload preview.
These are all the features we have to work on now.