import { importShared } from "./__federation_fn_import-hlt2XzeI.js"; import { j as jsxRuntimeExports } from "./jsx-runtime-CvJTHeKY.js"; const { useCallback, useEffect, useState } = await importShared("react"); const { Alert, AlertDescription, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Tabs, TabsContent, TabsList, TabsTrigger, Input, Label, Textarea, Switch, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Settings, Edit3, CheckCircle2, XCircle, Loader2, Key, AlertCircle, ExternalLink, RefreshCw, t, } = await importShared("@block-ninja/ui"); function renderConnectedAccount(apiKeyConfigured, calcomUsername) { if (apiKeyConfigured === false) { return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.connectedAs.noKey", "Configure the API key in plugin settings to connect an account."), }); } if (calcomUsername) { return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-mono", children: calcomUsername }); } return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.connectedAs.resolving", "Resolving account from API key…") }); } function CalcomBlockEditor({ content, onChange }) { const [activeTab, setActiveTab] = useState("config"); const [apiKeyConfigured, setApiKeyConfigured] = useState(null); const [calcomUsername, setCalcomUsername] = useState(""); const [eventTypes, setEventTypes] = useState([]); const [loadingEventTypes, setLoadingEventTypes] = useState(false); const [fetchFailed, setFetchFailed] = useState(false); const [retryCounter, setRetryCounter] = useState(0); const handleFieldChange = useCallback( (field, value) => { onChange({ ...content, [field]: value }); }, [content, onChange], ); const getString = (field, defaultValue = "") => { return content[field] || defaultValue; }; const getNumber = (field, defaultValue = 0) => { const val = content[field]; if (typeof val === "number") return val; if (typeof val === "string") return parseInt(val, 10) || defaultValue; return defaultValue; }; const getBool = (field, defaultValue = false) => { const val = content[field]; if (typeof val === "boolean") return val; return defaultValue; }; const eventTypeSlug = getString("eventTypeSlug"); useEffect(() => { fetch(`/api/plugins/calcomblock/settings`) .then((r) => r.json()) .then((d) => { setApiKeyConfigured(!!d.api_key_configured); setCalcomUsername(d.username ?? ""); }) .catch(() => setApiKeyConfigured(false)); }, []); useEffect(() => { if (calcomUsername && content.username !== calcomUsername) { onChange({ ...content, username: calcomUsername }); } }, [calcomUsername, content, onChange]); useEffect(() => { if (!apiKeyConfigured) { setEventTypes([]); setFetchFailed(false); return; } const timer = setTimeout(() => { setLoadingEventTypes(true); setFetchFailed(false); fetch(`/api/plugins/calcomblock/event-types?username=${encodeURIComponent(calcomUsername)}`) .then((r) => r.json()) .then((d) => { if (d.success) { setEventTypes(d.event_types ?? []); } else { setEventTypes([]); setFetchFailed(true); } }) .catch(() => { setEventTypes([]); setFetchFailed(true); }) .finally(() => setLoadingEventTypes(false)); }, 300); return () => clearTimeout(timer); }, [apiKeyConfigured, calcomUsername, retryCounter]); const handleRetry = useCallback(() => { setRetryCounter((n) => n + 1); }, []); const selectPlaceholder = (() => { if (apiKeyConfigured === false) { return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1.5 text-muted-foreground", children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Key, { className: "h-3 w-3" }), t("calcom.editor.eventType.placeholder.noApiKey", "Configure API key first")], }); } if (loadingEventTypes) { return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1.5 text-muted-foreground", children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "h-3 w-3 animate-spin" }), t("calcom.editor.eventType.placeholder.loading", "Loading…")], }); } if (!calcomUsername) { return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1.5 text-muted-foreground", children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "h-3 w-3 animate-spin" }), t("calcom.editor.eventType.placeholder.resolvingUser", "Resolving account…")], }); } if (eventTypes.length === 0) { return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1.5 text-muted-foreground", children: [/* @__PURE__ */ jsxRuntimeExports.jsx(XCircle, { className: "h-3 w-3" }), t("calcom.editor.eventType.placeholder.noEventTypes", "No event types found")], }); } return t("calcom.editor.eventType.placeholder.select", "Select event type"); })(); const apiKeyReady = apiKeyConfigured === true; const usernameReady = calcomUsername.length > 0; const eventTypeReady = eventTypeSlug.length > 0; const canOpenInCalcom = usernameReady && eventTypeReady; const renderStatusRow = (ok, label, action) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [ ok ? /* @__PURE__ */ jsxRuntimeExports.jsx(CheckCircle2, { "className": "h-4 w-4 text-primary", "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(XCircle, { "className": "h-4 w-4 text-destructive", "aria-hidden": "true" }), /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: ok ? "text-foreground" : "text-muted-foreground", children: label }), action ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-auto", children: action }) : null, ], }); return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "config", className: "gap-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Settings, { className: "h-4 w-4" }), /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("calcom.editor.tab.configuration", "Configuration") }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "content", className: "gap-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Edit3, { className: "h-4 w-4" }), /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("calcom.editor.tab.content", "Content") }), ], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsContent, { value: "config", className: "space-y-4 mt-4", children: [ apiKeyConfigured === false && /* @__PURE__ */ jsxRuntimeExports.jsx(Alert, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDescription, { children: [ t("calcom.editor.alert.apiKeyMissing.prefix", "Configure your Cal.com API key in"), " ", /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/admin/plugins?plugin=calcomblock", className: "text-primary hover:underline", children: t("calcom.editor.alert.apiKeyMissing.linkLabel", "plugin settings"), }), " ", t("calcom.editor.alert.apiKeyMissing.suffix", "to enable the event-type dropdown."), ], }), }), /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-base", children: t("calcom.editor.section.config.title", "Cal.com Settings") }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: t("calcom.editor.section.config.description", "Connect to your Cal.com account and select an event type"), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { children: t("calcom.editor.connectedAs.label", "Connected Account") }), renderConnectedAccount(apiKeyConfigured, calcomUsername), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(Label, { htmlFor: "eventTypeSlug", children: [ t("calcom.editor.eventType.label", "Event Type"), " ", /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive", children: "*" }), ], }), fetchFailed ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: "eventTypeSlug", value: eventTypeSlug, onChange: (e) => handleFieldChange("eventTypeSlug", e.target.value), placeholder: t("calcom.editor.eventType.fallbackPlaceholder", "30min"), className: "flex-1", }), /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { "type": "button", "size": "sm", "variant": "outline", "action": "retry", "entity": "event-types", "onClick": handleRetry, "disabled": loadingEventTypes, "aria-label": t("calcom.editor.eventType.retryAria", "Retry loading event types"), "children": [ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { "className": `h-4 w-4 ${loadingEventTypes ? "animate-spin" : ""}`, "aria-hidden": "true", }), /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-1", children: t("calcom.editor.eventType.retryLabel", "Retry"), }), ], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, { variant: "destructive", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertCircle, { "className": "h-4 w-4", "aria-hidden": "true" }), /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: t("calcom.editor.eventType.fetchFailed", "Couldn't load event types from Cal.com. Enter the slug manually or retry."), }), ], }), ], }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: eventTypeSlug, onValueChange: (v) => handleFieldChange("eventTypeSlug", v), disabled: loadingEventTypes || !apiKeyConfigured || eventTypes.length === 0, children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { "aria-label": t("calcom.editor.eventType.label", "Event Type"), "children": /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: selectPlaceholder }), }), /* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, { children: eventTypes.map((et) => /* @__PURE__ */ jsxRuntimeExports.jsxs( SelectItem, { value: et.slug, children: [ et.title, /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [" ", "(", et.slug, " · ", et.lengthInMinutes, "m)"], }), ], }, et.id, ), ), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.eventType.help", "Fetched from your Cal.com account"), }), ], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "weeksToShow", children: t("calcom.editor.weeksToShow.label", "Weeks to Display") }), /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: String(getNumber("weeksToShow", 2)), onValueChange: (v) => handleFieldChange("weeksToShow", parseInt(v, 10)), children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { "aria-label": t("calcom.editor.weeksToShow.label", "Weeks to Display"), "children": /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: t("calcom.editor.weeksToShow.placeholder", "Select weeks") }), }), /* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, { children: [1, 2, 3, 4, 5, 6, 7, 8].map((n) => /* @__PURE__ */ jsxRuntimeExports.jsxs( SelectItem, { value: String(n), children: [ n, " ", n > 1 ? t("calcom.editor.weeksToShow.unitPlural", "weeks") : t("calcom.editor.weeksToShow.unitSingular", "week"), ], }, n, ), ), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.weeksToShow.help", "How many weeks of dates to show in the calendar"), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between rounded-lg border p-3", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { children: t("calcom.editor.showTimezone.label", "Show Timezone Selector") }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.showTimezone.help", "Show a label above the date grid indicating which timezone times are displayed in."), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx(Switch, { "checked": getBool("showTimezone", true), "onCheckedChange": (v) => handleFieldChange("showTimezone", v), "aria-label": t("calcom.editor.showTimezone.label", "Show Timezone Selector"), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between rounded-lg border p-3", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { children: t("calcom.editor.captchaEnabled.label", "Enable captcha") }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t( "calcom.editor.captchaEnabled.help", "Require visitors to solve a privacy-friendly proof-of-work captcha before booking (spam protection).", ), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx(Switch, { "checked": getBool("captchaEnabled", false), "onCheckedChange": (v) => handleFieldChange("captchaEnabled", v), "aria-label": t("calcom.editor.captchaEnabled.label", "Enable captcha"), }), ], }), ], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-base", children: t("calcom.editor.status.title", "Configuration status") }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: t("calcom.editor.status.description", "Quick check of the values needed before this block renders bookings."), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-2", children: [ renderStatusRow( apiKeyReady, t("calcom.editor.status.apiKey", "API key configured"), !apiKeyReady ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/admin/plugins?plugin=calcomblock", className: "text-xs text-primary hover:underline", children: t("calcom.editor.status.apiKey.configureLink", "Configure"), }) : null, ), renderStatusRow(usernameReady, t("calcom.editor.status.username", "Account resolved")), renderStatusRow(eventTypeReady, t("calcom.editor.status.eventType", "Event type selected")), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex h-4 w-4 items-center justify-center text-muted-foreground", children: "·" }), /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: t("calcom.editor.status.eventTypesAvailable", "{count} event types available").replace("{count}", String(eventTypes.length)), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pt-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { "type": "button", "size": "sm", "variant": "outline", "action": "open", "entity": "calcom-page", "asChild": canOpenInCalcom, "disabled": !canOpenInCalcom, "aria-label": t("calcom.editor.status.openExternalAria", "Open Cal.com booking page in a new tab"), "children": canOpenInCalcom ? /* @__PURE__ */ jsxRuntimeExports.jsxs("a", { href: `https://cal.com/${calcomUsername}/${eventTypeSlug}`, target: "_blank", rel: "noopener noreferrer", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { "className": "h-4 w-4", "aria-hidden": "true" }), /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-1", children: t("calcom.editor.status.openExternal", "Open in Cal.com"), }), ], }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { "className": "h-4 w-4", "aria-hidden": "true" }), /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-1", children: t("calcom.editor.status.openExternal", "Open in Cal.com"), }), ], }), }), }), ], }), ], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "content", className: "space-y-4 mt-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-base", children: t("calcom.editor.section.content.title", "Widget Content") }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: t("calcom.editor.section.content.description", "Customize the text shown in the booking widget"), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "title", children: t("calcom.editor.title.label", "Title") }), /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: "title", value: getString("title"), onChange: (e) => handleFieldChange("title", e.target.value), placeholder: t("calcom.editor.title.placeholder", "Book a Meeting"), }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.title.help", "Main heading shown above the calendar"), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "description", children: t("calcom.editor.description.label", "Description") }), /* @__PURE__ */ jsxRuntimeExports.jsx(Textarea, { id: "description", value: getString("description"), onChange: (e) => handleFieldChange("description", e.target.value), placeholder: t("calcom.editor.description.placeholder", "Choose a convenient time for your consultation..."), rows: 3, }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.description.help", "Optional text shown below the title"), }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "unavailableMessage", children: t("calcom.editor.unavailableMessage.label", "Booking unavailable message"), }), /* @__PURE__ */ jsxRuntimeExports.jsx(Textarea, { id: "unavailableMessage", value: getString("unavailableMessage"), onChange: (e) => handleFieldChange("unavailableMessage", e.target.value), placeholder: t( "calcom.editor.unavailableMessage.placeholder", "Sorry — we couldn't complete your booking online. Please use our contact form and we'll get you booked in.", ), rows: 3, }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.unavailableMessage.help", "Shown if an online booking can't be completed. Leave blank to use the default."), }), ], }), ], }), ], }), }), ], }), }); } export { CalcomBlockEditor as default };