@fayz-ai/plugin-agenda 0.23.4 → 0.24.1

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":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAM/B,MAAM,SAAS,CAAA;AAubhB,MAAM,WAAW,6BAA6B;IAC5C,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AA8ED,wBAAgB,4BAA4B,CAAC,eAAe,CAAC,EAAE,6BAA6B,GAAG,kBAAkB,CAspDhH"}
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAM/B,MAAM,SAAS,CAAA;AAubhB,MAAM,WAAW,6BAA6B;IAC5C,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AA8ED,wBAAgB,4BAA4B,CAAC,eAAe,CAAC,EAAE,6BAA6B,GAAG,kBAAkB,CA6pDhH"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAInD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAoBnD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,2BAA2B,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAA;AAChG,YAAY,EACV,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,eAAe,GAChB,MAAM,yBAAyB,CAAA;AAMhC,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,cAAc,CAuehF;AAGD,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAGtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtD,YAAY,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAC5E,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAC1I,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAA;AAGlG,OAAO,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAIvK,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAInD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAoBnD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,2BAA2B,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAA;AAChG,YAAY,EACV,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,eAAe,GAChB,MAAM,yBAAyB,CAAA;AAMhC,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,cAAc,CAgfhF;AAGD,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAGtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtD,YAAY,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAC5E,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAC1I,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAA;AAGlG,OAAO,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAIvK,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { createMockAgendaProvider, createSupabasePublicBookingProvider } from '.
2
2
  export { createMockAgendaProvider } from './chunk-A77PUFY5.js';
3
3
  import React23, { useState, useEffect, useRef, useMemo, useCallback, useLayoutEffect } from 'react';
4
4
  import { tl, recordRailFields, RECORD_GROUP, activeFacet, connectionStatus, createConnectionStore, getActiveTenantId, createSafeDataProvider, todayLocal, getSupabaseClientOptional, registerTranslations, registerMessageDefaults, connectorRuntimeToken, CONNECTOR_RUNTIME_TOKEN_HEADER, getActiveUnitId, assertWrote, emitDataChanged, globalCache, usePluginRuntimeOptional, useTranslation, useActiveUnitId, emitDomainEvent, getCurrentLocale, localDateKey, useDataChanged, describeError, formatCurrency, resolveDataProvider } from '@fayz-ai/core';
5
- import { createPluginContext, fayzConnectorOAuth, UNIT_DETAIL_ZONES, setScheduleBlockConfig, getScheduleBlockConfig, registerPersonActions, PluginSettingsPanel, adminNavigateTo, createArchetypeLookup, dedup, usePluginPrefs, PersonLink, useTenantPluginSettings, SettingsGroup, ToggleRow, SelectRow, usePermissionOptional, PageActions, useRightRailStore, useFieldRules, deriveEntityKey, openEntity, ScheduleEditor, useLimitGuard, useLookupCreate, CrudFormPage, CrudDetailPage, ContactPicker, PaymentStatusBadge as PaymentStatusBadge$1, RightRailPage, invalidateLimit } from '@fayz-ai/admin';
5
+ import { createPluginContext, fayzConnectorOAuth, UNIT_DETAIL_ZONES, setScheduleBlockConfig, getScheduleBlockConfig, registerPersonActions, PluginSettingsPanel, adminNavigateTo, createArchetypeLookup, dedup, usePluginPrefs, PersonLink, useTenantPluginSettings, SettingsGroup, ToggleRow, SelectRow, usePermissionOptional, useAdminPath, PageActions, useRightRailStore, useFieldRules, deriveEntityKey, openEntity, ScheduleEditor, useLimitGuard, useLookupCreate, CrudFormPage, CrudDetailPage, ContactPicker, PaymentStatusBadge as PaymentStatusBadge$1, RightRailPage, 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';
@@ -677,6 +677,42 @@ var css = (
677
677
  text-transform: none;
678
678
  letter-spacing: 0;
679
679
  }
680
+
681
+ /* The day header fills its column, so a holiday name ellipses inside it
682
+ instead of pushing the day out. */
683
+ .agenda-calendar .fc-col-header-cell[data-date] .fc-col-header-cell-cushion {
684
+ display: block;
685
+ max-width: 100%;
686
+ overflow: hidden;
687
+ }
688
+
689
+ /* A day of the week opens that day. */
690
+ .agenda-calendar .agenda-day-link {
691
+ cursor: pointer;
692
+ border-radius: 0.5rem;
693
+ padding: 2px 4px;
694
+ transition: background-color 120ms ease-out;
695
+ }
696
+ .agenda-calendar .agenda-day-link:hover,
697
+ .agenda-calendar .agenda-day-link:focus-visible {
698
+ background: hsl(var(--foreground) / 0.07);
699
+ outline: none;
700
+ }
701
+
702
+ /* No schedule in the period: the whole grid reads as closed, in the same
703
+ hatch as time outside a schedule \u2014 a blank grid looks bookable. On the slot
704
+ rows, because with no schedule there may be no column to paint. */
705
+ .agenda-calendar.agenda-unscheduled .fc-timegrid-slots td.fc-timegrid-slot-lane {
706
+ background-color: hsl(var(--muted-foreground) / 0.2);
707
+ background-image: repeating-linear-gradient(
708
+ 45deg,
709
+ transparent,
710
+ transparent 4px,
711
+ hsl(var(--muted-foreground) / 0.12) 4px,
712
+ hsl(var(--muted-foreground) / 0.12) 8px
713
+ );
714
+ background-attachment: fixed;
715
+ }
680
716
  `
681
717
  );
682
718
  var injected = false;
@@ -695,6 +731,38 @@ function injectCalendarStyles() {
695
731
  document.head.appendChild(style);
696
732
  injected = true;
697
733
  }
734
+
735
+ // src/lib/agenda-url.ts
736
+ var VIEWS = ["day", "week", "month", "list"];
737
+ function parseAgendaPath(path) {
738
+ const parts = (path.split("?")[0] ?? "").split("/").filter(Boolean);
739
+ if (parts[0] !== "agenda") return null;
740
+ const view = parts[1];
741
+ if (!view || !VIEWS.includes(view)) return null;
742
+ if (parts.length === 2) return { view };
743
+ if (parts.length !== 5) return null;
744
+ const [y, m, d] = parts.slice(2).map(Number);
745
+ const date = new Date(y, m - 1, d);
746
+ if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) return null;
747
+ return { view, date };
748
+ }
749
+ function agendaPath(view, date) {
750
+ if (!date) return `/agenda/${view}`;
751
+ const pad = (n) => String(n).padStart(2, "0");
752
+ return `/agenda/${view}/${date.getFullYear()}/${pad(date.getMonth() + 1)}/${pad(date.getDate())}`;
753
+ }
754
+ function urlViewOf(viewType) {
755
+ if (viewType.startsWith("list")) return "list";
756
+ if (viewType.endsWith("Day")) return "day";
757
+ if (viewType.endsWith("Week")) return "week";
758
+ return "month";
759
+ }
760
+ function calendarViewFor(view, resourceCapable) {
761
+ if (view === "day") return resourceCapable ? "resourceTimeGridDay" : "timeGridDay";
762
+ if (view === "week") return resourceCapable ? "resourceTimeGridWeek" : "timeGridWeek";
763
+ if (view === "list") return resourceCapable ? "listWeek" : "listMonth";
764
+ return "dayGridMonth";
765
+ }
698
766
  var DEFAULTS = {
699
767
  startTime: "07:00",
700
768
  endTime: "21:00"
@@ -4428,7 +4496,9 @@ function CalendarView() {
4428
4496
  // Como a SEMANA se agrupa: 'day' põe o dia em cima e as pessoas dentro
4429
4497
  // dele; 'professional' inverte. 'auto' é o padrão e deixa a agenda decidir
4430
4498
  // pelo tamanho da equipe — ver `weekGrouping` mais abaixo.
4431
- weekGrouping: "auto"
4499
+ weekGrouping: "auto",
4500
+ // Which weekdays the WEEK draws: 'auto', or the shown days (0 = Sunday) — see `shownWeekDays`.
4501
+ weekDays: "auto"
4432
4502
  });
4433
4503
  const weekGroupingPref = prefs.get("weekGrouping") ?? "auto";
4434
4504
  const agendaSettings = useAgendaSettings();
@@ -4549,6 +4619,16 @@ function CalendarView() {
4549
4619
  const days2 = /* @__PURE__ */ new Set();
4550
4620
  const cursor = new Date(visibleRange.start);
4551
4621
  const end = new Date(visibleRange.end);
4622
+ if (currentView.endsWith("Week")) {
4623
+ cursor.setDate(cursor.getDate() - cursor.getDay());
4624
+ end.setTime(cursor.getTime());
4625
+ end.setDate(end.getDate() + 7);
4626
+ return {
4627
+ daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
4628
+ from: localDateKey(cursor),
4629
+ to: localDateKey(end)
4630
+ };
4631
+ }
4552
4632
  for (let i = 0; cursor < end && i < 62; i++) {
4553
4633
  days2.add(cursor.getDay());
4554
4634
  cursor.setDate(cursor.getDate() + 1);
@@ -4558,7 +4638,7 @@ function CalendarView() {
4558
4638
  from: visibleRange.start.slice(0, 10),
4559
4639
  to: visibleRange.end.slice(0, 10)
4560
4640
  };
4561
- }, [visibleRange]);
4641
+ }, [visibleRange, currentView]);
4562
4642
  const wantedSchedulesKey = useMemo(
4563
4643
  () => scheduleQuery ? "agenda:schedules:" + JSON.stringify(scheduleQuery) : null,
4564
4644
  [scheduleQuery]
@@ -4633,6 +4713,37 @@ function CalendarView() {
4633
4713
  const rows = scheduleIndex.get(profId);
4634
4714
  return !!rows && opensOnDate(rows, iso);
4635
4715
  }, [scheduleIndex]);
4716
+ const weekDaysPref = prefs.get("weekDays");
4717
+ const lastAutoWeekDays = useRef("0123456");
4718
+ const shownWeekDaysKey = useMemo(() => {
4719
+ const all = [0, 1, 2, 3, 4, 5, 6];
4720
+ if (Array.isArray(weekDaysPref)) {
4721
+ const chosen = all.filter((d) => weekDaysPref.includes(d));
4722
+ return (chosen.length > 0 ? chosen : all).join("");
4723
+ }
4724
+ const settled = currentView.endsWith("Week") && !schedulesLoading && schedulesKey === wantedSchedulesKey;
4725
+ if (!settled) return lastAutoWeekDays.current;
4726
+ if (!visibleRange || scheduleIndex.size === 0) return lastAutoWeekDays.current = all.join("");
4727
+ const sunday = new Date(visibleRange.start);
4728
+ sunday.setDate(sunday.getDate() - sunday.getDay());
4729
+ const works = (dow2) => {
4730
+ const day = new Date(sunday);
4731
+ day.setDate(day.getDate() + dow2);
4732
+ const iso = localDateKey(day);
4733
+ for (const [profId] of scheduleIndex) if (opensOn(profId, iso, dow2)) return true;
4734
+ return false;
4735
+ };
4736
+ return lastAutoWeekDays.current = all.filter((d) => d !== 0 && d !== 6 || works(d)).join("");
4737
+ }, [weekDaysPref, visibleRange, scheduleIndex, opensOn, currentView, schedulesLoading, schedulesKey, wantedSchedulesKey]);
4738
+ const shownWeekDays = useMemo(() => shownWeekDaysKey.split("").map(Number), [shownWeekDaysKey]);
4739
+ const weekViewOptions = useMemo(() => {
4740
+ const hiddenDays = [0, 1, 2, 3, 4, 5, 6].filter((d) => !shownWeekDays.includes(d));
4741
+ return { resourceTimeGridWeek: { hiddenDays }, timeGridWeek: { hiddenDays } };
4742
+ }, [shownWeekDays]);
4743
+ const toggleWeekDay = useCallback((dow2) => {
4744
+ const next = shownWeekDays.includes(dow2) ? shownWeekDays.filter((d) => d !== dow2) : [...shownWeekDays, dow2].sort();
4745
+ if (next.length > 0) prefs.set("weekDays", next);
4746
+ }, [shownWeekDays, prefs]);
4636
4747
  const relevantProfIds = useMemo(() => {
4637
4748
  const ids = /* @__PURE__ */ new Set();
4638
4749
  for (const [profId] of scheduleIndex) {
@@ -4911,13 +5022,49 @@ function CalendarView() {
4911
5022
  return [...bookingEvents, ...disponibilidade, ...blockEvents];
4912
5023
  }, [bookingEvents, availabilityEvents, blockEvents, currentView]);
4913
5024
  const storedView = prefs.get("calendarView");
4914
- const effectiveInitialView = resourceCapable ? viewForResources(storedView) : viewForNoResources(storedView);
5025
+ const adminPath = useAdminPath();
5026
+ const urlTarget = useMemo(() => parseAgendaPath(adminPath), [adminPath]);
5027
+ const effectiveInitialView = urlTarget ? calendarViewFor(urlTarget.view, resourceCapable) : resourceCapable ? viewForResources(storedView) : viewForNoResources(storedView);
4915
5028
  const handleDatesSet = useCallback((arg) => {
4916
5029
  setCalendarTitle(arg.view.title);
4917
5030
  setView(arg.view.type);
4918
5031
  setVisibleRange({ start: arg.startStr, end: arg.endStr });
4919
5032
  fetchBookings({ start: arg.startStr, end: arg.endStr });
5033
+ const here = window.location.hash.replace(/^#/, "");
5034
+ if (parseAgendaPath(here)) {
5035
+ const api = calendarRef.current?.getApi();
5036
+ const next = agendaPath(urlViewOf(arg.view.type), api?.getDate());
5037
+ if (next !== here) {
5038
+ try {
5039
+ window.history.replaceState(null, "", `#${next}`);
5040
+ } catch {
5041
+ }
5042
+ }
5043
+ }
4920
5044
  }, [fetchBookings, setView]);
5045
+ useEffect(() => {
5046
+ if (!urlTarget) return;
5047
+ const api = calendarRef.current?.getApi();
5048
+ if (!api) return;
5049
+ const view = calendarViewFor(urlTarget.view, resourceCapable);
5050
+ const sameDay = !urlTarget.date || api.getDate().toDateString() === urlTarget.date.toDateString();
5051
+ if (api.view.type === view && sameDay) return;
5052
+ api.changeView(view);
5053
+ if (urlTarget.date) {
5054
+ api.gotoDate(urlTarget.date);
5055
+ setSelectedDate(urlTarget.date);
5056
+ }
5057
+ }, [urlTarget, resourceCapable]);
5058
+ const openDay = useCallback((date) => {
5059
+ const api = calendarRef.current?.getApi();
5060
+ if (api && !parseAgendaPath(window.location.hash.replace(/^#/, ""))) {
5061
+ try {
5062
+ window.history.replaceState(null, "", `#${agendaPath(urlViewOf(api.view.type), api.getDate())}`);
5063
+ } catch {
5064
+ }
5065
+ }
5066
+ adminNavigateTo(agendaPath("day", date));
5067
+ }, []);
4921
5068
  const handleEventDidMount = useCallback((arg) => {
4922
5069
  const booking = arg.event.extendedProps?.booking;
4923
5070
  if (booking) arg.el.setAttribute("data-booking-id", booking.id);
@@ -5266,11 +5413,23 @@ function CalendarView() {
5266
5413
  const iso = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
5267
5414
  const noMes = arg.view?.type === "dayGridMonth";
5268
5415
  const feriado = noMes ? void 0 : holidayByDate.get(iso);
5269
- const wrapStyle = { display: "flex", flexDirection: "column", alignItems: "center", lineHeight: 1.15, maxWidth: "100%", minWidth: 0 };
5416
+ const wrapStyle = { display: "flex", flexDirection: "column", alignItems: "center", lineHeight: 1.15, width: "fit-content", maxWidth: "100%", minWidth: 0, margin: "0 auto", boxSizing: "border-box" };
5417
+ const dayLink = String(arg.view?.type ?? "").endsWith("Week") ? {
5418
+ role: "link",
5419
+ tabIndex: 0,
5420
+ className: "agenda-day-link",
5421
+ onClick: () => openDay(date),
5422
+ onKeyDown: (e) => {
5423
+ if (e.key === "Enter" || e.key === " ") {
5424
+ e.preventDefault();
5425
+ openDay(date);
5426
+ }
5427
+ }
5428
+ } : {};
5270
5429
  const dateStyle = { fontSize: "0.65rem", opacity: 0.75 };
5271
5430
  if (dayHeaderCompact) {
5272
5431
  const letter = date.toLocaleDateString(dateLocale, { weekday: "narrow" });
5273
- return /* @__PURE__ */ jsxs("div", { style: wrapStyle, title: feriado ? feriado.names.join(" \xB7 ") : void 0, children: [
5432
+ return /* @__PURE__ */ jsxs("div", { style: wrapStyle, title: feriado ? feriado.names.join(" \xB7 ") : void 0, ...dayLink, children: [
5274
5433
  /* @__PURE__ */ jsx("span", { style: { fontWeight: 600 }, children: letter }),
5275
5434
  /* @__PURE__ */ jsx("span", { style: dateStyle, children: date.getDate() }),
5276
5435
  feriado && /* @__PURE__ */ jsx(
@@ -5291,7 +5450,7 @@ function CalendarView() {
5291
5450
  const weekday = date.toLocaleDateString(dateLocale, { weekday: "short" });
5292
5451
  if (noMes) return /* @__PURE__ */ jsx("div", { style: wrapStyle, children: /* @__PURE__ */ jsx("span", { children: arg.text }) });
5293
5452
  const diaMes = date.toLocaleDateString(dateLocale, { day: "numeric", month: "numeric" });
5294
- return /* @__PURE__ */ jsxs("div", { style: wrapStyle, children: [
5453
+ return /* @__PURE__ */ jsxs("div", { style: wrapStyle, ...dayLink, children: [
5295
5454
  /* @__PURE__ */ jsx("span", { children: weekday }),
5296
5455
  /* @__PURE__ */ jsx("span", { style: dateStyle, children: diaMes }),
5297
5456
  feriado && /* @__PURE__ */ jsxs(
@@ -5316,7 +5475,7 @@ function CalendarView() {
5316
5475
  }
5317
5476
  )
5318
5477
  ] });
5319
- }, [dayHeaderCompact, currentLocale, holidayByDate]);
5478
+ }, [dayHeaderCompact, currentLocale, holidayByDate, openDay]);
5320
5479
  const dayCellContent = useCallback((arg) => {
5321
5480
  const date = arg.date;
5322
5481
  const pad = (n) => String(n).padStart(2, "0");
@@ -5524,6 +5683,43 @@ function CalendarView() {
5524
5683
  }
5525
5684
  )
5526
5685
  },
5686
+ {
5687
+ id: "week-days",
5688
+ title: "Dias da semana",
5689
+ // A choice away from the automatic one is something in force.
5690
+ count: Array.isArray(weekDaysPref) ? 1 : 0,
5691
+ hidden: !currentView.endsWith("Week") || currentView.startsWith("list"),
5692
+ defaultOpen: true,
5693
+ content: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
5694
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", role: "group", "aria-label": "Dias que a semana mostra", children: [1, 2, 3, 4, 5, 6, 0].map((dow2) => {
5695
+ const on = shownWeekDays.includes(dow2);
5696
+ const name = new Date(2024, 0, 7 + dow2).toLocaleDateString(currentLocale === "pt-BR" ? "pt-BR" : "en", { weekday: "long" });
5697
+ return /* @__PURE__ */ jsx(
5698
+ "button",
5699
+ {
5700
+ type: "button",
5701
+ "aria-pressed": on,
5702
+ title: name,
5703
+ "aria-label": name,
5704
+ "data-testid": `week-day-${dow2}`,
5705
+ onClick: () => toggleWeekDay(dow2),
5706
+ className: `flex h-7 w-7 items-center justify-center rounded-full text-xs font-medium uppercase transition-colors ${on ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"}`,
5707
+ children: name.charAt(0)
5708
+ },
5709
+ dow2
5710
+ );
5711
+ }) }),
5712
+ Array.isArray(weekDaysPref) && /* @__PURE__ */ jsx(
5713
+ "button",
5714
+ {
5715
+ type: "button",
5716
+ onClick: () => prefs.set("weekDays", "auto"),
5717
+ className: "text-xs text-muted-foreground underline-offset-2 hover:text-foreground hover:underline",
5718
+ children: "Voltar ao autom\xE1tico"
5719
+ }
5720
+ )
5721
+ ] })
5722
+ },
5527
5723
  {
5528
5724
  id: "hide-empty",
5529
5725
  title: t2("agenda.sidebar.hideEmptyGrids"),
@@ -5665,13 +5861,15 @@ function CalendarView() {
5665
5861
  }
5666
5862
  )
5667
5863
  ] }),
5668
- /* @__PURE__ */ jsx("div", { ref: wrapperRef, className: "min-h-0 min-w-0 flex-1 overflow-x-auto overflow-y-hidden agenda-calendar", children: /* @__PURE__ */ jsx("div", { className: "h-full", style: gridMinWidth ? { minWidth: gridMinWidth } : void 0, children: /* @__PURE__ */ jsx(
5864
+ /* @__PURE__ */ jsx("div", { ref: wrapperRef, className: `min-h-0 min-w-0 flex-1 overflow-x-auto overflow-y-hidden agenda-calendar${semGradeNoPeriodo ? " agenda-unscheduled" : ""}`, children: /* @__PURE__ */ jsx("div", { className: "h-full", style: gridMinWidth ? { minWidth: gridMinWidth } : void 0, children: /* @__PURE__ */ jsx(
5669
5865
  FullCalendar,
5670
5866
  {
5671
5867
  ref: calendarRef,
5672
5868
  plugins: [dayGridPlugin, timeGridPlugin, resourceTimeGridPlugin, interactionPlugin, listPlugin],
5673
5869
  initialView: mobileGridActive ? mobileView : effectiveInitialView,
5870
+ initialDate: urlTarget?.date,
5674
5871
  schedulerLicenseKey: "CC-Attribution-NonCommercial-NoDerivatives",
5872
+ views: weekViewOptions,
5675
5873
  resources: resourceCapable ? columnsSettled ? resources : [] : void 0,
5676
5874
  events,
5677
5875
  headerToolbar: false,
@@ -7678,7 +7876,7 @@ function createSupabaseAgendaProvider(providerOptions) {
7678
7876
  return { busyStarts, closedDates: Array.from(new Set(closedDates)) };
7679
7877
  },
7680
7878
  async updateBooking(id, data) {
7681
- const { core } = getClients();
7879
+ const { core, pub } = getClients();
7682
7880
  const { data: existing, error: existingErr } = await core.from("appointments").select("id, order_id, starts_at, assignee_id, unit_id, metadata").eq("id", id).single();
7683
7881
  if (existingErr) throw existingErr;
7684
7882
  const updates = {};
@@ -7746,6 +7944,10 @@ function createSupabaseAgendaProvider(providerOptions) {
7746
7944
  const { error: itemErr } = await core.from("items").insert(items);
7747
7945
  if (itemErr) throw itemErr;
7748
7946
  }
7947
+ try {
7948
+ await pub.rpc("order_reconcile_receivable", { p_order_id: orderId });
7949
+ } catch {
7950
+ }
7749
7951
  }
7750
7952
  } else if (data.services) {
7751
7953
  const tenantId = getTenantId();
@@ -22532,6 +22734,15 @@ function createAgendaPlugin(options) {
22532
22734
  }
22533
22735
  ],
22534
22736
  routes: [
22737
+ // The calendar's own links (/agenda/day/2026/10/15). Same screen and,
22738
+ // with the wildcard stripped, the same page key as /agenda — so moving
22739
+ // between a week and a day never remounts it.
22740
+ {
22741
+ path: "/agenda/*",
22742
+ component: PageComponent,
22743
+ fullBleed: true,
22744
+ permission: { feature: "agenda", action: "read" }
22745
+ },
22535
22746
  {
22536
22747
  path: "/agenda",
22537
22748
  component: PageComponent,