hunk.code_window:           onClose={onConditionsClose}
             updateConditions={updateConditions}
             conditions={conditions}
             filterPartsList={filterPartsList}
             defaultFilter={FilterPartTypeEnum.PAYLOAD}
           />
         )}
         <DeleteConfirmModal
           description={
  
hunk.labels: keep keep keep keep add keep keep keep keep keep
hunk.after_edit:           shouldDisallowEmptyConditions
  
hunk.file_path: apps/web/src/pages/templates/components/EditorSidebarHeaderActions.tsx
hunk.type: add
file: import { Grid, Group, ActionIcon, Center, useMantineTheme } from '@mantine/core';
  import styled from '@emotion/styled';
  import { Control, Controller, useFieldArray, useForm, useWatch } from 'react-hook-form';
  import { FilterPartTypeEnum, IFieldFilterPart, FieldLogicalOperatorEnum, FieldOperatorEnum } from '@novu/shared';
  import {
    Button,
    colors,
    Dropdown,
    Input,
    Select,
    Sidebar,
    Text,
    Title,
    Tooltip,
    ConditionPlus,
    DotsHorizontal,
    Duplicate,
    Trash,
    Condition,
    ErrorIcon,
    When,
  } from '@novu/design-system';
  
  import { DataSelect, IConditions, IConditionsForm, IConditionsProps, IFilterTypeList } from './types';
  import { OnlineConditionRow } from './OnlineConditionRow';
  import { DefaultGroupOperatorData, DefaultOperatorData } from './constants';
  import { PreviousStepsConditionRow } from './PreviousStepsConditionRow';
  
  export function Conditions({
    isOpened,
    isReadonly = false,
    conditions,
    onClose,
    updateConditions,
    name,
    label = '',
    filterPartsList,
    defaultFilter,
  }: {
    isOpened: boolean;
    isReadonly?: boolean;
    onClose: () => void;
    updateConditions: (data: IConditions[]) => void;
    conditions?: IConditions[];
    name: string;
    label?: string;
    filterPartsList: IFilterTypeList[];
    defaultFilter?: FilterPartTypeEnum;
  }) {
    const { colorScheme } = useMantineTheme();
  
    const {
      control,
      getValues,
      trigger,
      formState: { errors, isValid, isDirty },
    } = useForm<IConditionsForm>({
      defaultValues: { conditions },
      mode: 'onChange',
    });
  
    const defaultOnFilter = defaultFilter ?? filterPartsList[0].value;
  
    const { fields, append, remove, insert, update } = useFieldArray({
      control,
      name: `conditions.0.children` as 'conditions.0.children',
    });
  
    const filterPartTypeList = filterPartsList?.map(({ value, label: filterLabel }) => {
      return {
        value,
        label: filterLabel,
      };
    });
  
    function handleOnChildOnChange(index: number) {
      return (data) => {
        const { id: _, ...rest } = fields[index];
  
        if (data === FilterPartTypeEnum.IS_ONLINE) {
          update(index, { ...rest, on: data, value: true });
  
          return;
        }
  
        update(index, { ...rest, on: data });
      };
    }
  
    function handleDuplicate(index: number) {
      insert(index + 1, getValues(`conditions.0.children.${index}`));
    }
  
    function handleDelete(index: number) {
      remove(index);
    }
  
    const onApplyConditions = async () => {
      await trigger('conditions');
      if (!errors.conditions) {
        updateConditions(getValues('conditions'));
        onClose();
      }
    };
  
    return (
      <Sidebar
        isOpened={isOpened}
        onClose={onClose}
        isExpanded
        customHeader={
          <Center inline>
            <Condition color={colorScheme === 'dark' ? colors.white : colors.B30} />
            <Title ml={8} size={2} data-test-id="conditions-form-title">
              Conditions for {name} {label}
            </Title>
          </Center>
        }
        customFooter={
          <Group ml="auto">
            <Button variant="outline" onClick={onClose} data-test-id="conditions-form-cancel-btn">
              Cancel
            </Button>
            <Tooltip position="top" error disabled={isValid} label={'Some conditions are missing values'}>
              <div>
                <Button
                  disabled={!isDirty || isReadonly || (conditions?.length === 0 && fields?.length === 0)}
                  onClick={onApplyConditions}
                  data-test-id="apply-conditions-btn"
                >
                  Apply conditions
                </Button>
              </div>
            </Tooltip>
          </Group>
        }
        styles={{ body: { '.sidebar-body-holder': { height: '100%' } }, root: { zIndex: 300 } }}
      >
        <div>
          {fields.map((item, index) => {
            const filterFieldOn = item.on;
  
            const customData = filterPartsList?.find((filter) => filter.value === filterFieldOn)?.data;
  
            return (
              <div data-test-id="conditions-form-item" key={item.id}>
                <Grid align={'center'}>
                  <Grid.Col span={'auto'}>
                    <Grid columns={21} align="center" gutter={8}>
                      <Grid.Col span={2} miw={120}>
                        {index > 0 ? (
                          <Wrapper>
                            <Controller
                              control={control}
                              name={`conditions.0.value`}
                              defaultValue={FieldLogicalOperatorEnum.AND}
                              render={({ field }) => {
                                return (
                                  <Select
                                    data={DefaultGroupOperatorData}
                                    {...field}
                                    disabled={isReadonly}
                                    data-test-id="conditions-form-value-dropdown"
                                  />
                                );
                              }}
                            />
                          </Wrapper>
                        ) : (
                          <Text ml={14} color={colors.B60}>
                            When
                          </Text>
                        )}
                      </Grid.Col>
                      <Grid.Col span={3}>
                        <Controller
                          control={control}
                          name={`conditions.0.children.${index}.on`}
                          defaultValue={defaultOnFilter}
                          render={({ field }) => {
                            return (
                              <Select
                                placeholder="On"
                                data={filterPartTypeList}
                                {...field}
                                onChange={handleOnChildOnChange(index)}
                                disabled={isReadonly}
                                data-test-id="conditions-form-on"
                              />
                            );
                          }}
                        />
                      </Grid.Col>
                      <When truthy={filterFieldOn === FilterPartTypeEnum.WEBHOOK}>
                        <WebHookUrlForm control={control} index={index} isReadonly={isReadonly} />
                        <EqualityForm webhook control={control} index={index} isReadonly={isReadonly} />
                      </When>
                      <When truthy={filterFieldOn === FilterPartTypeEnum.PREVIOUS_STEP}>
                        <PreviousStepsConditionRow
                          customData={customData}
                          control={control}
                          index={index}
                          isReadonly={isReadonly}
                        />
                      </When>
                      <When
                        truthy={[FilterPartTypeEnum.IS_ONLINE, FilterPartTypeEnum.IS_ONLINE_IN_LAST].includes(
                          filterFieldOn
                        )}
                      >
                        <OnlineConditionRow
                          fieldOn={filterFieldOn}
                          control={control}
                          index={index}
                          isReadonly={isReadonly}
                        />
                      </When>
                      <When
                        truthy={[
                          FilterPartTypeEnum.PAYLOAD,
                          FilterPartTypeEnum.SUBSCRIBER,
                          FilterPartTypeEnum.TENANT,
                        ].includes(filterFieldOn)}
                      >
                        <EqualityForm customData={customData} control={control} index={index} isReadonly={isReadonly} />
                      </When>
                    </Grid>
                  </Grid.Col>
                  <ConditionRowMenu
                    onDuplicate={() => handleDuplicate(index)}
                    onDelete={() => handleDelete(index)}
                    isReadonly={isReadonly}
                  />
                </Grid>
              </div>
            );
          })}
        </div>
  
        <Group position="left" mb={8}>
          <Button
            variant="outline"
            onClick={() => {
              append({
                operator: FieldOperatorEnum.EQUAL,
                on: defaultOnFilter,
              } as IFieldFilterPart);
            }}
            icon={<ConditionPlus style={{ color: colorScheme === 'dark' ? colors.white : colors.gradientMiddle }} />}
            disabled={isReadonly}
            data-test-id="add-new-condition"
          >
            Add condition
          </Button>
        </Group>
      </Sidebar>
    );
  }
  
  function EqualityForm({
    control,
    index,
    webhook = false,
    isReadonly = false,
    customData,
  }: {
    control: Control<IConditionsForm>;
    index: number;
    webhook?: boolean;
    isReadonly?: boolean;
    customData?: DataSelect[];
  }) {
    const operator = useWatch({
      control,
      name: `conditions.0.children.${index}.operator`,
    });
  
    return (
      <>
        <Grid.Col span={webhook ? 3 : 4}>
          <Controller
            control={control}
            name={`conditions.0.children.${index}.field`}
            rules={{ required: true }}
            defaultValue=""
            render={({ field, fieldState }) => {
              return (
                <Input
                  placeholder="Key"
                  {...field}
                  rightSection={<RightSectionError showError={!!fieldState.error} label="Key is missing" />}
                  error={!!fieldState.error}
                  disabled={isReadonly}
                  data-test-id="conditions-form-key"
                />
              );
            }}
          />
        </Grid.Col>
        <Grid.Col span={3}>
          <Controller
            control={control}
            name={`conditions.0.children.${index}.operator`}
            defaultValue={FieldOperatorEnum.EQUAL}
            render={({ field }) => {
              return (
                <Select
                  placeholder="Operator"
                  data={customData ?? DefaultOperatorData}
                  {...field}
                  disabled={isReadonly}
                  data-test-id="conditions-form-operator"
                />
              );
            }}
          />
        </Grid.Col>
  
        <Grid.Col span="auto">
          {operator !== FieldOperatorEnum.IS_DEFINED && (
            <Controller
              control={control}
              name={`conditions.0.children.${index}.value`}
              defaultValue=""
              rules={{ required: true }}
              render={({ field, fieldState }) => {
                return (
                  <Input
                    {...field}
                    value={field.value as string}
                    rightSection={<RightSectionError showError={!!fieldState.error} label={'Value is missing'} />}
                    error={!!fieldState.error}
                    placeholder="Value"
                    disabled={isReadonly}
                    data-test-id="conditions-form-value"
                  />
                );
              }}
            />
          )}
        </Grid.Col>
      </>
    );
  }
  
  function WebHookUrlForm({ control, index, isReadonly = false }: IConditionsProps) {
    return (
      <>
        <Grid.Col span={4}>
          <Controller
            control={control}
            name={`conditions.0.children.${index}.webhookUrl`}
            defaultValue=""
            rules={{ required: true }}
            render={({ field, fieldState }) => {
              return (
                <Input
                  {...field}
                  rightSection={<RightSectionError showError={!!fieldState.error} label="Url is missing" />}
                  error={!!fieldState.error}
                  placeholder="Url"
                  disabled={isReadonly}
                  data-test-id="webhook-filter-url-input"
                />
              );
            }}
          />
        </Grid.Col>
      </>
    );
  }
  
  export function RightSectionError({ showError, label }: { showError: boolean; label: string }) {
    return (
      <When truthy={showError}>
        <Tooltip opened data-test-id="conditions-form-tooltip-error" error position="top" offset={15} label={label}>
          <span>
            <ErrorIcon data-test-id="conditions-form-value-error" color={colors.error} />
          </span>
        </Tooltip>
      </When>
    );
  }
  
  function ConditionRowMenu({
    isReadonly,
    onDuplicate,
    onDelete,
  }: {
    onDuplicate: () => void;
    onDelete: () => void;
    isReadonly?: boolean;
  }) {
    return (
      <Grid.Col span={'content'}>
        <Dropdown
          withArrow={false}
          offset={0}
          control={
            <ActionIcon data-test-id="conditions-row-btn" variant={'transparent'}>
              <DotsHorizontal color={colors.B60} />
            </ActionIcon>
          }
          middlewares={{ flip: false, shift: false }}
          position="bottom-end"
          disabled={isReadonly}
        >
          <Dropdown.Item data-test-id="conditions-row-duplicate" onClick={onDuplicate} icon={<Duplicate />}>
            Duplicate
          </Dropdown.Item>
          <Dropdown.Item data-test-id="conditions-row-delete" onClick={onDelete} icon={<Trash />}>
            Delete
          </Dropdown.Item>
        </Dropdown>
      </Grid.Col>
    );
  }
  
  const Wrapper = styled.div`
    .mantine-Select-wrapper:not(:hover) {
      .mantine-Select-input {
        border-color: transparent;
        color: ${colors.B60};
      }
      .mantine-Input-rightSection.mantine-Select-rightSection {
        svg {
          display: none;
        }
      }
    }
  `;
  