vdelacou/iblis-ui

View on GitHub
src/components/ui_components/account_menu/index.tsx

Summary

Maintainability
A
1 hr
Test Coverage
import { Divider, Grid, List, ListItem, ListItemIcon, ListItemText, Paper, WithStyles, withStyles, WithTheme, withTheme } from '@material-ui/core';
import { SvgIconProps } from '@material-ui/core/SvgIcon';
import * as React from 'react';
import { ClassKey, createSytle, style } from './style';

export interface AccountMenuLevelProps {
    /**
     * The text to display in the menu item
     */
    name: string;
    /**
     * The icon to display for the menu item
     */
    icon?: React.ReactElement<SvgIconProps>;
    /**
     * The action when click on menu item
     */
    action: () => void;
}

export interface AccountMenuProps {
    /**
     * The account card Component to display
     */
    accountComponent: React.ReactNode;
    /**
     * The account menu between the account card and sign out button
     */
    accountMenu?: AccountMenuLevelProps[];
    /**
     * The sign out text
     */
    signOutText: string;
    /**
     * The sign out icon
     */
    signOutIcon?: React.ReactElement<SvgIconProps>;
    /**
     * The sign out action
     */
    signOutAction: () => void;
}

const AccountMenuBase: React.StatelessComponent<AccountMenuProps & WithTheme & WithStyles<ClassKey>> = (props) => {

    const { accountComponent, accountMenu, signOutText, signOutIcon, signOutAction, classes, theme } = props;

    return (
        <Grid container={true} style={style(theme).lastMenuPortalContainer}>
            <Paper>
                <div style={style(theme).lastMenuPortalPaper}>
                    {accountComponent}
                </div>
                <Divider />
                <List style={style(theme).lastMenuPortalPaperList}>
                    {/* Display all the menus if needed*/}
                    {renderMenu(accountMenu)}
                    {/* Display the logout button */}
                    <ListItem button={true} onClick={() => signOutAction()} >
                        {renderLogoutIcon(classes, signOutIcon)}
                        <ListItemText primary={signOutText} />
                    </ListItem>
                </List>
            </Paper>
        </Grid>
    );
};

const renderMenu = (accountMenu?: AccountMenuLevelProps[]) => {
    if (accountMenu) {
        return accountMenu.map((
            menuItem: AccountMenuLevelProps,
            index: number) => {
            return (
                <div key={index}>
                    <ListItem button={true} onClick={() => menuItem.action()}>
                        {renderMenuItemIcon(menuItem)}
                        <ListItemText primary={menuItem.name} />
                    </ListItem>
                    <Divider />
                </div>
            );
        });
    }
    return null;
};

const renderMenuItemIcon = (menuItem: AccountMenuLevelProps) => {
    if (menuItem.icon) {
        return (
            <ListItemIcon>
                {menuItem.icon}
            </ListItemIcon>
        );
    }
    return null;
};

const renderLogoutIcon = (classes: Record<ClassKey, string>, signOutIcon?: React.ReactElement<SvgIconProps>) => {
    if (signOutIcon) {
        return (
            <ListItemIcon classes={{ root: classes.signOutButton }}>
                {signOutIcon}
            </ListItemIcon>
        );
    }
    return null;
};

const AccountMenuWithStyle: React.ComponentType<AccountMenuProps> = withStyles(createSytle)(AccountMenuBase);
const AccountMenuWithTheme: React.ComponentType<AccountMenuProps> = withTheme()(AccountMenuWithStyle);
/**
 * Display a menu with account card and logout button
 */
export const AccountMenu: React.ComponentType<AccountMenuProps> = (AccountMenuWithTheme);