gigafibre-fsm/apps/ops/src/components/customer/CustomerInfoCard.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

73 lines
3.4 KiB
Vue

<template>
<div>
<div class="section-title">
<q-icon name="info" size="18px" class="q-mr-xs" /> Informations
</div>
<div class="info-grid">
<div class="info-row editable-row">
<q-icon name="mail" size="16px" color="grey-6" />
<span class="info-label">Envoi:</span>
<q-select v-model="customer.invoice_delivery_method" dense borderless
:options="['Email', 'Poste', 'Email + Poste']" emit-value map-options
style="min-width:120px" input-class="editable-input text-weight-bold"
@update:model-value="save('invoice_delivery_method')" />
</div>
<div class="info-row editable-row">
<q-icon name="receipt_long" size="16px" color="grey-6" />
<span class="info-label">Taxe:</span>
<q-select v-model="customer.tax_category_legacy" dense borderless
:options="['Federal + Provincial (9.5%)', 'Federal seulement', 'Exempté']"
emit-value map-options style="min-width:140px" input-class="editable-input"
@update:model-value="save('tax_category_legacy')" />
</div>
<div class="info-row">
<q-toggle v-model="customer.is_bad_payer" dense size="xs" color="red"
@update:model-value="save('is_bad_payer')" />
<q-icon name="warning" size="16px" :color="customer.is_bad_payer ? 'red-6' : 'grey-4'" />
<span :class="customer.is_bad_payer ? 'text-negative text-weight-medium' : 'text-grey-5'">Mauvais payeur</span>
</div>
<div class="info-row">
<q-toggle v-model="customer.exclude_fees" dense size="xs" color="orange"
@update:model-value="save('exclude_fees')" />
<q-icon name="money_off" size="16px" :color="customer.exclude_fees ? 'orange-6' : 'grey-4'" />
<span :class="customer.exclude_fees ? 'text-warning' : 'text-grey-5'">Exclure frais</span>
</div>
<div class="info-row">
<q-toggle v-model="customer.ppa_enabled" dense size="xs" color="green"
@update:model-value="save('ppa_enabled')" />
<q-icon :name="customer.ppa_enabled ? 'credit_card' : 'credit_card_off'" size="16px"
:color="customer.ppa_enabled ? 'green-6' : 'grey-4'" />
<span :class="customer.ppa_enabled ? 'text-green-7' : 'text-grey-5'">PPA</span>
</div>
<div v-if="customer.date_created_legacy" class="info-row">
<q-icon name="event" size="16px" color="grey-6" />
<span class="text-caption text-grey-6">Client depuis {{ customer.date_created_legacy }}</span>
</div>
</div>
<div class="q-mt-sm" style="border-top:1px solid #e2e8f0;padding-top:6px">
<q-input v-model="customer.notes_internal" dense borderless type="textarea" autogrow
placeholder="Notes internes..." input-class="editable-input text-caption"
@blur="save('notes_internal')" @keyup.ctrl.enter="$event.target.blur()" />
</div>
</div>
</template>
<script setup>
import { updateDoc } from 'src/api/erp'
const props = defineProps({ customer: { type: Object, required: true } })
const CHECK_FIELDS = ['is_bad_payer', 'exclude_fees', 'ppa_enabled']
async function save (field) {
try {
let val = props.customer[field]
if (CHECK_FIELDS.includes(field)) val = val ? 1 : 0
await updateDoc('Customer', props.customer.name, { [field]: val ?? '' })
} catch (e) {
const { Notify } = await import('quasar')
Notify?.create?.({ type: 'negative', message: 'Erreur: ' + e.message, timeout: 3000 })
}
}
</script>