chore: initial commit — existing single-user document scanner codebase

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-05-22 08:53:28 +02:00
co-authored by Claude Sonnet 4.6
parent 6fed5ba531
commit 7a34807fa0
71 changed files with 16408 additions and 0 deletions
@@ -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>