diff --git a/src/components/courses/CourseList.js b/src/components/courses/CourseList.js
new file mode 100644
index 0000000..40cfe04
--- /dev/null
+++ b/src/components/courses/CourseList.js
@@ -0,0 +1,43 @@
+import React from "react";
+import PropTypes from "prop-types";
+import { Link } from "react-router-dom";
+
+const CourseList = ({ courses }) => (
+
+
+
+ |
+ Title |
+ Author |
+ Category |
+
+
+
+ {courses.map((course) => {
+ return (
+
+
+
+ Watch
+
+ |
+
+ {course.title}
+ |
+ {course.authorName} |
+ {course.category} |
+
+ );
+ })}
+
+
+);
+
+CourseList.propTypes = {
+ courses: PropTypes.array.isRequired
+};
+
+export default CourseList;
diff --git a/src/components/courses/CoursesPage.js b/src/components/courses/CoursesPage.js
index 67187f7..637135a 100644
--- a/src/components/courses/CoursesPage.js
+++ b/src/components/courses/CoursesPage.js
@@ -1,17 +1,33 @@
import React from "react";
import { connect } from "react-redux";
import * as courseActions from "../../redux/actions/courseActions";
+import * as authorActions from "../../redux/actions/authorActions";
import PropTypes from "prop-types";
import { bindActionCreators } from "redux";
+import CourseList from "./CourseList";
class CoursesPage extends React.Component {
+ componentDidMount() {
+ const { courses, authors, actions } = this.props;
+
+ if (courses.length === 0) {
+ actions.loadCourses().catch((error) => {
+ alert("Loading courses failed. " + error);
+ });
+ }
+
+ if (authors.length === 0) {
+ actions.loadAuthors().catch((error) => {
+ alert("Loading authors failed. " + error);
+ });
+ }
+ }
+
render() {
return (
<>
Courses
- {this.props.courses.map((course) => (
- {course.title}
- ))}
+
>
);
}
@@ -19,18 +35,35 @@ class CoursesPage extends React.Component {
CoursesPage.propTypes = {
courses: PropTypes.array.isRequired,
+ authors: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired
};
function mapStateToProps(state) {
return {
- courses: state.courses
+ courses:
+ state.authors.length === 0
+ ? []
+ : state.courses.map((course) => {
+ const author = state.authors.find((a) => a.id === course.authorId);
+ return {
+ ...course,
+ authorName: author.name
+ };
+ }),
+ authors: state.authors
};
}
function mapDispatchToProps(dispatch) {
return {
- actions: bindActionCreators(courseActions, dispatch)
+ actions: bindActionCreators(
+ {
+ loadCourses: courseActions.loadCourses,
+ loadAuthors: authorActions.loadAuthors
+ },
+ dispatch
+ )
};
}
diff --git a/src/redux/actions/actionTypes.js b/src/redux/actions/actionTypes.js
index f78d80f..a9d88e5 100644
--- a/src/redux/actions/actionTypes.js
+++ b/src/redux/actions/actionTypes.js
@@ -1,2 +1,3 @@
export const CREATE_COURSE = "CREATE_COURSE";
export const LOAD_COURSES_SUCCESS = "LOAD_COURSES_SUCCESS";
+export const LOAD_AUTHORS_SUCCESS = "LOAD_AUTHORS_SUCCESS";
diff --git a/src/redux/actions/authorActions.js b/src/redux/actions/authorActions.js
new file mode 100644
index 0000000..c850e1c
--- /dev/null
+++ b/src/redux/actions/authorActions.js
@@ -0,0 +1,19 @@
+import * as types from "./actionTypes";
+import * as authorApi from "../../api/authorApi";
+
+function loadAuthorsSuccess(authors) {
+ return { type: types.LOAD_AUTHORS_SUCCESS, authors };
+}
+
+export function loadAuthors() {
+ return function (dispatch) {
+ return authorApi
+ .getAuthors()
+ .then((authors) => {
+ dispatch(loadAuthorsSuccess(authors));
+ })
+ .catch((error) => {
+ throw error;
+ });
+ };
+}
diff --git a/src/redux/reducers/authorReducer.js b/src/redux/reducers/authorReducer.js
new file mode 100644
index 0000000..1cd9d9a
--- /dev/null
+++ b/src/redux/reducers/authorReducer.js
@@ -0,0 +1,11 @@
+import * as types from "../actions/actionTypes";
+
+export default function authorReducer(state = [], action) {
+ switch (action.type) {
+ case types.LOAD_AUTHORS_SUCCESS:
+ return action.authors;
+
+ default:
+ return state;
+ }
+}
diff --git a/src/redux/reducers/courseReducer.js b/src/redux/reducers/courseReducer.js
index 9dad124..2d09c6c 100644
--- a/src/redux/reducers/courseReducer.js
+++ b/src/redux/reducers/courseReducer.js
@@ -5,6 +5,9 @@ export default function courseReducer(state = [], action) {
case types.CREATE_COURSE:
return [...state, { ...action.course }];
+ case types.LOAD_COURSES_SUCCESS:
+ return action.courses;
+
default:
return state;
}
diff --git a/src/redux/reducers/index.js b/src/redux/reducers/index.js
index 5c5859d..5ecd3dc 100644
--- a/src/redux/reducers/index.js
+++ b/src/redux/reducers/index.js
@@ -1,8 +1,10 @@
import { combineReducers } from "redux";
import courseReducer from "./courseReducer";
+import authorReducer from "./authorReducer";
const rootReducer = combineReducers({
- courses: courseReducer
+ courses: courseReducer,
+ authors: authorReducer
});
export default rootReducer;