Skip to content

Commit

Permalink
Change the filters to a new structure
Browse files Browse the repository at this point in the history
  • Loading branch information
ysbrandB committed Jun 7, 2024
1 parent fc38afc commit dd99bc6
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 27 deletions.
23 changes: 10 additions & 13 deletions app/Http/Controllers/ItemController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,18 @@ public function index(Request $request)
{
$filters = $request->input('filters');
$items = Item::query();
foreach($filters ?? [] as $filterId => $values){
//binnen een categorie is een filter een or, tussen de categorieën is het een and
$items = $items->orWhereHas('attributes', function($query) use ($values){
$query->whereIn('attributes.id', $values);
});
foreach (json_decode($filters) ?? (object)[] as $attributeCategoryId => $attributeCategory) {
if ($attributeCategory->attributes) {
$items->whereHas('attributes', function ($query) use ($attributeCategoryId, $attributeCategory) {
$query->where('attribute_type_id', $attributeCategoryId)->whereIn('attributes.id', array_column($attributeCategory->attributes, 'id'));
});
}
}

//item a => a, c, d
//item b => a, b, d
//filter: a, c
//zelfde categorie => or = a of c => a and b
//andere categorie => and = a en c => a and c
return Inertia::render('Items/Index', [
'items' => $items->get(),
'attributeTypes' => AttributeType::with('attributes')->get(),
'filters' => $filters,
]);
}

Expand Down Expand Up @@ -65,10 +62,10 @@ public function store(StoreItemRequest $request)
*/
public function show(string $publicId)
{
$id = Hashids::decode($publicId);
$item = Item::query()->where('id', $id)->firstOrFail();
$id = Hashids::decode($publicId)[0];
$item = Item::with('attributes', 'attributes.attributeType')->findOrFail($id);
return Inertia::render('Items/Show', [
'item' => $item->with('attributes', 'attributes.attributeType')->first(),
'item' => $item,
]);
}

Expand Down
8 changes: 4 additions & 4 deletions app/Models/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\HigherOrderCollectionProxy;
use Vinkla\Hashids\Facades\Hashids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
Expand All @@ -27,7 +29,7 @@ class Item extends Model
use HasFactory;

/**
* @var \Illuminate\Support\HigherOrderCollectionProxy|mixed
* @var HigherOrderCollectionProxy|mixed
*/
protected $fillable = [
'title',
Expand All @@ -44,7 +46,7 @@ class Item extends Model
protected $with = ['attributes'];
protected $appends = ['public_id', 'photo_url', 'wiring_photo_url'];

public function attributes()
public function attributes(): BelongsToMany
{
return $this->belongsToMany(Attribute::class);
}
Expand All @@ -63,6 +65,4 @@ public function getPublicIdAttribute(): string
{
return Hashids::encode($this->id);
}


}
58 changes: 48 additions & 10 deletions resources/js/Pages/Items/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue";
import NavLink from "@/Components/NavLink.vue";
import OpeningComponent from "@/CustomComponents/OpeningComponent.vue";
import {nextTick, ref} from "vue";
import {computed, nextTick, ref} from "vue";
import {router} from "@inertiajs/vue3";
import Pill from "@/CustomComponents/Pill.vue";
const props = defineProps<{
items: {
Expand All @@ -20,25 +21,49 @@ const props = defineProps<{
title: string;
}[]
}[],
filters: {
[key: number]: number[];
};
}>();
const checkedAttributes = ref(new Map<number, number[]>());
const check = (typeId: number, attributeId: number, checked: boolean) => nextTick(() => {
//all the attributes that are checked
const checkedAttributes = ref(JSON.parse(props.filters) ?? {});
const check = (attributeType: { id: number }, attribute: { id: number }, checked: boolean) => nextTick(() => {
console.log(checkedAttributes.value, attributeType.id, attribute.id, checked)
if (checked) {
checkedAttributes.value.set(typeId, [...(checkedAttributes.value.get(typeId) || []), attributeId])
if (!Object.hasOwn(checkedAttributes.value, attributeType.id)) {
checkedAttributes.value[attributeType.id] = {
color: attributeType.color,
attributes: []
};
}
checkedAttributes.value[attributeType.id].attributes.push(attribute);
} else {
checkedAttributes.value.set(typeId, (checkedAttributes.value.get(typeId) || []).filter(id => id !== attributeId))
checkedAttributes.value[attributeType.id].attributes = checkedAttributes.value[attributeType.id].attributes.filter((oldAttribute: any) => oldAttribute.id !== attribute.id);
}
checkedAttributes.value = new Map([...checkedAttributes.value].filter(([_, value]) => value.length > 0))
//filter out the attribute type if there are no attributes
checkedAttributes.value = Object.fromEntries(Object.entries(checkedAttributes.value).filter(([key, value]) => value.attributes.length > 0));
router.reload({
data: {
filters: Object.fromEntries(checkedAttributes.value)
filters: JSON.stringify(checkedAttributes.value)
}
})
console.log(checkedAttributes.value);
});
console.log(route('attribute_types.create'));
const removeFilter = (attributeType, attribute) => {
checkedAttributes.value[attributeType.id].attributes = checkedAttributes.value[attributeType.id].attributes.filter((oldAttribute: any) => oldAttribute.id !== attribute.id);
//filter out the attribute type if there are no attributes
checkedAttributes.value = Object.fromEntries(Object.entries(checkedAttributes.value).filter(([key, value]) => value.attributes.length > 0));
router.reload({
data: {
filters: JSON.stringify(checkedAttributes.value)
}
})
}
</script>

<template>
Expand All @@ -63,9 +88,21 @@ console.log(route('attribute_types.create'));
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 pb-4">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg mt-4">
<div class="w-full text-2xl text-center font-semibold mt-4">Filters</div>
<div class="mx-2 flex flex-wrap text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg dark:bg-gray-700 dark:border-gray-600 dark:text-white">
<template v-for="(attributeType, idx) in checkedAttributes">
<pill class="cursor-pointer" @click="check({id:idx}, attribute, false)"
v-for="attribute in attributeType.attributes" :key="attribute.id"
:color="attributeType.color">
{{ attribute.title }} <span class="ms-2 text-red-600">x</span>
</pill>
</template>
<div v-if="Object.entries(checkedAttributes)<=0" class="w-full p-2 text-center text-gray-500">
No filters applied
</div>
</div>
<OpeningComponent v-for="attributeType in attributeTypes" :title="attributeType.title">
<template #title>
<div class="font-bold text-2xl p-3 rounded rounded-lg"
<div class="font-bold text-lg p-3 rounded rounded-lg"
:class="`bg-${attributeType.color}-100`">{{ attributeType.title }}
</div>
</template>
Expand All @@ -75,7 +112,8 @@ console.log(route('attribute_types.create'));
class="w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600">
<div class="flex items-center ps-3">
<input type="checkbox"
@change="check(attributeType.id, attribute.id, ($event as HTMLInputElement).target.checked)"
:checked="Object.hasOwn(checkedAttributes, attributeType.id) && checkedAttributes[attributeType.id].attributes.some((checkedAttribute: any) => checkedAttribute.id === attribute.id)"
@change="check(attributeType, attribute, ($event as HTMLInputElement).target.checked)"
:id="attribute.id.toString()" :value="attribute.id"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label :for="attribute.id.toString()"
Expand Down

0 comments on commit dd99bc6

Please sign in to comment.