teableio/teable

View on GitHub
apps/nextjs-app/src/features/app/blocks/setting/components/ScopesSelect.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import { actionPrefixMap } from '@teable/core';
import type { ActionPrefix, Action } from '@teable/core';
import { usePermissionActionsStatic } from '@teable/sdk/hooks';
import { Checkbox, Label } from '@teable/ui-lib/shadcn';
import { useMemo, useState } from 'react';

interface IScopesSelectProps {
  initValue?: Action[];
  onChange?: (value: string[]) => void;
  actionsPrefixes?: ActionPrefix[];
}

export const ScopesSelect = (props: IScopesSelectProps) => {
  const { onChange, initValue, actionsPrefixes } = props;
  const [value, setValue] = useState<Record<Action, boolean>>(() => {
    if (initValue) {
      return initValue.reduce(
        (acc, cur) => {
          acc[cur] = true;
          return acc;
        },
        {} as Record<Action, boolean>
      );
    }
    return {} as Record<Action, boolean>;
  });
  const { actionPrefixStaticMap, actionStaticMap } = usePermissionActionsStatic();

  const onCheckBoxChange = (status: boolean, val: Action) => {
    const actionMap = { ...value };
    actionMap[val] = status;
    setValue(actionMap);
    const actions = Object.keys(actionMap).filter((key) => actionMap[key as Action]);
    onChange?.(actions);
  };

  const actionsPrefix = useMemo(() => {
    if (actionsPrefixes) {
      return Object.keys(actionPrefixStaticMap).filter((key) =>
        actionsPrefixes.includes(key as ActionPrefix)
      ) as ActionPrefix[];
    }
    return Object.keys(actionPrefixStaticMap) as ActionPrefix[];
  }, [actionPrefixStaticMap, actionsPrefixes]);

  return (
    <div className="space-y-3 pl-2">
      {actionsPrefix.map((actionPrefix) => {
        const actions = actionPrefixMap[actionPrefix];
        return (
          <div key={actionPrefix} className="space-y-1">
            <Label>{actionPrefixStaticMap[actionPrefix].title}</Label>
            <div className="flex gap-3">
              {actions.map((action) => (
                <div className="flex items-center gap-1 text-sm" key={action}>
                  <Checkbox
                    id={action}
                    value={action}
                    checked={value[action]}
                    onCheckedChange={(val: boolean) => {
                      onCheckBoxChange(val, action);
                    }}
                  />
                  <Label htmlFor={action} className="text-xs font-normal">
                    {actionStaticMap[action].description}
                  </Label>
                </div>
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
};