gigafibre-fsm/apps/ops/src/pages/EquipePage.vue
louispaulb 512c4a5f1b feat(ops): dispatch auto complet + perf Boîte/rapports + fix session
Planificateur « Suggérer » : 4 stratégies (smart / meilleurs d'abord / équilibré /
juste ce qu'il faut), compétences+niveaux par tech (édition inline), niveau requis
par compétence + par job, carte des tournées (1 couleur/tech, domicile→arrêts,
sélecteur de jour), fenêtre de dispatch auj.+demain (dates sélectionnées), règle
week-end + placeholder « en attente du quart », clustering + lasso + filtre-date
sur la carte, accès rapide « À assigner » (badge).

Boîte : liste /conversations allégée (45 Mo → ~1 Mo, 17×) + messages chargés à
l'ouverture. Rapports : cache SWR sur revenue-explorer (22×). Session : keep-alive
+ timeout fetch global + authFetch durci → fin des rechargements manuels.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 08:49:35 -04:00

71 lines
2.5 KiB
Vue

<template>
<q-page padding>
<div class="row items-center q-mb-md">
<div class="text-h6 text-weight-bold">Équipe</div>
<q-space />
<div class="text-caption text-grey-6">Module en développement</div>
</div>
<div class="row q-col-gutter-md q-mb-lg">
<div class="col-6 col-md-3" v-for="stat in stats" :key="stat.label">
<div class="ops-card ops-stat">
<div class="ops-stat-value" :style="{ color: stat.color }">{{ stat.value }}</div>
<div class="ops-stat-label">{{ stat.label }}</div>
</div>
</div>
</div>
<div class="ops-card">
<div class="text-subtitle1 text-weight-bold q-mb-sm">Techniciens</div>
<DataTable
:rows="techs" :columns="columns" row-key="name"
flat dense class="ops-table"
:loading="loading"
:pagination="{ rowsPerPage: 20 }"
/>
</div>
</q-page>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { listDocs } from 'src/api/erp'
import DataTable from 'src/components/shared/DataTable.vue'
const loading = ref(false)
const techs = ref([])
const stats = ref([
{ label: 'Techniciens', value: '...', color: 'var(--ops-accent)' },
{ label: 'En service', value: '...', color: 'var(--ops-success)' },
{ label: 'Congé', value: '...', color: 'var(--ops-warning)' },
{ label: 'Tâches aujourd\'hui', value: '...', color: 'var(--ops-primary)' },
])
const columns = [
{ name: 'employee_name', label: 'Nom', field: 'employee_name', align: 'left' },
{ name: 'designation', label: 'Poste', field: 'designation', align: 'left' },
{ name: 'department', label: 'Département', field: 'department', align: 'left' },
{ name: 'cell_number', label: 'Téléphone', field: 'cell_number', align: 'left' },
{ name: 'office_extension', label: 'Ext.', field: 'office_extension', align: 'center' },
{ name: 'company_email', label: 'Courriel', field: 'company_email', align: 'left' },
{ name: 'status', label: 'Statut', field: 'status', align: 'center' },
]
onMounted(async () => {
loading.value = true
try {
techs.value = await listDocs('Employee', {
filters: { status: 'Active' },
fields: ['name', 'employee_name', 'designation', 'department', 'status', 'cell_number', 'company_email', 'office_extension'],
limit: 50,
orderBy: 'employee_name asc',
})
stats.value[0].value = techs.value.length.toString()
stats.value[1].value = techs.value.filter(t => t.status === 'Active').length.toString()
} catch {
techs.value = []
}
loading.value = false
})
</script>