diff --git a/README.md b/README.md index 76d6d581..ead7f604 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repository is for the Integrating With HubSpot I: Foundations course. This To read the full directions, please go to the [practicum instructions](https://app.hubspot.com/academy/l/tracks/1092124/1093824/5493?language=en). -**Put your HubSpot developer test account custom objects URL link here:** https://app.hubspot.com/contacts/l/objects/${custom-obj-number}/views/all/list +**Put your HubSpot developer test account custom objects URL link here:** https://app-eu1.hubspot.com/contacts/145876913/objects/2-140871415/views/all/list ___ ## Tips: diff --git a/index.js b/index.js index f337a32d..b863e4d1 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ const express = require('express'); const axios = require('axios'); +require('dotenv').config(); const app = express(); app.set('view engine', 'pug'); @@ -7,65 +8,66 @@ app.use(express.static(__dirname + '/public')); app.use(express.urlencoded({ extended: true })); app.use(express.json()); -// * Please DO NOT INCLUDE the private app access token in your repo. Don't do this practicum in your normal account. -const PRIVATE_APP_ACCESS = ''; - -// TODO: ROUTE 1 - Create a new app.get route for the homepage to call your custom object data. Pass this data along to the front-end and create a new pug template in the views folder. - -// * Code for Route 1 goes here - -// TODO: ROUTE 2 - Create a new app.get route for the form to create or update new custom object data. Send this data along in the next route. - -// * Code for Route 2 goes here - -// TODO: ROUTE 3 - Create a new app.post route for the custom objects form to create or update your custom object data. Once executed, redirect the user to the homepage. - -// * Code for Route 3 goes here - -/** -* * This is sample code to give you a reference for how you should structure your calls. +// Keep your token in a .env file +const PRIVATE_APP_ACCESS = process.env.PRIVATE_APP_ACCESS; + +// ROUTE 1 - Homepage: Display custom object data +app.get('/', async (req, res) => { + const url = 'https://api.hubapi.com/crm/v3/objects/pets?properties=name,type,age__years_'; + + const headers = { + Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, + 'Content-Type': 'application/json' + }; + + try { + const response = await axios.get(url, { headers }); + const pets = response.data.results; + res.render('homepage', { + title: 'Custom Object Table', + pets + }); + } catch (err) { + console.error(err); + res.status(500).send('Error retrieving pets'); + } +}); -* * App.get sample -app.get('/contacts', async (req, res) => { - const contacts = 'https://api.hubspot.com/crm/v3/objects/contacts'; - const headers = { - Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, - 'Content-Type': 'application/json' - } - try { - const resp = await axios.get(contacts, { headers }); - const data = resp.data.results; - res.render('contacts', { title: 'Contacts | HubSpot APIs', data }); - } catch (error) { - console.error(error); - } +// ROUTE 2 - Show form to create/update object +app.get('/update-cobj', (req, res) => { + res.render('updates', { + title: 'Update Custom Object Form | Integrating With HubSpot I Practicum' + }); }); -* * App.post sample -app.post('/update', async (req, res) => { - const update = { - properties: { - "favorite_book": req.body.newVal - } +// ROUTE 3 - Handle form submission to create object +app.post('/update-cobj', async (req, res) => { + const petData = { + properties: { + name: req.body.name, + type: req.body.type, + age__years_: req.body.age__years_ } + }; + + const url = 'https://api.hubapi.com/crm/v3/objects/pets'; + + const headers = { + Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, + 'Content-Type': 'application/json' + }; + + try { + await axios.post(url, petData, { headers }); + res.redirect('/'); + } catch (err) { + console.error(err); + res.status(500).send('Error creating pet'); + } +}); - const email = req.query.email; - const updateContact = `https://api.hubapi.com/crm/v3/objects/contacts/${email}?idProperty=email`; - const headers = { - Authorization: `Bearer ${PRIVATE_APP_ACCESS}`, - 'Content-Type': 'application/json' - }; - - try { - await axios.patch(updateContact, update, { headers } ); - res.redirect('back'); - } catch(err) { - console.error(err); - } +// Start server +app.listen(3000, () => console.log('Listening on http://localhost:3000')); -}); -*/ -// * Localhost -app.listen(3000, () => console.log('Listening on http://localhost:3000')); \ No newline at end of file diff --git a/package.json b/package.json index 62db37aa..cffbd16c 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "axios": "^1.3.5", + "dotenv": "^16.4.7", "express": "^4.18.2", "pug": "^3.0.2" } diff --git a/views/homepage.pug b/views/homepage.pug new file mode 100644 index 00000000..c7d155f9 --- /dev/null +++ b/views/homepage.pug @@ -0,0 +1,62 @@ +doctype html +html + head + title= title + style. + body { + font-family: 'Helvetica Neue', sans-serif; + text-align: center; + background: #f7f7f7; + padding: 50px; + } + h1 { + font-size: 2em; + margin-bottom: 0; + } + h2 { + margin-top: 0; + color: #777; + font-weight: normal; + } + table { + margin: 20px auto; + border-collapse: collapse; + background: white; + box-shadow: 0 2px 6px rgba(0,0,0,0.1); + width: 400px; + } + th, td { + padding: 12px 15px; + border: 1px solid #ccc; + text-align: left; + } + th { + background: #eee; + } + a { + display: inline-block; + margin-top: 20px; + text-decoration: none; + color: #007bff; + } + body + h1 Custom Object Table + h2 Integrating With HubSpot I Practicum + + if pets.length + table + thead + tr + th Name + th Type + th Age (Years) + tbody + each pet in pets + tr + td= pet.properties.name + td= pet.properties.type + td= pet.properties.age__years_ + else + p No pets found. + + a(href='/update-cobj') Add / Update this table diff --git a/views/updates.pug b/views/updates.pug new file mode 100644 index 00000000..5ff77705 --- /dev/null +++ b/views/updates.pug @@ -0,0 +1,56 @@ +doctype html +html + head + title= title + style. + body { + font-family: 'Helvetica Neue', sans-serif; + text-align: center; + background: #f7f7f7; + padding: 50px; + } + form { + background: white; + padding: 20px; + display: inline-block; + box-shadow: 0 2px 6px rgba(0,0,0,0.1); + border-radius: 10px; + } + input { + display: block; + margin: 10px auto; + padding: 8px; + width: 200px; + border: 1px solid #ccc; + border-radius: 5px; + } + button { + background: #28a745; + color: white; + border: none; + padding: 10px 20px; + border-radius: 5px; + cursor: pointer; + } + a { + display: block; + margin-top: 15px; + color: #007bff; + text-decoration: none; + } + body + h1= title + form(method='POST', action='/update-cobj') + label(for='name') Name: + input(type='text', name='name', required=true) + + label(for='type') Type: + input(type='text', name='type', required=true) + + label(for='age__years_') Age (Years): + input(type='number', name='age__years_', required=true) + + button(type='submit') Submit + + a(href='/') Go back to the table +