Untitled

 avatar
unknown
plain_text
2 months ago
7.7 kB
2
Indexable

  .rct-tree-item-li {
    list-style: none;
    border-radius: 4px;
    margin: 2px 0;
  }

  .rct-tree-item-title-container {
    display: flex;
    align-items: center;
    min-height: var(--rct-item-height, 32px);
    padding-right: 8px;
    border-radius: 4px;
  }

  .rct-tree-item-button-container {
    display: flex;
    align-items: center;
    flex: 1;
    min-width: 0; /* Prevents flex items from overflowing */
  }

  .rct-tree-item-button {
    display: flex;
    align-items: center;
    background: none;
    border: none;
    padding: 4px 8px;
    font: inherit;
    cursor: pointer;
    text-align: left;
    min-width: 0;
  }


  .rct-tree-item-title-container .rct-tree-item-arrow {
    margin-right: 4px;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

/* eslint-disable @typescript-eslint/no-unused-vars */
import React, { useState } from 'react';
import { observer } from 'mobx-react-lite';
import { useRootStore } from '../../providers/root-store-provider';
import { ControlledTreeEnvironment, Tree, TreeItem, TreeItemIndex, TreeItemRenderContext } from 'react-complex-tree';
import { VisibilityOff, Visibility, Edit } from '@mui/icons-material';
import { IconButton, Link, Paper } from '@mui/material';
import 'react-complex-tree/lib/style-modern.css';
import { CategoryNodeData } from 'models/stores/category-store';
import {
    TreeItemContainer,
    ItemTitle,
    ActionsContainer,
    ShowProductsLink,
    ProductCount,
    TreeContainer,
} from './categories-tree.styled';

const combineClasses = (...classes: (string | boolean | undefined)[]) => {
    return classes.filter(Boolean).join(' ');
};

export const CategoriesTree: React.FC = observer(() => {
    const rootStore = useRootStore();
    const { categoryStore } = rootStore;
    console.log(categoryStore.treeData);

    const renderItem = ({
        item,
        depth,
        children,
        arrow,
        context,
    }: {
        item: TreeItem<CategoryNodeData | null>;
        depth: number;
        children: React.ReactNode;
        arrow: React.ReactNode;
        context: TreeItemRenderContext;
    }) => {
        const category = item.data;
        if (!category) return null;

        const InteractiveComponent = context.isRenaming ? 'div' : 'button';
        const type = context.isRenaming ? undefined : 'button';

        return (
            <li
                {...context.itemContainerWithChildrenProps}
                className={combineClasses(
                    'rct-tree-item-li',
                    context.isSelected && 'rct-tree-item-li-selected',
                    context.isFocused && 'rct-tree-item-li-focused',
                    context.isDraggingOver && 'rct-tree-item-li-dragging-over',
                )}
                style={{ '--rct-item-height': '32px' } as React.CSSProperties}
            >
                <div
                    {...context.itemContainerWithoutChildrenProps}
                    className={combineClasses(
                        'rct-tree-item-title-container',
                        context.isSelected && 'rct-tree-item-title-container-selected',
                        context.isFocused && 'rct-tree-item-title-container-focused',
                        context.isDraggingOver && 'rct-tree-item-title-container-dragging-over',
                    )}
                    // This maintains proper indentation
                    style={{ paddingLeft: `${depth * 20}px` }}
                >
                    <div className="rct-tree-item-button-container">
                        {arrow}
                        <InteractiveComponent
                            {...context.interactiveElementProps}
                            type={type}
                            className={combineClasses(
                                'rct-tree-item-button',
                                context.isSelected && 'rct-tree-item-button-selected',
                                context.isFocused && 'rct-tree-item-button-focused',
                            )}
                        >
                            <ItemTitle>{category.name}</ItemTitle>
                            <ProductCount>({category.productIds.length})</ProductCount>
                        </InteractiveComponent>
                    </div>
                    <ActionsContainer>
                        <ShowProductsLink as={Link} href={''}>
                            Zobrazit produkty
                        </ShowProductsLink>
                        <IconButton size="small" disabled={!category.parentId}>
                            {category.isActive ? <Visibility /> : <VisibilityOff />}
                        </IconButton>
                        <IconButton size="small" disabled={!category.parentId}>
                            <Edit />
                        </IconButton>
                    </ActionsContainer>
                </div>
                {children}
            </li>
        );
    };

    return (
        <Paper>
            <ControlledTreeEnvironment
                items={categoryStore.treeData}
                getItemTitle={(item) => item.data?.name ?? 'Root'}
                viewState={{
                    categories: {
                        focusedItem: categoryStore.focusedItem,
                        expandedItems: categoryStore.expandedItems,
                        selectedItems: categoryStore.selectedItems,
                    },
                }}
                onFocusItem={(item) => categoryStore.setFocusedItem(item.index)}
                onExpandItem={(item) => categoryStore.toggleExpandedItem(item.index)}
                onCollapseItem={(item) => categoryStore.toggleExpandedItem(item.index)}
                onSelectItems={(items) => categoryStore.setSelectedItems(items)}
                renderItem={renderItem}
            >
                <Tree treeId="categories" rootItem="root" />
            </ControlledTreeEnvironment>
        </Paper>
    );
});

import { styled } from '@mui/material/styles';
import { alpha } from '@mui/material';

export const TreeContainer = styled('div')(({ theme }) => ({
    height: 500,
    '& .rct-tree-item-arrow': {
        color: theme.palette.grey[500],
        transition: 'transform 0.2s',
        marginRight: 8,
        '& svg': {
            width: '14px',
            height: '14px',
        },
    },
    '& .rct-tree-item-title-container': {
        display: 'flex',
        alignItems: 'center',
        width: '100%',
        padding: theme.spacing(1),
        '&:hover': {
            backgroundColor: alpha(theme.palette.warning.light, 0.1),
        },
    },
}));

export const TreeItemContainer = styled('div')<{ depth: number }>(({ theme, depth }) => ({
    display: 'flex',
    alignItems: 'center',
    margin: `8px 8px 8px ${depth * 20}px`,
    width: `calc(100% - ${depth * 20}px)`,
    transition: 'background-color 0.2s',
    '&:hover': {
        backgroundColor: alpha(theme.palette.warning.light, 0.1),
    },
}));

export const ItemTitle = styled('span')({
    display: 'inline-block',
    marginRight: 8,
});

export const ProductCount = styled('span')(({ theme }) => ({
    color: theme.palette.primary.main,
    fontWeight: 'bold',
    display: 'inline-block',
}));

export const ActionsContainer = styled('div')({
    display: 'flex',
    gap: 10,
    alignItems: 'center',
    marginLeft: 'auto',
    flexShrink: 0,
});

export const ShowProductsLink = styled('a')(({ theme }) => ({
    color: theme.palette.primary.main,
    fontSize: '0.75rem',
    textDecoration: 'underline',
    '&:hover': {
        color: theme.palette.primary.dark,
    },
}));

Editor is loading...
Leave a Comment