Skip to content

Commit ed24310

Browse files
committed
Infinite scroll added to lesson comments
1 parent deedb48 commit ed24310

File tree

7 files changed

+402
-200
lines changed

7 files changed

+402
-200
lines changed

assets/src/js/frontend/learning-area/lesson/comments.ts

Lines changed: 80 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type MutationState } from '@Core/ts/services/Query';
22
import { wpAjaxInstance } from '@TutorShared/utils/api';
33
import endpoints from '@TutorShared/utils/endpoints';
4+
import { convertToErrorMessage } from '@TutorShared/utils/util';
45
import { __ } from '@wordpress/i18n';
56

67
interface ReplyCommentPayload {
@@ -12,26 +13,45 @@ interface ReplyCommentPayload {
1213
/**
1314
* Lesson Comments Component
1415
*/
15-
const lessonComments = () => {
16+
const lessonComments = (lessonId?: number) => {
1617
const query = window.TutorCore.query;
1718

1819
return {
1920
query,
21+
lessonId: lessonId || null,
22+
currentPage: 1,
23+
loading: false,
24+
hasMore: true,
25+
$el: null as unknown as HTMLElement,
26+
$refs: {} as {
27+
commentList: HTMLElement;
28+
commentItems: HTMLElement;
29+
loadMoreTrigger: HTMLElement;
30+
},
2031
createCommentMutation: null as MutationState<unknown, unknown> | null,
2132
deleteCommentMutation: null as MutationState<unknown, unknown> | null,
2233
replyCommentMutation: null as MutationState<unknown, ReplyCommentPayload> | null,
2334

2435
init() {
36+
this.initInfiniteScroll();
37+
2538
// Lesson comment create mutation.
2639
this.createCommentMutation = this.query.useMutation(this.createComment, {
27-
onSuccess: () => {
40+
onSuccess: (response) => {
2841
window.TutorCore.toast.success(__('Comment added successfully.', 'tutor'));
29-
// const url = new URL(window.location.href);
30-
// url.searchParams.delete('id');
31-
// window.location.href = url.toString();
42+
this.$refs.commentList.innerHTML = response.data.html;
43+
44+
// Reset pagination state when new comment is added
45+
this.currentPage = 1;
46+
this.hasMore = true;
47+
48+
const formId = 'lesson-comment-form';
49+
if (window.TutorCore.form.hasForm(formId)) {
50+
window.TutorCore.form.reset(formId);
51+
}
3252
},
33-
onError: (error: Error) => {
34-
window.TutorCore.toast.error(error.message || __('Failed to delete Comment', 'tutor'));
53+
onError: (error) => {
54+
window.TutorCore.toast.error(convertToErrorMessage(error));
3555
},
3656
});
3757

@@ -42,19 +62,23 @@ const lessonComments = () => {
4262
url.searchParams.delete('id');
4363
window.location.href = url.toString();
4464
},
45-
onError: (error: Error) => {
46-
window.TutorCore.toast.error(error.message || __('Failed to delete Comment', 'tutor'));
65+
onError: (error) => {
66+
window.TutorCore.toast.error(convertToErrorMessage(error));
4767
},
4868
});
4969

5070
// Lesson comment reply mutation
5171
this.replyCommentMutation = this.query.useMutation(this.replyComment, {
52-
onSuccess: () => {
72+
onSuccess: (response) => {
5373
window.TutorCore.toast.success(__('Reply saved successfully', 'tutor'));
54-
window.location.reload();
74+
this.$refs.commentList.innerHTML = response.data.html;
75+
76+
// Reset pagination state when reply is added
77+
this.currentPage = 1;
78+
this.hasMore = true;
5579
},
56-
onError: (error: Error) => {
57-
window.TutorCore.toast.error(error.message || __('Failed to save reply', 'tutor'));
80+
onError: (error) => {
81+
window.TutorCore.toast.error(convertToErrorMessage(error));
5882
},
5983
});
6084
},
@@ -71,11 +95,54 @@ const lessonComments = () => {
7195
return wpAjaxInstance.post(endpoints.REPLY_LESSON_COMMENT, payload);
7296
},
7397

98+
loadNextPage() {
99+
if (!this.lessonId || this.loading || !this.hasMore) {
100+
return;
101+
}
102+
103+
this.loading = true;
104+
105+
wpAjaxInstance
106+
.post(endpoints.LOAD_LESSON_COMMENTS, {
107+
lesson_id: this.lessonId,
108+
current_page: this.currentPage + 1,
109+
})
110+
.then((response) => {
111+
if (response.data.has_more !== undefined) {
112+
this.hasMore = response.data.has_more;
113+
}
114+
115+
if (response.data.html?.trim()) {
116+
this.currentPage++;
117+
this.$refs.commentItems.insertAdjacentHTML('beforeend', response.data.html);
118+
}
119+
})
120+
.catch((error) => {
121+
window.TutorCore.toast.error(convertToErrorMessage(error));
122+
})
123+
.finally(() => {
124+
this.loading = false;
125+
});
126+
},
127+
74128
handleKeydown(event: KeyboardEvent) {
75129
if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
76130
(event.target as HTMLFormElement).closest('form')?.requestSubmit();
77131
}
78132
},
133+
134+
initInfiniteScroll() {
135+
const observer = new IntersectionObserver(
136+
([entry]) => {
137+
if (entry.isIntersecting && this.hasMore && !this.loading) {
138+
this.loadNextPage();
139+
}
140+
},
141+
{ rootMargin: '200px' },
142+
);
143+
144+
observer.observe(this.$refs.loadMoreTrigger);
145+
},
79146
};
80147
};
81148

assets/src/js/v3/shared/utils/endpoints.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ const endpoints = {
8181
// LESSON
8282
GET_LESSON_DETAILS: 'tutor_lesson_details',
8383
SAVE_LESSON: 'tutor_save_lesson',
84+
LOAD_LESSON_COMMENTS: 'tutor_load_lesson_comments',
8485
CREATE_LESSON_COMMENT: 'tutor_create_lesson_comment',
8586
DELETE_LESSON_COMMENT: 'tutor_delete_lesson_comment',
8687
REPLY_LESSON_COMMENT: 'tutor_reply_lesson_comment',

classes/Lesson.php

Lines changed: 85 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public function __construct( $register_hooks = true ) {
9999
add_action( 'wp_ajax_tutor_create_lesson_comment', array( $this, 'tutor_single_course_lesson_load_more' ) );
100100
add_action( 'wp_ajax_tutor_delete_lesson_comment', array( $this, 'ajax_delete_lesson_comment' ) );
101101
add_action( 'wp_ajax_tutor_reply_lesson_comment', array( $this, 'reply_lesson_comment' ) );
102+
add_action( 'wp_ajax_tutor_load_lesson_comments', array( $this, 'load_lesson_comments' ) );
102103

103104
// Add lesson title as nav item & render single content on the learning area.
104105
add_action( "tutor_learning_area_nav_item_{$this->post_type}", array( $this, 'render_nav_item' ), 10, 2 );
@@ -123,8 +124,11 @@ public function tutor_single_course_lesson_load_more() {
123124
self::create_comment( $comment_data );
124125
do_action( 'tutor_new_comment_added', $comment_data );
125126
}
127+
128+
$is_legacy_learning_mode = tutor_utils()->get_option( 'is_legacy_learning_mode' );
129+
126130
ob_start();
127-
tutor_load_template( 'single.lesson.comment' );
131+
tutor_load_template( $is_legacy_learning_mode ? 'single.lesson.comment' : 'learning-area.lesson.comment-list' );
128132
$html = ob_get_clean();
129133
wp_send_json_success( array( 'html' => $html ) );
130134
}
@@ -588,31 +592,39 @@ public function reply_lesson_comment() {
588592
$reply = get_comment( $comment_id );
589593
do_action( 'tutor_reply_lesson_comment_thread', $comment_id, $comment_data );
590594

591-
ob_start();
592-
?>
593-
<div class="tutor-comments-list tutor-child-comment tutor-mt-32" id="lesson-comment-<?php echo esc_attr( $reply->comment_ID ); ?>">
594-
<div class="comment-avatar">
595-
<img src="<?php echo esc_url( get_avatar_url( $reply->user_id ) ); ?>" alt="">
596-
</div>
597-
<div class="tutor-single-comment">
598-
<div class="tutor-actual-comment tutor-mb-12">
599-
<div class="tutor-comment-author">
600-
<span class="tutor-fs-6 tutor-fw-bold">
601-
<?php echo esc_html( $reply->comment_author ); ?>
602-
</span>
603-
<span class="tutor-fs-7 tutor-ml-0 tutor-ml-sm-10">
604-
<?php echo esc_html( human_time_diff( strtotime( $reply->comment_date ), tutor_time() ) . __( ' ago', 'tutor' ) ); ?>
605-
</span>
606-
</div>
607-
<div class="tutor-comment-text tutor-fs-6 tutor-mt-4">
608-
<?php echo esc_html( $reply->comment_content ); ?>
595+
$is_legacy_learning_mode = tutor_utils()->get_option( 'is_legacy_learning_mode' );
596+
if ( $is_legacy_learning_mode ) {
597+
ob_start();
598+
?>
599+
<div class="tutor-comments-list tutor-child-comment tutor-mt-32" id="lesson-comment-<?php echo esc_attr( $reply->comment_ID ); ?>">
600+
<div class="comment-avatar">
601+
<img src="<?php echo esc_url( get_avatar_url( $reply->user_id ) ); ?>" alt="">
602+
</div>
603+
<div class="tutor-single-comment">
604+
<div class="tutor-actual-comment tutor-mb-12">
605+
<div class="tutor-comment-author">
606+
<span class="tutor-fs-6 tutor-fw-bold">
607+
<?php echo esc_html( $reply->comment_author ); ?>
608+
</span>
609+
<span class="tutor-fs-7 tutor-ml-0 tutor-ml-sm-10">
610+
<?php echo esc_html( human_time_diff( strtotime( $reply->comment_date ), tutor_time() ) . __( ' ago', 'tutor' ) ); ?>
611+
</span>
612+
</div>
613+
<div class="tutor-comment-text tutor-fs-6 tutor-mt-4">
614+
<?php echo esc_html( $reply->comment_content ); ?>
615+
</div>
609616
</div>
610617
</div>
611618
</div>
612-
</div>
613-
<?php
614-
$html = ob_get_clean();
615-
wp_send_json_success( array( 'html' => $html ) );
619+
<?php
620+
$html = ob_get_clean();
621+
wp_send_json_success( array( 'html' => $html ) );
622+
} else {
623+
ob_start();
624+
tutor_load_template( 'learning-area.lesson.comment-list' );
625+
$html = ob_get_clean();
626+
wp_send_json_success( array( 'html' => $html ) );
627+
}
616628
}
617629

618630
/**
@@ -835,4 +847,54 @@ public function render_single_content( $lesson ): void {
835847
)
836848
);
837849
}
850+
851+
/**
852+
* Load lesson comments
853+
*
854+
* @since 4.0.0
855+
*
856+
* @return void
857+
*/
858+
public function load_lesson_comments() {
859+
$lesson_id = Input::post( 'lesson_id' ?? 0 );
860+
$current_page = Input::post( 'current_page', '1' );
861+
862+
$item_per_page = tutor_utils()->get_option( 'pagination_per_page', 10 );
863+
864+
$comment_list = self::get_comments(
865+
array(
866+
'post_id' => $lesson_id,
867+
'parent' => 0,
868+
'paged' => $current_page,
869+
'number' => $item_per_page,
870+
)
871+
);
872+
873+
// Get total comment count to determine if there are more pages.
874+
$total_comments = self::get_comments(
875+
array(
876+
'post_id' => $lesson_id,
877+
'parent' => 0,
878+
'count' => true,
879+
)
880+
);
881+
882+
ob_start();
883+
tutor_load_template(
884+
'learning-area.lesson.comment-items',
885+
compact( 'comment_list', 'lesson_id' )
886+
);
887+
$html = ob_get_clean();
888+
889+
// Calculate if there are more items beyond current page.
890+
$items_loaded = $current_page * $item_per_page;
891+
$has_more = $items_loaded < $total_comments;
892+
893+
wp_send_json_success(
894+
array(
895+
'html' => $html,
896+
'has_more' => $has_more,
897+
)
898+
);
899+
}
838900
}

0 commit comments

Comments
 (0)