This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
import { useCatalogSearch } from "@/composables/useCatalogSearch.js";
|
||||
@@ -16,6 +16,7 @@ const route = useRoute();
|
||||
const router = useRouter();
|
||||
const categories = ref([]);
|
||||
const conditions = ref([]);
|
||||
const filtersOpen = ref(false);
|
||||
const {
|
||||
query,
|
||||
category,
|
||||
@@ -52,6 +53,33 @@ const {
|
||||
initialPage: Number.parseInt(route.query.page, 10) || 1,
|
||||
});
|
||||
|
||||
const activeFilterCount = computed(() => [
|
||||
category.value,
|
||||
conditionId.value,
|
||||
setName.value,
|
||||
eventName.value,
|
||||
tag.value,
|
||||
status.value,
|
||||
newlyAdded.value,
|
||||
typeof minPriceMinor.value === "number",
|
||||
typeof maxPriceMinor.value === "number",
|
||||
sort.value !== "recent",
|
||||
].filter(Boolean).length);
|
||||
|
||||
function resetFilters() {
|
||||
category.value = "";
|
||||
conditionId.value = "";
|
||||
setName.value = "";
|
||||
eventName.value = "";
|
||||
tag.value = "";
|
||||
status.value = "";
|
||||
newlyAdded.value = false;
|
||||
minPriceMinor.value = undefined;
|
||||
maxPriceMinor.value = undefined;
|
||||
sort.value = "recent";
|
||||
page.value = 1;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([
|
||||
load(),
|
||||
@@ -120,7 +148,29 @@ watch(
|
||||
placeholder="Try Charizard, 151, plush..."
|
||||
/>
|
||||
</label>
|
||||
<div class="catalog-filters">
|
||||
<div class="catalog-filter-toolbar">
|
||||
<button
|
||||
class="catalog-filter-toggle"
|
||||
type="button"
|
||||
:aria-expanded="filtersOpen"
|
||||
aria-controls="catalog-filter-panel"
|
||||
@click="filtersOpen = !filtersOpen"
|
||||
>
|
||||
Filters<span v-if="activeFilterCount"> ({{ activeFilterCount }})</span>
|
||||
</button>
|
||||
<button
|
||||
v-if="activeFilterCount"
|
||||
class="catalog-filter-reset"
|
||||
type="button"
|
||||
@click="resetFilters"
|
||||
>
|
||||
Reset filters
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="catalog-filter-panel"
|
||||
:class="['catalog-filters', { 'catalog-filters--open': filtersOpen }]"
|
||||
>
|
||||
<CatalogTextFilter v-model="setName" label="Set" placeholder="SV151" />
|
||||
<CatalogTextFilter v-model="eventName" label="Event" placeholder="Worlds" />
|
||||
<CatalogTextFilter v-model="tag" label="Tag" placeholder="binder" />
|
||||
@@ -212,3 +262,44 @@ watch(
|
||||
</section>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.catalog-filter-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-3);
|
||||
margin-top: var(--space-4);
|
||||
}
|
||||
|
||||
.catalog-filter-toggle,
|
||||
.catalog-filter-reset {
|
||||
min-height: 44px;
|
||||
border: var(--border-thin) solid var(--color-border-strong);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-2) var(--space-3);
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.catalog-filter-reset {
|
||||
border-color: transparent;
|
||||
color: var(--color-interactive-text);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.catalog-filters {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.catalog-filters.catalog-filters--open {
|
||||
display: grid;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.catalog-filter-toolbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -167,6 +167,7 @@ Remaining roadmap areas are approved external provider credentials/adapters, bro
|
||||
- Public catalog filtering now supports URL-synchronized set, event, and tag text filters through a reusable atomic text-filter control and the shared search API.
|
||||
- Public catalog filtering now supports explicit Available, Pending, Sold, and All status modes plus a 30-day Newly added toggle through the shared search API and atomic controls.
|
||||
- Public catalog sorting now supports latest manual/calculated market value low-to-high and high-to-low, with null values placed last.
|
||||
- Public catalog filters now collapse behind an accessible mobile disclosure, show an active-filter count, and provide a reset action while preserving URL synchronization.
|
||||
|
||||
## Local Commands
|
||||
|
||||
|
||||
Reference in New Issue
Block a user