From fc1c2f023d54839c2d492c9a567f4ccf15bf83eb Mon Sep 17 00:00:00 2001 From: Kazem Alghasi Date: Mon, 24 Aug 2026 04:48:08 +0330 Subject: [PATCH] feat(ui): implement user notification system in customer dashboard Integrate a new notification module into the customer dashboard to allow users to view and manage alerts. - Add `get_notifications` and `mark_notification_read` methods to `IFNEX_User_Bridge` to interface with the API - Introduce a new 'notifications' tab in the customer dashboard shortcode - Implement notification badge logic to display unread counts in the sidebar menu - Add new SVG icon for notifications - Add comprehensive CSS styles for notification items, badges, and unread states --- .../ifnex-bridge/assets/css/ifnex-orders.css | 97 +++++++++++++++++++ .../ifnex-bridge/includes/shortcodes.php | 55 ++++++++++- .../ifnex-bridge/includes/user-bridge.php | 23 +++++ 3 files changed, 173 insertions(+), 2 deletions(-) diff --git a/03_WordPress/wp-content/plugins/ifnex-bridge/assets/css/ifnex-orders.css b/03_WordPress/wp-content/plugins/ifnex-bridge/assets/css/ifnex-orders.css index 3b4d649..67b918b 100644 --- a/03_WordPress/wp-content/plugins/ifnex-bridge/assets/css/ifnex-orders.css +++ b/03_WordPress/wp-content/plugins/ifnex-bridge/assets/css/ifnex-orders.css @@ -663,4 +663,101 @@ align-items: center; gap: 6px; animation: ifnexFadeIn 0.25s ease; +} + +/* ═══ Notifications ═══ */ +.ifnx-notif-badge { + position: absolute; + top: -6px; + right: -10px; + background: #ef4444; + color: #fff; + font-size: 10px; + font-weight: 800; + min-width: 18px; + height: 18px; + border-radius: 999px; + display: flex; + align-items: center; + justify-content: center; + padding: 0 4px; + box-shadow: 0 2px 6px rgba(239,68,68,0.4); + line-height: 1; +} + +.ifnx-notif-list { + display: flex; + flex-direction: column; + gap: 8px; +} + +.ifnx-notif-item { + display: flex; + gap: 14px; + padding: 16px 18px; + background: #fff; + border-radius: 14px; + border: 1px solid #eef2f7; + box-shadow: 0 1px 3px rgba(15,23,42,0.04); + transition: all 0.2s ease; + cursor: pointer; +} +.ifnx-notif-item:hover { + box-shadow: 0 6px 20px rgba(15,23,42,0.08); + transform: translateY(-1px); +} +.ifnx-notif-item.unread { + background: #fffbeb; + border-color: #fde68a; +} + +.ifnx-notif-dot { + width: 10px; + height: 10px; + border-radius: 50%; + flex-shrink: 0; + margin-top: 5px; + background: #e2e8f0; +} +.ifnx-notif-item.unread .ifnx-notif-dot { + background: #f59e0b; + box-shadow: 0 0 0 3px rgba(245,158,11,0.2); +} + +.ifnx-notif-body { flex: 1; min-width: 0; } + +.ifnx-notif-title { + font-size: 14px; + font-weight: 700; + color: #0f172a; + margin-bottom: 4px; +} +.ifnx-notif-item.unread .ifnx-notif-title { color: #92400e; } + +.ifnx-notif-message { + font-size: 13px; + color: #64748b; + line-height: 1.6; + margin-bottom: 6px; +} + +.ifnx-notif-link { + display: inline-block; + font-size: 12px; + font-weight: 600; + color: #f97316; + text-decoration: none; + margin-bottom: 6px; +} +.ifnx-notif-link:hover { text-decoration: underline; } + +.ifnx-notif-time { + font-size: 11px; + color: #94a3b8; + direction: ltr; + display: inline-block; +} + +@media (max-width: 640px) { + .ifnx-notif-item { padding: 12px 14px; } } \ No newline at end of file diff --git a/03_WordPress/wp-content/plugins/ifnex-bridge/includes/shortcodes.php b/03_WordPress/wp-content/plugins/ifnex-bridge/includes/shortcodes.php index 5e40d5d..df6c70e 100644 --- a/03_WordPress/wp-content/plugins/ifnex-bridge/includes/shortcodes.php +++ b/03_WordPress/wp-content/plugins/ifnex-bridge/includes/shortcodes.php @@ -1126,6 +1126,7 @@ function ifnex_icon($name, $size = 20) { 'truck' => '', 'check' => '', 'clock' => '', + 'bell' => '', ]; $path = $icons[$name] ?? $icons['dashboard']; @@ -1153,7 +1154,7 @@ function ifnex_customer_dashboard_shortcode($atts) { } $tab = sanitize_key($_GET['tab'] ?? 'dashboard'); - $allowed_tabs = ['dashboard', 'orders', 'new-order', 'wallet', 'transactions', 'tracking', 'profile']; + $allowed_tabs = ['dashboard', 'orders', 'new-order', 'wallet', 'transactions', 'notifications', 'tracking', 'profile']; if (!in_array($tab, $allowed_tabs)) $tab = 'dashboard'; $bridge = new IFNEX_User_Bridge(); @@ -1181,12 +1182,14 @@ function ifnex_customer_dashboard_shortcode($atts) { 'wallet' => ['icon' => 'wallet', 'label' => 'کیف پول'], 'transactions' => ['icon' => 'chart', 'label' => 'تراکنش‌ها'], 'tracking' => ['icon' => 'tracking', 'label' => 'رهگیری مرسوله'], + 'notifications' => ['icon' => 'bell', 'label' => 'اعلان‌ها'], 'profile' => ['icon' => 'user', 'label' => 'پروفایل'], ]; $tab_titles = [ 'dashboard' => 'داشبورد', 'orders' => 'سفارشات من', 'new-order' => 'ثبت سفارش جدید', - 'wallet' => 'کیف پول', 'transactions' => 'تراکنش‌ها', 'tracking' => 'رهگیری مرسوله', 'profile' => 'پروفایل', + 'wallet' => 'کیف پول', 'transactions' => 'تراکنش‌ها', 'notifications' => 'اعلان‌ها', + 'tracking' => 'رهگیری مرسوله', 'profile' => 'پروفایل', ]; ob_start(); @@ -1206,6 +1209,26 @@ function ifnex_customer_dashboard_shortcode($atts) { + + get_notifications($user_id, 1); + if (!is_wp_error($notif_result)) { + $unread_count = $notif_result['unread_count'] ?? 0; + } + ?> + $item): ?> + + + + 0): ?> + 9 ? '9+' : $unread_count; ?> + + + +
@@ -1301,6 +1324,34 @@ function ifnex_customer_dashboard_shortcode($atts) { + + get_notifications($user_id, 30); + if (is_wp_error($all_notifications)): + ?> +

خطا در دریافت اعلان‌ها.

+ +
+ +

اعلان جدیدی وجود ندارد.

+
+ +
+ diff --git a/03_WordPress/wp-content/plugins/ifnex-bridge/includes/user-bridge.php b/03_WordPress/wp-content/plugins/ifnex-bridge/includes/user-bridge.php index 4559d61..af25023 100644 --- a/03_WordPress/wp-content/plugins/ifnex-bridge/includes/user-bridge.php +++ b/03_WordPress/wp-content/plugins/ifnex-bridge/includes/user-bridge.php @@ -322,6 +322,29 @@ class IFNEX_User_Bridge { } } + /** + * دریافت نوتیفیکیشن‌های کاربر + */ + public function get_notifications($user_id, $per_page = 20) { + $result = $this->authenticated_request($user_id, '/customer/notifications', 'GET', array( + 'per_page' => $per_page, + )); + + if (is_wp_error($result)) { + return $result; + } + + return $result; + } + + /** + * علامت‌گذاری نوتیفیکیشن به عنوان خوانده‌شده + */ + public function mark_notification_read($user_id, $notification_id) { + $result = $this->authenticated_request($user_id, "/customer/notifications/{$notification_id}/read", 'POST'); + return $result; + } + // ══════════════════════════════════════════════════════════════ // AJAX Handler برای لغو سفارش // ══════════════════════════════════════════════════════════════