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:
2026-07-11 12:42:56 +02:00
co-authored by Cursor
parent 1000df5931
commit 0109f3a744
12 changed files with 99 additions and 82 deletions
-4
View File
@@ -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
View File
@@ -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 {
+3 -3
View File
@@ -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 {
+3 -3
View File
@@ -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>
+4 -4
View File
@@ -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>