From af9679e34a63b689b7e4e608bb45df4dad0765c0 Mon Sep 17 00:00:00 2001 From: Akiyo Fidel d Date: Thu, 13 Jul 2023 13:31:19 +0300 Subject: [PATCH 1/6] Replace course table with card, and improved UI --- package.json | 3 + src/App.css | 3 +- src/components/CourseCard/CourseCard.jsx | 8 +- .../CourseCard/SingleCourseCard.jsx | 36 +++++++++ src/components/CourseCard/index.js | 1 + src/components/CoursePlayer/VideoModal.jsx | 73 +++++++++++++------ src/components/CoursesTable/CoursesTable.jsx | 50 ++++++------- .../ExpansionPanel/ExpansionPanel.jsx | 2 +- .../ModuleContent/ModuleContent.jsx | 46 +++++++++--- src/components/Search/Search.jsx | 5 +- src/components/SingleCourse/SingleCourse.jsx | 55 +++++++++----- .../UserDashboard/TeacherDashboard.jsx | 4 +- src/index.js | 3 + yarn.lock | 71 ++++++++++++++++++ 14 files changed, 268 insertions(+), 92 deletions(-) create mode 100644 src/components/CourseCard/SingleCourseCard.jsx diff --git a/package.json b/package.json index 2582748..a119eda 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "aphrodite": "^2.4.0", "axios": "^0.19.2", "babel-eslint": "^10.1.0", + "bootstrap": "^5.3.0", "classnames": "^2.2.6", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.2", @@ -21,6 +22,7 @@ "eslint-config-airbnb": "^18.1.0", "express": "^4.17.1", "formik": "^2.1.4", + "jquery": "^3.7.0", "jsonwebtoken": "^8.5.1", "loaders.css": "^0.1.2", "mdbreact": "^4.27.0", @@ -51,6 +53,7 @@ "redux": "^4.0.5", "redux-mock-store": "^1.5.4", "redux-thunk": "^2.3.0", + "sass": "^1.63.6", "simple-flexbox": "^2.3.1", "valid-url": "^1.0.9", "yup": "^0.29.1" diff --git a/src/App.css b/src/App.css index 160cb74..8b6bdf0 100644 --- a/src/App.css +++ b/src/App.css @@ -11,4 +11,5 @@ @import "../node_modules/react-bootstrap-table-next/dist/react-bootstrap-table2.min.css"; @import url("https://bootswatch.com/_vendor/bootstrap/dist/css/bootstrap.min.css"); @import "../node_modules/react-loader-spinner/dist/loader/css/react-spinner-loader.css"; -@import url(https://fonts.googleapis.com/css?family=Open + Sans:300, 400, 600, 700|Open + Sans + Condensed:300, 700); +@import url("https://fonts.googleapis.com/css?family=Open + Sans:300, 400, 600, 700|Open + Sans + Condensed:300, 700"); +@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css"); diff --git a/src/components/CourseCard/CourseCard.jsx b/src/components/CourseCard/CourseCard.jsx index b92fe29..5a36aaa 100644 --- a/src/components/CourseCard/CourseCard.jsx +++ b/src/components/CourseCard/CourseCard.jsx @@ -25,15 +25,16 @@ export const CourseCard = (props) => {
+
{course.course_category}
-
+
{course.course_title}
@@ -41,7 +42,7 @@ export const CourseCard = (props) => {

{course.course_title.toUpperCase()}

-

{course.course_description}

+

{course.course_description}


@@ -57,7 +58,6 @@ export const CourseCard = (props) => {
-
{course.course_category}
diff --git a/src/components/CourseCard/SingleCourseCard.jsx b/src/components/CourseCard/SingleCourseCard.jsx new file mode 100644 index 0000000..0bf30b4 --- /dev/null +++ b/src/components/CourseCard/SingleCourseCard.jsx @@ -0,0 +1,36 @@ +import React from "react"; +import SrcImg from "../../assets/images/img_4.jpg"; +import { Link } from "react-router-dom"; + +const SingleCourseCard = (props) => { + return ( +
+ +
+ +
{props.coursecat}
+
+
{props.courset}
+

{props.coursedes}

+
+ Duration: {props.coursetime} hours +
+
+ Mr {props.courseinstructor} as Instructor +
+
+
+ 2,193 students +
+
+ 2 +
+
+
+
+ +
+ ); +}; + +export default SingleCourseCard; diff --git a/src/components/CourseCard/index.js b/src/components/CourseCard/index.js index a1000b7..fde66d7 100644 --- a/src/components/CourseCard/index.js +++ b/src/components/CourseCard/index.js @@ -1 +1,2 @@ export * from "./CourseCard.jsx"; +export * from "./SingleCourseCard.jsx"; diff --git a/src/components/CoursePlayer/VideoModal.jsx b/src/components/CoursePlayer/VideoModal.jsx index e2acc37..263c7f0 100644 --- a/src/components/CoursePlayer/VideoModal.jsx +++ b/src/components/CoursePlayer/VideoModal.jsx @@ -5,27 +5,56 @@ import { isWebUri } from "valid-url"; import CoursePlayer from "./CoursePlayer.jsx"; const VideoModal = (props) => ( -
- {isWebUri(props.content) - ? - - - - - - - : {props.content} - - - - } -
+
+ {isWebUri(props.content) ? ( + + + + + {props.contentTitle} + + + + + + +
+
+ + +
+
+ +
+
+
+
+ ) : ( + + + + + {props.contentTitle} + + + {props.content} + +
+
+ + +
+
+ +
+
+
+
+ )} +
); export default VideoModal; diff --git a/src/components/CoursesTable/CoursesTable.jsx b/src/components/CoursesTable/CoursesTable.jsx index 6ad4490..b232339 100644 --- a/src/components/CoursesTable/CoursesTable.jsx +++ b/src/components/CoursesTable/CoursesTable.jsx @@ -3,8 +3,10 @@ import axios from "axios"; import { Link } from "react-router-dom"; import moment from "moment"; import PaginationRow from "../Pagination/PaginationRow.jsx"; +import { CourseCard } from "../CourseCard/CourseCard.jsx"; +import SingleCourseCard from "../CourseCard/SingleCourseCard.jsx"; -const LIMIT = 5; +const LIMIT = 3; const CoursesTable = () => { const [courses, loadcourses] = React.useState([]); const [count, setCount] = useState(0); @@ -55,36 +57,26 @@ const CoursesTable = () => { return ( <> - - - - - - - - - - - - - +
+
{getDataByPage().map((course) => ( -
- - - - - - - - +
+
+ +
+ + {/* {console.log(course.course_category)} */} +
))} - -
Course NameTitleDescriptionDuration (Hrs) InstructorDate AddedAction
{course.course_category} - {course.course_title} - {course.course_description}{course.course_duration}{course.course_instructor}{moment(course.date_added).format("LL")} - -
+ +
{renderPagination()}
); diff --git a/src/components/ExpansionPanel/ExpansionPanel.jsx b/src/components/ExpansionPanel/ExpansionPanel.jsx index f2843f8..5b9bf02 100644 --- a/src/components/ExpansionPanel/ExpansionPanel.jsx +++ b/src/components/ExpansionPanel/ExpansionPanel.jsx @@ -38,7 +38,7 @@ const CourseExpansionPanel = (props) => {
} aria-controls="panel1a-content" id="panel1a-header"> -
{capitalize(props.module_title)}
+
{capitalize(props.module_title)}
diff --git a/src/components/ModuleContent/ModuleContent.jsx b/src/components/ModuleContent/ModuleContent.jsx index b70f820..19ac0b8 100644 --- a/src/components/ModuleContent/ModuleContent.jsx +++ b/src/components/ModuleContent/ModuleContent.jsx @@ -6,24 +6,46 @@ import { capitalize } from "../SingleCourse/utils"; const ModuleContent = (props) => { const [modalShow, setModalShow] = useState(false); const [activeModuleContent, setActiveModuleContent] = useState(); + const [activeModuleContentTitle, setActiveModuleContentTitle] = useState(); - const handleClick = (modulecontent) => { + const handleClick = (modulecontent, modulecontenttitle) => { setModalShow(true); setActiveModuleContent(modulecontent); + setActiveModuleContentTitle(modulecontenttitle); }; return ( -
-
    - {props.moduleData && props.moduleData.length ? props.moduleData.map((module) => ( -
  • handleClick(module.module_content)} style={{ color: "#7971ea", cursor: "pointer" }}> - {capitalize(module.module_content_title)} -
  • - )) :
  • No module content yet for this module
  • } - setModalShow(!modalShow)}/> -
-
); +
+
    + {props.moduleData && props.moduleData.length ? ( + props.moduleData.map((module) => ( +
  • handleClick(module.module_content, module.module_content_title)} + style={{ color: "#7971ea", cursor: "pointer" }} + > + + {capitalize(module.module_content_title)} +
  • + )) + ) : ( +
  • No module content yet for this module
  • + )} + setModalShow(!modalShow)} + /> +
+
+ + +
+
+ ); }; export default ModuleContent; diff --git a/src/components/Search/Search.jsx b/src/components/Search/Search.jsx index b8eb398..0edfa48 100644 --- a/src/components/Search/Search.jsx +++ b/src/components/Search/Search.jsx @@ -8,14 +8,15 @@ const Search = () => (
-
+
diff --git a/src/components/SingleCourse/SingleCourse.jsx b/src/components/SingleCourse/SingleCourse.jsx index 53529ef..adbe01f 100644 --- a/src/components/SingleCourse/SingleCourse.jsx +++ b/src/components/SingleCourse/SingleCourse.jsx @@ -12,10 +12,15 @@ import CommentsContainer from "../../containers/CommentContainer.jsx"; import enrollAction from "../../redux/actions/enrollAction.jsx"; import "react-toastify/dist/ReactToastify.css"; import fetchEnrolledStateAction from "../../redux/actions/fetchEnrolledStateAction.jsx"; +import SrcImg from "../../assets/images/img_4.jpg"; export const SingleCourse = (props) => { const isAuthenticated = localStorage.getItem("token"); const [disabled, setDisabled] = useState(true); + + //variable to extract course data object from props + const courseInfo = Object(props.data.data.course); + const enrollStatus = useSelector((state) => state.enrollReducer); const dispatch = useDispatch(); @@ -24,7 +29,7 @@ export const SingleCourse = (props) => { }; const handleClickResumeCourse = () => { - //dispatch(ResumeCourseAction(props.course_id)); + setDisabled(false); }; useEffect(() => { @@ -46,27 +51,36 @@ export const SingleCourse = (props) => { ) : (
)} +
+ {" "} +
-
-
-
-
-

{props.data.data.course ? capitalize(props.data.data.course.course_title) : null}

- +
+
+
+
+

{props.data.data.course ? capitalize(courseInfo.course_title) : null}

+
+ {courseInfo.course_title} +
{isAuthenticated && props.enrolledstt.data.message === "Registered" ? ( - + + ) : isAuthenticated && props.enrolledstt.error.message === "Not Registered" ? ( + ) : ( LOGIN TO ENROLL @@ -85,16 +99,16 @@ export const SingleCourse = (props) => {
)) : null} +
diff --git a/src/components/UserDashboard/TeacherDashboard.jsx b/src/components/UserDashboard/TeacherDashboard.jsx index 9cb00d7..a8c9bca 100644 --- a/src/components/UserDashboard/TeacherDashboard.jsx +++ b/src/components/UserDashboard/TeacherDashboard.jsx @@ -235,12 +235,14 @@ const TeacherDashboard = () => (
+ {/* List of users Enrolled courses */}
- + {/* List of all courses available */} + {/* */}
diff --git a/src/index.js b/src/index.js index 9d403d6..8f57823 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,9 @@ import thunk from "redux-thunk"; import combineReducers from "./redux/reducers/combinedReducer.jsx"; import Routes from "./app.js"; import Favicon from "react-favicon"; +import "bootstrap/dist/css/bootstrap.min.css"; +import "jquery/dist/jquery.min.js"; +import "bootstrap/dist/js/bootstrap.min.js"; const store = createStore(combineReducers, compose(applyMiddleware(thunk))); diff --git a/yarn.lock b/yarn.lock index 87eb69c..dea514a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2349,6 +2349,14 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + aos@^2.3.4: version "2.3.4" resolved "https://registry.yarnpkg.com/aos/-/aos-2.3.4.tgz#eb1c29f5c1806a197cf6323080747547edd3db8e" @@ -2901,6 +2909,11 @@ bootstrap-css-only@4.4.1: resolved "https://registry.yarnpkg.com/bootstrap-css-only/-/bootstrap-css-only-4.4.1.tgz#08012477b1baab52fa1ca304eaba2e40f6ef0d2e" integrity sha512-iBgNli7RnedBFwn6sMTQoAZ8WgIwmX4kF1rckfj+pgro5q/Q0DbLtcpfH60XoFnCXzbEJU/khC/B2EQap89mCg== +bootstrap@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.0.tgz#0718a7cc29040ee8dbf1bd652b896f3436a87c29" + integrity sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -3342,6 +3355,21 @@ cheerio@^1.0.0-rc.3: lodash "^4.15.0" parse5 "^3.0.1" +"chokidar@>=3.0.0 <4.0.0": + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -5678,6 +5706,11 @@ fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -5763,6 +5796,13 @@ glob-parent@^5.0.0, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" @@ -6246,6 +6286,11 @@ immer@1.10.0: resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== +immutable@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.0.tgz#eb1738f14ffb39fd068b1dbe1296117484dd34be" + integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg== + import-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" @@ -7248,6 +7293,11 @@ jquery@>=1.8.3: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5" integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg== +jquery@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612" + integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -10768,6 +10818,13 @@ readdirp@~3.4.0: dependencies: picomatch "^2.2.1" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + realpath-native@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" @@ -11222,6 +11279,15 @@ sass-loader@8.0.2, sass-loader@^8.0.2: schema-utils "^2.6.1" semver "^6.3.0" +sass@^1.63.6: + version "1.63.6" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.63.6.tgz#481610e612902e0c31c46b46cf2dad66943283ea" + integrity sha512-MJuxGMHzaOW7ipp+1KdELtqKbfAWbH7OLIdoSMnVe3EXPMTmxTmlaZDCTsgIpPCs3w99lLo9/zDKkOrJuT5byw== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -11572,6 +11638,11 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +"source-map-js@>=0.6.2 <2.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" From e82bf13106b7e94282ba437de61f9e2f2dab8c4e Mon Sep 17 00:00:00 2001 From: Akiyo Fidel d Date: Fri, 14 Jul 2023 12:00:46 +0300 Subject: [PATCH 2/6] ft view enrolled course cards, fetch enrolled courses --- .../CourseCard/SingleCourseCard.jsx | 2 +- src/components/CoursesTable/CoursesTable.jsx | 2 +- src/components/TableCard/TableCard.jsx | 95 +++- .../UserDashboard/TeacherDashboard.jsx | 456 +++++++++--------- src/redux/actions/actionTypes.jsx | 10 + .../actions/fetchEnrolledCoursesAction.jsx | 26 + src/redux/reducers/combinedReducer.jsx | 2 + .../reducers/fetchEnrolledCoursesReducer.jsx | 24 + 8 files changed, 382 insertions(+), 235 deletions(-) create mode 100644 src/redux/actions/fetchEnrolledCoursesAction.jsx create mode 100644 src/redux/reducers/fetchEnrolledCoursesReducer.jsx diff --git a/src/components/CourseCard/SingleCourseCard.jsx b/src/components/CourseCard/SingleCourseCard.jsx index 0bf30b4..3cbe970 100644 --- a/src/components/CourseCard/SingleCourseCard.jsx +++ b/src/components/CourseCard/SingleCourseCard.jsx @@ -7,7 +7,7 @@ const SingleCourseCard = (props) => {
- + {props.courset}
{props.coursecat}
{props.courset}
diff --git a/src/components/CoursesTable/CoursesTable.jsx b/src/components/CoursesTable/CoursesTable.jsx index b232339..822d507 100644 --- a/src/components/CoursesTable/CoursesTable.jsx +++ b/src/components/CoursesTable/CoursesTable.jsx @@ -6,7 +6,7 @@ import PaginationRow from "../Pagination/PaginationRow.jsx"; import { CourseCard } from "../CourseCard/CourseCard.jsx"; import SingleCourseCard from "../CourseCard/SingleCourseCard.jsx"; -const LIMIT = 3; +const LIMIT = 4; const CoursesTable = () => { const [courses, loadcourses] = React.useState([]); const [count, setCount] = useState(0); diff --git a/src/components/TableCard/TableCard.jsx b/src/components/TableCard/TableCard.jsx index 7996ecc..e231ab9 100644 --- a/src/components/TableCard/TableCard.jsx +++ b/src/components/TableCard/TableCard.jsx @@ -1,11 +1,88 @@ -import * as React from "react"; -import CoursesTable from "../CoursesTable/CoursesTable.jsx"; - -const TableCard = () => ( - <> -
MY COURSES
- - -); +import React, { useEffect, useState } from "react"; +import PaginationRow from "../Pagination/PaginationRow.jsx"; +import SingleCourseCard from "../CourseCard/SingleCourseCard.jsx"; +import { makeArray } from "jquery"; +import axios from "axios"; + +const LIMIT = 3; +const { REACT_APP_BASE_URL } = process.env; +const token = localStorage.getItem("token"); + +const TableCard = () => { + const [courses, loadcourses] = useState([""]); + const [count, setCount] = useState(0); + const [pageCount, setPageCount] = useState(0); + const [currentPage, setCurrentPage] = useState(1); + const [selectedPage, setSelectedPage] = useState(0); + + useEffect(() => { + async function fetchcoursesdata() { + await axios + .get(`${REACT_APP_BASE_URL}/api/v1/courses/enrolled`, { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}` + }, + mode: "cors" + }) + .then((res) => { + loadcourses(res.data.enrolled_courses); + setCount(res.data.enrolled_courses.length); + setPageCount(Math.ceil(res.data.enrolled_courses.length / LIMIT)); + }) + .catch((err) => err); + } + fetchcoursesdata(); + }, []); + + const handlePageChange = (page) => { + setSelectedPage(page.selected); + if (page.selected === selectedPage + 1) { + setCurrentPage(currentPage + 1); + } else if (page.selected === selectedPage - 1) { + setCurrentPage(currentPage - 1); + } else { + setCurrentPage(() => page.selected + 1); + } + }; + + const getDataByPage = () => { + const begin = (currentPage - 1) * LIMIT; + const end = begin + LIMIT; + + return courses.slice(begin, end); + }; + + const renderPagination = () => + count === 0 ? ( + "No Data" + ) : ( + + ); + + return ( + <> +
+
+ {getDataByPage().map((course) => ( +
+
+ +
+
+ ))} +
+
+
{renderPagination()}
+ + ); +}; export default TableCard; diff --git a/src/components/UserDashboard/TeacherDashboard.jsx b/src/components/UserDashboard/TeacherDashboard.jsx index a8c9bca..f7c6861 100644 --- a/src/components/UserDashboard/TeacherDashboard.jsx +++ b/src/components/UserDashboard/TeacherDashboard.jsx @@ -1,251 +1,259 @@ -import React from "react"; +import React, { useEffect } from "react"; import Search from "../Search/Search.jsx"; import TableCard from "../TableCard/TableCard.jsx"; -import CourseCard from "./CourseCard.jsx"; +import { useDispatch, useSelector } from "react-redux"; +import fetchEnrolledCoursesAction from "../../redux/actions/fetchEnrolledCoursesAction.jsx"; +import fetchCoursesAction from "../../redux/actions/fetchCoursesAction.jsx"; +import CoursesTable from "../CoursesTable/CoursesTable.jsx"; -const TeacherDashboard = () => ( -
- -
-
-
-
-
- Avatar -

Teacher1

+const TeacherDashboard = () => { + return ( +
+ +
+
+
+
+
+ Avatar +

Teacher1

+
-
-
-
- -
-
-

- Energistically administrate 24/7 portals and enabled catalysts for change. Objectively revolutionize - client-centered e-commerce via covalent scenarios. Continually envisioneer. -

- - Edit - -
-
-
- - Avatar +
+
+ +
+
+

+ Energistically administrate 24/7 portals and enabled catalysts for change. Objectively revolutionize + client-centered e-commerce via covalent scenarios. Continually envisioneer. +

+ + Edit + +
+
+
+ + Avatar + +
+

+ Antonius started following Jack Bay{" "} + - 2m ago +

+ Today 08:30 am - 02.05.2014 +
+
+ + +
-
- - + +
+ + Avatar + +
+

+ Antonius started following Jack Bay{" "} + - 2m ago +

+ Today 08:30 am - 02.05.2014 +
+
+ + +
- -
- +
+
Avatar - -
-

- Antonius started following Jack Bay{" "} - - 2m ago -

- Today 08:30 am - 02.05.2014 -
-
- - -
-
-
-
-
- User Avatar - -
-
- User Avatar - -
-
-
- User Avatar -
- - Stella -
- @stella -
- +
+
+ User Avatar +
+ + Stella +
+ @stella +
+ +
-
-
- User Avatar -
- - Stella -
- @stella -
- +
+ User Avatar +
+ + Stella +
+ @stella +
+ +
-
-
-
- {/* List of users Enrolled courses */} - +
MY COURSES
+
+
+ {/* List of users Enrolled courses */} + +
-
-
-
- {/* List of all courses available */} - {/* */} + +
ALL COURSES
+
+
+ {/* List of all courses available */} + +
-
-); + ); +}; export default TeacherDashboard; diff --git a/src/redux/actions/actionTypes.jsx b/src/redux/actions/actionTypes.jsx index 6ac9419..ab318bc 100644 --- a/src/redux/actions/actionTypes.jsx +++ b/src/redux/actions/actionTypes.jsx @@ -28,6 +28,16 @@ export const fetchCoursesFail = (error) => ({ error }); +export const fetchEnrolledCoursesSuccess = (payload) => ({ + type: "FETCH_ENROLLED_COURSES_SUCCESS", + payload +}); + +export const fetchEnrolledCoursesFail = (error) => ({ + type: "FETCH_ENROLLED_COURSES_FAIL", + error +}); + export const fetchSingleCourseSuccess = (payload) => ({ type: "FETCH_SINGLE_COURSE_SUCCESS", payload diff --git a/src/redux/actions/fetchEnrolledCoursesAction.jsx b/src/redux/actions/fetchEnrolledCoursesAction.jsx new file mode 100644 index 0000000..b6193d0 --- /dev/null +++ b/src/redux/actions/fetchEnrolledCoursesAction.jsx @@ -0,0 +1,26 @@ +import axios from "axios"; +import * as actions from "./actionTypes.jsx"; + +const { REACT_APP_BASE_URL } = process.env; +const token = localStorage.getItem("token"); + +const fetchEnrolledCoursesAction = () => (dispatch) => + axios + .get(`${REACT_APP_BASE_URL}/api/v1/courses/enrolled`, { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}` + }, + mode: "cors" + }) + .then( + (response) => { + if (response.data.enrolled_courses) { + dispatch(actions.fetchEnrolledCoursesSuccess(response.data.enrolled_courses)); + } else { + dispatch(actions.fetchEnrolledCoursesFail(response)); + } + }, + (error) => error + ); +export default fetchEnrolledCoursesAction; diff --git a/src/redux/reducers/combinedReducer.jsx b/src/redux/reducers/combinedReducer.jsx index 0cfc32c..de8fd00 100644 --- a/src/redux/reducers/combinedReducer.jsx +++ b/src/redux/reducers/combinedReducer.jsx @@ -12,12 +12,14 @@ import addCommentReducer from "./addCommentReducer.jsx"; import enrollReducer from "./enrollReducer.jsx"; import fetchEnrolledStateReducer from "./fetchEnrolledStateReducer.jsx"; import deleteBlogReducer from "./deleteBlogReducer.jsx"; +import fetchEnrolledCoursesReducer from "./fetchEnrolledCoursesReducer"; export default combineReducers({ loginReducer, signUpReducer, fetchCoursesReducer, fetchSingleCourseReducer, + fetchEnrolledCoursesReducer, fetchCourseModuleReducer, fetchCourseCommentsReducer, fetchBlogsReducer, diff --git a/src/redux/reducers/fetchEnrolledCoursesReducer.jsx b/src/redux/reducers/fetchEnrolledCoursesReducer.jsx new file mode 100644 index 0000000..a473a67 --- /dev/null +++ b/src/redux/reducers/fetchEnrolledCoursesReducer.jsx @@ -0,0 +1,24 @@ +const initialState = { + data: {}, + error: {} +}; + +const fetchEnrolledCoursesReducer = (state = initialState, action) => { + switch (action.type) { + case "FETCH_ENROLLED_COURSES_SUCCESS": + return { + ...state, + data: action.payload + }; + case "FETCH_ENROLLED_COURSES_FAIL": + return { + ...state, + error: action.error + }; + default: + return { + ...state + }; + } +}; +export default fetchEnrolledCoursesReducer; From 74ed1cd904f05e2c67af1ebd2608cef9775bbfd2 Mon Sep 17 00:00:00 2001 From: Akiyo Fidel d Date: Thu, 27 Jul 2023 00:39:49 +0300 Subject: [PATCH 3/6] Enhanced fetching all and enrolled courses in teachers dashboard component to fix rendering issues on reload or refresh --- src/components/CoursesTable/CoursesTable.jsx | 30 ++------- src/components/TableCard/TableCard.jsx | 41 +++---------- .../UserDashboard/TeacherDashboard.jsx | 61 +++++++++++++++++-- src/redux/reducers/combinedReducer.jsx | 2 +- 4 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/components/CoursesTable/CoursesTable.jsx b/src/components/CoursesTable/CoursesTable.jsx index 822d507..a4441bb 100644 --- a/src/components/CoursesTable/CoursesTable.jsx +++ b/src/components/CoursesTable/CoursesTable.jsx @@ -1,35 +1,13 @@ import React, { useState } from "react"; -import axios from "axios"; -import { Link } from "react-router-dom"; -import moment from "moment"; import PaginationRow from "../Pagination/PaginationRow.jsx"; -import { CourseCard } from "../CourseCard/CourseCard.jsx"; import SingleCourseCard from "../CourseCard/SingleCourseCard.jsx"; const LIMIT = 4; -const CoursesTable = () => { - const [courses, loadcourses] = React.useState([]); - const [count, setCount] = useState(0); - const [pageCount, setPageCount] = useState(0); +// eslint-disable-next-line react/prop-types +const CoursesTable = ({ courses, count, pageCount, limit }) => { const [currentPage, setCurrentPage] = useState(1); const [selectedPage, setSelectedPage] = useState(0); - const { REACT_APP_BASE_URL } = process.env; - - React.useEffect(() => { - async function fetchcoursesdata() { - await axios - .get(`${REACT_APP_BASE_URL}/api/v1/courses`) - .then((res) => { - loadcourses(res.data.courses); - setCount(res.data.courses.length); - setPageCount(Math.ceil(res.data.courses.length / LIMIT)); - }) - .catch((err) => err); - } - fetchcoursesdata(); - }, []); - const handlePageChange = (page) => { setSelectedPage(page.selected); if (page.selected === selectedPage + 1) { @@ -42,8 +20,8 @@ const CoursesTable = () => { }; const getDataByPage = () => { - const begin = (currentPage - 1) * LIMIT; - const end = begin + LIMIT; + const begin = (currentPage - 1) * limit; + const end = begin + limit; return courses.slice(begin, end); }; diff --git a/src/components/TableCard/TableCard.jsx b/src/components/TableCard/TableCard.jsx index e231ab9..7e1e095 100644 --- a/src/components/TableCard/TableCard.jsx +++ b/src/components/TableCard/TableCard.jsx @@ -1,40 +1,13 @@ -import React, { useEffect, useState } from "react"; +/* eslint-disable react/prop-types */ +import React, { useState } from "react"; import PaginationRow from "../Pagination/PaginationRow.jsx"; import SingleCourseCard from "../CourseCard/SingleCourseCard.jsx"; -import { makeArray } from "jquery"; -import axios from "axios"; -const LIMIT = 3; -const { REACT_APP_BASE_URL } = process.env; -const token = localStorage.getItem("token"); - -const TableCard = () => { - const [courses, loadcourses] = useState([""]); - const [count, setCount] = useState(0); - const [pageCount, setPageCount] = useState(0); +// eslint-disable-next-line react/prop-types +const TableCard = ({ courses, count, pageCount, limit }) => { const [currentPage, setCurrentPage] = useState(1); const [selectedPage, setSelectedPage] = useState(0); - useEffect(() => { - async function fetchcoursesdata() { - await axios - .get(`${REACT_APP_BASE_URL}/api/v1/courses/enrolled`, { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}` - }, - mode: "cors" - }) - .then((res) => { - loadcourses(res.data.enrolled_courses); - setCount(res.data.enrolled_courses.length); - setPageCount(Math.ceil(res.data.enrolled_courses.length / LIMIT)); - }) - .catch((err) => err); - } - fetchcoursesdata(); - }, []); - const handlePageChange = (page) => { setSelectedPage(page.selected); if (page.selected === selectedPage + 1) { @@ -47,8 +20,8 @@ const TableCard = () => { }; const getDataByPage = () => { - const begin = (currentPage - 1) * LIMIT; - const end = begin + LIMIT; + const begin = (currentPage - 1) * limit; + const end = begin + limit; return courses.slice(begin, end); }; @@ -57,7 +30,7 @@ const TableCard = () => { count === 0 ? ( "No Data" ) : ( - + ); return ( diff --git a/src/components/UserDashboard/TeacherDashboard.jsx b/src/components/UserDashboard/TeacherDashboard.jsx index f7c6861..dda0a06 100644 --- a/src/components/UserDashboard/TeacherDashboard.jsx +++ b/src/components/UserDashboard/TeacherDashboard.jsx @@ -1,12 +1,61 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; +import axios from "axios"; import Search from "../Search/Search.jsx"; import TableCard from "../TableCard/TableCard.jsx"; -import { useDispatch, useSelector } from "react-redux"; -import fetchEnrolledCoursesAction from "../../redux/actions/fetchEnrolledCoursesAction.jsx"; -import fetchCoursesAction from "../../redux/actions/fetchCoursesAction.jsx"; import CoursesTable from "../CoursesTable/CoursesTable.jsx"; +const LIMIT = 4; +const { REACT_APP_BASE_URL } = process.env; +const token = localStorage.getItem("token"); + const TeacherDashboard = () => { + const [enrolledcourses, loadEnrolledCourses] = useState([]); + const [enrolledcount, setEnrolledCount] = useState(0); + const [enrolledpageCount, setEnrolledPageCount] = useState(0); + const [courses, loadcourses] = useState([""]); + const [count, setCount] = useState(0); + const [pageCount, setPageCount] = useState(0); + + useEffect(() => { + async function fetchcoursesdata() { + await axios + .get(`${REACT_APP_BASE_URL}/api/v1/courses/enrolled`, { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}` + }, + mode: "cors" + }) + .then((res) => { + loadEnrolledCourses(res.data.enrolled_courses); + setEnrolledCount(res.data.enrolled_courses.length); + setEnrolledPageCount(Math.ceil(res.data.enrolled_courses.length / LIMIT)); + }) + .catch((err) => err); + } + fetchcoursesdata(); + }, []); + + useEffect(() => { + async function fetchcoursesdata() { + await axios + .get(`${REACT_APP_BASE_URL}/api/v1/courses`, { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}` + }, + mode: "cors" + }) + .then((res) => { + loadcourses(res.data.courses); + setCount(res.data.courses.length); + setPageCount(Math.ceil(res.data.courses.length / LIMIT)); + }) + .catch((err) => err); + } + fetchcoursesdata(); + }, []); + return (
@@ -241,7 +290,7 @@ const TeacherDashboard = () => {
{/* List of users Enrolled courses */} - +
@@ -249,7 +298,7 @@ const TeacherDashboard = () => {
{/* List of all courses available */} - +
diff --git a/src/redux/reducers/combinedReducer.jsx b/src/redux/reducers/combinedReducer.jsx index de8fd00..5c051e9 100644 --- a/src/redux/reducers/combinedReducer.jsx +++ b/src/redux/reducers/combinedReducer.jsx @@ -12,7 +12,7 @@ import addCommentReducer from "./addCommentReducer.jsx"; import enrollReducer from "./enrollReducer.jsx"; import fetchEnrolledStateReducer from "./fetchEnrolledStateReducer.jsx"; import deleteBlogReducer from "./deleteBlogReducer.jsx"; -import fetchEnrolledCoursesReducer from "./fetchEnrolledCoursesReducer"; +import fetchEnrolledCoursesReducer from "./fetchEnrolledCoursesReducer.jsx"; export default combineReducers({ loginReducer, From cbf15e78214401cc3b194918f279594075a21537 Mon Sep 17 00:00:00 2001 From: Akiyo Fidel d Date: Fri, 28 Jul 2023 20:40:46 +0300 Subject: [PATCH 4/6] enhancement for enroll - resume course button --- .../CourseCard/SingleCourseCard.jsx | 12 ++--- src/components/SingleCourse/SingleCourse.jsx | 47 ++++++++++++++----- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/components/CourseCard/SingleCourseCard.jsx b/src/components/CourseCard/SingleCourseCard.jsx index 3cbe970..e900f52 100644 --- a/src/components/CourseCard/SingleCourseCard.jsx +++ b/src/components/CourseCard/SingleCourseCard.jsx @@ -1,22 +1,22 @@ import React from "react"; -import SrcImg from "../../assets/images/img_4.jpg"; import { Link } from "react-router-dom"; +import SrcImg from "../../assets/images/img_4.jpg"; const SingleCourseCard = (props) => { return (
-
+
{props.courset}
{props.coursecat}
-
-
{props.courset}
-

{props.coursedes}

+
+
{props.courset}
+

{props.coursedes}

Duration: {props.coursetime} hours
- Mr {props.courseinstructor} as Instructor + Mr.{props.courseinstructor} as Instructor
diff --git a/src/components/SingleCourse/SingleCourse.jsx b/src/components/SingleCourse/SingleCourse.jsx index adbe01f..a5369ce 100644 --- a/src/components/SingleCourse/SingleCourse.jsx +++ b/src/components/SingleCourse/SingleCourse.jsx @@ -3,7 +3,9 @@ /* eslint-disable import/prefer-default-export */ import React, { useState, useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { toast, ToastContainer } from "react-toastify"; +import { toast } from "react-toastify"; +import { Link } from "react-router-dom"; +import { LinearProgress } from "@material-ui/core"; import Footer from "../Footer/Footer.jsx"; import Header from "../Header/Header.jsx"; import { capitalize } from "./utils"; @@ -11,14 +13,14 @@ import CourseExpansionPanel from "../ExpansionPanel/ExpansionPanel.jsx"; import CommentsContainer from "../../containers/CommentContainer.jsx"; import enrollAction from "../../redux/actions/enrollAction.jsx"; import "react-toastify/dist/ReactToastify.css"; -import fetchEnrolledStateAction from "../../redux/actions/fetchEnrolledStateAction.jsx"; import SrcImg from "../../assets/images/img_4.jpg"; export const SingleCourse = (props) => { const isAuthenticated = localStorage.getItem("token"); const [disabled, setDisabled] = useState(true); + const [visible, setVisible] = useState(false); - //variable to extract course data object from props + // variable to extract course data object from props const courseInfo = Object(props.data.data.course); const enrollStatus = useSelector((state) => state.enrollReducer); @@ -30,6 +32,7 @@ export const SingleCourse = (props) => { const handleClickResumeCourse = () => { setDisabled(false); + setVisible(true); }; useEffect(() => { @@ -73,8 +76,18 @@ export const SingleCourse = (props) => { className="img-fluid img-thumbnail rounded h-50 w-50" /> - {isAuthenticated && props.enrolledstt.data.message === "Registered" ? ( - */} + + {" "} + Back to View Courses List + + {/* {visible && <>You are at 50% Progress} */} + + ) : isAuthenticated && props.enrolledstt.data.message === "Registered" ? ( + ) : isAuthenticated && props.enrolledstt.error.message === "Not Registered" ? ( @@ -101,14 +114,24 @@ export const SingleCourse = (props) => {

Course Description

{props.data.data.course ? courseInfo.course_description : null}

- {isAuthenticated && props.enrolledstt.data.message ? ( - +
+
+ {visible && ( + <> + You are at 50% Progress + + + )} + + ) : isAuthenticated && props.enrolledstt.data.message === "Registered" ? ( + - ) : isAuthenticated && props.enrolledstt.error.message ? ( - ) : ( LOGIN TO ENROLL @@ -149,7 +172,7 @@ export const SingleCourse = (props) => { {props.data.data.course ? capitalize(props.data.data.course.course_instructor) : null} -

More than 5 years teaching experience having great mentorship abilities... .

+

More than 5 years teaching experience having great mentorship abilities....

From bd42e3690d974ace130c0b027aa1474700078556 Mon Sep 17 00:00:00 2001 From: Akiyo Fidel d Date: Fri, 28 Jul 2023 20:55:40 +0300 Subject: [PATCH 5/6] lint --- src/components/SingleCourse/SingleCourse.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SingleCourse/SingleCourse.jsx b/src/components/SingleCourse/SingleCourse.jsx index a5369ce..70d50b3 100644 --- a/src/components/SingleCourse/SingleCourse.jsx +++ b/src/components/SingleCourse/SingleCourse.jsx @@ -80,7 +80,7 @@ export const SingleCourse = (props) => { <> {/* */} - + {" "} Back to View Courses List From be9506bd03a4b7415e11148c0b35ed7388939235 Mon Sep 17 00:00:00 2001 From: Akiyo Fidel d Date: Tue, 8 Aug 2023 15:01:52 +0300 Subject: [PATCH 6/6] cleaned code, improved code fetching from api using container --- src/components/CourseCard/CourseCard.jsx | 9 +-- src/components/CoursesTable/CoursesTable.jsx | 2 - src/components/Main/Main.jsx | 2 +- src/components/SingleCourse/SingleCourse.jsx | 3 - src/components/TeachersPage.jsx | 4 +- .../UserDashboard/TeacherDashboard.jsx | 70 ++++--------------- src/containers/CourseCardContainer.jsx | 4 +- src/containers/CourseListContainer.jsx | 24 +++++++ src/index.js | 3 - src/redux/actions/fetchCoursesAction.jsx | 2 +- 10 files changed, 49 insertions(+), 74 deletions(-) create mode 100644 src/containers/CourseListContainer.jsx diff --git a/src/components/CourseCard/CourseCard.jsx b/src/components/CourseCard/CourseCard.jsx index 5a36aaa..c853e29 100644 --- a/src/components/CourseCard/CourseCard.jsx +++ b/src/components/CourseCard/CourseCard.jsx @@ -7,18 +7,19 @@ import { Link } from "react-router-dom"; import SrcImg from "../../assets/images/img_4.jpg"; import fetchSingleCourseAction from "../../redux/actions/fetchSingleCourseAction.jsx"; -export const CourseCard = (props) => { +export const CourseCard = ({ courseData }) => { const dispatch = useDispatch(); const handleClick = (id) => { dispatch(fetchSingleCourseAction(id)); }; + return (
- {props.data.data.courses ? ( - props.data.data.courses.map((course) => ( + {courseData ? ( + courseData.map((course) => (
handleClick(course.course_id)}>
@@ -41,7 +42,7 @@ export const CourseCard = (props) => {
-

{course.course_title.toUpperCase()}

+

{course.course_title}

{course.course_description}


diff --git a/src/components/CoursesTable/CoursesTable.jsx b/src/components/CoursesTable/CoursesTable.jsx index a4441bb..7e16dd4 100644 --- a/src/components/CoursesTable/CoursesTable.jsx +++ b/src/components/CoursesTable/CoursesTable.jsx @@ -49,8 +49,6 @@ const CoursesTable = ({ courses, count, pageCount, limit }) => { courseinstructor={course.course_instructor} />
- - {/* {console.log(course.course_category)} */}
))}
diff --git a/src/components/Main/Main.jsx b/src/components/Main/Main.jsx index 25d1446..635f05a 100644 --- a/src/components/Main/Main.jsx +++ b/src/components/Main/Main.jsx @@ -85,7 +85,7 @@ const Main = (props) => {
- +
diff --git a/src/components/SingleCourse/SingleCourse.jsx b/src/components/SingleCourse/SingleCourse.jsx index 70d50b3..ffad95d 100644 --- a/src/components/SingleCourse/SingleCourse.jsx +++ b/src/components/SingleCourse/SingleCourse.jsx @@ -78,13 +78,10 @@ export const SingleCourse = (props) => { {visible && isAuthenticated && props.enrolledstt.data.message === "Registered" ? ( <> - {/* */} {" "} Back to View Courses List - {/* {visible && <>You are at 50% Progress} */} ) : isAuthenticated && props.enrolledstt.data.message === "Registered" ? (
- +
); diff --git a/src/components/UserDashboard/TeacherDashboard.jsx b/src/components/UserDashboard/TeacherDashboard.jsx index dda0a06..0a722a6 100644 --- a/src/components/UserDashboard/TeacherDashboard.jsx +++ b/src/components/UserDashboard/TeacherDashboard.jsx @@ -1,61 +1,11 @@ -import React, { useEffect, useState } from "react"; -import axios from "axios"; +import React from "react"; import Search from "../Search/Search.jsx"; import TableCard from "../TableCard/TableCard.jsx"; import CoursesTable from "../CoursesTable/CoursesTable.jsx"; const LIMIT = 4; -const { REACT_APP_BASE_URL } = process.env; -const token = localStorage.getItem("token"); - -const TeacherDashboard = () => { - const [enrolledcourses, loadEnrolledCourses] = useState([]); - const [enrolledcount, setEnrolledCount] = useState(0); - const [enrolledpageCount, setEnrolledPageCount] = useState(0); - const [courses, loadcourses] = useState([""]); - const [count, setCount] = useState(0); - const [pageCount, setPageCount] = useState(0); - - useEffect(() => { - async function fetchcoursesdata() { - await axios - .get(`${REACT_APP_BASE_URL}/api/v1/courses/enrolled`, { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}` - }, - mode: "cors" - }) - .then((res) => { - loadEnrolledCourses(res.data.enrolled_courses); - setEnrolledCount(res.data.enrolled_courses.length); - setEnrolledPageCount(Math.ceil(res.data.enrolled_courses.length / LIMIT)); - }) - .catch((err) => err); - } - fetchcoursesdata(); - }, []); - - useEffect(() => { - async function fetchcoursesdata() { - await axios - .get(`${REACT_APP_BASE_URL}/api/v1/courses`, { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}` - }, - mode: "cors" - }) - .then((res) => { - loadcourses(res.data.courses); - setCount(res.data.courses.length); - setPageCount(Math.ceil(res.data.courses.length / LIMIT)); - }) - .catch((err) => err); - } - fetchcoursesdata(); - }, []); +const TeacherDashboard = ({ enrolledcourses, allcourses }) => { return (
@@ -289,16 +239,24 @@ const TeacherDashboard = () => {
MY COURSES
- {/* List of users Enrolled courses */} - +
ALL COURSES
- {/* List of all courses available */} - +
diff --git a/src/containers/CourseCardContainer.jsx b/src/containers/CourseCardContainer.jsx index 17ede12..6533a02 100644 --- a/src/containers/CourseCardContainer.jsx +++ b/src/containers/CourseCardContainer.jsx @@ -2,9 +2,9 @@ import React from "react"; import { CourseCard } from "../components/CourseCard"; -const CourseCardContainer = (props) => ( +const CourseCardContainer = ({ courseData }) => (
- +
); export default CourseCardContainer; diff --git a/src/containers/CourseListContainer.jsx b/src/containers/CourseListContainer.jsx new file mode 100644 index 0000000..26f57e6 --- /dev/null +++ b/src/containers/CourseListContainer.jsx @@ -0,0 +1,24 @@ +import React, { useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import TeacherDashboard from "../components/UserDashboard/TeacherDashboard.jsx"; +import fetchCoursesAction from "../redux/actions/fetchCoursesAction.jsx"; +import fetchEnrolledCoursesAction from "../redux/actions/fetchEnrolledCoursesAction.jsx"; + +const CourseListContainer = () => { + const dispatch = useDispatch(); + const EnrolledCoursesList = useSelector((state) => state.fetchEnrolledCoursesReducer); + const AllCoursesList = useSelector((state) => state.fetchCoursesReducer); + + useEffect(() => { + dispatch(fetchEnrolledCoursesAction()); + dispatch(fetchCoursesAction()); + }, []); + + return ( +
+ +
+ ); +}; + +export default CourseListContainer; diff --git a/src/index.js b/src/index.js index 8f57823..df3d612 100644 --- a/src/index.js +++ b/src/index.js @@ -6,16 +6,13 @@ import { Provider } from "react-redux"; import thunk from "redux-thunk"; import combineReducers from "./redux/reducers/combinedReducer.jsx"; import Routes from "./app.js"; -import Favicon from "react-favicon"; import "bootstrap/dist/css/bootstrap.min.css"; -import "jquery/dist/jquery.min.js"; import "bootstrap/dist/js/bootstrap.min.js"; const store = createStore(combineReducers, compose(applyMiddleware(thunk))); ReactDOM.render( - {/* */} , document.getElementById("root") diff --git a/src/redux/actions/fetchCoursesAction.jsx b/src/redux/actions/fetchCoursesAction.jsx index a35a545..fa31184 100644 --- a/src/redux/actions/fetchCoursesAction.jsx +++ b/src/redux/actions/fetchCoursesAction.jsx @@ -14,7 +14,7 @@ const fetchCoursesAction = () => (dispatch) => .then( (response) => { if (response.data.courses) { - dispatch(actions.fetchCoursesSuccess(response.data)); + dispatch(actions.fetchCoursesSuccess(response.data.courses)); } else { dispatch(actions.fetchCoursesFail(response.data)); }