├── 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 |
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 |
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 |
--------------------------------------------------------------------------------