Continue working with the Clark County Landscaping database, this time from an admin perspective.
In this lab, you’ll continue using the database we set up during the demo for Clark County Construction. You’ll be writing in a new app though, this time one that’s for admin.
-
Download the exercise materials from Frodo.
-
Navigate to the folder in your terminal.
-
Run
npm installto get the project’s dependencies installed -
Open your code and begin!
For our server files to work, we’re going to need dotenv.
-
Install ‘dotenv’ using
npm install dotenv -
Create a file at the root of your project called
.env -
In that file, create a
SERVER_PORTvariable and set it to 8765 (it needs to be this number or you’ll have to change all the front end code) -
Additionally, create a
CONNECTION_STRINGvariable and set it to your URI from bit.io (same as the one you used in the demo) -
At the top of
controller.js, require in thedotenvpackage and call theconfigmethod (you can ignore the other code in there until later steps) -
Optional: destructure
CONNECTION_STRINGfromprocess.envincontroller.js
In order to make queries to our database, we’ll need Sequelize.
-
Install Sequelize and its dependencies using
npm install sequelize pg pg-hstore -
In
controller.js, require thesequelizepackage and save it to a variable called Sequelize -
Initialize a new Sequelize instance, passing in your connection string and an object that looks like this:
{ dialect: 'postgres', dialectOptions: { ssl: { rejectUnauthorized: false } } } During the demo, we seeded our databases with lots of information. Now that we’re working on the admin side of things, we want a way to see all of our clients and their contact info. The front end is set up to receive an array of client info that contains data from both the cc_users and cc_clients tables, so we’ll need to use join.
-
In
controller.js’s export object, write a new function calledgetAllClients(make sure it acceptsreq&res) -
Using
sequelize.queryquery your database for all the columns in bothcc_usersandcc_clientsjoining them where theuser_idcolumn matches -
Handle the promise with
.then()passing in a callback:dbRes => res.status(200).send(dbRes[0])(you can also add a.catch) -
In
index.js, comment line 20 back in (this line:app.get('/clients', getAllClients)) -
Run
nodemon(make sure you’re in the right directory, also you can keep it running for the duration of the lab) -
Open
clients.html(public folder) in your browser -
You should be seeing your client information!
If you head to the home page of CCL Admin Portal, you’ll see sections for Pending, Upcoming, and Past Appointments. Pending appointments are those that have been requested but not yet approved. Let’s set up a query for those now.
-
In
controller.js, write a new function calledgetPendingAppointments -
Using
sequelize.queryquery your database for all appointments that are not approved (approved = false) and order them by date with the most recent dates at the top. -
Handle the promise with
.then() passing in a callback: ``dbRes => res.status(200).send(dbRes[0])(you can also add a.catch) -
In
index.js, comment line 23 and 24 back in (these lines:app.get('/pending',getPendingAppointments), andapp.get('/upcoming', getUpcomingAppointments)) -
In
home.js(public folder), comment line 107 back in (this line:getPendingAppointments()) -
Navigate to
home.htmlin your browser -
You should be seeing pending appointments!
Next, you’ll be writing a query that’s similar to the triple join query from getUpcomingAppointments, reference it as you write yours. This one will get all of the past appointments.
-
In
controller.js, write a new function calledgetPastAppointments -
Using
sequelize.queryquery your database for the following columns from their respective tables cc_appointments: appt_id, date, service_type, notes. cc_users: first_name, last_name. Reference thegetUpcomingAppointmentsfunction to see how to join all the information together (you’ll need all the same tables again). Make sure to select only rows where both theapprovedandcompletedvalues are true. And order the results by date with the most recent at the top. -
Handle the promise with
.then()passing in a callback:dbRes => res.status(200).send(dbRes[0])(you can also add a.catch) -
In
index.js, comment line 25 back in (this line:app.get('/appt', getPastAppointments)) -
In
home.js(public folder), comment lines 108 and 109 back in (these lines:getUpcomingAppointments()andgetPastAppointments()) -
Navigate to
home.htmlin your browser -
Now you should be able to see all the past appointments as well as the pending ones.
Part of this function has been given to you because it’s taking care of auto-assigning employees to appointments for us. Finish it up with one query and the ‘Mark Approved’ buttons on the front end should work.
-
In the
approveAppointmentfunction, delete*****YOUR CODE HERE****and replace it with a query that updates the appointments table. It should setapprovedto equal true where theappt_idmatches the one coming from thereq.body, which has been destructured for you as apptId. -
In
index.js, comment line 26 back in (this line:app.put('/approve', approveAppointment)) -
Navigate to
home.htmlin your browser -
Test out the ‘Mark Approved’ button!
No appointments to approve? There should be some appointments waiting for you from the demo. If there are not, start up your demo app again and request a few. Since they run on different ports, you can actually have your demo app and your lab app running at the same time.
Last but not least, let’s make the ‘Mark Completed’ button work.
-
In
controller.js, write a new function calledcompleteAppointment -
Using
sequelize.queryquery your database to update the appointments table. It should setcompletedto equal true where theappt_idmatches the one coming from thereq.body. (You can destructureapptIdlike in the previous step or usereq.body.apptId.) -
Handle the promise with
.then()passing in a callback:dbRes => res.status(200).send(dbRes[0])(you can also add a.catch) -
In
index.js, comment line 27 back in (this line:app.put('/complete', completeAppointment)) -
Navigate to
home.htmlin your browser -
Your whole page should work now! Once pending appointments are approved, they should move to the upcoming section, and once those are complete they should move to the past section.
Push your code to GitHub!
Read about subqueries below and then complete the given problems using the postgres sandbox. Save your answers in a new file called subqueries.sql, which you can create in the lab exercise folder you’ve been working in.
-
Subqueries are a queries that rely on an outer query.
-
A subquery is used to return data that will be used in the main query as a condition to further restrict the data to be retrieved.
Open up the postgres sandbox to complete these problems. Save your answers in a file subqueries.sql. Push to GitHub when you’re done.
-
Get all invoices where the unit_price on the invoice_line is greater than $0.99.
-
Get all playlist tracks where the playlist name is Music.
-
Get all track names for playlist_id 5.
-
Get all tracks where the genre is Comedy.
-
Get all tracks where the album is Fireball.
-
Get all tracks for the artist Queen ( 2 nested subqueries ).