diff --git a/ui/src/pages/OrderPriceList.vue b/ui/src/pages/OrderPriceList.vue
index b1c7022..5699016 100644
--- a/ui/src/pages/OrderPriceList.vue
+++ b/ui/src/pages/OrderPriceList.vue
@@ -363,8 +363,7 @@
:class="[props.col.classes, { 'sticky-col': isStickyCol(props.col.name), 'sticky-boundary': isStickyBoundary(props.col.name) }]"
:style="getBodyCellStyle(props.col)"
>
-
- -
+
@@ -505,7 +504,7 @@ const topUrunAnaGrubu = ref(null)
const selectedProductCodes = ref([])
const selectedCampaignLabels = ref([])
const campaignFilterSearch = ref('')
-const selectedPriceOptions = ref(priceOptions.map((x) => x.value))
+const selectedPriceOptions = ref(['usd5', 'try5'])
const leftDetailsExpanded = ref(true)
const rows = ref([])
@@ -815,7 +814,7 @@ async function reloadData ({ page = 1 } = {}) {
}
rows.value = buildRows(products, variants)
error.value = ''
- void loadImagesForRows(rows.value.slice(0, 120))
+ void loadImagesForRows(rows.value)
await nextTick()
} catch (err) {
rows.value = []
@@ -836,10 +835,18 @@ async function loadImagesForRows (list) {
seen.add(key)
targets.push({ row, key })
}
- await Promise.all(targets.map(async ({ row, key }) => {
+ const concurrency = 12
+ let cursor = 0
+ let loaded = 0
+ const workers = Array.from({ length: Math.min(concurrency, targets.length) }, async () => {
+ for (;;) {
+ const target = targets[cursor]
+ cursor += 1
+ if (!target) return
+ const { row, key } = target
if (imageCache.has(key)) {
row.imageUrl = imageCache.get(key)
- return
+ continue
}
try {
const res = await api.get('/product-images', {
@@ -858,7 +865,11 @@ async function loadImagesForRows (list) {
} catch {
imageCache.set(key, '')
}
- }))
+ loaded += 1
+ if (loaded % 12 === 0) rows.value = [...rows.value]
+ }
+ })
+ await Promise.all(workers)
rows.value = [...rows.value]
}
@@ -978,26 +989,29 @@ function col (name, label, field, width, extra = {}) {
const allColumns = [
col('image', '', 'imageUrl', 108, { align: 'center', classes: 'image-col sticky-col' }),
col('brandGroupSelection', 'MARKA GRUBU', 'brandGroupSelection', 86, { classes: 'ps-col sticky-col' }),
- col('marka', 'MARKA', 'marka', 62, { sortable: true, classes: 'ps-col sticky-col' }),
+ col('marka', 'MARKA', 'marka', 72, { sortable: true, classes: 'ps-col sticky-col' }),
col('productCode', 'URUN KODU', 'productCode', 112, { sortable: true, classes: 'ps-col product-code-col sticky-col' }),
- col('variantCodes', 'VARYANT', 'variantCodes', 112, { classes: 'ps-col variant-col sticky-col' }),
- col('variantStocks', 'STOK', 'stockQty', 62, { align: 'right', sortable: true, classes: 'ps-col variant-stock-col sticky-col' }),
+ col('variantCodes', 'VARYANT', 'variantCodes', 128, { classes: 'ps-col variant-col sticky-col' }),
+ col('variantStocks', 'STOK', 'stockQty', 72, { align: 'right', sortable: true, classes: 'ps-col variant-stock-col sticky-col' }),
col('campaignLabel', 'KAMPANYA', 'campaignLabel', 150, { classes: 'ps-col campaign-col sticky-col' }),
- col('campaignRate', 'IND %', 'campaignRate', 58, { align: 'right', classes: 'ps-col campaign-rate-col sticky-col' }),
- col('askiliYan', 'ASKILI YAN', 'askiliYan', 58, { sortable: true, classes: 'ps-col' }),
- col('kategori', 'KATEGORI', 'kategori', 58, { sortable: true, classes: 'ps-col' }),
- col('urunIlkGrubu', 'URUN ILK GRUBU', 'urunIlkGrubu', 70, { sortable: true, classes: 'ps-col' }),
- col('urunAnaGrubu', 'URUN ANA GRUBU', 'urunAnaGrubu', 74, { sortable: true, classes: 'ps-col' }),
- col('urunAltGrubu', 'URUN ALT GRUBU', 'urunAltGrubu', 74, { sortable: true, classes: 'ps-col' }),
- col('icerik', 'ICERIK', 'icerik', 66, { sortable: true, classes: 'ps-col' }),
- col('karisim', 'KARISIM', 'karisim', 66, { sortable: true, classes: 'ps-col' }),
+ col('campaignRate', 'IND %', 'campaignRate', 64, { align: 'right', classes: 'ps-col campaign-rate-col sticky-col' }),
+ col('askiliYan', 'ASKILI YAN', 'askiliYan', 72, { sortable: true, classes: 'ps-col' }),
+ col('kategori', 'KATEGORI', 'kategori', 82, { sortable: true, classes: 'ps-col' }),
+ col('urunIlkGrubu', 'URUN ILK GRUBU', 'urunIlkGrubu', 88, { sortable: true, classes: 'ps-col' }),
+ col('urunAnaGrubu', 'URUN ANA GRUBU', 'urunAnaGrubu', 96, { sortable: true, classes: 'ps-col' }),
+ col('urunAltGrubu', 'URUN ALT GRUBU', 'urunAltGrubu', 96, { sortable: true, classes: 'ps-col' }),
+ col('icerik', 'ICERIK', 'icerik', 112, { sortable: true, classes: 'ps-col' }),
+ col('karisim', 'KARISIM', 'karisim', 96, { sortable: true, classes: 'ps-col' }),
...campaignPairs.flatMap((p) => [
col(p.base, p.base.toUpperCase().replace(/([A-Z]+)(\d)/, '$1 $2'), p.base, 78, { align: 'right', classes: `${p.base.slice(0, 3)}-col` }),
col(p.derived, `${p.base.toUpperCase().replace(/([A-Z]+)(\d)/, '$1 $2')} KMP`, p.derived, 88, { align: 'right', classes: `${p.base.slice(0, 3)}-col campaign-price-col` })
])
]
-const hideableLeftDetailColumnNames = new Set([
+const compactHiddenColumnNames = new Set([
+ 'variantStocks',
+ 'campaignLabel',
+ 'campaignRate',
'askiliYan',
'kategori',
'urunIlkGrubu',
@@ -1010,7 +1024,7 @@ const hideableLeftDetailColumnNames = new Set([
const visibleColumns = computed(() => allColumns.filter((c) => {
if (/^(usd|eur|try)[1-6]$/.test(c.name)) return selectedPriceSet.value.has(c.name)
if (/^(usd|eur|try)[1-6]Campaign$/.test(c.name)) return selectedPriceSet.value.has(c.name.replace(/Campaign$/, ''))
- if (!leftDetailsExpanded.value && hideableLeftDetailColumnNames.has(c.name)) return false
+ if (!leftDetailsExpanded.value && compactHiddenColumnNames.has(c.name)) return false
return true
}))
@@ -1027,9 +1041,30 @@ const tableStyle = computed(() => ({
}))
const stickyColumnNames = computed(() => {
const visible = new Set(visibleColumns.value.map((x) => x.name))
- return ['image', 'brandGroupSelection', 'marka', 'productCode', 'variantCodes', 'variantStocks', 'campaignLabel', 'campaignRate'].filter((x) => visible.has(x))
+ const expanded = [
+ 'image',
+ 'brandGroupSelection',
+ 'marka',
+ 'productCode',
+ 'variantCodes',
+ 'variantStocks',
+ 'campaignLabel',
+ 'campaignRate',
+ 'askiliYan',
+ 'kategori',
+ 'urunIlkGrubu',
+ 'urunAnaGrubu',
+ 'urunAltGrubu',
+ 'icerik',
+ 'karisim'
+ ]
+ const compact = ['image', 'brandGroupSelection', 'marka', 'productCode', 'variantCodes']
+ return (leftDetailsExpanded.value ? expanded : compact).filter((x) => visible.has(x))
+})
+const stickyBoundaryColumnName = computed(() => {
+ const list = stickyColumnNames.value
+ return list.length ? list[list.length - 1] : ''
})
-const stickyBoundaryColumnName = 'campaignRate'
const stickyColumnNameSet = computed(() => new Set(stickyColumnNames.value))
const stickyLeftMap = computed(() => {
const map = {}
@@ -1043,8 +1078,9 @@ const stickyLeftMap = computed(() => {
return map
})
const stickyScrollComp = computed(() => {
- const boundaryCol = allColumns.find((x) => x.name === stickyBoundaryColumnName)
- return ((stickyLeftMap.value[stickyBoundaryColumnName] || 0) + extractWidth(boundaryCol?.style)) * 1.2
+ const boundaryName = stickyBoundaryColumnName.value
+ const boundaryCol = allColumns.find((x) => x.name === boundaryName)
+ return ((stickyLeftMap.value[boundaryName] || 0) + extractWidth(boundaryCol?.style)) * 1.2
})
function isStickyCol (name) {
@@ -1052,7 +1088,7 @@ function isStickyCol (name) {
}
function isStickyBoundary (name) {
- return name === stickyBoundaryColumnName
+ return name === stickyBoundaryColumnName.value
}
function getHeaderCellStyle (col) {
@@ -1081,12 +1117,11 @@ function exportCell (row, col) {
}
function exportVisibleExcel () {
- const cols = visibleColumns.value
+ const cols = visibleColumns.value.filter((c) => c.name !== 'image')
const body = filteredRows.value.map((row) => `
${cols.map((c) => {
- if (c.name === 'image' && row.imageUrl) return ` | `
return `${escapeHtml(exportCell(row, c))} | `
}).join('')}
`).join('')
- const html = `${cols.map((c) => `| ${escapeHtml(c.label || 'Gorsel')} | `).join('')}
${body}
`
+ const html = `${cols.map((c) => `| ${escapeHtml(c.label)} | `).join('')}
${body}
`
const blob = new Blob([html], { type: 'application/vnd.ms-excel;charset=utf-8' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
@@ -1184,7 +1219,7 @@ onMounted(() => {
display: flex;
flex-direction: column;
--pricing-row-height: 108px;
- --pricing-header-height: 72px;
+ --pricing-header-height: 88px;
--pricing-table-height: calc(100vh - 156px);
}
@@ -1315,6 +1350,13 @@ onMounted(() => {
border-bottom: 1px solid rgba(0, 0, 0, 0.08) !important;
}
+.pricing-table :deep(td) {
+ overflow: hidden !important;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ vertical-align: middle !important;
+}
+
.pricing-table :deep(th),
.pricing-table :deep(.q-table thead tr),
.pricing-table :deep(.q-table thead tr.header-row-fixed),
@@ -1328,9 +1370,10 @@ onMounted(() => {
.pricing-table :deep(th) {
padding-top: 0;
padding-bottom: 0;
- white-space: nowrap;
- word-break: normal;
- text-overflow: ellipsis;
+ white-space: normal;
+ word-break: break-word;
+ overflow-wrap: anywhere;
+ overflow: hidden;
text-align: center;
font-size: 10px;
font-weight: 800;
@@ -1411,15 +1454,22 @@ onMounted(() => {
width: 100%;
overflow: hidden;
text-align: center;
- text-overflow: ellipsis;
white-space: normal;
+ word-break: break-word;
+ overflow-wrap: anywhere;
font-weight: 800;
- line-height: 1.15;
+ line-height: 1.12;
display: -webkit-box;
- -webkit-line-clamp: 2;
+ -webkit-line-clamp: 4;
-webkit-box-orient: vertical;
}
+.campaign-badge {
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
.header-filter-btn {
width: 20px;
height: 20px;