fix pargar mande

This commit is contained in:
2026-07-25 12:13:30 +03:30
parent 9319906737
commit 7cd3fac28b
20 changed files with 608 additions and 41 deletions
+24
View File
@@ -0,0 +1,24 @@
import useAxios from '@/utils/useAxios'
export type AppNotificationSeverity = 'info' | 'success' | 'warning' | 'danger'
export interface CustomerAppNotification {
id: number
title: string
body: string
severity: AppNotificationSeverity
created_at?: string
is_read: boolean
}
export const getAppNotifications = async () =>
await useAxios.get<CustomerAppNotification[]>(`/customer/app_notifications`)
export const getAppNotificationsUnreadCount = async () =>
await useAxios.get<{ unread_count: number }>(`/customer/app_notifications/unread-count`)
export const markAppNotificationRead = async (id: number) =>
await useAxios.post(`/customer/app_notifications/${id}/read`)
export const markAllAppNotificationsRead = async () =>
await useAxios.post(`/customer/app_notifications/read-all`)
+22
View File
@@ -55,6 +55,28 @@ export function setupRouterGuards() {
clearFingerTimeout()
setFingerTimeOut(to)
if (to.name === 'notifyTrigger' && getToken()) {
const { useSettingsStore } = await import('@/store/settingsStore')
const settingsStore = useSettingsStore()
if (!settingsStore.loaded) {
await settingsStore.fetchSettings()
}
if (!settingsStore.isSettingTruthy('has_page_price_trigger')) {
return next({ name: (from.name as string) || 'user' })
}
}
if (to.name === 'appNotifications' && getToken()) {
const { useSettingsStore } = await import('@/store/settingsStore')
const settingsStore = useSettingsStore()
if (!settingsStore.loaded) {
await settingsStore.fetchSettings()
}
if (!settingsStore.isSettingTruthy('has_page_notification')) {
return next({ name: (from.name as string) || 'home' })
}
}
if (isFirst) {
isFirst = false
@@ -0,0 +1,61 @@
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { getAppNotificationsUnreadCount } from '@/api/appNotifications'
import { useSettingsStore } from '@/store/settingsStore'
import { isToken } from '@/utils'
const unreadCount = ref(0)
let pollTimer: ReturnType<typeof setInterval> | null = null
let started = false
async function refreshUnreadCount() {
const settingsStore = useSettingsStore()
if (!isToken() || !settingsStore.isSettingTruthy('has_page_notification')) {
unreadCount.value = 0
return
}
try {
const data = await getAppNotificationsUnreadCount()
unreadCount.value = Number(data?.unread_count ?? 0) || 0
} catch {
// silent — badge optional
}
}
function clearUnreadLocally() {
unreadCount.value = 0
}
export function useAppNotificationBadge() {
const settingsStore = useSettingsStore()
const enabled = computed(() => settingsStore.isSettingTruthy('has_page_notification'))
onMounted(() => {
if (started) {
void refreshUnreadCount()
return
}
started = true
void refreshUnreadCount()
pollTimer = setInterval(() => {
void refreshUnreadCount()
}, 60000)
})
onUnmounted(() => {
// keep poll for other mounted headers; only clear if needed later
})
watch(enabled, (on) => {
if (!on) unreadCount.value = 0
else void refreshUnreadCount()
})
return {
enabled,
unreadCount,
refreshUnreadCount,
clearUnreadLocally,
}
}
export { refreshUnreadCount, clearUnreadLocally }
+9 -1
View File
@@ -43,6 +43,7 @@ import logoFull from '@/assets/img/logo_full_.png'
import { isToken } from '@/utils'
import { useCartStore } from '@/store/cartStore'
import { useTrackingSystemsFeature } from '@/composables/useTrackingSystemsFeature'
import { useSettingsStore } from '@/store/settingsStore'
import { getPrimaryNavItems, getSecondaryNavItems } from '../config/navigation'
import { useAppNavigation } from '../composables/useAppNavigation'
import DesktopNavItem from './DesktopNavItem.vue'
@@ -51,13 +52,20 @@ const cartStore = useCartStore()
const authenticated = computed(() => isToken())
const navLogo = logoFull
const { trackingSystemsEnabled } = useTrackingSystemsFeature()
const settingsStore = useSettingsStore()
const primaryItems = computed(() => getPrimaryNavItems(authenticated.value))
/** «لیست دریافتی‌ها» فقط در موبایل نمایش داده می‌شود */
const DESKTOP_HIDDEN_NAV_IDS = ['list']
const secondaryItems = computed(() =>
getSecondaryNavItems(authenticated.value, {
includeRecoverySites: trackingSystemsEnabled.value,
}).filter((item) => !DESKTOP_HIDDEN_NAV_IDS.includes(item.id)),
}).filter((item) => {
if (DESKTOP_HIDDEN_NAV_IDS.includes(item.id)) return false
if (item.id === 'notifyTrigger') {
return settingsStore.isSettingTruthy('has_page_price_trigger')
}
return true
}),
)
const cartCount = computed(() => cartStore.itemCount || 0)
+6 -1
View File
@@ -38,7 +38,7 @@
</div>
</BasicButton>
<BasicButton
v-if="authenticated"
v-if="authenticated && priceTriggerEnabled"
icon-size="16"
class="!font-bold w-15rem"
@click="go('notifyTrigger')"
@@ -120,6 +120,7 @@ import { computed } from 'vue'
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import { useTrackingSystemsFeature } from '@/composables/useTrackingSystemsFeature'
import { useSettingsStore } from '@/store/settingsStore'
import { isToken } from '@/utils'
defineProps<{
@@ -133,6 +134,10 @@ const emit = defineEmits<{
const authenticated = computed(() => isToken())
const { trackingSystemsEnabled } = useTrackingSystemsFeature()
const settingsStore = useSettingsStore()
const priceTriggerEnabled = computed(() =>
settingsStore.isSettingTruthy('has_page_price_trigger'),
)
function go(routeName: string) {
emit('navigate', routeName)
+5
View File
@@ -75,6 +75,11 @@ const router = createRouter({
name: 'notifyTrigger',
component: () => import('@/views/base/priceTrigger/index.vue')
},
{
path: 'appNotifications',
name: 'appNotifications',
component: () => import('@/views/base/appNotifications/index.vue')
},
{
path: 'transfer',
name: 'transfer',
+13
View File
@@ -24,6 +24,18 @@ export const useSettingsStore = defineStore('settings', () => {
return item?.value ?? null
}
function isSettingTruthy(key: string) {
const value = getSettingByKey(key)
if (value == null) {
return false
}
if (value === true) {
return true
}
const normalized = String(value).trim().toLowerCase()
return normalized === 'true' || normalized === '1' || normalized === 'yes'
}
function mergeSettings(items?: AppSetting[] | null) {
if (!items?.length) {
return
@@ -80,6 +92,7 @@ export const useSettingsStore = defineStore('settings', () => {
fetchSettings,
mergeSettings,
getSettingByKey,
isSettingTruthy,
metalTypeSettingValue,
metalTypeLabel,
meltedGoldLabel,
@@ -0,0 +1,94 @@
import { computed, inject, onMounted, provide, ref, type InjectionKey } from 'vue'
import {
getAppNotifications,
markAllAppNotificationsRead,
markAppNotificationRead,
type CustomerAppNotification,
} from '@/api/appNotifications'
import { useSettingsStore } from '@/store/settingsStore'
export interface AppNotificationsPageContext {
loading: ReturnType<typeof ref<boolean>>
items: ReturnType<typeof ref<CustomerAppNotification[]>>
enabled: ReturnType<typeof computed<boolean>>
refresh: () => Promise<void>
markRead: (id: number) => Promise<void>
markAllRead: () => Promise<void>
}
export const APP_NOTIFICATIONS_PAGE_KEY: InjectionKey<AppNotificationsPageContext> =
Symbol('appNotificationsPage')
export function useAppNotificationsPage() {
const settingsStore = useSettingsStore()
const loading = ref(false)
const items = ref<CustomerAppNotification[]>([])
const enabled = computed(() => settingsStore.isSettingTruthy('has_page_notification'))
async function refresh() {
if (!enabled.value) {
items.value = []
return
}
loading.value = true
try {
const data = await getAppNotifications()
items.value = Array.isArray(data) ? data : []
} catch (e) {
console.error(e)
items.value = []
} finally {
loading.value = false
}
}
async function markRead(id: number) {
try {
await markAppNotificationRead(id)
const row = items.value.find((item) => item.id === id)
if (row) row.is_read = true
} catch (e) {
console.error(e)
}
}
async function markAllRead() {
try {
await markAllAppNotificationsRead()
items.value = items.value.map((item) => ({ ...item, is_read: true }))
const { clearUnreadLocally } = await import('@/composables/useAppNotificationBadge')
clearUnreadLocally()
} catch (e) {
console.error(e)
}
}
onMounted(() => {
void refresh().then(() => {
const hasUnread = items.value.some((item) => !item.is_read)
if (hasUnread) {
void markAllRead()
}
})
})
const ctx: AppNotificationsPageContext = {
loading,
items,
enabled,
refresh,
markRead,
markAllRead,
}
provide(APP_NOTIFICATIONS_PAGE_KEY, ctx)
return ctx
}
export function useAppNotificationsPageContext() {
const ctx = inject(APP_NOTIFICATIONS_PAGE_KEY)
if (!ctx) {
throw new Error('useAppNotificationsPageContext must be used within useAppNotificationsPage')
}
return ctx
}
@@ -0,0 +1,88 @@
<template>
<div class="dapp-notif">
<header class="dapp-notif__top">
<div>
<p class="dapp-notif__eyebrow">اعلان‌ها</p>
<h1 class="dapp-notif__title">پیام‌های مدیریت</h1>
</div>
</header>
<a-spin :spinning="loading">
<div v-if="!items.length" class="dapp-notif__empty">
<BasicIcon icon="vuesax-linear:notification-bing" size="36" />
<p>اعلانی برای نمایش نیست.</p>
</div>
<div v-else class="dapp-notif__list">
<article
v-for="item in items"
:key="item.id"
class="dapp-notif__card"
:class="`dapp-notif__card--${item.severity}`"
@click="markRead(item.id)"
>
<div class="flex items-start justify-between gap-3">
<h3 class="m-0 text-base font-bold">{{ item.title }}</h3>
<span class="dapp-notif__tag">{{ severityLabel(item.severity) }}</span>
</div>
<p class="m-0 mt-2 text-sm text-gray-600 whitespace-pre-wrap">{{ item.body }}</p>
</article>
</div>
</a-spin>
</div>
</template>
<script setup lang="ts">
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import { useAppNotificationsPageContext } from '../composables/useAppNotificationsPage'
const { loading, items, markRead } = useAppNotificationsPageContext()
function severityLabel(severity: string) {
switch (severity) {
case 'success':
return 'موفق'
case 'warning':
return 'هشدار'
case 'danger':
return 'مهم'
default:
return 'اطلاعات'
}
}
</script>
<style scoped>
.dapp-notif {
@apply p-6 min-h-full;
}
.dapp-notif__eyebrow {
@apply m-0 text-xs text-gray-500;
}
.dapp-notif__title {
@apply m-0 mt-1 text-xl font-bold;
}
.dapp-notif__empty {
@apply mt-10 flex flex-col items-center gap-2 text-gray-500;
}
.dapp-notif__list {
@apply mt-6 flex flex-col gap-3 max-w-3xl;
}
.dapp-notif__card {
@apply rounded-xl bg-white border border-gray-100 p-4 cursor-pointer;
}
.dapp-notif__tag {
@apply shrink-0 rounded-md px-2 py-0.5 text-xs font-bold bg-gray-50 text-gray-700;
}
.dapp-notif__card--info .dapp-notif__tag {
@apply bg-blue-50 text-blue-700;
}
.dapp-notif__card--success .dapp-notif__tag {
@apply bg-green-50 text-green-700;
}
.dapp-notif__card--warning .dapp-notif__tag {
@apply bg-orange-50 text-orange-700;
}
.dapp-notif__card--danger .dapp-notif__tag {
@apply bg-red-50 text-red-700;
}
</style>
+23
View File
@@ -0,0 +1,23 @@
<template>
<div class="app-notifications-page-root">
<DesktopAppNotificationsView v-show="isDesktop" />
<MobileAppNotificationsView v-show="!isDesktop" />
</div>
</template>
<script lang="ts" setup>
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
import { useAppNotificationsPage } from './composables/useAppNotificationsPage'
import DesktopAppNotificationsView from './desktop/DesktopAppNotificationsView.vue'
import MobileAppNotificationsView from './mobile/MobileAppNotificationsView.vue'
const isDesktop = useDesktopBreakpoint()
useAppNotificationsPage()
</script>
<style scoped>
.app-notifications-page-root {
min-height: 100%;
height: 100%;
}
</style>
@@ -0,0 +1,86 @@
<template>
<div class="app-notif-page">
<MobilePageHeader title="اعلان‌ها" show-back />
<div class="app-notif-page__body">
<a-spin :spinning="loading">
<div v-if="!items.length" class="app-notif-page__empty">
<BasicIcon icon="vuesax-linear:notification-bing" size="40" class="text-gray-400" />
<p class="m-0 mt-3 font-bold text-gray-700">اعلانی نیست</p>
<p class="m-0 mt-1 text-sm text-gray-500">هنوز اعلانی از طرف مدیریت ارسال نشده است.</p>
</div>
<div v-else class="flex flex-col gap-3">
<article
v-for="item in items"
:key="item.id"
class="app-notif-card"
:class="[
`app-notif-card--${item.severity}`,
{ 'app-notif-card--unread': !item.is_read },
]"
@click="markRead(item.id)"
>
<div class="flex items-start justify-between gap-2">
<h3 class="m-0 text-sm font-bold text-gray-900">{{ item.title }}</h3>
<span class="app-notif-card__badge">{{ severityLabel(item.severity) }}</span>
</div>
<p class="m-0 mt-2 text-sm text-gray-600 whitespace-pre-wrap">{{ item.body }}</p>
</article>
</div>
</a-spin>
</div>
</div>
</template>
<script setup lang="ts">
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import MobilePageHeader from '@/layouts/components/MobilePageHeader.vue'
import { useAppNotificationsPageContext } from '../composables/useAppNotificationsPage'
const { loading, items, markRead } = useAppNotificationsPageContext()
function severityLabel(severity: string) {
switch (severity) {
case 'success':
return 'موفق'
case 'warning':
return 'هشدار'
case 'danger':
return 'مهم'
default:
return 'اطلاعات'
}
}
</script>
<style scoped>
.app-notif-page {
@apply min-h-full flex flex-col bg-gray-50;
}
.app-notif-page__body {
@apply px-4 pb-8 pt-2;
}
.app-notif-page__empty {
@apply flex flex-col items-center justify-center rounded-xl bg-white p-8 text-center;
}
.app-notif-card {
@apply rounded-xl bg-white p-3 border border-gray-100;
}
.app-notif-card--unread {
@apply border-gray-200 shadow-sm;
}
.app-notif-card__badge {
@apply shrink-0 rounded-md px-2 py-0.5 text-xs font-bold;
}
.app-notif-card--info .app-notif-card__badge {
@apply bg-blue-50 text-blue-700;
}
.app-notif-card--success .app-notif-card__badge {
@apply bg-green-50 text-green-700;
}
.app-notif-card--warning .app-notif-card__badge {
@apply bg-orange-50 text-orange-700;
}
.app-notif-card--danger .app-notif-card__badge {
@apply bg-red-50 text-red-700;
}
</style>
+2 -2
View File
@@ -13,7 +13,7 @@
<div class="w-full mr-3">
<div class="flex justify-between w-full">
<div>{{ item.title }}</div>
<div>{{ toJalaliNotime(item.expire_at) }}</div>
<div>{{ toJalali(item.expire_at) }}</div>
</div>
<div class="flex justify-between mt-2">
<div
@@ -63,7 +63,7 @@ import { computed, ref } from 'vue'
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
import type { Transaction } from '@/models/transaction'
import { formatGoldAmount } from '@/utils/usePrice'
import { toJalaliNotime } from '@/utils/useDateTime'
import { toJalali } from '@/utils/useDateTime'
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
import TransactionDetailContent from './TransactionDetailContent.vue'
@@ -27,11 +27,7 @@
</div>
<div class="flex justify-between mb-3">
<div class="text-black">تاریخ:</div>
<div>{{ toJalaliNotime(item.expire_at) }}</div>
</div>
<div class="flex justify-between mb-3">
<div class="text-black">زمان:</div>
<div>{{ toTime(item.expire_at) }}</div>
<div>{{ toJalali(item.expire_at) }}</div>
</div>
</div>
</template>
@@ -39,7 +35,7 @@
<script lang="ts" setup>
import type { Transaction } from '@/models/transaction'
import { formatGoldAmount } from '@/utils/usePrice'
import { toJalaliNotime, toTime } from '@/utils/useDateTime'
import { toJalali } from '@/utils/useDateTime'
defineProps<{
item: Transaction
+62 -8
View File
@@ -14,14 +14,30 @@
</div>
</div>
<button
type="button"
class="mhome-header-btn mhome-header-btn--logout"
@click="$emit('logout')"
>
<Icon icon="vuesax-linear:logout" size="18" />
<span>خروج</span>
</button>
<div class="flex items-center gap-2">
<button
v-if="notificationEnabled"
type="button"
class="mhome-header-btn mhome-header-btn--notify"
aria-label="اعلان"
@click.stop="goNotifications"
>
<span class="mhome-header-btn__icon-wrap">
<Icon icon="vuesax-linear:notification-bing" size="18" />
<span v-if="unreadCount > 0" class="mhome-header-btn__badge">
{{ unreadCount > 99 ? '99+' : unreadCount }}
</span>
</span>
</button>
<button
type="button"
class="mhome-header-btn mhome-header-btn--logout"
@click="$emit('logout')"
>
<Icon icon="vuesax-linear:logout" size="18" />
<span>خروج</span>
</button>
</div>
</div>
</div>
</template>
@@ -30,6 +46,7 @@
import { nextTick, onActivated, onMounted, onUnmounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useUserStore } from '@/store/userStore'
import { useAppNotificationBadge } from '@/composables/useAppNotificationBadge'
import router from '@/router'
import Icon from '@/components/BasicPacks/BasicIcon.vue'
@@ -38,6 +55,16 @@ const isHeaderScrolled = ref(false)
const route = useRoute()
const userStore = useUserStore()
const {
enabled: notificationEnabled,
unreadCount,
clearUnreadLocally,
} = useAppNotificationBadge()
function goNotifications() {
clearUnreadLocally()
void router.push({ name: 'appNotifications' })
}
let intersectionObserver: IntersectionObserver | null = null
let scrollTarget: HTMLElement | Window | null = null
@@ -205,4 +232,31 @@ defineEmits<{
border-color: #fecaca;
background: #fef2f2;
}
.mhome-header-btn--notify {
color: #0a1b37;
border-color: #e5e7eb;
background: #fff;
}
.mhome-header-btn__icon-wrap {
position: relative;
display: inline-flex;
}
.mhome-header-btn__badge {
position: absolute;
top: -8px;
left: -8px;
min-width: 16px;
height: 16px;
padding: 0 4px;
border-radius: 999px;
background: #dc2626;
color: #fff;
font-size: 10px;
font-weight: 700;
line-height: 16px;
text-align: center;
}
</style>
@@ -10,6 +10,21 @@
<BasicIcon icon="vuesax-linear:user" size="16" />
<span>حساب کاربری</span>
</button>
<button
v-if="notificationEnabled"
type="button"
class="dhome-btn-ghost"
aria-label="اعلان"
@click="goNotifications"
>
<span class="dhome-notify-wrap">
<BasicIcon icon="vuesax-linear:notification-bing" size="16" />
<span v-if="unreadCount > 0" class="dhome-notify-badge">
{{ unreadCount > 99 ? '99+' : unreadCount }}
</span>
</span>
<span>اعلان</span>
</button>
<button type="button" class="dhome-btn-ghost" @click="$emit('logout')">
<BasicIcon icon="vuesax-linear:logout" size="16" />
<span>خروج</span>
@@ -21,6 +36,7 @@
<script lang="ts" setup>
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import { useUserStore } from '@/store/userStore'
import { useAppNotificationBadge } from '@/composables/useAppNotificationBadge'
import router from '@/router'
defineEmits<{
@@ -28,4 +44,36 @@ defineEmits<{
}>()
const userStore = useUserStore()
const {
enabled: notificationEnabled,
unreadCount,
clearUnreadLocally,
} = useAppNotificationBadge()
function goNotifications() {
clearUnreadLocally()
void router.push({ name: 'appNotifications' })
}
</script>
<style scoped>
.dhome-notify-wrap {
position: relative;
display: inline-flex;
}
.dhome-notify-badge {
position: absolute;
top: -8px;
left: -8px;
min-width: 16px;
height: 16px;
padding: 0 4px;
border-radius: 999px;
background: #dc2626;
color: #fff;
font-size: 10px;
font-weight: 700;
line-height: 16px;
text-align: center;
}
</style>
@@ -10,6 +10,21 @@
<BasicIcon icon="vuesax-linear:user" size="16" />
<span>حساب کاربری</span>
</button>
<button
v-if="notificationEnabled"
type="button"
class="dhome-btn-ghost"
aria-label="اعلان"
@click="goNotifications"
>
<span class="dhome-notify-wrap">
<BasicIcon icon="vuesax-linear:notification-bing" size="16" />
<span v-if="unreadCount > 0" class="dhome-notify-badge">
{{ unreadCount > 99 ? '99+' : unreadCount }}
</span>
</span>
<span>اعلان</span>
</button>
<button
v-if="showLogout"
type="button"
@@ -26,6 +41,7 @@
<script lang="ts" setup>
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import { useUserStore } from '@/store/userStore'
import { useAppNotificationBadge } from '@/composables/useAppNotificationBadge'
import router from '@/router'
withDefaults(
@@ -40,4 +56,36 @@ defineEmits<{
}>()
const userStore = useUserStore()
const {
enabled: notificationEnabled,
unreadCount,
clearUnreadLocally,
} = useAppNotificationBadge()
function goNotifications() {
clearUnreadLocally()
void router.push({ name: 'appNotifications' })
}
</script>
<style scoped>
.dhome-notify-wrap {
position: relative;
display: inline-flex;
}
.dhome-notify-badge {
position: absolute;
top: -8px;
left: -8px;
min-width: 16px;
height: 16px;
padding: 0 4px;
border-radius: 999px;
background: #dc2626;
color: #fff;
font-size: 10px;
font-weight: 700;
line-height: 16px;
text-align: center;
}
</style>
@@ -109,11 +109,7 @@
</div>
<div :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">تاریخ:</div>
<div :class="variant === 'desktop' ? 'dtxn-detail__value' : ''">{{ toJalaliNotime(item.expire_at) }}</div>
</div>
<div :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">زمان:</div>
<div :class="variant === 'desktop' ? 'dtxn-detail__value' : ''">{{ toTime(item.expire_at) }}</div>
<div :class="variant === 'desktop' ? 'dtxn-detail__value' : ''">{{ toJalali(item.expire_at) }}</div>
</div>
<div v-if="item.eaj" :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">مهلت ارسال فیش:</div>
@@ -130,7 +126,7 @@ import {
usePriceWithoutType,
} from '@/utils/usePrice'
import type { Transaction } from '@/models/transaction'
import { toJalaliNotime, toTime } from '@/utils/useDateTime'
import { toJalali } from '@/utils/useDateTime'
const props = withDefaults(
defineProps<{
@@ -13,6 +13,7 @@ import { message } from 'ant-design-vue'
import { updateMe, updatePass } from '@/api/me'
import { useUserStore } from '@/store/userStore'
import { useTrackingSystemsFeature } from '@/composables/useTrackingSystemsFeature'
import { useSettingsStore } from '@/store/settingsStore'
export interface UserMenuAction {
id: string
@@ -62,6 +63,7 @@ export function useUserPage() {
const editPassVisible = ref(false)
const editPasswordVisible = ref(false)
const { trackingSystemsEnabled } = useTrackingSystemsFeature()
const settingsStore = useSettingsStore()
const isLegal = computed(() => {
const result = { title: '', color: '', icon: '' }
@@ -97,7 +99,7 @@ export function useUserPage() {
label: 'هشدار قیمت',
icon: 'vuesax-linear:bill',
onClick: () => router.push({ name: 'notifyTrigger' }),
visible: true,
visible: settingsStore.isSettingTruthy('has_page_price_trigger'),
},
{
id: 'about',
@@ -87,6 +87,7 @@
</div>
</BasicButton>-->
<BasicButton
v-if="priceTriggerEnabled"
class="w-full mt-2"
size="large"
@click="$router.push({ name: 'notifyTrigger' })"
@@ -226,8 +227,9 @@ import DialogVant from '@/components/DialogVant.vue'
import { useWalletStore } from '@/store/walletStore'
import Icon from '@/components/BasicPacks/BasicIcon.vue'
import { useWindowScroll } from '@vueuse/core/index'
import { onMounted, ref } from 'vue'
import { onMounted, computed, ref } from 'vue'
import { useTrackingSystemsFeature } from '@/composables/useTrackingSystemsFeature'
import { useSettingsStore } from '@/store/settingsStore'
import { useUserStore } from '@/store/userStore'
import { useUserPageContext } from '../composables/useUserPage'
import MobilePageHeader from '@/layouts/components/MobilePageHeader.vue'
@@ -238,6 +240,10 @@ const showLogoutConfirm = ref<boolean>()
const logoutLoading = ref<boolean>(false)
const { y } = useWindowScroll()
const { trackingSystemsEnabled } = useTrackingSystemsFeature()
const settingsStore = useSettingsStore()
const priceTriggerEnabled = computed(() =>
settingsStore.isSettingTruthy('has_page_price_trigger'),
)
const { editPassVisible, editPasswordVisible, copyCode, shareCode } = useUserPageContext()
+3 -15
View File
@@ -20,7 +20,7 @@
<div class="w-full mr-3">
<div class="flex justify-between w-full">
<div>{{ item.type_str }}</div>
<div>{{ toJalaliNotime(item.created_at) }}</div>
<div>{{ toJalali(item.created_at) }}</div>
</div>
<div class="flex justify-between mt-2">
<div :class="item.gold >= 0? 'text-green-600':'text-red-600'" class="text-gray-500 text-xs number-ltr">
@@ -111,20 +111,8 @@
</div>
<div class="flex justify-between mb-3">
<div class="text-black">تاریخ:</div>
<div>{{ toJalaliNotime(item.expire_at) }}</div>
<div>{{ toJalali(item.expire_at) }}</div>
</div>
<div class="flex justify-between mb-3">
<div class="text-black">زمان:</div>
<div>{{ toTime(item.expire_at) }}</div>
</div>
<!-- <div class="flex justify-between mb-3">
<div class="text-black">وضعیت معامله:</div>
<div class="flex text-xs items-center">
<ATag class="!py-1 !px-6 !ml-0" color="orange">
معاملات باز
</ATag>
</div>
</div>-->
<div v-if="item.eaj" class="flex justify-between mb-3">
<div class="text-black">مهلت ارسال فیش:</div>
<div>{{ item.eaj }}</div>
@@ -143,7 +131,7 @@ import BasicActionSheet from "@/components/BasicPacks/BasicActionSheet.vue";
import {computed, ref} from "vue";
import BasicButton from "@/components/BasicPacks/BasicButton.vue";
import type {Transaction} from "@/models/transaction";
import {toJalaliNotime, toJalaliOutOfUTC, toTime} from "../../../../utils/useDateTime";
import {toJalali, toJalaliOutOfUTC} from "../../../../utils/useDateTime";
const infoVisible = ref<boolean>(false)