chore: initial commit — existing single-user document scanner codebase
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
6fed5ba531
commit
7a34807fa0
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Add form -->
|
||||
<form @submit.prevent="submit" class="flex gap-2 mb-6">
|
||||
<input
|
||||
v-model="form.name"
|
||||
type="text"
|
||||
placeholder="New topic name…"
|
||||
class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
v-model="form.color"
|
||||
type="color"
|
||||
class="w-10 h-10 rounded-lg border border-gray-300 cursor-pointer p-0.5"
|
||||
title="Pick color"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
class="px-4 py-2 bg-indigo-600 text-white rounded-lg text-sm font-medium hover:bg-indigo-700 transition-colors"
|
||||
:disabled="saving"
|
||||
>
|
||||
{{ saving ? 'Adding…' : 'Add' }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Error -->
|
||||
<p v-if="error" class="text-red-500 text-sm mb-4">{{ error }}</p>
|
||||
|
||||
<!-- Topic list -->
|
||||
<div class="space-y-2">
|
||||
<div
|
||||
v-for="topic in topicsStore.topics"
|
||||
:key="topic.id"
|
||||
class="flex items-center gap-3 bg-white border border-gray-200 rounded-lg px-4 py-3"
|
||||
>
|
||||
<span
|
||||
class="w-3 h-3 rounded-full shrink-0"
|
||||
:style="{ backgroundColor: topic.color }"
|
||||
></span>
|
||||
|
||||
<div v-if="editing === topic.id" class="flex-1 flex gap-2">
|
||||
<input
|
||||
v-model="editForm.name"
|
||||
class="flex-1 border border-gray-300 rounded px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400"
|
||||
/>
|
||||
<input v-model="editForm.color" type="color" class="w-8 h-8 rounded border border-gray-300 p-0.5" />
|
||||
<input
|
||||
v-model="editForm.description"
|
||||
placeholder="Description"
|
||||
class="flex-1 border border-gray-300 rounded px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400"
|
||||
/>
|
||||
<button @click="saveEdit(topic.id)" class="text-xs text-indigo-600 font-medium">Save</button>
|
||||
<button @click="editing = null" class="text-xs text-gray-400">Cancel</button>
|
||||
</div>
|
||||
|
||||
<div v-else class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-medium text-gray-800 text-sm">{{ topic.name }}</span>
|
||||
<span class="text-xs text-gray-400">({{ topic.doc_count }} docs)</span>
|
||||
</div>
|
||||
<p v-if="topic.description" class="text-xs text-gray-500 mt-0.5">{{ topic.description }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 shrink-0">
|
||||
<button @click="startEdit(topic)" class="text-xs text-gray-500 hover:text-indigo-600">Edit</button>
|
||||
<button @click="remove(topic)" class="text-xs text-gray-500 hover:text-red-500">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!topicsStore.topics.length" class="text-center py-8 text-gray-400 text-sm">
|
||||
No topics yet. Add one above.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useTopicsStore } from '../../stores/topics.js'
|
||||
|
||||
const topicsStore = useTopicsStore()
|
||||
const saving = ref(false)
|
||||
const error = ref(null)
|
||||
const editing = ref(null)
|
||||
|
||||
const form = reactive({ name: '', color: '#6366f1' })
|
||||
const editForm = reactive({ name: '', description: '', color: '' })
|
||||
|
||||
async function submit() {
|
||||
saving.value = true
|
||||
error.value = null
|
||||
try {
|
||||
await topicsStore.addTopic({ name: form.name, color: form.color })
|
||||
form.name = ''
|
||||
form.color = '#6366f1'
|
||||
} catch (e) {
|
||||
error.value = e.message
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function startEdit(topic) {
|
||||
editing.value = topic.id
|
||||
editForm.name = topic.name
|
||||
editForm.description = topic.description || ''
|
||||
editForm.color = topic.color
|
||||
}
|
||||
|
||||
async function saveEdit(id) {
|
||||
await topicsStore.editTopic(id, {
|
||||
name: editForm.name,
|
||||
description: editForm.description,
|
||||
color: editForm.color,
|
||||
})
|
||||
editing.value = null
|
||||
}
|
||||
|
||||
async function remove(topic) {
|
||||
if (!confirm(`Delete topic "${topic.name}"? It will be removed from all documents.`)) return
|
||||
await topicsStore.removeTopic(topic.id)
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user