🎨 Frontend komplett implementiert
Views: - Login/Registrierung - Dashboard mit Stats - Aufträge (Liste + Detail) - Mitarbeiterverwaltung - Verfügbarkeitskalender - Stundenzettel - Einstellungen - Module (Dev-Panel) Features: - Vue 3 + Composition API - TailwindCSS mit Dark Mode - Pinia State Management - JWT Auth mit Refresh - Responsive Design - Rollen-basierte Navigation
This commit is contained in:
132
src/views/ModulesView.vue
Normal file
132
src/views/ModulesView.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { api } from '@/api'
|
||||
|
||||
interface Module {
|
||||
id: string
|
||||
name: string
|
||||
display_name: string
|
||||
description?: string
|
||||
is_core: boolean
|
||||
enabled: boolean
|
||||
config: Record<string, unknown>
|
||||
}
|
||||
|
||||
const modules = ref<Module[]>([])
|
||||
const loading = ref(true)
|
||||
const systemStatus = ref<any>(null)
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadModules(), loadSystemStatus()])
|
||||
})
|
||||
|
||||
async function loadModules() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await api.get<{ modules: Module[] }>('/modules/org')
|
||||
modules.value = res.data.modules
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSystemStatus() {
|
||||
try {
|
||||
const res = await api.get<any>('/modules/developer/status')
|
||||
systemStatus.value = res.data
|
||||
} catch (e) {
|
||||
// Developer module might not be enabled
|
||||
console.log('Dev status not available')
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleModule(mod: Module) {
|
||||
if (mod.is_core) return
|
||||
|
||||
try {
|
||||
await api.post(`/modules/${mod.id}/toggle`, { enabled: !mod.enabled })
|
||||
mod.enabled = !mod.enabled
|
||||
} catch (e) {
|
||||
alert(e instanceof Error ? e.message : 'Fehler')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900 dark:text-white">⚙️ Module</h1>
|
||||
|
||||
<!-- System Status -->
|
||||
<div v-if="systemStatus" class="card bg-gradient-to-r from-primary-500 to-primary-700 text-white">
|
||||
<h2 class="text-lg font-semibold mb-4">System Status</h2>
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<p class="text-primary-100 text-sm">Benutzer</p>
|
||||
<p class="text-2xl font-bold">{{ systemStatus.stats?.user_count || 0 }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-primary-100 text-sm">Aufträge</p>
|
||||
<p class="text-2xl font-bold">{{ systemStatus.stats?.order_count || 0 }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-primary-100 text-sm">Stundenzettel</p>
|
||||
<p class="text-2xl font-bold">{{ systemStatus.stats?.timesheet_count || 0 }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-primary-100 text-sm">Aktive Module</p>
|
||||
<p class="text-2xl font-bold">{{ systemStatus.stats?.enabled_modules || 0 }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modules List -->
|
||||
<div class="card">
|
||||
<h2 class="text-lg font-semibold mb-4">Verfügbare Module</h2>
|
||||
|
||||
<div v-if="loading" class="text-center py-8 text-gray-500">Lädt...</div>
|
||||
|
||||
<div v-else class="space-y-4">
|
||||
<div
|
||||
v-for="mod in modules"
|
||||
:key="mod.id"
|
||||
class="flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="font-medium text-gray-900 dark:text-white">{{ mod.display_name }}</h3>
|
||||
<span v-if="mod.is_core" class="badge badge-primary">Core</span>
|
||||
</div>
|
||||
<p v-if="mod.description" class="text-sm text-gray-500 mt-1">{{ mod.description }}</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
:disabled="mod.is_core"
|
||||
:class="[
|
||||
'relative inline-flex h-6 w-11 items-center rounded-full transition-colors',
|
||||
mod.enabled ? 'bg-primary-600' : 'bg-gray-200 dark:bg-gray-600',
|
||||
mod.is_core ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
|
||||
]"
|
||||
@click="toggleModule(mod)"
|
||||
>
|
||||
<span
|
||||
:class="[
|
||||
'inline-block h-4 w-4 transform rounded-full bg-white transition-transform',
|
||||
mod.enabled ? 'translate-x-6' : 'translate-x-1'
|
||||
]"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2 class="text-lg font-semibold mb-2">Hinweis</h2>
|
||||
<p class="text-gray-500 text-sm">
|
||||
Core-Module (Basis-System, Auftragsverwaltung) können nicht deaktiviert werden.
|
||||
Änderungen an Modulen werden sofort wirksam.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user