admin firs step
This commit is contained in:
168
frontend/admin/components/TileCard.vue
Normal file
168
frontend/admin/components/TileCard.vue
Normal 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>
|
||||
Reference in New Issue
Block a user