diff --git a/assets/src/js/frontend/dashboard/pages/discussions.ts b/assets/src/js/frontend/dashboard/pages/discussions.ts index 25b1227fbb..c3e3901289 100644 --- a/assets/src/js/frontend/dashboard/pages/discussions.ts +++ b/assets/src/js/frontend/dashboard/pages/discussions.ts @@ -8,6 +8,12 @@ interface ReplyCommentPayload { comment_parent: number; comment: string; } + +interface DeleteCommentPayload { + comment_id: number; + is_reply?: boolean; +} + interface QnASingleActionPayload { question_id: number; qna_action: string; @@ -20,17 +26,41 @@ interface ReplyQnAPayload { answer: string; } +const FORM_ID_PREFIXES = { + COMMENT_EDIT: 'lesson-comment-edit-', + COMMENT_REPLY: 'lesson-comment-reply-form-', +}; + +const MODALS = { + COMMENT_DELETE: 'tutor-comment-delete-modal', + QNA_DELETE: 'tutor-qna-delete-modal', +}; + +const ELEMENT_IDS = { + COMMENT_TEXT_PREFIX: 'tutor-lesson-comment-text-', + REPLIES_LIST_CONTAINER: 'tutor-discussion-replies-list', +}; + +const URL_PARAMS = { + ID: 'id', + ORDER: 'order', +}; + /** * Discussions Page Component * Handles Q&A, Lesson comments related actions */ const discussionsPage = () => { const query = window.TutorCore.query; + const form = window.TutorCore.form; + const toast = window.TutorCore.toast; + const modal = window.TutorCore.modal; return { query, - deleteCommentMutation: null as MutationState | null, + deleteCommentMutation: null as MutationState | null, replyCommentMutation: null as MutationState | null, + editCommentMutation: null as MutationState | null, qnaSingleActionMutation: null as MutationState | null, deleteQnAMutation: null as MutationState | null, replyQnAMutation: null as MutationState | null, @@ -39,28 +69,70 @@ const discussionsPage = () => { isSolved: false, isImportant: false, isArchived: false, + editingId: null as number | null, + editingFormId: null as string | null, + loadingReplies: false, + repliesOrder: 'DESC', + $nextTick: undefined as ((callback: () => void) => void) | undefined, init() { + // Set initial state from URL + const url = new URL(window.location.href); + this.repliesOrder = url.searchParams.get(URL_PARAMS.ORDER) || 'DESC'; + // Lesson comment delete mutation. this.deleteCommentMutation = this.query.useMutation(this.deleteComment, { - onSuccess: () => { - const url = new URL(window.location.href); - url.searchParams.delete('id'); - window.location.href = url.toString(); + onSuccess: (_, payload) => { + if (payload.is_reply) { + toast.success(__('Reply deleted successfully', 'tutor')); + modal.closeModal(MODALS.COMMENT_DELETE); + this.reloadReplies(); + } else { + const url = new URL(window.location.href); + url.searchParams.delete(URL_PARAMS.ID); + window.location.href = url.toString(); + } }, onError: (error: Error) => { - window.TutorCore.toast.error(error.message || __('Failed to delete Comment', 'tutor')); + toast.error(error.message || __('Failed to delete Comment', 'tutor')); }, }); // Lesson comment reply mutation this.replyCommentMutation = this.query.useMutation(this.replyComment, { - onSuccess: () => { - window.TutorCore.toast.success(__('Reply saved successfully', 'tutor')); - window.location.reload(); + onSuccess: (_, payload) => { + toast.success(__('Reply saved successfully', 'tutor')); + this.reloadReplies(); + + const formId = `${FORM_ID_PREFIXES.COMMENT_REPLY}${payload.comment_parent}`; + if (form.hasForm(formId)) { + form.reset(formId); + } }, onError: (error: Error) => { - window.TutorCore.toast.error(error.message || __('Failed to save reply', 'tutor')); + toast.error(error.message || __('Failed to save reply', 'tutor')); + }, + }); + + // Lesson comment edit mutation. + this.editCommentMutation = this.query.useMutation(this.updateComment, { + onSuccess: (_, payload) => { + toast.success(__('Comment updated successfully.', 'tutor')); + + const element = document.getElementById(`${ELEMENT_IDS.COMMENT_TEXT_PREFIX}${payload.comment_id}`); + if (element) { + element.innerHTML = payload.comment; + } + + if (this.editingFormId && form.hasForm(this.editingFormId)) { + form.reset(this.editingFormId); + this.editingFormId = null; + } + + this.editingId = null; + }, + onError: (error: Error) => { + toast.error(error.message || __('Failed to update comment', 'tutor')); }, }); @@ -83,7 +155,7 @@ const discussionsPage = () => { ); }, onError: (error: Error) => { - window.TutorCore.toast.error(error.message || __('Action failed', 'tutor')); + toast.error(error.message || __('Action failed', 'tutor')); }, }); @@ -91,27 +163,61 @@ const discussionsPage = () => { this.deleteQnAMutation = this.query.useMutation(this.deleteQnA, { onSuccess: () => { const url = new URL(window.location.href); - url.searchParams.delete('id'); + url.searchParams.delete(URL_PARAMS.ID); window.location.href = url.toString(); }, onError: (error: Error) => { - window.TutorCore.toast.error(error.message || __('Failed to delete Q&A', 'tutor')); + toast.error(error.message || __('Failed to delete Q&A', 'tutor')); }, }); // Q&A reply mutation. this.replyQnAMutation = this.query.useMutation(this.replyQnA, { onSuccess: () => { - window.TutorCore.toast.success(__('Reply saved successfully', 'tutor')); + toast.success(__('Reply saved successfully', 'tutor')); window.location.reload(); }, onError: (error: Error) => { - window.TutorCore.toast.error(error.message || __('Failed to save reply', 'tutor')); + toast.error(error.message || __('Failed to save reply', 'tutor')); }, }); }, - deleteComment(payload: { comment_id: number }) { + async reloadReplies(order?: string) { + if (order) { + this.repliesOrder = order; + } + + const url = new URL(window.location.href); + const commentId = parseInt(url.searchParams.get(URL_PARAMS.ID) || '0'); + + if (!commentId) return; + + this.loadingReplies = true; + try { + const response = await wpAjaxInstance.post(endpoints.LOAD_DISCUSSION_REPLIES, { + comment_id: commentId, + order: this.repliesOrder, + }); + + const container = document.getElementById(ELEMENT_IDS.REPLIES_LIST_CONTAINER); + if (container && typeof response.data?.html === 'string') { + container.innerHTML = response.data.html; + + // Update URL without reload + const url = new URL(window.location.href); + url.searchParams.set(URL_PARAMS.ORDER, this.repliesOrder); + window.history.pushState({}, '', url.toString()); + } + } catch (error) { + // eslint-disable-next-line no-console + console.error('Failed to reload replies:', error); + } finally { + this.loadingReplies = false; + } + }, + + deleteComment(payload: DeleteCommentPayload) { return wpAjaxInstance.post(endpoints.DELETE_LESSON_COMMENT, payload); }, @@ -119,6 +225,10 @@ const discussionsPage = () => { return wpAjaxInstance.post(endpoints.REPLY_LESSON_COMMENT, payload); }, + updateComment(payload: { comment_id: number; comment: string }) { + return wpAjaxInstance.post(endpoints.UPDATE_LESSON_COMMENT, payload); + }, + qnaSingleAction(payload: QnASingleActionPayload) { return wpAjaxInstance.post(endpoints.QNA_SINGLE_ACTION, payload); }, @@ -146,11 +256,40 @@ const discussionsPage = () => { } }, + handleReplyComment(data: { comment: string }, commentId: number, courseId: number) { + return this.replyCommentMutation?.mutate({ + comment: data.comment, + comment_parent: commentId, + comment_post_ID: courseId, + }); + }, + + handleEditComment(data: { comment: string }, commentId: number) { + return this.editCommentMutation?.mutate({ + comment_id: commentId, + comment: data.comment, + }); + }, + handleKeydown(event: KeyboardEvent) { if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') { (event.target as HTMLFormElement).closest('form')?.requestSubmit(); } }, + + setEditing(id: number | null) { + this.editingId = id; + const formId = id ? `${FORM_ID_PREFIXES.COMMENT_EDIT}${id}` : null; + this.editingFormId = formId; + + if (id && formId) { + this.$nextTick?.(() => { + if (form.hasForm(formId)) { + form.setFocus(formId, 'comment'); + } + }); + } + }, }; }; diff --git a/assets/src/js/v3/shared/utils/endpoints.ts b/assets/src/js/v3/shared/utils/endpoints.ts index c32c9cf393..8333474b25 100644 --- a/assets/src/js/v3/shared/utils/endpoints.ts +++ b/assets/src/js/v3/shared/utils/endpoints.ts @@ -86,6 +86,7 @@ const endpoints = { UPDATE_LESSON_COMMENT: 'tutor_update_lesson_comment', DELETE_LESSON_COMMENT: 'tutor_delete_lesson_comment', REPLY_LESSON_COMMENT: 'tutor_reply_lesson_comment', + LOAD_COMMENT_REPLIES: 'tutor_load_comment_replies', // Q&A QNA_SINGLE_ACTION: 'tutor_qna_single_action', diff --git a/classes/Lesson.php b/classes/Lesson.php index 70598e3168..7d75b84223 100644 --- a/classes/Lesson.php +++ b/classes/Lesson.php @@ -112,6 +112,7 @@ public function __construct( $register_hooks = true ) { add_action( 'wp_ajax_tutor_update_lesson_comment', array( $this, 'ajax_update_lesson_comment' ) ); add_action( 'wp_ajax_tutor_reply_lesson_comment', array( $this, 'reply_lesson_comment' ) ); add_action( 'wp_ajax_tutor_load_lesson_comments', array( $this, 'load_lesson_comments' ) ); + add_action( 'wp_ajax_tutor_load_comment_replies', array( $this, 'load_comment_replies' ) ); // Add lesson title as nav item & render single content on the learning area. add_action( "tutor_learning_area_nav_item_{$this->post_type}", array( $this, 'render_nav_item' ), 10, 2 ); @@ -1092,4 +1093,38 @@ public function load_lesson_comments() { ) ); } + + /** + * Load comment replies for dashboard. + * + * @since 4.0.0 + * + * @return void + */ + public function load_comment_replies() { + tutor_utils()->check_nonce(); + + $comment_id = Input::post( 'comment_id', 0, Input::TYPE_INT ); + $replies_order = Input::post( 'order', 'DESC' ); + + if ( ! $comment_id ) { + $this->response_bad_request( __( 'Invalid comment ID', 'tutor' ) ); + } + + $user_id = get_current_user_id(); + $replies = self::get_comment_replies( $comment_id, $replies_order ); + + ob_start(); + tutor_load_template( + 'dashboard.discussions.comment-replies', + array( + 'replies' => $replies, + 'replies_order' => $replies_order, + 'user_id' => $user_id, + ) + ); + $html = ob_get_clean(); + + wp_send_json_success( array( 'html' => $html ) ); + } } diff --git a/templates/dashboard/discussions.php b/templates/dashboard/discussions.php index a6d179843f..f20745e8fa 100644 --- a/templates/dashboard/discussions.php +++ b/templates/dashboard/discussions.php @@ -45,7 +45,7 @@ if ( $discussion_id ) { $template = tutor()->path . 'templates/dashboard/discussions/qna-single.php'; if ( 'lesson-comments' === $current_tab ) { - $template = tutor()->path . 'templates/dashboard/discussions/lesson-comment-single.php'; + $template = tutor()->path . 'templates/dashboard/discussions/comment-single.php'; } require_once $template; } else { @@ -58,7 +58,7 @@ path . 'templates/dashboard/discussions/qna-list.php'; if ( 'lesson-comments' === $current_tab ) { - $template = tutor()->path . 'templates/dashboard/discussions/lesson-comment-list.php'; + $template = tutor()->path . 'templates/dashboard/discussions/comment-list.php'; } require_once $template; diff --git a/templates/dashboard/discussions/comment-card.php b/templates/dashboard/discussions/comment-card.php new file mode 100644 index 0000000000..16ea14bd8d --- /dev/null +++ b/templates/dashboard/discussions/comment-card.php @@ -0,0 +1,117 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use Tutor\Components\Constants\Size; +use TUTOR\Icon; +use Tutor\Components\Avatar; +use Tutor\Components\PreviewTrigger; +use Tutor\Helpers\UrlHelper; +use TUTOR\Lesson; + +$course = get_post( tutor_utils()->get_course_id_by( 'lesson', $lesson_comment->comment_post_ID ) ); +$last_reply = null; +$replies = Lesson::get_comments( + array( + 'parent' => $lesson_comment->comment_ID, + 'order' => 'DESC', + ) +); + +if ( ! empty( $replies ) ) { + $last_reply = $replies[0]; +} + +$single_url = UrlHelper::add_query_params( + $discussion_url, + array( + 'tab' => 'lesson-comments', + 'id' => $lesson_comment->comment_ID, + ) +); +?> +
+
+ user( $lesson_comment->user_id )->size( Size::SIZE_32 )->render(); ?> +
+
+
comment_author ); ?>
+
+ + id( $lesson_comment->comment_post_ID )->render(); ?> + + id( $course->ID )->render(); ?> +
+
+
comment_content ); ?>
+
+ + + +
+ render_svg_icon( Icon::COMMENTS, 20, 20 ); ?> + +
+ + +
+ user( $last_reply->user_id )->size( Size::SIZE_20 )->render(); ?> +
comment_date_gmt ) ) ) ); //phpcs:ignore ?>
+
+ +
comment_date_gmt ) ) ) ); //phpcs:ignore ?>
+ +
+
+
+ + + + user_id ) : ?> +
+ +
+
+ + +
+
+
+ +
+
+ + user_id ) : ?> +
+ 'lesson-comment-edit-' . (int) $lesson_comment->comment_ID, + 'default_value' => $lesson_comment->comment_content, + 'submit_handler' => '(data) => handleEditComment(data, ' . (int) $lesson_comment->comment_ID . ')', + 'cancel_handler' => 'reset(); editingId = null; focused = false', + 'is_pending' => 'editCommentMutation?.isPending', + 'placeholder' => __( 'Write your comment', 'tutor' ), + ) + ); + ?> +
+ +
diff --git a/templates/dashboard/discussions/comment-form.php b/templates/dashboard/discussions/comment-form.php new file mode 100644 index 0000000000..f18e2a183d --- /dev/null +++ b/templates/dashboard/discussions/comment-form.php @@ -0,0 +1,83 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use Tutor\Components\Button; +use Tutor\Components\Constants\InputType; +use Tutor\Components\Constants\Size; +use Tutor\Components\Constants\Variant; +use Tutor\Components\InputField; +use TUTOR\Icon; + +$label = $label ?? ''; +$submit_label = $submit_label ?? __( 'Update', 'tutor' ); +$form_class = $form_class ?? 'tutor-w-full'; +$default_value = $default_value ?? ''; +$is_pending = $is_pending ?? 'false'; +?> + +
+ type( InputType::TEXTAREA ) + ->name( 'comment' ) + ->placeholder( $placeholder ) + ->attr( 'x-bind', "register('comment', { required: '" . esc_js( __( 'Please enter a comment', 'tutor' ) ) . "' })" ) + ->attr( '@keydown', 'handleKeydown($event)' ) + ->attr( '@focus', 'focused = true' ); + + if ( $label ) { + $input->label( $label ); + } + + $input->render(); + ?> + +
+
+ render_svg_icon( Icon::COMMAND, 12, 12 ); ?> + + render_svg_icon( Icon::ENTER, 12, 12 ); ?> + +
+ +
+ label( __( 'Cancel', 'tutor' ) ) + ->variant( Variant::GHOST ) + ->size( Size::X_SMALL ) + ->attr( 'type', 'button' ) + ->attr( '@click', $cancel_handler ) + ->render(); + + Button::make() + ->label( $submit_label ) + ->variant( Variant::PRIMARY_SOFT ) + ->size( Size::X_SMALL ) + ->attr( 'type', 'submit' ) + ->attr( ':disabled', $is_pending ) + ->attr( ':class', "{ 'tutor-btn-loading': " . $is_pending . ' }' ) + ->render(); + ?> +
+
+
diff --git a/templates/dashboard/discussions/lesson-comment-list.php b/templates/dashboard/discussions/comment-list.php similarity index 98% rename from templates/dashboard/discussions/lesson-comment-list.php rename to templates/dashboard/discussions/comment-list.php index 6580c0b7c4..0fd2a365f8 100644 --- a/templates/dashboard/discussions/lesson-comment-list.php +++ b/templates/dashboard/discussions/comment-list.php @@ -74,7 +74,7 @@ $lesson_comment, 'discussion_url' => $discussion_url, diff --git a/templates/dashboard/discussions/comment-replies.php b/templates/dashboard/discussions/comment-replies.php new file mode 100644 index 0000000000..8e3752202f --- /dev/null +++ b/templates/dashboard/discussions/comment-replies.php @@ -0,0 +1,97 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use Tutor\Components\Avatar; +use Tutor\Components\Constants\Size; +use Tutor\Components\Sorting; +use TUTOR\Icon; + +?> + +
+
+ + () +
+ order( $replies_order ) + ->on_change( 'reloadReplies' ) + ->bind_active_order( 'repliesOrder' ) + ->render(); + ?> +
+ +
+ +
+
+ user( $reply->user_id )->size( Size::SIZE_40 )->render(); ?> +
+
+ + comment_author ); ?> + + + comment_date_gmt ) ) ) ); + ?> + +
+
+ comment_content ); ?> +
+
+ user_id ) : ?> +
+ +
+
+ + +
+
+
+ +
+ + user_id ) : ?> +
+ 'lesson-comment-edit-' . (int) $reply->comment_ID, + 'default_value' => $reply->comment_content, + 'submit_handler' => '(data) => handleEditComment(data, ' . (int) $reply->comment_ID . ')', + 'cancel_handler' => 'reset(); editingId = null; focused = false', + 'is_pending' => 'editCommentMutation?.isPending', + 'placeholder' => __( 'Write your comment', 'tutor' ), + ) + ); + ?> +
+ +
+ +
+ diff --git a/templates/dashboard/discussions/comment-single.php b/templates/dashboard/discussions/comment-single.php new file mode 100644 index 0000000000..1d9a6f9bd5 --- /dev/null +++ b/templates/dashboard/discussions/comment-single.php @@ -0,0 +1,153 @@ + + * @link https://themeum.com + * @since 4.0.0 + */ + +defined( 'ABSPATH' ) || exit; + +use Tutor\Components\Avatar; +use Tutor\Components\ConfirmationModal; +use Tutor\Components\Constants\Size; +use Tutor\Components\EmptyState; +use Tutor\Components\PreviewTrigger; +use Tutor\Helpers\UrlHelper; +use TUTOR\Icon; +use TUTOR\Input; +use TUTOR\Lesson; + +$lesson_comment = get_comment( $discussion_id ); +if ( ! $lesson_comment ) { + EmptyState::make()->render(); + return; +} + +$user_id = get_current_user_id(); + +$replies_order = Input::get( 'order', 'DESC' ); +$replies = Lesson::get_comment_replies( $discussion_id, $replies_order ); + +$course = get_post( tutor_utils()->get_course_id_by( 'lesson', $lesson_comment->comment_post_ID ) ); + +?> +
+ +
+
+ user( $lesson_comment->user_id )->size( Size::SIZE_40 )->render(); ?> +
+
+ comment_author ); ?> + + comment_date_gmt ) ) ) ); + ?> + +
+
+ + id( $lesson_comment->comment_post_ID )->render(); ?> + + id( $course->ID )->render(); ?> +
+
+
+ user_id ) : ?> +
+ +
+
+ + +
+
+
+ +
+
+ +
+
+ comment_content ); ?> +
+
+ + user_id ) : ?> +
+ 'lesson-comment-edit-' . (int) $lesson_comment->comment_ID, + 'default_value' => $lesson_comment->comment_content, + 'submit_handler' => '(data) => handleEditComment(data, ' . (int) $lesson_comment->comment_ID . ')', + 'cancel_handler' => 'reset(); editingId = null; focused = false', + 'is_pending' => 'editCommentMutation?.isPending', + 'placeholder' => __( 'Write your comment', 'tutor' ), + ) + ); + ?> +
+ +
+ 'lesson-comment-reply-form-' . $lesson_comment->comment_ID, + 'submit_handler' => '(data) => handleReplyComment(data, ' . (int) $lesson_comment->comment_ID . ', ' . (int) $course->ID . ')', + 'cancel_handler' => 'reset(); focused = false', + 'is_pending' => 'replyCommentMutation?.isPending', + 'placeholder' => __( 'Just drop your response here!', 'tutor' ), + 'label' => __( 'Reply', 'tutor' ), + 'submit_label' => __( 'Save', 'tutor' ), + 'form_class' => 'tutor-discussion-single-reply-form tutor-p-6', + ) + ); + ?> +
+ $replies, + 'replies_order' => $replies_order, + 'user_id' => $user_id, + ) + ); + ?> +
+ + id( 'tutor-comment-delete-modal' ) + ->title( __( 'Delete This Comment?', 'tutor' ) ) + ->message( __( 'Are you sure you want to delete this comment permanently? Please confirm your choice.', 'tutor' ) ) + ->confirm_text( __( 'Yes, Delete This', 'tutor' ) ) + ->confirm_handler( 'deleteCommentMutation?.mutate({ comment_id: payload?.commentId, is_reply: payload?.isReply })' ) + ->mutation_state( 'deleteCommentMutation' ) + ->render(); + ?> +
diff --git a/templates/dashboard/discussions/lesson-comment-card.php b/templates/dashboard/discussions/lesson-comment-card.php deleted file mode 100644 index 05adda6a96..0000000000 --- a/templates/dashboard/discussions/lesson-comment-card.php +++ /dev/null @@ -1,84 +0,0 @@ - - * @link https://themeum.com - * @since 4.0.0 - */ - -defined( 'ABSPATH' ) || exit; - -use Tutor\Components\Constants\Size; -use TUTOR\Icon; -use Tutor\Components\Avatar; -use Tutor\Components\PreviewTrigger; -use Tutor\Helpers\UrlHelper; -use TUTOR\Lesson; - -// Comment read-unread feature does not exist currently, will be added in future. -$is_unread = 0; -$course = get_post( tutor_utils()->get_course_id_by( 'lesson', $lesson_comment->comment_post_ID ) ); -$last_reply = null; -$replies = Lesson::get_comments( - array( - 'parent' => $lesson_comment->comment_ID, - 'order' => 'DESC', - ) -); - -if ( ! empty( $replies ) ) { - $last_reply = $replies[0]; -} - -$single_url = UrlHelper::add_query_params( - $discussion_url, - array( - 'tab' => 'lesson-comments', - 'id' => $lesson_comment->comment_ID, - ) -); -?> -
- user( $lesson_comment->user_id )->size( Size::SIZE_32 )->render(); ?> -
-
-
comment_author ); ?>
-
- - id( $lesson_comment->comment_post_ID )->render(); ?> - - id( $course->ID )->render(); ?> -
-
-
comment_content ); ?>
-
- -
- render_svg_icon( Icon::COMMENTS, 20, 20 ); ?> - -
- - -
- user( $last_reply->user_id )->size( Size::SIZE_20 )->render(); ?> -
comment_date_gmt ) ) ) ); //phpcs:ignore ?>
-
- -
comment_date_gmt ) ) ) ); //phpcs:ignore ?>
- -
-
-
- - - - -
-
diff --git a/templates/dashboard/discussions/lesson-comment-single.php b/templates/dashboard/discussions/lesson-comment-single.php deleted file mode 100644 index d3c7bce200..0000000000 --- a/templates/dashboard/discussions/lesson-comment-single.php +++ /dev/null @@ -1,177 +0,0 @@ - - * @link https://themeum.com - * @since 4.0.0 - */ - -defined( 'ABSPATH' ) || exit; - -use Tutor\Components\Avatar; -use Tutor\Components\Button; -use Tutor\Components\ConfirmationModal; -use Tutor\Components\Constants\InputType; -use Tutor\Components\Constants\Size; -use Tutor\Components\Constants\Variant; -use Tutor\Components\EmptyState; -use Tutor\Components\InputField; -use Tutor\Components\PreviewTrigger; -use Tutor\Components\Sorting; -use Tutor\Helpers\UrlHelper; -use TUTOR\Icon; -use TUTOR\Input; -use TUTOR\Lesson; - -$lesson_comment = get_comment( $discussion_id ); -if ( ! $lesson_comment ) { - EmptyState::make()->render(); - return; -} - -$replies_order = Input::get( 'order', 'DESC' ); -$replies = Lesson::get_comment_replies( $discussion_id, $replies_order ); - -$course = get_post( tutor_utils()->get_course_id_by( 'lesson', $lesson_comment->comment_post_ID ) ); - -?> -
- -
-
- user( $lesson_comment->user_id )->size( Size::SIZE_40 )->render(); ?> -
-
- comment_author ); ?> - - comment_date_gmt ) ) ) ); - ?> - -
-
- - id( $lesson_comment->comment_post_ID )->render(); ?> - - id( $course->ID )->render(); ?> -
-
-
- -
-
-
- comment_content ); ?> -
-
- comment_ID; ?> -
- type( InputType::TEXTAREA ) - ->name( 'comment' ) - ->label( __( 'Reply', 'tutor' ) ) - ->placeholder( __( 'Just drop your response here!', 'tutor' ) ) - ->attr( 'x-bind', "register('comment', { required: '" . esc_js( __( 'Please enter a response', 'tutor' ) ) . "' })" ) - ->attr( '@focus', 'focused = true' ) - ->attr( '@keydown', 'handleKeydown($event)' ) - ->render(); - ?> - -
-
- render_svg_icon( Icon::COMMAND, 12, 12 ); ?> - - render_svg_icon( Icon::ENTER, 12, 12 ); ?> - -
-
- label( __( 'Cancel', 'tutor' ) ) - ->variant( Variant::GHOST ) - ->size( Size::X_SMALL ) - ->attr( 'type', 'button' ) - ->attr( '@click', 'reset(); focused = false' ) - ->attr( ':disabled', 'replyCommentMutation?.isPending' ) - ->render(); - - Button::make() - ->label( __( 'Save', 'tutor' ) ) - ->variant( Variant::PRIMARY_SOFT ) - ->size( Size::X_SMALL ) - ->attr( 'type', 'submit' ) - ->attr( ':disabled', 'replyCommentMutation?.isPending' ) - ->attr( ':class', "{ 'tutor-btn-loading': replyCommentMutation?.isPending }" ) - ->render(); - ?> -
-
-
-
-
- - () -
- order( $replies_order )->render(); ?> -
- -
- -
- user( $reply->user_id )->size( Size::SIZE_40 )->render(); ?> -
-
- - comment_author ); ?> - - - comment_date_gmt ) ) ) ); - ?> - -
-
- comment_content ); ?> -
-
-
- -
- - - id( 'tutor-comment-delete-modal' ) - ->title( __( 'Delete This Comment?', 'tutor' ) ) - ->message( __( 'Are you sure you want to delete this comment permanently? Please confirm your choice.', 'tutor' ) ) - ->confirm_text( __( 'Yes, Delete This', 'tutor' ) ) - ->confirm_handler( 'deleteCommentMutation?.mutate({ comment_id: payload?.commentId })' ) - ->mutation_state( 'deleteCommentMutation' ) - ->render(); - ?> -
-