gigafibre-fsm/apps/ops/src/composables/useAbsenceResize.js
louispaulb c6b2dd1491 refactor: extract composables from 5 largest files — net -1950 lines from main components
DispatchPage.vue: 1320→1217 lines
  - Extract SbModal.vue + SbContextMenu.vue reusable components
  - Extract useAbsenceResize composable
  - Extract dispatch constants to config/dispatch.js

ProjectWizard.vue: 1185→673 lines (-43%)
  - Extract useWizardPublish composable (270-line publish function)
  - Extract useWizardCatalog composable
  - Extract wizard-constants.js (step labels, options, categories)

SettingsPage.vue: 1172→850 lines (-27%)
  - Extract usePermissionMatrix composable
  - Extract useUserGroups composable
  - Extract useLegacySync composable

ClientDetailPage.vue: 1169→864 lines (-26%)
  - Extract useClientData composable (loadCustomer broken into sub-functions)
  - Extract useEquipmentActions composable
  - Extract client-constants.js + erp-pdf.js utility

checkout.js: 639→408 lines (-36%)
  - Extract address-search.js module
  - Extract otp.js module
  - Extract email-templates.js module
  - Extract project-templates.js module
  - Add erpQuery() helper to DRY repeated URL construction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:57:24 -04:00

58 lines
2.0 KiB
JavaScript

import { hToTime } from 'src/composables/useHelpers'
import { updateTech } from 'src/api/dispatch'
export function useAbsenceResize (pxPerHr, H_START) {
function startAbsenceResize (e, seg, tech, side) {
e.preventDefault()
const startX = e.clientX
const block = e.target.closest('.sb-block-absence')
const startW = block.offsetWidth
const startL = parseFloat(block.style.left)
const SNAP_PX = pxPerHr.value / 4
const snapPx = px => Math.round(px / SNAP_PX) * SNAP_PX
function onMove (ev) {
const dx = ev.clientX - startX
if (side === 'right') {
block.style.width = Math.max(SNAP_PX, snapPx(startW + dx)) + 'px'
} else {
const newL = snapPx(startL + dx)
const newW = startW + (startL - newL)
if (newW >= SNAP_PX && newL >= 0) {
block.style.left = newL + 'px'
block.style.width = newW + 'px'
}
}
const curL = parseFloat(block.style.left)
const curW = parseFloat(block.style.width)
const sH = H_START + curL / pxPerHr.value
const eH = sH + curW / pxPerHr.value
const lbl = block.querySelector('.sb-absence-label')
if (lbl) lbl.textContent = `${hToTime(sH)}${hToTime(eH)}`
}
function onUp () {
document.removeEventListener('mousemove', onMove)
document.removeEventListener('mouseup', onUp)
const curL = parseFloat(block.style.left)
const curW = parseFloat(block.style.width)
const newStartH = H_START + curL / pxPerHr.value
const newEndH = newStartH + curW / pxPerHr.value
const startTime = hToTime(newStartH)
const endTime = hToTime(newEndH)
tech.absenceStartTime = startTime
tech.absenceEndTime = endTime
updateTech(tech.name || tech.id, {
absence_start_time: startTime,
absence_end_time: endTime,
}).catch(() => {})
}
document.addEventListener('mousemove', onMove)
document.addEventListener('mouseup', onUp)
}
return { startAbsenceResize }
}