├── free-tutor-link.sql ├── README.md ├── .gitignore ├── server ├── routes │ ├── login.js │ ├── search.js │ ├── availability.js │ └── profile.js ├── db.js ├── controllers │ ├── searchController.js │ ├── availabilityController.js │ ├── profileController.js │ └── loginController.js └── server.js ├── client ├── index.js └── components │ ├── profilePage │ ├── Availability.js │ ├── skillSetSelection.js │ ├── SkillSet.js │ └── Profile.js │ ├── Login.js │ ├── App.jsx │ ├── mainPage │ ├── AvailableTutor.js │ ├── Search.js │ └── Main.js │ └── User.js ├── index.html ├── package.json └── webpack.config.js /free-tutor-link.sql: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # free-tutor-link 2 | A chance to learn, for free, by a LinkedIn certified volunteer tutor. 3 | 4 | Welcome to LearningLink! Congratulations, you've taken the first step on your learning journey. And, it's free!!! 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | 4 | # dependencies 5 | node_modules/ 6 | 7 | # logs 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # output from webpack 13 | build/ 14 | 15 | # zip file for initial aws deployment 16 | *.zip 17 | 18 | # jest coverage 19 | coverage/ -------------------------------------------------------------------------------- /server/routes/login.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const loginController = require('../controllers/loginController'); 4 | 5 | router.get('/authCode', loginController.getAccessToken); 6 | router.get('/', loginController.sendToLinkedIn); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /client/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./components/App.jsx"; 4 | import { BrowserRouter, Link } from "react-router-dom"; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById("root") 11 | ); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /client/components/profilePage/Availability.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Availability = (props) => { 4 | return ( 5 |
6 | 7 | {props.date} {props.startTime}-{props.endTime} 8 | 9 | 10 |
11 | ); 12 | }; 13 | 14 | export default Availability; 15 | -------------------------------------------------------------------------------- /server/routes/search.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | const searchController = require('../controllers/searchController'); 5 | 6 | router.get('/', searchController.getSkillsList, (req, res) => { 7 | console.log('Inside search route'); 8 | return res.status(200).json({skills: res.locals.skills}); 9 | }); 10 | 11 | module.exports = router; -------------------------------------------------------------------------------- /server/db.js: -------------------------------------------------------------------------------- 1 | const { Pool } = require('pg'); 2 | 3 | const PG_URI = 'postgres://pbxpcmxr:jfFOHyIzqG5XBjISQWX4UKDPjj3GLGyh@ruby.db.elephantsql.com:5432/pbxpcmxr'; 4 | 5 | const pool = new Pool({ 6 | connectionString: PG_URI 7 | }); 8 | 9 | module.exports = { 10 | query: (text, params, callback) => { 11 | console.log('executed query', text); 12 | return pool.query(text, params, callback); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /client/components/Login.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | 3 | const Login = (props) => { 4 | return ( 5 |
6 |

Welcome to FreeTutorLink!

7 | 8 | Login with LinkedIn 9 | 10 |
11 | ); 12 | }; 13 | 14 | export default Login; 15 | -------------------------------------------------------------------------------- /client/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Switch, Route } from "react-router-dom"; 3 | import Login from "./Login.js"; 4 | import User from "./User.js"; 5 | 6 | const App = (props) => { 7 | return ( 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | ); 19 | }; 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /server/routes/availability.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const availabilityController = require('../controllers/availabilityController'); 4 | // tutors_input_ availability routes 5 | // availabilityController.getTutors, 6 | router.get( 7 | '/:subject', 8 | availabilityController.getSubjectID, 9 | availabilityController.getTutors, 10 | (req, res) => { 11 | return res.status(200).json({ tutors: res.locals.tutors }); 12 | } 13 | ); 14 | 15 | module.exports = router; 16 | -------------------------------------------------------------------------------- /client/components/profilePage/skillSetSelection.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const skillSetSelection = (props) => { 4 | let skills = ["Javascript", "SQL", "HTML", "Python", "Java"]; 5 | for (let i = 0; i < skills.length; i += 1) { 6 | checkbox.push( 7 |
8 | 9 | 10 |
11 | ); 12 | } 13 | return ( 14 |
15 | 16 |
17 | ); 18 | }; 19 | 20 | export default skillSetSelection; 21 | -------------------------------------------------------------------------------- /client/components/mainPage/AvailableTutor.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const AvailableTutor = (props) => { 4 | return ( 5 |
6 | 7 | 8 | 9 | 10 | 11 | {props.name} 12 | {props.date} 13 | 14 | {props.startTime} to {props.endTime} 15 | 16 | 17 | Send an Email 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default AvailableTutor; 24 | -------------------------------------------------------------------------------- /client/components/mainPage/Search.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | 3 | const Search = (props) => { 4 | return ( 5 |
6 | 14 | 15 |
16 | ); 17 | }; 18 | 19 | export default Search; 20 | -------------------------------------------------------------------------------- /client/components/profilePage/SkillSet.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | 3 | const skillSetSelection = (props) => { 4 | useEffect(() => {}, []); 5 | const checkbox = []; 6 | let skills = ['JavaScript', 'SQL', 'React', 'Node Express']; 7 | // for (let i = 0; i < skills.length; i += 1) { 8 | // checkbox.push( 9 | //
10 | // 11 | // 12 | //
13 | // ); 14 | // } 15 | checkbox.push(props.skills); 16 | return ( 17 |
18 |

Skill Set

19 |
{checkbox}
20 | 21 |
22 | ); 23 | }; 24 | 25 | export default skillSetSelection; 26 | -------------------------------------------------------------------------------- /server/controllers/searchController.js: -------------------------------------------------------------------------------- 1 | const searchController = {}; 2 | 3 | searchController.getSkillsList = (req, res, next) => { 4 | const sqlQuery = 'SELECT skill from skills'; 5 | console.log('Inside searchController'); 6 | db 7 | .query(sqlQuery) 8 | .then((data) => { 9 | console.log(data.rows); 10 | res.locals = data.rows; 11 | return next(); 12 | }) 13 | .catch((err) => { 14 | return next({ 15 | log: 'searchController.getSkillsList: ERROR: Error getting total skills list from the database', 16 | message: { 17 | err: 'searchController.getSkillsList: ERROR: Check server logs for details' 18 | } 19 | }); 20 | }); 21 | }; 22 | 23 | // searchController.getSearchResults = (req, res, next) => { 24 | // const sqlQuery = `` 25 | // } 26 | 27 | module.exports = searchController; -------------------------------------------------------------------------------- /client/components/User.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Main from './mainPage/Main'; 3 | import Profile from './profilePage/Profile'; 4 | 5 | const User = (props) => { 6 | const [mainPage, setMainPage] = useState(true); 7 | const [profilePage, setProfilePage] = useState(true); 8 | 9 | const handleToProfile = () => { 10 | setMainPage(false); 11 | setProfilePage(true); 12 | }; 13 | 14 | const handleToMain = () => { 15 | setProfilePage(false); 16 | setMainPage(true); 17 | }; 18 | 19 | if (mainPage) { 20 | return ( 21 |
22 |
23 |
24 | ); 25 | } 26 | 27 | if (profilePage) { 28 | return ( 29 |
30 | 31 |
32 | ); 33 | } 34 | 35 | return ( 36 |
37 |
Hello World, you're in the wrong place!
38 |
39 | ); 40 | }; 41 | 42 | export default User; 43 | -------------------------------------------------------------------------------- /server/routes/profile.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const profileController = require('../controllers/profileController'); 4 | 5 | // initial profile page 6 | router.get( 7 | '/:tutorid', 8 | profileController.getSkills, 9 | profileController.getCurrentAvailability, 10 | (req, res) => { 11 | return res 12 | .status(200) 13 | .json({ skills: res.locals.skills, availability: res.locals.availability }); 14 | } 15 | ); 16 | // updating skill 17 | router.put('/', profileController.updateSkills, profileController.getSkills, (req, res) => { 18 | return res.status(200).json({ skills: res.locals.skills }); 19 | }); 20 | 21 | // adding availability 22 | router.post( 23 | '/', 24 | profileController.addAvailability, 25 | profileController.getCurrentAvailability, 26 | (req, res) => { 27 | return res.status(200).json({ availability: res.locals.availability }); 28 | } 29 | ); 30 | 31 | // deleting availability 32 | router.delete( 33 | '/', 34 | profileController.deleteAvailability, 35 | profileController.getCurrentAvailability, 36 | (req, res) => { 37 | return res.status(200).json({ availability: res.locals.availability }); 38 | } 39 | ); 40 | 41 | module.exports = router; 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "free-tutor-link", 3 | "version": "1.0.0", 4 | "description": "A chance to learn, for free, by a LinkedIn certified volunteer tutor.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon server/server.js", 8 | "build": "webpack --env.NODE_ENV=production", 9 | "dev": "webpack-dev-server --env.NODE_ENV=development --open & nodemon server/server.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/LovelaceDink/free-tutor-link.git" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/LovelaceDink/free-tutor-link/issues" 20 | }, 21 | "homepage": "https://github.com/LovelaceDink/free-tutor-link#readme", 22 | "dependencies": { 23 | "cookie-parser": "^1.4.5", 24 | "express": "^4.12.3", 25 | "pg": "^8.2.1", 26 | "react": "^16.2.0", 27 | "react-dom": "^16.3.1", 28 | "react-router-dom": "^5.2.0", 29 | "superagent": "^5.2.2" 30 | }, 31 | "devDependencies": { 32 | "style-loader": "^1.2.1", 33 | "css-loader": "^3.6.0", 34 | "@babel/core": "^7.10.3", 35 | "@babel/preset-env": "^7.10.3", 36 | "@babel/preset-react": "^7.10.1", 37 | "babel-loader": "^8.1.0", 38 | "concurrently": "^4.1.0", 39 | "cross-env": "^5.2.0", 40 | "isomorphic-fetch": "^2.2.1", 41 | "nodemon": "^1.18.9", 42 | "sass": "^1.26.8", 43 | "sass-loader": "^8.0.2", 44 | "webpack": "^4.43.0", 45 | "webpack-cli": "^3.2.3", 46 | "webpack-dev-server": "^3.11.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = env => { 4 | console.log('NODE_ENV: ', env.NODE_ENV); 5 | return { 6 | entry: './client/index.js' , 7 | output: { 8 | path: path.resolve(__dirname, 'build') , 9 | filename: 'bundle.js' 10 | } , 11 | mode: env.NODE_ENV , 12 | devServer: { 13 | 14 | publicPath: '/build/', 15 | proxy: { 16 | '/': { 17 | target: 'http://localhost:3000', 18 | changeOrigin: true 19 | } 20 | 21 | } 22 | //port: 8080 23 | } , 24 | module: { 25 | rules: [ 26 | { test: /\.jsx?/, 27 | exclude: /(node_modules)/, 28 | use: { 29 | loader: 'babel-loader', 30 | options: { 31 | presets: ['@babel/preset-env','@babel/preset-react'] 32 | } 33 | } 34 | 35 | } , 36 | { 37 | test: /\.s[ac]ss$/i, 38 | use: [ 39 | // Creates `style` nodes from JS strings 40 | 'style-loader', 41 | // Translates CSS into CommonJS 42 | 'css-loader', 43 | // Compiles Sass to CSS 44 | 'sass-loader', 45 | ], 46 | }, 47 | ] 48 | } 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /client/components/mainPage/Main.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import AvailableTutor from './AvailableTutor'; 3 | import Search from './Search'; 4 | import Profile from '../profilePage/Profile'; 5 | 6 | const Main = (props) => { 7 | const [error, setError] = useState(null); 8 | const [choice, setChoice] = useState(''); 9 | const [availableTutors, setTutors] = useState([]); 10 | 11 | const tutors = []; 12 | 13 | if (!availableTutors.length) tutors.push(
No Tutors Available
); 14 | availableTutors.forEach((tutor) => { 15 | tutors.push( 16 | 25 | ); 26 | }); 27 | 28 | const handleSearch = (e) => { 29 | // const skillName = e.target.value; 30 | const skillName = choice; 31 | fetch(`/availability/${skillName}`) 32 | .then((resp) => resp.json()) 33 | .then( 34 | (result) => { 35 | console.log('Tutors ', result.tutors); 36 | setTutors(result.tutors); 37 | }, 38 | (error) => { 39 | setError(error); 40 | } 41 | ); 42 | }; 43 | 44 | const handleChoice = (e) => { 45 | setChoice(e.target.value); 46 | }; 47 | 48 | return ( 49 |
50 |
51 | 52 |
53 | 54 |
{tutors}
55 |
56 | ); 57 | }; 58 | 59 | export default Main; 60 | -------------------------------------------------------------------------------- /client/components/profilePage/Profile.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import Availability from './Availability.js'; 3 | import SkillSet from './SkillSet'; 4 | 5 | const Profile = (props) => { 6 | const [mainPage, setMainPage] = useState(true); 7 | const [profilePage, setProfilePage] = useState(true); 8 | const [availability, setAvailability] = useState([]); 9 | const [skills, setSkills] = useState([]); 10 | 11 | // who the user is, is currently hard coded 12 | useEffect(() => { 13 | fetch('/profile/2') 14 | .then((res) => res.json()) 15 | .then((data) => { 16 | console.log(data.availability); 17 | console.log(data.skills); 18 | setAvailability(data.availability); 19 | setSkills(data.skills); 20 | }); 21 | }, []); 22 | 23 | const schedule = []; 24 | for (let i = 0; i < availability.length; i += 1) { 25 | schedule.push( 26 | 32 | ); 33 | } 34 | 35 | return ( 36 |
37 | 38 |
39 | 40 |
41 |

Availability

42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {schedule} 51 |
52 | ); 53 | }; 54 | 55 | export default Profile; 56 | -------------------------------------------------------------------------------- /server/controllers/availabilityController.js: -------------------------------------------------------------------------------- 1 | const db = require("../db.js"); 2 | 3 | const availabilityController = {}; 4 | 5 | availabilityController.getSubjectID = (req, res, next) => { 6 | // convert string subjectWord into ID, then pass to the next controller, getTutors 7 | const subjectWord = [req.params.subject]; 8 | const sqlQuery = `SELECT _id FROM skills WHERE skill = $1`; 9 | db.query(sqlQuery, subjectWord) 10 | .then((data) => { 11 | console.log("DATA!!!", data.rows[0]._id); 12 | res.locals.skillid = data.rows[0]._id; 13 | return next(); 14 | }) 15 | .catch((err) => { 16 | return next({ 17 | log: 18 | "availabiltyController.getSubjectID: ERROR: Error getting skill data from the database", 19 | message: { 20 | err: 21 | "availabiltyController.getSubjectID: ERROR: Check server logs for details", 22 | }, 23 | }); 24 | }); 25 | }; 26 | 27 | availabilityController.getTutors = (req, res, next) => { 28 | const subjectID = [res.locals.skillid]; 29 | const sqlQuery = `SELECT name, skill, date, start_time AS start, end_time AS end , photo, linkedinprofile FROM tutors_skills INNER JOIN tutor_input_availability ON tutors_skills.tutor_id = tutor_input_availability.tutor_id LEFT JOIN tutors ON tutors._id = tutors_skills.tutor_id INNER JOIN skills ON skills._id = $1 AND skills._id = tutors_skills.skill_id;`; 30 | console.log("LOOK!", subjectID); 31 | db.query(sqlQuery, subjectID) 32 | .then((data) => { 33 | console.log("DATA!!!", data.rows); 34 | res.locals.tutors = data.rows; 35 | return next(); 36 | }) 37 | .catch((err) => { 38 | return next({ 39 | log: 40 | "availabiltyController.getTutor: ERROR: Error getting tutor data from the database", 41 | message: { 42 | err: 43 | "availabiltyController.getTutor: ERROR: Check server logs for details", 44 | }, 45 | }); 46 | }); 47 | }; 48 | 49 | module.exports = availabilityController; 50 | -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const express = require('express'); 3 | const cookieParser = require('cookie-parser'); 4 | 5 | const app = express(); 6 | const PORT = 3000; 7 | const availabilityRouter = require('./routes/availability.js'); 8 | const loginRouter = require('./routes/login.js'); 9 | const profileRouter = require('./routes/profile.js'); 10 | 11 | app.use((req, res, next) => { 12 | console.log(` 13 | ********* FLOW TEST *********\n 14 | METHOD: ${req.method}\n 15 | URL: ${req.url}\n 16 | BODY: ${JSON.stringify(req.body)}\n`); 17 | return next(); 18 | }); 19 | 20 | /** 21 | * handle parsing request body 22 | */ 23 | app.use(express.json()); 24 | app.use(cookieParser()); 25 | 26 | app.use('/availability', availabilityRouter); 27 | app.use('/login', loginRouter); 28 | app.use('/profile', profileRouter); 29 | 30 | /** 31 | * route handler to respond with main app 32 | */ 33 | app.use('/build', express.static(path.join(__dirname, '../build'))); 34 | app.get('/home', (req, res) => res.sendFile(path.join(__dirname, '../index.html'))); 35 | app.get('/', (req, res) => res.sendFile(path.join(__dirname, '../index.html'))); 36 | 37 | // catch-all route handler for any requests to an unknown route 38 | app.use((req, res) => res.status(404).send('Wake up Neo... Knock, knock.')); 39 | 40 | /** 41 | * configire express global error handler 42 | * @see https://expressjs.com/en/guide/error-handling.html#writing-error-handlers 43 | */ 44 | // eslint-disable-next-line no-unused-vars 45 | app.use((err, req, res, next) => { 46 | const defaultErr = { 47 | log: 'Express error handler caught unknown middleware error', 48 | status: 400, 49 | message: { err: 'An error occurred' }, 50 | }; 51 | const errorObj = Object.assign(defaultErr, err); 52 | console.log(errorObj.log); 53 | res.status(errorObj.status).json(errorObj.message); 54 | }); 55 | 56 | /** 57 | * start server 58 | */ 59 | 60 | app.listen(PORT, () => { 61 | console.log(`Server listening on port: ${PORT}`); 62 | }); 63 | 64 | module.exports = app; 65 | -------------------------------------------------------------------------------- /server/controllers/profileController.js: -------------------------------------------------------------------------------- 1 | const db = require('../db.js'); 2 | const profileController = {}; 3 | 4 | profileController.getSkills = (req, res, next) => { 5 | const tutorID = [req.params.tutorid]; 6 | const sqlQuery = `SELECT skill FROM "public"."tutors_skills" INNER JOIN skills on skill_id = skills._id where tutor_id = $1`; 7 | db.query(sqlQuery, tutorID) 8 | .then((data) => { 9 | // console.log('DATA!!!', data.rows[0].skills); 10 | console.log('GIMME THAT DATA', data.rows); 11 | // res.locals.skills = [ ...data.rows[skill] ]; 12 | const arr = data.rows; 13 | const result = []; 14 | arr.forEach((obj) => { 15 | result.push(obj.skill); 16 | }); 17 | console.log(result); 18 | 19 | // console.log('DATA', [ data.rows.skill ]); 20 | res.locals.skills = result; 21 | return next(); 22 | }) 23 | .catch((err) => { 24 | return next({ 25 | log: 'availabiltyController.getSkills ERROR: Error getting skills data from the database', 26 | message: { 27 | err: 'availabiltyController.getSkills: ERROR: Check server logs for details', 28 | }, 29 | }); 30 | }); 31 | }; 32 | 33 | profileController.updateSkills = (req, res, next) => { 34 | return next(); 35 | }; 36 | 37 | profileController.getCurrentAvailability = (req, res, next) => { 38 | // const currentSchedule = [ req.params.currentSchedule ]; 39 | console.log('ROUND TWO BABY', res.locals.skills); 40 | const tutorID = [ req.params.tutorid ]; 41 | console.log('MY TUTOR ID!!', tutorID); 42 | const sqlQuery = `SELECT * FROM "public"."tutor_input_availability" 43 | WHERE tutor_id = $1`; 44 | 45 | db.query(sqlQuery, tutorID).then((data) => { 46 | // console.log('DATA!!!', data.rows[0].skills); 47 | console.log('GIMME THAT DATA ROUND TWO', data.rows); 48 | res.locals.availability = data.rows; 49 | return next(); 50 | }); 51 | }; 52 | 53 | profileController.addAvailability = (req, res, next) => { 54 | return next(); 55 | }; 56 | 57 | profileController.deleteAvailability = (req, res, next) => { 58 | return next(); 59 | }; 60 | 61 | module.exports = profileController; 62 | -------------------------------------------------------------------------------- /server/controllers/loginController.js: -------------------------------------------------------------------------------- 1 | const request = require('superagent'); 2 | const db = require('../db.js'); 3 | 4 | const loginController = {}; 5 | 6 | const client_id = '77iojwzvr5axo9'; 7 | const client_secret = '2Ul4nGyuuFbylkm5'; 8 | const redirect_uri = 'http://localhost:3000/login/authCode'; 9 | 10 | loginController.sendToLinkedIn = (req, res) => 11 | res.redirect( 12 | `https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=${client_id}&redirect_uri=${redirect_uri}&scope=r_liteprofile%20r_emailaddress` 13 | ); 14 | 15 | loginController.getAccessToken = (req, res, next) => { 16 | const { code } = req.query; 17 | 18 | request 19 | .post( 20 | `https://www.linkedin.com/oauth/v2/accessToken?grant_type=authorization_code&code=${code}&redirect_uri=${redirect_uri}&client_id=${client_id}&client_secret=${client_secret}` 21 | ) 22 | .then((accessRes) => { 23 | res.locals.accessToken = accessRes.body.access_token; 24 | res.cookie('accessToken', res.locals.accessToken, { httpOnly: true, secure: true }); 25 | console.log('lev1', res.locals.accessToken); 26 | return request 27 | .get( 28 | 'https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))' 29 | ) 30 | .set('Authorization', `Bearer ${res.locals.accessToken}`); 31 | }) 32 | .then((userRes) => { 33 | const firstName = Object.values(userRes.body.firstName.localized)[0]; 34 | const lastName = Object.values(userRes.body.lastName.localized)[0]; 35 | const { id } = userRes.body; 36 | const imgUrl = 37 | userRes.body.profilePicture['displayImage~'].elements[0].identifiers[0].identifier; 38 | res.locals.newUser = { 39 | name: `${firstName} ${lastName}`, 40 | // userid: id, 41 | imgUrl, 42 | }; 43 | return request 44 | .get('https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))') 45 | .set('Authorization', `Bearer ${res.locals.accessToken}`); 46 | }) 47 | .then((emailRes) => { 48 | const email = emailRes.body.elements[0]['handle~'].emailAddress; 49 | res.locals.newUser.email = email; 50 | console.log('newUser info: ', res.locals.newUser); 51 | // add user to database 52 | const userData = res.locals.newUser; 53 | const sqlQuery = `INSERT INTO tutors (email, name, photo) VALUES ($1, $2, $3)` ; 54 | db 55 | .query(sqlQuery, [userData.email, userData.name, userData.imgUrl]) 56 | .then(() => { 57 | console.log('WORKINGGGG!') 58 | // const sqlQuery = `SELECT _id FROM tutors where order` 59 | // db 60 | // .query(sqlQuery) 61 | } 62 | ) 63 | // cookies? 64 | return res.redirect('http://localhost:3000/home'); 65 | }) 66 | .catch((err) => { 67 | return next({ 68 | log: `Error in loginController.getAccessToken: ${err}`, 69 | }); 70 | }); 71 | }; 72 | 73 | module.exports = loginController; 74 | --------------------------------------------------------------------------------