fix(products): treat SSE list as full active catalog
Stop keeping deactivated products when the stream shrinks, update prices in place to avoid grid flicker, and only keep admin-active items. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -117,48 +117,17 @@ function mergeLiveProductList(incoming: Product[], current?: Product[]): Product
|
||||
})
|
||||
}
|
||||
|
||||
/** فقط محصول فعال ادمین (باز) — نه show لحظهای ساعت/مظنه */
|
||||
/** فقط محصول فعال ادمین (باز) — فیلد خالی/undefined را فعال نگیر */
|
||||
function isActiveProduct(product: Product): boolean {
|
||||
const active = product.active as unknown
|
||||
return active !== false && active !== 0 && active !== '0'
|
||||
}
|
||||
|
||||
/** استریم گاهی لیست ناقص میفرستد — عضوهای قبلی را دور نریز. */
|
||||
function mergeSocketProductMembership(incoming: Product[], current?: Product[]): Product[] {
|
||||
if (!current?.length) return incoming
|
||||
|
||||
const incomingById = new Map(incoming.map((item) => [item.id, item]))
|
||||
const currentIds = new Set(current.map((item) => item.id))
|
||||
const hasAdded = incoming.some((item) => !currentIds.has(item.id))
|
||||
const missingFromIncoming = current.some((item) => !incomingById.has(item.id))
|
||||
|
||||
if (missingFromIncoming && !hasAdded && incoming.length < current.length) {
|
||||
return current.map((item) => {
|
||||
const updated = incomingById.get(item.id)
|
||||
return updated ? { ...item, ...updated } : item
|
||||
})
|
||||
}
|
||||
|
||||
const merged = incoming.map((item) => {
|
||||
const prev = current.find((row) => row.id === item.id)
|
||||
return prev ? { ...prev, ...item } : item
|
||||
})
|
||||
|
||||
if (missingFromIncoming) {
|
||||
for (const item of current) {
|
||||
if (!incomingById.has(item.id)) {
|
||||
merged.push(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return merged
|
||||
return active === true || active === 1 || active === '1'
|
||||
}
|
||||
|
||||
function applyProductsList(products: Product[]) {
|
||||
const visible = products.filter(isActiveProduct)
|
||||
const sorted = sortProductsByInventory(visible)
|
||||
productsFirstItems.value = sorted
|
||||
getProductsCatalogRef().value = sorted
|
||||
pruneEmptyTypeItems()
|
||||
|
||||
if (
|
||||
@@ -172,6 +141,46 @@ function applyProductsList(products: Product[]) {
|
||||
productsPageLoading.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* SSE همیشه لیست کامل محصولات فعال را میفرستد.
|
||||
* عضو جدید/حذفشده را از همان لیست بگیر؛ فقط عکس را از نسخهٔ قبلی نگه دار.
|
||||
* آپدیت قیمت روی همان آبجکتها تا گرید نپرد.
|
||||
*/
|
||||
function applySocketProductList(incoming: Product[], current?: Product[]) {
|
||||
const next = sortProductsByInventory(
|
||||
mergeLiveProductList(incoming, current).filter(isActiveProduct),
|
||||
)
|
||||
|
||||
if (!current?.length) {
|
||||
applyProductsList(next)
|
||||
return
|
||||
}
|
||||
|
||||
const nextById = new Map(next.map((item) => [item.id, item]))
|
||||
const currentIds = new Set(current.map((item) => item.id))
|
||||
const nextIds = new Set(next.map((item) => item.id))
|
||||
const membershipChanged =
|
||||
next.length !== current.length ||
|
||||
next.some((item) => !currentIds.has(item.id)) ||
|
||||
current.some((item) => !nextIds.has(item.id))
|
||||
|
||||
if (membershipChanged) {
|
||||
applyProductsList(next)
|
||||
return
|
||||
}
|
||||
|
||||
current.forEach((item) => {
|
||||
const updated = nextById.get(item.id)
|
||||
if (updated) {
|
||||
Object.assign(item, updated)
|
||||
}
|
||||
})
|
||||
|
||||
getProductsCatalogRef().value = current
|
||||
changeProductsTab()
|
||||
productsPageLoading.value = false
|
||||
}
|
||||
|
||||
export async function refreshProductsPageData() {
|
||||
try {
|
||||
const fresh = await getProductsCatalog(true)
|
||||
@@ -189,13 +198,10 @@ export function applyProductsListFromSocket(products: Product[]) {
|
||||
}
|
||||
|
||||
const base =
|
||||
getProductsCatalogRef().value.length
|
||||
? getProductsCatalogRef().value
|
||||
: productsFirstItems.value
|
||||
const withImages = mergeLiveProductList(products, base)
|
||||
const merged = mergeSocketProductMembership(withImages, base)
|
||||
getProductsCatalogRef().value = merged
|
||||
applyProductsList(merged)
|
||||
productsFirstItems.value?.length
|
||||
? productsFirstItems.value
|
||||
: getProductsCatalogRef().value
|
||||
applySocketProductList(products, base)
|
||||
}
|
||||
|
||||
function startProductListPolling() {
|
||||
|
||||
Reference in New Issue
Block a user