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 };