168 lines
4.4 KiB
Vue
168 lines
4.4 KiB
Vue
<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> |