Add searchable assignee and creator filters on the routines manage toolbar.
EOF Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, inject, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Select as ASelect } from 'ant-design-vue';
|
||||
import type { RoutineCategoryDto, RoutineDto } from '@mento/shared';
|
||||
import UiIcon from '@/components/UiIcon.vue';
|
||||
import UserAvatar from '@/components/UserAvatar.vue';
|
||||
@@ -28,7 +29,8 @@ const loading = ref(true);
|
||||
const error = ref('');
|
||||
const q = ref('');
|
||||
const status = ref<'all' | 'active' | 'inactive'>('all');
|
||||
const assignee = ref('');
|
||||
const assignee = ref<string | undefined>(undefined);
|
||||
const creator = ref<string | undefined>(undefined);
|
||||
const busyId = ref<string | null>(null);
|
||||
const menuFor = ref<string | null>(null);
|
||||
|
||||
@@ -60,6 +62,7 @@ const filtered = computed(() => {
|
||||
if (status.value === 'active' && !r.isActive) return false;
|
||||
if (status.value === 'inactive' && r.isActive) return false;
|
||||
if (assignee.value && r.assignee?.id !== assignee.value && `team:${r.team?.id}` !== assignee.value) return false;
|
||||
if (creator.value && (r.createdBy?.id ?? r.createdById) !== creator.value) return false;
|
||||
if (term && !r.title.includes(term)) return false;
|
||||
return true;
|
||||
});
|
||||
@@ -208,21 +211,53 @@ async function deleteCat(c: RoutineCategoryDto) {
|
||||
|
||||
const users = computed(() => shell.context.value?.users ?? []);
|
||||
const teams = computed(() => shell.context.value?.teams ?? []);
|
||||
|
||||
const assigneeFilterOptions = computed(() => [
|
||||
...users.value.map((u) => ({ value: u.id, label: u.fullName })),
|
||||
...teams.value.map((t) => ({ value: `team:${t.id}`, label: `تیم ${t.name}` })),
|
||||
]);
|
||||
|
||||
const creatorFilterOptions = computed(() =>
|
||||
users.value.map((u) => ({ value: u.id, label: u.fullName })),
|
||||
);
|
||||
|
||||
function filterSelectOption(input: string, option?: { label?: string }) {
|
||||
const q = input.trim().toLocaleLowerCase('fa');
|
||||
if (!q) return true;
|
||||
return String(option?.label ?? '')
|
||||
.toLocaleLowerCase('fa')
|
||||
.includes(q);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="manage">
|
||||
<div class="toolbar">
|
||||
<UiSearch v-model="q" placeholder="جستجوی عنوان…" class="search" />
|
||||
<UiSelect v-model="assignee" size="sm" class="who">
|
||||
<option value="">همه مسئولها</option>
|
||||
<optgroup label="کاربران">
|
||||
<option v-for="u in users" :key="u.id" :value="u.id">{{ u.fullName }}</option>
|
||||
</optgroup>
|
||||
<optgroup v-if="teams.length" label="تیمها">
|
||||
<option v-for="t in teams" :key="t.id" :value="`team:${t.id}`">{{ t.name }}</option>
|
||||
</optgroup>
|
||||
</UiSelect>
|
||||
<div class="who">
|
||||
<ASelect
|
||||
v-model:value="assignee"
|
||||
allow-clear
|
||||
show-search
|
||||
placeholder="همه مسئولها"
|
||||
:options="assigneeFilterOptions"
|
||||
:filter-option="filterSelectOption"
|
||||
:get-popup-container="(node) => node.parentElement ?? document.body"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</div>
|
||||
<div class="who">
|
||||
<ASelect
|
||||
v-model:value="creator"
|
||||
allow-clear
|
||||
show-search
|
||||
placeholder="همه سازندهها"
|
||||
:options="creatorFilterOptions"
|
||||
:filter-option="filterSelectOption"
|
||||
:get-popup-container="(node) => node.parentElement ?? document.body"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</div>
|
||||
<UiSegmented v-model="status" :options="statusOptions" />
|
||||
<span class="spacer" />
|
||||
<UiButton variant="ghost" size="sm" @click="catsOpen = true; editCat(null)">
|
||||
|
||||
Reference in New Issue
Block a user