feat(fc2b): suggestions store + modal panel components
Store: load per-image suggestions, accept (creates the tag first for raw/creates_new_tag suggestions, then accepts by id), aliasAccept, dismiss (client-side hide for raw tags), success toasts folded in. Panel: people/sources groups always open, General collapsed by default; alias picker dialog wired; shimmer skeleton while loading. SuggestionItem shows score %, +new badge for raw tags, kebab menu. AliasPickerDialog referenced (lands in Task 15). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="fc-suggestion">
|
||||
<span class="fc-suggestion__name">
|
||||
{{ suggestion.display_name }}
|
||||
<span v-if="suggestion.creates_new_tag" class="fc-suggestion__new"
|
||||
title="No matching tag yet — accepting creates it">+new</span>
|
||||
</span>
|
||||
<span class="fc-suggestion__score">{{ scorePct }}</span>
|
||||
<v-btn
|
||||
icon="mdi-plus" size="x-small" variant="text" color="accent"
|
||||
:aria-label="`Accept ${suggestion.display_name}`"
|
||||
@click="$emit('accept', suggestion)"
|
||||
/>
|
||||
<v-menu>
|
||||
<template #activator="{ props }">
|
||||
<v-btn icon="mdi-dots-vertical" size="x-small" variant="text" v-bind="props" />
|
||||
</template>
|
||||
<v-list density="compact">
|
||||
<v-list-item @click="$emit('alias', suggestion)">
|
||||
<v-list-item-title>Treat as alias for…</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="$emit('dismiss', suggestion)">
|
||||
<v-list-item-title>Dismiss for this image</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({ suggestion: { type: Object, required: true } })
|
||||
defineEmits(['accept', 'alias', 'dismiss'])
|
||||
|
||||
const scorePct = computed(() => `${Math.round(props.suggestion.score * 100)}%`)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-suggestion {
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
.fc-suggestion__name { flex: 1; min-width: 0; }
|
||||
.fc-suggestion__new {
|
||||
font-size: 10px; color: rgb(var(--v-theme-accent));
|
||||
margin-left: 4px;
|
||||
}
|
||||
.fc-suggestion__score {
|
||||
font-size: 11px;
|
||||
color: rgb(var(--v-theme-on-surface-variant, var(--v-theme-on-surface)));
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user