All files / libs/payout-definition/plans/components/src/lib/assigned-plans-dropdown-list AssignedPlansDropdownList.tsx

0% Statements 0/107
0% Branches 0/1
0% Functions 0/1
0% Lines 0/107

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108                                                                                                                                                                                                                       
import { partition } from 'lodash-es';
import { memo, useCallback, useMemo } from 'react';
import { FormattedMessage } from 'react-intl';
import { generatePath } from 'react-router-dom';

import {
  Button,
  ButtonLink,
  DropdownList,
  type DropdownListItem,
  type DropdownListProps,
} from '@allshares/studio-design-system';
import { routes } from '@amalia/core/routes';
import { useBoolState } from '@amalia/ext/react/hooks';
import { Link } from '@amalia/ext/react-router-dom';
import { canModifyPlans } from '@amalia/kernel/auth/shared';
import { useAbilityContext } from '@amalia/kernel/auth/state';
import { type Plan } from '@amalia/payout-definition/plans/types';

import { IconPlanVisibility } from '../plan-visibility/icons/IconPlanVisibility';

export type OnClickPlan = (planId: string) => Promise<void>;

export type AssignedPlansDropdownListProps = Omit<DropdownListProps, 'items'> & {
  readonly plans: Pick<Plan, 'archived' | 'id' | 'isHidden' | 'name'>[];
  readonly onClickPlan?: OnClickPlan;
};

export const AssignedPlansDropdownList = memo(function AssignedPlansDropdownList({
  plans,
  children,
  onClickPlan,
  ...props
}: AssignedPlansDropdownListProps) {
  const ability = useAbilityContext();

  const { isLoading, setLoadingTrue, setLoadingFalse } = useBoolState(false, 'loading');

  const handleClickPlan = useCallback(
    async (planId: string) => {
      try {
        setLoadingTrue();
        await onClickPlan?.(planId);
      } finally {
        setLoadingFalse();
      }
    },
    [onClickPlan, setLoadingTrue, setLoadingFalse],
  );

  const mapPlanToListItem = useCallback(
    (plan: AssignedPlansDropdownListProps['plans'][number]): DropdownListItem => ({
      icon: <IconPlanVisibility isPlanHidden={plan.isHidden} />,
      key: plan.id,
      label: plan.name,
      rightActions:
        canModifyPlans(ability) &&
        (onClickPlan ? (
          <Button
            disabled={isLoading}
            size="small"
            variant="primary-text"
            onClick={() => handleClickPlan(plan.id)}
          >
            <FormattedMessage defaultMessage="View" />
          </Button>
        ) : (
          <ButtonLink
            size="small"
            variant="primary-text"
            to={
              <Link
                openInNewTab
                to={generatePath(routes.PLAN_HUB_RULES, { planId: plan.id })}
              />
            }
          >
            <FormattedMessage defaultMessage="View" />
          </ButtonLink>
        )),
    }),
    [isLoading, ability, handleClickPlan, onClickPlan],
  );

  const plansListItems = useMemo(() => {
    const [activePlans, archivedPlans] = partition(plans, (plan) => !plan.archived);

    return [
      ...activePlans.map(mapPlanToListItem),
      {
        label: <FormattedMessage defaultMessage="Archived plans" />,
        items: archivedPlans.map(mapPlanToListItem),
        initialIsOpen: false,
      },
    ];
  }, [plans, mapPlanToListItem]);

  return (
    <DropdownList
      {...props}
      disabled={props.disabled || !plansListItems.length}
      items={plansListItems}
    >
      {children}
    </DropdownList>
  );
});