Files
mataba/shop/xshop-theme/template-parts/components/product-card.php
T

124 lines
4.6 KiB
PHP

<?php
/**
* XShop Product Card — reusable for shop/category/home/related/upsells/search.
*
* Expects: $args['product'] = WC_Product|int (ID)
* Optional: $args['show_hooks'] bool (wishlist/compare placeholders)
*
* @package XShop
*/
declare(strict_types=1);
defined('ABSPATH') || exit;
$product = $args['product'] ?? null;
if (is_int($product)) {
$product = wc_get_product($product);
}
if (!$product instanceof WC_Product) {
global $product;
if (!isset($product) || !$product instanceof WC_Product) {
return;
}
}
$pid = $product->get_id();
$title = $product->get_name();
if ($title === '') {
$title = esc_html__('Untitled', 'xshop');
}
$permalink = get_permalink($pid);
$priceHtml = $product->get_price_html();
$rating = $product->get_average_rating();
$count = $product->get_rating_count();
$stock = $product->get_stock_status();
$isOnSale = $product->is_on_sale();
$featured = $product->is_featured();
$type = $product->get_type();
$showHooks = !empty($args['show_hooks']);
?>
<article <?php wc_product_class('xshop-product-card', $product); ?>>
<a href="<?php echo esc_url($permalink); ?>" class="xshop-product-card__media" aria-label="<?php echo esc_attr($title); ?>">
<?php
$imageId = $product->get_image_id();
if ($imageId) {
echo wp_get_attachment_image($imageId, 'xshop-card', false, ['loading' => 'lazy', 'decoding' => 'async', 'alt' => esc_attr($title)]);
} elseif (has_post_thumbnail($pid)) {
echo get_the_post_thumbnail($pid, 'xshop-card', ['loading' => 'lazy', 'decoding' => 'async', 'alt' => esc_attr($title)]);
} else {
echo '<span class="xshop-card__media--placeholder" style="display:flex;inline-size:100%;block-size:100%;align-items:center;justify-content:center;">' . esc_html__('No image', 'xshop') . '</span>';
}
?>
<span class="xshop-product-card__badges" aria-hidden="true">
<?php if ($isOnSale): ?>
<span class="xshop-badge xshop-badge--sale">
<?php
if ($product->is_type('variable')) {
esc_html_e('Sale', 'xshop');
} else {
$regular = (float) $product->get_regular_price();
$sale = (float) $product->get_sale_price();
if ($regular > 0 && $sale > 0) {
$pct = (int) round(100 - ($sale / $regular * 100));
echo esc_html(sprintf('-%d%%', $pct));
} else {
esc_html_e('Sale', 'xshop');
}
}
?>
</span>
<?php endif; ?>
<?php if ($stock === 'outofstock'): ?>
<span class="xshop-badge xshop-badge--outofstock"><?php esc_html_e('Out of stock', 'xshop'); ?></span>
<?php endif; ?>
<?php if ($featured): ?>
<span class="xshop-badge xshop-badge--featured"><?php esc_html_e('Featured', 'xshop'); ?></span>
<?php endif; ?>
</span>
</a>
<div class="xshop-product-card__body">
<h3 class="xshop-product-card__title">
<a href="<?php echo esc_url($permalink); ?>"><?php echo esc_html($title); ?></a>
</h3>
<?php if ($priceHtml !== ''): ?>
<div class="xshop-product-card__price"><?php echo wp_kses_post($priceHtml); ?></div>
<?php endif; ?>
<div class="xshop-product-card__meta">
<?php if ($rating > 0): ?>
<span class="xshop-product-card__rating" aria-label="<?php echo esc_attr(sprintf(esc_html__('Rated %s out of 5', 'xshop'), $rating)); ?>">
<?php
$stars = str_repeat('★', (int) round($rating)) . str_repeat('☆', 5 - (int) round($rating));
echo esc_html($stars) . ' <span style="color:var(--xshop-muted)">(' . esc_html((string) $count) . ')</span>';
?>
</span>
<?php endif; ?>
<?php if ($type === 'variable'): ?>
<span><?php esc_html_e('Variable', 'xshop'); ?></span>
<?php endif; ?>
<?php if ($stock === 'outofstock'): ?>
<span><?php esc_html_e('Out of stock', 'xshop'); ?></span>
<?php endif; ?>
</div>
<div class="xshop-product-card__actions">
<?php
// Use Woo's add-to-cart template (handles simple/variable correctly)
woocommerce_template_loop_add_to_cart();
?>
<?php if ($showHooks): ?>
<span class="xshop-product-card__hook" aria-hidden="true"><?php esc_html_e('Wishlist', 'xshop'); ?></span>
<span class="xshop-product-card__hook" aria-hidden="true"><?php esc_html_e('Compare', 'xshop'); ?></span>
<?php endif; ?>
</div>
<?php
// Hook placeholders for future wishlist/compare (no fake functionality)
do_action('xshop_product_card_after_actions', $product);
?>
</div>
</article>