3a0cca5aca
Not all characters belong to a fandom (original characters, unsorted). The create flow forced every new character through FandomPicker, whose only outcomes were 'Use this fandom' (disabled until one is picked) or Cancel (which aborts the whole creation) — there was no way to confirm a character with no fandom. - FandomPicker: add a 'No fandom' action that emits confirm(null). - TagAutocomplete.onFandomChosen: pass fandom_id: null when null is emitted. Backend already supported this end to end (Tag.fandom_id nullable, the CHECK only forbids fandom_id on non-character kinds, tag_service find_or_create defaults fandom_id=None, API reads body.get). A fandom can still be assigned later from the chip kebab's 'Set fandom…'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
58 lines
1.9 KiB
Vue
58 lines
1.9 KiB
Vue
<template>
|
|
<v-card>
|
|
<v-card-title>Pick a fandom</v-card-title>
|
|
<v-card-text>
|
|
<v-autocomplete
|
|
v-model="selectedId"
|
|
:items="store.fandomCache"
|
|
:item-title="(f) => f.name"
|
|
:item-value="(f) => f.id"
|
|
label="Fandom" clearable density="compact"
|
|
/>
|
|
<v-divider class="my-3" />
|
|
<p class="text-caption mb-2">Or create a new fandom:</p>
|
|
<div class="d-flex" style="gap: 8px;">
|
|
<v-text-field v-model="newName" placeholder="New fandom name" density="compact" hide-details />
|
|
<v-btn :disabled="!newName.trim()" rounded="pill" @click="onCreate">Create</v-btn>
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<!-- Not every character belongs to a fandom (original characters,
|
|
unsorted, etc.). "No fandom" creates the character unassigned;
|
|
a fandom can still be set later from the chip's kebab menu. -->
|
|
<v-btn variant="text" @click="onNoFandom">No fandom</v-btn>
|
|
<v-spacer />
|
|
<v-btn @click="$emit('cancel')">Cancel</v-btn>
|
|
<v-btn :disabled="!selectedId" color="primary" rounded="pill" @click="onConfirm">Use this fandom</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, ref } from 'vue'
|
|
import { useTagStore } from '../../stores/tags.js'
|
|
|
|
const emit = defineEmits(['confirm', 'cancel'])
|
|
const store = useTagStore()
|
|
|
|
const selectedId = ref(null)
|
|
const newName = ref('')
|
|
|
|
onMounted(() => { if (store.fandomCache.length === 0) store.loadFandoms() })
|
|
|
|
async function onCreate() {
|
|
const f = await store.createFandom(newName.value.trim())
|
|
selectedId.value = f.id
|
|
newName.value = ''
|
|
}
|
|
function onConfirm() {
|
|
const f = store.fandomCache.find(x => x.id === selectedId.value)
|
|
if (f) emit('confirm', f)
|
|
}
|
|
// Create the character with no fandom. Emits null so the caller knows this
|
|
// was a deliberate "unassigned", not a cancel.
|
|
function onNoFandom() {
|
|
emit('confirm', null)
|
|
}
|
|
</script>
|