@fayz-ai/plugin-agenda 0.14.0 → 0.16.0
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.
- package/dist/components/AppointmentModal.d.ts.map +1 -1
- package/dist/config.d.ts +12 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/index.js +134 -13
- package/dist/index.js.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/dist/types.d.ts +45 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppointmentModal.d.ts","sourceRoot":"","sources":["../../src/components/AppointmentModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAA;AAoBnE,OAAO,KAAK,EAAE,kBAAkB,EAAiB,MAAM,UAAU,CAAA;AACjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AAiPtD,UAAU,KAAK;IACb,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,qBAAqB,CAAA;IACtC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,qBAAqB,KAAK,IAAI,CAAA;CACxE;
|
|
1
|
+
{"version":3,"file":"AppointmentModal.d.ts","sourceRoot":"","sources":["../../src/components/AppointmentModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAA;AAoBnE,OAAO,KAAK,EAAE,kBAAkB,EAAiB,MAAM,UAAU,CAAA;AACjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AAiPtD,UAAU,KAAK;IACb,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,qBAAqB,CAAA;IACtC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,qBAAqB,KAAK,IAAI,CAAA;CACxE;AASD,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,qBAw3BzH"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PluginRegistryDef, PluginScope, VerticalId } from '@fayz-ai/core';
|
|
2
|
-
import type
|
|
2
|
+
import { type EntityLookup } from '@fayz-ai/admin';
|
|
3
3
|
import type { AgendaDataProvider } from './data/types';
|
|
4
4
|
import type { StatusConfig, BookingTypeConfig } from './types';
|
|
5
5
|
import type { AgendaFinancialBridge } from './bridges/financial-bridge';
|
|
@@ -107,6 +107,16 @@ export interface AgendaPluginOptions {
|
|
|
107
107
|
autoCreateOrder?: boolean;
|
|
108
108
|
/** Contact/client lookup */
|
|
109
109
|
contactLookup?: EntityLookup;
|
|
110
|
+
/** De onde saem os CONVIDADOS.
|
|
111
|
+
*
|
|
112
|
+
* Separado de `contactLookup` de propósito. O lookup de cliente costuma ser
|
|
113
|
+
* estreito — numa casa é `customer|supplier|lead` —, e com razão: o cliente
|
|
114
|
+
* de um compromisso é uma dessas coisas.
|
|
115
|
+
*
|
|
116
|
+
* Convidado não. Numa reunião comercial senta gente da casa junto com gente
|
|
117
|
+
* de fora, e herdar o recorte do cliente deixaria de fora exatamente os
|
|
118
|
+
* colegas. O padrão é PESSOA, sem recorte. */
|
|
119
|
+
attendeeLookup?: EntityLookup;
|
|
110
120
|
/** Client entity definition for the Client tab in booking modal */
|
|
111
121
|
clientEntityDef?: EntityDef;
|
|
112
122
|
/** Service lookup */
|
|
@@ -219,6 +229,7 @@ export interface ResolvedAgendaConfig {
|
|
|
219
229
|
source?: ExternalBookingSource;
|
|
220
230
|
}) => void | Promise<void>;
|
|
221
231
|
contactLookup?: EntityLookup;
|
|
232
|
+
attendeeLookup?: EntityLookup;
|
|
222
233
|
clientEntityDef?: EntityDef;
|
|
223
234
|
serviceLookup?: EntityLookup;
|
|
224
235
|
professionalLookup?: EntityLookup;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAkOjD,MAAM,WAAW,6BAA6B;IAC5C,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAkOjD,MAAM,WAAW,6BAA6B;IAC5C,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAyDD,wBAAgB,4BAA4B,CAAC,eAAe,CAAC,EAAE,6BAA6B,GAAG,kBAAkB,CAigBhH"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createMockAgendaProvider, createSupabasePublicBookingProvider } from '.
|
|
|
2
2
|
export { createMockAgendaProvider } from './chunk-PDYBAVXU.js';
|
|
3
3
|
import React11, { useState, useEffect, useCallback, useMemo, useRef, useLayoutEffect } from 'react';
|
|
4
4
|
import { connectionStatus, createConnectionStore, getSupabaseClientOptional, getActiveTenantId, registerTranslations, registerMessageDefaults, createSafeDataProvider, connectorRuntimeToken, CONNECTOR_RUNTIME_TOKEN_HEADER, getActiveUnitId, emitDataChanged, usePluginRuntimeOptional, useTranslation, emitDomainEvent, getCurrentLocale, useActiveUnitId, useDataChanged, formatCurrency } from '@fayz-ai/core';
|
|
5
|
-
import { createPluginContext, fayzConnectorOAuth, setScheduleBlockConfig, getScheduleBlockConfig, PluginSettingsPanel, dedup, useTenantPluginSettings, SettingsGroup, ToggleRow, SelectRow, usePermissionOptional, PersonLink, usePluginPrefs, PageActions, PaymentStatusBadge as PaymentStatusBadge$1, RightRailPage, useLimitGuard, useLookupCreate, CrudFormPage, CrudDetailPage, ContactPicker, invalidateLimit } from '@fayz-ai/admin';
|
|
5
|
+
import { createPluginContext, fayzConnectorOAuth, setScheduleBlockConfig, getScheduleBlockConfig, PluginSettingsPanel, createArchetypeLookup, dedup, useTenantPluginSettings, SettingsGroup, ToggleRow, SelectRow, usePermissionOptional, PersonLink, usePluginPrefs, PageActions, PaymentStatusBadge as PaymentStatusBadge$1, RightRailPage, useLimitGuard, useLookupCreate, CrudFormPage, CrudDetailPage, ContactPicker, invalidateLimit } from '@fayz-ai/admin';
|
|
6
6
|
import FullCalendar from '@fullcalendar/react';
|
|
7
7
|
import dayGridPlugin from '@fullcalendar/daygrid';
|
|
8
8
|
import timeGridPlugin from '@fullcalendar/timegrid';
|
|
@@ -10,7 +10,7 @@ import resourceTimeGridPlugin from '@fullcalendar/resource-timegrid';
|
|
|
10
10
|
import interactionPlugin from '@fullcalendar/interaction';
|
|
11
11
|
import listPlugin from '@fullcalendar/list';
|
|
12
12
|
import ptBrLocale from '@fullcalendar/core/locales/pt-br';
|
|
13
|
-
import { Loader2, AlertCircle, RefreshCw, CalendarPlus, X, CheckCircle2, Search, LogIn, User, Clock, CalendarDays, Plus, Settings, ChevronLeft, ChevronRight, CircleAlert, CircleDollarSign, Ban, CheckSquare, Calendar, DollarSign, AlertTriangle, MapPin, Briefcase, CircleDot, FileText, Check, HandCoins, Pencil, Trash2, FileCheck, ArrowRightLeft, CreditCard, QrCode, Banknote, ExternalLink } from 'lucide-react';
|
|
13
|
+
import { Loader2, AlertCircle, RefreshCw, CalendarPlus, X, CheckCircle2, Search, LogIn, User, Clock, CalendarDays, Plus, Settings, ChevronLeft, ChevronRight, CircleAlert, CircleDollarSign, Ban, CheckSquare, Calendar, DollarSign, AlertTriangle, Users, MapPin, Briefcase, CircleDot, FileText, Check, HandCoins, Pencil, Trash2, FileCheck, ArrowRightLeft, CreditCard, QrCode, Banknote, ExternalLink } from 'lucide-react';
|
|
14
14
|
import { toast, Button, Checkbox, Badge, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SubpageHeader, FilterSection, MiniCalendar, PageHeaderActions, ConfirmDialog, FilterCheckRow, SearchCombobox, cn, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '@fayz-ai/ui';
|
|
15
15
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
16
16
|
import { createPortal } from 'react-dom';
|
|
@@ -203,8 +203,6 @@ function buildAgendaMessageDefaults() {
|
|
|
203
203
|
}
|
|
204
204
|
];
|
|
205
205
|
}
|
|
206
|
-
|
|
207
|
-
// src/config.ts
|
|
208
206
|
var DEFAULT_LABELS = {
|
|
209
207
|
pageTitle: "Agenda",
|
|
210
208
|
pageSubtitle: "Calendar and appointment management",
|
|
@@ -324,8 +322,21 @@ function resolveConfig(options) {
|
|
|
324
322
|
cancellationDetails: options?.cancellationDetails,
|
|
325
323
|
onBookingCreated: options?.onBookingCreated,
|
|
326
324
|
contactLookup: options?.contactLookup,
|
|
325
|
+
// Sem recorte quando ninguém disse o contrário: convidado é qualquer
|
|
326
|
+
// pessoa. Herdar `contactLookup` aqui seria herdar um recorte pensado
|
|
327
|
+
// para outra pergunta.
|
|
328
|
+
attendeeLookup: options?.attendeeLookup ?? createArchetypeLookup({ archetype: "person" }),
|
|
327
329
|
clientEntityDef: options?.clientEntityDef,
|
|
328
|
-
|
|
330
|
+
// Um PADRÃO, e não `undefined`.
|
|
331
|
+
//
|
|
332
|
+
// Sem ele o campo de serviço renderiza e nunca acha nada: o efeito que
|
|
333
|
+
// busca sai cedo quando não há lookup, então digitar não produz resultado
|
|
334
|
+
// nem erro. A pessoa conclui que não há serviços cadastrados — e havia.
|
|
335
|
+
//
|
|
336
|
+
// O arquétipo `service` já existe e faz exatamente esta busca; só nunca
|
|
337
|
+
// tinha sido ligado por omissão. Quem passa o próprio lookup continua
|
|
338
|
+
// mandando, porque é ele que ganha.
|
|
339
|
+
serviceLookup: options?.serviceLookup ?? createArchetypeLookup({ archetype: "service" }),
|
|
329
340
|
professionalLookup: options?.professionalLookup,
|
|
330
341
|
locationLookup: options?.locationLookup,
|
|
331
342
|
onEntityClick: options?.onEntityClick,
|
|
@@ -1241,6 +1252,11 @@ function LocationSelect({ value, onChange, locations }) {
|
|
|
1241
1252
|
)) })
|
|
1242
1253
|
] });
|
|
1243
1254
|
}
|
|
1255
|
+
function rotuloDoTipo(t2, id, fallback) {
|
|
1256
|
+
const chave = `agenda.bookingType.${id}`;
|
|
1257
|
+
const traduzido = t2(chave);
|
|
1258
|
+
return !traduzido || traduzido === chave ? fallback : traduzido;
|
|
1259
|
+
}
|
|
1244
1260
|
function AppointmentModal({ open, mode, bookingId, prefill, initialTab, externalSource, onClose, onCreated }) {
|
|
1245
1261
|
const t2 = useTranslation();
|
|
1246
1262
|
const locale = getCurrentLocale();
|
|
@@ -1265,6 +1281,8 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1265
1281
|
const [professionalId, setProfessionalId] = useState(prefill?.professionalId ?? "");
|
|
1266
1282
|
const [locationId, setLocationId] = useState(prefill?.locationId ?? "");
|
|
1267
1283
|
const [services, setServices] = useState([]);
|
|
1284
|
+
const [attendees, setAttendees] = useState([]);
|
|
1285
|
+
const [attendeeSeq, setAttendeeSeq] = useState(0);
|
|
1268
1286
|
const [serviceSearch, setServiceSearch] = useState("");
|
|
1269
1287
|
const [date, setDate] = useState(() => {
|
|
1270
1288
|
if (prefill?.startsAt) return prefill.startsAt.slice(0, 10);
|
|
@@ -1320,6 +1338,7 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1320
1338
|
setProfessionalId(prefill?.professionalId ?? "");
|
|
1321
1339
|
setLocationId(prefill?.locationId ?? "");
|
|
1322
1340
|
setServices([]);
|
|
1341
|
+
setAttendees([]);
|
|
1323
1342
|
setServiceSearch("");
|
|
1324
1343
|
setNotes("");
|
|
1325
1344
|
setStatus("scheduled");
|
|
@@ -1387,6 +1406,7 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1387
1406
|
durationMinutes: s.durationMinutes,
|
|
1388
1407
|
price: s.price
|
|
1389
1408
|
})));
|
|
1409
|
+
if (b.attendees) setAttendees(b.attendees.map((a) => ({ personId: a.personId, name: a.name })));
|
|
1390
1410
|
setEditOrderId(b.orderId ?? null);
|
|
1391
1411
|
setEditOrderTotal(b.orderTotal ?? 0);
|
|
1392
1412
|
setEditPaymentStatus(b.paymentStatus ?? "none");
|
|
@@ -1402,7 +1422,12 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1402
1422
|
notes: b.notes ?? "",
|
|
1403
1423
|
cancellationReasonId: "",
|
|
1404
1424
|
cancellationNotes: "",
|
|
1405
|
-
services: svcSnap
|
|
1425
|
+
services: svcSnap,
|
|
1426
|
+
// Sem isto, uma edição que SÓ acrescenta um convidado não conta como
|
|
1427
|
+
// alteração e o botão "Atualizar" fica desabilitado para sempre — o
|
|
1428
|
+
// mesmo defeito que os serviços tiveram e que fez a lista vazia travar
|
|
1429
|
+
// o formulário.
|
|
1430
|
+
attendees: (b.attendees ?? []).map((a) => a.personId).sort()
|
|
1406
1431
|
});
|
|
1407
1432
|
setLoading(false);
|
|
1408
1433
|
if (b.orderId && config.financialBridge) {
|
|
@@ -1523,7 +1548,8 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1523
1548
|
startsAt,
|
|
1524
1549
|
notes: notes || void 0,
|
|
1525
1550
|
title: activeType.fields.title ? title.trim() : void 0,
|
|
1526
|
-
services: services.map((s) => ({ serviceId: s.serviceId, name: s.name, durationMinutes: s.durationMinutes, price: s.price }))
|
|
1551
|
+
services: services.map((s) => ({ serviceId: s.serviceId, name: s.name, durationMinutes: s.durationMinutes, price: s.price })),
|
|
1552
|
+
attendees: activeType.fields.attendees ? attendees.map((a) => ({ personId: a.personId })) : void 0
|
|
1527
1553
|
});
|
|
1528
1554
|
invalidateLimit("bookings_month");
|
|
1529
1555
|
onClose();
|
|
@@ -1537,7 +1563,8 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1537
1563
|
notes: notes || void 0,
|
|
1538
1564
|
status,
|
|
1539
1565
|
title: activeType.fields.title ? title.trim() : void 0,
|
|
1540
|
-
services: services.map((s) => ({ serviceId: s.serviceId, name: s.name, durationMinutes: s.durationMinutes, price: s.price }))
|
|
1566
|
+
services: services.map((s) => ({ serviceId: s.serviceId, name: s.name, durationMinutes: s.durationMinutes, price: s.price })),
|
|
1567
|
+
attendees: activeType.fields.attendees ? attendees.map((a) => ({ personId: a.personId })) : void 0
|
|
1541
1568
|
});
|
|
1542
1569
|
if (status === "cancelled" && config.cancellationDetails && cancellationReasonId) {
|
|
1543
1570
|
await config.cancellationDetails.saveCancellationDetails({
|
|
@@ -1570,8 +1597,8 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1570
1597
|
const needsCancellationReason = mode === "edit" && status === "cancelled" && !!config.cancellationDetails;
|
|
1571
1598
|
const needsCancellationNotes = needsCancellationReason && !!selectedCancellationReason?.requiresNotes;
|
|
1572
1599
|
const formSnapshot = useMemo(
|
|
1573
|
-
() => JSON.stringify({ title, clientId, professionalId, locationId, date, startTime, status, notes, cancellationReasonId, cancellationNotes, services: services.map((s) => ({ id: s.serviceId, dur: s.durationMinutes, price: s.price })) }),
|
|
1574
|
-
[title, clientId, professionalId, locationId, date, startTime, status, notes, cancellationReasonId, cancellationNotes, services]
|
|
1600
|
+
() => JSON.stringify({ title, clientId, professionalId, locationId, date, startTime, status, notes, cancellationReasonId, cancellationNotes, services: services.map((s) => ({ id: s.serviceId, dur: s.durationMinutes, price: s.price })), attendees: attendees.map((a) => a.personId).sort() }),
|
|
1601
|
+
[title, clientId, professionalId, locationId, date, startTime, status, notes, cancellationReasonId, cancellationNotes, services, attendees]
|
|
1575
1602
|
);
|
|
1576
1603
|
const isDirty = mode === "create" || formSnapshot !== initialSnapshot.current;
|
|
1577
1604
|
const canSubmit = (!activeType.fields.title || title.trim()) && (!activeType.requiresClient || clientId) && (!activeType.fields.professional || professionalId) && (!activeType.requiresServices || services.length > 0) && (!needsCancellationReason || !!cancellationReasonId) && (!needsCancellationNotes || !!cancellationNotes.trim()) && !conflict && !saving;
|
|
@@ -1585,7 +1612,7 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1585
1612
|
/* @__PURE__ */ jsxs(RightRailPage, { title: railTitle, open, onClose, width: "max-w-lg", children: [
|
|
1586
1613
|
/* @__PURE__ */ jsxs("div", { className: "px-5 pt-3 pb-3 shrink-0 space-y-3", children: [
|
|
1587
1614
|
showTabs && mode === "create" ? /* @__PURE__ */ jsx("div", { className: "flex gap-1 border-b fayz-glass-divider", children: config.bookingTypes.map((bt) => {
|
|
1588
|
-
const label = t2
|
|
1615
|
+
const label = rotuloDoTipo(t2, bt.id, bt.label);
|
|
1589
1616
|
const isActive = bookingType === bt.id;
|
|
1590
1617
|
const BtIcon = BOOKING_TYPE_ICONS[bt.icon] ?? Calendar;
|
|
1591
1618
|
return /* @__PURE__ */ jsxs(
|
|
@@ -1603,7 +1630,7 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1603
1630
|
bt.id
|
|
1604
1631
|
);
|
|
1605
1632
|
}) }) : mode === "edit" && (config.clientEntityDef && clientId || config.modules.financial && editOrderId ? /* @__PURE__ */ jsx("div", { className: "flex gap-1 border-b fayz-glass-divider", children: [
|
|
1606
|
-
{ id: "appointment", label: t2
|
|
1633
|
+
{ id: "appointment", label: rotuloDoTipo(t2, bookingType, activeType.label), icon: Calendar, show: true },
|
|
1607
1634
|
{ id: "client", label: t2("agenda.appointment.clientTab"), icon: User, show: !!config.clientEntityDef && !!clientId },
|
|
1608
1635
|
{ id: "financial", label: t2("agenda.payment.title"), icon: DollarSign, show: config.modules.financial && !!editOrderId }
|
|
1609
1636
|
].filter((tab) => tab.show).map((tab) => {
|
|
@@ -1789,6 +1816,48 @@ function AppointmentModal({ open, mode, bookingId, prefill, initialTab, external
|
|
|
1789
1816
|
}
|
|
1790
1817
|
) })
|
|
1791
1818
|
] }),
|
|
1819
|
+
activeType.fields.attendees && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 py-1", children: [
|
|
1820
|
+
/* @__PURE__ */ jsx(Users, { className: "h-4 w-4 mt-1.5 text-muted-foreground shrink-0" }),
|
|
1821
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
1822
|
+
attendees.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5 mb-1.5", children: attendees.map((a) => /* @__PURE__ */ jsxs(
|
|
1823
|
+
"span",
|
|
1824
|
+
{
|
|
1825
|
+
className: "inline-flex items-center gap-1 rounded-full bg-muted/40 pl-2.5 pr-1 py-0.5 text-sm",
|
|
1826
|
+
children: [
|
|
1827
|
+
a.name,
|
|
1828
|
+
/* @__PURE__ */ jsx(
|
|
1829
|
+
"button",
|
|
1830
|
+
{
|
|
1831
|
+
type: "button",
|
|
1832
|
+
"aria-label": t2("agenda.attendees.remove"),
|
|
1833
|
+
onClick: () => setAttendees((p) => p.filter((x) => x.personId !== a.personId)),
|
|
1834
|
+
className: "rounded-full p-0.5 hover:bg-muted transition-colors",
|
|
1835
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
|
|
1836
|
+
}
|
|
1837
|
+
)
|
|
1838
|
+
]
|
|
1839
|
+
},
|
|
1840
|
+
a.personId
|
|
1841
|
+
)) }),
|
|
1842
|
+
/* @__PURE__ */ jsx(
|
|
1843
|
+
ContactPicker,
|
|
1844
|
+
{
|
|
1845
|
+
value: null,
|
|
1846
|
+
onChange: (contact) => {
|
|
1847
|
+
if (!contact?.id) return;
|
|
1848
|
+
setAttendees((p) => p.some((x) => x.personId === contact.id) ? p : [...p, { personId: contact.id, name: contact.name ?? "" }]);
|
|
1849
|
+
setAttendeeSeq((n) => n + 1);
|
|
1850
|
+
},
|
|
1851
|
+
lookup: config.attendeeLookup,
|
|
1852
|
+
createEntityDef: config.clientEntityDef,
|
|
1853
|
+
variant: "inline",
|
|
1854
|
+
placeholder: t2("agenda.attendees.add"),
|
|
1855
|
+
createLabel: t2("agenda.appointment.newClient")
|
|
1856
|
+
},
|
|
1857
|
+
attendeeSeq
|
|
1858
|
+
)
|
|
1859
|
+
] })
|
|
1860
|
+
] }),
|
|
1792
1861
|
activeType.fields.location && config.modules.locationSelection && (storeLocations.length > 0 || config.locations.length > 0) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 py-1", children: [
|
|
1793
1862
|
/* @__PURE__ */ jsx(MapPin, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
|
|
1794
1863
|
/* @__PURE__ */ jsx(
|
|
@@ -4052,6 +4121,33 @@ async function getCanonicalBookingById(core, id) {
|
|
|
4052
4121
|
return booking ?? null;
|
|
4053
4122
|
}
|
|
4054
4123
|
var bookingChangesChannelSequence = 0;
|
|
4124
|
+
async function lerConvidados(core, bookingId) {
|
|
4125
|
+
const { data, error } = await core.from("appointment_attendees").select("id, person_id, role, people(name, email, avatar_url)").eq("booking_id", bookingId).order("created_at", { ascending: true });
|
|
4126
|
+
if (error || !data) return [];
|
|
4127
|
+
return data.map((r) => ({
|
|
4128
|
+
id: r.id,
|
|
4129
|
+
personId: r.person_id,
|
|
4130
|
+
name: r.people?.name ?? "",
|
|
4131
|
+
role: r.role ?? "required",
|
|
4132
|
+
email: r.people?.email ?? null,
|
|
4133
|
+
avatarUrl: r.people?.avatar_url ?? null
|
|
4134
|
+
}));
|
|
4135
|
+
}
|
|
4136
|
+
async function sincronizarConvidados(core, bookingId, tenantId, attendees) {
|
|
4137
|
+
if (attendees === void 0) return;
|
|
4138
|
+
const { error: delErr } = await core.from("appointment_attendees").delete().eq("booking_id", bookingId);
|
|
4139
|
+
if (delErr) throw delErr;
|
|
4140
|
+
if (!attendees.length) return;
|
|
4141
|
+
const { error } = await core.from("appointment_attendees").insert(
|
|
4142
|
+
attendees.map((a) => ({
|
|
4143
|
+
tenant_id: tenantId,
|
|
4144
|
+
booking_id: bookingId,
|
|
4145
|
+
person_id: a.personId,
|
|
4146
|
+
role: a.role ?? "required"
|
|
4147
|
+
}))
|
|
4148
|
+
);
|
|
4149
|
+
if (error) throw error;
|
|
4150
|
+
}
|
|
4055
4151
|
function createSupabaseAgendaProvider(providerOptions) {
|
|
4056
4152
|
const professionalKind = providerOptions?.professionalKind ?? "staff";
|
|
4057
4153
|
return {
|
|
@@ -4101,6 +4197,7 @@ function createSupabaseAgendaProvider(providerOptions) {
|
|
|
4101
4197
|
if (itemDuration) booking.totalDurationMinutes = itemDuration;
|
|
4102
4198
|
}
|
|
4103
4199
|
}
|
|
4200
|
+
booking.attendees = await lerConvidados(core, booking.id);
|
|
4104
4201
|
return booking;
|
|
4105
4202
|
}
|
|
4106
4203
|
return getCanonicalBookingById(core, id);
|
|
@@ -4124,7 +4221,12 @@ function createSupabaseAgendaProvider(providerOptions) {
|
|
|
4124
4221
|
source: "agenda",
|
|
4125
4222
|
...serviceNames ? { serviceNames, itemsSummary: serviceNames } : {},
|
|
4126
4223
|
...contactName ? { contactName } : {},
|
|
4127
|
-
...eventTitle ? { title: eventTitle } : {}
|
|
4224
|
+
...eventTitle ? { title: eventTitle } : {},
|
|
4225
|
+
// O vínculo com o negócio, quando o compromisso nasce do funil. Só
|
|
4226
|
+
// quando existe: gravar `dealId: null` poria a chave em toda reserva
|
|
4227
|
+
// de mesa e todo horário de salão, e um campo que está em tudo e vale
|
|
4228
|
+
// para quase nada é o que faz ninguém confiar no metadata.
|
|
4229
|
+
...input.dealId ? { dealId: input.dealId } : {}
|
|
4128
4230
|
};
|
|
4129
4231
|
const { data: created, error: rpcErr } = await core.rpc("agenda_booking_create", {
|
|
4130
4232
|
p_starts_at: input.startsAt,
|
|
@@ -4147,6 +4249,11 @@ function createSupabaseAgendaProvider(providerOptions) {
|
|
|
4147
4249
|
});
|
|
4148
4250
|
if (rpcErr) throw rpcErr;
|
|
4149
4251
|
const booking = { id: created.appointment_id };
|
|
4252
|
+
try {
|
|
4253
|
+
await sincronizarConvidados(core, booking.id, tenantId, input.attendees);
|
|
4254
|
+
} catch (e) {
|
|
4255
|
+
console.error("[agenda] a reserva foi criada, os convidados n\xE3o:", e);
|
|
4256
|
+
}
|
|
4150
4257
|
const createdBooking = await this.getBookingById(booking.id);
|
|
4151
4258
|
if (!createdBooking) throw new Error("Created booking did not resolve from agenda read model");
|
|
4152
4259
|
return createdBooking;
|
|
@@ -4180,6 +4287,8 @@ function createSupabaseAgendaProvider(providerOptions) {
|
|
|
4180
4287
|
const effectiveAssigneeId = data.professionalId ?? existing?.assignee_id ?? null;
|
|
4181
4288
|
const { error } = await core.from("appointments").update(updates).eq("id", id);
|
|
4182
4289
|
if (error) throw error;
|
|
4290
|
+
const tid = getTenantId();
|
|
4291
|
+
if (tid) await sincronizarConvidados(core, id, tid, data.attendees);
|
|
4183
4292
|
const orderId = existing?.order_id;
|
|
4184
4293
|
if (orderId) {
|
|
4185
4294
|
const orderUpdates = {};
|
|
@@ -4939,6 +5048,12 @@ var en = {
|
|
|
4939
5048
|
"agenda.appointment.title": "Title",
|
|
4940
5049
|
"agenda.appointment.addTitle": "Add a title",
|
|
4941
5050
|
"agenda.appointment.untitled": "(no title)",
|
|
5051
|
+
"agenda.attendees.label": "Attendees",
|
|
5052
|
+
"agenda.attendees.add": "Add attendee",
|
|
5053
|
+
"agenda.attendees.remove": "Remove attendee",
|
|
5054
|
+
"agenda.attendees.required": "Required",
|
|
5055
|
+
"agenda.attendees.optional": "Optional",
|
|
5056
|
+
"agenda.bookingType.meeting": "Meeting",
|
|
4942
5057
|
"agenda.bookingType.appointment": "Appointment",
|
|
4943
5058
|
"agenda.bookingType.event": "Event",
|
|
4944
5059
|
"agenda.bookingType.task": "Task",
|
|
@@ -5162,6 +5277,12 @@ var ptBR = {
|
|
|
5162
5277
|
"agenda.appointment.title": "T\xEDtulo",
|
|
5163
5278
|
"agenda.appointment.addTitle": "Adicionar um t\xEDtulo",
|
|
5164
5279
|
"agenda.appointment.untitled": "(sem t\xEDtulo)",
|
|
5280
|
+
"agenda.attendees.label": "Convidados",
|
|
5281
|
+
"agenda.attendees.add": "Adicionar convidado",
|
|
5282
|
+
"agenda.attendees.remove": "Remover convidado",
|
|
5283
|
+
"agenda.attendees.required": "Obrigat\xF3rio",
|
|
5284
|
+
"agenda.attendees.optional": "Opcional",
|
|
5285
|
+
"agenda.bookingType.meeting": "Reuni\xE3o",
|
|
5165
5286
|
"agenda.bookingType.appointment": "Agendamento",
|
|
5166
5287
|
"agenda.bookingType.event": "Evento",
|
|
5167
5288
|
"agenda.bookingType.task": "Tarefa",
|