admin felület bekötése. pontosítások2
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
>
|
||||
<option value="all">{{ $t('garages.all_tiers') }}</option>
|
||||
<option
|
||||
v-for="tier in uniqueTiers"
|
||||
v-for="tier in availableTierNames"
|
||||
:key="tier"
|
||||
:value="tier"
|
||||
>
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
<!-- Content -->
|
||||
<template v-else>
|
||||
<!-- P0: Dynamic Stats Cards - based on real org_type data, not fake subscription tiers -->
|
||||
<!-- P0 HOTFIX: Global Stats Cards - always show unfiltered global counts -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 mb-8">
|
||||
<div class="bg-slate-800 rounded-xl border border-slate-700 p-4">
|
||||
<div class="flex items-center gap-3">
|
||||
@@ -78,7 +78,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-slate-400 uppercase tracking-wider">{{ $t('garages.total_garages') }}</p>
|
||||
<p class="text-2xl font-bold text-white">{{ garages.length }}</p>
|
||||
<p class="text-2xl font-bold text-white">{{ globalTotalCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,7 +91,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-slate-400 uppercase tracking-wider">{{ $t('garages.private_garages') }}</p>
|
||||
<p class="text-2xl font-bold text-emerald-400">{{ individualCount }}</p>
|
||||
<p class="text-2xl font-bold text-emerald-400">{{ globalIndividualCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -104,12 +104,17 @@
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-slate-400 uppercase tracking-wider">{{ $t('garages.corporate_garages') }}</p>
|
||||
<p class="text-2xl font-bold text-amber-400">{{ corporateCount }}</p>
|
||||
<p class="text-2xl font-bold text-amber-400">{{ globalCorporateCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- P0 HOTFIX: Filtered results indicator -->
|
||||
<div v-if="isFilterActive" class="mb-4 text-xs text-slate-500">
|
||||
Szűrt találat: <span class="text-slate-300 font-semibold">{{ garages.length }}</span> db
|
||||
</div>
|
||||
|
||||
<!-- Data Table -->
|
||||
<div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
@@ -143,7 +148,12 @@
|
||||
{{ getInitials(garageDisplayName(garage)) }}
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-white">{{ garageDisplayName(garage) }}</p>
|
||||
<NuxtLink
|
||||
:to="'/garages/' + garage.id"
|
||||
class="text-sm font-medium text-white hover:underline cursor-pointer hover:text-indigo-400 transition-colors"
|
||||
>
|
||||
{{ garageDisplayName(garage) }}
|
||||
</NuxtLink>
|
||||
<p class="text-xs text-slate-500">{{ garage.city || '—' }} · {{ garage.member_count }} {{ $t('garages.members') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -402,6 +412,10 @@ const searchQuery = ref('')
|
||||
const filterType = ref('all')
|
||||
const selectedPackage = ref('all')
|
||||
|
||||
// P0 HOTFIX: Accumulating tier names — never shrinks, only grows.
|
||||
// This prevents the dropdown from losing options when filtering by tier.
|
||||
const availableTierNames = ref<string[]>([])
|
||||
|
||||
// Modal state
|
||||
const showSubscriptionModal = ref(false)
|
||||
const selectedGarage = ref<Garage | null>(null)
|
||||
@@ -450,20 +464,30 @@ watch(selectedPackage, () => {
|
||||
|
||||
// ── Computed ───────────────────────────────────────────────────────
|
||||
|
||||
// P0: Dynamic stats based on real org_type from the database
|
||||
const individualCount = computed(() => garages.value.filter(g => g.org_type === 'individual').length)
|
||||
const corporateCount = computed(() => garages.value.filter(g => g.org_type !== 'individual').length)
|
||||
// P0 HOTFIX: Global stats stored from initial unfiltered load
|
||||
// These NEVER change when filters are applied, so the stat cards
|
||||
// always reflect the true database totals.
|
||||
const globalTotalCount = ref(0)
|
||||
const globalIndividualCount = ref(0)
|
||||
const globalCorporateCount = ref(0)
|
||||
|
||||
// P0: Extract unique subscription tier names for the filter dropdown
|
||||
const uniqueTiers = computed(() => {
|
||||
const tiers = new Set<string>()
|
||||
for (const g of garages.value) {
|
||||
// P0 HOTFIX: Detect if any filter is active
|
||||
const isFilterActive = computed(() => {
|
||||
return searchQuery.value !== '' || filterType.value !== 'all' || selectedPackage.value !== 'all'
|
||||
})
|
||||
|
||||
// P0 HOTFIX: Accumulating tier names — never shrinks, only grows.
|
||||
// Watcher on garages adds newly discovered tier names to availableTierNames.
|
||||
// This prevents the dropdown from losing options when filtering by tier.
|
||||
watch(garages, (newGarages) => {
|
||||
const currentSet = new Set(availableTierNames.value)
|
||||
for (const g of newGarages) {
|
||||
if (g.subscription_tier_name) {
|
||||
tiers.add(g.subscription_tier_name)
|
||||
currentSet.add(g.subscription_tier_name)
|
||||
}
|
||||
}
|
||||
return Array.from(tiers).sort()
|
||||
})
|
||||
availableTierNames.value = Array.from(currentSet).sort()
|
||||
}, { immediate: true, deep: true })
|
||||
|
||||
// P0: Server-side filtered — the API handles all filtering.
|
||||
// This computed is now a simple pass-through; the real filtering
|
||||
@@ -507,6 +531,16 @@ async function fetchGarages() {
|
||||
headers: getAuthHeaders(),
|
||||
})
|
||||
garages.value = response.garages
|
||||
|
||||
// P0 HOTFIX: Store global counts from unfiltered API response.
|
||||
// When no filters are active, the API returns the full dataset,
|
||||
// so we capture the global totals here. When filters ARE active,
|
||||
// we keep the previously captured global counts unchanged.
|
||||
if (!isFilterActive.value) {
|
||||
globalTotalCount.value = response.total
|
||||
globalIndividualCount.value = garages.value.filter(g => g.org_type === 'individual').length
|
||||
globalCorporateCount.value = garages.value.filter(g => g.org_type !== 'individual').length
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error('[Garages] Failed to fetch garages:', err)
|
||||
error.value = err?.data?.detail || err?.message || 'Failed to load garages'
|
||||
|
||||
Reference in New Issue
Block a user