Unify store-closed messaging when the market is closed or has no quote.
Treat missing quotes as closed across home and products, show only the admin closed_message as hint, and block trading with consistent notices. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Vendored
-4
@@ -15,16 +15,13 @@ declare module 'vue' {
|
|||||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||||
AppCreditLink: typeof import('./src/components/AppCreditLink.vue')['default']
|
AppCreditLink: typeof import('./src/components/AppCreditLink.vue')['default']
|
||||||
ARadio: typeof import('ant-design-vue/es')['Radio']
|
|
||||||
ARadioButton: typeof import('ant-design-vue/es')['RadioButton']
|
ARadioButton: typeof import('ant-design-vue/es')['RadioButton']
|
||||||
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
|
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
|
||||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||||
ASlider: typeof import('ant-design-vue/es')['Slider']
|
ASlider: typeof import('ant-design-vue/es')['Slider']
|
||||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||||
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
|
||||||
ATag: typeof import('ant-design-vue/es')['Tag']
|
ATag: typeof import('ant-design-vue/es')['Tag']
|
||||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
|
||||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||||
BaseDatePicker: typeof import('./src/components/BasicPacks/BaseDatePicker/src/BaseDatePicker.vue')['default']
|
BaseDatePicker: typeof import('./src/components/BasicPacks/BaseDatePicker/src/BaseDatePicker.vue')['default']
|
||||||
Basic: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/basic.vue')['default']
|
Basic: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/basic.vue')['default']
|
||||||
@@ -70,6 +67,5 @@ declare module 'vue' {
|
|||||||
TransactionSkeleton: typeof import('./src/components/TransactionSkeleton.vue')['default']
|
TransactionSkeleton: typeof import('./src/components/TransactionSkeleton.vue')['default']
|
||||||
VanActionSheet: typeof import('vant/es')['ActionSheet']
|
VanActionSheet: typeof import('vant/es')['ActionSheet']
|
||||||
VanDialog: typeof import('vant/es')['Dialog']
|
VanDialog: typeof import('vant/es')['Dialog']
|
||||||
VanField: typeof import('vant/es')['Field']
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-33
@@ -128,39 +128,69 @@ export function isStoreClosedBySchedule(now = new Date()): boolean {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isOutsideStoreTradingHours(now, start, end)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isOutsideStoreTradingHours(
|
||||||
|
now = new Date(),
|
||||||
|
start?: string,
|
||||||
|
end?: string,
|
||||||
|
): boolean {
|
||||||
|
const hours = start != null && end != null
|
||||||
|
? { start, end }
|
||||||
|
: getEffectiveTradingHours()
|
||||||
|
|
||||||
const currentSeconds = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds()
|
const currentSeconds = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds()
|
||||||
const openSeconds = parseTimeToSeconds(start)
|
const openSeconds = parseTimeToSeconds(hours.start)
|
||||||
const closeSeconds = parseTimeToSeconds(end)
|
const closeSeconds = parseTimeToSeconds(hours.end)
|
||||||
|
|
||||||
return currentSeconds < openSeconds || currentSeconds > closeSeconds
|
return currentSeconds < openSeconds || currentSeconds > closeSeconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hasLivePriceQuote(): boolean {
|
||||||
|
const p = lastPrice.value
|
||||||
|
return getTradeBuyPrice(p) > 0 || getTradeSellPrice(p) > 0
|
||||||
|
}
|
||||||
|
|
||||||
export function isStoreClosed(): boolean {
|
export function isStoreClosed(): boolean {
|
||||||
void productTradingHoursVersion.value
|
void productTradingHoursVersion.value
|
||||||
const { closePriceEnabled } = getStoreTradingHours()
|
|
||||||
|
|
||||||
if (closePriceEnabled) {
|
if (lastPrice.value?.closed === true) {
|
||||||
if (lastPrice.value?.closed === true) {
|
return true
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return isStoreClosedBySchedule()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// وقتی close_price خاموش است، صفر بودن قیمت مرجع به معنی بسته بودن فروشگاه نیست.
|
|
||||||
return isStoreClosedBySchedule()
|
return isStoreClosedBySchedule()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getStoreClosedMessage(): string {
|
export const STORE_CLOSED_TITLE = 'فروشگاه بسته است'
|
||||||
const { start, end } = getEffectiveTradingHours()
|
|
||||||
const open = formatTradingTimeDisplay(start)
|
|
||||||
const close = formatTradingTimeDisplay(end)
|
|
||||||
|
|
||||||
if (!open || !close) {
|
export function stripHtmlMessage(message: string): string {
|
||||||
return 'فروشگاه در حال حاضر بسته است.'
|
return message.replace(/<[^>]*>/g, '').trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStoreClosedHint(customMessage?: unknown): string {
|
||||||
|
const custom = typeof customMessage === 'string' ? customMessage.trim() : ''
|
||||||
|
if (custom) {
|
||||||
|
return stripHtmlMessage(custom)
|
||||||
}
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
return `فروشگاه در حال حاضر بسته است. ساعت کاری از ${open} تا ${close} میباشد.`
|
export function getStoreClosedMessage(): string {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
/** برای toast/اعلان: پیام ادمین یا عنوان پیشفرض */
|
||||||
|
export function resolveStoreClosedNotice(customMessage?: unknown): string {
|
||||||
|
return getStoreClosedHint(customMessage) || STORE_CLOSED_TITLE
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isMarketClosedForDisplay(): boolean {
|
||||||
|
return getPriceDisplayState() === 'closed'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shouldBlockStoreTrading(): boolean {
|
||||||
|
return isMarketClosedForDisplay()
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PriceDisplayState = 'open' | 'closed' | 'no_quote'
|
export type PriceDisplayState = 'open' | 'closed' | 'no_quote'
|
||||||
@@ -168,34 +198,27 @@ export type PriceDisplayState = 'open' | 'closed' | 'no_quote'
|
|||||||
export const NO_QUOTE_MESSAGE = 'مظنه در دسترس نیست'
|
export const NO_QUOTE_MESSAGE = 'مظنه در دسترس نیست'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* وضعیت نمایش قیمت در صفحه اصلی:
|
* وضعیت نمایش قیمت:
|
||||||
* - closed → فروشگاه بسته است (خارج از ساعت کاری close_price یا بازه محصول)
|
* - closed → فروشگاه بسته است (ساعت کاری، سیگنال سرور، یا نبود مظنه)
|
||||||
* - no_quote → مظنه در دسترس نیست (قیمت زنده نداریم و show_last_price خاموش است)
|
* - open → نمایش عادی قیمت
|
||||||
* - open → نمایش عادی قیمت
|
|
||||||
*
|
|
||||||
* اولویت با status ارسالی از سرور است؛ اگر نبود به منطق سمت کلاینت برمیگردیم.
|
|
||||||
*/
|
*/
|
||||||
export function getPriceDisplayState(): PriceDisplayState {
|
export function getPriceDisplayState(): PriceDisplayState {
|
||||||
void productTradingHoursVersion.value
|
void productTradingHoursVersion.value
|
||||||
const p = lastPrice.value
|
const p = lastPrice.value
|
||||||
const status = p?.status
|
|
||||||
|
|
||||||
if (status === 'closed') {
|
if (p?.status === 'closed' || p?.closed === true) {
|
||||||
return 'closed'
|
return 'closed'
|
||||||
}
|
}
|
||||||
if (status === 'no_quote') {
|
|
||||||
return getTradeBuyPrice(p) > 0 ? 'open' : 'no_quote'
|
|
||||||
}
|
|
||||||
if (status === 'open') {
|
|
||||||
return getTradeBuyPrice(p) > 0 || getTradeSellPrice(p) > 0 ? 'open' : 'no_quote'
|
|
||||||
}
|
|
||||||
|
|
||||||
// سرور status نفرستاده (سازگاری با نسخه قدیمی) → استنتاج سمت کلاینت
|
|
||||||
if (isStoreClosed()) {
|
if (isStoreClosed()) {
|
||||||
return 'closed'
|
return 'closed'
|
||||||
}
|
}
|
||||||
|
|
||||||
return getTradeBuyPrice(p) > 0 || getTradeSellPrice(p) > 0 ? 'open' : 'no_quote'
|
if (!hasLivePriceQuote()) {
|
||||||
|
return 'closed'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'open'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPriceDisplayMessage(state: PriceDisplayState = getPriceDisplayState()): string {
|
export function getPriceDisplayMessage(state: PriceDisplayState = getPriceDisplayState()): string {
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ import { calcFeeInGrams, calcPayablePriceRial, calcSellGoldDebit, feeDeductFromG
|
|||||||
import { resolveProductCashFeeBuyRial, resolveProductCashFeeSellRial } from '@/utils/productCashFee'
|
import { resolveProductCashFeeBuyRial, resolveProductCashFeeSellRial } from '@/utils/productCashFee'
|
||||||
import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod'
|
import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod'
|
||||||
import { getCashWalletBalance } from '@/utils/productAssets'
|
import { getCashWalletBalance } from '@/utils/productAssets'
|
||||||
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
|
import { isStoreClosed, resolveStoreClosedNotice } from '@/utils/storeHours'
|
||||||
import { resetTransactionsPageData } from '@/views/base/transactions/composables/useTransactionsPageData'
|
import { resetTransactionsPageData } from '@/views/base/transactions/composables/useTransactionsPageData'
|
||||||
|
|
||||||
const infoVisible = ref(false)
|
const infoVisible = ref(false)
|
||||||
@@ -663,7 +663,7 @@ async function initPrice() {
|
|||||||
|
|
||||||
function okConfirm() {
|
function okConfirm() {
|
||||||
if (isStoreClosed()) {
|
if (isStoreClosed()) {
|
||||||
message.warning(getStoreClosedMessage())
|
message.warning(resolveStoreClosedNotice(userStore.getValueByKey('closed_message')))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
confirmAction.value = true
|
confirmAction.value = true
|
||||||
@@ -671,7 +671,7 @@ function okConfirm() {
|
|||||||
|
|
||||||
async function ok() {
|
async function ok() {
|
||||||
if (isStoreClosed()) {
|
if (isStoreClosed()) {
|
||||||
message.warning(getStoreClosedMessage())
|
message.warning(resolveStoreClosedNotice(userStore.getValueByKey('closed_message')))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ import {
|
|||||||
serviceFeePercentage,
|
serviceFeePercentage,
|
||||||
type TradeInputLock,
|
type TradeInputLock,
|
||||||
} from '@/utils/serviceFee'
|
} from '@/utils/serviceFee'
|
||||||
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
|
import { isStoreClosed, resolveStoreClosedNotice } from '@/utils/storeHours'
|
||||||
import { resetTransactionsPageData } from '@/views/base/transactions/composables/useTransactionsPageData'
|
import { resetTransactionsPageData } from '@/views/base/transactions/composables/useTransactionsPageData'
|
||||||
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
|
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
|
||||||
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
|
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
|
||||||
@@ -776,7 +776,7 @@ async function initPrice() {
|
|||||||
|
|
||||||
function okConfirm() {
|
function okConfirm() {
|
||||||
if (isStoreClosed()) {
|
if (isStoreClosed()) {
|
||||||
message.warning(getStoreClosedMessage())
|
message.warning(resolveStoreClosedNotice(userStore.getValueByKey('closed_message')))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (cashValidationMessage.value) {
|
if (cashValidationMessage.value) {
|
||||||
@@ -791,7 +791,7 @@ async function ok() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (isStoreClosed()) {
|
if (isStoreClosed()) {
|
||||||
message.warning(getStoreClosedMessage())
|
message.warning(resolveStoreClosedNotice(userStore.getValueByKey('closed_message')))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-box__title">{{ statusTitle }}</div>
|
<div class="status-box__title">{{ statusTitle }}</div>
|
||||||
<div class="status-box__hint">{{ statusHint }}</div>
|
<div v-if="statusHint" class="status-box__hint">{{ statusHint }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -55,8 +55,9 @@ import { useUserStore } from '@/store/userStore'
|
|||||||
import { getTradeBuyPrice, lastPrice, percentPriceChanged, price } from '@/utils/price'
|
import { getTradeBuyPrice, lastPrice, percentPriceChanged, price } from '@/utils/price'
|
||||||
import {
|
import {
|
||||||
NO_QUOTE_MESSAGE,
|
NO_QUOTE_MESSAGE,
|
||||||
|
STORE_CLOSED_TITLE,
|
||||||
getPriceDisplayState,
|
getPriceDisplayState,
|
||||||
getStoreClosedMessage,
|
getStoreClosedHint,
|
||||||
} from '@/utils/storeHours'
|
} from '@/utils/storeHours'
|
||||||
import Vue3Odometer from 'vue3-odometer'
|
import Vue3Odometer from 'vue3-odometer'
|
||||||
import 'odometer/themes/odometer-theme-default.css'
|
import 'odometer/themes/odometer-theme-default.css'
|
||||||
@@ -67,16 +68,12 @@ const userStore = useUserStore()
|
|||||||
const displayState = computed(() => getPriceDisplayState())
|
const displayState = computed(() => getPriceDisplayState())
|
||||||
|
|
||||||
const statusTitle = computed(() =>
|
const statusTitle = computed(() =>
|
||||||
displayState.value === 'closed' ? 'فروشگاه بسته است' : NO_QUOTE_MESSAGE
|
displayState.value === 'closed' ? STORE_CLOSED_TITLE : NO_QUOTE_MESSAGE
|
||||||
)
|
)
|
||||||
|
|
||||||
const statusHint = computed(() => {
|
const statusHint = computed(() => {
|
||||||
if (displayState.value === 'closed') {
|
if (displayState.value === 'closed') {
|
||||||
const custom = userStore.getValueByKey('closed_message')
|
return getStoreClosedHint(userStore.getValueByKey('closed_message'))
|
||||||
if (typeof custom === 'string' && custom.trim()) {
|
|
||||||
return custom.replace(/<[^>]*>/g, '').trim()
|
|
||||||
}
|
|
||||||
return getStoreClosedMessage()
|
|
||||||
}
|
}
|
||||||
return 'در حال حاضر مظنهای برای نمایش وجود ندارد.'
|
return 'در حال حاضر مظنهای برای نمایش وجود ندارد.'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
} from '@/utils/productAssets'
|
} from '@/utils/productAssets'
|
||||||
import { useSettingsStore } from '@/store/settingsStore'
|
import { useSettingsStore } from '@/store/settingsStore'
|
||||||
import { getTradeBuyPrice, lastPrice, stopLastPricePolling } from '@/utils/price'
|
import { getTradeBuyPrice, lastPrice, stopLastPricePolling } from '@/utils/price'
|
||||||
import { getStoreClosedMessage, isStoreClosed } from '@/utils/storeHours'
|
import { isStoreClosed } from '@/utils/storeHours'
|
||||||
import { message, Modal } from 'ant-design-vue'
|
import { message, Modal } from 'ant-design-vue'
|
||||||
import { useBanners } from './useBanners'
|
import { useBanners } from './useBanners'
|
||||||
import { usePriceChart, type ChartMetalType } from './usePriceChart'
|
import { usePriceChart, type ChartMetalType } from './usePriceChart'
|
||||||
@@ -74,7 +74,7 @@ export function useHomePage() {
|
|||||||
const closedMessage = computed(() => userStore.getValueByKey('closed_message'))
|
const closedMessage = computed(() => userStore.getValueByKey('closed_message'))
|
||||||
const marketClosedText = computed(() => {
|
const marketClosedText = computed(() => {
|
||||||
if (!isStoreClosed()) return ''
|
if (!isStoreClosed()) return ''
|
||||||
// فقط پیام سفارشی ادمین رو نشون بده — پیام ساعت کاری در CurrentPrice نمایش داده میشه
|
// فقط پیام سفارشی ادمین — در CurrentPrice نمایش داده میشود
|
||||||
const custom = typeof closedMessage.value === 'string' ? closedMessage.value.trim() : ''
|
const custom = typeof closedMessage.value === 'string' ? closedMessage.value.trim() : ''
|
||||||
return custom || ''
|
return custom || ''
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p class="dhome-hero-price__closed-title">{{ statusTitle }}</p>
|
<p class="dhome-hero-price__closed-title">{{ statusTitle }}</p>
|
||||||
<p class="dhome-hero-price__closed-hint">{{ statusHint }}</p>
|
<p v-if="statusHint" class="dhome-hero-price__closed-hint">{{ statusHint }}</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -55,8 +55,9 @@ import { useUserStore } from '@/store/userStore'
|
|||||||
import { getTradeBuyPrice, lastPrice, percentPriceChanged } from '@/utils/price'
|
import { getTradeBuyPrice, lastPrice, percentPriceChanged } from '@/utils/price'
|
||||||
import {
|
import {
|
||||||
NO_QUOTE_MESSAGE,
|
NO_QUOTE_MESSAGE,
|
||||||
|
STORE_CLOSED_TITLE,
|
||||||
getPriceDisplayState,
|
getPriceDisplayState,
|
||||||
getStoreClosedMessage,
|
getStoreClosedHint,
|
||||||
} from '@/utils/storeHours'
|
} from '@/utils/storeHours'
|
||||||
import { formatSignedPercentChange } from '@/utils/usePrice'
|
import { formatSignedPercentChange } from '@/utils/usePrice'
|
||||||
|
|
||||||
@@ -65,16 +66,12 @@ const userStore = useUserStore()
|
|||||||
const displayState = computed(() => getPriceDisplayState())
|
const displayState = computed(() => getPriceDisplayState())
|
||||||
|
|
||||||
const statusTitle = computed(() =>
|
const statusTitle = computed(() =>
|
||||||
displayState.value === 'closed' ? 'فروشگاه بسته است' : NO_QUOTE_MESSAGE
|
displayState.value === 'closed' ? STORE_CLOSED_TITLE : NO_QUOTE_MESSAGE
|
||||||
)
|
)
|
||||||
|
|
||||||
const statusHint = computed(() => {
|
const statusHint = computed(() => {
|
||||||
if (displayState.value === 'closed') {
|
if (displayState.value === 'closed') {
|
||||||
const custom = userStore.getValueByKey('closed_message')
|
return getStoreClosedHint(userStore.getValueByKey('closed_message'))
|
||||||
if (typeof custom === 'string' && custom.trim()) {
|
|
||||||
return custom.replace(/<[^>]*>/g, '').trim()
|
|
||||||
}
|
|
||||||
return getStoreClosedMessage()
|
|
||||||
}
|
}
|
||||||
return 'در حال حاضر مظنهای برای نمایش وجود ندارد.'
|
return 'در حال حاضر مظنهای برای نمایش وجود ندارد.'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ import {
|
|||||||
} from '@/utils/productOrderLimit'
|
} from '@/utils/productOrderLimit'
|
||||||
import { useWalletAssets } from '@/composables/useWalletAssets'
|
import { useWalletAssets } from '@/composables/useWalletAssets'
|
||||||
import { formatProductWalletBalanceText, formatInventoryCardValue, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
|
import { formatProductWalletBalanceText, formatInventoryCardValue, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
|
||||||
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
|
import { isStoreClosed, resolveStoreClosedNotice } from '@/utils/storeHours'
|
||||||
|
|
||||||
const catalogProducts = getProductsCatalogRef()
|
const catalogProducts = getProductsCatalogRef()
|
||||||
|
|
||||||
@@ -864,7 +864,7 @@ async function initPrice() {
|
|||||||
|
|
||||||
function okConfirm() {
|
function okConfirm() {
|
||||||
if (isStoreClosed()) {
|
if (isStoreClosed()) {
|
||||||
message.warning(getStoreClosedMessage())
|
message.warning(resolveStoreClosedNotice(userStore.getValueByKey('closed_message')))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
confirmAction.value = true
|
confirmAction.value = true
|
||||||
@@ -873,7 +873,7 @@ function okConfirm() {
|
|||||||
|
|
||||||
async function ok() {
|
async function ok() {
|
||||||
if (isStoreClosed()) {
|
if (isStoreClosed()) {
|
||||||
message.warning(getStoreClosedMessage())
|
message.warning(resolveStoreClosedNotice(userStore.getValueByKey('closed_message')))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import { loading } from '@/utils'
|
|||||||
import type { Product } from '@/models/products'
|
import type { Product } from '@/models/products'
|
||||||
import { cloneDeep } from 'lodash'
|
import { cloneDeep } from 'lodash'
|
||||||
import { isProductPriceInactive } from '@/utils/productPrice'
|
import { isProductPriceInactive } from '@/utils/productPrice'
|
||||||
import { getStoreClosedMessage, isStoreClosed } from '@/utils/storeHours'
|
import { getStoreClosedHint, shouldBlockStoreTrading } from '@/utils/storeHours'
|
||||||
|
import { useUserStore } from '@/store/userStore'
|
||||||
import { lastPrice } from '@/utils/price'
|
import { lastPrice } from '@/utils/price'
|
||||||
import {
|
import {
|
||||||
changeProductsTab,
|
changeProductsTab,
|
||||||
@@ -50,15 +51,18 @@ export const PRODUCTS_PAGE_CONTEXT_KEY: InjectionKey<ProductsPageContext> =
|
|||||||
Symbol('productsPageContext')
|
Symbol('productsPageContext')
|
||||||
|
|
||||||
export function useProductsPageProvider() {
|
export function useProductsPageProvider() {
|
||||||
|
const userStore = useUserStore()
|
||||||
const showFilter = ref(false)
|
const showFilter = ref(false)
|
||||||
const orderSheetKey = ref(0)
|
const orderSheetKey = ref(0)
|
||||||
const selectedProduct = ref<Product>()
|
const selectedProduct = ref<Product>()
|
||||||
const isAfterCloseTime = ref(false)
|
const isAfterCloseTime = ref(false)
|
||||||
const isProductInactive = ref(false)
|
const isProductInactive = ref(false)
|
||||||
const storeClosedMessage = computed(() => getStoreClosedMessage())
|
const storeClosedMessage = computed(() =>
|
||||||
|
getStoreClosedHint(userStore.getValueByKey('closed_message')),
|
||||||
|
)
|
||||||
|
|
||||||
function syncStoreClosedState() {
|
function syncStoreClosedState() {
|
||||||
if (isStoreClosed()) {
|
if (shouldBlockStoreTrading()) {
|
||||||
showFilter.value = false
|
showFilter.value = false
|
||||||
isAfterCloseTime.value = true
|
isAfterCloseTime.value = true
|
||||||
}
|
}
|
||||||
@@ -73,7 +77,7 @@ export function useProductsPageProvider() {
|
|||||||
function clickProduct(item?: Product) {
|
function clickProduct(item?: Product) {
|
||||||
if (!item?.show) return
|
if (!item?.show) return
|
||||||
|
|
||||||
if (isStoreClosed()) {
|
if (shouldBlockStoreTrading()) {
|
||||||
showFilter.value = false
|
showFilter.value = false
|
||||||
isAfterCloseTime.value = true
|
isAfterCloseTime.value = true
|
||||||
return
|
return
|
||||||
@@ -95,7 +99,7 @@ export function useProductsPageProvider() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(showFilter, (open) => {
|
watch(showFilter, (open) => {
|
||||||
if (open && isStoreClosed()) {
|
if (open && shouldBlockStoreTrading()) {
|
||||||
showFilter.value = false
|
showFilter.value = false
|
||||||
isAfterCloseTime.value = true
|
isAfterCloseTime.value = true
|
||||||
return
|
return
|
||||||
@@ -115,7 +119,7 @@ export function useProductsPageProvider() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (router.currentRoute.value.query.state) {
|
if (router.currentRoute.value.query.state) {
|
||||||
if (isStoreClosed()) {
|
if (shouldBlockStoreTrading()) {
|
||||||
isAfterCloseTime.value = true
|
isAfterCloseTime.value = true
|
||||||
} else if (router.currentRoute.value.query.product) {
|
} else if (router.currentRoute.value.query.product) {
|
||||||
clickProduct(productsItems.value?.find((x) => x.title === 'سکه'))
|
clickProduct(productsItems.value?.find((x) => x.title === 'سکه'))
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<!-- بنر بسته بودن فروشگاه -->
|
<!-- بنر بسته بودن فروشگاه -->
|
||||||
<div v-if="storeClosed" class="dproducts-closed-banner">
|
<div v-if="storeClosed" class="dproducts-closed-banner">
|
||||||
<span>🔒</span>
|
<span>🔒</span>
|
||||||
<span class="dproducts-closed-banner__title">فروشگاه بسته است</span>
|
<span class="dproducts-closed-banner__title">{{ STORE_CLOSED_TITLE }}</span>
|
||||||
<span v-if="storeClosedMessage" class="dproducts-closed-banner__hint">— {{ storeClosedMessage }}</span>
|
<span v-if="storeClosedMessage" class="dproducts-closed-banner__hint">— {{ storeClosedMessage }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
import DesktopPageTopbar from '@/layouts/components/DesktopPageTopbar.vue'
|
import DesktopPageTopbar from '@/layouts/components/DesktopPageTopbar.vue'
|
||||||
import DesktopProductCard from './components/DesktopProductCard.vue'
|
import DesktopProductCard from './components/DesktopProductCard.vue'
|
||||||
import { useProductsPageContext } from '../composables/useProductsPage'
|
import { useProductsPageContext } from '../composables/useProductsPage'
|
||||||
import { getPriceDisplayState, isStoreClosedBySchedule, getStoreClosedMessage } from '@/utils/storeHours'
|
import { isMarketClosedForDisplay, STORE_CLOSED_TITLE } from '@/utils/storeHours'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -68,10 +68,10 @@ const {
|
|||||||
changeTab,
|
changeTab,
|
||||||
clickProduct,
|
clickProduct,
|
||||||
isProductPriceInactive,
|
isProductPriceInactive,
|
||||||
|
storeClosedMessage,
|
||||||
} = useProductsPageContext()
|
} = useProductsPageContext()
|
||||||
|
|
||||||
const storeClosed = computed(() => getPriceDisplayState() === 'closed' || isStoreClosedBySchedule())
|
const storeClosed = computed(() => isMarketClosedForDisplay())
|
||||||
const storeClosedMessage = computed(() => getStoreClosedMessage())
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" src="./styles/desktop-products.less"></style>
|
<style lang="less" src="./styles/desktop-products.less"></style>
|
||||||
|
|||||||
@@ -52,10 +52,9 @@
|
|||||||
|
|
||||||
<BasicModal v-model:visible="isAfterCloseTime" custom-footer :closable="false">
|
<BasicModal v-model:visible="isAfterCloseTime" custom-footer :closable="false">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<div class="font-bold text-red-600">مشتریان گرامی</div>
|
<div class="font-bold text-red-600">{{ STORE_CLOSED_TITLE }}</div>
|
||||||
<div class="mt-2 leading-relaxed">
|
<div v-if="storeClosedMessage" class="mt-2 leading-relaxed text-gray-600">
|
||||||
<p>{{ storeClosedMessage }}</p>
|
{{ storeClosedMessage }}
|
||||||
<p>از همراهی و اعتماد شما سپاسگزاریم.🤍</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -75,6 +74,7 @@ import BasicModal from '@/components/BasicPacks/BasicModal.vue'
|
|||||||
import ResponsiveViewPair from '@/layouts/components/ResponsiveViewPair.vue'
|
import ResponsiveViewPair from '@/layouts/components/ResponsiveViewPair.vue'
|
||||||
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
|
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
|
||||||
import { usesQuantityTrade } from '@/utils/productCategories'
|
import { usesQuantityTrade } from '@/utils/productCategories'
|
||||||
|
import { STORE_CLOSED_TITLE } from '@/utils/storeHours'
|
||||||
import { useProductsPageProvider } from './composables/useProductsPage'
|
import { useProductsPageProvider } from './composables/useProductsPage'
|
||||||
import MobileProductsView from './mobile/MobileProductsView.vue'
|
import MobileProductsView from './mobile/MobileProductsView.vue'
|
||||||
import DesktopProductsView from './desktop/DesktopProductsView.vue'
|
import DesktopProductsView from './desktop/DesktopProductsView.vue'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<div v-if="storeClosed" class="mx-4 mt-4 closed-banner">
|
<div v-if="storeClosed" class="mx-4 mt-4 closed-banner">
|
||||||
<div class="closed-banner__icon">🔒</div>
|
<div class="closed-banner__icon">🔒</div>
|
||||||
<div class="closed-banner__body">
|
<div class="closed-banner__body">
|
||||||
<div class="closed-banner__title">فروشگاه بسته است</div>
|
<div class="closed-banner__title">{{ STORE_CLOSED_TITLE }}</div>
|
||||||
<div v-if="storeClosedMessage" class="closed-banner__hint">{{ storeClosedMessage }}</div>
|
<div v-if="storeClosedMessage" class="closed-banner__hint">{{ storeClosedMessage }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,7 +59,7 @@ import img from '@/assets/img/user_ly1.svg'
|
|||||||
import MobilePageHeader from '@/layouts/components/MobilePageHeader.vue'
|
import MobilePageHeader from '@/layouts/components/MobilePageHeader.vue'
|
||||||
import ProductItem from '@/views/base/products/components/ProductItem.vue'
|
import ProductItem from '@/views/base/products/components/ProductItem.vue'
|
||||||
import { useProductsPageContext } from '../composables/useProductsPage'
|
import { useProductsPageContext } from '../composables/useProductsPage'
|
||||||
import { getPriceDisplayState, isStoreClosedBySchedule, getStoreClosedMessage } from '@/utils/storeHours'
|
import { isMarketClosedForDisplay, STORE_CLOSED_TITLE } from '@/utils/storeHours'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -70,10 +70,10 @@ const {
|
|||||||
changeTab,
|
changeTab,
|
||||||
clickProduct,
|
clickProduct,
|
||||||
isProductPriceInactive,
|
isProductPriceInactive,
|
||||||
|
storeClosedMessage,
|
||||||
} = useProductsPageContext()
|
} = useProductsPageContext()
|
||||||
|
|
||||||
const storeClosed = computed(() => getPriceDisplayState() === 'closed' || isStoreClosedBySchedule())
|
const storeClosed = computed(() => isMarketClosedForDisplay())
|
||||||
const storeClosedMessage = computed(() => getStoreClosedMessage())
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user