WIP: Frontend implementation #1

Draft
fager wants to merge 19 commits from ch-frontend into main
Showing only changes of commit 034d676463 - Show all commits

Frontend: Owner selection for Server

Frank Agerholm 2026-01-25 17:34:05 +01:00
No known key found for this signature in database

View file

@ -6,12 +6,65 @@ const { apiFetch } = useApi()
const servers = ref([]) const servers = ref([])
const newServer = ref({ const newServer = ref({
hostname: "", hostname: "",
description: "" description: "",
owner_id: null
}) })
const loading = ref(false) const loading = ref(false)
const error = ref("") const error = ref("")
const editingId = ref<number | null>(null)
const editServer = ref({
hostname: "",
description: "",
owner_id: null
})
function startEdit(server: any) {
editingId.value = Number(server.id)
editServer.value = {
hostname: server.hostname,
description: server.description,
owner_id: server.owner_id
}
}
function cancelEdit() {
editingId.value = null
}
async function saveEdit(serverId: number) {
try {
const updated = await apiFetch(`/servers/${serverId}`, {
method: "PUT",
body: {
hostname: editServer.value.hostname,
description: editServer.value.description,
owner_id: editServer.value.owner_id
}
})
// Liste aktualisieren
const idx = servers.value.findIndex(s => s.id === serverId)
if (idx !== -1) servers.value[idx] = updated
editingId.value = null
} catch (e: any) {
error.value = e.message
}
}
const owners = ref([])
async function loadOwners() {
try {
owners.value = await apiFetch("/owners")
} catch (e: any) {
error.value = e.message
}
}
async function loadServers() { async function loadServers() {
loading.value = true loading.value = true
try { try {
@ -31,7 +84,8 @@ async function createServer() {
method: "POST", method: "POST",
body: { body: {
hostname: newServer.value.hostname, hostname: newServer.value.hostname,
description: newServer.value.description description: newServer.value.description,
owner_id: newServer.value.owner_id
} }
}) })
@ -43,6 +97,7 @@ async function createServer() {
} }
onMounted(() => { onMounted(() => {
loadOwners()
loadServers() loadServers()
}) })
</script> </script>
@ -56,23 +111,21 @@ onMounted(() => {
<h2 class="text-xl font-semibold">Neuen Server anlegen</h2> <h2 class="text-xl font-semibold">Neuen Server anlegen</h2>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<input <input v-model="newServer.hostname" type="text" placeholder="Server Name" class="border p-2 rounded" />
v-model="newServer.hostname"
type="text"
placeholder="Server Name"
class="border p-2 rounded"
/>
<textarea <textarea v-model="newServer.description" placeholder="Beschreibung (optional)"
v-model="newServer.description" class="border p-2 rounded" />
placeholder="Beschreibung (optional)"
class="border p-2 rounded"
/>
<button <select v-model="newServer.owner_id" class="border p-2 rounded">
@click="createServer" <option :value="null">Kein Owner</option>
class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 self-start" <option v-for="owner in owners" :key="owner.id" :value="owner.id">
> {{ owner.name }}
</option>
</select>
<button @click="createServer"
class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 self-start">
Speichern Speichern
</button> </button>
</div> </div>
@ -91,17 +144,78 @@ onMounted(() => {
<th class="text-left p-2">ID</th> <th class="text-left p-2">ID</th>
<th class="text-left p-2">Name</th> <th class="text-left p-2">Name</th>
<th class="text-left p-2">Beschreibung</th> <th class="text-left p-2">Beschreibung</th>
<th class="text-left p-2">Eigentümer</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr <tr v-for="server in servers" :key="server.id" class="border-b hover:bg-gray-50">
v-for="server in servers"
:key="server.id"
class="border-b hover:bg-gray-50"
>
<td class="p-2">{{ server.id }}</td> <td class="p-2">{{ server.id }}</td>
<td class="p-2">{{ server.hostname }}</td> <td class="p-2">
<td class="p-2">{{ server.description }}</td> <template v-if="editingId === server.id">
<input
v-model="editServer.hostname"
class="border p-1 rounded w-full"
/>
</template>
<template v-else>
{{ server.hostname }}
</template>
</td>
<td class="p-2">
<template v-if="editingId === server.id">
<textarea
v-model="editServer.description"
class="border p-1 rounded w-full"
/>
</template>
<template v-else>
{{ server.description }}
</template>
</td>
<td class="p-2">
<template v-if="editingId === server.id">
<select v-model="editServer.owner_id" class="border p-1 rounded">
<option :value="null">Kein Owner</option>
<option
v-for="owner in owners"
:key="owner.id"
:value="owner.id"
>
{{ owner.name }}
</option>
</select>
</template>
<template v-else>
{{ server.owner ? server.owner.name : "—" }}
</template>
</td>
<td class="p-2">
<template v-if="editingId === server.id">
<button
@click="saveEdit(server.id)"
class="bg-green-600 text-white px-2 py-1 rounded mr-2"
>
Speichern
</button>
<button
@click="cancelEdit"
class="bg-gray-400 text-white px-2 py-1 rounded"
>
Abbrechen
</button>
</template>
<template v-else>
<button
@click="startEdit(server)"
class="bg-blue-600 text-white px-2 py-1 rounded"
>
Bearbeiten
</button>
</template>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>