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 }) => ( + + + + + + + + + + {courses.map((course) => { + return ( + + + + + + + ); + })} + +
+ TitleAuthorCategory
+ + 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;