course list

master
Tudor Stanciu 2020-04-11 22:54:32 +03:00
parent 04d8e062d4
commit 49fbd7be66
7 changed files with 118 additions and 6 deletions

View File

@ -0,0 +1,43 @@
import React from "react";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
const CourseList = ({ courses }) => (
<table className="table">
<thead>
<tr>
<th />
<th>Title</th>
<th>Author</th>
<th>Category</th>
</tr>
</thead>
<tbody>
{courses.map((course) => {
return (
<tr key={course.id}>
<td>
<a
className="btn btn-light"
href={"http://pluralsight.com/courses/" + course.slug}
>
Watch
</a>
</td>
<td>
<Link to={"/course/" + course.slug}>{course.title}</Link>
</td>
<td>{course.authorName}</td>
<td>{course.category}</td>
</tr>
);
})}
</tbody>
</table>
);
CourseList.propTypes = {
courses: PropTypes.array.isRequired
};
export default CourseList;

View File

@ -1,17 +1,33 @@
import React from "react"; import React from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import * as courseActions from "../../redux/actions/courseActions"; import * as courseActions from "../../redux/actions/courseActions";
import * as authorActions from "../../redux/actions/authorActions";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { bindActionCreators } from "redux"; import { bindActionCreators } from "redux";
import CourseList from "./CourseList";
class CoursesPage extends React.Component { 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() { render() {
return ( return (
<> <>
<h2>Courses</h2> <h2>Courses</h2>
{this.props.courses.map((course) => ( <CourseList courses={this.props.courses} />
<div key={course.title}>{course.title}</div>
))}
</> </>
); );
} }
@ -19,18 +35,35 @@ class CoursesPage extends React.Component {
CoursesPage.propTypes = { CoursesPage.propTypes = {
courses: PropTypes.array.isRequired, courses: PropTypes.array.isRequired,
authors: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired actions: PropTypes.object.isRequired
}; };
function mapStateToProps(state) { function mapStateToProps(state) {
return { 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) { function mapDispatchToProps(dispatch) {
return { return {
actions: bindActionCreators(courseActions, dispatch) actions: bindActionCreators(
{
loadCourses: courseActions.loadCourses,
loadAuthors: authorActions.loadAuthors
},
dispatch
)
}; };
} }

View File

@ -1,2 +1,3 @@
export const CREATE_COURSE = "CREATE_COURSE"; export const CREATE_COURSE = "CREATE_COURSE";
export const LOAD_COURSES_SUCCESS = "LOAD_COURSES_SUCCESS"; export const LOAD_COURSES_SUCCESS = "LOAD_COURSES_SUCCESS";
export const LOAD_AUTHORS_SUCCESS = "LOAD_AUTHORS_SUCCESS";

View File

@ -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;
});
};
}

View File

@ -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;
}
}

View File

@ -5,6 +5,9 @@ export default function courseReducer(state = [], action) {
case types.CREATE_COURSE: case types.CREATE_COURSE:
return [...state, { ...action.course }]; return [...state, { ...action.course }];
case types.LOAD_COURSES_SUCCESS:
return action.courses;
default: default:
return state; return state;
} }

View File

@ -1,8 +1,10 @@
import { combineReducers } from "redux"; import { combineReducers } from "redux";
import courseReducer from "./courseReducer"; import courseReducer from "./courseReducer";
import authorReducer from "./authorReducer";
const rootReducer = combineReducers({ const rootReducer = combineReducers({
courses: courseReducer courses: courseReducer,
authors: authorReducer
}); });
export default rootReducer; export default rootReducer;