Show negative SMS wallet warning modal on admin page loads.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -212,11 +212,19 @@ watch(modalVisible, (open) => {
|
||||
if (open) showLabelHint.value = false
|
||||
})
|
||||
|
||||
function onOpenChargeFromWarning() {
|
||||
modalVisible.value = true
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (isCompactDesktop.value) startLabelHintLoop()
|
||||
window.addEventListener('sms-open-charge-modal', onOpenChargeFromWarning)
|
||||
})
|
||||
|
||||
onUnmounted(stopLabelHintTimers)
|
||||
onUnmounted(() => {
|
||||
stopLabelHintTimers()
|
||||
window.removeEventListener('sms-open-charge-modal', onOpenChargeFromWarning)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import SmsNegativeBalanceModal from '@/components/SmsNegativeBalanceModal.vue'
|
||||
import { useSmsWalletStore } from '@/store/smsWalletStore'
|
||||
|
||||
const store = useSmsWalletStore()
|
||||
|
||||
const visible = computed({
|
||||
get: () => store.visible && store.loaded && store.negativeWarningVisible,
|
||||
set: (value: boolean) => {
|
||||
if (!value) store.dismissNegativeWarning()
|
||||
}
|
||||
})
|
||||
|
||||
function openCharge() {
|
||||
// باز کردن مودال شارژ از ویجت هدر با رویداد سفارشی ساده
|
||||
window.dispatchEvent(new CustomEvent('sms-open-charge-modal'))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SmsNegativeBalanceModal
|
||||
v-model:visible="visible"
|
||||
:balance="store.balance"
|
||||
@charge="openCharge"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,115 @@
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '@/components/BasicModal.vue'
|
||||
import BaseButton from '@core/components/BaseButton'
|
||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
|
||||
defineProps<{
|
||||
visible: boolean
|
||||
balance: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:visible': [value: boolean]
|
||||
charge: []
|
||||
}>()
|
||||
|
||||
function closeModal() {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
function openCharge() {
|
||||
emit('charge')
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
function formatNumber(value: number) {
|
||||
return Number(value || 0).toLocaleString('fa-IR')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicModal
|
||||
:visible="visible"
|
||||
width="28rem"
|
||||
title="هشدار موجودی پیامک"
|
||||
:custom-footer="true"
|
||||
@close="closeModal"
|
||||
@update:visible="emit('update:visible', $event)"
|
||||
>
|
||||
<div class="sms-neg-modal">
|
||||
<div class="sms-neg-modal__banner">
|
||||
<Icon icon="vuesax-linear:warning-2" :size="22" class="sms-neg-modal__icon" />
|
||||
<div>
|
||||
<p class="sms-neg-modal__title">موجودی کیف پول پیامک منفی است</p>
|
||||
<p class="sms-neg-modal__text">
|
||||
تا زمان شارژ و مثبت شدن موجودی، این هشدار با هر بار ورود به صفحات ادمین نمایش داده میشود.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sms-neg-modal__balance">
|
||||
<span>موجودی فعلی</span>
|
||||
<strong>{{ formatNumber(balance) }} ریال</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<BaseButton @click="closeModal">بستن</BaseButton>
|
||||
<BaseButton type="primary" @click="openCharge">اطلاعات واریز / شارژ</BaseButton>
|
||||
</template>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
.sms-neg-modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.sms-neg-modal__banner {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.75rem;
|
||||
padding: 0.85rem 1rem;
|
||||
border-radius: 0.85rem;
|
||||
border: 1px solid #fecaca;
|
||||
background: linear-gradient(135deg, #fef2f2, #fff);
|
||||
}
|
||||
|
||||
.sms-neg-modal__icon {
|
||||
color: #dc2626;
|
||||
flex-shrink: 0;
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
|
||||
.sms-neg-modal__title {
|
||||
margin: 0 0 0.35rem;
|
||||
font-weight: 700;
|
||||
color: #b91c1c;
|
||||
}
|
||||
|
||||
.sms-neg-modal__text {
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.8;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.sms-neg-modal__balance {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.75rem;
|
||||
background: var(--admin-bg-muted);
|
||||
border: 1px solid var(--admin-border);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.sms-neg-modal__balance strong {
|
||||
color: #b91c1c;
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -90,6 +90,7 @@
|
||||
</ALayout>
|
||||
<BasicMobileBottomNav v-if="isMobile" />
|
||||
<BaseSettings />
|
||||
<SmsNegativeBalanceHost />
|
||||
</ALayout>
|
||||
</template>
|
||||
|
||||
@@ -102,6 +103,7 @@ import { isMobile } from '@core/utils/is'
|
||||
import BaseSettings from '@core/layouts/BaseSettings.vue'
|
||||
import BasicMobileHeader from '@/components/BasicMobileHeader.vue'
|
||||
import BasicMobileBottomNav from '@/components/BasicMobileBottomNav.vue'
|
||||
import SmsNegativeBalanceHost from '@/components/SmsNegativeBalanceHost.vue'
|
||||
const { prefixCls } = usePrefix('basic-layout')
|
||||
const layoutStore = useLayoutStore()
|
||||
</script>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { getSmsWalletSummary, type SmsDepositInfo } from '@/api/smsPanel'
|
||||
import { useUserStore } from '@/store/userStore'
|
||||
|
||||
@@ -18,6 +19,8 @@ export const useSmsWalletStore = defineStore('smsWallet', () => {
|
||||
const deposit = ref<SmsDepositInfo>({ ...EMPTY_DEPOSIT })
|
||||
const loaded = ref(false)
|
||||
const loading = ref(false)
|
||||
/** هشدار موجودی منفی — با هر refresh اگر هنوز منفی باشد دوباره باز میشود */
|
||||
const negativeWarningVisible = ref(false)
|
||||
|
||||
/** ویجت فقط وقتی billing/پنل پیامک فعال است نمایش داده میشود. */
|
||||
const visible = computed(() => userStore.smsBillingEnabled)
|
||||
@@ -25,6 +28,7 @@ export const useSmsWalletStore = defineStore('smsWallet', () => {
|
||||
async function refresh() {
|
||||
if (!visible.value) {
|
||||
loaded.value = false
|
||||
negativeWarningVisible.value = false
|
||||
return
|
||||
}
|
||||
if (loading.value) return
|
||||
@@ -36,6 +40,7 @@ export const useSmsWalletStore = defineStore('smsWallet', () => {
|
||||
isBlocked.value = res.is_blocked
|
||||
deposit.value = res.deposit ?? { ...EMPTY_DEPOSIT }
|
||||
loaded.value = true
|
||||
negativeWarningVisible.value = res.balance < 0
|
||||
} catch {
|
||||
// خطای موجودی نباید مزاحم کاربر شود؛ ویجت در صورت نبود داده مخفی میماند
|
||||
} finally {
|
||||
@@ -43,6 +48,10 @@ export const useSmsWalletStore = defineStore('smsWallet', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function dismissNegativeWarning() {
|
||||
negativeWarningVisible.value = false
|
||||
}
|
||||
|
||||
return {
|
||||
balance,
|
||||
isBlocked,
|
||||
@@ -50,6 +59,8 @@ export const useSmsWalletStore = defineStore('smsWallet', () => {
|
||||
loaded,
|
||||
loading,
|
||||
visible,
|
||||
refresh
|
||||
negativeWarningVisible,
|
||||
refresh,
|
||||
dismissNegativeWarning
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user