updated dependecies, added context, axios config

This commit is contained in:
Ben Elferink
2021-03-13 17:46:51 +02:00
parent a895cc0647
commit bc37d68394
19 changed files with 39144 additions and 509 deletions

View File

@@ -48,15 +48,15 @@ Then go to your server folder (backend), and set your database within `server.js
###### Client:
> axios: 0.21.1 &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; Use the API<br /> react: 17.0.1
> &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; UI framework<br /> react-dom: 17.0.1 &nbsp;&nbsp;&nbsp;
> ---> &nbsp;&nbsp;&nbsp; UI framework<br /> react-scripts: 4.0.2 &nbsp;&nbsp;&nbsp; --->
> &nbsp;&nbsp;&nbsp; React 'npm' scripts
> axios: ^0.21.1 &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; Use the API<br /> react: ^17.0.1
> &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; UI framework<br /> react-dom: ^17.0.1
> &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; UI framework<br /> react-scripts: 4.0.3
> &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; React 'npm' scripts
###### Server:
> cors: 2.8.5 &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; Enable HTTP requests<br/> dotenv: 8.2.0
> &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; Secure sensitive information<br /> express: 4.17.1
> &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; Server app<br /> mongoose: 5.11.15 &nbsp;&nbsp;&nbsp;
> ---> &nbsp;&nbsp;&nbsp; MongoDB database<br /> morgan: 1.10.0 &nbsp;&nbsp;&nbsp; --->
> cors: ^2.8.5 &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; Enable HTTP requests<br/> dotenv: ^8.2.0
> &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; Secure sensitive information<br /> express: ^4.17.1
> &nbsp;&nbsp;&nbsp; ---> &nbsp;&nbsp;&nbsp; Server app<br /> mongoose: ^5.12.0 &nbsp;&nbsp;&nbsp;
> ---> &nbsp;&nbsp;&nbsp; MongoDB database<br /> morgan: ^1.10.0 &nbsp;&nbsp;&nbsp; --->
> &nbsp;&nbsp;&nbsp; Logs incoming requests

37447
client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -12,15 +12,27 @@
"eject": "react-scripts eject"
},
"dependencies": {
"axios": "0.21.1",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-scripts": "4.0.2"
"axios": "^0.21.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.3"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@@ -19,10 +19,10 @@
"type":"image/png"
}
],
"display": "standalone",
"start_url": ".",
"theme_color": "#000",
"background_color": "#fff",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff",
"developer": {
"name": "",
"url": ""

View File

@@ -1,9 +1,28 @@
import './styles/styles.css';
import { useAuth } from './contexts/AuthContext';
export default function App() {
const { isLoggedIn } = useAuth();
return (
<div className='App'>
<p>Hello World - React.js</p>
<h1>{isLoggedIn ? <LoggedInText /> : <LoggedOutText />}</h1>
</div>
);
}
const LoggedInText = () => (
<>
You are (not really) logged in,
<br />
check your console.log()
</>
);
const LoggedOutText = () => (
<>
Don't forget to start your backend server,
<br />
then hit refresh and see what happens...
</>
);

View File

@@ -1,12 +1,9 @@
import axios from 'axios';
// api base-url (that you created on server side)
const url = 'http://localhost:8080/api/v1';
// api url (where your serve is hosted at)
export const backendUrl = 'http://localhost:8080';
// current method: GET
// current path: http://localhost:8080/api/v1/example
export const getPeople = () => axios.get(`${url}/people`);
// current method: POST
// current path: http://localhost:8080/api/v1/example/upload
export const newPerson = (form) => axios.post(`${url}/people/new`, form);
// axios configuration
export default axios.create({
baseURL: backendUrl,
});

View File

@@ -0,0 +1,37 @@
import { createContext, useContext, useState, useEffect } from 'react';
import axios, { backendUrl } from '../api';
// init context
const AuthContext = createContext();
// export the consumer
export function useAuth() {
return useContext(AuthContext);
}
// export the provider (handle all the logic here)
export function AuthProvider({ children }) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
//
useEffect(() => {
(async () => {
try {
const response = await axios.get('/auth/account');
setIsLoggedIn(true);
// Did you know? You can use CSS in the console!
console.log(
`%cExample of using your backend routes %c(${backendUrl}/auth/account)`,
'color: lime;',
'color: unset;',
response,
);
} catch (error) {
console.error(error.message);
}
})();
}, []);
return <AuthContext.Provider value={{ isLoggedIn }}>{children}</AuthContext.Provider>;
}

View File

@@ -1,11 +1,13 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './styles/reset.css';
import App from './App';
import { AuthProvider } from './contexts/AuthContext';
ReactDOM.render(
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>,
document.getElementById('root'),
);

View File

@@ -1,406 +0,0 @@
/*
HTML5 Reset :: reset.css
---------------------------
We have learned much from/been inspired by/taken code where offered from:
Eric Meyer :: http://meyerweb.com
HTML5 Doctor :: http://html5doctor.com
and the HTML5 Boilerplate :: http://html5boilerplate.com
-----------------------------------------------------------
Let's default this puppy out
-----------------------------
*/
html,
body,
body div,
span,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
abbr,
address,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
samp,
small,
strong,
sub,
sup,
var,
b,
i,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
figure,
footer,
header,
menu,
nav,
section,
time,
mark,
audio,
video,
details,
summary {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font-weight: normal;
vertical-align: baseline;
background: transparent;
}
main,
article,
aside,
figure,
footer,
header,
nav,
section,
details,
summary {
display: block;
}
/*
Handle box-sizing while better addressing child elements:
http://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/
*/
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
/*
consider resetting the default cursor: https://gist.github.com/murtaugh/5247154
credits to: Tim Murtaugh - https://gist.github.com/murtaugh/5247154
*/
html,
body {
cursor: default;
}
code {
cursor: text;
}
/*
textarea and input[type="text"] already receive
"cursor: text" via browsers' base stylesheets
*/
a,
label,
button,
input[type='radio'],
input[type='submit'],
input[type='checkbox'] {
cursor: pointer;
}
button[disabled],
input[disabled] {
cursor: default;
}
/*
Responsive images and other embedded objects
if you don't have full control over `img` tags (if you have to overcome attributes), consider adding height: auto
*/
img,
object,
embed {
max-width: 100%;
}
/*
Note: keeping IMG here will cause problems if you're using foreground images as sprites.
In fact, it *will* cause problems with Google Maps' controls at small size.
If this is the case for you, try uncommenting the following:
#map img {
max-width: none;
}
*/
/*
force a vertical scrollbar to prevent a jumpy page
*/
html {
overflow-y: scroll;
}
/*
we use a lot of ULs that aren't bulleted.
you'll have to restore the bullets within content,
which is fine because they're probably customized anyway
*/
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: '';
content: none;
}
a {
margin: 0;
padding: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
}
del {
text-decoration: line-through;
}
abbr[title],
dfn[title] {
border-bottom: 1px dotted #000;
cursor: help;
}
/*
tables still need cellspacing="0" in the markup
*/
table {
border-collapse: separate;
border-spacing: 0;
}
th {
font-weight: bold;
vertical-align: bottom;
}
td {
font-weight: normal;
vertical-align: top;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #ccc;
margin: 1em 0;
padding: 0;
}
input,
select {
vertical-align: middle;
}
pre {
white-space: pre; /* CSS2 */
white-space: pre-wrap; /* CSS 2.1 */
white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
word-wrap: break-word; /* IE */
}
input[type='radio'] {
vertical-align: text-bottom;
}
input[type='checkbox'] {
vertical-align: bottom;
}
.ie7 input[type='checkbox'] {
vertical-align: baseline;
}
.ie6 input {
vertical-align: text-bottom;
}
select,
input,
textarea {
font: 99% sans-serif;
}
table {
font-size: inherit;
font: 100%;
}
small {
font-size: 85%;
}
strong {
font-weight: bold;
}
td,
td img {
vertical-align: top;
}
/*
Make sure sup and sub don't mess with your line-heights http://gist.github.com/413930
This is tested to not break line-heights in:
-- WinXP/IE6,
-- WinXP/IE7,
-- WinXP/IE8,
-- Mac/FF 3.5.9,
-- Mac/Chrome 5.0,
-- Mac/Safari 4.0.4,
assuming a base font size of 14px and a line-height of 21px, or 1.5em.
Poke this, try to make it break!
credits to: Ruthie BenDor - https://gist.github.com/unruthless/413930
*/
sub,
sup {
/*
Specified in % so that the sup/sup is the
right size relative to the surrounding text
*/
font-size: 75%;
/*
Zero out the line-height so that it doesn't
interfere with the positioning that follows
*/
line-height: 0;
/*
Where the magic happens: makes all browsers position
the sup/sup properly, relative to the surrounding text
*/
position: relative;
/*
Note that if you're using Eric Meyer's reset.css, this
is already set and you can remove this rule:
vertical-align: baseline;
*/
}
sup {
/*
Move the superscripted text up
*/
top: -0.5em;
}
sub {
/*
Move the subscripted text down, but only
half as far down as the superscript moved up
*/
bottom: -0.25em;
}
/*
standardize any monospaced elements
*/
pre,
code,
kbd,
samp {
font-family: monospace, sans-serif;
}
/*
hand cursor on clickable elements
*/
.clickable,
label,
input[type='button'],
input[type='submit'],
input[type='file'],
button {
cursor: pointer;
}
/*
Webkit browsers add a 2px margin outside the chrome of form elements
*/
button,
input,
select,
textarea {
margin: 0;
}
/*
make buttons play nice in IE
*/
button,
input[type='button'] {
width: auto;
overflow: visible;
}
/*
scale images in IE7 more attractively
*/
.ie7 img {
-ms-interpolation-mode: bicubic;
}
/*
prevent BG image flicker upon hover
(commented out as usage is rare, and the filter syntax messes with some pre-processors)
.ie6 html {
filter: expression(document.execCommand('BackgroundImageCache', false, true));
}
*/
/*
let's clear some floats
*/
.clearfix:after {
content: ' ';
display: block;
clear: both;
}

View File

@@ -1,4 +1,5 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
-webkit-font-smoothing: antialiased;
@@ -6,15 +7,12 @@ body {
}
.App {
width: 100%;
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.App > p {
text-align: center;
}

14
package-lock.json generated Normal file
View File

@@ -0,0 +1,14 @@
{
"name": "mern-application",
"version": "0.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "mern-application",
"version": "0.1.0",
"hasInstallScript": true,
"license": "ISC"
}
}
}

View File

@@ -0,0 +1,38 @@
import Account from '../models/Account.js';
// more about response status codes ---> https://restapitutorial.com/httpstatuscodes.html
export async function registerAccount(request, response, next) {
try {
// Handle your logic here...
// return something to the client-side
response.status(201).json({ message: 'Account registered' });
} catch (error) {
console.error(error);
response.status(500).send();
}
}
export async function loginAccount(request, response, next) {
try {
// Handle your logic here...
// return something to the client-side
response.status(200).json({ message: 'Account logged-in' });
} catch (error) {
console.error(error);
response.status(500).send();
}
}
export async function getAccount(request, response, next) {
try {
// Handle your logic here...
// return something to the client-side
response.status(200).json({ message: 'Account fetched' });
} catch (error) {
console.error(error);
response.status(500).send();
}
}

View File

@@ -1,29 +0,0 @@
import mongoose from 'mongoose';
import User from '../models/User.js';
// more about response status codes ---> https://restapitutorial.com/httpstatuscodes.html
export async function getAllUsers(request, response, next) {
try {
const allUsers = await User.find(); // finds all in 'users' collection
response.status(200).json(allUsers);
} catch (error) {
console.log(error);
response.status(500).json(error);
}
}
export const createNewUser = async (request, response, next) => {
try {
let newUser = new User({
_id: mongoose.Types.ObjectId(), // _id is set by default, (you can remove this line)
name: request.body.userName, // userName === name used on client side
});
const savedUser = await newUser.save();
response.status(201).json(savedUser);
} catch (error) {
console.log(error);
response.status(500).json(error);
}
};

View File

@@ -2,17 +2,18 @@ import mongoose from 'mongoose';
const instance = new mongoose.Schema(
{
_id: mongoose.Schema.Types.ObjectId, // _id is set by default, (you can remove this line)
/*
name = Object key
String = Type
document ID is set by default via MongoDB - next line is deprecated
_id: mongoose.Schema.Types.ObjectId,
*/
name: String,
// key: Type,
email: String,
password: String,
},
{
timestamps: true,
// this creates and maintains:
// ^ ^ ^ this creates and maintains:
// {
// createdAt: Date,
// updatedAt: Date,
@@ -21,7 +22,7 @@ const instance = new mongoose.Schema(
);
// NOTE! use a singular model name, mongoose automatically creates a collection like so:
// model: 'User' === collection: 'users'
const modelName = 'User';
// model: 'Account' === collection: 'accounts'
const modelName = 'Account';
export default mongoose.model(modelName, instance);

View File

@@ -0,0 +1,24 @@
import express from 'express';
import { registerAccount, loginAccount, getAccount } from '../controllers/authControllers.js';
// initialize router
const router = express.Router();
// example: empty middleware
const middleware = (request, response, next) => next();
/*
request methods ---> https://www.tutorialspoint.com/http/http_methods.htm
1st param = extended url path
2nd param = middlewares (optional)
3rd param = request & response function (controller)
*/
// POST at route: http://localhost:8080/auth/register
router.post('/register', middleware, registerAccount);
// POST at path: http://localhost:8080/auth/login
router.post('/login', middleware, loginAccount);
// GET at path: http://localhost:8080/auth/account
router.get('/account', middleware, getAccount);
export default router;

View File

@@ -1,22 +0,0 @@
import express from 'express';
import { getAllUsers, createNewUser } from '../controllers/controllers.js'; // import request & response function
// initialize router
const router = express.Router();
/*
request methods ---> https://www.tutorialspoint.com/http/http_methods.htm
1st param = extended url path
2nd param = middlewares (optional)
3rd param = request & response function (controller)
*/
// current method: GET
// current path: http://localhost:8080/api/v1/users
router.get('/', (request, response, next) => next(), getAllUsers);
// current method: POST
// current path: http://localhost:8080/api/v1/users/new
router.post('/new', (request, response, next) => next(), createNewUser);
export default router;

View File

@@ -3,9 +3,8 @@ import express from 'express'; // Backend App (server)
import dotenv from 'dotenv'; // Secures variables
import cors from 'cors'; // HTTP headers (enable requests)
import morgan from 'morgan'; // Logs incoming requests
// import routes from './api/routes/routes.js';
// ^ ^ ^ un-comment this to use imported route(s)
// doing this will link the following files: index.js -> routes.js -> controllers.js -> User.js
import authRoutes from './api/routes/authRoutes.js';
// ^ ^ ^ how to use imported route(s)
// initialize app
const app = express();
@@ -33,11 +32,11 @@ db.on('connected', () => console.log('✅ MongoDB connected')); // connected
db.on('disconnected', () => console.log('❌ MongoDB disconnected')); // disconnected
db.on('error', (error) => console.log('❌ MongoDB connection error', error)); // listen for errors during the session
// routes
app.get('/', (request, response, next) => response.status(200).json('<h1>Hello World!</h1>'));
// app.use('/api/v1/users', routes);
// ^ ^ ^ un-comment this to use imported route(s)
// define routes
app.get('/', (request, response, next) => response.status(200).json({ message: 'Hello World!' }));
app.use('/auth', authRoutes);
// ^ ^ ^ how to use imported route(s)
// server is listening for requests
// listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => console.log(`✅ Server is listening on port: ${PORT}`));

1504
server/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -10,10 +10,10 @@
},
"license": "ISC",
"dependencies": {
"cors": "2.8.5",
"dotenv": "8.2.0",
"express": "4.17.1",
"mongoose": "5.11.15",
"morgan": "1.10.0"
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"mongoose": "^5.12.0",
"morgan": "^1.10.0"
}
}