feat: default Aanbevolen filter on, larger search field, recommendation tooltip per person

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 22:14:31 +02:00
parent 2764d3476f
commit 27d64e409f

View File

@@ -24,7 +24,7 @@ const { mutateAsync: assignPerson, isPending: isAssigning } = useAssignPersonToS
// Search and filters
const searchQuery = ref('')
const showOnlyAvailable = ref(true)
const showRecommendedOnly = ref(false)
const showRecommendedOnly = ref(true)
const selectedCrowdType = ref<string | null>(null)
const assignError = ref<string | null>(null)
const showSuccess = ref(false)
@@ -77,6 +77,8 @@ watch(() => assignableData.value, (data) => {
watch(modelValue, (open) => {
if (open) {
searchQuery.value = ''
showRecommendedOnly.value = true
showOnlyAvailable.value = true
selectedCrowdType.value = null
assignError.value = null
}
@@ -177,6 +179,32 @@ function getPreferenceMatch(person: AssignablePerson) {
return person.section_preferences.find(sp => sp.section_name === sectionName)
}
function getRecommendationReasons(person: AssignablePerson): string[] {
const reasons: string[] = []
const sectionName = assignableData.value?.meta?.section_name
const prefMatch = sectionName
? person.section_preferences.find(sp => sp.section_name === sectionName)
: null
if (prefMatch) {
reasons.push(`Voorkeur voor ${sectionName} (prioriteit #${prefMatch.priority})`)
}
if (person.has_availability) {
reasons.push(`Beschikbaar voor tijdslot ${assignableData.value?.meta?.time_slot_name}`)
}
if (person.tags.length) {
const proficiencyLabel: Record<string, string> = { beginner: 'beginner', experienced: 'ervaren', expert: 'expert' }
const tagNames = person.tags.map(t =>
t.proficiency ? `${t.name} (${proficiencyLabel[t.proficiency]})` : t.name,
)
reasons.push(`Kenmerken: ${tagNames.join(', ')}`)
}
return reasons
}
function handleAssign(person: AssignablePerson) {
if (!props.shift) return
assignError.value = null
@@ -315,7 +343,7 @@ async function executeAssign(person: AssignablePerson) {
v-model="searchQuery"
prepend-inner-icon="tabler-search"
placeholder="Zoek op naam of e-mail..."
density="compact"
density="comfortable"
hide-details
clearable
class="mb-3"
@@ -390,6 +418,32 @@ async function executeAssign(person: AssignablePerson) {
<VListItemTitle class="d-flex align-center ga-2">
{{ person.name }}
<VTooltip
v-if="getRecommendationReasons(person).length"
location="top"
max-width="320"
>
<template #activator="{ props: tooltipProps }">
<VIcon
v-bind="tooltipProps"
size="16"
color="warning"
>
tabler-info-circle
</VIcon>
</template>
<div class="text-body-2">
<strong>Aanbevolen omdat:</strong>
<ul class="pl-4 mt-1 mb-0">
<li
v-for="(reason, i) in getRecommendationReasons(person)"
:key="i"
>
{{ reason }}
</li>
</ul>
</div>
</VTooltip>
<VChip
v-if="person.crowd_type"
size="x-small"