feat: Implement upsell functionality with repository and service layers
This commit is contained in:
@@ -6,23 +6,49 @@ if (!defined('ABSPATH')) {
|
||||
|
||||
use Sodino\Controllers\AdminController;
|
||||
use Sodino\Repositories\RuleRepository;
|
||||
use Sodino\Repositories\UpsellRepository;
|
||||
|
||||
// Initialize admin
|
||||
$ruleRepository = new RuleRepository();
|
||||
$adminController = new AdminController($ruleRepository);
|
||||
$upsellRepository = new UpsellRepository();
|
||||
$adminController = new AdminController($ruleRepository, $upsellRepository);
|
||||
|
||||
// Add menu
|
||||
add_action('admin_menu', [$adminController, 'addMenu']);
|
||||
|
||||
// Admin AJAX handlers
|
||||
add_action('wp_ajax_sodino_search_products', [$adminController, 'searchProductsAjax']);
|
||||
|
||||
// Enqueue admin assets
|
||||
add_action('admin_enqueue_scripts', function($hook) {
|
||||
add_action('admin_enqueue_scripts', function($hook) use ($adminController) {
|
||||
if (strpos($hook, 'sodino') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Enqueue Tailwind via CDN script
|
||||
wp_enqueue_script('sodino-tailwind', 'https://cdn.tailwindcss.com', [], null);
|
||||
|
||||
wp_enqueue_style('sodino-admin', plugin_dir_url(__FILE__) . 'css/admin.css', [], SODINO_VERSION);
|
||||
|
||||
if (strpos($hook, 'sodino_page_sodino-dashboard') !== false) {
|
||||
wp_enqueue_script('sodino-chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', [], null, true);
|
||||
wp_enqueue_script('sodino-dashboard-js', plugin_dir_url(__FILE__) . 'js/dashboard.js', ['sodino-chart-js'], null, true);
|
||||
}
|
||||
|
||||
if (strpos($hook, 'sodino_page_sodino-add-upsell') !== false) {
|
||||
wp_enqueue_script('sodino-upsell-admin', plugin_dir_url(__FILE__) . 'js/upsell-admin.js', [], SODINO_VERSION, true);
|
||||
wp_localize_script('sodino-upsell-admin', 'sodinoUpsellAdmin', [
|
||||
'nonce' => wp_create_nonce('sodino_search_products'),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle delete for any Sodino admin page
|
||||
if (isset($_GET['page']) && strpos($_GET['page'], 'sodino') === 0 && isset($_GET['action']) && $_GET['action'] === 'delete') {
|
||||
add_action('admin_init', [$adminController, 'handleDelete']);
|
||||
}
|
||||
|
||||
// Handle upsell actions
|
||||
if (isset($_GET['page']) && strpos($_GET['page'], 'sodino') === 0 && isset($_GET['action']) && in_array($_GET['action'], ['delete_upsell', 'toggle_upsell_status'], true)) {
|
||||
add_action('admin_init', [$adminController, 'handleUpsellActions']);
|
||||
}
|
||||
138
admin/class-upsell-list-table.php
Normal file
138
admin/class-upsell-list-table.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!class_exists('WP_List_Table')) {
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
}
|
||||
|
||||
class Sodino_Upsell_List_Table extends WP_List_Table {
|
||||
private $repository;
|
||||
private $items_per_page = 20;
|
||||
|
||||
public function __construct($repository) {
|
||||
parent::__construct([
|
||||
'singular' => 'sodino_upsell',
|
||||
'plural' => 'sodino_upsells',
|
||||
'ajax' => false,
|
||||
]);
|
||||
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function get_columns() {
|
||||
return [
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'title' => __('عنوان', 'sodino'),
|
||||
'trigger' => __('شرط فعالسازی', 'sodino'),
|
||||
'suggested_product'=> __('محصول پیشنهادی', 'sodino'),
|
||||
'discount' => __('تخفیف', 'sodino'),
|
||||
'status' => __('وضعیت', 'sodino'),
|
||||
'actions' => __('عملیات', 'sodino'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function get_sortable_columns() {
|
||||
return [
|
||||
'title' => ['title', true],
|
||||
'priority' => ['priority', true],
|
||||
];
|
||||
}
|
||||
|
||||
protected function column_cb($item) {
|
||||
return sprintf('<input type="checkbox" name="upsell_ids[]" value="%d" />', $item->id);
|
||||
}
|
||||
|
||||
public function get_bulk_actions() {
|
||||
return [
|
||||
'delete' => __('حذف گروهی', 'sodino'),
|
||||
];
|
||||
}
|
||||
|
||||
public function column_title($item) {
|
||||
$edit_url = admin_url('admin.php?page=sodino-add-upsell&action=edit&id=' . $item->id);
|
||||
$title = sprintf('<strong><a href="%s">%s</a></strong>', esc_url($edit_url), esc_html($item->title));
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function column_trigger($item) {
|
||||
switch ($item->trigger_type) {
|
||||
case 'product':
|
||||
$product = wc_get_product(intval($item->trigger_value));
|
||||
return $product ? esc_html($product->get_name()) : __('محصول خاص', 'sodino');
|
||||
case 'category':
|
||||
$term = get_term(intval($item->trigger_value));
|
||||
return $term && !is_wp_error($term) ? esc_html($term->name) : __('دستهبندی', 'sodino');
|
||||
case 'cart_total':
|
||||
return sprintf('%s %s', esc_html(number_format_i18n(floatval($item->trigger_value))), __('تومان', 'sodino'));
|
||||
default:
|
||||
return __('نامشخص', 'sodino');
|
||||
}
|
||||
}
|
||||
|
||||
public function column_suggested_product($item) {
|
||||
$product = wc_get_product($item->target_product_id);
|
||||
return $product ? esc_html($product->get_name()) : __('نامشخص', 'sodino');
|
||||
}
|
||||
|
||||
public function column_discount($item) {
|
||||
if ($item->discount_type === 'fixed') {
|
||||
return sprintf('%s %s', esc_html(number_format_i18n($item->discount_value)), __('تومان', 'sodino'));
|
||||
}
|
||||
if ($item->discount_type === 'percentage') {
|
||||
return sprintf('%s %%', esc_html($item->discount_value));
|
||||
}
|
||||
return __('بدون تخفیف', 'sodino');
|
||||
}
|
||||
|
||||
public function column_status($item) {
|
||||
return $item->status ? __('فعال', 'sodino') : __('غیرفعال', 'sodino');
|
||||
}
|
||||
|
||||
public function column_actions($item) {
|
||||
$edit_url = admin_url('admin.php?page=sodino-add-upsell&action=edit&id=' . $item->id);
|
||||
$toggle_url = wp_nonce_url(admin_url('admin.php?page=sodino-upsells&action=toggle_upsell_status&id=' . $item->id), 'toggle_upsell_status');
|
||||
$delete_url = wp_nonce_url(admin_url('admin.php?page=sodino-upsells&action=delete_upsell&id=' . $item->id), 'delete_upsell');
|
||||
|
||||
$toggle_label = $item->status ? __('غیرفعال کردن', 'sodino') : __('فعال کردن', 'sodino');
|
||||
|
||||
return sprintf(
|
||||
'<a href="%s">%s</a> | <a href="%s">%s</a> | <a href="%s" onclick="return confirm(\'%s\');">%s</a>',
|
||||
esc_url($edit_url),
|
||||
esc_html__('ویرایش', 'sodino'),
|
||||
esc_url($toggle_url),
|
||||
esc_html($toggle_label),
|
||||
esc_url($delete_url),
|
||||
esc_js(__('آیا از حذف این پیشنهاد آپسل مطمئن هستید؟', 'sodino')),
|
||||
esc_html__('حذف', 'sodino')
|
||||
);
|
||||
}
|
||||
|
||||
public function prepare_items() {
|
||||
$this->_column_headers = [$this->get_columns(), [], $this->get_sortable_columns()];
|
||||
$this->process_bulk_action();
|
||||
|
||||
$all_items = $this->repository->getAll();
|
||||
$current_page = $this->get_pagenum();
|
||||
$total_items = count($all_items);
|
||||
$this->items = array_slice($all_items, ($current_page - 1) * $this->items_per_page, $this->items_per_page);
|
||||
|
||||
$this->set_pagination_args([
|
||||
'total_items' => $total_items,
|
||||
'per_page' => $this->items_per_page,
|
||||
'total_pages' => ceil($total_items / $this->items_per_page),
|
||||
]);
|
||||
}
|
||||
|
||||
public function process_bulk_action() {
|
||||
if ('delete' === $this->current_action()) {
|
||||
$upsell_ids = isset($_POST['upsell_ids']) ? array_map('intval', $_POST['upsell_ids']) : [];
|
||||
if (!empty($upsell_ids) && check_admin_referer('bulk-' . $this->_args['plural'])) {
|
||||
foreach ($upsell_ids as $id) {
|
||||
$this->repository->delete($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,296 @@
|
||||
.wrap {
|
||||
#sodino-app {
|
||||
direction: rtl;
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.sodino-admin-table th,
|
||||
.sodino-admin-table td {
|
||||
#sodino-app * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#sodino-app a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#sodino-app .sd-app {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
#sodino-app .sd-header {
|
||||
background: #eef2ff;
|
||||
border: 1px solid #c7d2fe;
|
||||
border-radius: 1rem;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
#sodino-app .sd-header-title {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
#sodino-app .sd-header-subtitle {
|
||||
color: #475569;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
#sodino-app .sd-page-layout {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
#sodino-app .sd-page-layout {
|
||||
grid-template-columns: 260px minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
#sodino-app .sd-sidebar {
|
||||
background: #ffffff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 1rem;
|
||||
padding: 18px;
|
||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
#sodino-app .sd-sidebar-title {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#sodino-app .sd-nav {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#sodino-app .sd-nav-link {
|
||||
display: block;
|
||||
padding: 0.85rem 1rem;
|
||||
border-radius: 0.9rem;
|
||||
font-weight: 600;
|
||||
color: #334155;
|
||||
background: #f8fafc;
|
||||
border: 1px solid transparent;
|
||||
transition: all 0.15s ease-in-out;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.page-title-action {
|
||||
float: left;
|
||||
#sodino-app .sd-nav-link:hover,
|
||||
#sodino-app .sd-nav-link.active {
|
||||
background: #e0e7ff;
|
||||
border-color: #c7d2fe;
|
||||
color: #1e3a8a;
|
||||
}
|
||||
|
||||
.rtl .page-title-action {
|
||||
float: left;
|
||||
#sodino-app .sd-nav-link.disabled {
|
||||
color: #94a3b8;
|
||||
pointer-events: none;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
input.regular-text,
|
||||
select.regular-text,
|
||||
input.small-text {
|
||||
direction: rtl;
|
||||
#sodino-app .sd-main {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
#sodino-app .sd-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 1.25rem;
|
||||
padding: 24px;
|
||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
#sodino-app .sd-stat-grid {
|
||||
display: grid;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
#sodino-app .sd-stat-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
#sodino-app .sd-card-title {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: #334155;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#sodino-app .sd-card-amount {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
#sodino-app .sd-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 0.85rem;
|
||||
padding: 0.75rem 1.2rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.15s ease-in-out;
|
||||
border: 1px solid transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#sodino-app .sd-btn-primary {
|
||||
background: #4338ca;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#sodino-app .sd-btn-primary:hover {
|
||||
background: #3730a3;
|
||||
}
|
||||
|
||||
#sodino-app .sd-btn-secondary {
|
||||
background: #f8fafc;
|
||||
color: #0f172a;
|
||||
border-color: #e2e8f0;
|
||||
}
|
||||
|
||||
#sodino-app .sd-btn-secondary:hover {
|
||||
background: #eef2ff;
|
||||
}
|
||||
|
||||
#sodino-app .sd-btn-danger {
|
||||
background: #ef4444;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#sodino-app .sd-btn-danger:hover {
|
||||
background: #dc2626;
|
||||
}
|
||||
|
||||
#sodino-app .sd-form-group {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
#sodino-app .sd-label {
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
#sodino-app .sd-input,
|
||||
#sodino-app .sd-select,
|
||||
#sodino-app .sd-textarea {
|
||||
width: 100%;
|
||||
border-radius: 1rem;
|
||||
border: 1px solid #cbd5e1;
|
||||
padding: 0.85rem 1rem;
|
||||
background: #ffffff;
|
||||
color: #0f172a;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#sodino-app .sd-input:focus,
|
||||
#sodino-app .sd-select:focus,
|
||||
#sodino-app .sd-textarea:focus {
|
||||
border-color: #6366f1;
|
||||
box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.15);
|
||||
}
|
||||
|
||||
#sodino-app .sd-input[readonly],
|
||||
#sodino-app .sd-select[disabled] {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
#sodino-app .sd-helper {
|
||||
color: #64748b;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
#sodino-app .sd-table-wrapper {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#sodino-app table.sd-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
min-width: 700px;
|
||||
}
|
||||
|
||||
#sodino-app table.sd-table th,
|
||||
#sodino-app table.sd-table td {
|
||||
padding: 1rem 1.25rem;
|
||||
text-align: right;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#sodino-app table.sd-table thead th {
|
||||
background: #f8fafc;
|
||||
color: #475569;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#sodino-app table.sd-table tbody tr:nth-child(odd) {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
#sodino-app table.sd-table tbody tr:hover {
|
||||
background: #eef2ff;
|
||||
}
|
||||
|
||||
#sodino-app .sd-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.35rem 0.8rem;
|
||||
border-radius: 9999px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#sodino-app .sd-badge--success {
|
||||
background: #dcfce7;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
#sodino-app .sd-badge--danger {
|
||||
background: #fee2e2;
|
||||
color: #991b1b;
|
||||
}
|
||||
|
||||
#sodino-app .sd-alert {
|
||||
border-radius: 1rem;
|
||||
padding: 18px 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
#sodino-app .sd-alert-success {
|
||||
background: #ecfdf5;
|
||||
color: #064e3b;
|
||||
border: 1px solid #d1fae5;
|
||||
}
|
||||
|
||||
#sodino-app .sd-alert-error {
|
||||
background: #fef2f2;
|
||||
color: #7f1d1d;
|
||||
border: 1px solid #fecdd3;
|
||||
}
|
||||
|
||||
#sodino-app .sd-grid-3 {
|
||||
display: grid;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
#sodino-app .sd-grid-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
#sodino-app .sd-chart-card {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
175
admin/js/dashboard.js
Normal file
175
admin/js/dashboard.js
Normal file
@@ -0,0 +1,175 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const dataEl = document.getElementById('sodino-dashboard-data');
|
||||
if (!dataEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
let dashboardData;
|
||||
try {
|
||||
dashboardData = JSON.parse(dataEl.textContent || '{}');
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof Chart === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const salesChartContext = document.getElementById('sodinoSalesChart');
|
||||
const discountChartContext = document.getElementById('sodinoDiscountChart');
|
||||
const ruleChartContext = document.getElementById('sodinoRuleChart');
|
||||
|
||||
if (salesChartContext && dashboardData.salesChart) {
|
||||
new Chart(salesChartContext.getContext('2d'), {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: dashboardData.salesChart.labels,
|
||||
datasets: [
|
||||
{
|
||||
label: dashboardData.translations.afterApplying,
|
||||
data: dashboardData.salesChart.after,
|
||||
borderColor: '#0ea5e9',
|
||||
backgroundColor: 'rgba(14, 165, 233, 0.15)',
|
||||
fill: true,
|
||||
tension: 0.35,
|
||||
pointRadius: 3,
|
||||
},
|
||||
{
|
||||
label: dashboardData.translations.beforeApplying,
|
||||
data: dashboardData.salesChart.before,
|
||||
borderColor: '#ef4444',
|
||||
backgroundColor: 'rgba(239, 68, 68, 0.15)',
|
||||
fill: true,
|
||||
tension: 0.35,
|
||||
pointRadius: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: {
|
||||
color: '#334155',
|
||||
},
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
ticks: {
|
||||
color: '#475569',
|
||||
},
|
||||
grid: {
|
||||
color: 'rgba(148, 163, 184, 0.15)',
|
||||
},
|
||||
},
|
||||
y: {
|
||||
ticks: {
|
||||
color: '#475569',
|
||||
},
|
||||
grid: {
|
||||
color: 'rgba(148, 163, 184, 0.15)',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (discountChartContext && dashboardData.summary) {
|
||||
new Chart(discountChartContext.getContext('2d'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: [dashboardData.translations.totalDiscount, dashboardData.translations.totalRevenue],
|
||||
datasets: [
|
||||
{
|
||||
label: dashboardData.translations.discountEffect,
|
||||
data: [dashboardData.summary.total_discount, dashboardData.summary.total_revenue],
|
||||
backgroundColor: ['#fbbf24', '#0ea5e9'],
|
||||
borderRadius: 999,
|
||||
borderSkipped: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
ticks: {
|
||||
color: '#475569',
|
||||
},
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
ticks: {
|
||||
color: '#475569',
|
||||
},
|
||||
grid: {
|
||||
color: 'rgba(148, 163, 184, 0.15)',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (ruleChartContext && dashboardData.rulePerformance) {
|
||||
new Chart(ruleChartContext.getContext('2d'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: dashboardData.rulePerformance.names,
|
||||
datasets: [
|
||||
{
|
||||
label: dashboardData.translations.ruleRevenue,
|
||||
data: dashboardData.rulePerformance.revenue,
|
||||
backgroundColor: '#0ea5e9',
|
||||
borderRadius: 999,
|
||||
},
|
||||
{
|
||||
label: dashboardData.translations.ruleDiscount,
|
||||
data: dashboardData.rulePerformance.discount,
|
||||
backgroundColor: '#f59e0b',
|
||||
borderRadius: 999,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
indexAxis: 'y',
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
color: '#475569',
|
||||
},
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
ticks: {
|
||||
color: '#475569',
|
||||
},
|
||||
grid: {
|
||||
color: 'rgba(148, 163, 184, 0.15)',
|
||||
},
|
||||
},
|
||||
y: {
|
||||
ticks: {
|
||||
color: '#475569',
|
||||
},
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
106
admin/js/upsell-admin.js
Normal file
106
admin/js/upsell-admin.js
Normal file
@@ -0,0 +1,106 @@
|
||||
(function () {
|
||||
const triggerTypeInputs = document.querySelectorAll('.trigger-type');
|
||||
const triggerProductWrapper = document.getElementById('trigger-product-wrapper');
|
||||
const triggerCategoryWrapper = document.getElementById('trigger-category-wrapper');
|
||||
const triggerAmountWrapper = document.getElementById('trigger-amount-wrapper');
|
||||
const triggerValueInput = document.getElementById('trigger_value');
|
||||
const triggerProductSearch = document.getElementById('trigger_product_search');
|
||||
const triggerProductResults = document.getElementById('trigger_product_results');
|
||||
|
||||
const targetProductSearch = document.getElementById('target_product_search');
|
||||
const targetProductResults = document.getElementById('target_product_results');
|
||||
const targetProductIdInput = document.getElementById('target_product_id');
|
||||
|
||||
function setTriggerVisibility() {
|
||||
const selected = document.querySelector('input[name="trigger_type"]:checked');
|
||||
const value = selected ? selected.value : 'product';
|
||||
|
||||
triggerProductWrapper.classList.toggle('hidden', value !== 'product');
|
||||
triggerCategoryWrapper.classList.toggle('hidden', value !== 'category');
|
||||
triggerAmountWrapper.classList.toggle('hidden', value !== 'cart_total');
|
||||
|
||||
if (value !== 'product' && triggerProductSearch) {
|
||||
triggerValueInput.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
function searchProducts(inputElement, resultsContainer, targetInput) {
|
||||
const term = inputElement.value.trim();
|
||||
if (!term) {
|
||||
resultsContainer.classList.add('hidden');
|
||||
resultsContainer.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new URLSearchParams();
|
||||
formData.append('action', 'sodino_search_products');
|
||||
formData.append('security', sodinoUpsellAdmin.nonce);
|
||||
formData.append('term', term);
|
||||
|
||||
fetch(ajaxurl, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: formData,
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (!Array.isArray(data)) {
|
||||
resultsContainer.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
const items = data.map(product => {
|
||||
const button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
button.className = 'w-full text-right px-4 py-3 hover:bg-blue-50 focus:bg-blue-50';
|
||||
button.textContent = product.label;
|
||||
button.addEventListener('click', function () {
|
||||
if (targetInput) {
|
||||
targetInput.value = product.id;
|
||||
inputElement.value = product.label;
|
||||
} else {
|
||||
triggerValueInput.value = product.id;
|
||||
inputElement.value = product.label;
|
||||
}
|
||||
resultsContainer.classList.add('hidden');
|
||||
});
|
||||
return button;
|
||||
});
|
||||
|
||||
resultsContainer.innerHTML = '';
|
||||
items.forEach(item => resultsContainer.appendChild(item));
|
||||
resultsContainer.classList.toggle('hidden', items.length === 0);
|
||||
})
|
||||
.catch(() => {
|
||||
resultsContainer.classList.add('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
if (triggerTypeInputs.length) {
|
||||
triggerTypeInputs.forEach(input => {
|
||||
input.addEventListener('change', setTriggerVisibility);
|
||||
});
|
||||
setTriggerVisibility();
|
||||
}
|
||||
|
||||
if (triggerProductSearch) {
|
||||
triggerProductSearch.addEventListener('input', function () {
|
||||
searchProducts(triggerProductSearch, triggerProductResults, null);
|
||||
});
|
||||
}
|
||||
|
||||
if (targetProductSearch) {
|
||||
targetProductSearch.addEventListener('input', function () {
|
||||
searchProducts(targetProductSearch, targetProductResults, targetProductIdInput);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
if (triggerProductResults && !triggerProductResults.contains(event.target) && event.target !== triggerProductSearch) {
|
||||
triggerProductResults.classList.add('hidden');
|
||||
}
|
||||
if (targetProductResults && !targetProductResults.contains(event.target) && event.target !== targetProductSearch) {
|
||||
targetProductResults.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
})();
|
||||
145
admin/views/competitor-price.php
Normal file
145
admin/views/competitor-price.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_page = sanitize_text_field($_GET['page'] ?? 'sodino-competitor-price');
|
||||
?>
|
||||
<div id="sodino-app" class="min-h-screen bg-gray-50" dir="rtl">
|
||||
<div class="bg-white border-b border-gray-200">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900"><?php _e('سودینو', 'sodino'); ?></h1>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('بهینهسازی هوشمند فروش', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="flex gap-8">
|
||||
<aside class="w-64 flex-shrink-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('منوی سودینو', 'sodino'); ?></h2>
|
||||
<nav class="space-y-2">
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-dashboard'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-dashboard' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('داشبورد', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-rules'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-rules' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قوانین', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-rule' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن قانون', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-upsells'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-upsells' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('آپسل (پیشنهاد فروش)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-upsell'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-upsell' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن آپسل', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-competitor-price'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-competitor-price' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قیمت رقبا (بهزودی)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-settings'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-settings' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('تنظیمات', 'sodino'); ?>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="flex-1 min-w-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<h2 class="text-2xl font-semibold text-gray-900"><?php _e('قیمت رقبا', 'sodino'); ?></h2>
|
||||
<p class="mt-2 text-gray-600"><?php _e('بهزودی بخش مانیتورینگ قیمت رقبا فعال خواهد شد.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<span class="inline-flex items-center rounded-full bg-yellow-50 px-3 py-1 text-sm font-medium text-yellow-700"><?php _e('بهزودی', 'sodino'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-6 lg:grid-cols-3">
|
||||
<div class="lg:col-span-2 bg-white rounded-2xl border border-gray-200 shadow-sm p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('مشخصات رقیب', 'sodino'); ?></h3>
|
||||
<p class="text-sm text-gray-500 mb-6"><?php _e('این قابلیت به شما امکان میدهد قیمت محصولات خود را با رقبا مقایسه کرده و بهینهسازی کنید. (در نسخههای آینده فعال خواهد شد)', 'sodino'); ?></p>
|
||||
|
||||
<div class="overflow-x-auto rounded-xl border border-gray-200">
|
||||
<table class="min-w-full divide-y divide-gray-200 text-right text-sm text-gray-700">
|
||||
<thead class="bg-gray-50 text-gray-500">
|
||||
<tr>
|
||||
<th class="px-4 py-3 font-medium"><?php _e('محصول', 'sodino'); ?></th>
|
||||
<th class="px-4 py-3 font-medium"><?php _e('قیمت شما', 'sodino'); ?></th>
|
||||
<th class="px-4 py-3 font-medium"><?php _e('قیمت رقبا', 'sodino'); ?></th>
|
||||
<th class="px-4 py-3 font-medium"><?php _e('اختلاف قیمت', 'sodino'); ?></th>
|
||||
<th class="px-4 py-3 font-medium"><?php _e('وضعیت', 'sodino'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 bg-white">
|
||||
<tr>
|
||||
<td class="px-4 py-3"><?php _e('کفش دویدن', 'sodino'); ?></td>
|
||||
<td class="px-4 py-3">23,500 تومان</td>
|
||||
<td class="px-4 py-3">24,900 تومان</td>
|
||||
<td class="px-4 py-3 text-green-600">1,400 تومان کمتر</td>
|
||||
<td class="px-4 py-3"><span class="rounded-full bg-green-50 px-3 py-1 text-xs font-semibold text-green-700"><?php _e('رقبتی', 'sodino'); ?></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-4 py-3"><?php _e('کرم محافظ پوست', 'sodino'); ?></td>
|
||||
<td class="px-4 py-3">78,000 تومان</td>
|
||||
<td class="px-4 py-3">82,000 تومان</td>
|
||||
<td class="px-4 py-3 text-green-600">4,000 تومان کمتر</td>
|
||||
<td class="px-4 py-3"><span class="rounded-full bg-green-50 px-3 py-1 text-xs font-semibold text-green-700"><?php _e('رقبتی', 'sodino'); ?></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-4 py-3"><?php _e('کیف دستی', 'sodino'); ?></td>
|
||||
<td class="px-4 py-3">155,000 تومان</td>
|
||||
<td class="px-4 py-3">161,000 تومان</td>
|
||||
<td class="px-4 py-3 text-red-600">6,000 تومان بیشتر</td>
|
||||
<td class="px-4 py-3"><span class="rounded-full bg-gray-50 px-3 py-1 text-xs font-semibold text-gray-700"><?php _e('هشدار', 'sodino'); ?></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold text-gray-900"><?php _e('افزودن رقیب', 'sodino'); ?></h3>
|
||||
<span class="rounded-full bg-blue-50 px-3 py-1 text-xs font-semibold text-blue-700"><?php _e('بهزودی', 'sodino'); ?></span>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2"><?php _e('URL سایت رقیب', 'sodino'); ?></label>
|
||||
<input type="url" disabled class="w-full rounded-lg border border-gray-200 bg-gray-100 px-4 py-3 text-gray-500 shadow-sm" placeholder="https://example.com">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2"><?php _e('نام فروشگاه', 'sodino'); ?></label>
|
||||
<input type="text" disabled class="w-full rounded-lg border border-gray-200 bg-gray-100 px-4 py-3 text-gray-500 shadow-sm" placeholder="<?php _e('مثلاً اسم فروشگاه رقبا', 'sodino'); ?>">
|
||||
</div>
|
||||
<button disabled class="w-full rounded-full bg-gray-300 px-4 py-3 text-sm font-semibold text-gray-700"><?php _e('افزودن', 'sodino'); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-900"><?php _e('فعالسازی مانیتورینگ قیمت', 'sodino'); ?></h3>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('این ویژگی در نسخههای آینده فعال میشود.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="px-3 py-1 rounded-full bg-gray-100 text-xs font-semibold text-gray-600"><?php _e('غیرفعال', 'sodino'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-2xl border border-gray-200 bg-gray-50 p-5 text-sm text-gray-500">
|
||||
<?php _e('در اینجا میتوانید فعالسازی خودکار تحلیل قیمت رقبا را مشاهده کنید؛ در حال حاضر این بخش در دست ساخت است.', 'sodino'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
170
admin/views/dashboard.php
Normal file
170
admin/views/dashboard.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$summary = $dashboardData['summary'];
|
||||
$salesChart = $dashboardData['sales_chart'];
|
||||
$rulePerformance = $dashboardData['rule_performance'];
|
||||
$userBehavior = $dashboardData['user_behavior'];
|
||||
$insights = $dashboardData['insights'];
|
||||
$current_page = sanitize_text_field($_GET['page'] ?? 'sodino-dashboard');
|
||||
?>
|
||||
<div id="sodino-app" class="min-h-screen bg-gray-50" dir="rtl">
|
||||
<!-- Header -->
|
||||
<div class="bg-white border-b border-gray-200">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900"><?php _e('سودینو', 'sodino'); ?></h1>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('بهینهسازی هوشمند فروش', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="flex gap-8">
|
||||
<!-- Sidebar -->
|
||||
<aside class="w-64 flex-shrink-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('منوی سودینو', 'sodino'); ?></h2>
|
||||
<nav class="space-y-2">
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-dashboard'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-dashboard' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('داشبورد', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-rules'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-rules' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قوانین', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-rule' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن قانون', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-upsells'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-upsells' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('آپسل (پیشنهاد فروش)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-upsell'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-upsell' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن آپسل', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-competitor-price'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-competitor-price' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قیمت رقبا (بهزودی)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-settings'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-settings' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('تنظیمات', 'sodino'); ?>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="flex-1 min-w-0">
|
||||
<!-- Overview Card -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
|
||||
<h2 class="text-xl font-semibold text-gray-900 mb-2"><?php _e('نمای کلی داشبورد', 'sodino'); ?></h2>
|
||||
<p class="text-gray-600"><?php _e('نمایش سریع KPIها، عملکرد قوانین و رفتار مشتریان.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Stats Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<div class="bg-gradient-to-br from-blue-600 to-blue-700 rounded-lg p-6 text-white">
|
||||
<h3 class="text-sm font-medium opacity-90"><?php _e('درآمد کل', 'sodino'); ?></h3>
|
||||
<div class="text-2xl font-bold mt-2"><?php echo wc_price($summary['total_revenue']); ?></div>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-sm font-medium text-gray-600"><?php _e('میزان تخفیف داده شده', 'sodino'); ?></h3>
|
||||
<div class="text-2xl font-bold text-gray-900 mt-2"><?php echo wc_price($summary['total_discount']); ?></div>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-sm font-medium text-gray-600"><?php _e('نرخ تبدیل تقریبی', 'sodino'); ?></h3>
|
||||
<div class="text-2xl font-bold text-gray-900 mt-2"><?php echo esc_html($summary['conversion_rate']); ?>%</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-sm font-medium text-gray-600"><?php _e('بهترین قانون', 'sodino'); ?></h3>
|
||||
<div class="text-2xl font-bold text-gray-900 mt-2"><?php echo esc_html($summary['best_rule'] ?? __('بدون داده', 'sodino')); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Charts Grid -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('نمودار فروش (قبل و بعد)', 'sodino'); ?></h3>
|
||||
<div class="h-64">
|
||||
<canvas id="sodinoSalesChart" class="w-full h-full"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('تاثیر تخفیف', 'sodino'); ?></h3>
|
||||
<div class="h-64">
|
||||
<canvas id="sodinoDiscountChart" class="w-full h-full"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('عملکرد قوانین', 'sodino'); ?></h3>
|
||||
<div class="h-64">
|
||||
<canvas id="sodinoRuleChart" class="w-full h-full"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Behavior and Insights -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('رفتار کاربران', 'sodino'); ?></h3>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="bg-gray-50 rounded-lg p-4">
|
||||
<div class="text-sm font-medium text-gray-600"><?php _e('بازدید محصول', 'sodino'); ?></div>
|
||||
<div class="text-2xl font-bold text-gray-900 mt-1"><?php echo esc_html($userBehavior['product_views']); ?></div>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-4">
|
||||
<div class="text-sm font-medium text-gray-600"><?php _e('افزودن به سبد', 'sodino'); ?></div>
|
||||
<div class="text-2xl font-bold text-gray-900 mt-1"><?php echo esc_html($userBehavior['add_to_cart']); ?></div>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-4">
|
||||
<div class="text-sm font-medium text-gray-600"><?php _e('شروع پرداخت', 'sodino'); ?></div>
|
||||
<div class="text-2xl font-bold text-gray-900 mt-1"><?php echo esc_html($userBehavior['checkout_start']); ?></div>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-4">
|
||||
<div class="text-sm font-medium text-gray-600"><?php _e('خرید', 'sodino'); ?></div>
|
||||
<div class="text-2xl font-bold text-gray-900 mt-1"><?php echo esc_html($userBehavior['purchases']); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('بینشها', 'sodino'); ?></h3>
|
||||
<div class="space-y-3">
|
||||
<?php foreach ($insights as $insight) : ?>
|
||||
<div class="bg-gray-50 rounded-lg p-4">
|
||||
<div class="text-sm text-gray-600"><?php echo esc_html($insight); ?></div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script id="sodino-dashboard-data" type="application/json">
|
||||
<?php echo wp_json_encode([
|
||||
'salesChart' => $salesChart,
|
||||
'summary' => $summary,
|
||||
'rulePerformance' => [
|
||||
'names' => array_column($rulePerformance, 'name'),
|
||||
'revenue' => array_column($rulePerformance, 'revenue'),
|
||||
'discount' => array_column($rulePerformance, 'discount'),
|
||||
],
|
||||
'translations' => [
|
||||
'afterApplying' => __('پس از اعمال سودینو', 'sodino'),
|
||||
'beforeApplying' => __('قبل از اعمال سودینو', 'sodino'),
|
||||
'totalDiscount' => __('مجموع تخفیف', 'sodino'),
|
||||
'totalRevenue' => __('درآمد پس از تخفیف', 'sodino'),
|
||||
'discountEffect' => __('تاثیر تخفیف', 'sodino'),
|
||||
'ruleRevenue' => __('درآمد ایجاد شده', 'sodino'),
|
||||
'ruleDiscount' => __('تخفیف ثبت شده', 'sodino'),
|
||||
],
|
||||
], JSON_UNESCAPED_UNICODE); ?>
|
||||
</script>
|
||||
@@ -3,52 +3,165 @@
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_page = sanitize_text_field($_GET['page'] ?? 'sodino-add-rule');
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php echo $rule->id ? __('ویرایش قانون', 'sodino') : __('افزودن قانون جدید', 'sodino'); ?></h1>
|
||||
<div id="sodino-app" class="min-h-screen bg-gray-50" dir="rtl">
|
||||
<!-- Header -->
|
||||
<div class="bg-white border-b border-gray-200">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900"><?php _e('سودینو', 'sodino'); ?></h1>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('بهینهسازی هوشمند فروش', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="post">
|
||||
<?php wp_nonce_field('gheymatyar_save_rule', 'gheymatyar_rule_nonce'); ?>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row"><label for="name"><?php _e('عنوان قانون', 'sodino'); ?></label></th>
|
||||
<td><input type="text" name="name" id="name" value="<?php echo esc_attr($rule->name); ?>" class="regular-text" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="condition_type"><?php _e('نوع شرط', 'sodino'); ?></label></th>
|
||||
<td>
|
||||
<select name="condition_type" id="condition_type" class="regular-text" required>
|
||||
<option value="user_type" <?php selected($rule->condition_type, 'user_type'); ?>><?php _e('نوع کاربر', 'sodino'); ?></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="condition_value"><?php _e('نوع کاربر', 'sodino'); ?></label></th>
|
||||
<td>
|
||||
<select name="condition_value" id="condition_value" class="regular-text" required>
|
||||
<option value="new" <?php selected($rule->condition_value, 'new'); ?>><?php _e('کاربر جدید', 'sodino'); ?></option>
|
||||
<option value="returning" <?php selected($rule->condition_value, 'returning'); ?>><?php _e('کاربر بازگشتی', 'sodino'); ?></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="action_type"><?php _e('نوع عملیات', 'sodino'); ?></label></th>
|
||||
<td>
|
||||
<select name="action_type" id="action_type" class="regular-text" required>
|
||||
<option value="discount_percent" <?php selected($rule->action_type, 'discount_percent'); ?>><?php _e('درصد تخفیف', 'sodino'); ?></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="action_value"><?php _e('درصد تخفیف', 'sodino'); ?></label></th>
|
||||
<td><input type="number" name="action_value" id="action_value" value="<?php echo esc_attr($rule->action_value); ?>" min="0" max="100" step="0.01" class="small-text" required> %</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="enabled"><?php _e('وضعیت', 'sodino'); ?></label></th>
|
||||
<td><label><input type="checkbox" name="enabled" id="enabled" value="1" <?php checked($rule->enabled, 1); ?>> <?php _e('فعال باشد', 'sodino'); ?></label></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="flex gap-8">
|
||||
<!-- Sidebar -->
|
||||
<aside class="w-64 flex-shrink-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('منوی سودینو', 'sodino'); ?></h2>
|
||||
<nav class="space-y-2">
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-dashboard'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-dashboard' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('داشبورد', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-rules'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-rules' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قوانین', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-rule' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن قانون', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-upsells'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-upsells' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('آپسل (پیشنهاد فروش)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-upsell'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-upsell' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن آپسل', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-competitor-price'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-competitor-price' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قیمت رقبا (بهزودی)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-settings'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-settings' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('تنظیمات', 'sodino'); ?>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<?php submit_button($rule->id ? __('بهروزرسانی قانون', 'sodino') : __('افزودن قانون', 'sودino'), 'primary'); ?>
|
||||
</form>
|
||||
<!-- Main Content -->
|
||||
<main class="flex-1 min-w-0">
|
||||
<!-- Page Header -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="text-2xl font-semibold text-gray-900"><?php echo $rule->id ? __('ویرایش قانون', 'sodino') : __('افزودن قانون جدید', 'sodino'); ?></h2>
|
||||
<p class="mt-2 text-gray-600"><?php _e('قانون قیمتگذاری پویا ایجاد یا ویرایش کنید.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-rules'); ?>" class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-lg text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
||||
<svg class="-ml-1 mr-2 h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<?php _e('بازگشت به قوانین', 'sodino'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Form -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<form method="post">
|
||||
<?php wp_nonce_field('gheymatyar_save_rule', 'gheymatyar_rule_nonce'); ?>
|
||||
|
||||
<div class="grid gap-6 md:grid-cols-2">
|
||||
<!-- Rule Name -->
|
||||
<div class="md:col-span-2">
|
||||
<label for="name" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('عنوان قانون', 'sodino'); ?></label>
|
||||
<input type="text" name="name" id="name" value="<?php echo esc_attr($rule->name); ?>" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100" required>
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('نامی کوتاه و قابل فهم برای قانون انتخاب کنید.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Priority -->
|
||||
<div>
|
||||
<label for="priority" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('اولویت', 'sodino'); ?></label>
|
||||
<input type="number" name="priority" id="priority" value="<?php echo esc_attr($rule->priority ?: 10); ?>" min="1" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('عدد بالاتر، اولویت بیشتری دارد.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Usage Limit -->
|
||||
<div>
|
||||
<label for="usage_limit" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('محدودیت تعداد استفاده', 'sodino'); ?></label>
|
||||
<input type="number" name="usage_limit" id="usage_limit" value="<?php echo esc_attr($rule->usage_limit ?? 0); ?>" min="0" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('0 به معنی بدون محدودیت است.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- User Roles -->
|
||||
<div class="md:col-span-2">
|
||||
<label for="user_roles" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('محدودیت نقش کاربری', 'sodino'); ?></label>
|
||||
<select name="user_roles[]" id="user_roles" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100" multiple size="4">
|
||||
<?php foreach (wp_roles()->roles as $role_key => $role_data) : ?>
|
||||
<option value="<?php echo esc_attr($role_key); ?>" <?php echo in_array($role_key, (array) $rule->user_roles, true) ? 'selected' : ''; ?>><?php echo esc_html($role_data['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('نقشهایی که این قانون باید برای آنها اعمال شود.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Condition Type -->
|
||||
<div>
|
||||
<label for="condition_type" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('نوع شرط', 'sodino'); ?></label>
|
||||
<select name="condition_type" id="condition_type" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100" required>
|
||||
<option value="user_type" <?php selected($rule->condition_type, 'user_type'); ?>><?php _e('نوع کاربر', 'sodino'); ?></option>
|
||||
<option value="product_category" <?php selected($rule->condition_type, 'product_category'); ?>><?php _e('دستهبندی محصول', 'sodino'); ?></option>
|
||||
<option value="product_ids" <?php selected($rule->condition_type, 'product_ids'); ?>><?php _e('محصولات خاص', 'sodino'); ?></option>
|
||||
</select>
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('نوع شرطی که باید قبل از اعمال قانون بررسی شود.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Condition Value -->
|
||||
<div>
|
||||
<label for="condition_value" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('مقدار شرط', 'sodino'); ?></label>
|
||||
<input type="text" name="condition_value" id="condition_value" value="<?php echo esc_attr($rule->condition_value); ?>" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100" required>
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('برای کاربر جدید/بازگشتی: new یا returning. برای دستهبندی: شناسه دستهبندی، برای محصولات: شناسه محصول.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Action Type -->
|
||||
<div>
|
||||
<label for="action_type" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('نوع عملیات', 'sodino'); ?></label>
|
||||
<select name="action_type" id="action_type" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100" required>
|
||||
<option value="discount_percent" <?php selected($rule->action_type, 'discount_percent'); ?>><?php _e('درصد تخفیف', 'sodino'); ?></option>
|
||||
<option value="discount_fixed" <?php selected($rule->action_type, 'discount_fixed'); ?>><?php _e('تخفیف ثابت', 'sodino'); ?></option>
|
||||
<option value="free_shipping" <?php selected($rule->action_type, 'free_shipping'); ?>><?php _e('ارسال رایگان', 'sodino'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Action Value -->
|
||||
<div>
|
||||
<label for="action_value" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('مقدار عملیات', 'sodino'); ?></label>
|
||||
<input type="number" name="action_value" id="action_value" value="<?php echo esc_attr($rule->action_value); ?>" min="0" step="0.01" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('برای درصد یا مقدار ثابت وارد کنید.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- Status -->
|
||||
<div class="md:col-span-2">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="enabled" id="enabled" value="1" <?php checked($rule->enabled, 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('فعال باشد', 'sodino'); ?></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="mt-8 flex justify-end">
|
||||
<button type="submit" class="inline-flex items-center px-6 py-3 border border-transparent text-sm font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
||||
<?php echo $rule->id ? __('بهروزرسانی قانون', 'sodino') : __('افزودن قانون', 'sodino'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3,13 +3,81 @@
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_page = sanitize_text_field($_GET['page'] ?? 'sodino-rules');
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php _e('قوانین قیمتگذاری', 'sodino'); ?></h1>
|
||||
<div id="sodino-app" class="min-h-screen bg-gray-50" dir="rtl">
|
||||
<!-- Header -->
|
||||
<div class="bg-white border-b border-gray-200">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900"><?php _e('سودینو', 'sodino'); ?></h1>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('بهینهسازی هوشمند فروش', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="page-title-action"><?php _e('افزودن قانون جدید', 'sodino'); ?></a>
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="flex gap-8">
|
||||
<!-- Sidebar -->
|
||||
<aside class="w-64 flex-shrink-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('منوی سودینو', 'sodino'); ?></h2>
|
||||
<nav class="space-y-2">
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-dashboard'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-dashboard' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('داشبورد', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-rules'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-rules' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قوانین', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-rule' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن قانون', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-upsells'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-upsells' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('آپسل (پیشنهاد فروش)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-upsell'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-upsell' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن آپسل', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-competitor-price'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-competitor-price' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قیمت رقبا (بهزودی)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-settings'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-settings' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('تنظیمات', 'sودینو'); ?>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<form method="post">
|
||||
<?php $rulesTable->display(); ?>
|
||||
</form>
|
||||
<!-- Main Content -->
|
||||
<main class="flex-1 min-w-0">
|
||||
<!-- Page Header -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="text-2xl font-semibold text-gray-900"><?php _e('قوانین قیمتگذاری', 'sodino'); ?></h2>
|
||||
<p class="mt-2 text-gray-600"><?php _e('مدیریت قوانین قیمتگذاری پویا و تخفیفهای هوشمند.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
||||
<svg class="-ml-1 mr-2 h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<?php _e('افزودن قانون جدید', 'sodino'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rules Table -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
||||
<form method="post">
|
||||
<?php $rulesTable->display(); ?>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3,10 +3,198 @@
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_page = sanitize_text_field($_GET['page'] ?? 'sodino-settings');
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php _e('تنظیمات قیمتیار', 'sodino'); ?></h1>
|
||||
<div class="notice notice-info">
|
||||
<p><?php _e('در اینجا تنظیمات افزونه در آینده قرار خواهد گرفت.', 'sodino'); ?></p>
|
||||
<div id="sodino-app" class="min-h-screen bg-gray-50" dir="rtl">
|
||||
<!-- Header -->
|
||||
<div class="bg-white border-b border-gray-200">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900"><?php _e('سودینو', 'sodino'); ?></h1>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('بهینهسازی هوشمند فروش', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="flex gap-8">
|
||||
<!-- Sidebar -->
|
||||
<aside class="w-64 flex-shrink-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('منوی سودینو', 'sodino'); ?></h2>
|
||||
<nav class="space-y-2">
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-dashboard'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-dashboard' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('داشبورد', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-rules'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-rules' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قوانین', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-rule' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن قانون', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-upsells'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-upsells' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('آپسل (پیشنهاد فروش)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-upsell'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-upsell' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن آپسل', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-competitor-price'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-competitor-price' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قیمت رقبا (بهزودی)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-settings'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-settings' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('تنظیمات', 'sodino'); ?>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="flex-1 min-w-0">
|
||||
<!-- Page Header -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
|
||||
<h2 class="text-2xl font-semibold text-gray-900"><?php _e('تنظیمات سودینو', 'sodino'); ?></h2>
|
||||
<p class="mt-2 text-gray-600"><?php _e('کنترل کامل تجربه قیمتگذاری و بهینهسازی درآمد را از اینجا انجام دهید.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_GET['updated']) && $_GET['updated'] === 'true') : ?>
|
||||
<div class="mb-6 bg-green-50 border border-green-200 rounded-lg p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-5 w-5 text-green-400" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="mr-3">
|
||||
<p class="text-sm font-medium text-green-800"><?php _e('تنظیمات با موفقیت ذخیره شد.', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" class="space-y-6">
|
||||
<?php wp_nonce_field('sodino_save_settings', 'sodino_settings_nonce'); ?>
|
||||
|
||||
<!-- General Section -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<div class="mb-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900"><?php _e('عمومی', 'sodino'); ?></h3>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('تنظیمات کلی فعالسازی پلاگین و ویژگیهای اصلی.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="grid gap-6 md:grid-cols-2">
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="plugin_enabled" value="1" <?php checked($settings['plugin_enabled'], 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('فعالسازی کل پلاگین', 'sodino'); ?></span>
|
||||
</label>
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('اگر غیرفعال باشد، هیچ قاعدهای اعمال نخواهد شد.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="pricing_enabled" value="1" <?php checked($settings['pricing_enabled'], 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('فعالسازی قیمتگذاری پویا', 'sodino'); ?></span>
|
||||
</label>
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('این گزینه، اعمال قوانین قیمتگذاری را کنترل میکند.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="upsell_enabled" value="1" <?php checked($settings['upsell_enabled'], 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('فعالسازی سیستم آپسل', 'sodino'); ?></span>
|
||||
</label>
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('پیشنهادهای درآمدی اضافه را نمایش میدهد.', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing Behavior Section -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<div class="mb-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900"><?php _e('رفتار قیمتگذاری', 'sodino'); ?></h3>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('چگونگی اجرای قوانین در فرآیند قیمتگذاری.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="grid gap-6 md:grid-cols-2">
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="allow_multiple_rules" value="1" <?php checked($settings['allow_multiple_rules'], 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('اجازه اعمال چند قانون همزمان', 'sodino'); ?></span>
|
||||
</label>
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('قوانین معتبر به صورت متوالی اعمال میشوند.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-3"><?php _e('استراتژی اعمال', 'sodino'); ?></label>
|
||||
<select name="strategy" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
<option value="highest_discount" <?php selected($settings['strategy'], 'highest_discount'); ?>><?php _e('بالاترین تخفیف', 'sodino'); ?></option>
|
||||
<option value="first_valid" <?php selected($settings['strategy'], 'first_valid'); ?>><?php _e('اولین قانون معتبر', 'sodino'); ?></option>
|
||||
<option value="priority" <?php selected($settings['strategy'], 'priority'); ?>><?php _e('بر اساس اولویت', 'sodino'); ?></option>
|
||||
</select>
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('استراتژی انتخاب قانون زمانی که بیش از یک قانون معتبر وجود داشته باشد.', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Limits Section -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<div class="mb-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900"><?php _e('محدودیتها', 'sodino'); ?></h3>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('پارامترهای محدودسازی برای حفظ حاشیه سود.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="grid gap-6 md:grid-cols-2">
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-3"><?php _e('حداکثر درصد تخفیف', 'sodino'); ?></label>
|
||||
<input type="number" name="max_discount_percent" value="<?php echo esc_attr($settings['max_discount_percent']); ?>" min="0" max="100" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('حداکثر تخفیف مجاز برای هر محصول را تعیین میکند.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-3"><?php _e('حداقل قیمت محصول', 'sodino'); ?></label>
|
||||
<input type="number" name="min_product_price" value="<?php echo esc_attr($settings['min_product_price']); ?>" min="0" step="0.01" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('از کاهش قیمت زیر این مقدار جلوگیری میکند.', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features Section -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<div class="mb-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900"><?php _e('ویژگیها', 'sodino'); ?></h3>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('گزینههای پیشرفته برای شخصیسازی رفتار درآمدی.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="grid gap-6 md:grid-cols-2">
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="ab_testing_enabled" value="1" <?php checked($settings['ab_testing_enabled'], 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('فعالسازی تست A/B', 'sodino'); ?></span>
|
||||
</label>
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('امکان فعالسازی سناریوهای آزمایشی را اضافه میکند.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="cart_pricing_enabled" value="1" <?php checked($settings['cart_pricing_enabled'], 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('اعمال قیمتگذاری در سبد خرید', 'sodino'); ?></span>
|
||||
</label>
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('در صورت خاموش بودن، قیمتگذاری پویا فقط در نمایش محصول انجام میشود.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<div class="bg-gray-50 rounded-lg p-5 border border-gray-200">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="scheduled_campaigns_enabled" value="1" <?php checked($settings['scheduled_campaigns_enabled'], 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('فعالسازی کمپینهای زمانبندی شده', 'sodino'); ?></span>
|
||||
</label>
|
||||
<p class="mt-3 text-sm text-gray-500"><?php _e('با فعال کردن، میتوانید قوانین را به صورت زمانبندیشده اجرا کنید.', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="flex justify-end">
|
||||
<button type="submit" class="inline-flex items-center px-6 py-3 border border-transparent text-sm font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
||||
<?php _e('ذخیره تنظیمات', 'sodino'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
187
admin/views/upsell-form.php
Normal file
187
admin/views/upsell-form.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_page = sanitize_text_field($_GET['page'] ?? 'sodino-add-upsell');
|
||||
$trigger_product = null;
|
||||
$trigger_product_label = '';
|
||||
$target_product = null;
|
||||
$target_product_label = '';
|
||||
|
||||
if ($upsell->trigger_type === 'product' && $upsell->trigger_value) {
|
||||
$trigger_product = wc_get_product(intval($upsell->trigger_value));
|
||||
$trigger_product_label = $trigger_product ? $trigger_product->get_name() : '';
|
||||
}
|
||||
|
||||
if ($upsell->target_product_id) {
|
||||
$target_product = wc_get_product($upsell->target_product_id);
|
||||
$target_product_label = $target_product ? $target_product->get_name() : '';
|
||||
}
|
||||
|
||||
$product_categories = get_terms([
|
||||
'taxonomy' => 'product_cat',
|
||||
'hide_empty' => false,
|
||||
]);
|
||||
?>
|
||||
<div id="sodino-app" class="min-h-screen bg-gray-50" dir="rtl">
|
||||
<div class="bg-white border-b border-gray-200">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900"><?php _e('سودینو', 'sodino'); ?></h1>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('بهینهسازی هوشمند فروش', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="flex gap-8">
|
||||
<aside class="w-64 flex-shrink-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('منوی سودینو', 'sodino'); ?></h2>
|
||||
<nav class="space-y-2">
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-dashboard'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-dashboard' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('داشبورد', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-rules'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-rules' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قوانین', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-rule' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن قانون', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-upsells'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-upsells' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('آپسل (پیشنهاد فروش)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-upsell'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-upsell' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن آپسل', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-competitor-price'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-competitor-price' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قیمت رقبا (بهزودی)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-settings'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-settings' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('تنظیمات', 'sodino'); ?>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="flex-1 min-w-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
|
||||
<div class="flex items-center justify-between gap-4 flex-col sm:flex-row sm:items-center">
|
||||
<div>
|
||||
<h2 class="text-2xl font-semibold text-gray-900"><?php echo $upsell->id ? __('ویرایش آپسل', 'sodino') : __('افزودن آپسل جدید', 'sodino'); ?></h2>
|
||||
<p class="mt-2 text-gray-600"><?php _e('یک پیشنهاد فروش مکمل هوشمند برای مشتریان ایجاد یا ویرایش کنید.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-upsells'); ?>" class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-lg text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
||||
<?php _e('بازگشت به آپسلها', 'sodino'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<form method="post" class="space-y-6">
|
||||
<?php wp_nonce_field('sodino_save_upsell', 'sodino_upsell_nonce'); ?>
|
||||
|
||||
<div class="grid gap-6 md:grid-cols-2">
|
||||
<div class="md:col-span-2">
|
||||
<label for="title" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('عنوان', 'sodino'); ?></label>
|
||||
<input type="text" name="title" id="title" value="<?php echo esc_attr($upsell->title); ?>" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100" required>
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2"><?php _e('نوع شرط', 'sodino'); ?></label>
|
||||
<div class="space-y-3">
|
||||
<label class="flex items-center gap-3 rounded-lg border border-gray-200 bg-white px-4 py-3 cursor-pointer hover:border-blue-300">
|
||||
<input type="radio" name="trigger_type" value="product" class="trigger-type" <?php checked($upsell->trigger_type, 'product'); ?>>
|
||||
<span><?php _e('محصول خاص', 'sodino'); ?></span>
|
||||
</label>
|
||||
<label class="flex items-center gap-3 rounded-lg border border-gray-200 bg-white px-4 py-3 cursor-pointer hover:border-blue-300">
|
||||
<input type="radio" name="trigger_type" value="category" class="trigger-type" <?php checked($upsell->trigger_type, 'category'); ?>>
|
||||
<span><?php _e('دستهبندی', 'sodino'); ?></span>
|
||||
</label>
|
||||
<label class="flex items-center gap-3 rounded-lg border border-gray-200 bg-white px-4 py-3 cursor-pointer hover:border-blue-300">
|
||||
<input type="radio" name="trigger_type" value="cart_total" class="trigger-type" <?php checked($upsell->trigger_type, 'cart_total'); ?>>
|
||||
<span><?php _e('مبلغ سبد خرید', 'sodino'); ?></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="trigger_value" id="trigger_value" value="<?php echo esc_attr($upsell->trigger_value); ?>">
|
||||
|
||||
<div id="trigger-product-wrapper" class="md:col-span-2 <?php echo $upsell->trigger_type === 'product' ? '' : 'hidden'; ?>">
|
||||
<label for="trigger_product_search" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('محصول فعالساز', 'sodino'); ?></label>
|
||||
<div class="relative">
|
||||
<input type="text" id="trigger_product_search" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100" placeholder="<?php _e('جستجوی محصول...', 'sodino'); ?>" value="<?php echo esc_attr($trigger_product_label); ?>">
|
||||
<div id="trigger_product_results" class="absolute z-10 mt-1 w-full rounded-xl border border-gray-200 bg-white shadow-lg hidden"></div>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('محصولی که باعث نمایش پیشنهاد آپسل میشود را انتخاب کنید.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<div id="trigger-category-wrapper" class="md:col-span-2 <?php echo $upsell->trigger_type === 'category' ? '' : 'hidden'; ?>">
|
||||
<label for="trigger_value_category" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('دستهبندی', 'sodino'); ?></label>
|
||||
<select name="trigger_value" id="trigger_value_category" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
<option value=""><?php _e('دستهبندی را انتخاب کنید', 'sodino'); ?></option>
|
||||
<?php foreach ($product_categories as $category) : ?>
|
||||
<option value="<?php echo esc_attr($category->term_id); ?>" <?php selected($upsell->trigger_type, 'category'); selected($upsell->trigger_value, $category->term_id); ?>><?php echo esc_html($category->name); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id="trigger-amount-wrapper" class="md:col-span-2 <?php echo $upsell->trigger_type === 'cart_total' ? '' : 'hidden'; ?>">
|
||||
<label for="trigger_value_amount" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('مبلغ سبد خرید', 'sodino'); ?></label>
|
||||
<input type="number" name="trigger_value" id="trigger_value_amount" value="<?php echo esc_attr($upsell->trigger_type === 'cart_total' ? $upsell->trigger_value : ''); ?>" min="0" step="0.01" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<label for="target_product_search" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('محصول پیشنهادی', 'sodino'); ?></label>
|
||||
<div class="relative">
|
||||
<input type="hidden" name="target_product_id" id="target_product_id" value="<?php echo esc_attr($upsell->target_product_id); ?>">
|
||||
<input type="text" id="target_product_search" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100" placeholder="<?php _e('جستجوی محصول پیشنهادی...', 'sodino'); ?>" value="<?php echo esc_attr($target_product_label); ?>">
|
||||
<div id="target_product_results" class="absolute z-10 mt-1 w-full rounded-xl border border-gray-200 bg-white shadow-lg hidden"></div>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500"><?php _e('محصولی که به مشتری پیشنهاد میشود را انتخاب کنید.', 'sodino'); ?></p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="discount_type" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('نوع تخفیف', 'sodino'); ?></label>
|
||||
<select name="discount_type" id="discount_type" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
<option value="percentage" <?php selected($upsell->discount_type, 'percentage'); ?>><?php _e('درصدی', 'sodino'); ?></option>
|
||||
<option value="fixed" <?php selected($upsell->discount_type, 'fixed'); ?>><?php _e('مبلغ ثابت', 'sodino'); ?></option>
|
||||
<option value="none" <?php selected($upsell->discount_type, 'none'); ?>><?php _e('بدون تخفیف', 'sodino'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="discount_value" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('مقدار تخفیف', 'sodino'); ?></label>
|
||||
<input type="number" name="discount_value" id="discount_value" value="<?php echo esc_attr($upsell->discount_value); ?>" min="0" step="0.01" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="priority" class="block text-sm font-medium text-gray-700 mb-2"><?php _e('اولویت', 'sodino'); ?></label>
|
||||
<input type="number" name="priority" id="priority" value="<?php echo esc_attr($upsell->priority); ?>" min="1" class="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 text-gray-700 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-100">
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<label class="flex items-center gap-3 text-gray-700">
|
||||
<input type="checkbox" name="status" id="status" value="1" <?php checked($upsell->status, 1); ?> class="h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span><?php _e('فعال باشد', 'sodino'); ?></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<button type="submit" class="inline-flex items-center px-6 py-3 border border-transparent text-sm font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
||||
<?php echo $upsell->id ? __('ذخیره آپسل', 'sodino') : __('افزودن آپسل', 'sodino'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
78
admin/views/upsell-list.php
Normal file
78
admin/views/upsell-list.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_page = sanitize_text_field($_GET['page'] ?? 'sodino-upsells');
|
||||
?>
|
||||
<div id="sodino-app" class="min-h-screen bg-gray-50" dir="rtl">
|
||||
<div class="bg-white border-b border-gray-200">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900"><?php _e('سودینو', 'sodino'); ?></h1>
|
||||
<p class="mt-1 text-sm text-gray-500"><?php _e('بهینهسازی هوشمند فروش', 'sodino'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="flex gap-8">
|
||||
<aside class="w-64 flex-shrink-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-4"><?php _e('منوی سودینو', 'sodino'); ?></h2>
|
||||
<nav class="space-y-2">
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-dashboard'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-dashboard' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('داشبورد', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-rules'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-rules' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قوانین', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-rule'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-rule' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن قانون', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-upsells'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-upsells' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('آپسل (پیشنهاد فروش)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-upsell'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-add-upsell' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('افزودن آپسل', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-competitor-price'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-competitor-price' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('قیمت رقبا (بهزودی)', 'sodino'); ?>
|
||||
</a>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-settings'); ?>" class="block px-3 py-2 rounded-md text-sm font-medium <?php echo $current_page === 'sodino-settings' ? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'; ?>">
|
||||
<?php _e('تنظیمات', 'sodino'); ?>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="flex-1 min-w-0">
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-8">
|
||||
<div class="flex items-center justify-between gap-4 flex-col sm:flex-row sm:items-center">
|
||||
<div>
|
||||
<h2 class="text-2xl font-semibold text-gray-900"><?php _e('مدیریت آپسلها', 'sodino'); ?></h2>
|
||||
<p class="mt-2 text-gray-600"><?php _e('ایجاد، ویرایش و مدیریت پیشنهادهای فروش مکمل.', 'sodino'); ?></p>
|
||||
</div>
|
||||
<a href="<?php echo admin_url('admin.php?page=sodino-add-upsell'); ?>" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
||||
<svg class="-ml-1 mr-2 h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<?php _e('افزودن آپسل جدید', 'sodino'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
||||
<form method="post">
|
||||
<?php $upsellTable->display(); ?>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user