Merge pull request #1029 from ae-utbm/product-filter

add club and counter filters on product list page
This commit is contained in:
thomas girod 2025-02-26 16:20:03 +01:00 committed by GitHub
commit 6a17e4480e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 64 additions and 23 deletions

View File

@ -464,7 +464,7 @@ body {
flex-wrap: wrap;
$col-gap: 1rem;
$row-gap: 0.5rem;
$row-gap: $col-gap / 3;
&.gap {
column-gap: $col-gap;

View File

@ -98,3 +98,5 @@ class ProductFilterSchema(FilterSchema):
is_archived: bool | None = Field(None, q="archived")
buying_groups: set[int] | None = Field(None, q="buying_groups__in")
product_type: set[int] | None = Field(None, q="product_type__in")
club: set[int] | None = Field(None, q="club__in")
counter: set[int] | None = Field(None, q="counters__in")

View File

@ -60,6 +60,8 @@ document.addEventListener("alpine:init", () => {
productStatus: "" as "active" | "archived" | "both",
search: "",
productTypes: [] as string[],
clubs: [] as string[],
counters: [] as string[],
pageSize: defaultPageSize,
page: defaultPage,
@ -67,13 +69,27 @@ document.addEventListener("alpine:init", () => {
const url = getCurrentUrlParams();
this.search = url.get("search") || "";
this.productStatus = url.get("productStatus") ?? "active";
const widget = this.$refs.productTypesInput.widget as TomSelect;
widget.on("change", (items: string[]) => {
const productTypesWidget = this.$refs.productTypesInput.widget as TomSelect;
productTypesWidget.on("change", (items: string[]) => {
this.productTypes = [...items];
});
const clubsWidget = this.$refs.clubsInput.widget as TomSelect;
clubsWidget.on("change", (items: string[]) => {
this.clubs = [...items];
});
const countersWidget = this.$refs.countersInput.widget as TomSelect;
countersWidget.on("change", (items: string[]) => {
this.counters = [...items];
});
await this.load();
const searchParams = ["search", "productStatus", "productTypes"];
const searchParams = [
"search",
"productStatus",
"productTypes",
"clubs",
"counters",
];
for (const param of searchParams) {
this.$watch(param, () => {
this.page = defaultPage;
@ -109,6 +125,8 @@ document.addEventListener("alpine:init", () => {
is_archived: isArchived,
// biome-ignore lint/style/useNamingConvention: api is in snake_case
product_type: [...this.productTypes],
club: [...this.clubs],
counter: [...this.counters],
},
};
},
@ -121,14 +139,17 @@ document.addEventListener("alpine:init", () => {
const options = this.getQueryParams();
const resp = await productSearchProductsDetailed(options);
this.nbPages = Math.ceil(resp.data.count / defaultPageSize);
this.products = resp.data.results.reduce<GroupedProducts>((acc, curr) => {
const key = curr.product_type?.name ?? gettext("Uncategorized");
if (!(key in acc)) {
acc[key] = [];
}
acc[key].push(curr);
return acc;
}, {});
this.products = resp.data.results.reduce<GroupedProducts>(
(acc: GroupedProducts, curr: ProductSchema) => {
const key = curr.product_type?.name ?? gettext("Uncategorized");
if (!(key in acc)) {
acc[key] = [];
}
acc[key].push(curr);
return acc;
},
{},
);
this.loading = false;
},

View File

@ -7,6 +7,7 @@
{% block additional_js %}
<script type="module" src="{{ static("bundled/counter/components/ajax-select-index.ts") }}"></script>
<script type="module" src="{{ static("bundled/club/components/ajax-select-index.ts") }}"></script>
<script type="module" src="{{ static("bundled/counter/product-list-index.ts") }}"></script>
{% endblock %}
@ -22,7 +23,6 @@
<h4 class="margin-bottom">{% trans %}Filter products{% endtrans %}</h4>
<form id="search-form" class="margin-bottom">
<div class="row gap-4x">
<fieldset>
<label for="search-input">{% trans %}Product name{% endtrans %}</label>
<input
@ -48,16 +48,34 @@
</div>
</fieldset>
</div>
<fieldset>
<label for="type-search-input">{% trans %}Product type{% endtrans %}</label>
<product-type-ajax-select
id="type-search-input"
name="product-type"
x-ref="productTypesInput"
multiple
>
</product-type-ajax-select>
</fieldset>
<div class="row gap-4x">
<fieldset class="grow">
<label for="type-search-input">{% trans %}Product type{% endtrans %}</label>
<product-type-ajax-select
id="type-search-input"
name="product-type"
x-ref="productTypesInput"
multiple
></product-type-ajax-select>
</fieldset>
<fieldset class="grow">
<label for="club-search-input">{% trans %}Clubs{% endtrans %}</label>
<club-ajax-select
id="club-search-input"
name="club"
x-ref="clubsInput"
multiple></club-ajax-select>
</fieldset>
<fieldset class="grow">
<label for="counter-search-input">{% trans %}Counters{% endtrans %}</label>
<counter-ajax-select
id="counter-search-input"
name="counter"
x-ref="countersInput"
multiple
></counter-ajax-select>
</fieldset>
</div>
</form>
<h3 class="margin-bottom">{% trans %}Product list{% endtrans %}</h3>