Help to otimize this code below. This is what its purpose:
- receive data to mount two tables
- first table just for reference
- second table with an input, that when changes, calls recalculation of all related values ​​of this data
- when there's too much data, the changes are slow, as the first render.

import * as Resizer from '@column-resizer/react';
import { InputBlock } from '@components/Molecules';
import {
  Button,
  LoadingOverlay,
  Progress,
  RingProgress,
  Table,
  TextInput,
  Tooltip,
} from '@mantine/core';
import { useForm } from '@mantine/form';
import { Bloco } from '@src/components/Atoms/Library';
import {
  createMedicoes,
  createMedicoesItem,
  deleteMedicoes,
  updateObra,
} from '@src/graphql/mutations';
import { IRootState } from '@src/stores';
import { addNotification } from '@src/stores/notificationsSlice';
import { formatarMoeda, formatarQtd, getSubcategoryDepth, toFixedNumber } from '@src/utils';
import {
  MedicaoItem,
  MedicaoItemData,
  NewMedicaoItem,
  PlanilhaItemData,
} from '@src/utils/interfaces';
import { generateClient } from 'aws-amplify/api';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';

const client = generateClient();

export type MergedData = Pick<
  PlanilhaItemData,
  | 'item'
  | 'qtd'
  | 'proporcaoMaodeObra'
  | 'proporcaoMaterial'
  | 'precoUnitarioDesconto'
  | 'precoTotalDesconto'
  | 'dataType'
  | 'category'
  | 'subcategory'
> &
  MedicaoItem &
  NewMedicaoItem;

const AddMedicao = ({
  tableData,
  medicoesData,
  obraID,
  dataInicio,
  nextMedicaoNum,
  processedData,
  onUpdateProcessedData,
}: {
  tableData: PlanilhaItemData[];
  medicoesData: MedicaoItem[];
  obraID: string;
  dataInicio: string;
  nextMedicaoNum: number;
  processedData: MergedData[];
  onUpdateProcessedData: (newProcessedData: MergedData[]) => void;
}) => {
  if (!tableData) return;
  const [loading, setLoading] = useState(true);
  const { loggedUser } = useSelector((state: IRootState) => state.userInfo);
  const dispatch = useDispatch();

  let subcategoriasProfundidade = new Map<string, number>();
  const [subcategoriasOrdenadas, setSubcategoriasOrdenadas] = useState<
    { item: string; profundidade: number }[]
  >([]);

  const [totaisMedicao, setTotaisMedicao] = useState<{
    valorTotal: number;
    valorTotalMaodeObra: number;
    valorTotalMaterial: number;
    valorAcumulado: number;
    valorSaldo: number;
  }>({
    valorTotal: 0,
    valorTotalMaodeObra: 0,
    valorTotalMaterial: 0,
    valorAcumulado: 0,
    valorSaldo: 0,
  });

  const [mergedTableData, setMergedTableData] = useState<MergedData[]>([]);

  // Cria um objeto para facilitar a busca dos dados de medicoesData
  const medicoesDataMap = medicoesData.reduce((acc, medicao) => {
    acc[medicao.item] = medicao;
    return acc;
  }, {} as Record<string, MedicaoItem>);

  // Mesclar tableData e medicoesData usando item como chave
  const mergeOriginalData = () => {
    const mergedData: MergedData[] = tableData.map((row) => {
      const medicaoCorrespondente = medicoesDataMap[row.item];

      if (row.dataType !== 'item') {
        const profundidade = getSubcategoryDepth(row.item);
        subcategoriasProfundidade.set(row.item, profundidade);
      }

      const selectedRow = {
        item: row.item,
        qtd: row.qtd,
        proporcaoMaodeObra: row.proporcaoMaodeObra,
        proporcaoMaterial: row.proporcaoMaterial,
        precoUnitarioDesconto: row.precoUnitarioDesconto,
        precoTotalDesconto: row.precoTotalDesconto,
        dataType: row.dataType,
        category: row.category,
        subcategory: row.subcategory,
      };

      // Se existir um correspondente, combina os dados; caso contrário, usa apenas os dados de tableData
      if (medicaoCorrespondente) {
        return {
          ...selectedRow,
          ...medicaoCorrespondente,
          newQtd: null,
          newValorTotal: null,
          newValorTotalPerc: null,
          newAcumulado: null,
          newAcumuladoPerc: null,
          newSaldoQtd: null,
          newSaldoValor: null,
          newSaldoValorPerc: null,
        };
      } else {
        return {
          ...selectedRow,
          qtdMedicao: null,
          valorTotal: null,
          valorTotalPerc: null,
          acumulado: null,
          acumuladoPerc: null,
          saldoQtd: row.qtd,
          saldoValor: null,
          saldoValorPerc: null,
          newQtd: null,
          newValorTotal: null,
          newValorTotalPerc: null,
          newAcumulado: null,
          newAcumuladoPerc: null,
          newSaldoQtd: null,
          newSaldoValor: null,
          newSaldoValorPerc: null,
        };
      }
    });

    return mergedData;
  };

  useEffect(() => {
    if (!processedData.length) {
      window.log('Recalcula processedData');

      const mergedOriginalData = mergeOriginalData();

      // Seta o array de dados com as medições
      setMergedTableData(mergedOriginalData);

      // Chama a função de callback para atualizar os dados no componente pai
      onUpdateProcessedData(mergedOriginalData);
    } else {
      setMergedTableData(processedData);
    }

    // Cria lista de subcategorias ordenadas por profundidade
    const ordenadas = Array.from(subcategoriasProfundidade.entries()).sort((a, b) => {
      return b[1] - a[1];
    });

    // Transforma o array de arrays em um array de objetos
    const ordenadasComProfundidade = ordenadas.map(([item, profundidade]) => ({
      item,
      profundidade,
    }));
    setSubcategoriasOrdenadas(ordenadasComProfundidade);
    setLoading(false);
  }, [tableData]);

  // Use useMemo para calcular os valores
  const calculatedData = useMemo(() => {
    const dataWithCalculatedLine = mergedTableData.map((row) => {
      const precoUnitario = row.precoUnitarioDesconto || 0;
      const newQtd = row.newQtd || 0;
      const newValorTotal = toFixedNumber(newQtd * precoUnitario, 2);
      const newValorTotalMaodeObra = toFixedNumber(
        newValorTotal * (row.proporcaoMaodeObra || 0),
        2
      );
      const newValorTotalMaterial = toFixedNumber(newValorTotal * (row.proporcaoMaterial || 0), 2);
      const newSaldoQtd = (row.saldoQtd !== null ? row.saldoQtd : row.qtd || 0) - newQtd;
      const newAcumulado = toFixedNumber((row.acumulado || 0) + newValorTotal, 2);
      const newSaldoValor = toFixedNumber(
        row.precoTotalDesconto ? row.precoTotalDesconto - newAcumulado : 0,
        2
      );

      // Cálculos de percentual
      const newValorTotalPerc =
        (row.precoTotalDesconto ? (newValorTotal / row.precoTotalDesconto) * 100 : 0) || 0;
      const newAcumuladoPerc =
        (row.precoTotalDesconto ? (newAcumulado / row.precoTotalDesconto) * 100 : 0) || 0;

      return {
        ...row,
        newValorTotal,
        newValorTotalMaodeObra,
        newValorTotalMaterial,
        newValorTotalPerc,
        newAcumulado,
        newAcumuladoPerc,
        newSaldoQtd,
        newSaldoValor,
      };
    });

    // Calcula os totais por Categoria e Subcategoria
    let dataWithCalculatedTotals = dataWithCalculatedLine;
    subcategoriasOrdenadas.forEach((subcategory) => {
      // Busca todas as linhas que correspondem à subcategory atual
      const relatedRows = dataWithCalculatedTotals.filter((r) => {
        if (subcategory.item === '300') {
          return r.dataType === 'category';
        }
        if (subcategory.profundidade > 0) {
          // Se é subcategoria, busca linhas de item com a subcategory atual
          return r.subcategory === subcategory.item;
        } else {
          // Se é categoria, busca todas as linhas de categorias
          return r.category === subcategory.item && r.dataType === 'item';
        }
      });

      // Soma os valores de saldoValor encontrados
      const newSaldoValor = toFixedNumber(
        relatedRows.reduce((acc, r) => acc + (r.newSaldoValor || 0), 0),
        2
      );

      // Atualiza o saldoValor da linha atual com a soma
      dataWithCalculatedTotals = dataWithCalculatedTotals.map((row) => {
        if (row.item === subcategory.item) {
          // Calcular o valor percentual como um número
          const saldoValorPercentual = row.precoTotalDesconto
            ? ((row.precoTotalDesconto - newSaldoValor) / row.precoTotalDesconto) * 100
            : 0;

          return {
            ...row,
            newSaldoValor: newSaldoValor,
            newSaldoValorPerc: saldoValorPercentual,
          };
        }
        return row;
      });
    });

    // Calcula os totais gerais
    const valorTotal = toFixedNumber(
      dataWithCalculatedTotals.reduce(
        (acc, r) => acc + (r.dataType === 'item' ? r.newValorTotal || 0 : 0),
        0
      ),
      2
    );
    const valorTotalMaodeObra = toFixedNumber(
      dataWithCalculatedTotals.reduce((acc, r) => acc + (r.newValorTotalMaodeObra || 0), 0),
      2
    );
    const valorTotalMaterial = toFixedNumber(
      dataWithCalculatedTotals.reduce((acc, r) => acc + (r.newValorTotalMaterial || 0), 0),
      2
    );
    const valorAcumulado = toFixedNumber(
      dataWithCalculatedTotals.reduce((acc, r) => acc + (r.newAcumulado || 0), 0),
      2
    );
    const valorSaldo = toFixedNumber(
      dataWithCalculatedTotals.reduce(
        (acc, r) => acc + (r.dataType === 'item' ? r.newSaldoValor || 0 : 0),
        0
      ),
      2
    );

    // Atualiza os totaisMedicao
    setTotaisMedicao({
      valorTotal,
      valorTotalMaodeObra,
      valorTotalMaterial,
      valorAcumulado,
      valorSaldo,
    });

    return dataWithCalculatedTotals;
  }, [mergedTableData]);

  const handleMedicaoChange = (index: number, value: number) => {
    const row = mergedTableData[index];
    if (!row) return;

    // Converte o valor para decimal
    const originalQtd = parseFloat(row.newQtd ? row.newQtd.toString() : '0');
    const newQtd = parseFloat(value.toString());

    if (originalQtd === newQtd) return;

    setMergedTableData((prevData) =>
      prevData.map((data, idx) => {
        if (idx === index) {
          return { ...data, newQtd };
        }
        return data;
      })
    );
  };

  // Formulário e Salvar dados
  const form = useForm({
    validateInputOnChange: true,
    initialValues: {
      dataMedicao: '',
    },
    validate: {
      dataMedicao: (value: string) => {
        let error;
        const input = document.querySelector('input[name="dataMedicao"]') as HTMLInputElement;

        if (!value) error = 'Informe a data da medição';
        const date = new Date(value);
        if (date.getTime() < new Date(dataInicio).getTime()) {
          error = 'A data deve ser maior que o início da Obra';
        }
        if (date.getTime() > Date.now()) {
          error = 'A data deve ser menor que a data atual';
        }
        if (error) {
          if (input) input.focus();
          return error;
        }
        return null;
      },
    },
  });

  const handleKeyDown = useCallback((event: React.KeyboardEvent<HTMLFormElement>) => {
    if (event.key === 'Enter') {
      event.preventDefault();
    }
  }, []);

  const handleSubmit = async () => {
    setLoading(true);

    // Cria nova Medicao
    const medicaoID = await createNewMedicao();

    // Insere os items da medicao
    medicaoID && (await createNewMedicaoItem(medicaoID));
  };

  const createNewMedicao = async () => {
    const medicaoData = form.values;

    try {
      const medicao = await client.graphql({
        query: createMedicoes,
        variables: {
          input: {
            dataMedicao: medicaoData.dataMedicao,
            medicaoNum: nextMedicaoNum,
            valorTotal: totaisMedicao.valorTotal,
            valorTotalMaodeObra: totaisMedicao.valorTotalMaodeObra,
            valorTotalMaterial: totaisMedicao.valorTotalMaterial,
            valorAcumulado: totaisMedicao.valorAcumulado,
            valorSaldo: totaisMedicao.valorSaldo,
            obraID: obraID,
            userCreatedAt: loggedUser,
          },
        },
      });

      window.log('Medição criada com sucesso!', medicao.data.createMedicoes.id);

      // Atualiza dados da Obra
      await client.graphql({
        query: updateObra,
        variables: {
          input: {
            id: obraID,
            valorAcumulado: totaisMedicao.valorAcumulado,
            ultimaMedicao: medicaoData.dataMedicao,
          },
        },
      });

      return medicao.data.createMedicoes.id;
    } catch (error) {
      console.error('Erro ao criar medição: ', error);
      dispatch(
        addNotification({
          title: 'Erro ao criar medição',
          message: `Confira os dados e tente novamente. Se persistir, reporte este erro: ${error}`,
          type: 'error',
        })
      );
    }
  };

  const createNewMedicaoItem = async (medicaoID: string) => {
    window.log('Iniciando inserção de item da medicao', medicaoID);

    try {
      for (const row of calculatedData) {
        const medicaoItem: MedicaoItemData = {
          item: row.item,
          qtdMedicao: row.newQtd,
          valorTotal: row.newValorTotal,
          valorTotalPerc: row.newValorTotalPerc,
          acumulado: row.newAcumulado,
          acumuladoPerc: row.newAcumuladoPerc,
          saldoQtd: row.newSaldoQtd,
          saldoValor: row.newSaldoValor,
          saldoValorPerc: row.newSaldoValorPerc,
          medicaoID: medicaoID,
        };

        await client.graphql({
          query: createMedicoesItem,
          variables: {
            input: medicaoItem,
          },
        });
      }

      window.log('Finalizando inserção de item da medicao', medicaoID);

      dispatch(
        addNotification({
          title: 'Medição Criada com Sucesso!',
          message: `${nextMedicaoNum}ª medição desta Obra.`,
          type: 'success',
        })
      );

      // Reload page
      window.location.reload();
    } catch (error) {
      console.error('Erro ao inserir item da medicao: ', error);
      // Exclui medição em caso de erro
      await client.graphql({
        query: deleteMedicoes,
        variables: {
          input: {
            id: medicaoID,
          },
        },
      });
      setLoading(false);

      dispatch(
        addNotification({
          title: 'Erro ao criar medição',
          message: `Confira os dados e tente novamente. Se persistir, reporte este erro: ${error}`,
          type: 'error',
        })
      );
    }
  };

  return (
    <div className="flex-col relative">
      {loading && <LoadingOverlay visible={loading} overlayProps={{ radius: 'sm', blur: 2 }} />}
      <Resizer.Container>
        <Resizer.Section minSize={600}>
          <Table striped verticalSpacing="sm" className="text-sm">
            <Table.Thead>
              <Table.Tr>
                <Table.Th colSpan={7} align="center">
                  <h4>Orçamento Base</h4>
                </Table.Th>
              </Table.Tr>
              <Table.Tr>
                <Table.Th w={`5%`}>Item</Table.Th>
                <Table.Th w={`5%`}>Código</Table.Th>
                <Table.Th w={`25%`}>Descrição</Table.Th>
                <Table.Th>Un.</Table.Th>
                <Table.Th>Qtd</Table.Th>
                <Table.Th className="text-right">Preço Un.</Table.Th>
                <Table.Th className="text-right">
                  Preço<br></br>Total
                </Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {tableData.map((row, index) => {
                const dataType =
                  row.dataType === 'category' ||
                  row.dataType === 'subcategory' ||
                  row.dataType === 'sum'
                    ? 'title'
                    : 'data';
                return (
                  <Table.Tr
                    key={index}
                    className={`h-12 ${dataType === 'title' ? 'font-bold' : ''}`}
                  >
                    <Table.Td>{row.dataType !== 'sum' ? row.item : ''}</Table.Td>
                    <Table.Td
                      colSpan={dataType === 'title' ? 2 : 1}
                      className="max-w-20 limit-text"
                    >
                      {row.codigo || row.descricao}
                    </Table.Td>
                    {dataType === 'data' && (
                      <Table.Td
                        className="limit-text text-xs max-w-96"
                        title={String(row.descricao)}
                      >
                        {row.descricao !== 'undefined' && row.descricao}
                      </Table.Td>
                    )}
                    <Table.Td>{row.unidade}</Table.Td>
                    <Table.Td>{row.qtd && row.qtd > 0 ? formatarQtd(row.qtd) : ''} </Table.Td>
                    <Table.Td className="text-right">
                      {formatarMoeda(row.precoUnitarioDesconto)}
                    </Table.Td>
                    <Table.Td className="text-right">
                      {formatarMoeda(row.precoTotalDesconto)}
                    </Table.Td>
                  </Table.Tr>
                );
              })}
            </Table.Tbody>
          </Table>
        </Resizer.Section>
        {/*  */}
        <Resizer.Bar className="cursor-w-resize hover:bg-slate-100" />
        {/*  */}
        <Resizer.Section defaultSize={550} minSize={470}>
          <form onKeyDown={handleKeyDown} onSubmit={form.onSubmit(() => void handleSubmit())}>
            <Table striped verticalSpacing="sm" className="text-sm">
              <Table.Thead>
                <Table.Tr>
                  <Table.Th colSpan={6} align="center">
                    <Bloco horizontal justify="between" className="-mb-1 -mt-1">
                      <h4>{`Medição ${nextMedicaoNum}`}</h4>
                      <InputBlock
                        name="dataMedicao"
                        label="Data Medição"
                        type="date"
                        inputProps={form.getInputProps('dataMedicao')}
                      />
                    </Bloco>
                  </Table.Th>
                </Table.Tr>
                <Table.Tr className="justify-end">
                  <Table.Th w={`22%`}>Qtde.</Table.Th>
                  <Table.Th w={`21%`}>Valor Total</Table.Th>
                  <Table.Th w={`21%`}>Acumulado Liberado</Table.Th>
                  <Table.Th w={`15%`} className="text-right">
                    Saldo Qtd
                  </Table.Th>
                  <Table.Th w={`21%`} className="text-right">
                    Saldo Valor
                  </Table.Th>
                </Table.Tr>
              </Table.Thead>
              <Table.Tbody>
                {calculatedData.map((row, index) => (
                  <Table.Tr key={index} className="medicao h-12">
                    {row.dataType === 'category' ||
                    row.dataType === 'subcategory' ||
                    row.dataType === 'sum' ? (
                      <>
                        <Table.Td
                          colSpan={Math.round(Number(row.newSaldoValorPerc)) === 100 ? 5 : 4}
                        >
                          <Progress.Root size={20}>
                            <Tooltip label={`${formatarQtd(row.newSaldoValorPerc)}% Concluído`}>
                              <Progress.Section value={row.newSaldoValorPerc || 0} color="violet">
                                <Progress.Label className="font-normal">
                                  {`${formatarQtd(row.newSaldoValorPerc)}% Concluído`}
                                </Progress.Label>
                              </Progress.Section>
                            </Tooltip>
                          </Progress.Root>
                        </Table.Td>
                        {Math.round(Number(row.newSaldoValorPerc)) !== 100 && (
                          <Table.Td className="text-right font-bold">
                            {formatarMoeda(row.newSaldoValor)}
                          </Table.Td>
                        )}
                      </>
                    ) : (
                      <>
                        <Table.Td>
                          <TextInput
                            h={20}
                            className="input-clear"
                            type="text"
                            onBlur={(e) => {
                              const value = parseFloat(e.target.value);

                              if (!value) {
                                e.target.value = '';
                                handleMedicaoChange(index, 0);
                                return;
                              }

                              const qtdMax =
                                row.saldoQtd === null ? Number(row.qtd) : Number(row.saldoQtd);

                              if (value > qtdMax) {
                                // Valor não pode ser maior que a qtd
                                e.target.value = qtdMax === 0 ? '' : qtdMax.toString();
                                e.target.classList.add('blink-input-error');
                                handleMedicaoChange(index, qtdMax);
                                setTimeout(() => {
                                  e.target.classList.remove('blink-input-error');
                                }, 1000);
                              } else {
                                if (
                                  Number(row.qtd) - Number(row.saldoQtd) + value < 0 ||
                                  // Se valor for menor que saldo
                                  row.newSaldoQtd === null
                                ) {
                                  e.target.value = '';
                                  e.target.classList.add('blink-input-error');
                                  handleMedicaoChange(index, 0);
                                  setTimeout(() => {
                                    e.target.classList.remove('blink-input-error');
                                  }, 1000);
                                } else {
                                  handleMedicaoChange(index, value);
                                }
                              }
                            }}
                            onKeyDown={(event) => {
                              const isLetterKey = /^[a-zA-Z,]$/.test(event.key);

                              if (isLetterKey) {
                                event.preventDefault();
                              }
                            }}
                          />
                        </Table.Td>
                        <Table.Td>
                          <div className="flex flex-direction-column gap-1 justify-end">
                            {formatarMoeda(row.newValorTotal || 0)}{' '}
                            <RingProgress
                              size={22}
                              thickness={4}
                              sections={[
                                {
                                  value: row.newValorTotalPerc || 0,
                                  color: 'blue',
                                  tooltip: `${formatarQtd(row.newValorTotalPerc)}% Concluído`,
                                },
                              ]}
                            />
                          </div>
                        </Table.Td>
                        <Table.Td>
                          <div className="flex flex-direction-column gap-1 justify-end">
                            {formatarMoeda(row.newAcumulado || 0)}{' '}
                            <RingProgress
                              size={22}
                              thickness={3}
                              sections={[
                                {
                                  value: row.newAcumuladoPerc || row.acumuladoPerc || 0,
                                  color: 'orange',
                                },
                              ]}
                            />
                          </div>
                        </Table.Td>
                        <Table.Td className="text-right">{formatarQtd(row.newSaldoQtd)}</Table.Td>
                        <Table.Td className="text-right">
                          {formatarMoeda(row.newSaldoValor || 0)}
                        </Table.Td>
                        {/* ) : (
                          <>
                            <Table.Td colSpan={5}>
                              <Progress.Root size={18}>
                                <Progress.Section value={row.acumuladoPerc || 0} color="blue">
                                  <Progress.Label className="font-normal">
                                    {`${formatarQtd(
                                      row.acumuladoPerc
                                    )}% Concluído (R$ ${formatarMoeda(row.acumulado)})`}
                                  </Progress.Label>
                                </Progress.Section>
                              </Progress.Root>
                            </Table.Td>
                          </>
                        )} */}
                      </>
                    )}
                  </Table.Tr>
                ))}
              </Table.Tbody>
              <Table.Tfoot className="text-base">
                <Table.Tr>
                  <Table.Td colSpan={4} className="text-right font-bold">
                    Valor Total Medição
                  </Table.Td>
                  <Table.Td className="text-right">
                    {formatarMoeda(totaisMedicao.valorTotal)}
                  </Table.Td>
                </Table.Tr>
                <Table.Tr>
                  <Table.Td colSpan={4} className="text-right font-bold">
                    Valor Total Mão de Obra
                  </Table.Td>
                  <Table.Td className="text-right">
                    {formatarMoeda(totaisMedicao.valorTotalMaodeObra)}
                  </Table.Td>
                </Table.Tr>
                <Table.Tr>
                  <Table.Td colSpan={4} className="text-right font-bold">
                    Valor Total Material
                  </Table.Td>
                  <Table.Td className="text-right">
                    {formatarMoeda(totaisMedicao.valorTotalMaterial)}
                  </Table.Td>
                </Table.Tr>
                <Table.Tr>
                  <Table.Td colSpan={4} className="text-right font-bold">
                    Acumulado Liberado
                  </Table.Td>
                  <Table.Td className="text-right">
                    {formatarMoeda(totaisMedicao.valorAcumulado)}
                  </Table.Td>
                </Table.Tr>
                <Table.Tr>
                  <Table.Td colSpan={5} className="text-right">
                    <Button
                      type="submit"
                      loading={loading}
                      className="btn btn-primary w-full gap-2"
                    >
                      Salvar Medição
                    </Button>
                  </Table.Td>
                </Table.Tr>
              </Table.Tfoot>
            </Table>
          </form>
        </Resizer.Section>
      </Resizer.Container>
    </div>
  );
};

export default AddMedicao;