admin firs step

This commit is contained in:
Roo
2026-03-23 21:43:40 +00:00
parent 309a72cc0b
commit cddcd34ba9
47 changed files with 22698 additions and 19 deletions

View File

@@ -0,0 +1,168 @@
<template>
<v-card
:color="tileColor"
variant="tonal"
class="h-100 d-flex flex-column"
@click="handleTileClick"
>
<v-card-title class="d-flex align-center justify-space-between">
<div class="d-flex align-center">
<v-icon :icon="tileIcon" class="mr-2"></v-icon>
<span class="text-subtitle-1 font-weight-bold">{{ tile.title }}</span>
</div>
<v-chip size="small" :color="accessLevelColor" class="text-caption">
{{ accessLevelText }}
</v-chip>
</v-card-title>
<v-card-text class="flex-grow-1">
<p class="text-body-2">{{ tile.description }}</p>
<!-- Requirements Badges -->
<div class="mt-2">
<v-chip
v-for="role in tile.requiredRole"
:key="role"
size="x-small"
class="mr-1 mb-1"
variant="outlined"
>
{{ role }}
</v-chip>
<v-chip
v-if="tile.minRank"
size="x-small"
class="mr-1 mb-1"
color="warning"
variant="outlined"
>
Rank {{ tile.minRank }}+
</v-chip>
</div>
<!-- Scope Level Indicator -->
<div v-if="tile.scopeLevel && tile.scopeLevel.length > 0" class="mt-2">
<v-icon icon="mdi-map-marker" size="small" class="mr-1"></v-icon>
<span class="text-caption">
{{ tile.scopeLevel.join(', ') }}
</span>
</div>
</v-card-text>
<v-card-actions class="mt-auto">
<v-spacer></v-spacer>
<v-btn
variant="text"
size="small"
:prepend-icon="actionIcon"
@click.stop="handleTileClick"
>
Open
</v-btn>
</v-card-actions>
</v-card>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import type { TilePermission } from '~/composables/useRBAC'
interface Props {
tile: TilePermission
}
const props = defineProps<Props>()
// Tile color based on ID
const tileColor = computed(() => {
const colors: Record<string, string> = {
'ai-logs': 'indigo',
'financial-dashboard': 'green',
'salesperson-hub': 'orange',
'user-management': 'blue',
'service-moderation-map': 'teal',
'gamification-control': 'purple',
'system-health': 'red'
}
return colors[props.tile.id] || 'surface'
})
// Tile icon based on ID
const tileIcon = computed(() => {
const icons: Record<string, string> = {
'ai-logs': 'mdi-robot',
'financial-dashboard': 'mdi-chart-line',
'salesperson-hub': 'mdi-account-tie',
'user-management': 'mdi-account-group',
'service-moderation-map': 'mdi-map',
'gamification-control': 'mdi-trophy',
'system-health': 'mdi-heart-pulse'
}
return icons[props.tile.id] || 'mdi-view-dashboard'
})
// Action icon
const actionIcon = computed(() => {
const actions: Record<string, string> = {
'ai-logs': 'mdi-chart-timeline',
'financial-dashboard': 'mdi-finance',
'salesperson-hub': 'mdi-chart-bar',
'user-management': 'mdi-account-cog',
'service-moderation-map': 'mdi-map-search',
'gamification-control': 'mdi-cog',
'system-health': 'mdi-monitor-dashboard'
}
return actions[props.tile.id] || 'mdi-open-in-new'
})
// Access level indicator
const accessLevelColor = computed(() => {
if (props.tile.requiredRole.includes('superadmin')) return 'purple'
if (props.tile.requiredRole.includes('admin')) return 'blue'
if (props.tile.requiredRole.includes('moderator')) return 'green'
return 'orange'
})
const accessLevelText = computed(() => {
if (props.tile.requiredRole.includes('superadmin')) return 'Superadmin'
if (props.tile.requiredRole.includes('admin')) return 'Admin'
if (props.tile.requiredRole.includes('moderator')) return 'Moderator'
return 'Sales'
})
// Handle tile click
function handleTileClick() {
const routes: Record<string, string> = {
'ai-logs': '/ai-logs',
'financial-dashboard': '/finance',
'salesperson-hub': '/sales',
'user-management': '/users',
'service-moderation-map': '/map',
'gamification-control': '/gamification',
'system-health': '/system'
}
const route = routes[props.tile.id]
if (route) {
navigateTo(route)
} else {
console.warn(`No route defined for tile: ${props.tile.id}`)
}
}
</script>
<style scoped>
.v-card {
cursor: pointer;
transition: all 0.2s ease-in-out;
}
.v-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.h-100 {
height: 100%;
}
</style>