483 lines
14 KiB
Vue
483 lines
14 KiB
Vue
<template>
|
|
<v-container>
|
|
<!-- Welcome Header -->
|
|
<v-row class="mb-6">
|
|
<v-col>
|
|
<h1 class="text-h3 font-weight-bold" style="color: #a31515;">
|
|
Welcome Back, {{ firstName }}!
|
|
</h1>
|
|
<p class="text-h6 text-medium-emphasis">
|
|
MonacoUSA Administration Portal
|
|
</p>
|
|
<v-chip color="error" variant="elevated" class="mt-2">
|
|
<v-icon start>mdi-shield-crown</v-icon>
|
|
Administrator
|
|
</v-chip>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<!-- System Status -->
|
|
<v-row class="mb-6">
|
|
<v-col cols="12">
|
|
<v-card class="pa-4" elevation="2">
|
|
<h3 class="mb-3">
|
|
<v-icon class="mr-2" color="success">mdi-server</v-icon>
|
|
System Status
|
|
</h3>
|
|
<v-row>
|
|
<v-col cols="6" md="3">
|
|
<v-chip color="success" variant="elevated">
|
|
<v-icon start>mdi-check-circle</v-icon>
|
|
System Healthy
|
|
</v-chip>
|
|
</v-col>
|
|
<v-col cols="6" md="3">
|
|
<v-chip color="info" variant="elevated">
|
|
<v-icon start>mdi-account-multiple</v-icon>
|
|
{{ systemStats.totalUsers }} Users
|
|
</v-chip>
|
|
</v-col>
|
|
<v-col cols="6" md="3">
|
|
<v-chip color="warning" variant="elevated">
|
|
<v-icon start>mdi-database</v-icon>
|
|
{{ systemStats.diskUsage }} Disk
|
|
</v-chip>
|
|
</v-col>
|
|
<v-col cols="6" md="3">
|
|
<v-chip color="primary" variant="elevated">
|
|
<v-icon start>mdi-memory</v-icon>
|
|
{{ systemStats.memoryUsage }} Memory
|
|
</v-chip>
|
|
</v-col>
|
|
</v-row>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<!-- Admin Tools -->
|
|
<v-row class="mb-6">
|
|
<v-col cols="12" md="4">
|
|
<v-card class="pa-4 text-center" elevation="2" hover>
|
|
<v-icon size="48" color="error" class="mb-2">mdi-account-cog</v-icon>
|
|
<h3 class="mb-2">User Management</h3>
|
|
<p class="text-body-2 mb-4">Add, edit, and manage user accounts</p>
|
|
<v-btn
|
|
color="error"
|
|
variant="outlined"
|
|
style="border-color: #f44336; color: #f44336;"
|
|
@click="navigateToUserManagement"
|
|
>
|
|
Manage Users
|
|
</v-btn>
|
|
</v-card>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="4">
|
|
<v-card class="pa-4 text-center" elevation="2" hover>
|
|
<v-icon size="48" color="error" class="mb-2">mdi-file-document-outline</v-icon>
|
|
<h3 class="mb-2">Audit Logs</h3>
|
|
<p class="text-body-2 mb-4">View system and user activity logs</p>
|
|
<v-btn
|
|
color="error"
|
|
variant="outlined"
|
|
style="border-color: #f44336; color: #f44336;"
|
|
@click="navigateToAuditLogs"
|
|
>
|
|
View Logs
|
|
</v-btn>
|
|
</v-card>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="4">
|
|
<v-card class="pa-4 text-center" elevation="2" hover>
|
|
<v-icon size="48" color="error" class="mb-2">mdi-cog</v-icon>
|
|
<h3 class="mb-2">System Config</h3>
|
|
<p class="text-body-2 mb-4">Configure system settings</p>
|
|
<v-btn
|
|
color="error"
|
|
variant="outlined"
|
|
style="border-color: #f44336; color: #f44336;"
|
|
@click="navigateToSystemConfig"
|
|
>
|
|
Settings
|
|
</v-btn>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<!-- System Metrics -->
|
|
<v-row class="mb-6">
|
|
<v-col cols="12">
|
|
<v-card elevation="2">
|
|
<v-card-title class="pa-4" style="background-color: #f5f5f5;">
|
|
<v-icon class="mr-2" color="primary">mdi-chart-line</v-icon>
|
|
System Metrics
|
|
</v-card-title>
|
|
<v-card-text class="pa-4">
|
|
<v-row>
|
|
<v-col cols="6" md="3" class="text-center">
|
|
<div class="text-h4 font-weight-bold" style="color: #a31515;">{{ systemStats.totalUsers }}</div>
|
|
<div class="text-body-2">Total Users</div>
|
|
</v-col>
|
|
<v-col cols="6" md="3" class="text-center">
|
|
<div class="text-h4 font-weight-bold" style="color: #a31515;">{{ systemStats.activeUsers }}</div>
|
|
<div class="text-body-2">Active Users</div>
|
|
</v-col>
|
|
<v-col cols="6" md="3" class="text-center">
|
|
<div class="text-h4 font-weight-bold" style="color: #a31515;">{{ systemStats.totalSessions }}</div>
|
|
<div class="text-body-2">Active Sessions</div>
|
|
</v-col>
|
|
<v-col cols="6" md="3" class="text-center">
|
|
<div class="text-h4 font-weight-bold" style="color: #a31515;">{{ systemStats.uptime }}</div>
|
|
<div class="text-body-2">System Uptime</div>
|
|
</v-col>
|
|
</v-row>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<!-- Recent Admin Activity -->
|
|
<v-row class="mb-6">
|
|
<v-col cols="12">
|
|
<v-card elevation="2">
|
|
<v-card-title class="pa-4" style="background-color: #f5f5f5;">
|
|
<v-icon class="mr-2" color="primary">mdi-history</v-icon>
|
|
Recent Admin Activity
|
|
</v-card-title>
|
|
<v-card-text class="pa-4">
|
|
<v-list>
|
|
<v-list-item v-for="activity in recentActivity" :key="activity.id">
|
|
<v-list-item-content>
|
|
<v-list-item-title>{{ activity.title }}</v-list-item-title>
|
|
<v-list-item-subtitle>
|
|
{{ activity.description }} - {{ activity.timestamp }}
|
|
</v-list-item-subtitle>
|
|
</v-list-item-content>
|
|
<v-list-item-action>
|
|
<v-chip :color="activity.type" size="small">{{ activity.status }}</v-chip>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<!-- Security & Monitoring -->
|
|
<v-row class="mb-6">
|
|
<v-col cols="12" md="6">
|
|
<v-card elevation="2">
|
|
<v-card-title class="pa-4" style="background-color: #f5f5f5;">
|
|
<v-icon class="mr-2" color="error">mdi-security</v-icon>
|
|
Security Alerts
|
|
</v-card-title>
|
|
<v-card-text class="pa-4">
|
|
<v-list>
|
|
<v-list-item v-for="alert in securityAlerts" :key="alert.id">
|
|
<v-list-item-content>
|
|
<v-list-item-title>{{ alert.title }}</v-list-item-title>
|
|
<v-list-item-subtitle>{{ alert.description }}</v-list-item-subtitle>
|
|
</v-list-item-content>
|
|
<v-list-item-action>
|
|
<v-chip :color="alert.severity" size="small">{{ alert.level }}</v-chip>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="6">
|
|
<v-card elevation="2">
|
|
<v-card-title class="pa-4" style="background-color: #f5f5f5;">
|
|
<v-icon class="mr-2" color="primary">mdi-monitor-dashboard</v-icon>
|
|
System Health
|
|
</v-card-title>
|
|
<v-card-text class="pa-4">
|
|
<div class="mb-3">
|
|
<div class="d-flex justify-space-between mb-1">
|
|
<span>CPU Usage</span>
|
|
<span>{{ systemHealth.cpu }}%</span>
|
|
</div>
|
|
<v-progress-linear
|
|
:model-value="systemHealth.cpu"
|
|
color="primary"
|
|
height="8"
|
|
/>
|
|
</div>
|
|
<div class="mb-3">
|
|
<div class="d-flex justify-space-between mb-1">
|
|
<span>Memory Usage</span>
|
|
<span>{{ systemHealth.memory }}%</span>
|
|
</div>
|
|
<v-progress-linear
|
|
:model-value="systemHealth.memory"
|
|
color="warning"
|
|
height="8"
|
|
/>
|
|
</div>
|
|
<div class="mb-3">
|
|
<div class="d-flex justify-space-between mb-1">
|
|
<span>Disk Usage</span>
|
|
<span>{{ systemHealth.disk }}%</span>
|
|
</div>
|
|
<v-progress-linear
|
|
:model-value="systemHealth.disk"
|
|
color="success"
|
|
height="8"
|
|
/>
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<!-- Quick Admin Actions -->
|
|
<v-row>
|
|
<v-col cols="12">
|
|
<v-card elevation="2">
|
|
<v-card-title class="pa-4" style="background-color: #f5f5f5;">
|
|
<v-icon class="mr-2" color="primary">mdi-lightning-bolt</v-icon>
|
|
Quick Admin Actions
|
|
</v-card-title>
|
|
<v-card-text class="pa-4">
|
|
<v-row>
|
|
<v-col cols="12" md="3">
|
|
<v-btn
|
|
color="error"
|
|
variant="outlined"
|
|
block
|
|
style="border-color: #f44336; color: #f44336;"
|
|
@click="createNewUser"
|
|
>
|
|
<v-icon start>mdi-account-plus</v-icon>
|
|
Create User
|
|
</v-btn>
|
|
</v-col>
|
|
<v-col cols="12" md="3">
|
|
<v-btn
|
|
color="error"
|
|
variant="outlined"
|
|
block
|
|
style="border-color: #f44336; color: #f44336;"
|
|
@click="generateSystemReport"
|
|
>
|
|
<v-icon start>mdi-file-chart</v-icon>
|
|
System Report
|
|
</v-btn>
|
|
</v-col>
|
|
<v-col cols="12" md="3">
|
|
<v-btn
|
|
color="error"
|
|
variant="outlined"
|
|
block
|
|
style="border-color: #f44336; color: #f44336;"
|
|
@click="managePermissions"
|
|
>
|
|
<v-icon start>mdi-shield-key</v-icon>
|
|
Permissions
|
|
</v-btn>
|
|
</v-col>
|
|
<v-col cols="12" md="3">
|
|
<v-btn
|
|
color="error"
|
|
variant="outlined"
|
|
block
|
|
style="border-color: #f44336; color: #f44336;"
|
|
@click="systemMaintenance"
|
|
>
|
|
<v-icon start>mdi-wrench</v-icon>
|
|
Maintenance
|
|
</v-btn>
|
|
</v-col>
|
|
</v-row>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
definePageMeta({
|
|
layout: 'dashboard',
|
|
middleware: 'auth'
|
|
});
|
|
|
|
const { firstName, isAdmin } = useAuth();
|
|
|
|
// Check admin access on mount
|
|
onMounted(async () => {
|
|
if (!isAdmin.value) {
|
|
throw createError({
|
|
statusCode: 403,
|
|
statusMessage: 'Access denied. Administrator privileges required.'
|
|
});
|
|
}
|
|
|
|
// Load admin dashboard data
|
|
await loadAdminStats();
|
|
});
|
|
|
|
// Reactive data
|
|
const systemStats = ref({
|
|
totalUsers: 0,
|
|
activeUsers: 0,
|
|
totalSessions: 0,
|
|
diskUsage: '0%',
|
|
memoryUsage: '0%',
|
|
uptime: '0d'
|
|
});
|
|
|
|
|
|
const systemHealth = ref({
|
|
cpu: 45,
|
|
memory: 62,
|
|
disk: 38
|
|
});
|
|
|
|
const recentActivity = ref([
|
|
{
|
|
id: 1,
|
|
title: 'User Created',
|
|
description: 'New user account created for john.doe@example.com',
|
|
timestamp: '2 hours ago',
|
|
type: 'success',
|
|
status: 'Completed'
|
|
},
|
|
{
|
|
id: 2,
|
|
title: 'System Backup',
|
|
description: 'Automated system backup completed successfully',
|
|
timestamp: '6 hours ago',
|
|
type: 'info',
|
|
status: 'Completed'
|
|
},
|
|
{
|
|
id: 3,
|
|
title: 'Permission Update',
|
|
description: 'User permissions updated for board member',
|
|
timestamp: '1 day ago',
|
|
type: 'warning',
|
|
status: 'Completed'
|
|
}
|
|
]);
|
|
|
|
const securityAlerts = ref([
|
|
{
|
|
id: 1,
|
|
title: 'Failed Login Attempts',
|
|
description: '3 failed login attempts from IP 192.168.1.100',
|
|
severity: 'warning',
|
|
level: 'Medium'
|
|
},
|
|
{
|
|
id: 2,
|
|
title: 'System Update Available',
|
|
description: 'Security update available for Keycloak',
|
|
severity: 'info',
|
|
level: 'Low'
|
|
}
|
|
]);
|
|
|
|
// Load admin statistics
|
|
const loadAdminStats = async () => {
|
|
try {
|
|
const stats = await $fetch<{
|
|
totalUsers: number;
|
|
activeUsers: number;
|
|
totalSessions: number;
|
|
diskUsage: string;
|
|
memoryUsage: string;
|
|
}>('/api/admin/stats');
|
|
|
|
systemStats.value = {
|
|
totalUsers: stats.totalUsers || 0,
|
|
activeUsers: stats.activeUsers || 0,
|
|
totalSessions: stats.totalSessions || 0,
|
|
diskUsage: stats.diskUsage || '0%',
|
|
memoryUsage: stats.memoryUsage || '0%',
|
|
uptime: '5d 12h'
|
|
};
|
|
} catch (error) {
|
|
console.error('Failed to load admin stats:', error);
|
|
// Use mock data on error
|
|
systemStats.value = {
|
|
totalUsers: 156,
|
|
activeUsers: 45,
|
|
totalSessions: 67,
|
|
diskUsage: '45%',
|
|
memoryUsage: '62%',
|
|
uptime: '5d 12h'
|
|
};
|
|
}
|
|
};
|
|
|
|
// Navigation methods (placeholder implementations)
|
|
const navigateToUserManagement = () => {
|
|
console.log('Navigate to user management');
|
|
};
|
|
|
|
const navigateToAuditLogs = () => {
|
|
console.log('Navigate to audit logs');
|
|
};
|
|
|
|
const navigateToSystemConfig = () => {
|
|
console.log('Navigate to system config');
|
|
};
|
|
|
|
|
|
const createNewUser = () => {
|
|
console.log('Create new user');
|
|
};
|
|
|
|
const generateSystemReport = () => {
|
|
console.log('Generate system report');
|
|
};
|
|
|
|
const managePermissions = () => {
|
|
console.log('Manage permissions');
|
|
};
|
|
|
|
const systemMaintenance = () => {
|
|
console.log('System maintenance');
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.v-card {
|
|
border-radius: 12px !important;
|
|
}
|
|
|
|
.v-card:hover {
|
|
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
|
|
transition: box-shadow 0.2s ease;
|
|
}
|
|
|
|
.v-btn {
|
|
text-transform: none !important;
|
|
}
|
|
|
|
.v-icon {
|
|
color: #a31515 !important;
|
|
}
|
|
|
|
h3 {
|
|
color: #333;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.text-body-2 {
|
|
color: #666;
|
|
}
|
|
|
|
.v-chip {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.v-progress-linear {
|
|
border-radius: 4px;
|
|
}
|
|
</style>
|