Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<q-page class="q-pa-xs pricing-page">
|
||||
<q-inner-loading :showing="pageBusy">
|
||||
<q-spinner-gears size="52px" color="primary" />
|
||||
</q-inner-loading>
|
||||
|
||||
<div class="top-bar row items-center justify-between q-mb-xs">
|
||||
<div class="text-subtitle1 text-weight-bold">Urun Fiyatlandirma</div>
|
||||
<div class="top-actions">
|
||||
@@ -13,6 +17,7 @@
|
||||
map-options
|
||||
:options="topUrunIlkGrubuOptions"
|
||||
:loading="Boolean(serverFilterLoading.urunIlkGrubu)"
|
||||
:disable="pageBusy"
|
||||
label="Urun Ilk Grubu"
|
||||
style="min-width: 220px"
|
||||
@filter="onTopFilterSearchUrunIlkGrubu"
|
||||
@@ -29,6 +34,7 @@
|
||||
map-options
|
||||
:options="topUrunAnaGrubuOptions"
|
||||
:loading="Boolean(serverFilterLoading.urunAnaGrubu)"
|
||||
:disable="pageBusy"
|
||||
label="Urun Ana Grubu (max 3)"
|
||||
style="min-width: 260px"
|
||||
@filter="onTopFilterSearchUrunAnaGrubu"
|
||||
@@ -38,7 +44,7 @@
|
||||
color="primary"
|
||||
icon="filter_alt"
|
||||
label="Gruplari Getir"
|
||||
:disable="!canFetchByGroup"
|
||||
:disable="pageBusy || !canFetchByGroup"
|
||||
:loading="store.loading"
|
||||
@click="reloadData({ page: 1 })"
|
||||
/>
|
||||
@@ -47,6 +53,7 @@
|
||||
color="grey-7"
|
||||
icon="restart_alt"
|
||||
label="Secimleri Sifirla"
|
||||
:disable="pageBusy"
|
||||
@click="resetGroupSelections"
|
||||
/>
|
||||
</div>
|
||||
@@ -59,6 +66,7 @@
|
||||
color="grey-8"
|
||||
icon="view_sidebar"
|
||||
:label="leftDetailsExpanded ? 'Detaylari Gizle' : 'Detaylari Goster'"
|
||||
:disable="pageBusy"
|
||||
@click="leftDetailsExpanded = !leftDetailsExpanded"
|
||||
/>
|
||||
<q-btn-dropdown dense color="secondary" outline icon="view_module" label="Doviz Gorunumu" :auto-close="false">
|
||||
@@ -75,6 +83,7 @@
|
||||
<q-checkbox
|
||||
:model-value="isCurrencySelected(option.value)"
|
||||
dense
|
||||
:disable="pageBusy"
|
||||
@update:model-value="(val) => toggleCurrency(option.value, val)"
|
||||
@click.stop
|
||||
/>
|
||||
@@ -92,7 +101,7 @@
|
||||
:color="showSelectedOnly ? 'primary' : 'grey-7'"
|
||||
:icon="showSelectedOnly ? 'checklist_rtl' : 'list_alt'"
|
||||
:label="showSelectedOnly ? `Secililer (${selectedRowCount})` : 'Secili Olanlari Getir'"
|
||||
:disable="!showSelectedOnly && selectedRowCount === 0"
|
||||
:disable="pageBusy || (!showSelectedOnly && selectedRowCount === 0)"
|
||||
@click="toggleShowSelectedOnly"
|
||||
/>
|
||||
<q-btn
|
||||
@@ -101,7 +110,7 @@
|
||||
outline
|
||||
icon="calculate"
|
||||
label="Secilileri Hesapla"
|
||||
:disable="selectedRowCount === 0 || bulkCalcLoading"
|
||||
:disable="pageBusy || selectedRowCount === 0 || bulkCalcLoading"
|
||||
:loading="bulkCalcLoading"
|
||||
@click="calculateSelectedRows"
|
||||
/>
|
||||
@@ -110,7 +119,7 @@
|
||||
color="primary"
|
||||
icon="save"
|
||||
:label="saveButtonLabel"
|
||||
:disable="selectedDirtyCount === 0 || saving"
|
||||
:disable="pageBusy || selectedDirtyCount === 0 || saving"
|
||||
:loading="saving"
|
||||
@click="saveSelectedRows"
|
||||
/>
|
||||
@@ -146,6 +155,7 @@
|
||||
:max-pages="8"
|
||||
boundary-links
|
||||
direction-links
|
||||
:disable="pageBusy"
|
||||
@update:model-value="onPageChange"
|
||||
/>
|
||||
<div class="text-caption text-grey-8">
|
||||
@@ -157,9 +167,6 @@
|
||||
</div>
|
||||
|
||||
<div class="table-wrap" :style="{ '--sticky-scroll-comp': `${stickyScrollComp}px` }">
|
||||
<q-inner-loading :showing="saving || bulkCalcLoading">
|
||||
<q-spinner-gears size="46px" color="primary" />
|
||||
</q-inner-loading>
|
||||
<div v-if="showGuidanceOverlay" class="empty-overlay">
|
||||
<div class="empty-overlay-inner">
|
||||
<div class="text-subtitle1 text-weight-bold">Calismaya Baslamak Icin</div>
|
||||
@@ -835,6 +842,9 @@ import api, { download } from 'src/services/api'
|
||||
|
||||
const $q = useQuasar()
|
||||
const store = useProductPricingStore()
|
||||
|
||||
const isReloading = ref(false)
|
||||
const pageBusy = computed(() => Boolean(isReloading.value || store.loading || saving.value || bulkCalcLoading.value || exportAllLoading.value))
|
||||
const PAGE_LIMIT = 250
|
||||
const currentPage = ref(1)
|
||||
let reloadTimer = null
|
||||
@@ -2451,7 +2461,9 @@ async function fetchChunk ({ page = 1, useCache = true } = {}) {
|
||||
}
|
||||
|
||||
async function reloadData ({ page = 1, useCache = true } = {}) {
|
||||
if (isReloading.value) return
|
||||
const startedAt = Date.now()
|
||||
isReloading.value = true
|
||||
console.info('[product-pricing][ui] reload:start', {
|
||||
at: new Date(startedAt).toISOString()
|
||||
})
|
||||
@@ -2469,6 +2481,10 @@ async function reloadData ({ page = 1, useCache = true } = {}) {
|
||||
has_error: Boolean(store.error)
|
||||
})
|
||||
await bindHorizontalScrollSync()
|
||||
// Let the table render before we re-enable actions (prevents double-submits while the UI is still updating).
|
||||
await nextTick()
|
||||
await new Promise((resolve) => setTimeout(resolve, 0))
|
||||
isReloading.value = false
|
||||
}
|
||||
|
||||
// Full "fetch all pages" is intentionally avoided; keep server-side paging for performance.
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<q-page class="q-pa-xs pricing-page">
|
||||
<q-inner-loading :showing="pageBusy">
|
||||
<q-spinner-gears size="52px" color="primary" />
|
||||
</q-inner-loading>
|
||||
|
||||
<div class="top-bar row items-center justify-between q-mb-xs">
|
||||
<div class="text-subtitle1 text-weight-bold">Toptan Kampanya Yonetimi</div>
|
||||
<div class="top-actions">
|
||||
@@ -13,6 +17,7 @@
|
||||
map-options
|
||||
:options="topUrunIlkGrubuOptions"
|
||||
:loading="Boolean(serverFilterLoading.urunIlkGrubu)"
|
||||
:disable="pageBusy"
|
||||
label="Urun Ilk Grubu"
|
||||
style="min-width: 220px"
|
||||
@filter="onTopFilterSearchUrunIlkGrubu"
|
||||
@@ -29,6 +34,7 @@
|
||||
map-options
|
||||
:options="topUrunAnaGrubuOptions"
|
||||
:loading="Boolean(serverFilterLoading.urunAnaGrubu)"
|
||||
:disable="pageBusy"
|
||||
label="Urun Ana Grubu (max 3)"
|
||||
style="min-width: 260px"
|
||||
@filter="onTopFilterSearchUrunAnaGrubu"
|
||||
@@ -38,7 +44,7 @@
|
||||
color="primary"
|
||||
icon="filter_alt"
|
||||
label="Gruplari Getir"
|
||||
:disable="!canFetchByGroup"
|
||||
:disable="pageBusy || !canFetchByGroup"
|
||||
:loading="store.loading"
|
||||
@click="reloadData({ page: 1 })"
|
||||
/>
|
||||
@@ -47,6 +53,7 @@
|
||||
color="grey-7"
|
||||
icon="restart_alt"
|
||||
label="Secimleri Sifirla"
|
||||
:disable="pageBusy"
|
||||
@click="resetGroupSelections"
|
||||
/>
|
||||
</div>
|
||||
@@ -59,6 +66,7 @@
|
||||
color="grey-8"
|
||||
icon="view_sidebar"
|
||||
:label="leftDetailsExpanded ? 'Detaylari Gizle' : 'Detaylari Goster'"
|
||||
:disable="pageBusy"
|
||||
@click="leftDetailsExpanded = !leftDetailsExpanded"
|
||||
/>
|
||||
<q-btn-dropdown dense color="secondary" outline icon="view_module" label="Gosterge Fiyat Sec" :auto-close="false">
|
||||
@@ -75,6 +83,7 @@
|
||||
<q-checkbox
|
||||
:model-value="isPriceOptionSelected(option.value)"
|
||||
dense
|
||||
:disable="pageBusy"
|
||||
@update:model-value="(val) => togglePriceOption(option.value, val)"
|
||||
@click.stop
|
||||
/>
|
||||
@@ -106,7 +115,7 @@
|
||||
:color="showSelectedOnly ? 'primary' : 'grey-7'"
|
||||
:icon="showSelectedOnly ? 'checklist_rtl' : 'list_alt'"
|
||||
:label="showSelectedOnly ? `Secililer (${selectedRowCount})` : 'Secili Olanlari Getir'"
|
||||
:disable="!showSelectedOnly && selectedRowCount === 0"
|
||||
:disable="pageBusy || (!showSelectedOnly && selectedRowCount === 0)"
|
||||
@click="toggleShowSelectedOnly"
|
||||
/>
|
||||
<q-btn
|
||||
@@ -114,7 +123,7 @@
|
||||
color="primary"
|
||||
icon="save"
|
||||
:label="saveButtonLabel"
|
||||
:disable="selectedDirtyCount === 0 || saving"
|
||||
:disable="pageBusy || selectedDirtyCount === 0 || saving"
|
||||
:loading="saving"
|
||||
@click="saveSelectedRows"
|
||||
/>
|
||||
@@ -150,6 +159,7 @@
|
||||
:max-pages="8"
|
||||
boundary-links
|
||||
direction-links
|
||||
:disable="pageBusy"
|
||||
@update:model-value="onPageChange"
|
||||
/>
|
||||
<div class="text-caption text-grey-8">
|
||||
@@ -161,9 +171,6 @@
|
||||
</div>
|
||||
|
||||
<div class="table-wrap" :style="{ '--sticky-scroll-comp': `${stickyScrollComp}px` }">
|
||||
<q-inner-loading :showing="saving">
|
||||
<q-spinner-gears size="46px" color="primary" />
|
||||
</q-inner-loading>
|
||||
<div v-if="showGuidanceOverlay" class="empty-overlay">
|
||||
<div class="empty-overlay-inner">
|
||||
<div class="text-subtitle1 text-weight-bold">Calismaya Baslamak Icin</div>
|
||||
@@ -840,6 +847,9 @@ import api, { download } from 'src/services/api'
|
||||
|
||||
const $q = useQuasar()
|
||||
const store = useProductPricingStore()
|
||||
|
||||
const isReloading = ref(false)
|
||||
const pageBusy = computed(() => Boolean(isReloading.value || store.loading || variantLoading.value || saving.value || exportAllLoading.value))
|
||||
// Variant rows explode product rows; keep this smaller than ProductPricing for responsiveness.
|
||||
const PAGE_LIMIT = 50
|
||||
const currentPage = ref(1)
|
||||
@@ -2618,7 +2628,9 @@ async function buildVariantRowsForProductPage (baseProductRows = []) {
|
||||
}
|
||||
|
||||
async function reloadData ({ page = 1, useCache = true } = {}) {
|
||||
if (isReloading.value) return
|
||||
const startedAt = Date.now()
|
||||
isReloading.value = true
|
||||
console.info('[product-pricing][ui] reload:start', {
|
||||
at: new Date(startedAt).toISOString()
|
||||
})
|
||||
@@ -2640,6 +2652,9 @@ async function reloadData ({ page = 1, useCache = true } = {}) {
|
||||
has_error: Boolean(store.error)
|
||||
})
|
||||
await bindHorizontalScrollSync()
|
||||
await nextTick()
|
||||
await new Promise((resolve) => setTimeout(resolve, 0))
|
||||
isReloading.value = false
|
||||
}
|
||||
|
||||
// Full "fetch all pages" is intentionally avoided; keep server-side paging for performance.
|
||||
|
||||
Reference in New Issue
Block a user