diff --git a/README.md b/README.md index 76d6d581..b752daa0 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.hubspot.com/property-settings/49610863/properties?type=0-1 ___ ## Tips: diff --git a/index.js b/index.js index f337a32d..c75928e7 100644 --- a/index.js +++ b/index.js @@ -1,71 +1,73 @@ const express = require('express'); const axios = require('axios'); const app = express(); +require('dotenv').config(); app.set('view engine', 'pug'); 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 = ''; +const PRIVATE_APP_ACCESS = process.env.HUBSPOT_API_KEY; -// 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. +// ROUTE 1 - Homepage route to list contacts +app.get('/', async (req, res) => { + const url = 'https://api.hubapi.com/crm/v3/objects/contacts?properties=firstname,hs_role,company&limit=100&sort=-createdAt'; -// * 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. - -* * 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); + const response = await axios.get(url, { headers }); + var records = response.data.results; + records.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); + + // Get only the 10 most recent + records = records.slice(0, 10); + + res.render('homepage', { title: 'Recent Contact Records', records }); + } catch (err) { + console.error(err.response?.data || err); + res.send('Failed to fetch contact records.'); } }); -* * App.post sample -app.post('/update', async (req, res) => { - const update = { +// ROUTE 2 - Render form to add a contact +app.get('/update-cobj', (req, res) => { + res.render('updates', { title: 'Add New Contact | HubSpot Integration Practicum' }); +}); + +// ROUTE 3 - Handle contact form submission +app.post('/update-cobj', async (req, res) => { + const { firstname, hs_role, company } = req.body; + + console.log('Form submission:', req.body); // for debugging + + const contactData = { properties: { - "favorite_book": req.body.newVal + firstname, + hs_role, + company } - } + }; + + const url = 'https://api.hubapi.com/crm/v3/objects/contacts'; - 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); + try { + const response = await axios.post(url, contactData, { headers }); + console.log('Contact created:', response.data); + res.redirect('/'); + } catch (err) { + console.error('Error creating contact:', err.response?.data || err.message); + res.status(500).send('Failed to create contact.'); } - }); -*/ - -// * 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..f40ac940 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "author": "HubSpot Academy learner", "license": "ISC", "dependencies": { - "axios": "^1.3.5", + "axios": "^1.10.0", + "dotenv": "^17.0.1", "express": "^4.18.2", "pug": "^3.0.2" } diff --git a/views/homepage.html b/views/homepage.html new file mode 100644 index 00000000..e69de29b diff --git a/views/homepage.pug b/views/homepage.pug new file mode 100644 index 00000000..4a23d43e --- /dev/null +++ b/views/homepage.pug @@ -0,0 +1,24 @@ +doctype html +html + head + title= title + body + h1= title + + a(href='/update-cobj') Add a new contact + + if records.length + table(border='1' cellpadding='8') + thead + tr + th First Name + th Role + th Company + tbody + each record in records + tr + td= record.properties.firstname + td= record.properties.hs_role + td= record.properties.company + else + p No contact records found. \ No newline at end of file diff --git a/views/updates.html b/views/updates.html new file mode 100644 index 00000000..b7893577 --- /dev/null +++ b/views/updates.html @@ -0,0 +1 @@ +

Fill in the form below to create a new contact.

Return to the homepage \ No newline at end of file diff --git a/views/updates.pug b/views/updates.pug new file mode 100644 index 00000000..585f6c80 --- /dev/null +++ b/views/updates.pug @@ -0,0 +1,27 @@ +doctype html +html + head + title= title + body + h1= title + p Fill in the form below to create a new contact. + + form(action='/update-cobj' method='POST') + div + label(for='firstname') First Name: + input(type='text' id='firstname' name='firstname' required) + div + label(for='hs_role') Role: + select(id='hs_role' name='hs_role') + option(value='accounting') Accounting + option(value='business_development') Business Development + option(value='consulting') Consulting + option(value='customer_service') Customer Service + option(value='design') Design + div + label(for='company') Company: + input(type='text' id='company' name='company' required) + div + button(type='submit') Submit + + a(href='/') Return to the homepage \ No newline at end of file