feat: add content feed with AJAX filtering and load more on front page

This commit is contained in:
2026-04-03 01:13:09 +05:00
parent 82105c6f09
commit 8f1f001085
7 changed files with 484 additions and 1 deletions
@@ -0,0 +1,78 @@
<?php
/**
* БИТ.WMS Child Theme — inc/ajax-filter.php
*
* AJAX handler for the content feed filter bar and "Load more" button.
* Registered for both logged-in and non-logged-in users.
*
* @package bitwms-child
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_action( 'wp_ajax_bitwms_filter', 'bitwms_ajax_filter_handler' );
add_action( 'wp_ajax_nopriv_bitwms_filter', 'bitwms_ajax_filter_handler' );
/**
* Handle the AJAX filter/load-more request.
*
* Expected POST parameters:
* - post_type (string) — 'all' or one of: post, case, webinar, course, event, material
* - page (int) — page number (1-based)
* - nonce (string) — security nonce
*
* Returns JSON: { success: true, data: { html: "...", has_more: bool } }
*/
function bitwms_ajax_filter_handler() {
// Verify nonce.
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'bitwms_filter_nonce' ) ) {
wp_send_json_error( array( 'message' => 'Security check failed.' ), 403 );
}
$valid_types = array( 'post', 'case', 'webinar', 'course', 'event', 'material' );
$all_post_types = $valid_types;
$raw_type = isset( $_POST['post_type'] ) ? sanitize_key( $_POST['post_type'] ) : 'all';
$page = isset( $_POST['page'] ) ? max( 1, (int) $_POST['page'] ) : 1;
if ( 'all' === $raw_type ) {
$post_type = $all_post_types;
} elseif ( in_array( $raw_type, $valid_types, true ) ) {
$post_type = array( $raw_type );
} else {
$post_type = $all_post_types;
}
$posts_per_page = 6;
$query = new WP_Query( array(
'post_type' => $post_type,
'posts_per_page' => $posts_per_page,
'paged' => $page,
'orderby' => 'date',
'order' => 'DESC',
'post_status' => 'publish',
) );
$html = '';
$has_more = false;
if ( $query->have_posts() ) {
ob_start();
while ( $query->have_posts() ) {
$query->the_post();
get_template_part( 'templates/content-card' );
}
$html = ob_get_clean();
wp_reset_postdata();
$has_more = ( $page * $posts_per_page ) < $query->found_posts;
}
wp_send_json_success( array(
'html' => $html,
'has_more' => $has_more,
) );
}
+21 -1
View File
@@ -16,13 +16,33 @@ add_action( 'wp_enqueue_scripts', 'bitwms_enqueue_scripts', 20 );
function bitwms_enqueue_scripts() {
$theme_version = wp_get_theme()->get( 'Version' );
$theme_uri = get_stylesheet_directory_uri();
// Sidebar navigation — loaded in footer (5th arg: true).
wp_enqueue_script(
'bitwms-sidebar-nav',
get_stylesheet_directory_uri() . '/js/sidebar-nav.js',
$theme_uri . '/js/sidebar-nav.js',
array(), // no dependencies
$theme_version,
true // load in footer
);
// Content feed AJAX filter — front page only.
if ( is_front_page() ) {
wp_enqueue_script(
'bitwms-ajax-filter',
$theme_uri . '/js/ajax-filter.js',
array(),
$theme_version,
true
);
wp_localize_script(
'bitwms-ajax-filter',
'bitwmsAjax',
array(
'url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'bitwms_filter_nonce' ),
)
);
}
}