@ -93,129 +93,128 @@ const seasonOptions: { value: string; label: string }[] = [
|
||||
<div class="showsbody">
|
||||
<!-- LEFT SIDEBAR -->
|
||||
<aside class="showsaside">
|
||||
<div class="showsaside-head">
|
||||
<h2 class="showsaside-h">REFINE</h2>
|
||||
</div>
|
||||
<div class="showsaside-head">
|
||||
<h2 class="showsaside-h">REFINE</h2>
|
||||
</div>
|
||||
|
||||
<div class="showsaside-body">
|
||||
<!-- Designer 多选 -->
|
||||
<section class="showsg">
|
||||
<header class="showsg-h" @click="toggleGroup('designers')">
|
||||
<span>DESIGNERS</span>
|
||||
<span class="showsg-right">
|
||||
<span class="showsg-count" x-text="selectedBrands.length">0</span>
|
||||
<span class="showsg-chev" :class="{ 'is-collapsed': collapsedGroups.designers }">
|
||||
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
</span>
|
||||
</header>
|
||||
<div class="showsg-b" x-show="!collapsedGroups.designers">
|
||||
<ul class="showschecks">
|
||||
<template x-for="b in hotBrands.slice(0, 10)" :key="b.id">
|
||||
<li>
|
||||
<label class="flex items-center gap-2 w-full cursor-pointer">
|
||||
<input type="checkbox" :value="b.id" :checked="selectedBrands.includes(b.id)" @change="toggleBrand(b.id)" />
|
||||
<span x-text="b.name"></span>
|
||||
<span class="ct" x-text="b.article_count ? b.article_count : ''"></span>
|
||||
</label>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<a class="showsmore" @click="openBrandModal()" x-text="'ALL BRANDS +'" role="button" tabindex="0"></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Collection type -->
|
||||
<section class="showsg">
|
||||
<header class="showsg-h" @click="toggleGroup('collection')">
|
||||
<span>COLLECTION</span>
|
||||
<span class="showsg-chev" :class="{ 'is-collapsed': collapsedGroups.collection }">
|
||||
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
</header>
|
||||
<div class="showsg-b" x-show="!collapsedGroups.collection">
|
||||
<ul class="showschecks showschecks--flat">
|
||||
{collectionOptions.map((o) => (
|
||||
<li><label><input type="checkbox" value={o.value} x-model="selectedCt" @change="refreshFilter()" /> <span>{o.label}</span></label></li>
|
||||
))}
|
||||
<div class="showsaside-body">
|
||||
<!-- Designer 多选 -->
|
||||
<section class="showsg">
|
||||
<header class="showsg-h" @click="toggleGroup('designers')">
|
||||
<span>{t('brands')}</span>
|
||||
<span class="showsg-right">
|
||||
<span class="showsg-chev" :class="{ 'is-collapsed': collapsedGroups.designers }">
|
||||
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
</span>
|
||||
</header>
|
||||
<div class="showsg-b" x-show="!collapsedGroups.designers">
|
||||
<ul class="showschecks">
|
||||
<template x-for="b in hotBrands.slice(0, 10)" :key="b.id">
|
||||
<li>
|
||||
<label class="flex items-center gap-2 w-full cursor-pointer">
|
||||
<input type="checkbox" :value="b.id" :checked="selectedBrands.includes(b.id)" @change="toggleBrand(b.id)" />
|
||||
<span x-text="b.name"></span>
|
||||
<span class="ct" x-text="b.article_count ? b.article_count : ''"></span>
|
||||
</label>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<a class="showsmore" @click="openBrandModal()" x-text="'ALL BRANDS +'" role="button" tabindex="0"></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Season -->
|
||||
<section class="showsg">
|
||||
<header class="showsg-h" @click="toggleGroup('season')">
|
||||
<span>SEASON</span>
|
||||
<span class="showsg-chev" :class="{ 'is-collapsed': collapsedGroups.season }">
|
||||
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
</header>
|
||||
<div class="showsg-b" x-show="!collapsedGroups.season">
|
||||
<ul class="showschecks showschecks--flat">
|
||||
{seasonOptions.map((o) => (
|
||||
<li><label><input type="checkbox" value={o.value} x-model="selectedSeason" @change="refreshFilter()" /> <span>{o.label}</span></label></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Collection type -->
|
||||
<section class="showsg">
|
||||
<header class="showsg-h" @click="toggleGroup('collection')">
|
||||
<span>COLLECTION</span>
|
||||
<span class="showsg-chev" :class="{ 'is-collapsed': collapsedGroups.collection }">
|
||||
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
</header>
|
||||
<div class="showsg-b" x-show="!collapsedGroups.collection">
|
||||
<ul class="showschecks showschecks--flat">
|
||||
{collectionOptions.map((o) => (
|
||||
<li><label><input type="checkbox" value={o.value} x-model="selectedCt" @change="refreshFilter()" /> <span>{o.label}</span></label></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Year -->
|
||||
<section class="showsg">
|
||||
<header class="showsg-h" @click="toggleGroup('year')">
|
||||
<span>YEAR</span>
|
||||
<span class="showsg-chev" :class="{ 'is-collapsed': collapsedGroups.year }">
|
||||
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
</header>
|
||||
<div class="showsg-b" x-show="!collapsedGroups.year">
|
||||
<ul class="showschecks showschecks--flat">
|
||||
{yearOptions.map((o) => (
|
||||
<li><label><input type="checkbox" value={String(o.value)} x-model="selectedYear" @change="refreshFilter()" /> <span>{o.label}</span></label></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Season -->
|
||||
<section class="showsg">
|
||||
<header class="showsg-h" @click="toggleGroup('season')">
|
||||
<span>SEASON</span>
|
||||
<span class="showsg-chev" :class="{ 'is-collapsed': collapsedGroups.season }">
|
||||
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
</header>
|
||||
<div class="showsg-b" x-show="!collapsedGroups.season">
|
||||
<ul class="showschecks showschecks--flat">
|
||||
{seasonOptions.map((o) => (
|
||||
<li><label><input type="checkbox" value={o.value} x-model="selectedSeason" @change="refreshFilter()" /> <span>{o.label}</span></label></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button class="showsclear" type="button" @click="clearAll()" x-show="pills.length > 0" x-cloak>Clear all ×</button>
|
||||
</div>
|
||||
<!-- Year -->
|
||||
<section class="showsg">
|
||||
<header class="showsg-h" @click="toggleGroup('year')">
|
||||
<span>YEAR</span>
|
||||
<span class="showsg-chev" :class="{ 'is-collapsed': collapsedGroups.year }">
|
||||
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
</header>
|
||||
<div class="showsg-b" x-show="!collapsedGroups.year">
|
||||
<ul class="showschecks showschecks--flat">
|
||||
{yearOptions.map((o) => (
|
||||
<li><label><input type="checkbox" value={String(o.value)} x-model="selectedYear" @change="refreshFilter()" /> <span>{o.label}</span></label></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button class="showsclear" type="button" @click="clearAll()" x-show="pills.length > 0" x-cloak>Clear all ×</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- MAIN GRID -->
|
||||
<main class="showsmain">
|
||||
<div class="showsgrid" :class="{ 'is-loading': loading }">
|
||||
|
||||
<!-- 骨架屏:结构与真实卡片完全一致,loading 期间占位,杜绝 加载中→数据完成 的尺寸抖动 -->
|
||||
<template x-if="loading && items.length === 0">
|
||||
<template x-for="i in skeletonCount" :key="'skel-'+i">
|
||||
<div class="showscard showscard--skel" aria-hidden="true">
|
||||
<div class="showscard-left">
|
||||
<div class="showscard-img"></div>
|
||||
</div>
|
||||
<div class="showscard-right">
|
||||
<div class="showscard-info">
|
||||
<div class="showsline h-[41px] mb-[10px] rounded-[2px]"></div>
|
||||
<div class="showsline h-[29px] mb-[14px] rounded-[2px]"></div>
|
||||
<div class="showsline h-[38px] rounded-[2px]"></div>
|
||||
</div>
|
||||
<div class="showscard-strip">
|
||||
<div class="showscard-thumb"></div>
|
||||
<div class="showscard-thumb"></div>
|
||||
<div class="showscard-thumb"></div>
|
||||
<div class="showscard-thumb"></div>
|
||||
<div class="showscard-thumb"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<div class="showsgrid" :class="{ 'is-loading': loading }">
|
||||
|
||||
<!-- 骨架屏:结构与真实卡片完全一致,loading 期间占位,杜绝 加载中→数据完成 的尺寸抖动 -->
|
||||
<template x-if="loading && items.length === 0">
|
||||
<template x-for="i in skeletonCount" :key="'skel-'+i">
|
||||
<div class="showscard showscard--skel" aria-hidden="true">
|
||||
<div class="showscard-left">
|
||||
<div class="showscard-img"></div>
|
||||
</div>
|
||||
<div class="showscard-right">
|
||||
<div class="showscard-info">
|
||||
<div class="showsline h-[41px] mb-[10px] rounded-[2px]"></div>
|
||||
<div class="showsline h-[29px] mb-[14px] rounded-[2px]"></div>
|
||||
<div class="showsline h-[38px] rounded-[2px]"></div>
|
||||
</div>
|
||||
<div class="showscard-strip">
|
||||
<div class="showscard-thumb"></div>
|
||||
<div class="showscard-thumb"></div>
|
||||
<div class="showscard-thumb"></div>
|
||||
<div class="showscard-thumb"></div>
|
||||
<div class="showscard-thumb"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- Empty State -->
|
||||
<template x-if="!loading && items.length === 0">
|
||||
<div class="showsempty">No shows match the current filters</div>
|
||||
</template>
|
||||
<!-- Empty State -->
|
||||
<template x-if="!loading && items.length === 0">
|
||||
<div class="showsempty">No shows match the current filters</div>
|
||||
</template>
|
||||
|
||||
<!-- Card List -->
|
||||
<template x-for="it in items" :key="it.id">
|
||||
<!-- Card List -->
|
||||
<template x-for="it in items" :key="it.id">
|
||||
<a class="showscard" :href="itemHref(it)" :aria-label="`${it.brand_name} ${it.title}`">
|
||||
<div class="showscard-left">
|
||||
<div class="showscard-img" :class="{ 'is-loaded': it._imgLoaded }">
|
||||
@ -238,12 +237,12 @@ const seasonOptions: { value: string; label: string }[] = [
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="showsloadmore-wrap" x-show="items.length > 0">
|
||||
<button class="showsloadmore" type="button" :disabled="loadingMore || isEnd" @click="loadPage(page + 1, true)" x-text="loadBtnText"></button>
|
||||
</div>
|
||||
<div class="showsloadmore-wrap" x-show="items.length > 0">
|
||||
<button class="showsloadmore" type="button" :disabled="loadingMore || isEnd" @click="loadPage(page + 1, true)" x-text="loadBtnText"></button>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user