Загрузка данных


dmitriev-aal@VDI-Dmitriev-A:~/Desktop/rshbintech/crft/ckof/ownfin/frontend/prd/autopayments-ui$ cat src/client/view/auto-payment-edit-page/index.tsx
import {
  BasicAction,
  NavigationBar,
  useTemplateLayout,
} from "@rshbintech.ckof.ownfin/core-ui";
import { useEffect, useMemo, useRef } from "react";
import { useParams, useNavigate, generatePath } from "react-router-dom";
import { Icons } from "@rshbintech.ckof.ownfin/icons";
import { useAppSelector } from "src/hooks";
import { ToastNotificationContainer } from "src/client/shared/ui/toast-notification-container";
import {
  getAutoPaymentsSelector,
  getTemplateByIdSelector,
  selectNewAdditionalAccount,
} from "src/client/model/get-auto-payments/selectors";
import { useScrollAnchor } from "src/client/view/auto-transfer-edit-page/use-scroll-anchor";
import { useNameInput } from "src/client/view/auto-transfer-edit-page/hooks/use-name-input";
import { AmountInputPage } from "src/client/view/auto-transfer-edit-page/components/amount-input-page";
import { useAmountInputPage } from "src/client/view/auto-transfer-edit-page/hooks/use-amount-input-page";
import { useEditFormState } from "src/client/view/auto-transfer-edit-page/hooks/use-edit-form-state";
import { useSaveEntityChanges } from "src/client/view/auto-transfer-edit-page/hooks/use-save-changes/use-save-changes";
import { useFormChanges } from "src/client/view/auto-transfer-edit-page/hooks/use-form-changes/use-form-changes";
import { FormChangesResultWithAdditional } from "src/client/view/auto-transfer-edit-page/hooks/use-form-changes/types";
import { EntityType } from "src/client/view/auto-transfer-edit-page/hooks/use-save-changes/types";
import { accountsSelector } from "src/client/model/accounts-payments/selectors";
import { ROUTES } from "src/constants";
import { PaymentRecurrentType } from "src/client/common/types";
import { EditForm } from "./components/edit-form";
import { usePaymentScheduleNavigation } from "./hooks/use-schedule-navigation/use-payment-schedule-navigation";
import { convertScheduleTypeToPayment, validateAmount } from "./utils";
import {
  HEADER_TEXT,
  DATA_TEST_ID_PAGE,
  SAVE_CHANGES_BASIC_ACTION_TITLE,
} from "./constants";
import styles from "./styles.scss";

export const AutoPaymentEditPage = () => {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();

  const autoPayment = useAppSelector(getTemplateByIdSelector);
  const autoPaymentsData = useAppSelector(getAutoPaymentsSelector);
  const templateById = (autoPaymentsData ?? []).find(
    (template) => template.id === id
  );

  const screenRef = useRef<HTMLDivElement>(null);

  const { withShadowBottom, scrollHandler } = useTemplateLayout({ screenRef });

  const accounts = useAppSelector(accountsSelector);

  const newAdditionalAccount = useAppSelector(selectNewAdditionalAccount);

  const {
    containerRef: formsContainerRef,
    bottomRef,
    bottomStyle,
    scrollToBottom,
  } = useScrollAnchor();

  const formState = useEditFormState({
    entity: autoPayment,
    userProducts: accounts,
    getAmount: (entity) => entity.amount?.toString() || "",
    getProductId: (entity) => entity.accountId,
    getUserProductId: (product) => product.id,
  });

  const nameInput = useNameInput("", scrollToBottom);

  useEffect(() => {
    const state = formState.locationState;

    if (state?.nameValue !== undefined) {
      nameInput.setNameValue(state.nameValue);
      formState.setLocationState(null);
    } else if (autoPayment?.name && !nameInput.nameValue) {
      nameInput.setNameValue(autoPayment.name);
    }
  }, [autoPayment?.name, formState.locationState]);

  const amountInputPage = useAmountInputPage({
    entity: autoPayment,
    amountValue: formState.amountValue,
    setAmountValue: formState.setAmountValue,
    onGoBackFromMain: () =>
      navigate(
        generatePath(ROUTES.AUTO_PAYMENT_DETAIL_PAGE, { id: autoPayment?.id })
      ),
  });

  const hasActualScheduleChanges = useMemo(() => {
    if (!autoPayment || !formState.scheduleChanges) {
      return false;
    }

    const newScheduleType = convertScheduleTypeToPayment(
      formState.scheduleChanges.scheduleType
    );

    const initRecurrentType = autoPayment.recurrentType;
    const sameScheduleTypes = newScheduleType === initRecurrentType;

    const areArraysEqual = (
      arr1: number[] | undefined,
      arr2: number[] | undefined
    ) => {
      if (arr1 === arr2) {
        return true;
      }

      if (!arr1 || !arr2) {
        return false;
      }

      if (arr1.length !== arr2.length) {
        return false;
      }

      const sorted1 = [...arr1].sort((a, b) => a - b);
      const sorted2 = [...arr2].sort((a, b) => a - b);

      return sorted1.every((value, index) => value === sorted2[index]);
    };

    if (sameScheduleTypes) {
      if (
        newScheduleType === PaymentRecurrentType.DAILY &&
        initRecurrentType === PaymentRecurrentType.DAILY
      ) {
        return false;
      }

      if (
        newScheduleType === PaymentRecurrentType.WEEKLY &&
        initRecurrentType === PaymentRecurrentType.WEEKLY
      ) {
        return !areArraysEqual(
          formState.scheduleChanges.weekDays,
          autoPayment.days
        );
      }

      if (
        newScheduleType === PaymentRecurrentType.MONTHLY &&
        initRecurrentType === PaymentRecurrentType.MONTHLY
      ) {
        return !areArraysEqual(
          formState.scheduleChanges.monthDays,
          autoPayment.days
        );
      }
    }

    return true;
  }, [autoPayment, formState.scheduleChanges]);

  const formChanges = useFormChanges({
    amountValue: formState.amountValue,
    nameValue: nameInput.nameValue,
    activeProductIndex: formState.activeProductIndex,
    initialProductIndex: formState.initialProductIndexRef.current,
    scheduleChanges: formState.scheduleChanges,
    hasScheduleChangesFlag: hasActualScheduleChanges,
    entity: autoPayment,
    userProducts: accounts,
    additionalAccountId: newAdditionalAccount,
  }) as FormChangesResultWithAdditional;

  const saveChanges = useSaveEntityChanges({
    id,
    entityType: EntityType.PAYMENT,
    autoPayment,
    userProducts: accounts,
    activeProductIndex: formState.activeProductIndex,
    amountValue: formState.amountValue,
    nameValue: nameInput.nameValue,
    scheduleChanges: formState.scheduleChanges,
    hasSumChanged: formChanges.hasSumChanged,
    hasNameChanged: formChanges.hasNameChanged,
    hasAccountChanged: formChanges.hasAccountChanged,
    hasScheduleChanged: formChanges.hasScheduleChanged,
    hasChanges: formChanges.hasChanges,
    hasAdditionalAccountChanged: formChanges.hasAdditionalAccountChanged,
    newAdditionalAccount,
  });

  const scheduleNavigation = usePaymentScheduleNavigation({
    id,
    autoPayment,
    scheduleChanges: formState.scheduleChanges,
    amountValue: formState.amountValue,
    nameValue: nameInput.nameValue,
    activeProductIndex: formState.activeProductIndex,
  });

  useEffect(() => {
    if (id && !autoPayment) {
      navigate(-1);
    }
  }, [id, autoPayment, navigate]);

  const isAmountError = useMemo(
    () => validateAmount(formState.amountValue),
    [formState.amountValue]
  );

  if (!autoPayment || !accounts) {
    return null;
  }

  return (
    <div
      className={styles["auto-payment-edit-page"]}
      data-test-id={DATA_TEST_ID_PAGE}
      ref={screenRef}
      onScroll={scrollHandler}
    >
      <NavigationBar
        title={HEADER_TEXT}
        leftButton={<Icons.ArrowLeftBase />}
        onLeftButtonClick={amountInputPage.handleGoBack}
        background
        safeTop
        className={styles["nav-bar"]}
        fixed
      />
      <div className={styles["content-wrapper"]}>
        {amountInputPage.isAmountInputPage ? (
          <AmountInputPage
            amountValue={formState.amountValue}
            currency={templateById?.currency}
            amountInputRef={amountInputPage.amountInputRef}
            onAmountChange={formState.setAmountValue}
            onGoBack={amountInputPage.handleGoBack}
            isAmountInputPage={amountInputPage.isAmountInputPage}
            onBackToForm={amountInputPage.backToForm}
            onFocus={nameInput.handleNameInputFocus}
            onBlur={nameInput.handleNameInputBlur}
          />
        ) : (
          <>
            <EditForm
              autoPayment={autoPayment}
              currency={templateById?.currency}
              activeProductIndex={formState.activeProductIndex}
              amountValue={formState.amountValue}
              nameValue={nameInput.nameValue}
              scheduleChanges={formState.scheduleChanges}
              isAmountError={isAmountError}
              nameInputRef={nameInput.nameInputRef}
              formsContainerRef={formsContainerRef}
              bottomRef={bottomRef}
              bottomStyle={bottomStyle}
              onProductChange={formState.setActiveProductIndex}
              onAmountClick={amountInputPage.handleSumClick}
              onNameChange={nameInput.handleNameValueChange}
              onNameFocus={nameInput.handleNameInputFocus}
              onNameBlur={nameInput.handleNameInputBlur}
              onScheduleClick={scheduleNavigation.handleScheduleClick}
            />
            <BasicAction
              disablePrimaryButton={!formChanges.hasChanges}
              onButtonClick={saveChanges.handleSaveChanges}
              isLoadingPrimaryButton={saveChanges.isLoading}
              fixed
              safeBottom={!nameInput.isInputFocused}
              shadow={withShadowBottom}
            >
              {SAVE_CHANGES_BASIC_ACTION_TITLE}
            </BasicAction>
          </>
        )}
      </div>
      {saveChanges.fullScreenLoader}
      <ToastNotificationContainer targetPage={DATA_TEST_ID_PAGE} />
    </div>
  );
};