buster/web/src/components/features/dropdowns/SaveToCollectionsDropdown.tsx

110 lines
3.8 KiB
TypeScript

import { Dropdown, type DropdownItem, type DropdownProps } from '@/components/ui/dropdown';
import { AppTooltip } from '@/components/ui/tooltip';
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
import { BusterRoutes, createBusterRoute } from '@/routes/busterRoutes';
import { useMemoizedFn } from '@/hooks';
import React, { useMemo } from 'react';
import type { BusterCollectionListItem } from '@/api/asset_interfaces/collection';
import { NewCollectionModal } from '../modal/NewCollectionModal';
import { Plus } from '@/components/ui/icons';
import { Button } from '@/components/ui/buttons';
import { useGetCollectionsList } from '@/api/buster_rest/collections';
export const SaveToCollectionsDropdown: React.FC<{
children: React.ReactNode;
selectedCollections: string[];
onSaveToCollection: (collectionId: string[]) => Promise<void>;
onRemoveFromCollection: (collectionId: string) => Promise<void>;
}> = React.memo(({ children, onRemoveFromCollection, onSaveToCollection, selectedCollections }) => {
const { data: collectionsList, isPending: isCreatingCollection } = useGetCollectionsList({});
const onChangePage = useAppLayoutContextSelector((s) => s.onChangePage);
const [openCollectionModal, setOpenCollectionModal] = React.useState(false);
const [showDropdown, setShowDropdown] = React.useState(false);
const items: DropdownProps['items'] = useMemo(() => {
const collectionsItems = (collectionsList || []).map<DropdownItem>((collection) => {
return {
value: collection.id,
label: collection.name,
selected: selectedCollections.some((id) => id === collection.id),
onClick: () => onClickItem(collection),
link: createBusterRoute({
route: BusterRoutes.APP_COLLECTIONS_ID,
collectionId: collection.id
})
};
});
return collectionsItems;
}, [collectionsList, selectedCollections]);
const onClickItem = useMemoizedFn((collection: BusterCollectionListItem) => {
const isSelected = selectedCollections.some((id) => id === collection.id);
if (isSelected) {
onRemoveFromCollection(collection.id);
} else {
const allCollectionsAndSelected = selectedCollections.map((id) => id).concat(collection.id);
onSaveToCollection(allCollectionsAndSelected);
}
});
const onCollectionCreated = useMemoizedFn(async (collectionId: string) => {
await onSaveToCollection([collectionId]);
onChangePage({
route: BusterRoutes.APP_COLLECTIONS_ID,
collectionId
});
});
const onCloseCollectionModal = useMemoizedFn(() => {
setOpenCollectionModal(false);
setShowDropdown(false);
});
const onOpenChange = useMemoizedFn((open: boolean) => {
setShowDropdown(open);
});
const onOpenNewCollectionModal = useMemoizedFn(() => {
setOpenCollectionModal(true);
setShowDropdown(false);
});
const memoizedButton = useMemo(() => {
return (
<Button
variant="ghost"
block
loading={isCreatingCollection}
className="justify-start!"
prefix={<Plus />}
onClick={onOpenNewCollectionModal}>
New collection
</Button>
);
}, [onOpenNewCollectionModal]);
return (
<>
<Dropdown
side="bottom"
align="center"
menuHeader={items.length > 0 ? 'Save to a collection' : undefined}
onOpenChange={onOpenChange}
footerContent={memoizedButton}
emptyStateText="No collections found"
items={items}>
<AppTooltip title={showDropdown ? '' : 'Save to collection'}>{children} </AppTooltip>
</Dropdown>
<NewCollectionModal
open={openCollectionModal}
onClose={onCloseCollectionModal}
useChangePage={false}
onCollectionCreated={onCollectionCreated}
/>
</>
);
});
SaveToCollectionsDropdown.displayName = 'SaveToCollectionsDropdown';