So this time around, we want to create the necessary code to make this screen in our admin tool actually
useful, and that is the listing of all reservations.
Now we're going to have another one for listing new reservations, which, of course, means we're going
to have to add a column to our database table for reservations that indicates whether it's been processed
or not.
If it's been processed, it's not new.
If it has not been processed, then it is new.
But we'll do that when we get to new reservations.
So if you think about the things we need to do here to start with, we're going to have to have a database
query that gets a list of all reservations for us.
And then we're going to have to create a handler that calls that database routine.
And then somehow we're going to have to present that information in a meaningful fashion in this particular
window.
So let's get started.
Let's go back to our idea and look at our handlers, which are right here.
And the one we're doing right now is listing all reservations.
So before we we actually send this information off, before we render this template, we need to get
the list of all reservations from the database, which means we need to go to our post Glasgow and add
a new function here and then add it to our repository and add one in our test repository as well.
So I'll create a new function, which I'll call it has to have the receiver Postgrads DB Reffo and I'll
call this all reservations, which seems like a meaningful name.
And it's not going to take any parameters because we want all of the reservations and it will return
a slice of model's reservation and potentially an error.
OK, as we usually do, we'll copy our context lines and paste them in here and then we'll create a
variable which I'll call reservations and it will be a type of type models reservation, a slice of
models reservation.
And now we'll do our query.
And the query is really simple.
I'll put it in tactics so I can put it on as many lines as I want select and I'm going to aliased the
table reservations to the letter are we want the ID, the first name.
The last name.
I don't know.
I get an either.
I should be in our first name, last name, email the start date.
And the phone I'll put after email.
The end date.
The remedy.
The created at.
The updated at.
And we're going to also want to get the room information, so we'll join that table in a minute and
I'll aliased to R.M. for the remedy the Rumney.
And we're going to we're going to be selecting that from reservations are and we will join left join
rooms, R.M. and we'll join it on our dot room.
ID equals our Amde ID.
And I want to order this in any particular way.
I probably do.
Always good to get information, lots of information and sort it in some meaningful fashion.
So I'll order this by our start date and I'll make it ascending.
And if that doesn't suit our purposes, we can change it later.
So now I have the query.
I have a place to store this information.
So let's get some rose and potentially an error from the database by calling m dot db dot query context.
And give it the context and give it a query, and it has no arguments in this case and we'll check for
an error, if error is not equal to nil, just return our empty variable, which is reservations and
the error.
Otherwise, let's scan this for Rosie next, what are we going to do inside of this?
We're going to create a new new variable and I'll just call it eye for item and let's have type models,
DOT reservation.
And now we'll scan our information into this newly created eye variable rose dot scan.
And I'll put this on multiple lines, so it's readable and we're going to scan into the variable eye
the ID, which is the first thing in our select statement, then we'll scan into our first name and
let's just duplicate this a few times to make it faster.
Then the last name, then email, then phone and start date.
An end date and then remedy.
And after that, we're scanning our created that are updated at.
And now we're scanning into our room, the I.D. and then room name, room, room name.
All right, I'm not going to bother with the creator created and an updated that it out for the room
because I'm actually not going to use that information.
And if that doesn't work, if we have an error, we'll just check for the error.
If error is not equal to nil.
We'll return once again our reservations and the error.
Otherwise append this.
So we'll append our new variable to the reservations.
Slice reservations equals append reservations.
And I and then, as is always good practice, after we're finished, our for Loop will check for one
more error.
If error equals Rossdale error, error is not equal to nil return reservations.
And the air and I think I missed some parentheses here, it looks like I did.
Otherwise, everything worked, so we'll just return reservations and nil, no error.
OK, so let's give this thing a comment.
Returns a slice of all reservations and let's copy this and put it into our repository, which is under
internal repository repository.
So we'll put that right here and then we'll copy the entire function.
And go to our test tube repo and put it in there and just make it as simple as we possibly can.
So I'll delete all of this information, delete the context that we're not using and give it the correct
receiver, which is tested repo there.
So this should compile.
Let's make sure it does.
It does.
OK, so let's stop our application and go put this in our handler and just see if it actually works.
So back to our handlers and we called this all reservations.
So let's get our reservations.
I'll call it reservations.
Error is a sign, the value of Magdeburg, all reservations if air is not equal to nil.
And I will just do helper's that server error.
And return, so now we have our reservations, let's put them somewhere, let's put a crate, our slice
for data data is a sign the value of make a map string interface data and I'll call the variable that
I'm going to pass reservations.
Is equal to reservations, and here I will pass that data in using our predefine member data, which
is going to be equal to data.
OK, so this should work as well.
So now if this works properly, we actually should have our reservations available to us in this template
admin on reservations page.
So let's see if we do, I'll get rid of the all reservations content and just to see if it works, I
will get the variable from my data and store it in a local variable, which I'll call Rez is a the value
of index dot data and I called it reservations.
That's the key I look it up with.
And now I should be able to range rez and all I'll do just to make sure this is working is close this
with an end.
And inside of this, I will just print out the IDs one at a time.
Each one on its own line.
So let's compile this run.
And see if we got everything right.
Reload this, I got a log in, of course, admin added Mint.com Password.
Go back to our dashboard and look at all reservations, and there they are.
So I have a bunch of reservations in there.
So now we've got our information being passed to this particular screen and that seems to work well.
So one thing I believe I forgot to do, and I probably should do that right now is if I go to Postgres,
did I defer Roques clothes?
I did not defer rose dot clothes.
That's better.
Otherwise, I'm going to have a memory leak.
So we have this actually working the way we want to.
But the information we're displaying is not ideal.
It doesn't look very good.
It's just a list of IDs.
So obviously this is a lot of rows of information coming from the database that I want to display on
the screen.
So probably the best way to do this is to create a table.
So let's do that.
Let's go back to our original reservations page.
And instead of just doing it this way and just displaying the ID, let's get rid of that and let's create
a table.
So we'll do the first part of our table outside of the loop and we'll do inside of the loop each of
the rows of information.
So let's create a table, table, class equals table, table striped and I'll add table cover as well.
And that way when people roll their mouse over a given row in the table, it will light up and I'll
give this an ID ID equals already.
I'm not going to do anything with that yet, but I will later.
And the closing table tag, of course, has to be after this part.
And here we want our ticket to give it a nicely formatted head and then we want a tier and then one
t h for each of the columns in the table and I'll display all of the useful information.
So I'll duplicate that a few times.
I'll put the ID there, I'll put the guests last name and then I'll put the room they're staying in
and then I'll put the arrival and the departure and that's probably enough.
So that's how she had then we want our Tibaldi and the T bodies.
Closing tag has to go after a range and let's format this whole thing.
And every time I Leapster this, I'm going to be putting one rowin.
So I need a Rohtak and then I have my TDRS td and the first one is just the ID and I'll duplicate this
a few times then the last name.
Then the room, not room name, because the room is actually stored as an entry in the struct, but
it it itself is also a struct of type room.
And then we want start date or start date is the arrival and end date is the departure.
All right.
Now, that should work.
Let's give this a try.
Go back and just reload this page.
OK, that's not bad.
But as you can see, as we start adding more and more reservations, this is going to become unwieldy.
If we have 200 reservations, I'm going to be scrolling along way down.
I have no means of searching for a particular entry.
There's got to be a better way of doing this.
And in fact, there is what we want is sometimes called a data grid and sometimes called a data table.
And there are lots of them out there.
Most of them use query.
But I made that decision early on that I want to use as little query as I possibly can.
And yes, I know that this uses query and that's fine.
But I want to think about the future and I want to, if possible, avoid using query as much as I can.
Well, there's a really good package based upon a really popular plug in for Jake Query called Data
Tables.
And this one is called Simple Data Tables.
And this is the URL right here.
It's on GitHub dot com.
And I'll put a link to this on the course resources for this lecture.
This one doesn't use query.
It's lightweight, it's extendible, it's dependency free.
So it's pure JavaScript.
And this looks like it's exactly what I want.
So I'm going to use this and I'm going to copy these links that point to a content delivery network
that allows us to use this without having to download it.
And I'll go back to my template and at the top, I'll take advantage of that section we defined in our
template called S.O.S.
And I'll put my untag in there and then format this and then I'll just put in, first of all, the top
part, I'll put in the link to the success and then I'll cut the script part, the JavaScript, which
I guess I missed the tag there.
And now at the bottom, I'll define, you know, G.S., I'll paste in what I just cut and close that.
OK, now how do we use this thing?
Let's go back and look.
Features in store QuickStart if using the CDN, this is what we're going to be using somebody's copy
this and come down here and in my jazz section of my template, I'll put in a script tag paste in what
they just gave me.
I did not call my table or the ID of my table.
I called it all.
Red's not my table.
So it says what we're doing is this great.
Let's just get rid of all those other options and just go with the default install and see how that
looks.
So hopefully this will work.
Let's save this, go back, find our page and reload this.
And look, that is much nicer.
It really is.
I can search for things.
So if I search, for example, for Wayne there, there's Wayne, I can pageant through the results,
go back and forth.
I can show more entries per page if I want to.
I can show five per page.
This looks ideal.
Now I have my nice hover thing here, which looks very good, but my stripe isn't working.
Why isn't my stripe working?
Well, if I inspect this, if I.
Right.
Click on it and choose inspect element.
Looks like somewhere in here I have a content wrapper, so that seems to be covering the entire section.
And if I look at the CFS for this, it has a background.
If I change that background to white, that looks a little better.
It does.
Now I have my stripe table.
I still have my hover effect.
So what I'll do is open my base template and change the CSC for content wrapper, which is easy enough.
Let's go back over here and find our templates and find our admin layout.
And in the CSC section at the top, just before my per page access, I'll put in a style tag.
And I'll overate content wrapper and give it a background of white.
Now I want to come back here and close this and reload the page that should stay white.
OK, that's much better.
Now, obviously, listing the reservations isn't that helpful.
I can see what's going on.
I can I can sort my room if I want to by clicking on the tall column, and that works really well.
But there's a couple of things I don't like here.
First of all, I should have some means of clicking on a given reservation and going to detailed information
about it, maybe modifying information, maybe deleting information.
And also this date is way too long.
I just want 20, 21, zero three 10.
I don't want the rest of this stuff because I'm always storing things at midnight.
I'm just storing things by day, not by time.
So I want to make a couple of changes.
And what I'm going to do, first of all, is go over to my render package.
So let's go back to our ID and find our packages for rendered right here.
And you may recall a long time ago we created this variable right here called Functions, and it is
a type template, funk map.
And what this allows us to do is to specify the certain functions that are available to our goaland
templates.
So what I'm going to do is create a new function and I'll do it right down here and I'll call that func
human date.
In other words, a date that's nice for humans to read and it will take an argument of named T of type
time dot time and it will return a string.
And all I'm going to do is take that time that I'm past and send it back in a particular format.
I'll return t dot format and give it the layout.
And the layout I want is we're in four digits and then the month in to digits and then the day in digits.
And this is again using that strange reference time that goal uses.
Now I have defined this as human date and in my func map I can actually put in a name that I can refer
to in my goal line template, which I'll call human date with a lowercase H.
And that's going to be equal to Human Day.
With no parentheses now, when I restart my application, I will have access to a function in my Gullwing
templates called human date that points to this function human date, which is this one right here.
So let's give this a comment.
Returns time in year, year, year, month, month data format.
OK, so let's stop our application.
And I'm going to do one more thing here just because I hate having to log in every time I'm going to
find my roots.
And I'm going to disable my off so I can while developing reload admin page templates without having
to log in every time.
And before I go into production, I'll just uncommented that and then our security will be back in place.
So let's run our application.
It's running and let's go back to our admin layout are our admin, our reservations page, and let's
add that function just to this one human date, which is what I called it in that funk map back in my
render package.
And let's go reload the page.
That looks a little better.
OK, so I've now formatted the day, the date in a way that is less intrusive.
It doesn't take up all this horizontal space and let's put the same function on end date, human date.
And reload, perfect.
OK, so the last thing I want to add right now is I want to make the last name clickable, I want to
make it clickable.
So it will take me to a screen that gives me more information about that particular reservation.
And we'll just make the link and then we'll make the actual handler for that link later on.
So let's go back to our template here.
And I want to put it on last name, so I'll give myself some room.
And it'll just create a link here, a H.F. equals and what do I want that link to be?
Well, it's going to start with admin because I want it to be password protected and it's in the reservations
part.
So I'll use reservations and then I want to put in the ID.
One more thing I'll add here, I get that at closing e-TAG down where it belongs, I know I'm going
to be listing all reservations and I know I'm going to be listing new reservations.
So this is the all part.
So I'll just put all there.
So the full you URL to click on a reservation from this screen will be slash admin, slash reservations,
slash all and then the idea of the current reservation.
So let's just reload that page and make sure that it actually works the way we want it to and point
at it.
And if I look in the lower left hand corner slash admin slash slash all five and there's six and there's
four.
Perfect.
OK, well that seems like it's coming along reasonably well.
The last thing I want to do here is I want to change this so that it's sorted by arrival date and I
can do that.
If you look at the documentation for this simple, simple data, tables, documentation, there's all
kinds of things listed here.
And I already read it.
And I know that if I come down here and in the curly brackets, when I initialize data tables, I actually
can say select is an option.
And I want to go to the third column starting at zero and sort by descending.
OK, so we're select three sort descending, so I'm selecting the third column starting at zero zero
one, two, three, and now this should be sorted by descending.
So let's reload this.
And it is it's working quite well.
So twenty, twenty one that seems to work well and I can sort by date this way.
Looks great.
OK, that's a little bit better.
The last thing I want to do is I have this script and the script is going to try to run as soon as it
possibly can.
And I want to defer the running of that script until the document is actually loaded, until everything
is there that needs to be there just to be safe.
So I'll just put a listener on here document at event listener.
And the event I'm listening for is Dom Content loaded and I want to after the DOM content is loaded,
after everything is loaded, run a function and now I'll take this part, these last two things and
get those out of there and put them after this and format everything.
And now this won't run until the DOM content, until all of the necessary content is loaded.
Let's just make sure it works.
Reload the page and it's good.
All right.
So we have this done now.
That's the all reservations and that seems to work pretty well.
We're going to do new reservations next, and that's going to require another database query that gets
us just new reservations, which is also going to require that we modify the structure for our reservations
table and put a new column in there, something like process with a default of zero.
So when a new reservation comes in, it will have a processed column set to the value of zero.
And after we process it saying, yes, I'm aware of this reservation, it's confirmed we'll change that
to a one or something like that.
And that'll give us a means of finding reservations that are processed and finding new reservations.
And we'll take care of that in the next lecture.