enterprise_assest_managemen.../frontend/src/views/Dashboard.vue

305 lines
8.0 KiB
Vue

<!-- frontend/src/views/Dashboard.vue -->
<template>
<div class="dashboard">
<!-- Page header with Fluent Design -->
<div class="page-header fluent-entrance mb-8">
<div class="d-flex justify-space-between align-center">
<div>
<h1 class="text-title1 mb-2">Dashboard</h1>
<p class="text-body1" style="color: #605E5C;">
Welcome back! Here's an overview of your assets.
</p>
</div>
<v-btn
color="primary"
variant="elevated"
size="large"
prepend-icon="mdi-plus"
class="fluent-layer-2"
@click="createAsset"
>
Add Asset
</v-btn>
</div>
</div>
<!-- Stats cards with Fluent Design -->
<v-row class="mb-8">
<v-col cols="12" sm="6" md="3">
<v-card class="stat-card fluent-layer-1 pa-6 text-center" elevation="0">
<v-icon size="40" color="primary" class="mb-3">
mdi-package-variant
</v-icon>
<div class="text-title2 font-weight-bold mb-1" style="color: #0078D4;">
{{ totalAssets }}
</div>
<div class="text-caption1" style="color: #605E5C;">Total Assets</div>
</v-card>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-card class="stat-card fluent-layer-1 pa-6 text-center" elevation="0">
<v-icon size="40" color="success" class="mb-3">
mdi-check-circle
</v-icon>
<div class="text-title2 font-weight-bold mb-1" style="color: #107C10;">
{{ activeAssets }}
</div>
<div class="text-caption1" style="color: #605E5C;">Active Assets</div>
</v-card>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-card class="stat-card fluent-layer-1 pa-6 text-center" elevation="0">
<v-icon size="40" color="warning" class="mb-3">mdi-wrench</v-icon>
<div class="text-title2 font-weight-bold mb-1" style="color: #FFB900;">
{{ maintenanceAssets }}
</div>
<div class="text-caption1" style="color: #605E5C;">In Maintenance</div>
</v-card>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-card class="stat-card fluent-layer-1 pa-6 text-center" elevation="0">
<v-icon size="40" color="info" class="mb-3">
mdi-currency-usd
</v-icon>
<div class="text-title2 font-weight-bold mb-1" style="color: #0078D4;">
{{ formatCurrency(totalValue) }}
</div>
<div class="text-caption1" style="color: #605E5C;">Total Value</div>
</v-card>
</v-col>
</v-row>
<!-- Quick actions and recent activity -->
<v-row>
<!-- Quick actions -->
<v-col cols="12" md="4">
<v-card class="pa-4">
<v-card-title class="text-h6 pa-0 mb-4"> Quick Actions </v-card-title>
<div class="d-flex flex-column ga-2">
<v-btn
variant="outlined"
block
prepend-icon="mdi-plus"
@click="createAsset"
>
Add New Asset
</v-btn>
<v-btn
variant="outlined"
block
prepend-icon="mdi-wrench"
@click="createWorkOrder"
>
Create Work Order
</v-btn>
<v-btn
variant="outlined"
block
prepend-icon="mdi-qrcode"
@click="scanQRCode"
>
Scan QR Code
</v-btn>
<v-btn
variant="outlined"
block
prepend-icon="mdi-chart-bar"
@click="viewReports"
>
View Reports
</v-btn>
</div>
</v-card>
</v-col>
<!-- Recent assets -->
<v-col cols="12" md="8">
<v-card class="pa-4">
<v-card-title
class="text-h6 pa-0 mb-4 d-flex justify-space-between align-center"
>
Recent Assets
<v-btn variant="text" size="small" @click="viewAllAssets">
View All
</v-btn>
</v-card-title>
<v-data-table
:headers="assetHeaders"
:items="recentAssets"
:loading="isLoading"
hide-default-footer
density="compact"
>
<template #item.status="{ item }">
<v-chip
:color="getStatusColor(item.status)"
size="small"
variant="flat"
>
{{ item.status }}
</v-chip>
</template>
<template #item.actions="{ item }">
<v-btn
icon="mdi-eye"
size="small"
variant="text"
@click="viewAsset(item.id)"
/>
</template>
</v-data-table>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { ref, computed, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { useAssetsStore } from '../stores/assets';
import { useUIStore } from '../stores/ui';
export default {
name: 'Dashboard',
setup() {
const router = useRouter();
const assetsStore = useAssetsStore();
const uiStore = useUIStore();
const assetHeaders = [
{ title: 'Name', value: 'name', sortable: false },
{ title: 'Identifier', value: 'asset_identifier', sortable: false },
{ title: 'Category', value: 'category', sortable: false },
{ title: 'Status', value: 'status', sortable: false },
{ title: 'Actions', value: 'actions', sortable: false, width: 80 },
];
// Mock data for demo
const mockAssets = [
{
id: '1',
name: 'Dell Laptop #001',
asset_identifier: 'IT001',
category: 'IT Equipment',
status: 'active',
},
{
id: '2',
name: 'Conference Table',
asset_identifier: 'FUR001',
category: 'Office Furniture',
status: 'active',
},
{
id: '3',
name: 'X-Ray Machine',
asset_identifier: 'MED001',
category: 'Medical Equipment',
status: 'maintenance',
},
];
const totalAssets = computed(() => 24); // Mock data
const activeAssets = computed(() => 20); // Mock data
const maintenanceAssets = computed(() => 3); // Mock data
const totalValue = computed(() => 125000); // Mock data
const recentAssets = computed(() => mockAssets);
const isLoading = computed(() => assetsStore.isLoading);
const createAsset = () => {
router.push('/assets/add');
};
const createWorkOrder = () => {
router.push('/work-orders/new');
};
const scanQRCode = () => {
uiStore.showInfo('QR Code scanner feature coming soon!');
};
const viewReports = () => {
router.push('/reports');
};
const viewAllAssets = () => {
router.push('/assets');
};
const viewAsset = (id) => {
router.push(`/assets/${id}`);
};
const formatCurrency = (amount) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(amount);
};
const getStatusColor = (status) => {
const colors = {
active: 'success',
inactive: 'default',
maintenance: 'warning',
retired: 'error',
};
return colors[status] || 'default';
};
onMounted(() => {
uiStore.setPageTitle('Dashboard');
});
return {
assetHeaders,
totalAssets,
activeAssets,
maintenanceAssets,
totalValue,
recentAssets,
isLoading,
createAsset,
createWorkOrder,
scanQRCode,
viewReports,
viewAllAssets,
viewAsset,
formatCurrency,
getStatusColor,
};
},
};
</script>
<style scoped>
.dashboard {
padding: 24px;
}
.v-card {
transition: all 0.3s ease;
}
.v-card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
@media (max-width: 768px) {
.dashboard {
padding: 16px;
}
}
</style>