From 8b0e633aac0420d43ace77a2e158f65d9fe51b93 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 11 May 2026 10:44:16 -0300 Subject: [PATCH] agenda: centralize FullCalendar touch defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sem long-press delays customizados, tap em slot vazio precisa de 1000ms antes de disparar select — diverge totalmente do mouse (clique abre na hora). Mesmo problema em eventDrop. Move pra utils/fcDefaults.js e aplica nos 4 calendars (AgendaCalendar, AgendaClinicMosaic, AgendaTerapeutaPage, MelissaAgenda no proximo commit). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../agenda/components/AgendaCalendar.vue | 2 ++ .../agenda/components/AgendaClinicMosaic.vue | 2 ++ .../agenda/pages/AgendaTerapeutaPage.vue | 2 ++ src/features/agenda/utils/fcDefaults.js | 32 +++++++++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 src/features/agenda/utils/fcDefaults.js diff --git a/src/features/agenda/components/AgendaCalendar.vue b/src/features/agenda/components/AgendaCalendar.vue index 9b5a8d4..12badac 100644 --- a/src/features/agenda/components/AgendaCalendar.vue +++ b/src/features/agenda/components/AgendaCalendar.vue @@ -23,6 +23,7 @@ import interactionPlugin from '@fullcalendar/interaction'; import dayGridPlugin from '@fullcalendar/daygrid'; import ProgressSpinner from 'primevue/progressspinner'; +import { FC_TOUCH_DEFAULTS } from '@/features/agenda/utils/fcDefaults'; const props = defineProps({ // UI @@ -71,6 +72,7 @@ const calendarOptions = computed(() => { const maxTime = isWorkHours ? props.slotMaxTime : '23:59:59'; return { + ...FC_TOUCH_DEFAULTS, plugins: [timeGridPlugin, interactionPlugin, dayGridPlugin], initialView: initialView.value, diff --git a/src/features/agenda/components/AgendaClinicMosaic.vue b/src/features/agenda/components/AgendaClinicMosaic.vue index fb910f7..8a2fd36 100644 --- a/src/features/agenda/components/AgendaClinicMosaic.vue +++ b/src/features/agenda/components/AgendaClinicMosaic.vue @@ -23,6 +23,7 @@ import dayGridPlugin from '@fullcalendar/daygrid'; import listPlugin from '@fullcalendar/list'; import interactionPlugin from '@fullcalendar/interaction'; import ptBrLocale from '@fullcalendar/core/locales/pt-br'; +import { FC_TOUCH_DEFAULTS } from '@/features/agenda/utils/fcDefaults'; const props = defineProps({ view: { type: String, default: 'day' }, // 'day' | 'week' | 'month' @@ -258,6 +259,7 @@ function emitDebug(col) { function buildFcOptions(ownerId) { const base = { + ...FC_TOUCH_DEFAULTS, plugins: [timeGridPlugin, dayGridPlugin, listPlugin, interactionPlugin], locale: ptBrLocale, timeZone: props.timezone, diff --git a/src/features/agenda/pages/AgendaTerapeutaPage.vue b/src/features/agenda/pages/AgendaTerapeutaPage.vue index 91b1327..0953b36 100644 --- a/src/features/agenda/pages/AgendaTerapeutaPage.vue +++ b/src/features/agenda/pages/AgendaTerapeutaPage.vue @@ -31,6 +31,7 @@ import dayGridPlugin from '@fullcalendar/daygrid'; import listPlugin from '@fullcalendar/list'; import interactionPlugin from '@fullcalendar/interaction'; import ptBrLocale from '@fullcalendar/core/locales/pt-br'; +import { FC_TOUCH_DEFAULTS } from '@/features/agenda/utils/fcDefaults'; import AgendaEventDialog from '@/features/agenda/components/AgendaEventDialog.vue'; import BloqueioDialog from '@/features/agenda/components/BloqueioDialog.vue'; @@ -672,6 +673,7 @@ const _initSlotMax = slotMaxTime.value; const fcOptions = computed(() => ({ plugins: [timeGridPlugin, dayGridPlugin, listPlugin, interactionPlugin], locale: ptBrLocale, + ...FC_TOUCH_DEFAULTS, timeZone: timezone.value, headerToolbar: false, diff --git a/src/features/agenda/utils/fcDefaults.js b/src/features/agenda/utils/fcDefaults.js new file mode 100644 index 0000000..6203d53 --- /dev/null +++ b/src/features/agenda/utils/fcDefaults.js @@ -0,0 +1,32 @@ +/* + * FullCalendar shared defaults. + * + * Centraliza opções que devem se aplicar a TODAS as instâncias do + * FullCalendar do sistema (MelissaAgenda, AgendaTerapeutaPage, + * AgendaClinicMosaic, e futuras). Se aparecer outra agenda, basta: + * + * import { FC_TOUCH_DEFAULTS } from '@/features/agenda/utils/fcDefaults'; + * const fcOptions = { ...FC_TOUCH_DEFAULTS, ...resto }; + * + * Sem isso, tablet/touch fica sem paridade com mouse — ver detalhe abaixo. + */ + +/** + * Defaults pra paridade touch ↔ mouse no FullCalendar. + * + * Por padrão o FC exige long-press de 1000ms no touch antes de disparar + * `select` ou `eventDrop` — no mouse, qualquer clique/drag funciona na hora. + * Zerar os dois delays faz tap se comportar igual clique do mouse. + * + * - selectLongPressDelay: 0 → tap em slot vazio dispara `select` na hora + * (abre o AgendaEventDialog igual ao desktop) + * - eventLongPressDelay: 0 → tap-and-drag em evento existente já move/resize + * sem precisar segurar 1s + * + * O FC continua diferenciando tap curto (select de 1 slot) de tap+drag + * (select de range) automaticamente — não há perda de funcionalidade. + */ +export const FC_TOUCH_DEFAULTS = Object.freeze({ + selectLongPressDelay: 0, + eventLongPressDelay: 0 +});