From 1c3c494a434592e1d803e266780cfb8abd98c9ae Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Sun, 9 Aug 2026 14:32:09 +0200 Subject: [PATCH] Improve order detail UX, confirm check actions, and fix notification deep links. Normalize inbox /orders/:id links, open related admin pages on click, and keep Jalali dates consistent. Co-authored-by: Cursor --- src/assets/styles/responsive.css | 84 ++-- src/components/layout/AdminHeader.vue | 40 +- src/components/ui/BaseModal.vue | 31 +- src/composables/useOrdersPage.ts | 45 ++- src/data/mockData.ts | 26 +- src/router/index.ts | 9 + src/types/index.ts | 3 + src/utils/format.ts | 56 ++- src/utils/inboxLinks.ts | 112 ++++++ src/views/checks/CheckManagementView.vue | 60 ++- src/views/orders/OrderPricingView.vue | 15 +- .../orders/components/CompactOrdersPage.vue | 84 +++- .../orders/components/OrderDetailContent.vue | 369 ++++++++++++------ src/views/shipping/ShippingView.vue | 15 +- 14 files changed, 737 insertions(+), 212 deletions(-) create mode 100644 src/utils/inboxLinks.ts diff --git a/src/assets/styles/responsive.css b/src/assets/styles/responsive.css index e444aaa..ebef51c 100644 --- a/src/assets/styles/responsive.css +++ b/src/assets/styles/responsive.css @@ -297,49 +297,22 @@ font-weight: 700; } -/* Responsive overrides for shared admin components */ +/* Tablet / compact desktop: keep multi-column layouts usable in modals */ @media (max-width: 1279px) { .admin-shell__content { padding: var(--page-padding); } - .admin-page-header { - flex-direction: column; - align-items: stretch; - } - - .admin-page-header .admin-btn, - .admin-page-header .admin-action-group { - width: 100%; - } - - .admin-page-header .admin-action-group { - flex-wrap: wrap; - } - - .admin-page-header .admin-action-group .admin-btn { - flex: 1; - min-width: fit-content; - } - .admin-summary-grid { grid-template-columns: repeat(2, 1fr); } .admin-form-grid { - grid-template-columns: 1fr; + grid-template-columns: repeat(2, 1fr); } .admin-info-grid { - grid-template-columns: 1fr; - } - - .admin-footer-actions { - flex-direction: column; - } - - .admin-footer-actions .admin-btn { - width: 100%; + grid-template-columns: repeat(2, 1fr); } .admin-pagination { @@ -352,17 +325,53 @@ justify-content: center; flex-wrap: wrap; } + + .admin-tab { + padding: 10px 12px; + font-size: 0.8125rem; + } + + .admin-page-header .admin-action-group { + flex-wrap: wrap; + gap: 8px; + } } +/* Phone only: stack to single column / action sheet */ @media (max-width: 767px) { :root { --header-height: 60px; } - .admin-summary-grid { + .admin-page-header { + flex-direction: column; + align-items: stretch; + } + + .admin-page-header .admin-btn, + .admin-page-header .admin-action-group { + width: 100%; + } + + .admin-page-header .admin-action-group .admin-btn { + flex: 1; + min-width: fit-content; + } + + .admin-summary-grid, + .admin-form-grid, + .admin-info-grid { grid-template-columns: 1fr; } + .admin-footer-actions { + flex-direction: column; + } + + .admin-footer-actions .admin-btn { + width: 100%; + } + .admin-form__row { grid-template-columns: 1fr; } @@ -397,16 +406,3 @@ width: 100%; } } - -@media (max-width: 1279px) { - .admin-tab { - padding: 10px 12px; - font-size: 0.8125rem; - } -} - -@media (min-width: 768px) and (max-width: 1279px) { - .admin-form-grid { - grid-template-columns: repeat(2, 1fr); - } -} diff --git a/src/components/layout/AdminHeader.vue b/src/components/layout/AdminHeader.vue index 39f335c..8d06128 100644 --- a/src/components/layout/AdminHeader.vue +++ b/src/components/layout/AdminHeader.vue @@ -5,7 +5,9 @@ import { onClickOutside, useEventListener } from '@vueuse/core' import AdminIcon from '@/components/icons/AdminIcon.vue' import BasicIcon from '@/components/BasicPacks/BasicIcon.vue' import { dashboardApi, notificationsApi } from '@/services/api' +import { adminNotifications, internalMessages } from '@/data/mockData' import { formatDateTime } from '@/utils/format' +import { resolveAdminInboxLink } from '@/utils/inboxLinks' import { useAuthStore } from '@/stores/auth' import { useThemeStore, type ThemePreference } from '@/stores/theme' import type { AdminNotification, InternalMessage } from '@/types' @@ -26,8 +28,8 @@ const theme = useThemeStore() const openPanel = ref(null) const actionsRef = ref(null) -const messageList = ref([]) -const notificationList = ref([]) +const messageList = ref(internalMessages.map((m) => ({ ...m }))) +const notificationList = ref(adminNotifications.map((n) => ({ ...n }))) const unreadMessages = computed(() => messageList.value.filter((m) => !m.isRead).length) const unreadNotifications = computed(() => notificationList.value.filter((n) => !n.isRead).length) @@ -53,7 +55,7 @@ void dashboardApi if (data.notifications?.length) notificationList.value = data.notifications }) .catch(() => { - /* keep mock fallback */ + /* keep mock fallback seeded above */ }) onClickOutside(actionsRef, () => { @@ -103,12 +105,34 @@ function markAllNotificationsRead() { }) } +function navigateInboxTarget(target: string | null) { + closePanel() + if (!target) return + void router.push(target) +} + +function openMessage(message: InternalMessage) { + markMessageRead(message) + navigateInboxTarget( + resolveAdminInboxLink({ + link: message.link, + orderId: message.orderId, + title: message.subject, + body: message.preview, + }), + ) +} + function openNotification(notification: AdminNotification) { markNotificationRead(notification) - closePanel() - if (notification.link) { - router.push(notification.link) - } + navigateInboxTarget( + resolveAdminInboxLink({ + link: notification.link, + orderId: notification.orderId, + title: notification.title, + body: notification.body, + }), + ) } function selectTheme(value: ThemePreference) { @@ -176,7 +200,7 @@ function selectTheme(value: ThemePreference) { class="admin-header__panel-item" :class="{ unread: !message.isRead }" > -