create page working

PHOTO EMBED

Mon May 26 2025 15:39:06 GMT+0000 (Coordinated Universal Time)

Saved by @krisha_joshi

import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { McButton, McInput, McMultiSelect } from '@maersk-global/mds-react-wrapper';
import { McSelect } from '@maersk-global/mds-react-wrapper/components-core/mc-select';
import { McOption } from '@maersk-global/mds-react-wrapper/components-core/mc-option';
import styles from '../styles/CreateRule.module.css';
import data from '../data/PnLGroup.json';

const CreateRules = () => {
  const navigate = useNavigate();
  const [activeTab, setActiveTab] = useState('ruleInfo');
  const [isLoading, setIsLoading] = useState(false);
  const [ruleData, setRuleData] = useState({
    num: '',
    name: '',
    desc: '',
    custRefID: '',
    ruleGroup: '',
    isActive: 'Y',
    pnlGroup: '',
  });
  const [steps, setSteps] = useState([
    {
      stepNo: '',
      stepName: 'Single Step',
      StepDesc: '',
      stepType: 'S',
      preAggregatorColumns: '',
      sourceTable: '',
      sourceFilters: '',
      joinColumns: '',
      allocationColumns: '',
      driverTableID: '',
      driverWeightColumn: '',
      driverFilters: '',
    },
  ]);
  const [errors, setErrors] = useState({ rule: {}, steps: [{}] });

  const pnlGroups = data.PnLGroups ? Object.keys(data.PnLGroups) : [];
  const ruleGroups = ruleData.pnlGroup && data.PnLGroups[ruleData.pnlGroup]
    ? data.PnLGroups[ruleData.pnlGroup].RuleGroups || []
    : [];

  console.log('pnlGroups:', pnlGroups);
  console.log('ruleGroups:', ruleGroups);

  const addStep = () => {
    setSteps((prevSteps) => [
      ...prevSteps,
      {
        stepNo: '',
        stepName: 'Single Step',
        StepDesc: '',
        stepType: 'S',
        preAggregatorColumns: '',
        sourceTable: '',
        sourceFilters: '',
        joinColumns: '',
        allocationColumns: '',
        driverTableID: '',
        driverWeightColumn: '',
        driverFilters: '',
      },
    ]);
    setErrors((prevErrors) => ({
      ...prevErrors,
      steps: [...prevErrors.steps, {}],
    }));
  };

  const removeStep = (index) => {
    if (steps.length === 1) {
      alert('At least one step is required.');
      return;
    }
    setSteps((prevSteps) => prevSteps.filter((_, i) => i !== index));
    setErrors((prevErrors) => ({
      ...prevErrors,
      steps: prevErrors.steps.filter((_, i) => i !== index),
    }));
  };

  const validateForm = () => {
    const newErrors = { rule: {}, steps: steps.map(() => ({})) };
    let isValid = true;

    if (!ruleData.num) {
      newErrors.rule.num = 'Rule Number is required';
      isValid = false;
    } else if (!/^[a-zA-Z0-9]+$/.test(ruleData.num)) {
      newErrors.rule.num = 'Rule Number must be alphanumeric';
      isValid = false;
    }
    if (!ruleData.name) {
      newErrors.rule.name = 'Rule Name is required';
      isValid = false;
    }
    if (!ruleData.desc) {
      newErrors.rule.desc = 'Description is required';
      isValid = false;
    }
    if (!ruleData.custRefID) {
      newErrors.rule.custRefID = 'Customer Reference ID is required';
      isValid = false;
    }
    if (!ruleData.pnlGroup) {
      newErrors.rule.pnlGroup = 'PnL Group is required';
      isValid = false;
    }
    if (!ruleData.ruleGroup) {
      newErrors.rule.ruleGroup = 'Rule Group is required';
      isValid = false;
    }
    if (!ruleData.isActive) {
      newErrors.rule.isActive = 'Active status is required';
      isValid = false;
    }

    const stepNumbers = new Set();
    steps.forEach((step, index) => {
      const stepErrors = {};
      if (!step.stepNo) {
        stepErrors.stepNo = 'Step Number is required';
        isValid = false;
      } else if (stepNumbers.has(step.stepNo)) {
        stepErrors.stepNo = 'Step Number must be unique';
        isValid = false;
      } else {
        stepNumbers.add(step.stepNo);
      }
      if (!step.stepName) {
        stepErrors.stepName = 'Step Name is required';
        isValid = false;
      }
      if (!step.StepDesc) {
        stepErrors.StepDesc = 'Step Description is required';
        isValid = false;
      }
      if (!step.stepType) {
        stepErrors.stepType = 'Step Type is required';
        isValid = false;
      }
      if (!step.preAggregatorColumns) {
        stepErrors.preAggregatorColumns = 'Pre-Aggregator Columns are required';
        isValid = false;
      }
      if (!step.sourceTable) {
        stepErrors.sourceTable = 'Source Table is required';
        isValid = false;
      }
      if (!step.sourceFilters) {
        stepErrors.sourceFilters = 'Source Filters are required';
        isValid = false;
      } else {
        try {
          parseFilters(step.sourceFilters);
        } catch (e) {
          stepErrors.sourceFilters = 'Invalid Source Filter format';
          isValid = false;
        }
      }
      if (!step.joinColumns) {
        stepErrors.joinColumns = 'Join Columns are required';
        isValid = false;
      }
      if (!step.allocationColumns) {
        stepErrors.allocationColumns = 'Allocation Columns are required';
        isValid = false;
      }
      if (!step.driverTableID) {
        stepErrors.driverTableID = 'Driver Table ID is required';
        isValid = false;
      }
      if (!step.driverWeightColumn) {
        stepErrors.driverWeightColumn = 'Driver Weight Column is required';
        isValid = false;
      }
      if (!step.driverFilters) {
        stepErrors.driverFilters = 'Driver Filters are required';
        isValid = false;
      } else {
        try {
          parseFilters(step.driverFilters);
        } catch (e) {
          stepErrors.driverFilters = 'Invalid Driver Filter format';
          isValid = false;
        }
      }
      newErrors.steps[index] = stepErrors;
    });

    setErrors(newErrors);
    return isValid;
  };

  const parseColumns = (input) => input.split(',').map((item) => item.trim()).filter((item) => item);

  const parseFilters = (input) => {
    if (!input) return [];
    const filters = input.split(';').map((item) => item.trim()).filter((item) => item);
    return filters.map((filter) => {
      const parts = filter.split(':').map((item) => item.trim());
      if (parts.length !== 3) {
        throw new Error('Invalid filter format');
      }
      const [name, filterType, values] = parts;
      if (!name || !filterType || !values) {
        throw new Error('Invalid filter format');
      }
      return { name, filterType, values };
    });
  };

  const handleInputChange = (e, stepIndex = null) => {
    const { name, value } = e.target;
    console.log(`Input changed: ${name} = ${value}${stepIndex !== null ? ` (Step ${stepIndex + 1})` : ''}`);

    if (stepIndex !== null) {
      setSteps((prevSteps) => {
        const newSteps = [...prevSteps];
        newSteps[stepIndex] = { ...newSteps[stepIndex], [name]: value };
        return newSteps;
      });
      setErrors((prevErrors) => ({
        ...prevErrors,
        steps: prevErrors.steps.map((stepErrors, i) =>
          i === stepIndex ? { ...stepErrors, [name]: '' } : stepErrors
        ),
      }));
    } else {
      setRuleData((prevData) => {
        const newData = {
          ...prevData,
          [name]: value,
          ...(name === 'pnlGroup' ? { ruleGroup: '' } : {}),
        };
        console.log('Updated ruleData:', newData);
        return newData;
      });
      setErrors((prevErrors) => ({
        ...prevErrors,
        rule: { ...prevErrors.rule, [name]: '' },
      }));
    }
  };

  const resetForm = () => {
    setRuleData({
      num: '',
      name: '',
      desc: '',
      custRefID: '',
      ruleGroup: '',
      isActive: 'Y',
      pnlGroup: '',
    });
    setSteps([
      {
        stepNo: '',
        stepName: 'Single Step',
        StepDesc: '',
        stepType: 'S',
        preAggregatorColumns: '',
        sourceTable: '',
        sourceFilters: '',
        joinColumns: '',
        allocationColumns: '',
        driverTableID: '',
        driverWeightColumn: '',
        driverFilters: '',
      },
    ]);
    setErrors({ rule: {}, steps: [{}] });
    setActiveTab('ruleInfo');
  };

  const handleSave = async () => {
    if (!validateForm()) {
      console.log('Validation failed:', JSON.stringify(errors, null, 2));
      alert('Please fill out all required fields.');
      return;
    }

    setIsLoading(true);

    const ruleJson = {
      rules: {
        rule: [
          {
            num: ruleData.num,
            name: ruleData.name,
            desc: ruleData.desc,
            custRefID: ruleData.custRefID,
            ruleGroup: ruleData.ruleGroup,
            isActive: ruleData.isActive,
            Step: steps.map((step, index) => ({
              stepNo: step.stepNo || `${ruleData.num}.${index + 1}`,
              stepName: step.stepName === 'Single Step' ? 'single' : 'multi',
              StepDesc: step.StepDesc,
              stepType: step.stepType,
              isActive: 'Y',
              SourceTable: {
                id: '1',
                Name: step.sourceTable,
              },
              sourceFilters: {
                columns: parseFilters(step.sourceFilters),
              },
              preAggregator: {
                columns: parseColumns(step.preAggregatorColumns),
              },
              join: {
                columns: parseColumns(step.joinColumns),
              },
              allocation: {
                columns: parseColumns(step.allocationColumns),
              },
              driver: {
                driverTableID: step.driverTableID,
                driverWeightColumn: step.driverWeightColumn,
                driverFilters: {
                  columns: parseFilters(step.driverFilters),
                },
              },
            })),
          },
        ],
      },
    };

    console.log('Saving Rule Data:', JSON.stringify(ruleJson, null, 2));

    try {
      const response = await fetch('/api/rules', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
        body: JSON.stringify(ruleJson),
      });

      if (response.ok) {
        console.log('Rule created successfully');
        alert('Rule created successfully!');
        resetForm();
        navigate('/');
      } else {
        const errorData = await response.json().catch(() => ({ message: response.statusText }));
        console.error('Failed to create rule:', response.status, errorData);
        alert(`Failed to create rule: ${errorData.message || response.statusText}`);
      }
    } catch (error) {
      console.error('Error during API call:', error.message);
      alert('An error occurred while saving the rule. Please try again.');
    } finally {
      setIsLoading(false);
    }
  };

  const handleCancel = () => {
    console.log('Cancelling rule creation');
    navigate('/');
  };

  const renderTabContent = () => {
    console.log('Rendering tab:', activeTab);
    switch (activeTab) {
      case 'ruleInfo':
        return (
          <div className={styles.tabContent}>
            {Object.values(errors.rule).some((error) => error) && (
              <div className={styles.errorSummary}>
                <h4>Please fix the following errors:</h4>
                <ul>
                  {Object.entries(errors.rule).map(([key, error]) => error && (
                    <li key={key}>{error}</li>
                  ))}
                </ul>
              </div>
            )}
            <h3 className={styles.sectionTitle}>Rule Information</h3>
            <div className={styles.formGrid}>
              <div className={styles.gridItem}>
                <McSelect
                  label="PnL Group"
                  name="pnlGroup"
                  value={ruleData.pnlGroup}
                  input={handleInputChange}
                  placeholder="Select a PnL Group"
                  required
                  invalid={!!errors.rule.pnlGroup}
                  invalidmessage={errors.rule.pnlGroup}
                >
                  {pnlGroups.map((group) => (
                    <McOption key={group} value={group}>
                      {group}
                    </McOption>
                  ))}
                </McSelect>
              </div>
              <div className={styles.gridItem}>
                <McSelect
                  label="Rule Group"
                  name="ruleGroup"
                  value={ruleData.ruleGroup}
                  input={handleInputChange}
                  placeholder={ruleGroups.length ? "Select a Rule Group" : "Select a PnL Group first"}
                  required
                  disabled={!ruleData.pnlGroup || !ruleGroups.length}
                  invalid={!!errors.rule.ruleGroup}
                  invalidmessage={errors.rule.ruleGroup}
                >
                  {ruleGroups.map((group) => (
                    <McOption key={group} value={group}>
                      {group}
                    </McOption>
                  ))}
                </McSelect>
              </div>
            </div>
            <div className={styles.inputGroup}>
              <McInput
                label="Rule Number"
                name="num"
                value={ruleData.num}
                input={handleInputChange}
                placeholder="Enter rule number"
                required
                invalid={!!errors.rule.num}
                invalidmessage={errors.rule.num}
              />
            </div>
            <div className={styles.inputGroup}>
              <McInput
                label="Rule Name"
                name="name"
                value={ruleData.name}
                input={handleInputChange}
                placeholder="Enter rule name"
                required
                invalid={!!errors.rule.name}
                invalidmessage={errors.rule.name}
              />
            </div>
            <div className={styles.inputGroup}>
              <McInput
                label="Description"
                name="desc"
                value={ruleData.desc}
                input={handleInputChange}
                placeholder="Enter rule description"
                multiline
                rows={3}
                required
                invalid={!!errors.rule.desc}
                invalidmessage={errors.rule.desc}
              />
            </div>
            <div className={styles.inputGroup}>
              <McInput
                label="Customer Reference ID"
                name="custRefID"
                value={ruleData.custRefID}
                input={handleInputChange}
                placeholder="Enter customer reference ID"
                required
                invalid={!!errors.rule.custRefID}
                invalidmessage={errors.rule.custRefID}
              />
            </div>
          </div>
        );
      case 'step':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Step Information</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Step Number"
                    name="stepNo"
                    value={step.stepNo}
                    input={(e) => handleInputChange(e, index)}
                    placeholder={`Enter step number (e.g., ${ruleData.num}.${index + 1})`}
                    required
                    invalid={!!errors.steps[index].stepNo}
                    invalidmessage={errors.steps[index].stepNo}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McSelect
                    label="Step Name"
                    name="stepName"
                    value={step.stepName}
                    input={(e) => handleInputChange(e, index)}
                    required
                    placeholder="Select Step Name"
                    invalid={!!errors.steps[index].stepName}
                    invalidmessage={errors.steps[index].stepName}
                  >
                    <McOption value="Single Step">Single Step</McOption>
                    <McOption value="Multi Step">Multi Step</McOption>
                  </McSelect>
                </div>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Step Description"
                    name="StepDesc"
                    value={step.StepDesc}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter step description"
                    multiline
                    rows={3}
                    required
                    invalid={!!errors.steps[index].StepDesc}
                    invalidmessage={errors.steps[index].StepDesc}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McSelect
                    label="Step Type"
                    name="stepType"
                    value={step.stepType}
                    input={(e) => handleInputChange(e, index)}
                    required
                    placeholder="Select Step Type"
                    invalid={!!errors.steps[index].stepType}
                    invalidmessage={errors.steps[index].stepType}
                  >
                    <McOption value="S">S</McOption>
                    <McOption value="M">M</McOption>
                  </McSelect>
                </div>
              </div>
            ))}
            <div className={styles.stepButtonContainer}>
              <McButton
                label="Add Step"
                appearance="secondary"
                click={addStep}
                className={styles.actionButton}
              />
              {steps.length > 1 && (
                <McButton
                  label="Remove Step"
                  appearance="neutral"
                  click={() => removeStep(steps.length - 1)}
                  className={styles.actionButton}
                />
              )}
            </div>
          </div>
        );
      case 'source':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Source Information</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Source Table"
                    name="sourceTable"
                    value={step.sourceTable}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter source table name"
                    required
                    invalid={!!errors.steps[index].sourceTable}
                    invalidmessage={errors.steps[index].sourceTable}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Source Filters"
                    name="sourceFilters"
                    value={step.sourceFilters}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter filters (e.g., PNL_LINE:IN:PnL.DVC.214,PnL.DVC.215;MOVE_TYPE:EQ:EX)"
                    multiline
                    rows={3}
                    required
                    invalid={!!errors.steps[index].sourceFilters}
                    invalidmessage={errors.steps[index].sourceFilters}
                  />
                </div>
              </div>
            ))}
          </div>
        );
      case 'preAggregate':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Pre-Aggregate Columns</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Pre-Aggregator Columns"
                    name="preAggregatorColumns"
                    value={step.preAggregatorColumns}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter columns (comma-separated)"
                    multiline
                    rows={3}
                    required
                    invalid={!!errors.steps[index].preAggregatorColumns}
                    invalidmessage={errors.steps[index].preAggregatorColumns}
                  />
                </div>
              </div>
            ))}
          </div>
        );
      case 'join':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Join Columns</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Join Columns"
                    name="joinColumns"
                    value={step.joinColumns}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter columns (comma-separated)"
                    multiline
                    rows={3}
                    required
                    invalid={!!errors.steps[index].joinColumns}
                    invalidmessage={errors.steps[index].joinColumns}
                  />
                </div>
              </div>
            ))}
          </div>
        );
      case 'allocation':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Allocation Columns</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Allocation Columns"
                    name="allocationColumns"
                    value={step.allocationColumns}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter columns (comma-separated)"
                    multiline
                    rows={3}
                    required
                    invalid={!!errors.steps[index].allocationColumns}
                    invalidmessage={errors.steps[index].allocationColumns}
                  />
                </div>
              </div>
            ))}
          </div>
        );
      case 'driver':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Driver Information</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Driver Table ID"
                    name="driverTableID"
                    value={step.driverTableID}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter driver table ID"
                    required
                    invalid={!!errors.steps[index].driverTableID}
                    invalidmessage={errors.steps[index].driverTableID}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Driver Weight Column"
                    name="driverWeightColumn"
                    value={step.driverWeightColumn}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter driver weight column"
                    required
                    invalid={!!errors.steps[index].driverWeightColumn}
                    invalidmessage={errors.steps[index].driverWeightColumn}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Driver Filters"
                    name="driverFilters"
                    value={step.driverFilters}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter filters"
                    multiline
                    rows={3}
                    required
                    invalid={!!errors.steps[index].driverFilters}
                    invalidmessage={errors.steps[index].driverFilters}
                  />
                </div>
              </div>
            ))}
          </div>
        );
      default:
        return <div className={styles.tabContent}>No Tab Selected</div>;
    }
  };

  return (
    <div className={styles.pageWrapper}>
      <div className={styles.container}>
        <div className={styles.card}>
          <div className={styles.buttonContainer}>
            <McButton
              label="Back"
              appearance="neutral"
              click={handleCancel}
              className={styles.actionButton}
            />
            <McButton
              label="Save"
              appearance="primary"
              click={handleSave}
              className={styles.actionButton}
              loading={isLoading}
              disabled={isLoading}
            />
          </div>

          <div className={styles.tabs}>
            <button
              className={`${styles.tabButton} ${activeTab === 'ruleInfo' ? styles.activeTab : ''}`}
              onClick={() => setActiveTab('ruleInfo')}
            >
              Rule Info
            </button>
            <button
              className={`${styles.tabButton} ${activeTab === 'step' ? styles.activeTab : ''}`}
              onClick={() => setActiveTab('step')}
            >
              Step
            </button>
            <button
              className={`${styles.tabButton} ${activeTab === 'source' ? styles.activeTab : ''}`}
              onClick={() => setActiveTab('source')}
            >
              Source
            </button>
            <button
              className={`${styles.tabButton} ${activeTab === 'preAggregate' ? styles.activeTab : ''}`}
              onClick={() => setActiveTab('preAggregate')}
            >
              Pre-Aggregate
            </button>
            <button
              className={`${styles.tabButton} ${activeTab === 'join' ? styles.activeTab : ''}`}
              onClick={() => setActiveTab('join')}
            >
              Join
            </button>
            <button
              className={`${styles.tabButton} ${activeTab === 'allocation' ? styles.activeTab : ''}`}
              onClick={() => setActiveTab('allocation')}
            >
              Allocation
            </button>
            <button
              className={`${styles.tabButton} ${activeTab === 'driver' ? styles.activeTab : ''}`}
              onClick={() => setActiveTab('driver')}
            >
              Driver
            </button>
          </div>

          {renderTabContent()}
        </div>
      </div>
    </div>
  );
};

export default CreateRules;

import React, { useState, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { McButton, McInput, McMultiSelect, McSelect } from '@maersk-global/mds-react-wrapper';
import { McOption } from '@maersk-global/mds-react-wrapper/components-core/mc-option';
import styles from '../styles/CreateRule.module.css';
import data from '../data/PnLGroup.json';

class ErrorBoundary extends React.Component {
  state = { hasError: false };
  static getDerivedStateFromError() {
    return { hasError: true };
  }
  render() {
    if (this.state.hasError) {
      return <div>Something went wrong. Please refresh the page.</div>;
    }
    return this.props.children;
  }
}

const CreateRules = () => {
  const navigate = useNavigate();
  const [activeTab, setActiveTab] = useState('ruleInfo');
  const [isLoading, setIsLoading] = useState(false);
  const [ruleData, setRuleData] = useState({
    num: '',
    name: '',
    desc: '',
    custRefID: '',
    ruleGroup: '',
    isActive: 'Y',
    pnlGroup: '',
  });
  const [steps, setSteps] = useState([
    {
      stepNo: '',
      stepName: 'Single Step',
      stepDesc: '',
      stepType: 'S',
      preAggregatorColumns: [],
      sourceTableID: '',
      sourceFilters: [],
      sourceOperator: '',
      joinColumns: [],
      allocationColumns: [],
      driverTableID: '',
      driverWeightColumn: '',
      driverFilters: [],
      driverOperator: '',
    },
  ]);
  const [errors, setErrors] = useState({ rule: {}, steps: [{}] });

  const pnLGroups = data.PnLGroups && typeof data.PnLGroups === 'object'
    ? Object.keys(data.PnLGroups)
    : [];
  const ruleGroups = ruleData.pnlGroup && data.PnLGroups[ruleData.pnlGroup]
    ? data.PnLGroups[ruleData.pnlGroup].RuleGroups || []
    : [];

  const sourceFilterOptions = [
    { value: 'Source_Filter_1', label: 'Source Filter 1' },
    { value: 'Source_Filter_2', label: 'Source Filter 2' },
    { value: 'Source_Filter_3', label: 'Source Filter 3' },
  ];
  const preAggregatorOptions = [
    { value: 'column1', label: 'Column 1' },
    { value: 'column2', label: 'Column 2' },
    { value: 'column3', label: 'Column 3' },
  ];
  const joinColumnsOptions = [
    { value: 'join_col1', label: 'Join Column 1' },
    { value: 'join_col2', label: 'Join Column 2' },
    { value: 'join_col3', label: 'Join Column 3' },
  ];
  const allocationColumnsOptions = [
    { value: 'alloc_col1', label: 'Allocation Column 1' },
    { value: 'alloc_col2', label: 'Allocation Column 2' },
    { value: 'alloc_col3', label: 'Allocation Column 3' },
  ];
  const driverFilterOptions = [
    { value: 'Driver_Type_1', label: 'Driver Type: Type 1' },
    { value: 'Driver_Type_2', label: 'Driver Type: Type 2' },
    { value: 'Driver_Status_Active', label: 'Driver Status: Active' },
  ];

  const operatorOptions = useMemo(() => [
    { value: 'IN', label: 'IN' },
    { value: 'NOT IN', label: 'NOT IN' },
    { value: 'EQ', label: 'EQ' },
    { value: 'NTEQ', label: 'NTEQ' },
    { value: 'IS NULL', label: 'IS NULL' },
    { value: 'GT', label: 'GT' },
    { value: 'LT', label: 'LT' },
    { value: 'GTEQ', label: 'GTEQ' },
    { value: 'LTEQ', label: 'LTEQ' },
    { value: 'BETWEEN', label: 'BETWEEN' },
    { value: 'NOT BETWEEN', label: 'NOT BETWEEN' },
    { value: 'LIKE', label: 'LIKE' },
  ], []);

  const addStep = useCallback(() => {
    setSteps((prevSteps) => [
      ...prevSteps,
      {
        stepNo: '',
        stepName: 'Single Step',
        stepDesc: '',
        stepType: 'S',
        preAggregatorColumns: [],
        sourceTableID: '',
        sourceFilters: [],
        sourceOperator: '',
        joinColumns: [],
        allocationColumns: [],
        driverTableID: '',
        driverWeightColumn: '',
        driverFilters: [],
        driverOperator: '',
      },
    ]);
    setErrors((prevErrors) => ({
      ...prevErrors,
      steps: [...prevErrors.steps, {}],
    }));
  }, []);

  const removeStep = useCallback((index) => {
    if (steps.length === 1) {
      alert('At least one step is required.');
      return;
    }
    setSteps((prevSteps) => prevSteps.filter((_, i) => i !== index));
    setErrors((prevErrors) => ({
      ...prevErrors,
      steps: prevErrors.steps.filter((_, i) => i !== index),
    }));
  }, [steps.length]);

  const validateForm = useCallback(() => {
    try {
      const newErrors = { rule: {}, steps: steps.map(() => ({})) };
      let isValid = true;

      if (!ruleData.num) {
        newErrors.rule.num = 'Rule Number is required';
        isValid = false;
      } else if (!/^[a-zA-Z0-9]+$/.test(ruleData.num)) {
        newErrors.rule.num = 'Rule Number must be alphanumeric';
        isValid = false;
      }
      if (!ruleData.name) {
        newErrors.rule.name = 'Rule Name is required';
        isValid = false;
      }
      if (!ruleData.desc) {
        newErrors.rule.desc = 'Description is required';
        isValid = false;
      }
      if (!ruleData.custRefID) {
        newErrors.rule.custRefID = 'Customer Reference ID is required';
        isValid = false;
      }
      if (!ruleData.pnlGroup) {
        newErrors.rule.pnlGroup = 'PnL Group is required';
        isValid = false;
      }
      if (!ruleData.ruleGroup) {
        newErrors.rule.ruleGroup = 'Rule Group is required';
        isValid = false;
      }
      if (!ruleData.isActive) {
        newErrors.rule.isActive = 'Active status is required';
        isValid = false;
      }

      const stepNumbers = new Set();
      steps.forEach((step, index) => {
        const stepErrors = {};
        if (!step.stepNo) {
          stepErrors.stepNo = 'Step Number is required';
          isValid = false;
        } else if (stepNumbers.has(step.stepNo)) {
          stepErrors.stepNo = 'Step Number must be unique';
          isValid = false;
        } else {
          stepNumbers.add(step.stepNo);
        }
        if (!step.stepName) {
          stepErrors.stepName = 'Step Name is required';
          isValid = false;
        }
        if (!step.stepDesc) {
          stepErrors.stepDesc = 'Step Description is required';
          isValid = false;
        }
        if (!step.stepType) {
          stepErrors.stepType = 'Step Type is required';
          isValid = false;
        }
        if (!step.preAggregatorColumns.length) {
          stepErrors.preAggregatorColumns = 'Pre-Aggregator Columns are required';
          isValid = false;
        }
        if (!step.sourceTableID) {
          stepErrors.sourceTableID = 'Source Table ID is required';
          isValid = false;
        }
        if (!step.sourceFilters.length) {
          stepErrors.sourceFilters = 'Source Filters are required';
          isValid = false;
        }
        if (!step.sourceOperator) {
          stepErrors.sourceOperator = 'Source Operator is required';
          isValid = false;
        }
        if (!step.joinColumns.length) {
          stepErrors.joinColumns = 'Join Columns are required';
          isValid = false;
        }
        if (!step.allocationColumns.length) {
          stepErrors.allocationColumns = 'Allocation Columns are required';
          isValid = false;
        }
        if (!step.driverTableID) {
          stepErrors.driverTableID = 'Driver Table ID is required';
          isValid = false;
        }
        if (!step.driverWeightColumn) {
          stepErrors.driverWeightColumn = 'Driver Weight Column is required';
          isValid = false;
        }
        if (!step.driverFilters.length) {
          stepErrors.driverFilters = 'Driver Filters are required';
          isValid = false;
        }
        if (!step.driverOperator) {
          stepErrors.driverOperator = 'Driver Operator is required';
          isValid = false;
        }
        newErrors.steps[index] = stepErrors;
      });

      setErrors(newErrors);
      return isValid;
    } catch (error) {
      alert('An error occurred during form validation. Please try again.');
      return false;
    }
  }, [ruleData, steps]);

  const parseColumns = (input) => input;

  const parseFilters = (filters, operator) => {
    if (!filters.length || !operator) return [];
    return filters.map((filter) => ({
      name: filter,
      filterType: operator,
      values: filter,
    }));
  };

  const handleInputChange = useCallback((e, stepIndex = null) => {
    const { name, value } = e.target;
    if (stepIndex !== null) {
      setSteps((prevSteps) => {
        const newSteps = [...prevSteps];
        newSteps[stepIndex] = { ...newSteps[stepIndex], [name]: value };
        return newSteps;
      });
      setErrors((prevErrors) => ({
        ...prevErrors,
        steps: prevErrors.steps.map((stepErrors, i) =>
          i === stepIndex ? { ...stepErrors, [name]: '' } : stepErrors
        ),
      }));
    } else {
      setRuleData((prevData) => ({
        ...prevData,
        [name]: value,
        ...(name === 'pnlGroup' ? { ruleGroup: '' } : {}),
      }));
      setErrors((prevErrors) => ({
        ...prevErrors,
        rule: { ...prevErrors.rule, [name]: '' },
      }));
    }
  }, []);

  const handleMultiSelectChange = useCallback((e, stepIndex, fieldName) => {
    const selectedValues = e.detail.map((option) => option.value);
    setSteps((prevSteps) => {
      const newSteps = [...prevSteps];
      newSteps[stepIndex] = { ...newSteps[stepIndex], [fieldName]: selectedValues };
      return newSteps;
    });
    setErrors((prevErrors) => ({
      ...prevErrors,
      steps: prevErrors.steps.map((stepErrors, i) =>
        i === stepIndex ? { ...stepErrors, [fieldName]: '' } : stepErrors
      ),
    }));
  }, []);

  const resetForm = useCallback(() => {
    setRuleData({
      num: '',
      name: '',
      desc: '',
      custRefID: '',
      ruleGroup: '',
      isActive: 'Y',
      pnlGroup: '',
    });
    setSteps([
      {
        stepNo: '',
        stepName: 'Single Step',
        stepDesc: '',
        stepType: 'S',
        preAggregatorColumns: [],
        sourceTableID: '',
        sourceFilters: [],
        sourceOperator: '',
        joinColumns: [],
        allocationColumns: [],
        driverTableID: '',
        driverWeightColumn: '',
        driverFilters: [],
        driverOperator: '',
      },
    ]);
    setErrors({ rule: {}, steps: [{}] });
    setActiveTab('ruleInfo');
  }, []);

  const handleSave = useCallback(async () => {
    if (!validateForm()) {
      alert('Please fill out all required fields.');
      return;
    }

    setIsLoading(true);

    const ruleJson = {
      rules: {
        rule: [
          {
            num: ruleData.num,
            name: ruleData.name,
            desc: ruleData.desc,
            custRefID: ruleData.custRefID,
            ruleGroup: ruleData.ruleGroup,
            isActive: ruleData.isActive,
            Step: steps.map((step, index) => ({
              stepNo: step.stepNo || `${ruleData.num}.${index + 1}`,
              stepName: step.stepName === 'Single Step' ? 'single' : 'multi',
              stepDesc: step.stepDesc,
              stepType: step.stepType,
              isActive: 'Y',
              SourceTable: {
                id: step.sourceTableID,
                Name: step.sourceTableID,
              },
              sourceFilters: {
                columns: parseFilters(step.sourceFilters, step.sourceOperator),
                operator: step.sourceOperator,
              },
              preAggregator: {
                columns: parseColumns(step.preAggregatorColumns),
              },
              join: {
                columns: parseColumns(step.joinColumns),
              },
              allocation: {
                columns: parseColumns(step.allocationColumns),
              },
              driver: {
                driverTableID: step.driverTableID,
                driverWeightColumn: step.driverWeightColumn,
                driverFilters: {
                  columns: parseFilters(step.driverFilters, step.driverOperator),
                  operator: step.driverOperator,
                },
              },
            })),
          },
        ],
      },
    };

    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 10000);

    try {
      const response = await fetch('/api/rules', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
        body: JSON.stringify(ruleJson),
        signal: controller.signal,
      });

      clearTimeout(timeoutId);

      if (response.ok) {
        alert('Rule created successfully!');
        resetForm();
        navigate('/');
      } else {
        const errorData = await response.json().catch(() => ({ message: response.statusText }));
        alert(`Failed to create rule: ${errorData.message || response.statusText}`);
      }
    } catch (error) {
      if (error.name === 'AbortError') {
        alert('Request timed out. Please try again.');
      } else {
        alert('An error occurred while saving the rule. Please try again.');
      }
    } finally {
      setIsLoading(false);
    }
  }, [validateForm, ruleData, steps, resetForm, navigate]);

  const handleCancel = useCallback(() => {
    navigate('/');
  }, [navigate]);

  const renderTabContent = () => {
    switch (activeTab) {
      case 'ruleInfo':
        return (
          <div className={styles.tabContent}>
            {Object.values(errors.rule).some((error) => error) && (
              <div className={styles.errorSummary}>
                <h4>Please fix the following errors:</h4>
                <ul>
                  {Object.entries(errors.rule).map(([key, error]) => error && (
                    <li key={key}>{error}</li>
                  ))}
                </ul>
              </div>
            )}
            <h3 className={styles.sectionTitle}>Rule Information</h3>
            <div className={styles.formGrid}>
              <div className={styles.gridItem}>
                <McSelect
                  label="PnL Group"
                  name="pnlGroup"
                  value={ruleData.pnlGroup}
                  input={handleInputChange}
                  placeholder="Select a PnL Group"
                  required
                  invalid={!!errors.rule.pnlGroup}
                  invalidmessage={errors.rule.pnlGroup}
                >
                  {pnLGroups.map((group) => (
                    <McOption key={group} value={group}>
                      {group}
                    </McOption>
                  ))}
                </McSelect>
              </div>
              <div className={styles.gridItem}>
                <McSelect
                  label="Rule Group"
                  name="ruleGroup"
                  value={ruleData.ruleGroup}
                  input={handleInputChange}
                  placeholder={ruleGroups.length ? "Select a Rule Group" : "Select a PnL Group first"}
                  required
                  disabled={!ruleData.pnlGroup || !ruleGroups.length}
                  invalid={!!errors.rule.ruleGroup}
                  invalidmessage={errors.rule.ruleGroup}
                >
                  {ruleGroups.map((group) => (
                    <McOption key={group} value={group}>
                      {group}
                    </McOption>
                  ))}
                </McSelect>
              </div>
            </div>
            <div className={styles.inputGroup}>
              <McInput
                label="Rule Number"
                name="num"
                value={ruleData.num}
                input={handleInputChange}
                placeholder="Enter rule number"
                required
                invalid={!!errors.rule.num}
                invalidmessage={errors.rule.num}
              />
            </div>
            <div className={styles.inputGroup}>
              <McInput
                label="Rule Name"
                name="name"
                value={ruleData.name}
                input={handleInputChange}
                placeholder="Enter rule name"
                required
                invalid={!!errors.rule.name}
                invalidmessage={errors.rule.name}
              />
            </div>
            <div className={styles.inputGroup}>
              <McInput
                label="Description"
                name="desc"
                value={ruleData.desc}
                input={handleInputChange}
                placeholder="Enter rule description"
                multiline
                rows={3}
                required
                invalid={!!errors.rule.desc}
                invalidmessage={errors.rule.desc}
              />
            </div>
            <div className={styles.inputGroup}>
              <McInput
                label="Customer Reference ID"
                name="custRefID"
                value={ruleData.custRefID}
                input={handleInputChange}
                placeholder="Enter customer reference ID"
                required
                invalid={!!errors.rule.custRefID}
                invalidmessage={errors.rule.custRefID}
              />
            </div>
          </div>
        );
      case 'step':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Step Information</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Step Number"
                    name="stepNo"
                    value={step.stepNo}
                    input={(e) => handleInputChange(e, index)}
                    placeholder={`Enter step number (e.g., ${ruleData.num}.${index + 1})`}
                    required
                    invalid={!!errors.steps[index].stepNo}
                    invalidmessage={errors.steps[index].stepNo}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McSelect
                    label="Step Name"
                    name="stepName"
                    value={step.stepName}
                    input={(e) => handleInputChange(e, index)}
                    required
                    placeholder="Select Step Name"
                    invalid={!!errors.steps[index].stepName}
                    invalidmessage={errors.steps[index].stepName}
                  >
                    <McOption value="Single Step">Single Step</McOption>
                    <McOption value="Multi Step">Multi Step</McOption>
                  </McSelect>
                </div>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Step Description"
                    name="stepDesc"
                    value={step.stepDesc}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter step description"
                    multiline
                    rows={3}
                    required
                    invalid={!!errors.steps[index].stepDesc}
                    invalidmessage={errors.steps[index].stepDesc}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McSelect
                    label="Step Type"
                    name="stepType"
                    value={step.stepType}
                    input={(e) => handleInputChange(e, index)}
                    required
                    placeholder="Select Step Type"
                    invalid={!!errors.steps[index].stepType}
                    invalidmessage={errors.steps[index].stepType}
                  >
                    <McOption value="S">S</McOption>
                    <McOption value="M">M</McOption>
                  </McSelect>
                </div>
              </div>
            ))}
            <div className={styles.stepButtonContainer}>
              <McButton
                label="Add Step"
                appearance="secondary"
                click={addStep}
                className={styles.actionButton}
              />
              {steps.length > 1 && (
                <McButton
                  label="Remove Step"
                  appearance="neutral"
                  click={() => removeStep(steps.length - 1)}
                  className={styles.actionButton}
                />
              )}
            </div>
          </div>
        );
      case 'source':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Source Information</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Source Table ID"
                    name="sourceTableID"
                    value={step.sourceTableID}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter source table ID"
                    required
                    invalid={!!errors.steps[index].sourceTableID}
                    invalidmessage={errors.steps[index].sourceTableID}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McMultiSelect
                    label="Source Filters"
                    name="sourceFilters"
                    value={step.sourceFilters}
                    optionselected={(e) => handleMultiSelectChange(e, index, 'sourceFilters')}
                    placeholder="Select source filters"
                    required
                    invalid={!!errors.steps[index].sourceFilters}
                    invalidmessage={errors.steps[index].sourceFilters}
                  >
                    {sourceFilterOptions.map((option) => (
                      <McOption key={option.value} value={option.value}>
                        {option.label}
                      </McOption>
                    ))}
                  </McMultiSelect>
                </div>
                <div className={styles.inputGroup}>
                  <McSelect
                    label="Source Operator"
                    name="sourceOperator"
                    value={step.sourceOperator}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Select an operator"
                    required
                    invalid={!!errors.steps[index].sourceOperator}
                    invalidmessage={errors.steps[index].sourceOperator}
                  >
                    {operatorOptions.map((option) => (
                      <McOption key={option.value} value={option.value}>
                        {option.label}
                      </McOption>
                    ))}
                  </McSelect>
                </div>
              </div>
            ))}
          </div>
        );
      case 'preAggregate':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Pre-Aggregate Columns</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McMultiSelect
                    label="Pre-Aggregator Columns"
                    name="preAggregatorColumns"
                    value={step.preAggregatorColumns}
                    optionselected={(e) => handleMultiSelectChange(e, index, 'preAggregatorColumns')}
                    placeholder="Select pre-aggregator columns"
                    required
                    invalid={!!errors.steps[index].preAggregatorColumns}
                    invalidmessage={errors.steps[index].preAggregatorColumns}
                  >
                    {preAggregatorOptions.map((option) => (
                      <McOption key={option.value} value={option.value}>
                        {option.label}
                      </McOption>
                    ))}
                  </McMultiSelect>
                </div>
              </div>
            ))}
          </div>
        );
      case 'join':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Join Columns</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McMultiSelect
                    label="Join Columns"
                    name="joinColumns"
                    value={step.joinColumns}
                    optionselected={(e) => handleMultiSelectChange(e, index, 'joinColumns')}
                    placeholder="Select join columns"
                    required
                    invalid={!!errors.steps[index].joinColumns}
                    invalidmessage={errors.steps[index].joinColumns}
                  >
                    {joinColumnsOptions.map((option) => (
                      <McOption key={option.value} value={option.value}>
                        {option.label}
                      </McOption>
                    ))}
                  </McMultiSelect>
                </div>
              </div>
            ))}
          </div>
        );
      case 'allocation':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Allocation Columns</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McMultiSelect
                    label="Allocation Columns"
                    name="allocationColumns"
                    value={step.allocationColumns}
                    optionselected={(e) => handleMultiSelectChange(e, index, 'allocationColumns')}
                    placeholder="Select allocation columns"
                    required
                    invalid={!!errors.steps[index].allocationColumns}
                    invalidmessage={errors.steps[index].allocationColumns}
                  >
                    {allocationColumnsOptions.map((option) => (
                      <McOption key={option.value} value={option.value}>
                        {option.label}
                      </McOption>
                    ))}
                  </McMultiSelect>
                </div>
              </div>
            ))}
          </div>
        );
      case 'driver':
        return (
          <div className={styles.tabContent}>
            <h3 className={styles.sectionTitle}>Driver Information</h3>
            {steps.map((step, index) => (
              <div key={index} className={styles.stepCase}>
                <h4 style={{ color: '#35B0CB' }}>STEP {index + 1}</h4>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Driver Table ID"
                    name="driverTableID"
                    value={step.driverTableID}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter driver table ID"
                    required
                    invalid={!!errors.steps[index].driverTableID}
                    invalidmessage={errors.steps[index].driverTableID}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McInput
                    label="Driver Weight Column"
                    name="driverWeightColumn"
                    value={step.driverWeightColumn}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Enter driver weight column"
                    required
                    invalid={!!errors.steps[index].driverWeightColumn}
                    invalidmessage={errors.steps[index].driverWeightColumn}
                  />
                </div>
                <div className={styles.inputGroup}>
                  <McMultiSelect
                    label="Driver Filters"
                    name="driverFilters"
                    value={step.driverFilters}
                    optionselected={(e) => handleMultiSelectChange(e, index, 'driverFilters')}
                    placeholder="Select driver filters"
                    required
                    invalid={!!errors.steps[index].driverFilters}
                    invalidmessage={errors.steps[index].driverFilters}
                  >
                    {driverFilterOptions.map((option) => (
                      <McOption key={option.value} value={option.value}>
                        {option.label}
                      </McOption>
                    ))}
                  </McMultiSelect>
                </div>
                <div className={styles.inputGroup}>
                  <McSelect
                    label="Driver Operator"
                    name="driverOperator"
                    value={step.driverOperator}
                    input={(e) => handleInputChange(e, index)}
                    placeholder="Select an operator"
                    required
                    invalid={!!errors.steps[index].driverOperator}
                    invalidmessage={errors.steps[index].driverOperator}
                  >
                    {operatorOptions.map((option) => (
                      <McOption key={option.value} value={option.value}>
                        {option.label}
                      </McOption>
                    ))}
                  </McSelect>
                </div>
              </div>
            ))}
          </div>
        );
      default:
        return <div className={styles.tabContent}>No Tab Selected</div>;
    }
  };

  return (
    <ErrorBoundary>
      <div className={styles.pageWrapper}>
        {isLoading && (
          <div className={styles.loader}>Loading...</div>
        )}
        <div className={styles.container}>
          <div className={styles.card}>
            <div className={styles.buttonContainer}>
              <McButton
                label="Back"
                appearance="neutral"
                click={handleCancel}
                className={styles.actionButton}
              />
              <McButton
                label="Save"
                appearance="primary"
                click={handleSave}
                className={styles.actionButton}
                loading={isLoading}
                disabled={isLoading}
              />
            </div>

            <div className={styles.tabs}>
              <button
                className={`${styles.tabButton} ${activeTab === 'ruleInfo' ? styles.activeTab : ''}`}
                onClick={() => setActiveTab('ruleInfo')}
              >
                Rule Info
              </button>
              <button
                className={`${styles.tabButton} ${activeTab === 'step' ? styles.activeTab : ''}`}
                onClick={() => setActiveTab('step')}
              >
                Step
              </button>
              <button
                className={`${styles.tabButton} ${activeTab === 'source' ? styles.activeTab : ''}`}
                onClick={() => setActiveTab('source')}
              >
                Source
              </button>
              <button
                className={`${styles.tabButton} ${activeTab === 'preAggregate' ? styles.activeTab : ''}`}
                onClick={() => setActiveTab('preAggregate')}
              >
                Pre-Aggregate
              </button>
              <button
                className={`${styles.tabButton} ${activeTab === 'join' ? styles.activeTab : ''}`}
                onClick={() => setActiveTab('join')}
              >
                Join
              </button>
              <button
                className={`${styles.tabButton} ${activeTab === 'allocation' ? styles.activeTab : ''}`}
                onClick={() => setActiveTab('allocation')}
              >
                Allocation
              </button>
              <button
                className={`${styles.tabButton} ${activeTab === 'driver' ? styles.activeTab : ''}`}
                onClick={() => setActiveTab('driver')}
              >
                Driver
              </button>
            </div>

            {renderTabContent()}
          </div>
        </div>
      </div>
    </ErrorBoundary>
  );
};

export default CreateRules;
content_copyCOPY