feat(admin-web): show brand quota alongside question quota on brands page
Frontend CI / Frontend (push) Successful in 3m44s
Backend CI / Backend (push) Successful in 16m18s

Display used/max brand count next to the existing question quota in the
brands page header, laid out as a two-column grid that collapses to full
width on narrow viewports.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-24 09:25:51 +08:00
parent 348f2e3451
commit 2133295ce2
+36 -4
View File
@@ -131,12 +131,19 @@ const orderedBrands = computed(() => {
}) })
const canSortBrands = computed(() => brandList.value.length > 1) const canSortBrands = computed(() => brandList.value.length > 1)
const hasBrandOrderChanges = computed( const hasBrandOrderChanges = computed(
() => !isSameBrandOrder(draftBrandIds.value, brandList.value.map((brand) => brand.id)), () =>
!isSameBrandOrder(
draftBrandIds.value,
brandList.value.map((brand) => brand.id),
),
) )
const currentQuestions = computed(() => questionsQuery.data.value?.items ?? []) const currentQuestions = computed(() => questionsQuery.data.value?.items ?? [])
const questionTotal = computed(() => questionsQuery.data.value?.total ?? 0) const questionTotal = computed(() => questionsQuery.data.value?.total ?? 0)
const maxBrands = computed(() => brandLibrarySummary.value?.max_brands ?? 0)
const usedBrands = computed(() => brandLibrarySummary.value?.used_brands ?? brandList.value.length)
const maxQuestions = computed( const maxQuestions = computed(
() => () =>
brandLibrarySummary.value?.max_questions ?? brandLibrarySummary.value?.max_questions ??
@@ -638,10 +645,16 @@ async function invalidateBrandQueries(): Promise<void> {
<p class="eyebrow">{{ t('brands.eyebrow') }}</p> <p class="eyebrow">{{ t('brands.eyebrow') }}</p>
<h2>{{ t('brands.title') }}</h2> <h2>{{ t('brands.title') }}</h2>
</div> </div>
<div class="brand-page-head__quotas">
<div class="brand-page-head__quota">
<span>{{ t('brands.quota.brands') }}</span>
<strong>{{ usedBrands }} / {{ maxBrands || '--' }}</strong>
</div>
<div class="brand-page-head__quota"> <div class="brand-page-head__quota">
<span>{{ t('brands.quota.questions') }}</span> <span>{{ t('brands.quota.questions') }}</span>
<strong>{{ usedQuestions }} / {{ maxQuestions || '--' }}</strong> <strong>{{ usedQuestions }} / {{ maxQuestions || '--' }}</strong>
</div> </div>
</div>
</section> </section>
<section class="brand-rail"> <section class="brand-rail">
@@ -1020,11 +1033,21 @@ async function invalidateBrandQueries(): Promise<void> {
font-weight: 760; font-weight: 760;
} }
.brand-page-head__quotas {
display: grid;
grid-template-columns: repeat(2, minmax(150px, 1fr));
align-items: stretch;
}
.brand-page-head__quota { .brand-page-head__quota {
min-width: 132px; display: flex;
padding-left: 18px; flex-direction: column;
align-items: center;
justify-content: center;
min-width: 0;
padding: 0 24px;
border-left: 1px solid #e2e8f0; border-left: 1px solid #e2e8f0;
text-align: right; text-align: center;
} }
.brand-page-head__quota span { .brand-page-head__quota span {
@@ -1335,6 +1358,15 @@ async function invalidateBrandQueries(): Promise<void> {
justify-content: flex-start; justify-content: flex-start;
} }
.brand-page-head__quotas {
width: 100%;
}
.brand-page-head__quota {
min-width: 0;
padding: 0 12px;
}
.brand-detail__actions { .brand-detail__actions {
justify-content: flex-start; justify-content: flex-start;
} }