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


import { useDeviceRepository } from '@/domains/equipment/repositories/device.repository';
import { normalizeSipUriForPayload } from '@/domains/equipment/repositories/helpers/normalizeSipUriForPayload';
import { usePreservedSipUri } from '@/domains/equipment/repositories/helpers/usePreservedSipUri';
import {
  DeviceModel,
  useAddDeviceModelMutation,
  useGetDeviceModelByIdQuery,
} from '@/shared/api/controller/client';
import { Ieee8021X } from '@/widgets/Monitoring/model/networkEquipment.model';

import { yupResolver } from '@hookform/resolvers/yup';
import { QueryStatus, skipToken } from '@reduxjs/toolkit/query';
import { Button, Drawer, DrawerActions } from '@shared/components';
import { useCloseDrawer } from '@shared/hooks/drawer/useCloseDrawer';
import { useSelectDrawerType } from '@shared/hooks/drawer/useSelectDrawerType';
import {
  EventActionTypes,
  useSendClickStreamEvent,
} from '@shared/hooks/useSendClickStreamEvent';
import { DrawerTypes } from '@shared/model/drawer/drawer.types';
import { useSelectActiveController } from '@shared/store/сontrollers/сontrollers.selectors';
import { useSyncControlPage } from '@widgets/Monitoring/hooks';
import { memo, useEffect, useState } from 'react';
import {
  FormProvider,
  Resolver,
  SubmitHandler,
  useForm,
} from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { CreateDeviceForm } from '../CreateDeviceForm';
import { CreateDeviceFormData } from '../model/types';
import { createDeviceFormSchema } from '../validation/validator';

const defaultValues: CreateDeviceFormData = {
  name: '',
  description: '',
  ip: '',
  mac: '',
  controlPage: '',
  typeName: '',
  manufacturerName: '',
  sipUri: '',
  hasSipUri: null,
  modelId: '',
  hardwareId: '',
  type: 'ethernet',
  bidirectional: false,
  ieee8021x: Ieee8021X.MAB,
  protocolIp: 'dhcp',
  firmware: null,
  serialNumber: null,
  inventoryNumber: null,
  ipAvLan: '',
  localAddress: undefined,
  port: undefined,
  netInterface: false,
  netInterfaceInfo: [],
  disableMonitoring: false,
};

export const CreateDeviceDrawer = memo(() => {
  const { t } = useTranslation('common');
  const { sendEvent } = useSendClickStreamEvent(EventActionTypes.createDevice);

  const drawerType = useSelectDrawerType();
  const isVisible = drawerType[DrawerTypes.createDevice];
  const closeDrawer = useCloseDrawer();
  const activeController = useSelectActiveController();

  const [model, setModel] = useState<DeviceModel | null>(null);
  const [createdModelId, setCreatedModelId] = useState<string | null>(null);

  const { preserveSipUri, getPreservedSipUri, resetPreservedSipUri } =
    usePreservedSipUri();

  const [, createDeviceModelResult] = useAddDeviceModelMutation({
    fixedCacheKey: 'create-device-model',
  });

  useEffect(() => {
    const id = createDeviceModelResult.data?.id;

    if (id) {
      setCreatedModelId(id);
    }
  }, [createDeviceModelResult.data?.id]);

  const { data: createdModel } = useGetDeviceModelByIdQuery(
    createdModelId ? { modelId: createdModelId } : skipToken,
    {
      refetchOnMountOrArgChange: true,
    },
  );

  useEffect(() => {
    if (createdModel) {
      setModel(createdModel);
    }
  }, [createdModel]);

  const {
    saveDevice,
    createDeviceStatus,
    isCreateDeviceLoading,
    resetCreateDevice,
  } = useDeviceRepository();

  const methods = useForm<CreateDeviceFormData>({
    mode: 'onBlur',
    reValidateMode: 'onChange',
    defaultValues,
    resolver: yupResolver(
      createDeviceFormSchema,
    ) as Resolver<CreateDeviceFormData>,
  });

  useSyncControlPage(defaultValues.ip, methods);

  useEffect(() => {
    const currentHasSipUri = methods.getValues('hasSipUri');

    if (currentHasSipUri) {
      preserveSipUri(methods.getValues('sipUri'));
    }

    if (model) {
      const modelHasSipUri = model.type?.hasSipUri ?? false;

      methods.setValue('modelId', model.id || '');
      methods.setValue('manufacturerName', model.manufacturer?.name);
      methods.setValue('typeName', model.type?.name);
      methods.setValue('hasSipUri', modelHasSipUri);

      if (modelHasSipUri) {
        methods.setValue('sipUri', getPreservedSipUri());
      }

      return;
    }

    methods.setValue('modelId', '');
    methods.resetField('manufacturerName');
    methods.resetField('typeName');
    methods.setValue('hasSipUri', null);
  }, [model, methods, preserveSipUri, getPreservedSipUri]);

  useEffect(() => {
    if (isVisible) {
      methods.reset(defaultValues);
      resetPreservedSipUri();
      setCreatedModelId(null);
      setModel(null);
    }
  }, [isVisible, methods, resetPreservedSipUri]);

  useEffect(() => {
    if (createDeviceStatus === QueryStatus.fulfilled) {
      closeDrawer(DrawerTypes.createDevice);
      methods.reset(defaultValues);
      resetPreservedSipUri();
      resetCreateDevice();
      setCreatedModelId(null);
      setModel(null);
      sendEvent();
    }
  }, [
    createDeviceStatus,
    closeDrawer,
    methods,
    resetPreservedSipUri,
    resetCreateDevice,
    sendEvent,
  ]);

  const submitHandler: SubmitHandler<CreateDeviceFormData> = (values) => {
    if (activeController?.id) {
      saveDevice(normalizeSipUriForPayload(values), activeController.id);
    }
  };

  const actions: DrawerActions = {
    actionPrimary: (
      <Button
        data-fui-tid={`${DrawerTypes.createDevice}-actionPrimary`}
        onClick={methods.handleSubmit(submitHandler)}
        loading={isCreateDeviceLoading}
        disabled={!methods.formState.isValid}
      >
        {t('buttons.save')}
      </Button>
    ),
  };

  return (
    <FormProvider {...methods}>
      <Drawer
        type={DrawerTypes.createDevice}
        actions={actions}
        title={t('drawerTitle.createDevice')}
      >
        <CreateDeviceForm setModel={setModel} model={model} />
      </Drawer>
    </FormProvider>
  );
});