215 lines
11 KiB
PHP
215 lines
11 KiB
PHP
<?php
|
||
/**
|
||
* کارت محصول - سفارشی مطابق با طراحی مطیب (با AJAX و علاقهمندی)
|
||
*
|
||
* @package Motayeb
|
||
* @version 1.0.1
|
||
*
|
||
* تغییرات نسخه ۱.۰.۱:
|
||
* - guard کامل WooCommerce (بدون fatal error اگه غیرفعال باشه)
|
||
* - data-product-id و data-wishlist-btn برای هماهنگی با main.js
|
||
* - مدیریت محصولات متغیر (هدایت به صفحه محصول بهجای quick-add)
|
||
* - مدیریت محصولات ناموجود (برچسب "ناموجود" + دکمه غیرفعال)
|
||
* - number_format_i18n برای اعداد فارسی
|
||
* - loading="lazy" + width/height + decoding="async" روی تصاویر
|
||
* - aria-label روی دکمههای آیکونی
|
||
* - Schema.org Product markup
|
||
* - نمایش دستهبندی محصول
|
||
* - برچسبهای بهتر: تخفیف، ویژه، ناموجود
|
||
*/
|
||
|
||
defined( 'ABSPATH' ) || exit;
|
||
|
||
global $product;
|
||
|
||
// guard: اگه ووکامرس غیرفعال باشه یا محصول معتبر نباشه
|
||
if ( ! class_exists( 'WooCommerce' ) || ! is_a( $product, 'WC_Product' ) ) {
|
||
return;
|
||
}
|
||
|
||
// دریافت دادههای ضروری
|
||
$product_id = $product->get_id();
|
||
$product_name = $product->get_name();
|
||
$product_link = $product->get_permalink();
|
||
$image_id = $product->get_image_id();
|
||
|
||
// تصویر محصول با fallback
|
||
$img_src = '';
|
||
$img_width = 400;
|
||
$img_height = 400;
|
||
if ( $image_id ) {
|
||
$image_data = wp_get_attachment_image_src( $image_id, 'medium' );
|
||
if ( $image_data ) {
|
||
$img_src = $image_data[0];
|
||
$img_width = $image_data[1];
|
||
$img_height = $image_data[2];
|
||
}
|
||
}
|
||
if ( ! $img_src ) {
|
||
$img_src = 'https://picsum.photos/seed/' . $product_id . '/400/400.jpg';
|
||
}
|
||
|
||
// امتیاز و تعداد نظرات
|
||
$rating = $product->get_average_rating();
|
||
$review_count = $product->get_rating_count();
|
||
|
||
// وضعیتهای محصول
|
||
$is_on_sale = $product->is_on_sale();
|
||
$is_featured = $product->is_featured();
|
||
$is_in_stock = $product->is_in_stock();
|
||
$is_variable = $product->is_type( 'variable' );
|
||
|
||
// محاسبه درصد تخفیف
|
||
$discount_percent = 0;
|
||
if ( $is_on_sale ) {
|
||
$regular_price = (float) $product->get_regular_price();
|
||
$sale_price = (float) $product->get_sale_price();
|
||
if ( $regular_price > 0 && $sale_price < $regular_price ) {
|
||
$discount_percent = round( ( ( $regular_price - $sale_price ) / $regular_price ) * 100 );
|
||
}
|
||
}
|
||
|
||
// دستهبندی محصول (اولین دسته)
|
||
$product_cats = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'names' ) );
|
||
$first_cat = ! empty( $product_cats ) && ! is_wp_error( $product_cats ) ? $product_cats[0] : '';
|
||
|
||
// قیمت HTML (بدون wp_kses_post — خود ووکامرس امنه)
|
||
$price_html = $product->get_price_html();
|
||
|
||
// تعیین نوع دکمه افزودن به سبد
|
||
$button_action = 'quick'; // پیشفرض: quick-add
|
||
$button_label = 'افزودن';
|
||
$button_icon = 'lucide:shopping-bag';
|
||
$button_disabled = false;
|
||
|
||
if ( ! $is_in_stock ) {
|
||
$button_action = 'none';
|
||
$button_label = 'ناموجود';
|
||
$button_icon = 'lucide:x-circle';
|
||
$button_disabled = true;
|
||
} elseif ( $is_variable ) {
|
||
$button_action = 'view'; // محصول متغیر: هدایت به صفحه محصول
|
||
$button_label = 'مشاهده';
|
||
$button_icon = 'lucide:eye';
|
||
}
|
||
?>
|
||
|
||
<div <?php wc_product_class( 'product-card group bg-white dark:bg-dark-card rounded-2xl overflow-hidden border border-cream-200/50 dark:border-dark-border/50 hover:shadow-xl transition-all relative w-full', $product ); ?>
|
||
itemscope itemtype="https://schema.org/Product">
|
||
|
||
<!-- متادیتای Schema.org (مخفی) -->
|
||
<meta itemprop="productID" content="<?php echo esc_attr( $product_id ); ?>">
|
||
<meta itemprop="name" content="<?php echo esc_attr( $product_name ); ?>">
|
||
<meta itemprop="url" content="<?php echo esc_attr( $product_link ); ?>">
|
||
<div itemprop="offers" itemscope itemtype="https://schema.org/Offer" class="hidden">
|
||
<meta itemprop="price" content="<?php echo esc_attr( $product->get_price() ); ?>">
|
||
<meta itemprop="priceCurrency" content="IRR">
|
||
<link itemprop="availability" href="<?php echo $is_in_stock ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock'; ?>">
|
||
</div>
|
||
|
||
<!-- عکس و لینک محصول -->
|
||
<a href="<?php echo esc_url( $product_link ); ?>" class="block relative overflow-hidden bg-cream-100 dark:bg-dark-bg" aria-label="<?php echo esc_attr( sprintf( __( 'مشاهده %s', 'motayeb' ), $product_name ) ); ?>">
|
||
<img src="<?php echo esc_url( $img_src ); ?>"
|
||
alt="<?php echo esc_attr( $product_name ); ?>"
|
||
width="<?php echo esc_attr( $img_width ); ?>"
|
||
height="<?php echo esc_attr( $img_height ); ?>"
|
||
loading="lazy"
|
||
decoding="async"
|
||
class="product-img w-full h-48 md:h-56 object-cover">
|
||
|
||
<!-- برچسبهای بالای عکس -->
|
||
<div class="absolute top-3 right-3 flex flex-col gap-1.5">
|
||
<?php if ( ! $is_in_stock ) : ?>
|
||
<span class="px-2.5 py-1 bg-cream-400 dark:bg-dark-muted text-white text-[10px] rounded-full font-medium">ناموجود</span>
|
||
<?php elseif ( $is_featured ) : ?>
|
||
<span class="px-2.5 py-1 bg-forest-500 text-white text-[10px] rounded-full font-medium">ویژه</span>
|
||
<?php endif; ?>
|
||
|
||
<?php if ( $discount_percent > 0 ) : ?>
|
||
<span class="px-2.5 py-1 bg-red-500 text-white text-[10px] rounded-full font-medium">
|
||
<?php echo esc_html( number_format_i18n( $discount_percent ) ); ?>٪ تخفیف
|
||
</span>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<?php if ( ! $is_in_stock ) : ?>
|
||
<!-- overlay ناموجود -->
|
||
<div class="absolute inset-0 bg-white/40 dark:bg-dark-bg/40 flex items-center justify-center">
|
||
<span class="px-4 py-2 bg-cream-400 dark:bg-dark-muted text-white text-xs font-bold rounded-xl">ناموجود</span>
|
||
</div>
|
||
<?php endif; ?>
|
||
</a>
|
||
|
||
<!-- دکمههای عملیات (هاور در دسکتاپ، همیشه در موبایل) -->
|
||
<?php if ( $is_in_stock ) : ?>
|
||
<div class="quick-actions absolute bottom-3 left-3 right-3 flex gap-2 z-10">
|
||
<?php if ( $button_action === 'view' ) : ?>
|
||
<!-- محصول متغیر: هدایت به صفحه محصول -->
|
||
<a href="<?php echo esc_url( $product_link ); ?>"
|
||
class="flex-1 py-2.5 bg-white/90 dark:bg-dark-card/90 backdrop-blur rounded-xl text-xs font-bold hover:bg-forest-500 hover:text-white transition flex items-center justify-center gap-1">
|
||
<iconify-icon icon="<?php echo esc_attr( $button_icon ); ?>" width="14"></iconify-icon>
|
||
<span><?php echo esc_html( $button_label ); ?></span>
|
||
</a>
|
||
<?php else : ?>
|
||
<!-- محصول ساده: افزودن با AJAX -->
|
||
<button onclick="quickAddToCart(<?php echo esc_js( $product_id ); ?>)"
|
||
class="flex-1 py-2.5 bg-white/90 dark:bg-dark-card/90 backdrop-blur rounded-xl text-xs font-bold hover:bg-forest-500 hover:text-white transition flex items-center justify-center gap-1"
|
||
aria-label="<?php echo esc_attr( sprintf( __( 'افزودن %s به سبد خرید', 'motayeb' ), $product_name ) ); ?>">
|
||
<iconify-icon icon="<?php echo esc_attr( $button_icon ); ?>" width="14"></iconify-icon>
|
||
<span><?php echo esc_html( $button_label ); ?></span>
|
||
</button>
|
||
<?php endif; ?>
|
||
|
||
<!-- دکمه علاقهمندیها -->
|
||
<button onclick="toggleWishlist(this, <?php echo esc_js( $product_id ); ?>)"
|
||
data-wishlist-btn
|
||
data-product-id="<?php echo esc_attr( $product_id ); ?>"
|
||
class="w-10 h-10 bg-white/90 dark:bg-dark-card/90 backdrop-blur rounded-xl flex items-center justify-center hover:bg-red-50 hover:text-red-500 transition"
|
||
aria-label="<?php echo esc_attr( sprintf( __( 'افزودن %s به علاقهمندیها', 'motayeb' ), $product_name ) ); ?>">
|
||
<iconify-icon icon="lucide:heart" width="16"></iconify-icon>
|
||
</button>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- اطلاعات محصول -->
|
||
<div class="p-4">
|
||
<!-- دستهبندی -->
|
||
<?php if ( $first_cat ) : ?>
|
||
<div class="text-[10px] text-cream-500 dark:text-dark-muted mb-1.5 font-medium uppercase tracking-wide"><?php echo esc_html( $first_cat ); ?></div>
|
||
<?php endif; ?>
|
||
|
||
<!-- عنوان -->
|
||
<a href="<?php echo esc_url( $product_link ); ?>"
|
||
class="block font-bold text-sm line-clamp-2 mb-3 group-hover:text-forest-500 dark:group-hover:text-forest-300 transition leading-relaxed"
|
||
itemprop="name">
|
||
<?php echo esc_html( $product_name ); ?>
|
||
</a>
|
||
|
||
<!-- ستارهها -->
|
||
<?php if ( $rating > 0 ) : ?>
|
||
<div class="flex items-center gap-1 mb-2" itemprop="aggregateRating" itemscope itemtype="https://schema.org/AggregateRating">
|
||
<span class="text-honey-400 text-xs" aria-hidden="true">★</span>
|
||
<span class="text-xs font-medium"><?php echo esc_html( number_format_i18n( $rating, 1 ) ); ?></span>
|
||
<span class="text-xs text-cream-400 dark:text-dark-muted">(<?php echo esc_html( number_format_i18n( $review_count ) ); ?>)</span>
|
||
<meta itemprop="ratingValue" content="<?php echo esc_attr( $rating ); ?>">
|
||
<meta itemprop="reviewCount" content="<?php echo esc_attr( $review_count ); ?>">
|
||
</div>
|
||
<?php else : ?>
|
||
<div class="flex items-center gap-1 mb-2">
|
||
<span class="text-cream-300 dark:text-dark-muted text-xs" aria-hidden="true">★★★★★</span>
|
||
<span class="text-xs text-cream-400 dark:text-dark-muted">بدون امتیاز</span>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- قیمت -->
|
||
<div class="flex items-end gap-2" itemprop="price">
|
||
<?php if ( $is_in_stock ) : ?>
|
||
<span class="font-extrabold text-forest-500 dark:text-forest-300 text-sm md:text-base">
|
||
<?php echo $price_html; // ووکامرس خودش escape میکنه ?>
|
||
</span>
|
||
<?php else : ?>
|
||
<span class="font-bold text-cream-400 dark:text-dark-muted text-sm italic">ناموجود</span>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|