@agent-native/core 0.154.5 → 0.157.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/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/account-health/SKILL.md +76 -0
- package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +3 -0
- package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +2 -1
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +6 -5
- package/corpus/templates/analytics/AGENTS.md +3 -0
- package/corpus/templates/analytics/actions/account-deep-dive.ts +3 -2
- package/corpus/templates/analytics/actions/bigquery.ts +1 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -1
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyCombobox.tsx +12 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyValueCombobox.tsx +5 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer/property-label.ts +32 -0
- package/corpus/templates/analytics/changelog/2026-08-13-account-health-readouts-verify-customer-scope-and-contract-metrics.md +7 -0
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +43 -17
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +17 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
- package/corpus/templates/assets/app/i18n-data.ts +21 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +17 -13
- package/corpus/templates/calendar/AGENTS.md +2 -0
- package/corpus/templates/calendar/DEVELOPING.md +4 -4
- package/corpus/templates/calendar/actions/get-settings.ts +4 -11
- package/corpus/templates/calendar/actions/update-availability.ts +15 -4
- package/corpus/templates/calendar/actions/update-settings.ts +15 -4
- package/corpus/templates/calendar/app/components/booking/DatePicker.tsx +9 -3
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +21 -19
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +9 -6
- package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +25 -3
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +10 -3
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +9 -9
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -3
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +10 -4
- package/corpus/templates/calendar/app/i18n-data.ts +30 -0
- package/corpus/templates/calendar/app/lib/availability-schedule.ts +53 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +5 -0
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +90 -28
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +135 -61
- package/corpus/templates/calendar/app/pages/BookingPage.tsx +2 -0
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +30 -15
- package/corpus/templates/calendar/app/pages/Settings.tsx +60 -1
- package/corpus/templates/calendar/changelog/2026-08-13-find-a-time-now-closes-from-a-clear-header-action.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +2 -1
- package/corpus/templates/calendar/server/handlers/settings.ts +12 -16
- package/corpus/templates/calendar/shared/api.ts +1 -0
- package/corpus/templates/calendar/shared/availability-schedule.ts +64 -0
- package/corpus/templates/calendar/shared/calendar-week.ts +21 -0
- package/corpus/templates/calendar/shared/settings.ts +44 -0
- package/corpus/templates/clips/AGENTS.md +2 -0
- package/corpus/templates/clips/actions/add-comment.ts +5 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +31 -1
- package/corpus/templates/clips/actions/get-recording-player-data.ts +9 -0
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +21 -1
- package/corpus/templates/clips/actions/reply-to-comment.ts +5 -2
- package/corpus/templates/clips/actions/update-comment.ts +9 -2
- package/corpus/templates/clips/app/components/library/search-bar.tsx +26 -13
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +135 -3
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +5 -99
- package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +7 -3
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +102 -59
- package/corpus/templates/clips/app/components/player/video-player.tsx +84 -24
- package/corpus/templates/clips/app/components/workspace/notifications-list.tsx +11 -3
- package/corpus/templates/clips/app/i18n/en-US.ts +12 -0
- package/corpus/templates/clips/app/lib/public-meeting.ts +11 -3
- package/corpus/templates/clips/app/lib/search-focus.ts +15 -0
- package/corpus/templates/clips/app/root.tsx +2 -1
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +94 -26
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +24 -7
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +8 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +29 -8
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +24 -6
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +72 -26
- package/corpus/templates/clips/changelog/2026-08-13-inline-markdown-comments.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-13-private-meeting-agent-links.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +116 -19
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +13 -29
- package/corpus/templates/clips/desktop/src/lib/recording-request.ts +39 -0
- package/corpus/templates/clips/desktop/src/lib/settings-navigation.ts +11 -0
- package/corpus/templates/clips/desktop/src/lib/whisper-model-picker.ts +7 -0
- package/corpus/templates/clips/desktop/src/styles.css +117 -0
- package/corpus/templates/clips/server/db/index.ts +10 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/recordings.ts +3 -1
- package/corpus/templates/clips/server/lib/seekable-media-state.ts +90 -0
- package/corpus/templates/clips/server/plugins/db.ts +5 -0
- package/corpus/templates/clips/server/routes/api/public-meeting.get.ts +37 -4
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +16 -5
- package/corpus/templates/clips/shared/clips-ai-prefs.ts +3 -0
- package/corpus/templates/clips/shared/meeting-agent-access.ts +5 -0
- package/corpus/templates/content/actions/add-comment.ts +2 -1
- package/corpus/templates/content/actions/update-comment.ts +1 -1
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +24 -15
- package/corpus/templates/design/actions/generate-design.ts +10 -7
- package/corpus/templates/design/actions/present-design-variants.ts +35 -6
- package/corpus/templates/design/actions/run-design-audit.ts +33 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-audit-now-catches-a-screen-that-renders-behind-an.md +6 -0
- package/corpus/templates/design/shared/design-review.ts +1 -0
- package/corpus/templates/design/shared/html-integrity.ts +66 -0
- package/corpus/templates/dispatch/.env.example +5 -0
- package/corpus/templates/dispatch/AGENTS.md +24 -19
- package/corpus/templates/dispatch/app/i18n-data.ts +20 -0
- package/corpus/templates/dispatch/server/lib/identity-sso.ts +21 -90
- package/corpus/templates/dispatch/server/plugins/identity-sso.ts +3 -12
- package/corpus/templates/dispatch/shared/feature-flags.ts +4 -0
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +23 -0
- package/corpus/templates/factory/actions/view-screen.ts +17 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +239 -0
- package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +2 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +130 -7
- package/corpus/templates/factory/app/i18n/en-US.ts +20 -0
- package/corpus/templates/factory/app/routes/factory.tsx +41 -0
- package/corpus/templates/factory/package.json +1 -0
- package/corpus/templates/factory/server/factory-graph/contracts.ts +2 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -0
- package/corpus/templates/factory/server/plugins/dispatch-db.ts +1 -0
- package/corpus/templates/factory/server/plugins/setup-dispatch.ts +3 -0
- package/corpus/templates/mail/app/lib/native-mcp-exclusions.ts +3 -0
- package/corpus/templates/mail/vite.config.ts +7 -0
- package/corpus/templates/plan/actions/reply-to-plan-comment.ts +7 -2
- package/corpus/templates/plan/actions/resolve-plan-comment.ts +2 -2
- package/corpus/templates/plan/actions/update-visual-plan.ts +1 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +29 -20
- package/corpus/templates/slides/actions/add-slide-comment.ts +1 -1
- package/corpus/templates/slides/actions/update-slide-comment.ts +1 -1
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +9 -6
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +98 -29
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +45 -91
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +94 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +17 -29
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +42 -2
- package/corpus/templates/slides/app/global.css +7 -40
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +130 -45
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/production-agent.d.ts +30 -0
- package/dist/agent/production-agent.js +105 -9
- package/dist/agent/thread-data-builder.js +17 -1
- package/dist/agent/types.d.ts +9 -0
- package/dist/cli/skills-content/help.js +6 -4
- package/dist/cli/skills.js +17 -2
- package/dist/cli/workspacify.d.ts +5 -0
- package/dist/cli/workspacify.js +65 -8
- package/dist/client/AgentPanel.d.ts +5 -0
- package/dist/client/AgentPanel.js +32 -13
- package/dist/client/AssistantChat.d.ts +36 -1
- package/dist/client/AssistantChat.js +175 -110
- package/dist/client/MultiTabAssistantChat.js +44 -27
- package/dist/client/active-run-state.d.ts +14 -1
- package/dist/client/active-run-state.js +0 -0
- package/dist/client/agent-chat-adapter.js +107 -5
- package/dist/client/analytics.js +9 -2
- package/dist/client/chat/markdown-renderer.js +4 -2
- package/dist/client/chat/message-components.d.ts +2 -2
- package/dist/client/chat/message-components.js +69 -35
- package/dist/client/chat/run-recovery.d.ts +4 -1
- package/dist/client/chat/run-recovery.js +62 -30
- package/dist/client/chat/tool-call-display.d.ts +12 -3
- package/dist/client/chat/tool-call-display.js +79 -40
- package/dist/client/chat/widgets/DataChartRenderer.js +3 -1
- package/dist/client/chat/widgets/DataChartWidget.js +8 -2
- package/dist/client/chat/widgets/DataInsightsWidget.js +3 -1
- package/dist/client/chat/widgets/DataTableWidget.js +23 -9
- package/dist/client/chat/widgets/builtin-tool-renderers.js +3 -1
- package/dist/client/chat-first/apps-rail.js +9 -4
- package/dist/client/chat-first/primary-nav.d.ts +2 -1
- package/dist/client/chat-first/primary-nav.js +3 -3
- package/dist/client/chat-first/types.d.ts +5 -1
- package/dist/client/components/ui/message-scroller.d.ts +1 -1
- package/dist/client/components/ui/message-scroller.js +7 -3
- package/dist/client/composer/runtime-adapters.js +3 -2
- package/dist/client/context-xray/ContextMeter.js +5 -1
- package/dist/client/context-xray/ContextXRayPanel.js +5 -5
- package/dist/client/error-format.d.ts +4 -0
- package/dist/client/error-format.js +93 -5
- package/dist/client/i18n.js +83 -17
- package/dist/client/markdown/InlineMarkdown.d.ts +23 -0
- package/dist/client/markdown/InlineMarkdown.js +65 -0
- package/dist/client/markdown/index.d.ts +1 -0
- package/dist/client/markdown/index.js +1 -0
- package/dist/client/observability/ThumbsFeedback.js +10 -8
- package/dist/client/review/ReviewThreadPanel.js +2 -1
- package/dist/client/run-stream-ownership.d.ts +39 -0
- package/dist/client/run-stream-ownership.js +65 -0
- package/dist/client/sharing/ShareButton.js +160 -54
- package/dist/coding-tools/run-code.js +2 -1
- package/dist/coding-tools/sandbox/background.d.ts +1 -0
- package/dist/coding-tools/sandbox/background.js +8 -1
- package/dist/coding-tools/sandbox/executions-store.d.ts +2 -0
- package/dist/coding-tools/sandbox/executions-store.js +41 -3
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/store.d.ts +10 -0
- package/dist/feature-flags/store.js +112 -1
- package/dist/guards/no-env-credentials.js +4 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/integrations/adapters/slack.js +5 -1
- package/dist/localization/core-messages/ar-SA.d.ts +3 -0
- package/dist/localization/core-messages/ar-SA.js +541 -0
- package/dist/localization/core-messages/de-DE.d.ts +3 -0
- package/dist/localization/core-messages/de-DE.js +513 -0
- package/dist/localization/core-messages/en-US.d.ts +513 -0
- package/dist/localization/core-messages/en-US.js +513 -0
- package/dist/localization/core-messages/es-ES.d.ts +3 -0
- package/dist/localization/core-messages/es-ES.js +520 -0
- package/dist/localization/core-messages/fr-FR.d.ts +3 -0
- package/dist/localization/core-messages/fr-FR.js +520 -0
- package/dist/localization/core-messages/hi-IN.d.ts +3 -0
- package/dist/localization/core-messages/hi-IN.js +513 -0
- package/dist/localization/core-messages/ja-JP.d.ts +3 -0
- package/dist/localization/core-messages/ja-JP.js +506 -0
- package/dist/localization/core-messages/ko-KR.d.ts +3 -0
- package/dist/localization/core-messages/ko-KR.js +506 -0
- package/dist/localization/core-messages/pt-BR.d.ts +3 -0
- package/dist/localization/core-messages/pt-BR.js +520 -0
- package/dist/localization/core-messages/zh-CN.d.ts +3 -0
- package/dist/localization/core-messages/zh-CN.js +506 -0
- package/dist/localization/core-messages/zh-TW.d.ts +3 -0
- package/dist/localization/core-messages/zh-TW.js +506 -0
- package/dist/localization/core-messages.d.ts +524 -0
- package/dist/localization/core-messages.js +124 -0
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.js +3 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +2 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/resources/agents.js +40 -5
- package/dist/resources/metadata.d.ts +10 -0
- package/dist/resources/metadata.js +7 -3
- package/dist/review/actions/create-review-comment.js +1 -1
- package/dist/review/actions/reply-review-comment.js +1 -1
- package/dist/review/actions/resolve-review-thread.js +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-routes.js +32 -6
- package/dist/server/agent-chat/plugin-options.d.ts +7 -2
- package/dist/server/agent-chat-plugin.d.ts +10 -0
- package/dist/server/agent-chat-plugin.js +144 -41
- package/dist/server/agent-discovery.js +14 -3
- package/dist/server/agent-run-context.d.ts +7 -1
- package/dist/server/agent-run-context.js +9 -2
- package/dist/server/agent-teams-run-queue.d.ts +3 -0
- package/dist/server/agent-teams.js +38 -9
- package/dist/server/core-routes-plugin.js +1 -1
- package/dist/server/identity-sso-migrations.d.ts +7 -0
- package/dist/server/identity-sso-migrations.js +36 -0
- package/dist/server/identity-sso-store.d.ts +3 -2
- package/dist/server/identity-sso-store.js +8 -3
- package/dist/server/index.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +4 -0
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.js +15 -0
- package/dist/tracking/providers.js +13 -3
- package/dist/workspace-files/tool.js +1 -1
- package/docs/content/agent-surfaces.mdx +30 -0
- package/package.json +3 -2
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
CustomField,
|
|
15
15
|
DaySchedule,
|
|
16
16
|
} from "@shared/api";
|
|
17
|
+
import { getWeekdayOrder, getWeekStartsOn } from "@shared/calendar-week";
|
|
17
18
|
import {
|
|
18
19
|
IconBrandGoogle,
|
|
19
20
|
IconBrandZoom,
|
|
@@ -113,7 +114,16 @@ import {
|
|
|
113
114
|
OPTIMISTIC_PREFIX,
|
|
114
115
|
} from "@/hooks/use-booking-links";
|
|
115
116
|
import { useGoogleAuthStatus } from "@/hooks/use-google-auth";
|
|
117
|
+
import { useSettings } from "@/hooks/use-settings";
|
|
116
118
|
import { useZoomStatus, useConnectZoom } from "@/hooks/use-zoom-auth";
|
|
119
|
+
import {
|
|
120
|
+
DEFAULT_TIME_SLOT,
|
|
121
|
+
addTimeSlot,
|
|
122
|
+
getEditableTimeSlots,
|
|
123
|
+
removeTimeSlot,
|
|
124
|
+
setDayEnabled,
|
|
125
|
+
updateTimeSlot,
|
|
126
|
+
} from "@/lib/availability-schedule";
|
|
117
127
|
import { copyTextToClipboard } from "@/lib/clipboard";
|
|
118
128
|
import { cn } from "@/lib/utils";
|
|
119
129
|
|
|
@@ -175,7 +185,7 @@ const DAYS: { key: DayName }[] = [
|
|
|
175
185
|
|
|
176
186
|
const DEFAULT_SCHEDULE: DaySchedule = {
|
|
177
187
|
enabled: false,
|
|
178
|
-
slots: [{
|
|
188
|
+
slots: [{ ...DEFAULT_TIME_SLOT }],
|
|
179
189
|
};
|
|
180
190
|
|
|
181
191
|
type Tab = "links" | "availability" | "bookings";
|
|
@@ -290,11 +300,12 @@ function formatAvailabilitySummary(
|
|
|
290
300
|
dayLabel = enabledDays.map((d) => shortNames[d]).join(", ");
|
|
291
301
|
}
|
|
292
302
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (!slot) return dayLabel;
|
|
303
|
+
const slots = ws[enabledDays[0]].slots;
|
|
304
|
+
if (slots.length === 0) return dayLabel;
|
|
296
305
|
|
|
297
|
-
return `${dayLabel}, ${
|
|
306
|
+
return `${dayLabel}, ${slots
|
|
307
|
+
.map((slot) => `${formatTime12(slot.start)} - ${formatTime12(slot.end)}`)
|
|
308
|
+
.join(", ")}`;
|
|
298
309
|
}
|
|
299
310
|
|
|
300
311
|
function BookingLinksListSkeleton() {
|
|
@@ -697,17 +708,36 @@ export default function BookingLinksPage({
|
|
|
697
708
|
function updateDay(day: DayName, updates: Partial<DaySchedule>) {
|
|
698
709
|
setSchedule((prev) => ({
|
|
699
710
|
...prev,
|
|
700
|
-
[day]:
|
|
711
|
+
[day]:
|
|
712
|
+
typeof updates.enabled === "boolean"
|
|
713
|
+
? setDayEnabled(prev[day], updates.enabled)
|
|
714
|
+
: { ...prev[day], ...updates },
|
|
701
715
|
}));
|
|
702
716
|
}
|
|
703
717
|
|
|
704
|
-
function updateDaySlot(
|
|
718
|
+
function updateDaySlot(
|
|
719
|
+
day: DayName,
|
|
720
|
+
slotIndex: number,
|
|
721
|
+
field: "start" | "end",
|
|
722
|
+
value: string,
|
|
723
|
+
) {
|
|
705
724
|
setSchedule((prev) => ({
|
|
706
725
|
...prev,
|
|
707
|
-
[day]:
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
726
|
+
[day]: updateTimeSlot(prev[day], slotIndex, field, value),
|
|
727
|
+
}));
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
function addDaySlot(day: DayName) {
|
|
731
|
+
setSchedule((prev) => ({
|
|
732
|
+
...prev,
|
|
733
|
+
[day]: addTimeSlot(prev[day]),
|
|
734
|
+
}));
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
function removeDaySlot(day: DayName, slotIndex: number) {
|
|
738
|
+
setSchedule((prev) => ({
|
|
739
|
+
...prev,
|
|
740
|
+
[day]: removeTimeSlot(prev[day], slotIndex),
|
|
711
741
|
}));
|
|
712
742
|
}
|
|
713
743
|
|
|
@@ -1756,7 +1786,7 @@ export default function BookingLinksPage({
|
|
|
1756
1786
|
</div>
|
|
1757
1787
|
{DAYS.map(({ key }) => {
|
|
1758
1788
|
const day = schedule[key];
|
|
1759
|
-
const
|
|
1789
|
+
const slots = getEditableTimeSlots(day);
|
|
1760
1790
|
const label = t(`bookingLinks.days.${key}`);
|
|
1761
1791
|
const short = t(`bookingLinks.days.${key}Short`);
|
|
1762
1792
|
return (
|
|
@@ -1778,26 +1808,65 @@ export default function BookingLinksPage({
|
|
|
1778
1808
|
</div>
|
|
1779
1809
|
|
|
1780
1810
|
{day.enabled ? (
|
|
1781
|
-
<div className="flex
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1811
|
+
<div className="min-w-0 flex-1 space-y-2">
|
|
1812
|
+
{slots.map((slot, slotIndex) => (
|
|
1813
|
+
<div
|
|
1814
|
+
key={`${key}-${slotIndex}`}
|
|
1815
|
+
className="flex flex-wrap items-center gap-2"
|
|
1816
|
+
>
|
|
1817
|
+
<Input
|
|
1818
|
+
type="time"
|
|
1819
|
+
value={slot.start}
|
|
1820
|
+
onChange={(e) =>
|
|
1821
|
+
updateDaySlot(
|
|
1822
|
+
key,
|
|
1823
|
+
slotIndex,
|
|
1824
|
+
"start",
|
|
1825
|
+
e.target.value,
|
|
1826
|
+
)
|
|
1827
|
+
}
|
|
1828
|
+
className="w-28 sm:w-32"
|
|
1829
|
+
/>
|
|
1830
|
+
<span className="text-muted-foreground">
|
|
1831
|
+
{t("bookingLinks.to")}
|
|
1832
|
+
</span>
|
|
1833
|
+
<Input
|
|
1834
|
+
type="time"
|
|
1835
|
+
value={slot.end}
|
|
1836
|
+
onChange={(e) =>
|
|
1837
|
+
updateDaySlot(
|
|
1838
|
+
key,
|
|
1839
|
+
slotIndex,
|
|
1840
|
+
"end",
|
|
1841
|
+
e.target.value,
|
|
1842
|
+
)
|
|
1843
|
+
}
|
|
1844
|
+
className="w-28 sm:w-32"
|
|
1845
|
+
/>
|
|
1846
|
+
{slots.length > 1 && (
|
|
1847
|
+
<Button
|
|
1848
|
+
type="button"
|
|
1849
|
+
variant="ghost"
|
|
1850
|
+
size="sm"
|
|
1851
|
+
className="h-8 px-2 text-muted-foreground hover:text-destructive"
|
|
1852
|
+
onClick={() => removeDaySlot(key, slotIndex)}
|
|
1853
|
+
>
|
|
1854
|
+
<IconTrash className="mr-1.5 h-3.5 w-3.5" />
|
|
1855
|
+
{t("eventForm.delete")}
|
|
1856
|
+
</Button>
|
|
1857
|
+
)}
|
|
1858
|
+
</div>
|
|
1859
|
+
))}
|
|
1860
|
+
<Button
|
|
1861
|
+
type="button"
|
|
1862
|
+
variant="ghost"
|
|
1863
|
+
size="sm"
|
|
1864
|
+
className="h-8 px-2"
|
|
1865
|
+
onClick={() => addDaySlot(key)}
|
|
1866
|
+
>
|
|
1867
|
+
<IconPlus className="mr-1.5 h-3.5 w-3.5" />
|
|
1868
|
+
{t("bookingLinks.add")}
|
|
1869
|
+
</Button>
|
|
1801
1870
|
</div>
|
|
1802
1871
|
) : (
|
|
1803
1872
|
<span className="text-sm text-muted-foreground">
|
|
@@ -1971,6 +2040,8 @@ function BookingPreview({
|
|
|
1971
2040
|
onCollapse?: () => void;
|
|
1972
2041
|
}) {
|
|
1973
2042
|
const t = useT();
|
|
2043
|
+
const { data: settings } = useSettings();
|
|
2044
|
+
const weekStartsOn = getWeekStartsOn(settings?.weekStart);
|
|
1974
2045
|
const displayTitle = title.trim() || t("bookingLinks.untitledMeeting");
|
|
1975
2046
|
const hasDurationChoice = durations.length > 1;
|
|
1976
2047
|
const primaryDuration = durations[0] ?? 30;
|
|
@@ -2005,8 +2076,8 @@ function BookingPreview({
|
|
|
2005
2076
|
// Calendar data for viewed month
|
|
2006
2077
|
const monthStart = startOfMonth(viewMonth);
|
|
2007
2078
|
const monthEnd = endOfMonth(viewMonth);
|
|
2008
|
-
const calStart = startOfWeek(monthStart);
|
|
2009
|
-
const calEnd = endOfWeek(monthEnd);
|
|
2079
|
+
const calStart = startOfWeek(monthStart, { weekStartsOn });
|
|
2080
|
+
const calEnd = endOfWeek(monthEnd, { weekStartsOn });
|
|
2010
2081
|
const calDays = eachDayOfInterval({ start: calStart, end: calEnd });
|
|
2011
2082
|
|
|
2012
2083
|
function isDayDisabled(day: Date) {
|
|
@@ -2027,28 +2098,28 @@ function BookingPreview({
|
|
|
2027
2098
|
const dayName = DAY_MAP[getDay(selectedDate)];
|
|
2028
2099
|
const daySchedule = availability.weeklySchedule[dayName];
|
|
2029
2100
|
if (!daySchedule?.enabled) return [];
|
|
2030
|
-
const slot = daySchedule.slots[0];
|
|
2031
|
-
if (!slot) return [];
|
|
2032
2101
|
|
|
2033
2102
|
const dur = selectedDuration ?? primaryDuration;
|
|
2034
|
-
const [startH, startM] = slot.start.split(":").map(Number);
|
|
2035
|
-
const [endH, endM] = slot.end.split(":").map(Number);
|
|
2036
|
-
const startMin = startH * 60 + startM;
|
|
2037
|
-
const endMin = endH * 60 + endM;
|
|
2038
2103
|
const slots: string[] = [];
|
|
2039
|
-
const
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2104
|
+
for (const slot of daySchedule.slots) {
|
|
2105
|
+
const [startH, startM] = slot.start.split(":").map(Number);
|
|
2106
|
+
const [endH, endM] = slot.end.split(":").map(Number);
|
|
2107
|
+
const startMin = startH * 60 + startM;
|
|
2108
|
+
const endMin = endH * 60 + endM;
|
|
2109
|
+
const firstStart =
|
|
2110
|
+
Math.ceil(startMin / BOOKING_SLOT_STEP_MINUTES) *
|
|
2111
|
+
BOOKING_SLOT_STEP_MINUTES;
|
|
2112
|
+
for (
|
|
2113
|
+
let m = firstStart;
|
|
2114
|
+
m + dur <= endMin;
|
|
2115
|
+
m += BOOKING_SLOT_STEP_MINUTES
|
|
2116
|
+
) {
|
|
2117
|
+
const h = Math.floor(m / 60);
|
|
2118
|
+
const mm = m % 60;
|
|
2119
|
+
const ampm = h >= 12 ? "PM" : "AM";
|
|
2120
|
+
const h12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
2121
|
+
slots.push(`${h12}:${mm.toString().padStart(2, "0")} ${ampm}`);
|
|
2122
|
+
}
|
|
2052
2123
|
}
|
|
2053
2124
|
return slots;
|
|
2054
2125
|
}, [selectedDate, selectedDuration, primaryDuration, availability]);
|
|
@@ -2307,14 +2378,17 @@ function BookingPreview({
|
|
|
2307
2378
|
|
|
2308
2379
|
{/* Weekday headers */}
|
|
2309
2380
|
<div className="grid grid-cols-7 mb-0.5">
|
|
2310
|
-
{
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2381
|
+
{getWeekdayOrder(weekStartsOn).map((day) => {
|
|
2382
|
+
const dayKey = WEEKDAY_HEADER_KEYS[day];
|
|
2383
|
+
return (
|
|
2384
|
+
<div
|
|
2385
|
+
key={dayKey}
|
|
2386
|
+
className="py-0.5 text-center text-[10px] font-medium text-muted-foreground/60"
|
|
2387
|
+
>
|
|
2388
|
+
{t(`bookingLinks.days.${dayKey}`)}
|
|
2389
|
+
</div>
|
|
2390
|
+
);
|
|
2391
|
+
})}
|
|
2318
2392
|
</div>
|
|
2319
2393
|
|
|
2320
2394
|
{/* Days grid */}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
StarfieldBackground,
|
|
6
6
|
} from "@agent-native/core/client/ui";
|
|
7
7
|
import type { Booking } from "@shared/api";
|
|
8
|
+
import { getWeekStartsOn } from "@shared/calendar-week";
|
|
8
9
|
import { IconAlertTriangle, IconCalendar } from "@tabler/icons-react";
|
|
9
10
|
import {
|
|
10
11
|
addMinutes,
|
|
@@ -432,6 +433,7 @@ export default function BookingPage() {
|
|
|
432
433
|
availabilityLoading={availableDatesLoading}
|
|
433
434
|
viewMonth={viewMonth}
|
|
434
435
|
onViewMonthChange={setViewMonth}
|
|
436
|
+
weekStartsOn={getWeekStartsOn(settings?.weekStart)}
|
|
435
437
|
/>
|
|
436
438
|
</div>
|
|
437
439
|
)}
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
CalendarEventDraft,
|
|
7
7
|
UpdateEventScope,
|
|
8
8
|
} from "@shared/api";
|
|
9
|
+
import { getWeekStartsOn } from "@shared/calendar-week";
|
|
9
10
|
import {
|
|
10
11
|
IconCheck,
|
|
11
12
|
IconChevronLeft,
|
|
@@ -89,8 +90,8 @@ import {
|
|
|
89
90
|
buildEventTitleUpdate,
|
|
90
91
|
dateTimeInTimezoneToIso,
|
|
91
92
|
getEditableEventTitle,
|
|
92
|
-
getLocalTimezone,
|
|
93
93
|
UNNAMED_EVENT_TITLE,
|
|
94
|
+
resolveEventTimezone,
|
|
94
95
|
} from "@/lib/event-form-utils";
|
|
95
96
|
import { buildDeleteEventMutationInput } from "@/lib/event-mutation-inputs";
|
|
96
97
|
import { getLocationSuggestions } from "@/lib/location-suggestions";
|
|
@@ -373,6 +374,7 @@ export default function CalendarView() {
|
|
|
373
374
|
const defaultAccountEmail = googleStatus.data?.accounts?.[0]?.email;
|
|
374
375
|
const settingsQuery = useSettings();
|
|
375
376
|
const { data: settings } = settingsQuery;
|
|
377
|
+
const weekStartsOn = getWeekStartsOn(settings?.weekStart);
|
|
376
378
|
const { data: rawOverlayPeople } = useOverlayPeople();
|
|
377
379
|
const overlayPeople = Array.isArray(rawOverlayPeople) ? rawOverlayPeople : [];
|
|
378
380
|
const overlayEmails = useMemo(
|
|
@@ -398,14 +400,14 @@ export default function CalendarView() {
|
|
|
398
400
|
const ms = startOfMonth(selectedDate);
|
|
399
401
|
const me = endOfMonth(selectedDate);
|
|
400
402
|
return {
|
|
401
|
-
from: startOfWeek(ms).toISOString(),
|
|
402
|
-
to: endOfWeek(me).toISOString(),
|
|
403
|
+
from: startOfWeek(ms, { weekStartsOn }).toISOString(),
|
|
404
|
+
to: endOfWeek(me, { weekStartsOn }).toISOString(),
|
|
403
405
|
};
|
|
404
406
|
}
|
|
405
407
|
case "week": {
|
|
406
408
|
return {
|
|
407
|
-
from: startOfWeek(selectedDate).toISOString(),
|
|
408
|
-
to: endOfWeek(selectedDate).toISOString(),
|
|
409
|
+
from: startOfWeek(selectedDate, { weekStartsOn }).toISOString(),
|
|
410
|
+
to: endOfWeek(selectedDate, { weekStartsOn }).toISOString(),
|
|
409
411
|
};
|
|
410
412
|
}
|
|
411
413
|
case "day": {
|
|
@@ -416,7 +418,7 @@ export default function CalendarView() {
|
|
|
416
418
|
return { from: dayStart.toISOString(), to: dayEnd.toISOString() };
|
|
417
419
|
}
|
|
418
420
|
}
|
|
419
|
-
}, [viewMode, selectedDate]);
|
|
421
|
+
}, [viewMode, selectedDate, weekStartsOn]);
|
|
420
422
|
|
|
421
423
|
const {
|
|
422
424
|
data: rawEventsData,
|
|
@@ -470,8 +472,8 @@ export default function CalendarView() {
|
|
|
470
472
|
const next = addMonths(selectedDate, 1);
|
|
471
473
|
const prev = subMonths(selectedDate, 1);
|
|
472
474
|
return [next, prev].map((d) => ({
|
|
473
|
-
from: startOfWeek(startOfMonth(d)).toISOString(),
|
|
474
|
-
to: endOfWeek(endOfMonth(d)).toISOString(),
|
|
475
|
+
from: startOfWeek(startOfMonth(d), { weekStartsOn }).toISOString(),
|
|
476
|
+
to: endOfWeek(endOfMonth(d), { weekStartsOn }).toISOString(),
|
|
475
477
|
}));
|
|
476
478
|
}
|
|
477
479
|
case "week": {
|
|
@@ -480,8 +482,8 @@ export default function CalendarView() {
|
|
|
480
482
|
const next2 = addWeeks(selectedDate, 2);
|
|
481
483
|
const prev = subWeeks(selectedDate, 1);
|
|
482
484
|
return [next, next2, prev].map((d) => ({
|
|
483
|
-
from: startOfWeek(d).toISOString(),
|
|
484
|
-
to: endOfWeek(d).toISOString(),
|
|
485
|
+
from: startOfWeek(d, { weekStartsOn }).toISOString(),
|
|
486
|
+
to: endOfWeek(d, { weekStartsOn }).toISOString(),
|
|
485
487
|
}));
|
|
486
488
|
}
|
|
487
489
|
case "day": {
|
|
@@ -500,7 +502,14 @@ export default function CalendarView() {
|
|
|
500
502
|
for (const range of ranges) {
|
|
501
503
|
void prefetchEvents(queryClient, range.from, range.to, overlayEmails);
|
|
502
504
|
}
|
|
503
|
-
}, [
|
|
505
|
+
}, [
|
|
506
|
+
isLoading,
|
|
507
|
+
viewMode,
|
|
508
|
+
selectedDate,
|
|
509
|
+
overlayEmails,
|
|
510
|
+
queryClient,
|
|
511
|
+
weekStartsOn,
|
|
512
|
+
]);
|
|
504
513
|
|
|
505
514
|
// Show the skeleton only when there is genuinely nothing to show for the
|
|
506
515
|
// current date range — the first load, or navigating to a range we have not
|
|
@@ -675,7 +684,9 @@ export default function CalendarView() {
|
|
|
675
684
|
}
|
|
676
685
|
|
|
677
686
|
const location = draft.location ?? draft.workingLocationLabel ?? "";
|
|
678
|
-
const timezone =
|
|
687
|
+
const timezone = resolveEventTimezone(
|
|
688
|
+
draft.startTimeZone ?? draft.endTimeZone,
|
|
689
|
+
);
|
|
679
690
|
const semanticFullDay =
|
|
680
691
|
eventType === "outOfOffice" &&
|
|
681
692
|
draft.fullDay === true &&
|
|
@@ -1143,7 +1154,9 @@ export default function CalendarView() {
|
|
|
1143
1154
|
if (newEnd.getTime() <= newStart.getTime()) return;
|
|
1144
1155
|
|
|
1145
1156
|
if (calendarDraftIdFromEventId(eventId)) {
|
|
1146
|
-
const timezone =
|
|
1157
|
+
const timezone = resolveEventTimezone(
|
|
1158
|
+
event.startTimeZone ?? event.endTimeZone,
|
|
1159
|
+
);
|
|
1147
1160
|
updateDraftEvent(eventId, {
|
|
1148
1161
|
start: newStart.toISOString(),
|
|
1149
1162
|
end: newEnd.toISOString(),
|
|
@@ -1592,8 +1605,8 @@ export default function CalendarView() {
|
|
|
1592
1605
|
? format(selectedDate, "MMM yyyy")
|
|
1593
1606
|
: format(selectedDate, "MMMM yyyy");
|
|
1594
1607
|
case "week": {
|
|
1595
|
-
const ws = startOfWeek(selectedDate);
|
|
1596
|
-
const we = endOfWeek(selectedDate);
|
|
1608
|
+
const ws = startOfWeek(selectedDate, { weekStartsOn });
|
|
1609
|
+
const we = endOfWeek(selectedDate, { weekStartsOn });
|
|
1597
1610
|
return isMobile
|
|
1598
1611
|
? `${format(ws, "MMM d")} – ${format(we, "d")}`
|
|
1599
1612
|
: `${format(ws, "MMM d")} – ${format(we, "d, yyyy")}`;
|
|
@@ -1801,6 +1814,7 @@ export default function CalendarView() {
|
|
|
1801
1814
|
onDraftCreate={createDraftEvent}
|
|
1802
1815
|
onDraftDiscard={discardDraftEvent}
|
|
1803
1816
|
isLoading={eventsLoading}
|
|
1817
|
+
weekStartsOn={weekStartsOn}
|
|
1804
1818
|
/>
|
|
1805
1819
|
)}
|
|
1806
1820
|
{viewMode === "week" && (
|
|
@@ -1819,6 +1833,7 @@ export default function CalendarView() {
|
|
|
1819
1833
|
onDraftCreate={createDraftEvent}
|
|
1820
1834
|
onDraftDiscard={discardDraftEvent}
|
|
1821
1835
|
isLoading={eventsLoading}
|
|
1836
|
+
weekStartsOn={weekStartsOn}
|
|
1822
1837
|
/>
|
|
1823
1838
|
)}
|
|
1824
1839
|
{viewMode === "day" && (
|
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
AppearancePicker,
|
|
15
15
|
type AppearancePresetId,
|
|
16
16
|
} from "@agent-native/core/client/ui";
|
|
17
|
+
import type { CalendarWeekStart } from "@shared/calendar-week";
|
|
18
|
+
import { isCalendarWeekStart } from "@shared/calendar-week";
|
|
17
19
|
import {
|
|
18
20
|
IconBrandZoom,
|
|
19
21
|
IconExternalLink,
|
|
@@ -38,6 +40,13 @@ import {
|
|
|
38
40
|
} from "@/components/ui/card";
|
|
39
41
|
import { Input } from "@/components/ui/input";
|
|
40
42
|
import { Label } from "@/components/ui/label";
|
|
43
|
+
import {
|
|
44
|
+
Select,
|
|
45
|
+
SelectContent,
|
|
46
|
+
SelectItem,
|
|
47
|
+
SelectTrigger,
|
|
48
|
+
SelectValue,
|
|
49
|
+
} from "@/components/ui/select";
|
|
41
50
|
import { Separator } from "@/components/ui/separator";
|
|
42
51
|
import { Textarea } from "@/components/ui/textarea";
|
|
43
52
|
import {
|
|
@@ -56,6 +65,8 @@ import { shouldOfferGoogleOAuthSetup } from "@/lib/google-oauth-setup";
|
|
|
56
65
|
|
|
57
66
|
import changelog from "../../CHANGELOG.md?raw";
|
|
58
67
|
|
|
68
|
+
const AVAILABILITY_SETTINGS_PATH = "/booking-links?tab=availability";
|
|
69
|
+
|
|
59
70
|
export default function Settings() {
|
|
60
71
|
const t = useT();
|
|
61
72
|
const agentSettingsTabs = useAgentSettingsTabs();
|
|
@@ -83,6 +94,7 @@ export default function Settings() {
|
|
|
83
94
|
const [bookingTitle, setBookingTitle] = useState("");
|
|
84
95
|
const [bookingDescription, setBookingDescription] = useState("");
|
|
85
96
|
const [defaultDuration, setDefaultDuration] = useState(30);
|
|
97
|
+
const [weekStart, setWeekStart] = useState<CalendarWeekStart>("sunday");
|
|
86
98
|
|
|
87
99
|
useEffect(() => {
|
|
88
100
|
if (settings) {
|
|
@@ -90,6 +102,9 @@ export default function Settings() {
|
|
|
90
102
|
setBookingTitle(settings.bookingPageTitle);
|
|
91
103
|
setBookingDescription(settings.bookingPageDescription);
|
|
92
104
|
setDefaultDuration(settings.defaultEventDuration);
|
|
105
|
+
setWeekStart(
|
|
106
|
+
isCalendarWeekStart(settings.weekStart) ? settings.weekStart : "sunday",
|
|
107
|
+
);
|
|
93
108
|
}
|
|
94
109
|
}, [settings]);
|
|
95
110
|
|
|
@@ -100,6 +115,7 @@ export default function Settings() {
|
|
|
100
115
|
bookingPageTitle: bookingTitle,
|
|
101
116
|
bookingPageDescription: bookingDescription,
|
|
102
117
|
defaultEventDuration: defaultDuration,
|
|
118
|
+
weekStart,
|
|
103
119
|
},
|
|
104
120
|
{
|
|
105
121
|
onSuccess: () => toast.success(t("settings.saved")),
|
|
@@ -185,9 +201,16 @@ export default function Settings() {
|
|
|
185
201
|
{
|
|
186
202
|
id: "calendar-general",
|
|
187
203
|
label: t("settings.general"),
|
|
188
|
-
keywords:
|
|
204
|
+
keywords:
|
|
205
|
+
"timezone week start sunday monday booking duration defaults general",
|
|
189
206
|
hash: "general-settings",
|
|
190
207
|
},
|
|
208
|
+
{
|
|
209
|
+
id: "calendar-availability",
|
|
210
|
+
label: t("bookingLinks.availability"),
|
|
211
|
+
keywords: "availability available hours booking schedule working hours",
|
|
212
|
+
hash: "availability",
|
|
213
|
+
},
|
|
191
214
|
{
|
|
192
215
|
id: "calendar-appearance",
|
|
193
216
|
label: t("settings.appearance"),
|
|
@@ -240,6 +263,18 @@ export default function Settings() {
|
|
|
240
263
|
}}
|
|
241
264
|
/>
|
|
242
265
|
</SettingsRow>
|
|
266
|
+
<SettingsRow
|
|
267
|
+
id="availability"
|
|
268
|
+
label={t("bookingLinks.availability")}
|
|
269
|
+
description={t("bookingLinks.availabilityDescription")}
|
|
270
|
+
control={
|
|
271
|
+
<Button variant="outline" size="sm" asChild>
|
|
272
|
+
<Link to={AVAILABILITY_SETTINGS_PATH}>
|
|
273
|
+
{t("bookingLinks.availability")}
|
|
274
|
+
</Link>
|
|
275
|
+
</Button>
|
|
276
|
+
}
|
|
277
|
+
/>
|
|
243
278
|
</SettingsGroup>
|
|
244
279
|
|
|
245
280
|
{/* Google Calendar Connection */}
|
|
@@ -412,6 +447,30 @@ export default function Settings() {
|
|
|
412
447
|
<TimezoneCombobox value={timezone} onChange={setTimezone} />
|
|
413
448
|
</div>
|
|
414
449
|
|
|
450
|
+
<div className="space-y-2">
|
|
451
|
+
<Label htmlFor="week-start">
|
|
452
|
+
{t("settings.weekStartLabel")}
|
|
453
|
+
</Label>
|
|
454
|
+
<Select
|
|
455
|
+
value={weekStart}
|
|
456
|
+
onValueChange={(value) => {
|
|
457
|
+
if (isCalendarWeekStart(value)) setWeekStart(value);
|
|
458
|
+
}}
|
|
459
|
+
>
|
|
460
|
+
<SelectTrigger id="week-start" className="w-full sm:w-56">
|
|
461
|
+
<SelectValue />
|
|
462
|
+
</SelectTrigger>
|
|
463
|
+
<SelectContent>
|
|
464
|
+
<SelectItem value="sunday">
|
|
465
|
+
{t("settings.weekStartSunday")}
|
|
466
|
+
</SelectItem>
|
|
467
|
+
<SelectItem value="monday">
|
|
468
|
+
{t("settings.weekStartMonday")}
|
|
469
|
+
</SelectItem>
|
|
470
|
+
</SelectContent>
|
|
471
|
+
</Select>
|
|
472
|
+
</div>
|
|
473
|
+
|
|
415
474
|
<div className="space-y-2">
|
|
416
475
|
<Label htmlFor="booking-title">
|
|
417
476
|
{t("settings.bookingTitleLabel")}
|
|
@@ -28,6 +28,7 @@ import type {
|
|
|
28
28
|
CustomField,
|
|
29
29
|
TimeSlot,
|
|
30
30
|
} from "../../shared/api.js";
|
|
31
|
+
import { normalizeAvailabilitySlots } from "../../shared/availability-schedule.js";
|
|
31
32
|
import { getDb, schema } from "../db/index.js";
|
|
32
33
|
import {
|
|
33
34
|
parseBookingLinkDurations,
|
|
@@ -626,7 +627,7 @@ export function generateAvailableSlotsForDate({
|
|
|
626
627
|
timezone,
|
|
627
628
|
);
|
|
628
629
|
|
|
629
|
-
for (const scheduleSlot of daySchedule.slots) {
|
|
630
|
+
for (const scheduleSlot of normalizeAvailabilitySlots(daySchedule.slots)) {
|
|
630
631
|
const [startHour, startMin] = scheduleSlot.start.split(":").map(Number);
|
|
631
632
|
const [endHour, endMin] = scheduleSlot.end.split(":").map(Number);
|
|
632
633
|
if (
|
|
@@ -7,14 +7,7 @@ import {
|
|
|
7
7
|
} from "@agent-native/core/settings";
|
|
8
8
|
import { defineEventHandler, setResponseStatus, type H3Event } from "h3";
|
|
9
9
|
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
const DEFAULT_SETTINGS: Settings = {
|
|
13
|
-
timezone: "America/New_York",
|
|
14
|
-
bookingPageTitle: "Book a Meeting",
|
|
15
|
-
bookingPageDescription: "Select a time that works for you.",
|
|
16
|
-
defaultEventDuration: 30,
|
|
17
|
-
};
|
|
10
|
+
import { normalizeCalendarSettings } from "../../shared/settings.js";
|
|
18
11
|
|
|
19
12
|
async function uEmail(event: H3Event): Promise<string> {
|
|
20
13
|
const session = await getSession(event);
|
|
@@ -28,9 +21,9 @@ async function uEmail(event: H3Event): Promise<string> {
|
|
|
28
21
|
export const getSettings = defineEventHandler(async (event: H3Event) => {
|
|
29
22
|
try {
|
|
30
23
|
const email = await uEmail(event);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
return normalizeCalendarSettings(
|
|
25
|
+
await getUserSetting(email, "calendar-settings"),
|
|
26
|
+
);
|
|
34
27
|
} catch (error: any) {
|
|
35
28
|
setResponseStatus(event, 500);
|
|
36
29
|
return { error: error.message };
|
|
@@ -38,16 +31,19 @@ export const getSettings = defineEventHandler(async (event: H3Event) => {
|
|
|
38
31
|
});
|
|
39
32
|
|
|
40
33
|
export const getPublicSettings = defineEventHandler(async (_event: H3Event) => {
|
|
41
|
-
|
|
42
|
-
((await getSetting("calendar-settings")) as unknown as Settings | null) ||
|
|
43
|
-
DEFAULT_SETTINGS;
|
|
44
|
-
return settings;
|
|
34
|
+
return normalizeCalendarSettings(await getSetting("calendar-settings"));
|
|
45
35
|
});
|
|
46
36
|
|
|
47
37
|
export const updateSettings = defineEventHandler(async (event: H3Event) => {
|
|
48
38
|
try {
|
|
49
39
|
const email = await uEmail(event);
|
|
50
|
-
const
|
|
40
|
+
const body = await readBody<unknown>(event);
|
|
41
|
+
const settings = normalizeCalendarSettings({
|
|
42
|
+
...normalizeCalendarSettings(
|
|
43
|
+
await getUserSetting(email, "calendar-settings"),
|
|
44
|
+
),
|
|
45
|
+
...(body && typeof body === "object" ? body : {}),
|
|
46
|
+
});
|
|
51
47
|
const settingsRecord = settings as unknown as Record<string, unknown>;
|
|
52
48
|
await putUserSetting(email, "calendar-settings", settingsRecord);
|
|
53
49
|
// Also write to global key so the public booking/settings page can read it
|