Sync live quote handling, SSE product images, store hours, file URL normalization, PWA icon cache, TV monitor, about software, SuperAdmin menu gates, price alerts, and related UX from modular while preserving boursecu branding and config constraints. Co-authored-by: Cursor <cursoragent@cursor.com>
177 lines
5.5 KiB
Vue
177 lines
5.5 KiB
Vue
<template>
|
|
<div v-if="variant === 'desktop'" class="dptr-card">
|
|
<p class="dptr-card__price">{{ usePrice(item.target_price) }}</p>
|
|
|
|
<div class="dptr-card__meta">
|
|
<div class="dptr-card__row">
|
|
<span class="dptr-card__label">محصول:</span>
|
|
<span class="dptr-card__value">{{ productTitle }}</span>
|
|
</div>
|
|
<div class="dptr-card__row">
|
|
<span class="dptr-card__label">جهت قیمت:</span>
|
|
<span class="dptr-card__value">{{ returnPriceCondition(item.price_condition) }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dptr-card__actions">
|
|
<button
|
|
type="button"
|
|
class="dptr-card__icon-btn dptr-card__icon-btn--edit"
|
|
@click.stop="emits('edit', item)"
|
|
>
|
|
<BasicIcon color="green" icon="vuesax-linear:edit" size="18" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="dptr-card__icon-btn dptr-card__icon-btn--danger"
|
|
@click.stop="deleteConfirmVisible = true"
|
|
>
|
|
<BasicIcon color="red" icon="vuesax-linear:trash" size="18" />
|
|
</button>
|
|
</div>
|
|
|
|
<div class="dptr-card__footer">
|
|
<span class="dptr-card__date">{{ toJalali(item.created_at) }}</span>
|
|
<a-switch
|
|
v-model:checked="isActive"
|
|
checked-children="فعال"
|
|
un-checked-children="غیر فعال"
|
|
@change="changeActive"
|
|
/>
|
|
</div>
|
|
|
|
<DialogVant v-model:show="deleteConfirmVisible" :closeOnClickOverlay="false" :timeOut="-1" teleport="body">
|
|
<template #title>
|
|
<div class="flex flex-col items-center">
|
|
<div class="p-5 text-sm">آیا از حذف هشدار اطمینان دارید؟</div>
|
|
</div>
|
|
</template>
|
|
<template #button>
|
|
<div class="text-center text-red flex items-center justify-center" @click="deleteItem">
|
|
<a-spin :spinning="deleteLoading" size="small">تایید</a-spin>
|
|
</div>
|
|
<div class="text-center" @click="deleteConfirmVisible = false">انصراف</div>
|
|
</template>
|
|
</DialogVant>
|
|
</div>
|
|
|
|
<div v-else @click="infoVisible = true" class="shadow mb-2 p-2 rounded-lg">
|
|
<div class="flex justify-between">
|
|
<div>
|
|
<div class="font-bold text-base mb-2">{{ usePrice(item.target_price) }}</div>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<BasicIcon
|
|
class="p-1"
|
|
color="red"
|
|
icon="vuesax-linear:trash"
|
|
@click.stop="deleteConfirmVisible = true"
|
|
/>
|
|
<BasicIcon
|
|
class="p-1"
|
|
color="green"
|
|
icon="vuesax-linear:edit"
|
|
@click.stop="emits('edit', item)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col gap-2 mt-2">
|
|
<BasicInfoItem is-line title="محصول" :value="productTitle" />
|
|
<BasicInfoItem is-line title="جهت قیمت" :value="returnPriceCondition(item.price_condition)" />
|
|
</div>
|
|
<a-divider class="!my-3" />
|
|
<div class="flex justify-between mt-1">
|
|
<div class="mb-2">{{ toJalali(item.created_at) }}</div>
|
|
<a-switch
|
|
v-model:checked="isActive"
|
|
checked-children="فعال"
|
|
un-checked-children="غیر فعال"
|
|
@change="changeActive"
|
|
/>
|
|
</div>
|
|
|
|
<DialogVant v-model:show="deleteConfirmVisible" :closeOnClickOverlay="false" :timeOut="-1" teleport="body">
|
|
<template #title>
|
|
<div class="flex flex-col items-center">
|
|
<div class="p-5 text-sm">آیا از حذف هشدار اطمینان دارید؟</div>
|
|
</div>
|
|
</template>
|
|
<template #button>
|
|
<div class="text-center text-red flex items-center justify-center" @click="deleteItem">
|
|
<a-spin :spinning="deleteLoading" size="small">تایید</a-spin>
|
|
</div>
|
|
<div class="text-center" @click="deleteConfirmVisible = false">انصراف</div>
|
|
</template>
|
|
</DialogVant>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { usePrice } from '../../../../utils/usePrice'
|
|
import { computed, onMounted, ref } from 'vue'
|
|
import { toJalali } from '../../../../utils/useDateTime'
|
|
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
|
import type { PriceTrigger } from '@/models/PriceTrigger'
|
|
import BasicInfoItem from '@/components/BasicPacks/BasicInfoItem.vue'
|
|
import DialogVant from '@/components/DialogVant.vue'
|
|
import { deletePriceTrigger, updatePriceTrigger } from '@/api/triggerPrice'
|
|
import { loading } from '@/utils'
|
|
|
|
const infoVisible = ref(false)
|
|
const isActive = ref(false)
|
|
const deleteLoading = ref(false)
|
|
const deleteConfirmVisible = ref(false)
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
item: PriceTrigger
|
|
variant?: 'mobile' | 'desktop'
|
|
}>(),
|
|
{ variant: 'mobile' },
|
|
)
|
|
|
|
const emits = defineEmits(['edit', 'refresh'])
|
|
|
|
const productTitle = computed(() => props.item.product?.title || 'طلا')
|
|
|
|
onMounted(() => {
|
|
isActive.value = props.item.is_active
|
|
})
|
|
|
|
async function changeActive(val: boolean) {
|
|
try {
|
|
loading.value = true
|
|
await updatePriceTrigger(props?.item.id, { is_active: val })
|
|
} catch (e) {
|
|
console.log(e)
|
|
isActive.value = !isActive.value
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
function returnPriceCondition(val: string) {
|
|
switch (val) {
|
|
case '==':
|
|
return 'مساوی'
|
|
case '<':
|
|
return 'کوچکتر'
|
|
case '>':
|
|
return 'بزرگتر'
|
|
}
|
|
}
|
|
|
|
async function deleteItem() {
|
|
try {
|
|
deleteLoading.value = true
|
|
await deletePriceTrigger(props.item.id)
|
|
deleteConfirmVisible.value = false
|
|
emits('refresh')
|
|
} catch (e) {
|
|
console.log(e)
|
|
} finally {
|
|
deleteLoading.value = false
|
|
}
|
|
}
|
|
</script>
|