104 lines
4.3 KiB
PHP
104 lines
4.3 KiB
PHP
<?php
|
||
/**
|
||
* Shop / category archive — XShop filters + AJAX grid + no-JS fallback.
|
||
*
|
||
* Integrates product-filters sidebar (desktop) + drawer (mobile) + toolbar.
|
||
* Server render uses Woo hooks + ProductQuery via pre_get_posts (inc/woocommerce/setup.php) for no-JS.
|
||
* JS enhances via REST /xshop/v1/products.
|
||
*
|
||
* WC version tested: 11.1.0
|
||
* Template version: 3.4.0
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
get_header('shop');
|
||
|
||
do_action('woocommerce_before_main_content');
|
||
|
||
if (is_product_category() || is_product_tag() || is_tax('product_brand')) {
|
||
$term = get_queried_object();
|
||
if ($term instanceof WP_Term) {
|
||
echo '<header class="xshop-page-header">';
|
||
echo '<h1 class="xshop-page-header__title">' . esc_html($term->name) . '</h1>';
|
||
if (!empty($term->description)) {
|
||
echo '<div class="xshop-page-header__desc">' . wp_kses_post(wpautop($term->description)) . '</div>';
|
||
}
|
||
echo '<p class="xshop-text-muted" style="font-size:var(--xshop-text-sm)">' . esc_html(sprintf(esc_html__('%s products', 'xshop'), number_format_i18n((int) $term->count))) . '</p>';
|
||
echo '</header>';
|
||
}
|
||
} elseif (is_shop()) {
|
||
$shopId = wc_get_page_id('shop');
|
||
$title = $shopId ? get_the_title($shopId) : esc_html__('Shop', 'xshop');
|
||
echo '<header class="xshop-page-header"><h1 class="xshop-page-header__title">' . esc_html($title) . '</h1></header>';
|
||
}
|
||
?>
|
||
|
||
<div class="xshop-shop" data-xshop-shop>
|
||
<!-- Mobile filter toggle -->
|
||
<button type="button" class="xshop-btn xshop-btn--secondary xshop-shop__filter-toggle" data-xshop-drawer-toggle aria-expanded="false" aria-controls="xshop-filter-drawer">
|
||
<?php esc_html_e('Filters', 'xshop'); ?>
|
||
</button>
|
||
|
||
<div class="xshop-shop__layout">
|
||
<!-- Desktop sidebar -->
|
||
<aside class="xshop-shop__sidebar" aria-label="<?php esc_attr_e('Filters', 'xshop'); ?>">
|
||
<?php get_template_part('template-parts/components/product-filters'); ?>
|
||
</aside>
|
||
|
||
<!-- Mobile drawer -->
|
||
<div class="xshop-drawer" id="xshop-filter-drawer" hidden data-xshop-drawer role="dialog" aria-modal="true" aria-label="<?php esc_attr_e('Filters', 'xshop'); ?>">
|
||
<div class="xshop-drawer__header">
|
||
<h2 class="xshop-drawer__title"><?php esc_html_e('Filters', 'xshop'); ?></h2>
|
||
<button type="button" class="xshop-btn xshop-btn--ghost" data-xshop-drawer-close aria-label="<?php esc_attr_e('Close filters', 'xshop'); ?>">×</button>
|
||
</div>
|
||
<div class="xshop-drawer__body">
|
||
<?php get_template_part('template-parts/components/product-filters'); ?>
|
||
</div>
|
||
</div>
|
||
<div class="xshop-drawer__overlay" hidden data-xshop-drawer-overlay></div>
|
||
|
||
<!-- Main -->
|
||
<div class="xshop-shop__main" data-xshop-shop-main>
|
||
<div class="xshop-shop__toolbar" data-xshop-toolbar>
|
||
<?php do_action('woocommerce_before_shop_loop'); ?>
|
||
</div>
|
||
|
||
<div class="xshop-search__loading" hidden data-xshop-loading style="display:none">
|
||
<span class="xshop-loading__spinner" aria-hidden="true"></span> <?php esc_html_e('Loading…', 'xshop'); ?>
|
||
</div>
|
||
<div class="xshop-search__error" hidden data-xshop-error role="alert"></div>
|
||
|
||
<div data-xshop-products-container>
|
||
<?php
|
||
if (woocommerce_product_loop()) {
|
||
woocommerce_product_loop_start();
|
||
while (have_posts()) { the_post(); do_action('woocommerce_shop_loop'); wc_get_template_part('content', 'product'); }
|
||
woocommerce_product_loop_end();
|
||
do_action('woocommerce_after_shop_loop');
|
||
} else {
|
||
do_action('woocommerce_no_products_found');
|
||
get_template_part('template-parts/components/empty-state', null, [
|
||
'title' => esc_html__('No products found', 'xshop'),
|
||
'text' => esc_html__('Try adjusting your filters or browse all products.', 'xshop'),
|
||
'cta_label' => esc_html__('Browse shop', 'xshop'),
|
||
'cta_url' => wc_get_page_permalink('shop'),
|
||
]);
|
||
}
|
||
?>
|
||
</div>
|
||
|
||
<div data-xshop-pagination>
|
||
<?php
|
||
// Woo pagination rendered via woocommerce_after_shop_loop already inside loop; for AJAX we render custom via JS
|
||
// Ensure result count is accessible
|
||
?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php
|
||
do_action('woocommerce_after_main_content');
|
||
get_footer('shop');
|