diff --git a/apps/ops/src/pages/PlanificationPage.vue b/apps/ops/src/pages/PlanificationPage.vue index 9f24492..55283fa 100644 --- a/apps/ops/src/pages/PlanificationPage.vue +++ b/apps/ops/src/pages/PlanificationPage.vue @@ -1620,19 +1620,29 @@ Choisir le domicile (point de départ) sur la carte Fixer le départ à la position GPS live actuelle du tech (Traccar) - +
- + Appareil GPS : - - - - + + + +
Aucun job ce jour.
@@ -2676,14 +2686,37 @@ async function loadTraccarDevices () { devicesLoading.value = true try { const d = await roster.listTraccarDevices(); traccarDevices.value = Array.isArray(d) ? d : (d && d.devices) || []; _devicesLoaded = true } catch (e) { /* non bloquant */ } finally { devicesLoading.value = false } } -function filterDevices (val, update) { update(() => { deviceFilter.value = (val || '').toLowerCase() }) } const deviceOptions = computed(() => { - const q = deviceFilter.value + const q = deviceFilter.value.toLowerCase().trim() return traccarDevices.value .map(d => ({ label: d.name || d.uniqueId || ('#' + d.id), value: String(d.id), uniqueId: d.uniqueId || '', online: d.status === 'online' })) .filter(o => !q || o.label.toLowerCase().includes(q) || (o.uniqueId && o.uniqueId.toLowerCase().includes(q))) .sort((a, b) => (b.online ? 1 : 0) - (a.online ? 1 : 0) || a.label.localeCompare(b.label)) }) +// Appareil ACTUELLEMENT relié au tech de l'éditeur (résout l'id → nom réel, ex. « 24 - Stephane M »). missing = id enregistré mais introuvable dans Traccar. +const jdDevice = computed(() => { + const id = dayEditor.tech && dayEditor.tech.traccar_device_id + if (!id) return null + const d = traccarDevices.value.find(x => String(x.id) === String(id)) + if (d) return { value: String(d.id), label: d.name || d.uniqueId || ('#' + d.id), online: d.status === 'online', uniqueId: d.uniqueId || '' } + return { value: String(id), label: devicesLoading.value ? ('#' + id + '…') : ('#' + id + ' — introuvable'), online: false, missing: !devicesLoading.value } +}) +// Suggestion AUTO quand non relié : appareil dont le nom/uniqueId contient un mot du nom du tech (≥3 lettres). Facilite « relier ». +const _normDev = (s) => String(s || '').toLowerCase().normalize('NFD').replace(/\p{Diacritic}/gu, '') +const jdDeviceSuggest = computed(() => { + if (jdDevice.value) return null + const t = dayEditor.tech; if (!t) return null + const parts = _normDev(t.name).split(/[^a-z]+/).filter(p => p.length >= 3) + if (!parts.length) return null + let best = null + for (const d of traccarDevices.value) { + const dn = _normDev(d.name) + ' ' + _normDev(d.uniqueId) + const hit = parts.filter(p => dn.includes(p)).length + if (hit > (best ? best.hit : 0)) best = { hit, d } + } + if (best && best.hit >= 1) { const d = best.d; return { value: String(d.id), label: d.name || ('#' + d.id), online: d.status === 'online' } } + return null +}) async function onPickDevice (tech, deviceId) { if (!tech || !tech.id) return const prev = tech.traccar_device_id || ''; const v = deviceId == null ? '' : String(deviceId)