server-worklog/frontend/app/pages/workentries/search.vue

147 lines
3.9 KiB
Vue

<script setup lang="ts">
definePageMeta({
requiresAuth: true
})
import { ref, onMounted } from "vue"
import { isUnauthorized } from "~/utils/auth"
const { apiFetch } = useApi()
const { servers, loadServers } = useServers()
const selectedServer = ref(null)
const query = ref("")
const results = ref([])
const loading = ref(false)
const error = ref("")
const expandedRow = ref<number | null>(null)
function toggleRow(id: number) {
expandedRow.value = expandedRow.value === id ? null : id
}
async function search() {
if (!selectedServer.value && !query.value) {
results.value = []
return
}
loading.value = true
error.value = ""
try {
const params: any = {}
if (selectedServer.value) {
params.server_id = selectedServer.value
}
if (query.value) {
params.q = query.value
}
const result = await apiFetch("/work-entries", {
query: params
})
if (isUnauthorized(result)) {
return result
}
results.value = result
} catch (e: any) {
error.value = e.message
} finally {
loading.value = false
}
}
onMounted(async () => {
if (isUnauthorized(await loadServers())) return
})
</script>
<template>
<div class="space-y-6">
<h1 class="text-3xl font-bold">Worklog-Suche</h1>
<form @submit.prevent="search" class="p-4 bg-white shadow rounded space-y-4">
<select
v-model="selectedServer"
class="border p-2 rounded w-full"
>
<option :value="null">Server auswählen</option>
<option
v-for="s in servers"
:key="s.id"
:value="s.id"
>
{{ s.hostname }}
</option>
</select>
<input
v-model="query"
type="text"
placeholder="Freitextsuche (optional)"
class="border p-2 rounded w-full"
/>
<button
type="submit"
class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
>
Suchen
</button>
</form>
<!-- Nur anzeigen, wenn ein Server gewählt wurde -->
<div v-if="selectedServer || query" class="p-4 bg-white shadow rounded">
<h2 class="text-xl font-semibold mb-4">Suchergebnisse</h2>
<div v-if="loading">Lade</div>
<div v-if="error" class="text-red-600">{{ error }}</div>
<table v-if="results.length" class="w-full border-collapse">
<thead>
<tr class="border-b">
<th class="text-left p-2">Titel</th>
<th class="text-left p-2">Dauer</th>
<th class="text-left p-2">Erstellt am</th>
<th class="text-left p-2">Server</th>
</tr>
</thead>
<tbody>
<template v-for="entry in results" :key="entry.id">
<tr
@click="toggleRow(entry.id)"
class="border-b hover:bg-gray-50 cursor-pointer"
>
<td class="p-2">{{ entry.title }}</td>
<td class="p-2">{{ entry.duration_minutes ?? "—" }}</td>
<td class="p-2">{{ new Date(entry.created_at).toLocaleString() }}</td>
<td class="p-2">
<span
v-for="s in entry.servers"
:key="s.id"
class="inline-block bg-gray-200 px-2 py-1 rounded mr-1 text-sm"
>
{{ s.hostname }}
</span>
</td>
</tr>
<!-- Detailzeile -->
<tr v-if="expandedRow === entry.id" class="bg-gray-50">
<td colspan="4" class="p-4">
<h3 class="font-semibold mb-2">Beschreibung</h3>
<p class="whitespace-pre-line">
{{ entry.description || "Keine Beschreibung vorhanden." }}
</p>
</td>
</tr>
</template>
</tbody>
</table>
<div v-else class="text-gray-500">
Keine Einträge gefunden.
</div>
</div>
</div>
</template>