import { I as __exportAll } from "./portal_tenant_content-DPLnrtOG.mjs";
import { n as useDataSourceRegistryConfig } from "./registry-context-DdfXs3K3.mjs";
import { i as useWidgetsApi, n as useWidgetPreviewContext, t as ErrorState } from "./error-state-DSJb-3r5.mjs";
import { i as getBorderColorField, l as getColorField, m as getPaddingField, n as borderWidthClasses, o as getBorderRadiusField, s as getBorderWidthField, t as borderColorClasses, u as getFontSizeField } from "./registries-BR8vLBBe.mjs";
import { f as fluidToast } from "./src-Dk1FJOX0.mjs";
import { t as parseTaskBody } from "./parse-task-body-DNn57dfP.mjs";
import { useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
import { ListChecks, Plus } from "lucide-react";
//#region ../widgets/src/hooks/use-todos.preview.ts
const now = /* @__PURE__ */ new Date();
function daysFromNow(days) {
	const d = new Date(now);
	d.setDate(d.getDate() + days);
	return d.toISOString();
}
const PREVIEW_DATA = [
	{
		id: 1,
		body: "Send follow-up email to new leads",
		dueAt: daysFromNow(1),
		completedAt: null,
		createdAt: daysFromNow(-2),
		contactId: 101,
		contactName: "Sarah Johnson"
	},
	{
		id: 2,
		body: "Prepare slides for team training",
		dueAt: daysFromNow(3),
		completedAt: null,
		createdAt: daysFromNow(-1),
		contactId: null,
		contactName: null
	},
	{
		id: 3,
		body: "Review monthly sales report",
		dueAt: daysFromNow(-1),
		completedAt: null,
		createdAt: daysFromNow(-5),
		contactId: 102,
		contactName: "Mike Chen"
	}
];
//#endregion
//#region ../widgets/src/hooks/use-todos.ts
/**
* Shared cache key for the todos list. Both useTodos (read) and
* useUpdateTodo (write) use this — drift would silently break optimistic
* updates.
*/
function todosQueryKey(args) {
	return [
		"portal-widget-use",
		"todos",
		args.isPreview ? "preview" : args.baseUrl
	];
}
function useTodos() {
	const widgetsApi = useWidgetsApi();
	const { isPreview } = useWidgetPreviewContext();
	const { baseUrl } = useDataSourceRegistryConfig();
	return useQuery({
		queryKey: todosQueryKey({
			baseUrl,
			isPreview
		}),
		queryFn: ({ signal }) => widgetsApi.fetchTodos(signal),
		enabled: !isPreview,
		...isPreview && { placeholderData: PREVIEW_DATA }
	});
}
//#endregion
//#region ../widgets/src/hooks/use-update-todo.ts
function useUpdateTodo() {
	const widgetsApi = useWidgetsApi();
	const queryClient = useQueryClient();
	const { isPreview } = useWidgetPreviewContext();
	const { baseUrl } = useDataSourceRegistryConfig();
	const queryKey = todosQueryKey({
		baseUrl,
		isPreview
	});
	return useMutation({
		mutationFn: ({ id, completed }) => {
			if (isPreview) return Promise.reject(/* @__PURE__ */ new Error("Todo updates are disabled in preview mode"));
			return widgetsApi.updateTodo(id, completed);
		},
		onMutate: async ({ id, completed }) => {
			await queryClient.cancelQueries({ queryKey });
			const previous = queryClient.getQueryData(queryKey);
			queryClient.setQueryData(queryKey, (current) => (current ?? []).map((todo) => todo.id === id ? {
				...todo,
				completedAt: completed ? (/* @__PURE__ */ new Date()).toISOString() : null
			} : todo));
			return { previous };
		},
		onSuccess: (updated, { completed }) => {
			queryClient.setQueryData(queryKey, (current) => (current ?? []).map((todo) => todo.id === updated.id ? updated : todo));
			if (completed) fluidToast({
				title: "Todo completed",
				type: "success"
			});
		},
		onError: (_error, _variables, context) => {
			if (context?.previous) queryClient.setQueryData(queryKey, context.previous);
			fluidToast({
				title: "Failed to update todo",
				type: "error"
			});
		},
		onSettled: () => {
			queryClient.invalidateQueries({ queryKey });
		}
	});
}
//#endregion
//#region ../widgets/src/widgets/ToDoWidget.tsx
var ToDoWidget_exports = /* @__PURE__ */ __exportAll({
	ToDoWidget: () => ToDoWidget,
	toDoWidgetPropertySchema: () => toDoWidgetPropertySchema
});
function ToDoWidget({ titleEnabled = true, titleText = "To-Do", titleFontSize = "lg", titleColor = "foreground", background = {
	type: "solid",
	color: "background"
}, textColor = "foreground", accentColor = "primary", padding = 4, borderRadius = "md", borderWidth = "none", borderColor = "muted", maxItems = 5, className, ...props }) {
	const backgroundColor = background.color || "background";
	const backgroundImage = (background.resource?.image_url || background.resource?.imageUrl) && background.type === "image" ? `url(${background.resource.image_url || background.resource.imageUrl})` : "none";
	const { data: todos = [], isLoading, isError } = useTodos();
	const updateTodo = useUpdateTodo();
	const { isPreview } = useWidgetPreviewContext();
	const [pendingIds, setPendingIds] = useState(/* @__PURE__ */ new Set());
	const toggleTodo = (id, completed) => {
		if (isPreview || pendingIds.has(id)) return;
		setPendingIds((prev) => new Set(prev).add(id));
		updateTodo.mutate({
			id,
			completed
		}, { onSettled: () => setPendingIds((prev) => {
			const next = new Set(prev);
			next.delete(id);
			return next;
		}) });
	};
	const activeTodos = todos.filter((todo) => !todo.completedAt);
	const todosToShow = activeTodos.slice(0, maxItems);
	const remainingCount = activeTodos.length - todosToShow.length;
	const isEmpty = activeTodos.length === 0;
	const groupedTodos = todosToShow.reduce((groups, todo) => {
		const existing = groups.find((g) => g.contactId === todo.contactId);
		if (existing) existing.todos.push(todo);
		else groups.push({
			contactId: todo.contactId,
			contactName: todo.contactName,
			todos: [todo]
		});
		return groups;
	}, []);
	return /* @__PURE__ */ jsxs("div", {
		className: `overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? borderColorClasses[borderColor] : ""} bg-${backgroundColor} text-${textColor} p-${padding} ${className ?? ""}`,
		style: { backgroundImage },
		...props,
		children: [/* @__PURE__ */ jsxs("div", {
			className: "mb-3 flex items-center justify-between",
			children: [/* @__PURE__ */ jsx("div", {
				className: "flex items-center gap-3",
				children: titleEnabled && titleText && /* @__PURE__ */ jsx("h2", {
					className: `text-${titleFontSize} font-header font-bold text-${titleColor}`,
					children: titleText
				})
			}), /* @__PURE__ */ jsxs("div", {
				className: "flex items-center gap-2",
				children: [!isEmpty && !isLoading && /* @__PURE__ */ jsx("span", {
					className: `text-2xl font-bold text-${accentColor}`,
					children: activeTodos.length
				}), /* @__PURE__ */ jsx("div", {
					className: `flex h-10 w-10 shrink-0 items-center justify-center`,
					children: /* @__PURE__ */ jsx(ListChecks, { className: `h-5 w-5 text-${accentColor}-foreground` })
				})]
			})]
		}), isLoading ? /* @__PURE__ */ jsx("div", {
			className: "flex min-h-[120px] items-center justify-center",
			children: /* @__PURE__ */ jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-current border-t-transparent" })
		}) : isError ? /* @__PURE__ */ jsx(ErrorState, {}) : isEmpty ? /* @__PURE__ */ jsx("div", {
			className: "flex flex-col items-center justify-center py-8",
			children: /* @__PURE__ */ jsx("p", {
				className: `text-center text-${textColor}/60`,
				children: "You've got nothing else To-Do!"
			})
		}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
			className: "flex flex-col gap-3",
			children: groupedTodos.map((group) => /* @__PURE__ */ jsxs("div", {
				className: "flex flex-col",
				children: [group.contactName && /* @__PURE__ */ jsx("div", {
					className: `mb-1 text-xs font-semibold tracking-wide uppercase text-${textColor}/60`,
					children: group.contactName
				}), group.todos.map((todo, index) => /* @__PURE__ */ jsxs("div", {
					className: `flex items-center gap-3 py-2 ${index !== group.todos.length - 1 ? `border-b border-${textColor}/10` : ""}`,
					children: [/* @__PURE__ */ jsx("input", {
						type: "checkbox",
						className: `h-5 w-5 rounded-full border-2 border-${textColor}/30 bg-transparent not-disabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-60`,
						checked: !!todo.completedAt,
						disabled: isPreview || pendingIds.has(todo.id),
						onChange: (event) => toggleTodo(todo.id, event.target.checked)
					}), /* @__PURE__ */ jsx("span", {
						className: "line-clamp-1 flex-1 text-sm",
						children: parseTaskBody(todo.body).title
					})]
				}, todo.id))]
			}, group.contactId ?? "__unassigned__"))
		}), /* @__PURE__ */ jsxs("div", {
			className: "mt-2 flex items-center justify-between",
			children: [remainingCount > 0 && /* @__PURE__ */ jsxs("span", {
				className: `text-sm text-${textColor}/50 underline`,
				children: [
					remainingCount,
					" more task",
					remainingCount > 1 ? "s" : ""
				]
			}), /* @__PURE__ */ jsx("div", {
				className: "ml-auto",
				children: /* @__PURE__ */ jsx(Plus, { className: `h-5 w-5 text-${textColor}/50` })
			})]
		})] })]
	});
}
const toDoWidgetPropertySchema = {
	widgetType: "ToDoWidget",
	displayName: "To-Do Widget",
	tabsConfig: [{
		id: "styling",
		label: "Styling"
	}],
	fields: [
		{
			key: "titleEnabled",
			label: "Widget Title",
			type: "boolean",
			description: "Enable the title displayed above the todo list",
			defaultValue: true,
			tab: "styling",
			group: "Title"
		},
		{
			key: "titleText",
			label: "Title",
			type: "text",
			description: "Title text displayed above the todo list",
			defaultValue: "To-Do",
			tab: "styling",
			group: "Title",
			requiresKeyToBeTrue: "titleEnabled"
		},
		getFontSizeField({
			key: "titleFontSize",
			label: "Title Font Size",
			description: "Font size for the widget title",
			defaultValue: "xl",
			tab: "styling",
			group: "Title",
			requiresKeyToBeTrue: "titleEnabled"
		}),
		getColorField({
			key: "titleColor",
			label: "Title Color",
			description: "Color for the widget title",
			defaultValue: "foreground",
			tab: "styling",
			group: "Title",
			requiresKeyToBeTrue: "titleEnabled"
		}),
		{
			type: "background",
			key: "background",
			label: "Background",
			description: "Background for the widget container",
			defaultValue: "background",
			tab: "styling",
			group: "Design"
		},
		getColorField({
			key: "textColor",
			label: "Text Color",
			description: "Default text color for todo items",
			defaultValue: "foreground",
			tab: "styling",
			group: "Design"
		}),
		getColorField({
			key: "accentColor",
			label: "Accent Color",
			description: "Color used for count badge and icon",
			defaultValue: "primary",
			tab: "styling",
			group: "Design"
		}),
		{
			key: "separator",
			type: "separator",
			label: "Separator",
			tab: "styling",
			group: "Design"
		},
		{
			key: "maxItems",
			label: "Max Items",
			type: "number",
			description: "Maximum number of todo items to display",
			min: 1,
			max: 20,
			step: 1,
			defaultValue: 5,
			tab: "styling",
			group: "Design"
		},
		getPaddingField({
			key: "padding",
			label: "Padding",
			description: "Padding around the widget container",
			defaultValue: 4,
			tab: "styling",
			group: "Design"
		}),
		getBorderRadiusField({
			key: "borderRadius",
			label: "Border Radius",
			description: "Border radius for the widget container",
			defaultValue: "md",
			tab: "styling",
			group: "Design"
		}),
		getBorderWidthField({
			key: "borderWidth",
			label: "Border Width",
			description: "Border width for the widget",
			defaultValue: "none",
			tab: "styling",
			group: "Design"
		}),
		getBorderColorField({
			key: "borderColor",
			label: "Border Color",
			description: "Border color for the widget",
			defaultValue: "muted",
			tab: "styling",
			group: "Design"
		})
	]
};
//#endregion
export { ToDoWidget_exports as n, toDoWidgetPropertySchema as r, ToDoWidget as t };

//# sourceMappingURL=ToDoWidget-IKwBkpj3.mjs.map