@fayz-ai/plugin-agenda 0.18.1 → 0.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"registries.d.ts","sourceRoot":"","sources":["../../src/data/registries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AA+BtD,eAAO,MAAM,gBAAgB,EAAE,iBAAiB,EAO/C,CAAA"}
1
+ {"version":3,"file":"registries.d.ts","sourceRoot":"","sources":["../../src/data/registries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAmCtD,eAAO,MAAM,gBAAgB,EAAE,iBAAiB,EAO/C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAG/B,MAAM,SAAS,CAAA;AA4ZhB,MAAM,WAAW,6BAA6B;IAC5C,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAyDD,wBAAgB,4BAA4B,CAAC,eAAe,CAAC,EAAE,6BAA6B,GAAG,kBAAkB,CAi1ChH"}
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAG/B,MAAM,SAAS,CAAA;AA6ZhB,MAAM,WAAW,6BAA6B;IAC5C,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAyDD,wBAAgB,4BAA4B,CAAC,eAAe,CAAC,EAAE,6BAA6B,GAAG,kBAAkB,CA+1ChH"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createMockAgendaProvider, createSupabasePublicBookingProvider } from './chunk-RVO5ILXN.js';
2
2
  export { createMockAgendaProvider } from './chunk-RVO5ILXN.js';
3
3
  import React20, { useState, useEffect, useRef, useMemo, useCallback, useLayoutEffect } from 'react';
4
- import { tl, connectionStatus, createConnectionStore, todayLocal, getSupabaseClientOptional, getActiveTenantId, registerTranslations, registerMessageDefaults, createSafeDataProvider, connectorRuntimeToken, CONNECTOR_RUNTIME_TOKEN_HEADER, getActiveUnitId, emitDataChanged, globalCache, usePluginRuntimeOptional, useTranslation, emitDomainEvent, getCurrentLocale, useActiveUnitId, localDateKey, useDataChanged, formatCurrency, resolveDataProvider } from '@fayz-ai/core';
4
+ import { tl, recordRailFields, RECORD_GROUP, activeFacet, connectionStatus, createConnectionStore, todayLocal, getSupabaseClientOptional, getActiveTenantId, registerTranslations, registerMessageDefaults, createSafeDataProvider, connectorRuntimeToken, CONNECTOR_RUNTIME_TOKEN_HEADER, getActiveUnitId, assertWrote, emitDataChanged, globalCache, usePluginRuntimeOptional, useTranslation, emitDomainEvent, getCurrentLocale, useActiveUnitId, localDateKey, useDataChanged, formatCurrency, resolveDataProvider } from '@fayz-ai/core';
5
5
  import { createPluginContext, fayzConnectorOAuth, setScheduleBlockConfig, getScheduleBlockConfig, registerPersonActions, PluginSettingsPanel, createArchetypeLookup, dedup, usePluginPrefs, useTenantPluginSettings, SettingsGroup, ToggleRow, SelectRow, PersonLink, PageActions, useRightRailStore, usePermissionOptional, ScheduleEditor, useLimitGuard, useLookupCreate, CrudFormPage, CrudDetailPage, ContactPicker, openEntity, PaymentStatusBadge as PaymentStatusBadge$1, RightRailPage, invalidateLimit } from '@fayz-ai/admin';
6
6
  import FullCalendar from '@fullcalendar/react';
7
7
  import dayGridPlugin from '@fullcalendar/daygrid';
@@ -3620,6 +3620,10 @@ function bookingToEvent(booking, statusColors, visibleResourceIds = []) {
3620
3620
  extendedProps: { booking, serviceNames }
3621
3621
  };
3622
3622
  }
3623
+ function localDateTimeString(d) {
3624
+ const pad = (n) => String(n).padStart(2, "0");
3625
+ return `${localDateKey(d)}T${pad(d.getHours())}:${pad(d.getMinutes())}:00`;
3626
+ }
3623
3627
  function generateAvailabilityEvents(schedules, professionals, dateRange, businessHours, locationMap, defaultLocationName) {
3624
3628
  if (!dateRange || schedules.length === 0) return [];
3625
3629
  const bgEvents = [];
@@ -3800,10 +3804,11 @@ function CalendarView() {
3800
3804
  const prefs = usePluginPrefs("agenda", {
3801
3805
  calendarView: config.defaultCalendarView ?? "resourceTimeGridWeek",
3802
3806
  // Como a SEMANA se agrupa: 'day' põe o dia em cima e as pessoas dentro
3803
- // dele; 'professional' inverte. Ver `weekGrouping` mais abaixo.
3804
- weekGrouping: "day"
3807
+ // dele; 'professional' inverte. 'auto' é o padrão e deixa a agenda decidir
3808
+ // pelo tamanho da equipe — ver `weekGrouping` mais abaixo.
3809
+ weekGrouping: "auto"
3805
3810
  });
3806
- const weekGrouping = prefs.get("weekGrouping") ?? "day";
3811
+ const weekGroupingPref = prefs.get("weekGrouping") ?? "auto";
3807
3812
  const agendaSettings = useAgendaSettings();
3808
3813
  const effectiveBusinessHours = {
3809
3814
  startTime: agendaSettings.startTime,
@@ -4167,6 +4172,7 @@ function CalendarView() {
4167
4172
  extendedProps: { avatarUrl: p.avatarUrl }
4168
4173
  })), [drawnProfessionals]);
4169
4174
  const visibleResourceIds = useMemo(() => resources.map((resource) => resource.id), [resources]);
4175
+ const weekGrouping = weekGroupingPref === "auto" ? resources.length <= 1 ? "professional" : "day" : weekGroupingPref;
4170
4176
  const gridMinWidth = useMemo(() => {
4171
4177
  if (!currentView.startsWith("resource")) return void 0;
4172
4178
  const daysInView = currentView.endsWith("Day") ? 1 : 7;
@@ -4361,8 +4367,12 @@ function CalendarView() {
4361
4367
  }
4362
4368
  return null;
4363
4369
  }, [schedules]);
4364
- const handleSelect = useCallback((arg) => {
4370
+ const lastSlotOpenRef = useRef(0);
4371
+ const openCreateForSlot = useCallback((startStr, endStr, professionalId) => {
4365
4372
  calendarRef.current?.getApi().unselect();
4373
+ const now = Date.now();
4374
+ if (now - lastSlotOpenRef.current < 500) return;
4375
+ lastSlotOpenRef.current = now;
4366
4376
  if (popoverVisibleRef.current || contextMenuVisibleRef.current) {
4367
4377
  setPopoverVisible(false);
4368
4378
  setSelectedBooking(null);
@@ -4371,11 +4381,10 @@ function CalendarView() {
4371
4381
  setContextMenu(null);
4372
4382
  return;
4373
4383
  }
4374
- const professionalId = arg.resource?.id;
4375
- const schedule = findScheduleForSlot(professionalId, arg.startStr);
4384
+ const schedule = findScheduleForSlot(professionalId, startStr);
4376
4385
  const proceed = () => {
4377
4386
  const locId = schedule?.locationId ?? schedule?.metadata?.locationId;
4378
- openModal("create", { prefill: { startsAt: arg.startStr, endsAt: arg.endStr, professionalId, locationId: locId || void 0 } });
4387
+ openModal("create", { prefill: { startsAt: startStr, endsAt: endStr, professionalId, locationId: locId || void 0 } });
4379
4388
  };
4380
4389
  if (config.modules.workingHours && !schedule) {
4381
4390
  setScheduleConfirm({ onConfirm: proceed });
@@ -4383,6 +4392,18 @@ function CalendarView() {
4383
4392
  }
4384
4393
  proceed();
4385
4394
  }, [openModal, findScheduleForSlot, config.modules.workingHours]);
4395
+ const handleSelect = useCallback((arg) => {
4396
+ openCreateForSlot(arg.startStr, arg.endStr, arg.resource?.id);
4397
+ }, [openCreateForSlot]);
4398
+ const handleDateClick = useCallback((arg) => {
4399
+ const professionalId = arg.resource?.id;
4400
+ if (arg.allDay) {
4401
+ openCreateForSlot(arg.dateStr, localDateKey(new Date(arg.date.getTime() + 864e5)), professionalId);
4402
+ return;
4403
+ }
4404
+ const end = new Date(arg.date.getTime() + config.slotDuration * 6e4);
4405
+ openCreateForSlot(localDateTimeString(arg.date), localDateTimeString(end), professionalId);
4406
+ }, [openCreateForSlot, config.slotDuration]);
4386
4407
  const handleEventDrop = useCallback(async (arg) => {
4387
4408
  if (arg.event.extendedProps?.isBlock) {
4388
4409
  const clicado = blocks.find((b) => b.id === arg.event.extendedProps.blockId);
@@ -5032,6 +5053,8 @@ function CalendarView() {
5032
5053
  eventMouseEnter: handleEventMouseEnter,
5033
5054
  eventMouseLeave: handleEventMouseLeave,
5034
5055
  select: handleSelect,
5056
+ dateClick: handleDateClick,
5057
+ selectLongPressDelay: 400,
5035
5058
  eventDrop: handleEventDrop,
5036
5059
  resourceLabelContent,
5037
5060
  dayHeaderContent,
@@ -6886,17 +6909,20 @@ function createSupabaseAgendaProvider(providerOptions) {
6886
6909
  if (orderId && movementCount > 0) {
6887
6910
  await pub.from("plg_financial_movements").update({ status: "cancelled" }).eq("invoice_id", orderId);
6888
6911
  await core.from("orders").update({ status: "cancelled" }).eq("id", orderId);
6889
- const { error } = await core.from("appointments").update({ status: "cancelled" }).eq("id", id);
6912
+ const { data: cancelados, error } = await core.from("appointments").update({ status: "cancelled" }).eq("id", id).select("id");
6890
6913
  if (error) throw error;
6914
+ assertWrote(cancelados);
6891
6915
  } else {
6892
6916
  if (orderId) {
6893
6917
  await pub.from("plg_financial_movements").delete().eq("invoice_id", orderId);
6894
6918
  }
6895
- const { error } = await core.from("appointments").delete().eq("id", id);
6919
+ const { data: apagados, error } = await core.from("appointments").delete().eq("id", id).select("id");
6896
6920
  if (error) throw error;
6921
+ assertWrote(apagados);
6897
6922
  if (orderId) {
6898
- const { error: orderErr } = await core.from("orders").delete().eq("id", orderId);
6923
+ const { data: pedidos, error: orderErr } = await core.from("orders").delete().eq("id", orderId).select("id");
6899
6924
  if (orderErr) throw orderErr;
6925
+ if (!pedidos?.length) console.warn("[agenda] pedido do agendamento n\xE3o foi apagado", orderId);
6900
6926
  }
6901
6927
  }
6902
6928
  },
@@ -7946,25 +7972,26 @@ function createAgendaStore(provider2, financialBridge) {
7946
7972
  }
7947
7973
  }));
7948
7974
  }
7949
-
7950
- // src/data/registries.ts
7951
7975
  var holidayEntity = {
7952
7976
  name: "Holiday",
7953
7977
  namePlural: "Holidays",
7954
7978
  icon: "TreePalm",
7955
7979
  displayField: "name",
7956
7980
  defaultSort: "date",
7981
+ formColumns: 2,
7982
+ facets: [activeFacet({ active: "Ativos", inactive: "Inativos", all: "Todos" })],
7983
+ fieldGroups: [{ id: "identity", label: "O feriado", columns: 2 }, { ...RECORD_GROUP }],
7957
7984
  defaultSortDir: "asc",
7958
7985
  fields: [
7959
- { key: "name", label: "Name", type: "text", required: true, showInTable: true },
7960
- { key: "date", label: "Date", type: "date", required: true, showInTable: true, sortable: true },
7961
- { key: "recurring", label: "Recurring Annually", type: "boolean", showInTable: true, defaultValue: false },
7986
+ { key: "name", label: "Name", type: "text", required: true, showInTable: true, group: "identity" },
7987
+ { key: "date", label: "Date", type: "date", required: true, showInTable: true, sortable: true, group: "identity" },
7988
+ { key: "recurring", label: "Recurring Annually", type: "boolean", showInTable: true, defaultValue: false, group: "identity" },
7962
7989
  // O *Tipo* do V1, em forma de chave: marcado = Feriado ("afeta agenda e
7963
7990
  // funcionamento"); desmarcado = Data Comemorativa ("usada no marketing").
7964
7991
  // Sem ele a tabela guarda o Dia do Sorvete e o 7 de setembro como iguais.
7965
- { key: "closes", label: "Affects the agenda", type: "boolean", showInTable: true, defaultValue: true },
7966
- { key: "description", label: "Description", type: "text", showInTable: false },
7967
- { key: "isActive", label: "Active", type: "boolean", showInTable: true, defaultValue: true }
7992
+ { key: "closes", label: "Affects the agenda", type: "boolean", showInTable: true, defaultValue: true, group: "identity" },
7993
+ { key: "description", label: "Description", type: "text", showInTable: false, group: "identity" },
7994
+ ...recordRailFields({ tagsTable: "holidays", activeLabel: "Ativo" })
7968
7995
  ],
7969
7996
  data: {
7970
7997
  table: "holidays",
@@ -13404,6 +13431,19 @@ BEGIN
13404
13431
  END IF;
13405
13432
  END $$;
13406
13433
  `;
13434
+ var MIGRATION_015_O_FERIADO_TAMBEM_TEM_OBSERVACAO_E_ETIQUETA = `-- ---------------------------------------------------------------------------
13435
+ -- O feriado tamb\xE9m tem observa\xE7\xE3o e etiqueta.
13436
+ --
13437
+ -- Irm\xE3 da 150 do n\xFAcleo e da 103 do financeiro, para o \xFAltimo cadastro que
13438
+ -- ficou de fora. Mesmo argumento, e aqui a etiqueta tem um uso imediato:
13439
+ -- \xABbanc\xE1rio\xBB, \xABmunicipal\xBB, \xABponto facultativo\xBB s\xE3o recortes que mudam quem
13440
+ -- fecha e quem n\xE3o fecha, e que nenhum campo do cadastro responde.
13441
+ -- ---------------------------------------------------------------------------
13442
+
13443
+ ALTER TABLE public.holidays
13444
+ ADD COLUMN IF NOT EXISTS notes text,
13445
+ ADD COLUMN IF NOT EXISTS tags text[] DEFAULT '{}'::text[];
13446
+ `;
13407
13447
  var MIGRATIONS = [
13408
13448
  { id: "000_baseline", sql: MIGRATION_000_BASELINE },
13409
13449
  { id: "001_the_connector_definers_keep_a_pinned_path", sql: MIGRATION_001_THE_CONNECTOR_DEFINERS_KEEP_A_PINNED_PATH },
@@ -13419,7 +13459,8 @@ var MIGRATIONS = [
13419
13459
  { id: "011_a_sala_entra_no_compromisso", sql: MIGRATION_011_A_SALA_ENTRA_NO_COMPROMISSO },
13420
13460
  { id: "012_a_sala_sem_nome_tambem_e_uma_sala", sql: MIGRATION_012_A_SALA_SEM_NOME_TAMBEM_E_UMA_SALA },
13421
13461
  { id: "013_o_selo_do_atendimento_tem_onde_morar", sql: MIGRATION_013_O_SELO_DO_ATENDIMENTO_TEM_ONDE_MORAR },
13422
- { id: "014_a_configuracao_nao_e_uma_tabela", sql: MIGRATION_014_A_CONFIGURACAO_NAO_E_UMA_TABELA }
13462
+ { id: "014_a_configuracao_nao_e_uma_tabela", sql: MIGRATION_014_A_CONFIGURACAO_NAO_E_UMA_TABELA },
13463
+ { id: "015_o_feriado_tambem_tem_observacao_e_etiqueta", sql: MIGRATION_015_O_FERIADO_TAMBEM_TEM_OBSERVACAO_E_ETIQUETA }
13423
13464
  ];
13424
13465
  function computeCommissionAmount(total, ratePercent) {
13425
13466
  const base = Number(total) || 0;