diff --git a/index.js b/index.js index f337a32d..2ead7540 100644 --- a/index.js +++ b/index.js @@ -1,71 +1,86 @@ +require('dotenv').config(); const express = require('express'); const axios = require('axios'); +const hubspot = require('@hubspot/api-client'); const app = express(); +const hubspotClient = new hubspot.Client({ + accessToken: process.env.PRIVATE_APP_ACCESS +}); + 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 = ''; - -// 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. - -* * 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 1 — Homepage: Mostrar todos los contactos */ +app.get('/', async (req, res) => { + try { + const contactsResponse = await hubspotClient.crm.contacts.basicApi.getPage( + 10, + undefined, + [ + 'email', + 'firstname', + 'lastname', + 'icecream_flavor', + 'message', + 'feeling_after_eating', + 'second_scoop' + ] + ); + + const contacts = contactsResponse.results; + + res.render('contacts', { + title: 'Dessert Directory | Contacts', + data: contacts + }); + } catch (error) { + console.error('❌ Error fetching contacts:', error.message || error); + res.status(500).send('Error fetching contacts'); + } }); -* * App.post sample -app.post('/update', async (req, res) => { - const update = { - properties: { - "favorite_book": req.body.newVal - } - } - - 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); - } - +//** ✅ ROUTE 2 — Formulario para crear nuevo contacto */ +app.get('/update-contact', (req, res) => { + res.render('updates', { + title: 'Update Contact | Dessert Directory' + }); +}); +//** ✅ ROUTE 3 +app.post('/update-contact', async (req, res) => { + const { + fullname, + email, + icecream_flavor, + message, + feeling_after_eating, + second_scoop + } = req.body; + + const [firstname, ...rest] = fullname.split(' '); + const lastname = rest.join(' ') || 'DessertLover'; + + try { + const createContact = await hubspotClient.crm.contacts.basicApi.create({ + properties: { + email, + firstname, + lastname, + icecream_flavor, + message, + feeling_after_eating, + second_scoop + } + }); + + console.log('✅ Contact created:', createContact.id); + res.redirect('/'); + } catch (error) { + console.error('❌ Error creating contact:', error.message || error); + res.status(500).send(`

Something went wrong.

${error.message}

`); + } }); -*/ - -// * Localhost -app.listen(3000, () => console.log('Listening on http://localhost:3000')); \ No newline at end of file +app.listen(3000, () => console.log('Listening on http://localhost:3000')); diff --git a/package.json b/package.json index 62db37aa..5b5f970e 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,10 @@ "author": "HubSpot Academy learner", "license": "ISC", "dependencies": { - "axios": "^1.3.5", - "express": "^4.18.2", + "@hubspot/api-client": "^13.0.0", + "axios": "^1.10.0", + "dotenv": "^17.0.1", + "express": "^4.21.2", "pug": "^3.0.2" } } diff --git a/views/contacts.pug b/views/contacts.pug index c600ca01..80474aee 100644 --- a/views/contacts.pug +++ b/views/contacts.pug @@ -1,15 +1,22 @@ -//- ** This is a sample of a pug template and how it uses the data passed to it from index.js. - -//- doctype html -//- html -//- head -//- title= `${title}` -//- meta(name="viewport" content="width=device-width, initial-scale=1") -//- link(rel="stylesheet", href="/css/style.css") -//- body -//- h1 Contacts -//- .cards -//- each contact in data -//- .card -//- h2.card__name #{contact.properties.firstname} #{contact.properties.lastname} -//- p.card__email #{contact.properties.email} \ No newline at end of file +doctype html +html + head + title= title + meta(name="viewport", content="width=device-width, initial-scale=1") + link(rel="stylesheet", href="/css/style.css") + body + h1 Dessert Contacts + a(href="/update-contact") Add New Contact + .cards + each contact in data + .card + h2.card__name #{contact.properties.firstname} #{contact.properties.lastname} + p.card__email #{contact.properties.email} + if contact.properties.icecream_flavor + p.card__flavor First Scoop: #{contact.properties.icecream_flavor} + if contact.properties.message + p.card__message Feeling: #{contact.properties.message} + if contact.properties.feeling_after_eating + p.card__feeling Feeling after eating: #{contact.properties.feeling_after_eating} + if contact.properties.second_scoop + p.card__second 🍨 Second Scoop: #{contact.properties.second_scoop} diff --git a/views/updates.pug b/views/updates.pug new file mode 100644 index 00000000..f5f33eb2 --- /dev/null +++ b/views/updates.pug @@ -0,0 +1,38 @@ +// views/updates.pug + +doctype html +html + head + title= `${title}` + link(rel="stylesheet", href="/css/style.css") + body + h1 Create a Dessert-Loving Contact + form(method="POST", action="/update-contact") + label(for="fullname") Full Name: + input(type="text", name="fullname", required=true) + br + + label(for="email") Email: + input(type="email", name="email", required=true) + br + + label(for="icecream_flavor") Favorite Dessert: + input(type="text", name="icecream_flavor") + br + + label(for="message") Mood Before Eating: + input(type="text", name="message") + br + + label(for="feeling_after_eating") Feeling After Eating: + input(type="text", name="feeling_after_eating") + br + + label(for="second_scoop") Second Scoop: + input(type="text", name="second_scoop") + br + + button(type="submit") Add Contact + + br + a(href="/") Back to Home