diff --git a/assets/icons/play-line-2.svg b/assets/icons/play-line-2.svg new file mode 100644 index 0000000000..5524807ae6 --- /dev/null +++ b/assets/icons/play-line-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/src/js/v3/shared/icons/types.ts b/assets/src/js/v3/shared/icons/types.ts index 5fe65f2f03..3fb5c9f111 100644 --- a/assets/src/js/v3/shared/icons/types.ts +++ b/assets/src/js/v3/shared/icons/types.ts @@ -292,6 +292,7 @@ export const icons = [ 'play2', 'playFill', 'playLine', + 'playLine2', 'plus', 'plusMinus', 'plusSquare', diff --git a/assets/src/scss/frontend/dashboard/_progress-card.scss b/assets/src/scss/frontend/dashboard/_progress-card.scss index 4dee52410e..3778a814ef 100644 --- a/assets/src/scss/frontend/dashboard/_progress-card.scss +++ b/assets/src/scss/frontend/dashboard/_progress-card.scss @@ -113,14 +113,20 @@ &:focus-within { background-color: $tutor-surface-l1-hover; - .tutor-progress-card-actions { + > .tutor-progress-card-actions { opacity: 1; visibility: visible; } } + &.tutor-active { + background-color: $tutor-surface-l1-hover; + } + &:focus-visible { @include tutor-focus-ring(); + border-radius: $tutor-radius-2xl !important; + z-index: $tutor-z-positive; } @include tutor-breakpoint-down(lg) { @@ -134,10 +140,10 @@ @include tutor-flex(column, stretch, flex-start); height: auto; gap: $tutor-spacing-none; - padding: $tutor-spacing-4 $tutor-spacing-4 $tutor-spacing-5; .tutor-progress-card-inner { flex-direction: column; + gap: $tutor-spacing-none; } .tutor-progress-card-thumbnail { @@ -155,7 +161,7 @@ } &-header { - margin-bottom: $tutor-spacing-4; + margin-bottom: $tutor-spacing-6; } &-details { @@ -168,7 +174,7 @@ &-actions { position: static; - display: block; + display: flex; visibility: visible; opacity: 1; padding: $tutor-spacing-6 0 0; diff --git a/classes/Icon.php b/classes/Icon.php index 32eaf82132..f5f405f060 100644 --- a/classes/Icon.php +++ b/classes/Icon.php @@ -308,6 +308,7 @@ final class Icon { const PLAY_2 = 'play-2'; const PLAY_FILL = 'play-fill'; const PLAY_LINE = 'play-line'; + const PLAY_LINE_2 = 'play-line-2'; const PLUS = 'plus'; const PLUS_MINUS = 'plus-minus'; const PLUS_SQUARE = 'plus-square'; diff --git a/classes/Student.php b/classes/Student.php index 208c8f599c..572527869a 100644 --- a/classes/Student.php +++ b/classes/Student.php @@ -373,7 +373,7 @@ public function get_courses_tab( $active_tab, $post_type_args, $enrolled_course_ ), array( 'label' => __( 'Active', 'tutor' ), - 'icon' => Icon::PLAY_LINE, + 'icon' => Icon::PLAY_LINE_2, 'url' => esc_url( add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( 'courses/active-courses' ) ) ), 'active' => 'courses/active-courses' === $active_tab ? true : false, 'count' => $active_course_count, diff --git a/classes/Utils.php b/classes/Utils.php index aac76ca20a..0fc4fa5365 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -2103,22 +2103,38 @@ public function get_total_students( $search_term = '', $course_id = '', $date = * * @return array */ - public function get_completed_courses_ids_by_user( $user_id = 0 ) { + public function get_completed_courses_ids_by_user( $user_id = 0, $with_bundle_enrolled_courses = true ) { global $wpdb; $user_id = $this->get_user_id( $user_id ); + $with_bundle_enrolled_courses_clause = ''; + if ( ! $with_bundle_enrolled_courses ) { + $with_bundle_enrolled_courses_clause = $wpdb->prepare( + "AND NOT EXISTS ( + SELECT 1 + FROM {$wpdb->postmeta} pm + WHERE pm.post_id = e.ID + AND pm.meta_key = %s + )", + '_tutor_bundle_id' + ); + } + $course_ids = (array) $wpdb->get_col( $wpdb->prepare( "SELECT comment_post_ID AS course_id - FROM {$wpdb->comments} - WHERE comment_agent = %s + FROM {$wpdb->comments} + WHERE comment_agent = %s AND comment_type = %s AND user_id = %d AND comment_post_ID IN ( - select post_parent AS course_id from {$wpdb->posts} where post_type=%s AND post_author = %d - ) - ", + SELECT e.post_parent + FROM {$wpdb->posts} e + WHERE e.post_type = %s + AND e.post_author = %d + {$with_bundle_enrolled_courses_clause} + )", 'TutorLMSPlugin', 'course_completed', $user_id, diff --git a/models/CourseModel.php b/models/CourseModel.php index b866ced236..45f213ffff 100644 --- a/models/CourseModel.php +++ b/models/CourseModel.php @@ -1291,7 +1291,7 @@ function ( $item ) { */ public static function get_completed_courses_by_user( $user_id = 0, $offset = 0, $posts_per_page = -1, $args = array() ) { $user_id = tutor_utils()->get_user_id( $user_id ); - $course_ids = tutor_utils()->get_completed_courses_ids_by_user( $user_id ); + $course_ids = tutor_utils()->get_completed_courses_ids_by_user( $user_id, false ); if ( count( $course_ids ) ) { $course_post_type = tutor()->course_post_type; @@ -1301,6 +1301,7 @@ public static function get_completed_courses_by_user( $user_id = 0, $offset = 0, 'post__in' => $course_ids, 'posts_per_page' => $posts_per_page, 'offset' => $offset, + 'orderby' => 'post__in', ); $args = apply_filters( 'tutor_get_completed_courses_by_user', $args, $user_id, $course_post_type ); @@ -1326,7 +1327,7 @@ public static function get_completed_courses_by_user( $user_id = 0, $offset = 0, */ public static function get_active_courses_by_user( $user_id = 0, $offset = 0, $posts_per_page = -1, $args = array() ) { $user_id = tutor_utils()->get_user_id( $user_id ); - $course_ids = tutor_utils()->get_completed_courses_ids_by_user( $user_id ); + $course_ids = tutor_utils()->get_completed_courses_ids_by_user( $user_id, false ); $enrolled_course_ids = tutor_utils()->get_enrolled_courses_ids_by_user( $user_id, false ); $active_courses = array_diff( $enrolled_course_ids, $course_ids ); @@ -1338,6 +1339,7 @@ public static function get_active_courses_by_user( $user_id = 0, $offset = 0, $p 'post__in' => $active_courses, 'posts_per_page' => $posts_per_page, 'offset' => $offset, + 'orderby' => 'post__in', ); $args = apply_filters( 'tutor_get_active_courses_by_user', $args, $user_id, $course_post_type ); @@ -1377,6 +1379,7 @@ public static function get_enrolled_courses_by_user( $user_id = 0, $post_status 'post__in' => $course_ids, 'offset' => $offset, 'posts_per_page' => $posts_per_page, + 'orderby' => 'post__in', ); $args = apply_filters( 'tutor_get_enrolled_courses_by_user', $args, $user_id, $course_post_type ); diff --git a/templates/dashboard/courses.php b/templates/dashboard/courses.php index d7aedbd82b..07e4434957 100644 --- a/templates/dashboard/courses.php +++ b/templates/dashboard/courses.php @@ -45,27 +45,32 @@ $active_tab = 'courses'; } -$enrolled_courses = CourseModel::get_enrolled_courses_by_user( get_current_user_id(), array( 'private', 'publish' ), $offset, $courses_per_page ); -$active_courses = CourseModel::get_active_courses_by_user( null, $offset, $courses_per_page, array( 'post_status' => array( 'private', 'publish' ) ) ); -$completed_courses = CourseModel::get_completed_courses_by_user( null, $offset, $courses_per_page, array( 'post_status' => array( 'private', 'publish' ) ) ); - -$enrolled_course_count = is_a( $enrolled_courses, 'WP_Query' ) ? $enrolled_courses->found_posts : 0; -$active_course_count = is_a( $active_courses, 'WP_Query' ) ? $active_courses->found_posts : 0; -$completed_course_count = is_a( $completed_courses, 'WP_Query' ) ? $completed_courses->found_posts : 0; - -// Get Paginated course list. -$courses_list_array = array( - 'courses' => $enrolled_courses, - 'courses/active-courses' => $active_courses, - 'courses/completed-courses' => $completed_courses, - 'courses/wishlist' => array(), - 'courses/my-quiz-attempts' => __( 'Quiz Attempts', 'tutor' ), -); +// Only fetch the paginated list for the active tab. +switch ( $active_tab ) { + case 'courses': + $courses_list = CourseModel::get_enrolled_courses_by_user( get_current_user_id(), array( CourseModel::STATUS_PRIVATE, CourseModel::STATUS_PUBLISH ), $offset, $courses_per_page ); + break; + case 'courses/active-courses': + $courses_list = CourseModel::get_active_courses_by_user( null, $offset, $courses_per_page, array( 'post_status' => array( CourseModel::STATUS_PRIVATE, CourseModel::STATUS_PUBLISH ) ) ); + break; + case 'courses/completed-courses': + $courses_list = CourseModel::get_completed_courses_by_user( null, $offset, $courses_per_page, array( 'post_status' => array( CourseModel::STATUS_PRIVATE, CourseModel::STATUS_PUBLISH ) ) ); + break; + default: + $courses_list = null; + break; +} -$courses_tab = ( new Student() )->get_courses_tab( $active_tab, $post_type_args, $enrolled_course_count, $active_course_count, $completed_course_count ); +// Separate count queries with no offset so tab counts are always accurate regardless of current page. +$enrolled_courses_for_count = CourseModel::get_enrolled_courses_by_user( get_current_user_id(), array( CourseModel::STATUS_PRIVATE, CourseModel::STATUS_PUBLISH ), 0, 1 ); +$active_courses_for_count = CourseModel::get_active_courses_by_user( null, 0, 1, array( 'post_status' => array( CourseModel::STATUS_PRIVATE, CourseModel::STATUS_PUBLISH ) ) ); +$completed_courses_for_count = CourseModel::get_completed_courses_by_user( null, 0, 1, array( 'post_status' => array( CourseModel::STATUS_PRIVATE, CourseModel::STATUS_PUBLISH ) ) ); -// Prepare course list based on page tab. -$courses_list = $courses_list_array[ $active_tab ]; +$enrolled_course_count = is_a( $enrolled_courses_for_count, 'WP_Query' ) ? $enrolled_courses_for_count->found_posts : 0; +$active_course_count = is_a( $active_courses_for_count, 'WP_Query' ) ? $active_courses_for_count->found_posts : 0; +$completed_course_count = is_a( $completed_courses_for_count, 'WP_Query' ) ? $completed_courses_for_count->found_posts : 0; + +$courses_tab = ( new Student() )->get_courses_tab( $active_tab, $post_type_args, $enrolled_course_count, $active_course_count, $completed_course_count ); ?> @@ -92,16 +97,22 @@ break; } elseif ( 'courses' === $active_tab || 'courses/active-courses' === $active_tab || 'courses/completed-courses' === $active_tab ) : - // Prepare course list based on page tab. - $courses_list = $courses_list_array[ $active_tab ]; ?>