169 lines
6.6 KiB
Vue
169 lines
6.6 KiB
Vue
<template>
|
|
<section class="content-grid">
|
|
<v-card class="metric span-3">
|
|
<div class="metric-label">Assigned</div>
|
|
<div class="metric-value">{{ summary.active_assignments || 0 }}</div>
|
|
<div class="metric-subtle">Assets with active custody</div>
|
|
</v-card>
|
|
<v-card class="metric span-3">
|
|
<div class="metric-label">Unassigned</div>
|
|
<div class="metric-value">{{ summary.unassigned_assets || 0 }}</div>
|
|
<div class="metric-subtle">Need owner/location review</div>
|
|
</v-card>
|
|
<v-card class="metric span-3">
|
|
<div class="metric-label">Employees</div>
|
|
<div class="metric-value">{{ employees.length }}</div>
|
|
<div class="metric-subtle">Manual or Workday synced</div>
|
|
</v-card>
|
|
<v-card class="metric span-3">
|
|
<div class="metric-label">Locations</div>
|
|
<div class="metric-value">{{ summary.assigned_locations || 0 }}</div>
|
|
<div class="metric-subtle">Active assignment sites</div>
|
|
</v-card>
|
|
|
|
<v-card class="span-5 panel-pad">
|
|
<h2 class="section-title mb-4">Assign asset</h2>
|
|
<v-select v-model="assignmentForm.asset_id" :items="assetOptions" item-title="title" item-value="value" label="Asset" />
|
|
<v-select v-model="assignmentForm.employee_id" :items="employeeOptions" item-title="title" item-value="value" clearable label="Employee" @update:model-value="applyEmployeeDefaults" />
|
|
<v-text-field v-model="assignmentForm.department" label="Department" />
|
|
<v-text-field v-model="assignmentForm.location" label="Location" />
|
|
<v-textarea v-model="assignmentForm.notes" label="Notes" rows="2" />
|
|
<v-btn color="primary" prepend-icon="mdi-account-check" :loading="assignmentSaving" @click="$emit('assign-asset', assignmentForm)">Assign asset</v-btn>
|
|
</v-card>
|
|
|
|
<v-card class="span-7 panel-pad">
|
|
<div class="toolbar-row mb-4">
|
|
<h2 class="section-title">Employees</h2>
|
|
<v-spacer />
|
|
<v-btn variant="tonal" prepend-icon="mdi-account-plus" @click="employeeDialog = true">Add employee</v-btn>
|
|
</div>
|
|
<v-list lines="two">
|
|
<v-list-item v-for="employee in employees" :key="employee.id" prepend-icon="mdi-account">
|
|
<v-list-item-title>{{ employee.name }}</v-list-item-title>
|
|
<v-list-item-subtitle>{{ employee.email || employee.employee_number }} · {{ employee.department || 'No department' }} · {{ employee.location || 'No location' }}</v-list-item-subtitle>
|
|
<template #append>
|
|
<v-chip size="small" variant="tonal">{{ employee.source }}</v-chip>
|
|
</template>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-card>
|
|
|
|
<v-card class="span-12 panel-pad">
|
|
<div class="toolbar-row mb-4">
|
|
<h2 class="section-title">Traceability</h2>
|
|
<v-spacer />
|
|
<v-btn variant="tonal" prepend-icon="mdi-refresh" @click="$emit('reload')">Refresh</v-btn>
|
|
</div>
|
|
<div style="overflow-x:auto">
|
|
<table class="asset-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Asset</th>
|
|
<th>Employee</th>
|
|
<th>Department</th>
|
|
<th>Location</th>
|
|
<th>Assigned</th>
|
|
<th>Status</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="assignment in assignments" :key="assignment.id">
|
|
<td>
|
|
<strong>{{ assignment.asset_code }}</strong><br />
|
|
<span class="quiet">{{ assignment.asset_description }}</span>
|
|
</td>
|
|
<td>{{ assignment.employee_name || 'Unassigned employee' }}</td>
|
|
<td>{{ assignment.department || '-' }}</td>
|
|
<td>{{ assignment.location || '-' }}</td>
|
|
<td>{{ shortDate(assignment.assigned_at) }}</td>
|
|
<td><span :class="['status-chip', assignment.active ? 'status-in_service' : 'status-disposed']">{{ assignment.status }}</span></td>
|
|
<td class="text-right">
|
|
<v-btn v-if="assignment.active" size="small" variant="text" color="warning" @click="$emit('release-assignment', assignment)">Release</v-btn>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</v-card>
|
|
|
|
<v-dialog v-model="employeeDialog" max-width="480">
|
|
<v-card>
|
|
<v-card-title>Add employee</v-card-title>
|
|
<v-card-text>
|
|
<v-text-field v-model="employeeForm.name" label="Name" />
|
|
<v-text-field v-model="employeeForm.email" label="Email" />
|
|
<v-text-field v-model="employeeForm.employee_number" label="Employee number" />
|
|
<v-text-field v-model="employeeForm.department" label="Department" />
|
|
<v-text-field v-model="employeeForm.location" label="Location" />
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer />
|
|
<v-btn variant="text" @click="employeeDialog = false">Cancel</v-btn>
|
|
<v-btn color="primary" @click="saveEmployee">Save employee</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</v-dialog>
|
|
</section>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
props: {
|
|
assignments: { type: Array, required: true },
|
|
assets: { type: Array, required: true },
|
|
assignmentSaving: { type: Boolean, default: false },
|
|
employees: { type: Array, required: true },
|
|
shortDate: { type: Function, required: true },
|
|
summary: { type: Object, required: true }
|
|
},
|
|
emits: ['add-employee', 'assign-asset', 'release-assignment', 'reload'],
|
|
data() {
|
|
return {
|
|
assignmentForm: {
|
|
asset_id: null,
|
|
employee_id: null,
|
|
department: '',
|
|
location: '',
|
|
notes: ''
|
|
},
|
|
employeeDialog: false,
|
|
employeeForm: {
|
|
name: '',
|
|
email: '',
|
|
employee_number: '',
|
|
department: '',
|
|
location: ''
|
|
}
|
|
};
|
|
},
|
|
computed: {
|
|
assetOptions() {
|
|
return this.assets.map((asset) => ({
|
|
title: `${asset.asset_id} · ${asset.description}`,
|
|
value: asset.id
|
|
}));
|
|
},
|
|
employeeOptions() {
|
|
return this.employees.map((employee) => ({
|
|
title: `${employee.name}${employee.department ? ` · ${employee.department}` : ''}`,
|
|
value: employee.id
|
|
}));
|
|
}
|
|
},
|
|
methods: {
|
|
applyEmployeeDefaults(id) {
|
|
const employee = this.employees.find((item) => item.id === id);
|
|
if (!employee) return;
|
|
this.assignmentForm.department = employee.department || '';
|
|
this.assignmentForm.location = employee.location || '';
|
|
},
|
|
saveEmployee() {
|
|
this.$emit('add-employee', { ...this.employeeForm });
|
|
this.employeeDialog = false;
|
|
this.employeeForm = { name: '', email: '', employee_number: '', department: '', location: '' };
|
|
}
|
|
}
|
|
};
|
|
</script>
|