From 94c9d7335bd533b6c222ede01e7633a16f3b29e2 Mon Sep 17 00:00:00 2001 From: sanjana4khan Date: Fri, 15 May 2026 16:20:12 +0600 Subject: [PATCH 1/6] Time spent logic change for student dashboard --- classes/Course.php | 24 ++++++++++++++++------- classes/Utils.php | 4 ++-- templates/dashboard/student-dashboard.php | 8 ++++---- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/classes/Course.php b/classes/Course.php index 73eaa08070..e1ed01f723 100644 --- a/classes/Course.php +++ b/classes/Course.php @@ -3437,7 +3437,7 @@ public function render_course_action_btn( int $course_id ) { } /** - * Calculate the total course duration for a set of courses. + * Calculate the total course duration for a set of courses and returns the total time in hours, minutes, and seconds. * * @since 4.0.0 * @@ -3455,19 +3455,29 @@ public static function get_total_course_duration( $course_ids ): array { foreach ( $course_ids as $id ) { $duration = tutor_utils()->get_course_duration( (int) $id, true ); - $total_seconds += ( (int) $duration['durationHours'] * 3600 ) - + ( (int) $duration['durationMinutes'] * 60 ) + $completion_percentage = tutor_utils()->is_completed_course( $id ) + ? 100 + : (int) tutor_utils()->get_course_completed_percent( (int) $id ); + + if ( 0 === $completion_percentage ) { + continue; + } + + $course_duration_in_seconds = ( (int) $duration['durationHours'] * HOUR_IN_SECONDS ) + + ( (int) $duration['durationMinutes'] * MINUTE_IN_SECONDS ) + ( (int) $duration['durationSeconds'] ); + + // Calculate the time spent by a user based on the course completion percentage. + $total_seconds += $course_duration_in_seconds * ( $completion_percentage / 100 ); } - $hours = floor( $total_seconds / 3600 ); - $minutes = floor( $total_seconds / 60 ); - $seconds = $total_seconds; + $hours = floor( $total_seconds / HOUR_IN_SECONDS ); + $minutes = floor( $total_seconds / MINUTE_IN_SECONDS ); return array( 'hours' => (int) $hours, 'minutes' => (int) $minutes, - 'seconds' => (int) $seconds, + 'seconds' => (int) $total_seconds, ); } diff --git a/classes/Utils.php b/classes/Utils.php index a6d26ca9cd..5906306d53 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -8119,10 +8119,10 @@ public function course_with_materials(): array { * @since 2.0.0 * * @param int $course_id course id. - * @param array $return_array return array. + * @param bool $return_array return array. * @param array $texts texts. * - * @return string + * @return string | array */ public function get_course_duration( $course_id, $return_array, $texts = array( 'h' => 'hr', diff --git a/templates/dashboard/student-dashboard.php b/templates/dashboard/student-dashboard.php index de8a7f140a..fe9a248336 100644 --- a/templates/dashboard/student-dashboard.php +++ b/templates/dashboard/student-dashboard.php @@ -53,19 +53,19 @@ $enrolled_course = CourseModel::get_enrolled_courses_by_user( $user_id, array( 'private', 'publish' ) ); $completed_courses = CourseModel::get_completed_courses_by_user( $user_id, 0, -1, array( 'post_status' => array( 'private', 'publish' ) ) ); $has_completed_courses = is_object( $completed_courses ) && $completed_courses->have_posts(); - $completed_courses_ids = $has_completed_courses ? wp_list_pluck( $completed_courses->posts, 'ID' ) : array(); $active_courses = CourseModel::get_active_courses_by_user( $user_id, 0, -1, array( 'post_status' => array( 'private', 'publish' ) ) ); $enrolled_course_count = $enrolled_course ? $enrolled_course->post_count : 0; $completed_course_count = $has_completed_courses ? $completed_courses->post_count : 0; $active_course_count = is_object( $active_courses ) && $active_courses->have_posts() ? $active_courses->post_count : 0; + $enrolled_courses_ids = $enrolled_course_count ? wp_list_pluck( $enrolled_course->posts, 'ID' ) : array(); $enrolled_course_link = tutor_utils()->tutor_dashboard_url( 'courses' ); $completed_course_link = tutor_utils()->tutor_dashboard_url( 'courses/completed-courses' ); $active_course_link = tutor_utils()->tutor_dashboard_url( 'courses/active-courses' ); - $time_spent = Course::get_total_course_duration( $completed_courses_ids ); - $grid_col = $time_spent['hours'] > 0 ? 'tutor-grid-cols-4' : 'tutor-grid-cols-3'; + $time_spent = Course::get_total_course_duration( $enrolled_courses_ids ); + $grid_col = $time_spent['minutes'] > 0 ? 'tutor-grid-cols-4' : 'tutor-grid-cols-3'; ?>
@@ -115,7 +115,7 @@
- 0 ) : ?> + 0 ) : ?>
Date: Tue, 19 May 2026 12:30:57 +0600 Subject: [PATCH 2/6] mintue value added to card if time spent is less than hour. --- templates/dashboard/student-dashboard.php | 43 ++++++++++++++--------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/templates/dashboard/student-dashboard.php b/templates/dashboard/student-dashboard.php index fe9a248336..25b72bb88f 100644 --- a/templates/dashboard/student-dashboard.php +++ b/templates/dashboard/student-dashboard.php @@ -64,10 +64,15 @@ $completed_course_link = tutor_utils()->tutor_dashboard_url( 'courses/completed-courses' ); $active_course_link = tutor_utils()->tutor_dashboard_url( 'courses/active-courses' ); - $time_spent = Course::get_total_course_duration( $enrolled_courses_ids ); - $grid_col = $time_spent['minutes'] > 0 ? 'tutor-grid-cols-4' : 'tutor-grid-cols-3'; + // Time spent calculation. + $time_spent = Course::get_total_course_duration( $enrolled_courses_ids ); + $is_hour_format = $time_spent['hours'] > 0; + $has_time_spent = $is_hour_format || $time_spent['minutes'] > 0; + $time_spent_value = $is_hour_format ? $time_spent['hours'] : $time_spent['minutes']; + $time_spent_unit = $is_hour_format ? 'h+' : 'm+'; + $time_spent_unit_modal = $is_hour_format ? 'hours' : 'minutes'; ?> -
- + 0 ) : ?>
+ From 3daf87febbfb6b87d3480add1ae3880c8aee5ab7 Mon Sep 17 00:00:00 2001 From: Sazedul Haque Date: Wed, 20 May 2026 17:14:19 +0600 Subject: [PATCH 3/6] Social links added to profile completion --- classes/Utils.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/classes/Utils.php b/classes/Utils.php index a6d26ca9cd..23f20fbb53 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -7216,10 +7216,12 @@ public function user_profile_completion( $user_id = 0 ) { $instructor_status = get_user_meta( $user_id, '_tutor_instructor_status', true ); $settings_url = Dashboard::get_account_page_url( 'settings' ); + $social_settings_url = Dashboard::get_account_page_url( 'settings?tab=social-accounts' ); $withdraw_settings_url = Dashboard::get_account_page_url( 'settings?tab=withdraw' ); $required_fields = array( '_tutor_profile_photo' => __( 'Set Your Profile Photo', 'tutor' ), + '_tutor_social_links' => __( 'Add Your Social Links', 'tutor' ), '_tutor_profile_bio' => __( 'Set Your Bio', 'tutor' ), ); @@ -7228,16 +7230,31 @@ public function user_profile_completion( $user_id = 0 ) { $required_fields['_tutor_withdraw_method_data'] = __( 'Set Withdraw Method', 'tutor' ); } + // Check if any individual social link meta is set. + $social_meta_keys = array_keys( $this->tutor_user_social_icons() ); + $has_social_link = false; + foreach ( $social_meta_keys as $social_key ) { + if ( get_user_meta( $user_id, $social_key, true ) ) { + $has_social_link = true; + break; + } + } + // url where user should redirect for profile completion. $profile_completion_urls = array( '_tutor_profile_photo' => $settings_url, '_tutor_profile_bio' => $settings_url, + '_tutor_social_links' => $social_settings_url, '_tutor_withdraw_method_data' => $withdraw_settings_url, ); foreach ( $required_fields as $key => $field ) { + $is_set = '_tutor_social_links' === $key + ? $has_social_link + : (bool) get_user_meta( $user_id, $key, true ); + $required_fields[ $key ] = array( 'text' => $field, - 'is_set' => get_user_meta( $user_id, $key, true ) ? true : false, + 'is_set' => $is_set, 'url' => $profile_completion_urls[ $key ], ); } From f67ba636f014d8a628d0d1034586f49e18cc7752 Mon Sep 17 00:00:00 2001 From: Sazedul Haque Date: Wed, 20 May 2026 17:14:46 +0600 Subject: [PATCH 4/6] Profile completion support added for students --- .../profile-completion.php | 0 templates/dashboard/dashboard.php | 2 +- templates/dashboard/student-dashboard.php | 29 ++----------------- 3 files changed, 3 insertions(+), 28 deletions(-) rename templates/dashboard/{instructor/home => components}/profile-completion.php (100%) diff --git a/templates/dashboard/instructor/home/profile-completion.php b/templates/dashboard/components/profile-completion.php similarity index 100% rename from templates/dashboard/instructor/home/profile-completion.php rename to templates/dashboard/components/profile-completion.php diff --git a/templates/dashboard/dashboard.php b/templates/dashboard/dashboard.php index 9cf103154e..1525d7bbf0 100644 --- a/templates/dashboard/dashboard.php +++ b/templates/dashboard/dashboard.php @@ -12,5 +12,5 @@ defined( 'ABSPATH' ) || exit; do_action( 'tutor_before_dashboard_content' ); -tutor_load_template( 'dashboard.instructor.home.profile-completion' ); +tutor_load_template( 'dashboard.components.profile-completion' ); tutor_load_template( 'dashboard.instructor.home' ); diff --git a/templates/dashboard/student-dashboard.php b/templates/dashboard/student-dashboard.php index de8a7f140a..02bb78fe4f 100644 --- a/templates/dashboard/student-dashboard.php +++ b/templates/dashboard/student-dashboard.php @@ -15,39 +15,14 @@ use TUTOR\Dashboard; use TUTOR\Icon; use Tutor\Components\SvgIcon; -use Tutor\Components\Constants\Color; use Tutor\Helpers\UrlHelper; use Tutor\Models\CourseModel; $user_id = get_current_user_id(); $user_data = get_userdata( $user_id ); - -if ( tutor_utils()->get_option( 'enable_profile_completion' ) ) { - $profile_completion = tutor_utils()->user_profile_completion( $user_id ); - - $photo_data = $profile_completion['_tutor_profile_photo'] ?? array(); - $is_set = $photo_data['is_set'] ?? null; - $text = $photo_data['text'] ?? ''; - if ( empty( $is_set ) ) { - ?> -
-
-
- name( Icon::INFO )->size( 24 )->color( Color::BRAND )->render(); ?> - - - -
- - - -
-
- +
- + 0 ) : ?> Date: Thu, 21 May 2026 16:01:12 +0600 Subject: [PATCH 5/6] Student dashboard empty state design added --- assets/images/illustrations/confetti.svg | 25 +----- .../images/illustrations/dashboard-empty.svg | 1 + .../src/scss/frontend/dashboard/_index.scss | 2 + .../dashboard/_profile-completion.scss | 38 ++++++++ .../pages/_instructor-dashboard.scss | 36 -------- .../dashboard/pages/_student-dashboard.scss | 47 ++++++++++ assets/src/scss/frontend/kids/_dashboard.scss | 15 ++++ templates/dashboard/student-dashboard.php | 15 +++- .../dashboard/student/dashboard-empty.php | 86 +++++++++++++++++++ 9 files changed, 201 insertions(+), 64 deletions(-) create mode 100644 assets/images/illustrations/dashboard-empty.svg create mode 100644 assets/src/scss/frontend/dashboard/_profile-completion.scss create mode 100644 assets/src/scss/frontend/dashboard/pages/_student-dashboard.scss create mode 100644 templates/dashboard/student/dashboard-empty.php diff --git a/assets/images/illustrations/confetti.svg b/assets/images/illustrations/confetti.svg index 810ee97024..dd7ef638dc 100644 --- a/assets/images/illustrations/confetti.svg +++ b/assets/images/illustrations/confetti.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/assets/images/illustrations/dashboard-empty.svg b/assets/images/illustrations/dashboard-empty.svg new file mode 100644 index 0000000000..c2ac5a4c16 --- /dev/null +++ b/assets/images/illustrations/dashboard-empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/src/scss/frontend/dashboard/_index.scss b/assets/src/scss/frontend/dashboard/_index.scss index be7b568821..aa0559ba04 100644 --- a/assets/src/scss/frontend/dashboard/_index.scss +++ b/assets/src/scss/frontend/dashboard/_index.scss @@ -10,6 +10,7 @@ @forward 'layout/account'; // Dashboard components +@forward 'profile-completion'; @forward 'stat-card'; @forward 'progress-card'; @forward 'course-card'; @@ -20,6 +21,7 @@ @forward 'pages/courses'; @forward 'pages/announcements'; @forward 'pages/wishlist'; +@forward 'pages/student-dashboard'; @forward 'pages/instructor-dashboard'; // Account Pages diff --git a/assets/src/scss/frontend/dashboard/_profile-completion.scss b/assets/src/scss/frontend/dashboard/_profile-completion.scss new file mode 100644 index 0000000000..d9fc4912db --- /dev/null +++ b/assets/src/scss/frontend/dashboard/_profile-completion.scss @@ -0,0 +1,38 @@ +@use '@Core/scss/mixins' as *; +@use '@Core/scss/tokens' as *; + +.tutor-profile-completion { + position: relative; + margin-bottom: $tutor-spacing-7; + + &-header { + @include tutor-flex(row, center, space-between); + padding: $tutor-spacing-5; + background-color: $tutor-surface-l1; + border: 1px solid $tutor-border-idle; + border-radius: $tutor-radius-2xl; + + &.tutor-expanded { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + } + + &-body { + @include tutor-flex(column); + gap: $tutor-spacing-5; + padding: $tutor-spacing-5 26px; + border: 1px solid $tutor-border-idle; + border-top: none; + border-bottom-left-radius: $tutor-radius-2xl; + border-bottom-right-radius: $tutor-radius-2xl; + box-shadow: $tutor-shadow-lg; + + position: absolute; + top: 100%; + left: 0; + width: 100%; + background-color: $tutor-surface-l1; + z-index: $tutor-z-dropdown; + } +} diff --git a/assets/src/scss/frontend/dashboard/pages/_instructor-dashboard.scss b/assets/src/scss/frontend/dashboard/pages/_instructor-dashboard.scss index b5d6f073b3..9b3a4b095a 100644 --- a/assets/src/scss/frontend/dashboard/pages/_instructor-dashboard.scss +++ b/assets/src/scss/frontend/dashboard/pages/_instructor-dashboard.scss @@ -1,42 +1,6 @@ @use '@Core/scss/mixins' as *; @use '@Core/scss/tokens' as *; -.tutor-profile-completion { - position: relative; - margin-bottom: $tutor-spacing-6; - - &-header { - @include tutor-flex(row, center, space-between); - padding: $tutor-spacing-5; - background-color: $tutor-surface-l1; - border: 1px solid $tutor-border-idle; - border-radius: $tutor-radius-2xl; - - &.tutor-expanded { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } - } - - &-body { - @include tutor-flex(column); - gap: $tutor-spacing-5; - padding: $tutor-spacing-5 26px; - border: 1px solid $tutor-border-idle; - border-top: none; - border-bottom-left-radius: $tutor-radius-2xl; - border-bottom-right-radius: $tutor-radius-2xl; - box-shadow: $tutor-shadow-lg; - - position: absolute; - top: 100%; - left: 0; - width: 100%; - background-color: $tutor-surface-l1; - z-index: $tutor-z-dropdown; - } -} - .tutor-stat-card-value { @include tutor-text(h3); } diff --git a/assets/src/scss/frontend/dashboard/pages/_student-dashboard.scss b/assets/src/scss/frontend/dashboard/pages/_student-dashboard.scss new file mode 100644 index 0000000000..78a670295c --- /dev/null +++ b/assets/src/scss/frontend/dashboard/pages/_student-dashboard.scss @@ -0,0 +1,47 @@ +@use '@Core/scss/tokens' as *; +@use '@Core/scss/mixins' as *; + +.tutor-dashboard-welcome-card { + @include tutor-flex(row, center, space-between); + @include tutor-card-base(); + @include tutor-card-radius(2xl); + padding: $tutor-spacing-8; + margin-bottom: $tutor-spacing-7; + + @include tutor-breakpoint-down(sm) { + flex-direction: column; + align-items: start; + gap: $tutor-spacing-8; + } + + .tutor-dashboard-welcome-content { + max-width: 270px; + } + + .tutor-dashboard-welcome-badge { + @include tutor-typography(tiny, semibold, brand); + display: inline-flex; + align-items: center; + gap: $tutor-spacing-2; + background-color: $tutor-surface-brand-tertiary; + padding: $tutor-spacing-2 $tutor-spacing-5; + border-radius: $tutor-radius-6xl; + } + + .tutor-dashboard-welcome-banner { + padding-inline-end: $tutor-spacing-6; + } +} + +.tutor-dashboard-quick-tips-card { + @include tutor-flex(row, start, space-between); + @include tutor-card-base(); + @include tutor-card-radius(2xl); + padding: $tutor-spacing-8; + margin-bottom: $tutor-spacing-7; + + @include tutor-breakpoint-down(sm) { + flex-direction: column; + gap: $tutor-spacing-8; + } +} diff --git a/assets/src/scss/frontend/kids/_dashboard.scss b/assets/src/scss/frontend/kids/_dashboard.scss index 019b18bf63..f080da8c4d 100644 --- a/assets/src/scss/frontend/kids/_dashboard.scss +++ b/assets/src/scss/frontend/kids/_dashboard.scss @@ -47,6 +47,12 @@ @include tutor-kids-shadow; } + .tutor-dashboard-welcome-card, + .tutor-dashboard-quick-tips-card, + .tutor-profile-completion-header { + @include tutor-kids-shadow(false); + } + .tutor-billing-card:hover { @include tutor-kids-shadow; &:not(:last-of-type) { @@ -70,6 +76,15 @@ } // home + .tutor-profile-completion-body { + border: none; + box-shadow: + 0 2px 0 2px $tutor-border-idle, + 0 5px 0 0 $tutor-border-idle; + border-bottom-left-radius: $tutor-radius-5xl; + border-bottom-right-radius: $tutor-radius-5xl; + } + .tutor-student-dashboard-courses { .tutor-progress-card:not(:first-child) { margin-top: $tutor-spacing-4; diff --git a/templates/dashboard/student-dashboard.php b/templates/dashboard/student-dashboard.php index 02bb78fe4f..5a3da3152e 100644 --- a/templates/dashboard/student-dashboard.php +++ b/templates/dashboard/student-dashboard.php @@ -20,18 +20,25 @@ $user_id = get_current_user_id(); $user_data = get_userdata( $user_id ); + +$enrolled_course = CourseModel::get_enrolled_courses_by_user( $user_id, array( 'private', 'publish' ) ); +$enrolled_course_count = $enrolled_course ? $enrolled_course->post_count : 0; + +do_action( 'tutor_before_dashboard_content' ); +tutor_load_template( 'dashboard.components.profile-completion' ); + +if ( 0 === $enrolled_course_count ) { + tutor_load_template( 'dashboard.student.dashboard-empty' ); + return; +} ?> - -
array( 'private', 'publish' ) ) ); $has_completed_courses = is_object( $completed_courses ) && $completed_courses->have_posts(); $completed_courses_ids = $has_completed_courses ? wp_list_pluck( $completed_courses->posts, 'ID' ) : array(); $active_courses = CourseModel::get_active_courses_by_user( $user_id, 0, -1, array( 'post_status' => array( 'private', 'publish' ) ) ); - $enrolled_course_count = $enrolled_course ? $enrolled_course->post_count : 0; $completed_course_count = $has_completed_courses ? $completed_courses->post_count : 0; $active_course_count = is_object( $active_courses ) && $active_courses->have_posts() ? $active_courses->post_count : 0; diff --git a/templates/dashboard/student/dashboard-empty.php b/templates/dashboard/student/dashboard-empty.php new file mode 100644 index 0000000000..a002e9dd61 --- /dev/null +++ b/templates/dashboard/student/dashboard-empty.php @@ -0,0 +1,86 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +use Tutor\Components\Button; +use Tutor\Components\Constants\Color; +use Tutor\Components\Constants\Size; +use Tutor\Components\Constants\Variant; +use Tutor\Components\SvgIcon; +use Tutor\Helpers\UrlHelper; +use TUTOR\Icon; + +defined( 'ABSPATH' ) || exit; + +$quick_tips = array( + __( 'Use notes to save key ideas as you watch', 'tutor' ), + __( 'Check the calendar for upcoming live sessions', 'tutor' ), + __( 'Discussions are a great place to ask questions', 'tutor' ), + __( 'You can pause and resume courses any time', 'tutor' ), +); +?> +
+
+
+ + + + <?php esc_html_e( 'Confetti', 'tutor' ); ?> +
+

+ +

+

+ +

+ label( __( 'Explore Courses', 'tutor' ) ) + ->variant( Variant::PRIMARY ) + ->size( Size::X_SMALL ) + ->icon( Icon::ARROW_RIGHT_2, 'right' ) + ->tag( 'a' ) + ->attr( 'href', tutor_utils()->course_archive_page_url() ) + ->render(); + ?> +
+
+ <?php esc_html_e( 'Confetti', 'tutor' ); ?> +
+
+ +
+
+
+ name( Icon::BULB_LINE )->size( Size::SIZE_32 )->color( Color::BRAND )->render(); ?> +
+
+
+ +
+
+ +
+
+
+
+ $value ) : ?> +
+ name( Icon::CHECK_2 )->color( Color::BRAND )->attr( 'class', 'tutor-mt-1' )->render(); ?> +
+ +
+
+ +
+
From 5f383f5e99a3a3b593d171c2f3b9c18f302746ed Mon Sep 17 00:00:00 2001 From: Sazedul Haque Date: Fri, 22 May 2026 15:26:14 +0600 Subject: [PATCH 6/6] Split student dashboard templates into multiple files with improvements --- .../scss/frontend/dashboard/_stat-card.scss | 2 - components/EmptyState.php | 10 +- templates/dashboard.php | 3 +- templates/dashboard/courses/course-card.php | 6 +- templates/dashboard/student-dashboard.php | 303 ------------------ .../dashboard/student/continue-learning.php | 51 +++ templates/dashboard/student/dashboard.php | 46 +++ templates/dashboard/student/stat-card.php | 47 +++ templates/dashboard/student/stats.php | 113 +++++++ .../dashboard/student/time-spent-modal.php | 91 ++++++ 10 files changed, 361 insertions(+), 311 deletions(-) delete mode 100644 templates/dashboard/student-dashboard.php create mode 100644 templates/dashboard/student/continue-learning.php create mode 100644 templates/dashboard/student/dashboard.php create mode 100644 templates/dashboard/student/stat-card.php create mode 100644 templates/dashboard/student/stats.php create mode 100644 templates/dashboard/student/time-spent-modal.php diff --git a/assets/src/scss/frontend/dashboard/_stat-card.scss b/assets/src/scss/frontend/dashboard/_stat-card.scss index db62692f29..4bb156b58d 100644 --- a/assets/src/scss/frontend/dashboard/_stat-card.scss +++ b/assets/src/scss/frontend/dashboard/_stat-card.scss @@ -111,8 +111,6 @@ } &-time-spent { - cursor: pointer; - .tutor-stat-card-icon { color: $tutor-text-exception4; } diff --git a/components/EmptyState.php b/components/EmptyState.php index 440815c172..69251263f7 100644 --- a/components/EmptyState.php +++ b/components/EmptyState.php @@ -159,8 +159,16 @@ public function get(): string { ); } + // Merge custom classes. + $wrapper_classes = 'tutor-px-9 tutor-py-10 tutor-flex-center-col'; + if ( ! empty( $this->attributes['class'] ) ) { + $wrapper_classes .= ' ' . $this->attributes['class']; + unset( $this->attributes['class'] ); + } + $this->attributes['class'] = $wrapper_classes; + $this->component_string = sprintf( - '
+ '
%s
%s
%s diff --git a/templates/dashboard.php b/templates/dashboard.php index 7acae0e5ce..fcdf4b0705 100644 --- a/templates/dashboard.php +++ b/templates/dashboard.php @@ -115,7 +115,7 @@ } elseif ( User::is_instructor_view() ) { tutor_load_template( 'dashboard.dashboard' ); } else { - tutor_load_template( 'dashboard.student-dashboard' ); + tutor_load_template( 'dashboard.student.dashboard' ); } ?>
@@ -123,7 +123,6 @@
- diff --git a/templates/dashboard/courses/course-card.php b/templates/dashboard/courses/course-card.php index c8b2d6e8ec..25d3599b39 100644 --- a/templates/dashboard/courses/course-card.php +++ b/templates/dashboard/courses/course-card.php @@ -30,11 +30,11 @@ ?>
-
+
- <?php the_title(); ?> + <?php the_title_attribute(); ?>
@@ -47,7 +47,7 @@

- +

diff --git a/templates/dashboard/student-dashboard.php b/templates/dashboard/student-dashboard.php deleted file mode 100644 index d0e98b824e..0000000000 --- a/templates/dashboard/student-dashboard.php +++ /dev/null @@ -1,303 +0,0 @@ - - * @link https://themeum.com - * @since 4.0.0 - */ - -defined( 'ABSPATH' ) || exit; - -use TUTOR\Course; -use TUTOR\Dashboard; -use TUTOR\Icon; -use Tutor\Components\SvgIcon; -use Tutor\Helpers\UrlHelper; -use Tutor\Models\CourseModel; - -$user_id = get_current_user_id(); -$user_data = get_userdata( $user_id ); - -$enrolled_course = CourseModel::get_enrolled_courses_by_user( $user_id, array( 'private', 'publish' ) ); -$enrolled_course_count = $enrolled_course ? $enrolled_course->post_count : 0; - -do_action( 'tutor_before_dashboard_content' ); -tutor_load_template( 'dashboard.components.profile-completion' ); - -if ( 0 === $enrolled_course_count ) { - tutor_load_template( 'dashboard.student.dashboard-empty' ); - return; -} -?> -
- array( 'private', 'publish' ) ) ); - $has_completed_courses = is_object( $completed_courses ) && $completed_courses->have_posts(); - $active_courses = CourseModel::get_active_courses_by_user( $user_id, 0, -1, array( 'post_status' => array( 'private', 'publish' ) ) ); - - $completed_course_count = $has_completed_courses ? $completed_courses->post_count : 0; - $active_course_count = is_object( $active_courses ) && $active_courses->have_posts() ? $active_courses->post_count : 0; - $enrolled_courses_ids = $enrolled_course_count ? wp_list_pluck( $enrolled_course->posts, 'ID' ) : array(); - - $enrolled_course_link = tutor_utils()->tutor_dashboard_url( 'courses' ); - $completed_course_link = tutor_utils()->tutor_dashboard_url( 'courses/completed-courses' ); - $active_course_link = tutor_utils()->tutor_dashboard_url( 'courses/active-courses' ); - - // Time spent calculation. - $time_spent = Course::get_total_course_duration( $enrolled_courses_ids ); - $is_hour_format = $time_spent['hours'] > 0; - $has_time_spent = $is_hour_format || $time_spent['minutes'] > 0; - $time_spent_value = $is_hour_format ? $time_spent['hours'] : $time_spent['minutes']; - $time_spent_unit = $is_hour_format ? 'h+' : 'm+'; - $time_spent_unit_modal = $is_hour_format ? 'hours' : 'minutes'; - ?> - - - 0 ) : ?> -
- -
- -
- - array( 'private', 'publish' ) ) ); -?> - -have_posts() ) : ?> -
-
-
- -
- - - -
-
- have_posts() ) : - $courses_in_progress->the_post(); - $tutor_course_img = get_tutor_course_thumbnail_src(); - $course_categories = get_tutor_course_categories(); - $course_progress = tutor_utils()->get_course_completed_percent( get_the_ID(), 0, true ); - $completed_number = 0 === (int) $course_progress['completed_count'] ? 1 : (int) $course_progress['completed_count']; - $course_learning_url = tutor_utils()->get_course_first_lesson(); - if ( get_post_type() !== tutor()->course_post_type ) { - $course_learning_url = get_permalink(); - } - ?> -
-
-
- <?php the_title(); ?> -
-
-
- -
- -
- -

-
-
-
- - - -
-
-
-
-
-
-
-
-
-
- -
-
- - -
-
- diff --git a/templates/dashboard/student/continue-learning.php b/templates/dashboard/student/continue-learning.php new file mode 100644 index 0000000000..910c22f546 --- /dev/null +++ b/templates/dashboard/student/continue-learning.php @@ -0,0 +1,51 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use Tutor\Components\EmptyState; +use Tutor\Models\CourseModel; + +$user_id = $user_id ?? get_current_user_id(); +$courses_in_progress = CourseModel::get_active_courses_by_user( $user_id, 0, 2, array( 'post_status' => array( 'private', 'publish' ) ) ); +?> +
+
+
+ +
+ have_posts() ) : ?> + + + + +
+
+ have_posts() ) : + while ( $courses_in_progress->have_posts() ) : + $courses_in_progress->the_post(); + tutor_load_template( 'dashboard.courses.course-card' ); + endwhile; + wp_reset_postdata(); + else : + EmptyState::make() + ->title( __( 'No Courses Found', 'tutor' ) ) + ->icon( tutor_utils()->get_themed_svg( 'images/illustrations/learning-empty.svg' ) ) + ->attr( 'class', 'tutor-card' ) + ->render(); + endif; + ?> +
+
diff --git a/templates/dashboard/student/dashboard.php b/templates/dashboard/student/dashboard.php new file mode 100644 index 0000000000..de3427c77d --- /dev/null +++ b/templates/dashboard/student/dashboard.php @@ -0,0 +1,46 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use TUTOR\Course; +use Tutor\Models\CourseModel; + +$user_id = get_current_user_id(); +$user_data = get_userdata( $user_id ); + +$enrolled_course = CourseModel::get_enrolled_courses_by_user( $user_id, array( 'private', 'publish' ) ); +$enrolled_course_count = $enrolled_course ? $enrolled_course->post_count : 0; + +do_action( 'tutor_before_dashboard_content' ); +tutor_load_template( 'dashboard.components.profile-completion' ); + +if ( 0 === $enrolled_course_count ) { + tutor_load_template( 'dashboard.student.dashboard-empty' ); + return; +} + +tutor_load_template( + 'dashboard.student.stats', + array( + 'user_id' => $user_id, + 'user_data' => $user_data, + ) +); + +tutor_load_template( + 'dashboard.student.continue-learning', + array( + 'user_id' => $user_id, + ) +); + +do_action( 'tutor_after_continue_learning_section' ); diff --git a/templates/dashboard/student/stat-card.php b/templates/dashboard/student/stat-card.php new file mode 100644 index 0000000000..f1ff6b6dc5 --- /dev/null +++ b/templates/dashboard/student/stat-card.php @@ -0,0 +1,47 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use Tutor\Components\SvgIcon; + +$tag = isset( $url ) && ! empty( $url ) ? 'a' : 'div'; +$class_name = $class ?? ''; +$icon_size = $icon_size ?? 20; +$modal_id = isset( $modal_id ) ? sanitize_key( $modal_id ) : ''; +$modal_action = $modal_id ? sprintf( "TutorCore.modal.showModal('%s')", $modal_id ) : ''; +$card_attributes = ''; + +if ( 'a' === $tag ) { + $card_attributes = sprintf( ' href="%s"', esc_url( $url ) ); +} elseif ( $modal_action ) { + $card_attributes = sprintf( + ' role="button" tabindex="0" @click="%1$s" @keydown.enter.prevent="%1$s" @keydown.space.prevent="%1$s"', + esc_attr( $modal_action ) + ); +} +?> + +< class="tutor-stat-card "> +
+

+ +

+
+ name( $icon )->size( $icon_size )->render(); ?> +
+
+
+
+ +
+
+> diff --git a/templates/dashboard/student/stats.php b/templates/dashboard/student/stats.php new file mode 100644 index 0000000000..6541f07819 --- /dev/null +++ b/templates/dashboard/student/stats.php @@ -0,0 +1,113 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use TUTOR\Course; +use Tutor\Models\CourseModel; +use TUTOR\Icon; + +$user_id = $user_id ?? get_current_user_id(); +$user_data = $user_data ?? get_userdata( $user_id ); + +// Query metrics and stats data. +$enrolled_course = CourseModel::get_enrolled_courses_by_user( $user_id, array( 'private', 'publish' ) ); +$completed_courses = CourseModel::get_completed_courses_by_user( $user_id, 0, -1, array( 'post_status' => array( 'private', 'publish' ) ) ); +$has_completed_courses = is_object( $completed_courses ) && $completed_courses->have_posts(); +$active_courses = CourseModel::get_active_courses_by_user( $user_id, 0, -1, array( 'post_status' => array( 'private', 'publish' ) ) ); + +$enrolled_course_count = $enrolled_course ? $enrolled_course->post_count : 0; +$completed_course_count = $has_completed_courses ? $completed_courses->post_count : 0; +$active_course_count = is_object( $active_courses ) && $active_courses->have_posts() ? $active_courses->post_count : 0; +$enrolled_courses_ids = $enrolled_course_count ? wp_list_pluck( $enrolled_course->posts, 'ID' ) : array(); + +// Time spent calculation. +$time_spent = Course::get_total_course_duration( $enrolled_courses_ids ); +$is_hour_format = $time_spent['hours'] > 0; +$has_time_spent = $is_hour_format || $time_spent['minutes'] > 0; +$time_spent_value = $is_hour_format ? $time_spent['hours'] : $time_spent['minutes']; + +$time_spent_unit = $is_hour_format + ? _x( 'h+', 'abbreviation for hours with plus sign', 'tutor' ) + : _x( 'm+', 'abbreviation for minutes with plus sign', 'tutor' ); + +$time_spent_unit_modal = $is_hour_format + ? _x( 'hours', 'time unit', 'tutor' ) + : _x( 'minutes', 'time unit', 'tutor' ); + +$time_spent_card_value = $has_time_spent ? sprintf( + /* translators: 1: total time spent 2: Unit. */ + __( '%1$d %2$s', 'tutor' ), + $time_spent_value, + $time_spent_unit +) : '0'; + +$time_spent_modal_value = sprintf( + /* translators: 1: total time spent 2: Unit. */ + __( '%1$d+ %2$s', 'tutor' ), + $time_spent_value, + $time_spent_unit_modal +); + +$cards = array( + array( + 'title' => __( 'Enrolled Courses', 'tutor' ), + 'icon' => Icon::COURSES, + 'value' => $enrolled_course_count, + 'url' => tutor_utils()->tutor_dashboard_url( 'courses' ), + 'class' => 'tutor-stat-card-enrolled', + ), + array( + 'title' => __( 'Active', 'tutor' ), + 'icon' => Icon::PLAY_LINE, + 'value' => $active_course_count, + 'url' => tutor_utils()->tutor_dashboard_url( 'courses/active-courses' ), + 'class' => 'tutor-stat-card-active', + ), + array( + 'title' => __( 'Completed', 'tutor' ), + 'icon' => Icon::COMPLETED_CIRCLE, + 'value' => $completed_course_count, + 'url' => tutor_utils()->tutor_dashboard_url( 'courses/completed-courses' ), + 'class' => 'tutor-stat-card-completed', + ), + array( + 'title' => __( 'Time Spent', 'tutor' ), + 'icon' => Icon::TIME, + 'value' => $time_spent_card_value, + 'class' => 'tutor-stat-card-time-spent', + 'modal_id' => $has_time_spent ? 'tutor-time-spent-modal' : '', + ), +); +?> + +
+
+ +
+ + + $user_data, + 'time_spent' => $time_spent, + 'time_spent_value' => $time_spent_modal_value, + ) + ); + ?> + +
diff --git a/templates/dashboard/student/time-spent-modal.php b/templates/dashboard/student/time-spent-modal.php new file mode 100644 index 0000000000..64e0963778 --- /dev/null +++ b/templates/dashboard/student/time-spent-modal.php @@ -0,0 +1,91 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use TUTOR\Icon; +use Tutor\Components\SvgIcon; +use Tutor\Helpers\UrlHelper; + +$minutes_value = (int) $time_spent['minutes']; +$seconds_value = (int) $time_spent['seconds']; + +$has_minutes = $minutes_value > 0; +$has_seconds = $seconds_value > 0; + +$minutes_html = '' . esc_html( $minutes_value ) . '+'; +$seconds_html = '' . esc_html( $seconds_value ) . '+'; + +if ( $has_minutes && $has_seconds ) { + $text = sprintf( + /* translators: 1: minutes, 2: seconds */ + __( 'That\'s %1$s minutes, and %2$s seconds! Incredible!', 'tutor' ), + $minutes_html, + $seconds_html + ); +} elseif ( $has_minutes ) { + $text = sprintf( + /* translators: 1: minutes */ + __( 'That\'s %1$s minutes! Incredible!', 'tutor' ), + $minutes_html + ); +} elseif ( $has_seconds ) { + $text = sprintf( + /* translators: 1: seconds */ + __( 'That\'s %1$s seconds! Incredible!', 'tutor' ), + $seconds_html + ); +} else { + $text = __( "That's 0 seconds! Incredible!", 'tutor' ); +} +?> +
+ +