Run the following command from root folder of the cloned project to install all dependencies.
npm install
In order to verify that everything is setup correctly, run the following command, which should show you the failing tests. This is good! We'll be fixing these tests once we jump into the build step.
npm run test
Every time you want to check your work locally you can type that command, and it will report the status of every task in that module.
As you move through the modules, you can run module-specific tests with the script npm run test:module1, replacing the number with one that corresponds with the module you are working in.
In order to see your changes in a browser, you can run npm start to start the application, and when you visit http://localhost:3000 in a browser, you should see your components rendered.
@app-require-built-ins In app.js require the built-in library fs and store a reference to it in a const called fs. Next, require the built-in library path and store a reference to it in a const called path.
@app-require-express-const-app In app.js, require the express framework and store a reference to it in a const called express. Next, call the express function and store it in a const called app.
@app-set-views-directory-engine Still in app.js, use the set function of your newly created app to configure the directory where our views can be found. Using the same set function, set the view engine to ejs. Hint: path.join() & __dirname
@app-use-express-static All of our CSS/JS for the client-side is found in the public directory. We need to point express to public.
- In app.js call the
usefunction ofappwith a call to theexpress.static()function as the only parameter. express.static()should be passed the full path to thepublicdirectory. Hint:path.join()&__dirname
@index-ejs-create-view-file Create a new file called index.ejs in the src/views/ directory.
@index-ejs-create-view In the newly created file index.ejs complete the following:
- Include
header.ejsHint: <%- %> - Add a
divelement with a class ofcontainer. - In the container div display the value of the
titlekey in anh1element. Hint: <%= %> - Add an anchor element below the
h1that points to the/profileURL path, and has the text contentProfile. - Below the container div add a line break and another anchor element that points to the
/transferURL path with the text contentTransfer. - Include
footer.ejsHint: <%- %>
@app-get-index-route In app.js create a get route that points at the root URL path '/'. Render the index view (created in the next step) and pass an object with a single key value pair, title: 'Index'.
@app-listen-console-log In app.js using the listen function to create a server that listens on port 3000 and then prints the message PS Project Running on port 3000! to the console after the server is created.
@app-read-account-data In app.js above the index route, use the readFileSync function of the built-in fs library to read the contents of the file located at src/json/accounts.json. Declare a const called accountData to store the contents of the file. accountData now contains JSON, use JSON.parse to convert it to a javascript object. Declare a const called accounts to store this javascript object. Note: read the file with the UTF8 encoding.
@app-read-user-data In app.js near the index route, use the readFileSync function of the built-in fs library to read the contents of the file located at src/json/users.json. Declare a const called userData to store the contents of the file. userData now contains JSON, use JSON.parse to convert it to a javascript object. Declare a const called users to store this javascript object. Note: read the file with the UTF8 encoding.
@app-update-index-route In app.js update the object passed to the existing index route. The title should be Account Summary. A new key value pair should be added, accounts: accounts.
@index-ejs-update-view In index.ejs and after the container div, add the ejs markup to include the summary view for each account in the accounts variable, savings, checking, and credit. Hint: you will have three include statements(<%- %>), each include function will be passed a different account, i.e { account: accounts.checking }.
@app-get-savings-account-route In app.js near the index route, create a get route that points at the /savings URL path. Render the account view and pass an object with the following key value pair:
account: accounts.savings
@app-get-other-account-routes Now that you have created the savings account route, create similar routes for the checking and credit accounts in the app.js file.
@account-ejs-show-transactions In account.ejs after the header markup, add the ejs markup to include the transactions view. Pass the include function an object with the following key value pair:
account: account
@profile-ejs-create-view-file Create a new file called profile.ejs in the src/views/ directory.
@profile-ejs-create-view In the newly created file profile.ejs complete the following:
- Include
header.ejsHint: <%- %> - Add an
h1element with the text contentProfile - Add a
divelement below theh1that displays each detail of theuserobject (passed to the view in the next step) on a new line. The details are user.name, user.username, user.phone, user.email, and user.address. - Below the
divadd a line break, then an anchor element that points to the root URL path and has the text contentBack to Account Summary. - Include
footer.ejsHint: <%- %>
@app-get-profile-route Back In app.js below the account get routes create a get route that points at the /profile URL path. Render the profile view and pass an object with the following key value pair:
user: users[0]
@app-urlencoded-form-data In app.js near your other app.use statement add express middleware to handle POST data. With the use function add the express.urlencoded middleware to app. Make sure to set the extended option to true.
@app-get-transfer-route Near your other routes in app.js create a get route that points to the /transfer URL path. It should render the transfer view.
@transfer-ejs-update-view In transfer.ejs in the src/views/ directory complete the following:
- Add the necessary attributes to the
transferFormso that it posts to a transfer route. - Add a
nameandidattribute with a value offromto the first select. - Add a
nameandidattribute with a value oftoto the second select.
@app-post-transfer-route Switch back to app.js and create a post route that points to the /transfer URL path. We will fill in the body of the function for this route in the next few steps.
@app-post-transfer-route-from-balance Still in app.js and in the function body of the post route we are going to calculate the new balances for the account we are transferring from.
We have several values that have been entered into the HTML form in transfer.ejs. Upon form submission the request body will contain from, to, and amount. Current account balances are stored in the accounts object. As an example to access the current balance for the savings account use accounts["savings"].balance.
- Subtract the amount entered from the account selected (req.body.from) and save it back to the accounts object.
@app-post-transfer-route-to-balance Still in app.js and in the function body of the post route we are going to calculate the new balances for the account we are transferring to.
We have several values that have been entered into the HTML form in transfer.ejs. Upon form submission the request body will contain from, to, and amount. Current account balances are stored in the accounts object. As an example to access the current balance for the savings account use accounts["savings"].balance.
- Add the amount entered to the account selected (req.body.to) and save it back to back to the accounts object, remember to use
parseInt()on both values when adding.
@app-post-transfer-route-convert-json Still in app.js and in the function body of the post route, convert the accounts javascript object to a string using the JSON.stringify function save this string in a variable called accountsJSON.
@app-post-transfer-route-write-json Still in app.js and in the function body of the post route, use the writeFileSync function of the built-in fs library to write the variable accountsJSON to the file located at json/accounts.json.
Notes:
- If at any point
accounts.jsongets overwritten and you would like the original back copy the JSON fromaccount_backup.jsontoaccount.json - Specify the absolute file path using
path.join&__dirname - Write the file with the
UTF8encoding.
@app-post-transfer-route-redirect Still in app.js and in the function body of the post route, render the transfer view and pass an object with the following key value pair:
message: "Transfer Completed"
@app-payment-feature The payment feature of the application is similar to the transfer feature. Add this new feature using this general outline of the steps:
- Near your existing routes in
app.jscreate a get route with a URL path of/paymentthat renders thepaymentview. - Below the payment get route create a post route with a URL path of
/paymentand an empty function. - In the body of the payment post route function:
- Subtract
req.body.amountfromaccounts.credit.balanceand save it back toaccounts.credit.balance - Add
req.body.amounttoaccounts.credit.availableand save it back toaccounts.credit.availableremember to useparseInt()on both values when adding. - Convert the
accountsjavascript object to a JSON string and save it to a variable calledaccountsJSON - Write
accountsJSONto a file. Note: write the file with theUTF8encoding. - Render the
paymentview and pass an object with the following key value pair,{ message: "Payment Successful", account: accounts.credit }
- Subtract
@data-js-create-file Create a new file called data.js in the root of the src/ directory.
@data-js-require-built-ins In data.js require the built-in library fs and store a reference to it in a const called fs. Next, require the built-in library path and store a reference to it in a const called path.
@data-js-transition-const-accounts In app.js locate the lines that are responsible for reading and parsing JSON from the src/json/accounts.json file. Copy and paste them to the new data.js file below the require statements.
@data-js-transition-const-users In app.js locate the lines that are responsible for reading and parsing JSON from the src/json/users.json file. Copy and paste them to the new data.js file below the accounts const.
@data-js-write-json-function In data.js below the account and user data lines create a function called writeJSON. Hint: It is best to use ES6 arrow style function (=>).
@data-js-write-json-function-body In app.js locate the lines in the transfer post route function body that are responsible for writing JSON data to a file. Hint: there are two lines. Copy these lines to the body of the writeJSON function in the data.js file.
@data-js-export-data In data.js use module.exports to export an object containing the constants accounts, users, and the writeJSON function.
@app-js-require-data-js Back In app.js require data.js and at the same time use object destructing to create three constants for accounts, users, and writeJSON. Remove the lines in app.js that create the accountData, accounts, userData, and users consts. accounts, users, and the writeJSON function are now brought in by the require statement. Note: use relative paths to require the data module './data'
@app-js-call-write-json-transfer In app.js locate the lines in the transfer post route function body that are responsible for writing JSON data to a file and replace them with a call to the writeJSON() function.
@app-js-call-write-json-payment In app.js locate the lines in the payment post route function body that are responsible for writing JSON data to a file and replace them with a call to the writeJSON() function.
@routes-accounts-js-create-file Create a new file called accounts.js in the directory src/routes/ (you will need to create this directory).
@routes-accounts-js-require-express In the new accounts.js require the express framework and store a reference to it in a const called express. Next, call the express.Router() function and store it in a const called router.
@routes-accounts-js-require-data In accounts.js require data.js and at the same time use object destructuring to create one constant called accounts. Note: use relative paths to require the data module. Use '../data' since it is one level up.
@routes-accounts-js-move-routes In app.js locate the savings, checking, and credit get routes, cut and paste these routes in accounts.js below the require statements. Now in accounts.js update the routes to be part of the router by replacing app.get with router.get.
@routes-accounts-js-export-router In accounts.js export the router using the module.exports syntax.
@routes-services-js-create-file Create a new file called services.js in the directory src/routes/.
@routes-services-js-require-express In the new services.js require the express framework and store a reference to it in a const called express. Next, call the express.Router() function and store it in a const called router.
@routes-services-js-require-data In services.js require data.js and at the same time use object destructing to create two constants called accounts and writeJSON. Note: use relative paths to require the data module. Use '../data' since it is one level up.
@routes-services-js-move-routes In app.js locate the transfer and payment post and get routes, cut and paste these routes to services.js below the require statements. Now in services.js update the routes to be part of the router by replacing app.get with router.get.
@routes-services-js-export-router In services.js export the router using the module.exports syntax.
@app-require-account-routes Switch to app.js and require the routes/accounts.js file and store a reference to it in a const called accountRoutes.
@app-require-services-routes Switch to app.js and require the routes/services.js file and store a reference to it in a const called servicesRoutes.
@app-use-account-routes In app.js where your account routes used to be, call the use function on app with two arguments. The first argument should be /account and the second is the accountRoutes const.
@app-use-services-routes In app.js where your account routes used to be, call the use function on app with two arguments. The first argument should be /services and the second is the servicesRoutes const.
@views-update-for-routes Since all URL paths have changed for accounts and services we need to change the following views:
- In
src/views/index.ejschangehref="/transfer"tohref="/services/transfer" - In
src/views/summary.ejschangehref="<%= account.unique_name %>"tohref="/account/<%= account.unique_name %>" - In
src/views/transfer.ejschangeaction="/transfer"toaction="/services/transfer" - In
src/views/payment.ejschangeaction="/payment"toaction="/services/payment" - In
src/views/account.ejschangehref="/payment"tohref="/services/payment"