Rudimentary searching

This commit is contained in:
2024-04-08 13:03:33 -04:00
parent ffaf31bbeb
commit 4c2cae7149
3 changed files with 102 additions and 46 deletions

View File

@@ -56,12 +56,10 @@
emit-value
map-options
input-debounce="250"
@new-value="addTag"
:options="skillTagOptions"
option-label="name"
option-value="$id"
@filter="filterSkillTags"
new-value-mode="add-unique"
>
</q-select>
</div>
@@ -159,7 +157,7 @@
</template>
<script setup lang="ts">
import { reactive, ref, Ref } from 'vue';
import { computed, reactive, ref, Ref } from 'vue';
import { useRouter } from 'vue-router';
import { useTaskStore, TASKSTATUS } from 'src/stores/task';
import type { TaskTag, SkillTag, Task } from 'src/stores/task';
@@ -194,24 +192,33 @@ const boatList = ref<Boat[]>(useBoatStore().boats);
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
function filterSkillTags(val: string, update: (cb: () => void) => void): void {
return filterTags(skillTagOptions, taskStore.skillTags, val, update);
}
function filterTaskTags(val: string, update: (cb: () => void) => void): void {
return filterTags(taskTagOptions, taskStore.taskTags, val, update);
}
function filterTasks(val: string, update: (cb: () => void) => void): void {
if (val === '') {
update(() => {
tasks = taskStore.tasks;
});
return;
}
const filterSkillTags = computed(
() =>
(val: string, update: (cb: () => void) => void): void => {
return filterTags(skillTagOptions, taskStore.skillTags, val, update);
}
);
const filterTaskTags = computed(
() =>
(val: string, update: (cb: () => void) => void): void => {
return filterTags(taskTagOptions, taskStore.taskTags, val, update);
}
);
const filterTasks = computed(
() =>
(val: string, update: (cb: () => void) => void): void => {
if (val === '') {
update(() => {
tasks = taskStore.tasks;
});
return;
}
update(() => {
tasks = taskStore.filterTasksByTitle(val);
});
}
update(() => {
tasks = taskStore.filterTasksByTitle(val);
});
}
);
function filterTags(
optionVar: Ref<(SkillTag | TaskTag)[] | undefined>,
@@ -233,9 +240,6 @@ function filterTags(
});
}
function addTag(tag: string) {
return;
}
// Method to update the model in ISO 8601 format
const updateDateISO = (value: string) => {
modifiedTask.due_date = date.formatDate(value, 'YYYY-MM-DD');

View File

@@ -3,6 +3,7 @@
<q-table
:rows="tasks"
:columns="columns"
:grid="$q.screen.xs"
dense
row-key="$id"
flatten
@@ -11,7 +12,7 @@
selection="multiple"
v-model:selected="selected"
:filter="searchFilter"
:filter-method="filterByTitle"
:filter-method="filterRows"
@row-click="onRowClick"
>
<template v-slot:top>
@@ -30,7 +31,42 @@
@click="deleteTasks"
/>
<q-space />
<q-input flatten debounce="300" color="primary" v-model="searchFilter">
<q-select
style="width: 250px"
multiple
use-chips
clearable
label="Skills Filter"
input-debounce="250"
:options="skillTagOptions"
v-model="searchFilter.skillTags"
option-label="name"
option-value="$id"
>
</q-select>
<q-select
style="width: 250px"
multiple
use-chips
clearable
label="Tag Filter"
input-debounce="250"
:options="taskTagOptions"
v-model="searchFilter.taskTags"
option-label="name"
option-value="$id"
>
<template v-slot: prepend>
<q-icon name="wrench"></q-icon>
</template>
</q-select>
<q-space />
<q-input
flatten
debounce="300"
color="primary"
v-model="searchFilter.title"
>
<template v-slot:append>
<q-icon name="search" />
</template>
@@ -75,8 +111,8 @@
</template>
<script setup lang="ts">
import { defineProps, ref } from 'vue';
import { useTaskStore, Task } from 'src/stores/task';
import { computed, defineProps, ref } from 'vue';
import { useTaskStore, Task, SkillTag, TaskTag } from 'src/stores/task';
import { QTableProps, date, useQuasar } from 'quasar';
import { useBoatStore } from 'src/stores/boat';
import { useRouter } from 'vue-router';
@@ -129,7 +165,7 @@ const columns = <QTableProps['columns']>[
label: 'Boat',
field: (row) =>
useBoatStore().boats.find((boat) => boat.$id === row.boat)?.name,
sortable: false,
sortable: true,
},
{
name: 'volunteers',
@@ -164,27 +200,45 @@ const columns = <QTableProps['columns']>[
const props = defineProps<{ tasks: Task[] }>();
const taskStore = useTaskStore();
const searchFilter = ref('');
const $q = useQuasar();
const searchFilter = ref({
title: '',
skillTags: <SkillTag[]>[],
taskTags: <TaskTag[]>[],
});
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
function onRowClick(evt: Event, row: Task) {
console.log(row);
router.push({ name: 'edit-task', params: { id: row.$id } });
}
const filterByTitle = (
rows: readonly Task[],
terms: any,
cols: any,
cellValueFn: any
) => {
console.log(terms);
return terms
? rows.filter((row) =>
row.title.toLowerCase().includes(terms.toLowerCase())
)
: rows;
};
// TODO: Implement server side search
const filterRows = computed(
() => (rows: readonly Task[], terms: any, cols: any, cellValueFn: any) => {
let result = rows;
result = rows.filter((row) =>
terms.title
? row.title.toLowerCase().includes(terms.title.toLowerCase())
: true
);
result = result.filter((row) =>
terms.skillTags.length > 0
? row.required_skills.some((req_skill) =>
terms.skillTags.map((t) => t.$id).includes(req_skill)
)
: true
);
result = result.filter((row) =>
terms.taskTags.length > 0
? row.tags.some((tag) => terms.taskTags.map((t) => t.$id).includes(tag))
: true
);
return result;
}
);
function deleteTasks() {
confirmDelete(selected.value);

View File

@@ -1,15 +1,13 @@
<template>
<toolbar-component pageTitle="Tasks" />
<q-page padding>
<TaskListComponent v-if="$q.screen.lt.sm" :tasks="taskStore.tasks" />
<TaskTableComponent v-else :tasks="taskStore.tasks" />
<TaskTableComponent :tasks="taskStore.tasks" />
</q-page>
</template>
<script setup lang="ts">
import { useTaskStore } from 'stores/task';
import ToolbarComponent from 'src/components/ToolbarComponent.vue';
import TaskListComponent from 'src/components/task/TaskListComponent.vue';
import TaskTableComponent from 'src/components/task/TaskTableComponent.vue';
const taskStore = useTaskStore();