Add store-product Excel bulk edit and polish the business dashboard.
Export/import price and stock from Store Products, keep card order after saves, localize variations, and drop unused website nav items. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
7b51dda82a
commit
832ac32a09
@@ -63,7 +63,10 @@ function isVariantInStock(variant: StoreItem) {
|
||||
return variant.stockQuantity === null || variant.stockQuantity > 0
|
||||
}
|
||||
|
||||
export function groupStoreItemsByProduct(items: StoreItem[]): StoreProductListing[] {
|
||||
export function groupStoreItemsByProduct(
|
||||
items: StoreItem[],
|
||||
productOrder?: string[],
|
||||
): StoreProductListing[] {
|
||||
const byProduct = new Map<string, StoreItem[]>()
|
||||
|
||||
for (const item of items) {
|
||||
@@ -72,48 +75,53 @@ export function groupStoreItemsByProduct(items: StoreItem[]): StoreProductListin
|
||||
byProduct.set(item.productId, variants)
|
||||
}
|
||||
|
||||
return [...byProduct.values()]
|
||||
.map((variants) => {
|
||||
const sorted = [...variants].sort((a, b) => {
|
||||
const aInStock = isVariantInStock(a)
|
||||
const bInStock = isVariantInStock(b)
|
||||
if (aInStock !== bInStock) return aInStock ? -1 : 1
|
||||
const listings = [...byProduct.values()].map((variants) => {
|
||||
const sorted = [...variants].sort((a, b) => {
|
||||
const aInStock = isVariantInStock(a)
|
||||
const bInStock = isVariantInStock(b)
|
||||
if (aInStock !== bInStock) return aInStock ? -1 : 1
|
||||
|
||||
const updatedDiff = parseDateMs(b.updatedAt) - parseDateMs(a.updatedAt)
|
||||
if (updatedDiff !== 0) return updatedDiff
|
||||
return parseDateMs(b.createdAt) - parseDateMs(a.createdAt)
|
||||
})
|
||||
|
||||
const representative = sorted[0]!
|
||||
const { displayPrice, displayDiscountedPrice } = pickDisplayPrice(sorted)
|
||||
|
||||
return {
|
||||
productId: representative.productId,
|
||||
productTitle: representative.productTitle,
|
||||
productNameFa: representative.productNameFa,
|
||||
productImage: representative.productImage,
|
||||
productTotalStock: representative.productTotalStock,
|
||||
variantCount: sorted.length,
|
||||
variants: sorted,
|
||||
representative,
|
||||
displayPrice,
|
||||
displayDiscountedPrice,
|
||||
showFestival: sorted.some(
|
||||
(variant) => variant.isFestival || (variant.rewardPoints ?? 0) > 0,
|
||||
),
|
||||
}
|
||||
const updatedDiff = parseDateMs(b.updatedAt) - parseDateMs(a.updatedAt)
|
||||
if (updatedDiff !== 0) return updatedDiff
|
||||
return parseDateMs(b.createdAt) - parseDateMs(a.createdAt)
|
||||
})
|
||||
.sort(
|
||||
(a, b) => {
|
||||
const aInStock = a.variants.some(isVariantInStock)
|
||||
const bInStock = b.variants.some(isVariantInStock)
|
||||
if (aInStock !== bInStock) return aInStock ? -1 : 1
|
||||
|
||||
return (
|
||||
parseDateMs(b.representative.updatedAt) - parseDateMs(a.representative.updatedAt)
|
||||
)
|
||||
},
|
||||
)
|
||||
const representative = sorted[0]!
|
||||
const { displayPrice, displayDiscountedPrice } = pickDisplayPrice(sorted)
|
||||
|
||||
return {
|
||||
productId: representative.productId,
|
||||
productTitle: representative.productTitle,
|
||||
productNameFa: representative.productNameFa,
|
||||
productImage: representative.productImage,
|
||||
productTotalStock: representative.productTotalStock,
|
||||
variantCount: sorted.length,
|
||||
variants: sorted,
|
||||
representative,
|
||||
displayPrice,
|
||||
displayDiscountedPrice,
|
||||
showFestival: sorted.some(
|
||||
(variant) => variant.isFestival || (variant.rewardPoints ?? 0) > 0,
|
||||
),
|
||||
}
|
||||
})
|
||||
|
||||
if (productOrder && productOrder.length > 0) {
|
||||
const indexById = new Map(productOrder.map((id, index) => [id, index]))
|
||||
return listings.sort((a, b) => {
|
||||
const ai = indexById.get(a.productId) ?? Number.MAX_SAFE_INTEGER
|
||||
const bi = indexById.get(b.productId) ?? Number.MAX_SAFE_INTEGER
|
||||
return ai - bi
|
||||
})
|
||||
}
|
||||
|
||||
return listings.sort((a, b) => {
|
||||
const aInStock = a.variants.some(isVariantInStock)
|
||||
const bInStock = b.variants.some(isVariantInStock)
|
||||
if (aInStock !== bInStock) return aInStock ? -1 : 1
|
||||
|
||||
return parseDateMs(b.representative.updatedAt) - parseDateMs(a.representative.updatedAt)
|
||||
})
|
||||
}
|
||||
|
||||
export function formatVariantCount(count: number, locale: 'en' | 'fa' = 'en'): string {
|
||||
|
||||
Reference in New Issue
Block a user