Move member filter to separate component
This commit is contained in:
parent
f33a23ecc3
commit
27f805700e
|
@ -48,8 +48,7 @@ class FilterScope extends ScoutFilter
|
||||||
public ?bool $hasBirthday = null,
|
public ?bool $hasBirthday = null,
|
||||||
public ?bool $hasSvk = null,
|
public ?bool $hasSvk = null,
|
||||||
public ?bool $hasVk = null,
|
public ?bool $hasVk = null,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $options
|
* @param array<string, mixed> $options
|
||||||
|
@ -110,20 +109,20 @@ class FilterScope extends ScoutFilter
|
||||||
}
|
}
|
||||||
if ($this->subactivityIds && $this->activityIds) {
|
if ($this->subactivityIds && $this->activityIds) {
|
||||||
$combinations = $this->combinations($this->activityIds, $this->subactivityIds)
|
$combinations = $this->combinations($this->activityIds, $this->subactivityIds)
|
||||||
->map(fn ($combination) => implode('|', $combination))
|
->map(fn($combination) => implode('|', $combination))
|
||||||
->map(fn ($combination) => str($combination)->wrap('"'));
|
->map(fn($combination) => str($combination)->wrap('"'));
|
||||||
$filter->push($this->inExpression('memberships.both', $combinations));
|
$filter->push($this->inExpression('memberships.both', $combinations));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->memberships as $membership) {
|
foreach ($this->memberships as $membership) {
|
||||||
$filter->push($this->inExpression('memberships.with_group', $this->possibleValuesForMembership($membership)->map(fn ($value) => str($value)->wrap('"'))));
|
$filter->push($this->inExpression('memberships.with_group', $this->possibleValuesForMembership($membership)->map(fn($value) => str($value)->wrap('"'))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($this->exclude)) {
|
if (count($this->exclude)) {
|
||||||
$filter->push($this->notInExpression('id', $this->exclude));
|
$filter->push($this->notInExpression('id', $this->exclude));
|
||||||
}
|
}
|
||||||
|
|
||||||
$andFilter = $filter->map(fn ($expression) => "($expression)")->implode(' AND ');
|
$andFilter = $filter->map(fn($expression) => "($expression)")->implode(' AND ');
|
||||||
|
|
||||||
$options['filter'] = $this->implode(collect([$andFilter])->push($this->inExpression('id', $this->include)), 'OR');
|
$options['filter'] = $this->implode(collect([$andFilter])->push($this->inExpression('id', $this->include)), 'OR');
|
||||||
$options['sort'] = ['lastname:asc', 'firstname:asc'];
|
$options['sort'] = ['lastname:asc', 'firstname:asc'];
|
||||||
|
@ -137,7 +136,7 @@ class FilterScope extends ScoutFilter
|
||||||
*/
|
*/
|
||||||
protected function implode(Collection $values, string $between): string
|
protected function implode(Collection $values, string $between): string
|
||||||
{
|
{
|
||||||
return $values->filter(fn ($expression) => $expression)->implode(" {$between} ");
|
return $values->filter(fn($expression) => $expression)->implode(" {$between} ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,7 +176,7 @@ class FilterScope extends ScoutFilter
|
||||||
$membership['activity_ids'] = count($membership['activity_ids']) === 0 ? Activity::pluck('id')->toArray() : $membership['activity_ids'];
|
$membership['activity_ids'] = count($membership['activity_ids']) === 0 ? Activity::pluck('id')->toArray() : $membership['activity_ids'];
|
||||||
$membership['subactivity_ids'] = count($membership['subactivity_ids']) === 0 ? Subactivity::pluck('id')->toArray() : $membership['subactivity_ids'];
|
$membership['subactivity_ids'] = count($membership['subactivity_ids']) === 0 ? Subactivity::pluck('id')->toArray() : $membership['subactivity_ids'];
|
||||||
return $this->combinations($membership['group_ids'], $membership['activity_ids'], $membership['subactivity_ids'])
|
return $this->combinations($membership['group_ids'], $membership['activity_ids'], $membership['subactivity_ids'])
|
||||||
->map(fn ($combination) => collect($combination)->implode('|'));
|
->map(fn($combination) => collect($combination)->implode('|'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -191,7 +190,7 @@ class FilterScope extends ScoutFilter
|
||||||
|
|
||||||
if (!count($otherParts)) {
|
if (!count($otherParts)) {
|
||||||
/** @var Collection<int, Collection<int, int>> */
|
/** @var Collection<int, Collection<int, int>> */
|
||||||
return collect($firstPart)->map(fn ($p) => [$p]);
|
return collect($firstPart)->map(fn($p) => [$p]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var Collection<int, mixed> */
|
/** @var Collection<int, mixed> */
|
||||||
|
|
|
@ -136,8 +136,8 @@ class MemberResource extends JsonResource
|
||||||
$createActivities = Activity::remote()->with(['subactivities' => fn($q) => $q->remote()])->get();
|
$createActivities = Activity::remote()->with(['subactivities' => fn($q) => $q->remote()])->get();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'filterActivities' => Activity::where('is_filterable', true)->pluck('name', 'id'),
|
'filterActivities' => Activity::where('is_filterable', true)->get()->map(fn($a) => ['id' => $a->id, 'name' => $a->name]),
|
||||||
'filterSubactivities' => Subactivity::where('is_filterable', true)->pluck('name', 'id'),
|
'filterSubactivities' => Subactivity::where('is_filterable', true)->get()->map(fn($a) => ['id' => $a->id, 'name' => $a->name]),
|
||||||
'formActivities' => $activities->pluck('name', 'id'),
|
'formActivities' => $activities->pluck('name', 'id'),
|
||||||
'formSubactivities' => $activities->map(function (Activity $activity) {
|
'formSubactivities' => $activities->map(function (Activity $activity) {
|
||||||
return ['subactivities' => $activity->subactivities->pluck('name', 'id'), 'id' => $activity->id];
|
return ['subactivities' => $activity->subactivities->pluck('name', 'id'), 'id' => $activity->id];
|
||||||
|
|
|
@ -56,6 +56,11 @@ export function useIndex(props, siteName) {
|
||||||
reload(true);
|
reload(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setFilterObject(o) {
|
||||||
|
inner.filter.value = o;
|
||||||
|
reload(true);
|
||||||
|
}
|
||||||
|
|
||||||
startListener();
|
startListener();
|
||||||
onBeforeUnmount(() => stopListener());
|
onBeforeUnmount(() => stopListener());
|
||||||
|
|
||||||
|
@ -70,6 +75,8 @@ export function useIndex(props, siteName) {
|
||||||
toFilterString,
|
toFilterString,
|
||||||
reloadPage,
|
reloadPage,
|
||||||
axios,
|
axios,
|
||||||
|
filter: inner.filter,
|
||||||
|
setFilterObject,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
<template>
|
||||||
|
<f-switch
|
||||||
|
v-show="hasModule('bill')"
|
||||||
|
id="ausstand"
|
||||||
|
name="ausstand"
|
||||||
|
:model-value="getFilter('ausstand')"
|
||||||
|
label="Nur Ausstände"
|
||||||
|
size="sm"
|
||||||
|
@update:model-value="setFilter('ausstand', $event)"
|
||||||
|
></f-switch>
|
||||||
|
<f-select
|
||||||
|
id="has_vk"
|
||||||
|
name="has_vk"
|
||||||
|
:model-value="getFilter('has_vk')"
|
||||||
|
label="Verhaltenskodex unterschrieben"
|
||||||
|
size="sm"
|
||||||
|
:options="meta.boolean_filter"
|
||||||
|
@update:model-value="setFilter('has_vk', $event)"
|
||||||
|
></f-select>
|
||||||
|
<f-select
|
||||||
|
id="has_svk"
|
||||||
|
name="has_svk"
|
||||||
|
:model-value="getFilter('has_svk')"
|
||||||
|
label="SVK unterschrieben"
|
||||||
|
size="sm"
|
||||||
|
:options="meta.boolean_filter"
|
||||||
|
@update:model-value="setFilter('has_svk', $event)"
|
||||||
|
></f-select>
|
||||||
|
<f-multipleselect
|
||||||
|
id="group_ids"
|
||||||
|
:options="meta.groups"
|
||||||
|
:model-value="getFilter('group_ids')"
|
||||||
|
label="Gruppierungen"
|
||||||
|
size="sm"
|
||||||
|
@update:model-value="setFilter('group_ids', $event)"
|
||||||
|
></f-multipleselect>
|
||||||
|
<f-select
|
||||||
|
v-show="hasModule('bill')"
|
||||||
|
id="billKinds"
|
||||||
|
name="billKinds"
|
||||||
|
:options="meta.billKinds"
|
||||||
|
:model-value="getFilter('bill_kind')"
|
||||||
|
label="Rechnung"
|
||||||
|
size="sm"
|
||||||
|
@update:model-value="setFilter('bill_kind', $event)"
|
||||||
|
></f-select>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div>nach mitgitedschaftren</div>
|
||||||
|
<button class="btn btn-primary label mt-2" @click.prevent="memberships = [...memberships, {...meta.default_membership_filter}]">
|
||||||
|
<ui-sprite class="w-3 h-3 xl:mr-2" src="plus"></ui-sprite>
|
||||||
|
<span class="hidden xl:inline">Hinzufügen</span>
|
||||||
|
</button>
|
||||||
|
<div v-for="(filter, index) in memberships" :key="index" class="flex space-x-2 mt-2">
|
||||||
|
<f-multipleselect :id="`group_ids-multiple-${index}`" v-model="filter.group_ids" :options="meta.groups" label="Gruppierung" size="sm"></f-multipleselect>
|
||||||
|
<f-multipleselect :id="`activity_ids-multiple-${index}`" v-model="filter.activity_ids" :options="meta.filterActivities" label="Tätigkeiten" size="sm"></f-multipleselect>
|
||||||
|
<f-multipleselect :id="`subactivity_ids-multiple-${index}`" v-model="filter.subactivity_ids" :options="meta.filterSubactivities" label="Untertätigkeiten" size="sm"></f-multipleselect>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary label mt-3"
|
||||||
|
@click.prevent="
|
||||||
|
setFilterObject({...filter, memberships: membershipFilters});
|
||||||
|
membershipFilters = null;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span class="hidden xl:inline">Anwenden</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {onMounted, ref, watch} from 'vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function getFilter(key) {
|
||||||
|
return props.modelValue[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFilter(key, value) {
|
||||||
|
emit('update:modelValue', {
|
||||||
|
...props.modelValue,
|
||||||
|
[key]: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const memberships = ref([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
memberships.value = props.modelValue.memberships;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
memberships,
|
||||||
|
function (newValue) {
|
||||||
|
console.log('II');
|
||||||
|
setFilter('meberships', newValue);
|
||||||
|
},
|
||||||
|
{deep: true}
|
||||||
|
);
|
||||||
|
</script>
|
|
@ -17,80 +17,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ui-popup>
|
</ui-popup>
|
||||||
<ui-popup v-if="membershipFilters !== null" heading="Nach Mitgliedschaften filtern" full @close="membershipFilters = null">
|
|
||||||
<button class="btn btn-primary label mt-2" @click.prevent="membershipFilters.push({...meta.default_membership_filter})">
|
|
||||||
<ui-sprite class="w-3 h-3 xl:mr-2" src="plus"></ui-sprite>
|
|
||||||
<span class="hidden xl:inline">Hinzufügen</span>
|
|
||||||
</button>
|
|
||||||
<div v-for="(filter, index) in membershipFilters" :key="index" class="flex space-x-2 mt-2">
|
|
||||||
<f-multipleselect :id="`group_ids-multiple-${index}`" v-model="filter.group_ids" :options="meta.groups" label="Gruppierung" size="sm"></f-multipleselect>
|
|
||||||
<f-multipleselect :id="`activity_ids-multiple-${index}`" v-model="filter.activity_ids" :options="meta.filterActivities" label="Tätigkeiten" size="sm"></f-multipleselect>
|
|
||||||
<f-multipleselect :id="`subactivity_ids-multiple-${index}`" v-model="filter.subactivity_ids" :options="meta.filterSubactivities" label="Untertätigkeiten" size="sm"></f-multipleselect>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="btn btn-primary label mt-3"
|
|
||||||
@click.prevent="
|
|
||||||
setFilter('memberships', membershipFilters);
|
|
||||||
membershipFilters = null;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span class="hidden xl:inline">Anwenden</span>
|
|
||||||
</button>
|
|
||||||
</ui-popup>
|
|
||||||
<page-filter>
|
<page-filter>
|
||||||
<template #fields>
|
<template #fields>
|
||||||
<f-switch
|
<member-filter :meta="meta" :model-value="filter" @update:model-value="setFilterObject($event)" />
|
||||||
v-show="hasModule('bill')"
|
|
||||||
id="ausstand"
|
|
||||||
name="ausstand"
|
|
||||||
:model-value="getFilter('ausstand')"
|
|
||||||
label="Nur Ausstände"
|
|
||||||
size="sm"
|
|
||||||
@update:model-value="setFilter('ausstand', $event)"
|
|
||||||
></f-switch>
|
|
||||||
<f-select
|
|
||||||
id="has_vk"
|
|
||||||
name="has_vk"
|
|
||||||
:model-value="getFilter('has_vk')"
|
|
||||||
label="Verhaltenskodex unterschrieben"
|
|
||||||
size="sm"
|
|
||||||
:options="meta.boolean_filter"
|
|
||||||
@update:model-value="setFilter('has_vk', $event)"
|
|
||||||
></f-select>
|
|
||||||
<f-select
|
|
||||||
id="has_svk"
|
|
||||||
name="has_svk"
|
|
||||||
:model-value="getFilter('has_svk')"
|
|
||||||
label="SVK unterschrieben"
|
|
||||||
size="sm"
|
|
||||||
:options="meta.boolean_filter"
|
|
||||||
@update:model-value="setFilter('has_svk', $event)"
|
|
||||||
></f-select>
|
|
||||||
<f-multipleselect
|
|
||||||
id="group_ids"
|
|
||||||
:options="meta.groups"
|
|
||||||
:model-value="getFilter('group_ids')"
|
|
||||||
label="Gruppierungen"
|
|
||||||
size="sm"
|
|
||||||
@update:model-value="setFilter('group_ids', $event)"
|
|
||||||
></f-multipleselect>
|
|
||||||
<f-select
|
|
||||||
v-show="hasModule('bill')"
|
|
||||||
id="billKinds"
|
|
||||||
name="billKinds"
|
|
||||||
:options="meta.billKinds"
|
|
||||||
:model-value="getFilter('bill_kind')"
|
|
||||||
label="Rechnung"
|
|
||||||
size="sm"
|
|
||||||
@update:model-value="setFilter('bill_kind', $event)"
|
|
||||||
></f-select>
|
|
||||||
<button class="btn btn-primary label mr-2" @click.prevent="membershipFilters = getFilter('memberships')">
|
|
||||||
<ui-sprite class="w-3 h-3 xl:mr-2" src="filter"></ui-sprite>
|
|
||||||
<span class="hidden xl:inline">Mitgliedschaften</span>
|
|
||||||
</button>
|
|
||||||
</template>
|
</template>
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<f-text id="search" :model-value="getFilter('search')" label="Suchen …" size="sm" @update:model-value="setFilter('search', $event)"></f-text>
|
<f-text id="search" :model-value="filter.search" label="Suchen …" size="sm" @update:model-value="setFilterObject({...filter, search: $event})"></f-text>
|
||||||
<button class="btn btn-primary label mr-2" @click.prevent="exportMembers">
|
<button class="btn btn-primary label mr-2" @click.prevent="exportMembers">
|
||||||
<ui-sprite class="w-3 h-3 xl:mr-2" src="save"></ui-sprite>
|
<ui-sprite class="w-3 h-3 xl:mr-2" src="save"></ui-sprite>
|
||||||
<span class="hidden xl:inline">Exportieren</span>
|
<span class="hidden xl:inline">Exportieren</span>
|
||||||
|
@ -161,21 +93,21 @@
|
||||||
</page-layout>
|
</page-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="js" setup>
|
<script setup>
|
||||||
import MemberInvoicePositions from './MemberInvoicePositions.vue';
|
import MemberInvoicePositions from './MemberInvoicePositions.vue';
|
||||||
import MemberMemberships from './MemberMemberships.vue';
|
import MemberMemberships from './MemberMemberships.vue';
|
||||||
import MemberCourses from './MemberCourses.vue';
|
import MemberCourses from './MemberCourses.vue';
|
||||||
import Tags from './Tags.vue';
|
import Tags from './Tags.vue';
|
||||||
import Actions from './index/Actions.vue';
|
import Actions from './index/Actions.vue';
|
||||||
import { indexProps, useIndex } from '../../composables/useIndex.js';
|
import {indexProps, useIndex} from '../../composables/useIndex.js';
|
||||||
import { ref, defineProps } from 'vue';
|
import {ref, defineProps} from 'vue';
|
||||||
|
import MemberFilter from './MemberFilter.vue';
|
||||||
|
|
||||||
const single = ref(null);
|
const single = ref(null);
|
||||||
const deleting = ref(null);
|
const deleting = ref(null);
|
||||||
const membershipFilters = ref(null);
|
|
||||||
|
|
||||||
const props = defineProps(indexProps);
|
const props = defineProps(indexProps);
|
||||||
var { router, data, meta, getFilter, setFilter, filterString, reloadPage } = useIndex(props.data, 'member');
|
var {router, data, meta, filter, setFilterObject, filterString, reloadPage} = useIndex(props.data, 'member');
|
||||||
|
|
||||||
function exportMembers() {
|
function exportMembers() {
|
||||||
window.open(`/member-export?filter=${filterString.value}`);
|
window.open(`/member-export?filter=${filterString.value}`);
|
||||||
|
@ -183,7 +115,7 @@ function exportMembers() {
|
||||||
|
|
||||||
async function remove(member) {
|
async function remove(member) {
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
deleting.value = { resolve, reject, member };
|
deleting.value = {resolve, reject, member};
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
router.delete(`/member/${member.id}`);
|
router.delete(`/member/${member.id}`);
|
||||||
|
|
Loading…
Reference in New Issue