feat(products): add list and TV visibility icons in operations
Clarify tooltips for product-list vs TV board, keep the same switches in the editor, and show separate status columns. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -52,6 +52,9 @@ export const changeSellActiveProduct = async (id?: number) => {
|
|||||||
export const changeActiveProduct = async (id: number) => {
|
export const changeActiveProduct = async (id: number) => {
|
||||||
return await useAxios.get(`/admin/product/active/${id}`)
|
return await useAxios.get(`/admin/product/active/${id}`)
|
||||||
}
|
}
|
||||||
|
export const changeShowOnTvProduct = async (id: number) => {
|
||||||
|
return await useAxios.get(`/admin/product/show_on_tv/${id}`)
|
||||||
|
}
|
||||||
export const changeVisibilityProduct = async (id: number) => {
|
export const changeVisibilityProduct = async (id: number) => {
|
||||||
return await useAxios.get(`/admin/product/hide/${id}`)
|
return await useAxios.get(`/admin/product/hide/${id}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -496,11 +496,19 @@
|
|||||||
<div class="grid gap-4 md:grid-cols-2">
|
<div class="grid gap-4 md:grid-cols-2">
|
||||||
<div class="product-visibility-panel">
|
<div class="product-visibility-panel">
|
||||||
<div class="product-visibility-row">
|
<div class="product-visibility-row">
|
||||||
<span class="text-sm">نمایش در لیست محصولات</span>
|
<DashboardLabelWithHelp
|
||||||
|
label="نمایش در لیست محصولات"
|
||||||
|
:help="showInListHelp"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
<a-switch v-model:checked="form.show_in_list" />
|
<a-switch v-model:checked="form.show_in_list" />
|
||||||
</div>
|
</div>
|
||||||
<div class="product-visibility-row">
|
<div class="product-visibility-row">
|
||||||
<span class="text-sm">نمایش در تابلو TV</span>
|
<DashboardLabelWithHelp
|
||||||
|
label="نمایش در تابلو TV"
|
||||||
|
:help="showOnTvHelp"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
<a-switch v-model:checked="form.show_on_tv" />
|
<a-switch v-model:checked="form.show_on_tv" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -770,11 +778,13 @@ const cashFeeSellHelp: DashboardHelp = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const showOnTvHelp: DashboardHelp = {
|
const showOnTvHelp: DashboardHelp = {
|
||||||
description: 'روشن: این محصول در صفحه تابلو قیمت مشتری (/tv) نمایش داده میشود.',
|
description:
|
||||||
|
'مستقل از لیست محصولات است. روشن: این محصول در صفحه تابلو قیمت مشتری (/tv) نمایش داده میشود؛ حتی اگر در لیست محصولات خاموش باشد.',
|
||||||
}
|
}
|
||||||
|
|
||||||
const showInListHelp: DashboardHelp = {
|
const showInListHelp: DashboardHelp = {
|
||||||
description: 'روشن: این محصول در صفحه لیست محصولات اپ مشتری نمایش داده میشود.',
|
description:
|
||||||
|
'مستقل از تابلو TV است. روشن: این محصول در صفحه لیست محصولات اپ مشتری نمایش داده میشود. همان آیکون تیک/ضربدر در ستون عملیات همین وضعیت را عوض میکند.',
|
||||||
}
|
}
|
||||||
|
|
||||||
const autoOpenHelp: DashboardHelp = {
|
const autoOpenHelp: DashboardHelp = {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
@toggleBuy="$emit('toggleBuy', $event)"
|
@toggleBuy="$emit('toggleBuy', $event)"
|
||||||
@toggleSell="$emit('toggleSell', $event)"
|
@toggleSell="$emit('toggleSell', $event)"
|
||||||
@toggleActive="$emit('toggleActive', $event)"
|
@toggleActive="$emit('toggleActive', $event)"
|
||||||
|
@toggleShowOnTv="$emit('toggleShowOnTv', $event)"
|
||||||
@edit="$emit('edit', $event)"
|
@edit="$emit('edit', $event)"
|
||||||
@archive="$emit('archive', $event)"
|
@archive="$emit('archive', $event)"
|
||||||
/>
|
/>
|
||||||
@@ -43,6 +44,7 @@ defineEmits<{
|
|||||||
(e: 'toggleBuy', item: Product): void
|
(e: 'toggleBuy', item: Product): void
|
||||||
(e: 'toggleSell', item: Product): void
|
(e: 'toggleSell', item: Product): void
|
||||||
(e: 'toggleActive', item: Product): void
|
(e: 'toggleActive', item: Product): void
|
||||||
|
(e: 'toggleShowOnTv', item: Product): void
|
||||||
(e: 'archive', item: Product): void
|
(e: 'archive', item: Product): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,20 @@
|
|||||||
/>
|
/>
|
||||||
<MobileIconButton
|
<MobileIconButton
|
||||||
plain
|
plain
|
||||||
:key="`active-${row.id}-${row.active}`"
|
:key="`list-${row.id}-${row.show_in_list ?? row.active}`"
|
||||||
:icon="row.active ? 'vuesax-linear:tick-circle' : 'vuesax-linear:close-circle'"
|
:icon="(row.show_in_list ?? row.active) ? 'vuesax-linear:tick-circle' : 'vuesax-linear:close-circle'"
|
||||||
:color="row.active ? '#16A34A' : '#DC2626'"
|
:color="(row.show_in_list ?? row.active) ? '#16A34A' : '#DC2626'"
|
||||||
:size="22"
|
:size="22"
|
||||||
@click="$emit('toggleActive', row)"
|
@click="$emit('toggleActive', row)"
|
||||||
/>
|
/>
|
||||||
|
<MobileIconButton
|
||||||
|
plain
|
||||||
|
:key="`tv-${row.id}-${row.show_on_tv}`"
|
||||||
|
icon="vuesax-linear:monitor"
|
||||||
|
:color="row.show_on_tv ? '#16A34A' : '#DC2626'"
|
||||||
|
:size="22"
|
||||||
|
@click="$emit('toggleShowOnTv', row)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -103,6 +111,7 @@ const emit = defineEmits<{
|
|||||||
(e: 'toggleBuy', item: Product): void
|
(e: 'toggleBuy', item: Product): void
|
||||||
(e: 'toggleSell', item: Product): void
|
(e: 'toggleSell', item: Product): void
|
||||||
(e: 'toggleActive', item: Product): void
|
(e: 'toggleActive', item: Product): void
|
||||||
|
(e: 'toggleShowOnTv', item: Product): void
|
||||||
(e: 'edit', item: Product): void
|
(e: 'edit', item: Product): void
|
||||||
(e: 'archive', item: Product): void
|
(e: 'archive', item: Product): void
|
||||||
}>()
|
}>()
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ defineEmits<{
|
|||||||
(e: 'edit', item: Product): void
|
(e: 'edit', item: Product): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const statusDotClass = computed(() => (props.item.active ? 'bg-green-500' : 'bg-red-400'))
|
const statusDotClass = computed(() =>
|
||||||
|
(props.item.show_in_list ?? props.item.active) ? 'bg-green-500' : 'bg-red-400',
|
||||||
|
)
|
||||||
const priceLabel = computed(() => (props.item.price ? usePrice(props.item.price) : '-'))
|
const priceLabel = computed(() => (props.item.price ? usePrice(props.item.price) : '-'))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -75,20 +75,37 @@
|
|||||||
@click="activeSell(record)"
|
@click="activeSell(record)"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip class="cursor-pointer" :key="`active-${record.id}-${record.active}`">
|
<a-tooltip class="cursor-pointer" :key="`list-${record.id}-${record.show_in_list ?? record.active}`">
|
||||||
<template v-if="!record.active" #title><span>فعال کردن محصول</span></template>
|
<template v-if="!(record.show_in_list ?? record.active)" #title>
|
||||||
<template v-else #title><span>غیر فعال کردن محصول</span></template>
|
<span>فعال کردن نمایش در لیست محصولات</span>
|
||||||
|
</template>
|
||||||
|
<template v-else #title>
|
||||||
|
<span>غیرفعال کردن نمایش در لیست محصولات</span>
|
||||||
|
</template>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
v-if="!record.active"
|
v-if="!(record.show_in_list ?? record.active)"
|
||||||
icon="vuesax-linear:close-circle"
|
icon="vuesax-linear:close-circle"
|
||||||
color="#DC2626"
|
color="#DC2626"
|
||||||
@click="activeProduct(record)"
|
@click="toggleShowInList(record)"
|
||||||
/>
|
/>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
v-else
|
v-else
|
||||||
icon="vuesax-linear:tick-circle"
|
icon="vuesax-linear:tick-circle"
|
||||||
color="#16A34A"
|
color="#16A34A"
|
||||||
@click="activeProduct(record)"
|
@click="toggleShowInList(record)"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip class="cursor-pointer" :key="`tv-${record.id}-${record.show_on_tv}`">
|
||||||
|
<template v-if="!record.show_on_tv" #title>
|
||||||
|
<span>فعال کردن نمایش در تابلو TV</span>
|
||||||
|
</template>
|
||||||
|
<template v-else #title>
|
||||||
|
<span>غیرفعال کردن نمایش در تابلو TV</span>
|
||||||
|
</template>
|
||||||
|
<BaseIcon
|
||||||
|
icon="vuesax-linear:monitor"
|
||||||
|
:color="record.show_on_tv ? '#16A34A' : '#DC2626'"
|
||||||
|
@click="toggleShowOnTv(record)"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip placement="bottom" class="cursor-pointer" @click="emits('edit', record)">
|
<a-tooltip placement="bottom" class="cursor-pointer" @click="emits('edit', record)">
|
||||||
@@ -118,7 +135,8 @@
|
|||||||
@edit="emits('edit', $event)"
|
@edit="emits('edit', $event)"
|
||||||
@toggleBuy="activeBuy"
|
@toggleBuy="activeBuy"
|
||||||
@toggleSell="activeSell"
|
@toggleSell="activeSell"
|
||||||
@toggleActive="activeProduct"
|
@toggleActive="toggleShowInList"
|
||||||
|
@toggleShowOnTv="toggleShowOnTv"
|
||||||
@archive="handleArchive"
|
@archive="handleArchive"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -137,6 +155,7 @@ import {
|
|||||||
changeActiveProduct,
|
changeActiveProduct,
|
||||||
changeBuyActiveProduct,
|
changeBuyActiveProduct,
|
||||||
changeSellActiveProduct,
|
changeSellActiveProduct,
|
||||||
|
changeShowOnTvProduct,
|
||||||
getCustomerTable,
|
getCustomerTable,
|
||||||
setActiveTime
|
setActiveTime
|
||||||
} from '@/api/product'
|
} from '@/api/product'
|
||||||
@@ -232,12 +251,18 @@ const activeBuy = (product: Product) =>
|
|||||||
await fetch()
|
await fetch()
|
||||||
})
|
})
|
||||||
|
|
||||||
const activeProduct = (product: Product) =>
|
const toggleShowInList = (product: Product) =>
|
||||||
confirmToggle('آیا مطمئن به انجام این عملیات هستید؟', async () => {
|
confirmToggle('نمایش این محصول در لیست محصولات تغییر میکند. آیا مطمئن هستید؟', async () => {
|
||||||
await changeActiveProduct(product.id)
|
await changeActiveProduct(product.id)
|
||||||
await fetch()
|
await fetch()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const toggleShowOnTv = (product: Product) =>
|
||||||
|
confirmToggle('نمایش این محصول در تابلو TV تغییر میکند. آیا مطمئن هستید؟', async () => {
|
||||||
|
await changeShowOnTvProduct(product.id)
|
||||||
|
await fetch()
|
||||||
|
})
|
||||||
|
|
||||||
function handleArchive(product: Product) {
|
function handleArchive(product: Product) {
|
||||||
confirmToggle(
|
confirmToggle(
|
||||||
'آیا این محصول بایگانی شود؟ نمایش، خرید و فروش آن غیرفعال میشود.',
|
'آیا این محصول بایگانی شود؟ نمایش، خرید و فروش آن غیرفعال میشود.',
|
||||||
|
|||||||
@@ -104,21 +104,44 @@ export function getProductColumns(): BaseTableColumn[] {
|
|||||||
},
|
},
|
||||||
...(isStoreApp() ? [inventoryColumn] : []),
|
...(isStoreApp() ? [inventoryColumn] : []),
|
||||||
{
|
{
|
||||||
title: 'وضعیت محصول',
|
title: 'وضعیت لیست',
|
||||||
dataIndex: 'active',
|
dataIndex: 'show_in_list',
|
||||||
key: 'active',
|
key: 'show_in_list',
|
||||||
type: 'Boolean',
|
type: 'Boolean',
|
||||||
customRender: (record) => (
|
customRender: (record) => {
|
||||||
<div class="flex justify-center">
|
const on = record?.record.show_in_list ?? record?.record.active
|
||||||
<CustomTag
|
return (
|
||||||
class="px-3 font-bold py-1"
|
<div class="flex justify-center">
|
||||||
textColor={record?.record.active ? '#65a30d' : '#dc2626'}
|
<CustomTag
|
||||||
bgColor={record?.record.active ? '#ecfccb' : '#fee2e2'}
|
class="px-3 font-bold py-1"
|
||||||
>
|
textColor={on ? '#65a30d' : '#dc2626'}
|
||||||
{record?.record.active ? 'باز' : 'بسته'}
|
bgColor={on ? '#ecfccb' : '#fee2e2'}
|
||||||
</CustomTag>
|
>
|
||||||
</div>
|
{on ? 'باز' : 'بسته'}
|
||||||
)
|
</CustomTag>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'تابلو TV',
|
||||||
|
dataIndex: 'show_on_tv',
|
||||||
|
key: 'show_on_tv',
|
||||||
|
type: 'Boolean',
|
||||||
|
customRender: (record) => {
|
||||||
|
const on = !!record?.record.show_on_tv
|
||||||
|
return (
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<CustomTag
|
||||||
|
class="px-3 font-bold py-1"
|
||||||
|
textColor={on ? '#65a30d' : '#dc2626'}
|
||||||
|
bgColor={on ? '#ecfccb' : '#fee2e2'}
|
||||||
|
>
|
||||||
|
{on ? 'روشن' : 'خاموش'}
|
||||||
|
</CustomTag>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'عملیات',
|
title: 'عملیات',
|
||||||
|
|||||||
Reference in New Issue
Block a user