Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"axios": "^0.21.1",
"husky": "^4.3.0",
"lodash": "^4.17.20",
"moment": "^2.29.1",
Expand All @@ -23,6 +24,7 @@
"redux-devtools-extension": "^2.13.8",
"redux-promise-middleware": "^6.1.2",
"redux-thunk": "^2.3.0",
"uuid": "^8.3.2",
"web-vitals": "^0.2.4",
"yarn": "^1.22.10"
},
Expand Down
28 changes: 25 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React, { useEffect } from "react";
import "./App.css";
import { Switch, Route } from "react-router-dom";
import FrontPage from "./components/FrontPage";
Expand All @@ -11,19 +12,35 @@ import Footer from "./components/Footer";
import ContactUs from "./components/ContactUs";
import FAQ from "./components/FAQ";
import Header from "./components/Header/Header";
import { api } from "./store";
import { actions, api } from "./store";
import classPage from "./components/classPage/classPage";
import ScrollToTop from "./components/ScrollToTop";
import { connect } from "react-redux";
import Login from "./components/auth/Login";
import SignUp from "./components/auth/SignUp";
import BreadCrumb from "./components/Breadcrumbs/Breadcrumbs";
import Cat from "./components/Cat";
import { loadUser } from "./actions/auth";
import setAuthToken from "./utils/setAuthToken";
import Dashboard from "./components/dashboard/Dashboard";
import { connect } from "./lib/stateToRedux";
import CreateProfile from "./components/Profile/CreateProfile";

if (localStorage.token) {
setAuthToken(localStorage.token);
}

function App(props) {
api.auth.get().then((data) =>
actions.auth.auth.update({
isAuthenicated: true,
loaded: false,
user: data,
})
);
const { books, categories } = props;
api.book.read();
api.category.read();
api.user.get();
let cats = Object.values(categories); // covert categories to array
const getBookTitle = (props) => {
const id = props.match.params.id;
Expand Down Expand Up @@ -99,6 +116,11 @@ function App(props) {
</Route>
);
})}

{/*When connecting these needs to be <PrivateRoute/> */}
<Route exact path="/dashboard" component={Dashboard} />
<Route exact path="/create-profile" component={CreateProfile} />
{/*<Route exact path="/edit-profile" component={ EditProfile }/>*/}
</Switch>
</ScrollToTop>
<Footer />
Expand All @@ -107,7 +129,7 @@ function App(props) {
}

function mapStateToProps(state) {
return { categories: state.category, books: state.book };
return { categories: state.api.category, books: state.api.book };
}

export default connect(mapStateToProps)(App);
12 changes: 12 additions & 0 deletions src/actions/alert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { v4 as uuid } from "uuid";
import { SET_ALERT, REMOVE_ALERT } from "./types";

export const setAlert = (msg, alertType) => (dispatch) => {
const id = uuid();
dispatch({
type: SET_ALERT,
payload: { msg, alertType, id },
});

setTimeout(() => dispatch({ type: REMOVE_ALERT, payload: id }), 5000);
};
101 changes: 101 additions & 0 deletions src/actions/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import axios from "axios";
import {
LOGIN_SUCCSESS,
LOGIN_FAIL,
REGISTER_SUCCSESS,
REGISTER_FAIL,
USER_LOADED,
AUTH_ERROR,
LOGOUT,
CLEAR_PROFILE,
} from "./types";
import { setAlert } from "./alert";
import setAuthToken from "../utils/setAuthToken";

//load user
export const loadUser = () => async (dispatch) => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}

try {
const res = await axios.get("/api/auth");

dispatch({
type: USER_LOADED,
payload: res.data,
});
} catch (err) {
dispatch({
type: AUTH_ERROR,
});
}
};

//register user
export const register = ({ username, email, password }) => async (dispatch) => {
const config = {
headers: {
Content_Type: "application/json",
},
};

const body = JSON.stringify({ username, email, password });

try {
const res = await axios.post("api/users", body, config);
dispatch({
type: REGISTER_SUCCSESS,
payload: res.data,
});

dispatch(loadUser());
} catch (err) {
const errors = err.response.data.errors;

if (errors) {
errors.forEach((error) => dispatch(setAlert(error.msg)));
}

dispatch({
type: REGISTER_FAIL,
});
}
};

//login user
export const login = (email, password) => async (dispatch) => {
const config = {
headers: {
Content_Type: "application/json",
},
};

const body = JSON.stringify({ email, password });

try {
const res = await axios.post("api/auth", body, config);
dispatch({
type: LOGIN_SUCCSESS,
payload: res.data,
});

dispatch(loadUser());
} catch (err) {
const errors = err.response.data.errors;

if (errors) {
errors.forEach((error) => dispatch(setAlert(error.msg)));
}

dispatch({
type: LOGIN_FAIL,
});
}
};

//logout
export const logout = () => (dispatch) => {
dispatch({ type: CLEAR_PROFILE });
dispatch({ type: LOGOUT });
};
57 changes: 57 additions & 0 deletions src/actions/profile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import axios from "axios";
import { setAlert } from "./alert";

import { GET_PROFILE, PROFILE_ERROR } from "./types";

//get current users profile
export const getCurrentProfile = () => async (dispatch) => {
try {
const res = await axios.get("api/profile/me");
dispatch({
type: GET_PROFILE,
payload: res.data,
});
} catch (err) {
dispatch({
type: PROFILE_ERROR,
payload: { msg: err.response.statusText, status: err.response.status },
});
}
};

//create or update profile

export const createProfile = (formData, history, edit = false) => async (
dispatch
) => {
try {
const config = {
headers: {
"Content-Type": "applicationn/json",
},
};

const res = await axios.post("/api/profile", formData, config);

dispatch({
type: GET_PROFILE,
payload: res.data,
});

dispatch(setAlert(edit ? "Profile Updated" : "Profile Created"));

if (!edit) {
history.push("dashboard");
}
} catch (err) {
const errors = err.response.data.errors;

if (errors) {
errors.forEach((error) => dispatch(setAlert(error.msg)));
}
dispatch({
type: PROFILE_ERROR,
payload: { msg: err.response.statusText, status: err.response.status },
});
}
};
12 changes: 12 additions & 0 deletions src/actions/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const REGISTER_SUCCSESS = "REGISTER_SUCCSESS";
export const REGISTER_FAIL = "REGISTER_FAIL";
export const LOGIN_SUCCSESS = "LOGIN_SUCCSESS";
export const LOGIN_FAIL = "LOGIN_FAIL";
export const LOGOUT = "LOGOUT";
export const GET_PROFILE = "GET_PROFILE";
export const PROFILE_ERROR = "PROFILE_ERROR";
export const SET_ALERT = "SET_ALERT";
export const REMOVE_ALERT = "REMOVE_ALERT";
export const USER_LOADED = "USER_LOADED";
export const AUTH_ERROR = "AUTH_ERROR";
export const CLEAR_PROFILE = "CLEAR_PROFILE";
21 changes: 21 additions & 0 deletions src/components/Alert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import PropTypes from "prop-types";
import { connect } from "../lib/stateToRedux";

const Alert = ({ alerts }) =>
alerts !== null &&
alerts.length > 0 &&
alerts.map((alert) => (
<div key={alert.id} className="white bg-red f3 w-60 ttc center ba pa2 mb0">
{alert.msg}
</div>
));

Alert.propTypes = {
alerts: PropTypes.array.isRequired,
};
const mapStateToProps = (state) => ({
alerts: state.auth.alerts,
});

export default connect(mapStateToProps)(Alert);
2 changes: 2 additions & 0 deletions src/components/FrontPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const frontPage = (props) => {
style={background}
className="cover bg-near-white mw-100 vh-75"
></div> */}

<h1 className="tc ttu f1 fw9 tracked-tight">
Welcome to Collegiate Independent Study
</h1>
Expand All @@ -29,6 +30,7 @@ const frontPage = (props) => {
className="center vh-75"
/>
</div>

<HomepageIntro />
<CategoryScroller
categories={_.uniq(
Expand Down
5 changes: 1 addition & 4 deletions src/components/Navbar/Navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ export const Navbar = ({ signedIn }) => {
) : (
<div className="ml-auto">
<Link className={className} to="./signup">
Sign Up
</Link>
<Link className={className} to="/my-classes">
My Classes
Sign up/Login
</Link>
</div>
);
Expand Down
30 changes: 30 additions & 0 deletions src/components/PrivateRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Route, Redirect } from "react-router-dom";

const PrivateRoute = ({
component: Component,
auth: { isAuthenicated, loading },
...rest
}) => (
<Route
{...rest}
render={(props) =>
!isAuthenicated && !loading ? (
<Redirect to="/login" />
) : (
<Component {...props} />
)
}
/>
);

PrivateRoute.propTypes = {
auth: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
auth: state.auth,
});
export default connect(mapStateToProps)(PrivateRoute);
Loading