/* eslint-disable react/no-unknown-property */
// Ignored because of gridstack attributes
import { useMemo } from "react";
import type { RefObject } from "react";
import { ActionIcon, Card, Menu } from "@mantine/core";
import { useElementSize } from "@mantine/hooks";
import { IconDotsVertical, IconLayoutKanban, IconPencil, IconTrash } from "@tabler/icons-react";
import combineClasses from "clsx";
import { useAtomValue } from "jotai";
import { clientApi } from "@homarr/api/client";
import { useConfirmModal, useModalAction } from "@homarr/modals";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import {
loadWidgetDynamic,
reduceWidgetOptionsWithDefaultValues,
useServerDataFor,
WidgetEditModal,
widgetImports,
} from "@homarr/widgets";
import type { Item } from "~/app/[locale]/boards/_types";
import { useRequiredBoard } from "~/app/[locale]/boards/(content)/_context";
import { editModeAtom } from "../editMode";
import { useItemActions } from "../items/item-actions";
import type { UseGridstackRefs } from "./gridstack/use-gridstack";
import classes from "./item.module.css";
interface Props {
items: Item[];
refs: UseGridstackRefs;
}
export const SectionContent = ({ items, refs }: Props) => {
const board = useRequiredBoard();
return (
<>
{items.map((item) => (
))}
>
);
};
interface ItemProps {
item: Item;
refs: UseGridstackRefs;
opacity: number;
}
const BoardItem = ({ refs, item, opacity }: ItemProps) => {
const { ref, width, height } = useElementSize();
return (
}
>
);
};
interface ItemContentProps {
item: Item;
width: number;
height: number;
}
const BoardItemContent = ({ item, ...dimensions }: ItemContentProps) => {
const board = useRequiredBoard();
const editMode = useAtomValue(editModeAtom);
const serverData = useServerDataFor(item.id);
const Comp = loadWidgetDynamic(item.kind);
const options = reduceWidgetOptionsWithDefaultValues(item.kind, item.options);
const newItem = { ...item, options };
if (!serverData?.isReady) return null;
return (
<>
>
);
};
const ItemMenu = ({ offset, item }: { offset: number; item: Item }) => {
const tItem = useScopedI18n("item");
const t = useI18n();
const { openModal } = useModalAction(WidgetEditModal);
const { openConfirmModal } = useConfirmModal();
const isEditMode = useAtomValue(editModeAtom);
const { updateItemOptions, updateItemAdvancedOptions, updateItemIntegrations, removeItem } = useItemActions();
const { data: integrationData, isPending } = clientApi.integration.all.useQuery();
const currentDefinition = useMemo(() => widgetImports[item.kind].definition, [item.kind]);
if (!isEditMode || isPending) return null;
const openEditModal = () => {
openModal({
kind: item.kind,
value: {
advancedOptions: item.advancedOptions,
options: item.options,
integrations: item.integrations,
},
onSuccessfulEdit: ({ options, integrations, advancedOptions }) => {
updateItemOptions({
itemId: item.id,
newOptions: options,
});
updateItemAdvancedOptions({
itemId: item.id,
newAdvancedOptions: advancedOptions,
});
updateItemIntegrations({
itemId: item.id,
newIntegrations: integrations,
});
},
integrationData: (integrationData ?? []).filter(
(integration) =>
"supportedIntegrations" in currentDefinition &&
(currentDefinition.supportedIntegrations as string[]).some((kind) => kind === integration.kind),
),
integrationSupport: "supportedIntegrations" in currentDefinition,
});
};
const openRemoveModal = () => {
openConfirmModal({
title: tItem("remove.title"),
children: tItem("remove.message"),
onConfirm: () => {
removeItem({ itemId: item.id });
},
});
};
return (
);
};