feat: Implement upsell functionality with repository and service layers

This commit is contained in:
2026-05-02 23:30:23 +03:30
parent 4928901a08
commit 5930c1ad6f
26 changed files with 3130 additions and 126 deletions

View File

@@ -0,0 +1,91 @@
<?php
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
use Sodino\Repositories\UpsellRepository;
use Sodino\Services\UpsellService;
global $sodino_upsell_service;
$upsellRepository = new UpsellRepository();
$sodino_upsell_service = new UpsellService($upsellRepository);
add_action('woocommerce_before_cart', 'sodino_render_upsell_suggestions');
function sodino_render_upsell_suggestions() {
if (is_admin() || !is_cart()) {
return;
}
$settings = wp_parse_args(get_option('sodino_settings', []), [
'upsell_enabled' => 1,
]);
if (empty($settings['upsell_enabled'])) {
return;
}
global $sodino_upsell_service;
if (!isset($sodino_upsell_service)) {
return;
}
$cart = WC()->cart;
if (!$cart || $cart->is_empty()) {
return;
}
$upsells = $sodino_upsell_service->getMatchingUpsells($cart);
if (empty($upsells)) {
return;
}
echo '<div class="sodino-upsell-panel bg-white rounded-2xl border border-gray-200 p-6 mb-8 shadow-sm">';
echo '<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">';
echo '<div>';
echo '<p class="text-sm font-semibold text-blue-600">' . esc_html__('پیشنهاد ویژه آپسل', 'sodino') . '</p>';
echo '<h2 class="mt-2 text-xl font-bold text-gray-900">' . esc_html__('این محصول را همراه خرید خود با تخفیف ویژه دریافت کنید', 'sodino') . '</h2>';
echo '</div>';
echo '<span class="inline-flex items-center rounded-full bg-blue-50 px-3 py-1 text-sm font-medium text-blue-700">' . count($upsells) . ' ' . esc_html__('پیشنهاد فعال', 'sodino') . '</span>';
echo '</div>';
echo '<div class="mt-6 grid gap-4 lg:grid-cols-'.min(2, count($upsells)).'">';
foreach ($upsells as $upsell) {
$product = wc_get_product($upsell->target_product_id);
if (!$product) {
continue;
}
$discountedPrice = $sodino_upsell_service->applyUpsellDiscount($product, $upsell);
$originalPrice = floatval($product->get_price());
$priceHtml = wc_price($discountedPrice);
if ($discountedPrice < $originalPrice) {
$priceHtml .= ' <span class="mr-2 text-sm text-gray-500 line-through">' . wc_price($originalPrice) . '</span>';
}
$addToCartUrl = esc_url(add_query_arg('add-to-cart', $product->get_id(), wc_get_cart_url()));
$image = $product->get_image('woocommerce_thumbnail', ['class' => 'h-20 w-20 rounded-xl object-cover']);
echo '<div class="rounded-2xl border border-gray-200 p-5 bg-gray-50">';
echo '<div class="flex gap-4">';
echo '<div class="flex-shrink-0">' . $image . '</div>';
echo '<div class="flex-1">';
echo '<p class="text-sm font-medium text-gray-700">' . esc_html($upsell->title) . '</p>';
echo '<h3 class="mt-2 text-lg font-semibold text-gray-900">' . esc_html($product->get_name()) . '</h3>';
echo '<div class="mt-3 flex items-center gap-3">';
echo '<span class="rounded-full bg-green-50 px-3 py-1 text-sm font-medium text-green-700">' . esc_html($sodino_upsell_service->getDiscountLabel($upsell)) . '</span>';
echo '<span class="text-sm text-gray-600">' . esc_html($sodino_upsell_service->getTriggerLabel($upsell)) . '</span>';
echo '</div>';
echo '</div>';
echo '</div>';
echo '<div class="mt-5 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">';
echo '<div class="text-lg font-semibold text-gray-900">' . $priceHtml . '</div>';
echo '<a href="' . $addToCartUrl . '" class="inline-flex items-center justify-center rounded-full bg-blue-600 px-5 py-3 text-sm font-semibold text-white hover:bg-blue-700">' . esc_html__('افزودن به سبد', 'sodino') . '</a>';
echo '</div>';
echo '</div>';
}
echo '</div>';
echo '</div>';
}