From a7d890aeecbd8e6e2bcb71e2faf675e67fa4731d Mon Sep 17 00:00:00 2001
From: Fedor Katurov <gotham48@gmail.com>
Date: Fri, 5 Mar 2021 11:32:50 +0700
Subject: [PATCH] fixed error translation

---
 src/components/input/InputText/index.tsx     |  7 ++++--
 src/constants/errors.ts                      |  2 ++
 src/containers/dialogs/LoginDialog/index.tsx |  8 +++++--
 src/redux/auth/sagas.ts                      | 23 ++++++++++++++------
 src/utils/hooks/useTranslatedError.ts        | 17 +++++++++++++++
 5 files changed, 46 insertions(+), 11 deletions(-)
 create mode 100644 src/utils/hooks/useTranslatedError.ts

diff --git a/src/components/input/InputText/index.tsx b/src/components/input/InputText/index.tsx
index 5495c068..1d4f4153 100644
--- a/src/components/input/InputText/index.tsx
+++ b/src/components/input/InputText/index.tsx
@@ -4,6 +4,7 @@ import styles from '~/styles/common/inputs.module.scss';
 import { Icon } from '~/components/input/Icon';
 import { IInputTextProps } from '~/redux/types';
 import { LoaderCircle } from '~/components/input/LoaderCircle';
+import { useTranslatedError } from '~/utils/hooks/useTranslatedError';
 
 const InputText: FC<IInputTextProps> = ({
   wrapperClassName,
@@ -36,6 +37,8 @@ const InputText: FC<IInputTextProps> = ({
   const onFocus = useCallback(() => setFocused(true), []);
   const onBlur = useCallback(() => setFocused(false), []);
 
+  const translatedError = useTranslatedError(error);
+
   useEffect(() => {
     if (onRef) onRef(inner_ref);
   }, [inner_ref, onRef]);
@@ -86,9 +89,9 @@ const InputText: FC<IInputTextProps> = ({
         </div>
       )}
 
-      {error && (
+      {!!translatedError && (
         <div className={styles.error}>
-          <span>{error}</span>
+          <span>{translatedError}</span>
         </div>
       )}
 
diff --git a/src/constants/errors.ts b/src/constants/errors.ts
index fbb68c4e..bf88f347 100644
--- a/src/constants/errors.ts
+++ b/src/constants/errors.ts
@@ -42,6 +42,7 @@ export const ERRORS = {
   CANT_RESTORE_COMMENT: 'CantRestoreComment',
   MESSAGE_NOT_FOUND: 'MessageNotFound',
   COMMENT_TOO_LONG: 'CommentTooLong',
+  NETWORK_ERROR: 'Network Error',
 };
 
 export const ERROR_LITERAL = {
@@ -89,4 +90,5 @@ export const ERROR_LITERAL = {
   [ERRORS.CANT_RESTORE_COMMENT]: 'Не удалось восстановить комментарий',
   [ERRORS.MESSAGE_NOT_FOUND]: 'Сообщение не найдено',
   [ERRORS.COMMENT_TOO_LONG]: 'Комментарий слишком длинный',
+  [ERRORS.NETWORK_ERROR]: 'Подключение не удалось',
 };
diff --git a/src/containers/dialogs/LoginDialog/index.tsx b/src/containers/dialogs/LoginDialog/index.tsx
index 23792200..9aa7d12b 100644
--- a/src/containers/dialogs/LoginDialog/index.tsx
+++ b/src/containers/dialogs/LoginDialog/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC, FormEvent, useCallback, useEffect, useState } from 'react';
+import React, { FC, FormEvent, useCallback, useEffect, useMemo, useState } from 'react';
 import { connect } from 'react-redux';
 import { DIALOGS, IDialogProps } from '~/redux/modal/constants';
 import { useCloseOnEscape } from '~/utils/hooks';
@@ -18,6 +18,8 @@ import { pick } from 'ramda';
 import { LoginDialogButtons } from '~/containers/dialogs/LoginDialogButtons';
 import { OAUTH_EVENT_TYPES } from '~/redux/types';
 import { DialogTitle } from '~/components/dialogs/DialogTitle';
+import { ERROR_LITERAL } from '~/constants/errors';
+import { useTranslatedError } from '~/utils/hooks/useTranslatedError';
 
 const mapStateToProps = state => ({
   ...pick(['error', 'is_registering'], selectAuthLogin(state)),
@@ -90,12 +92,14 @@ const LoginDialogUnconnected: FC<IProps> = ({
 
   useCloseOnEscape(onRequestClose);
 
+  const translatedError = useTranslatedError(error);
+
   return (
     <form onSubmit={onSubmit}>
       <div>
         <BetterScrollDialog
           width={300}
-          error={error}
+          error={translatedError}
           onClose={onRequestClose}
           footer={<LoginDialogButtons openOauthWindow={openOauthWindow} />}
           backdrop={<div className={styles.backdrop} />}
diff --git a/src/redux/auth/sagas.ts b/src/redux/auth/sagas.ts
index 8f029a01..40d8912b 100644
--- a/src/redux/auth/sagas.ts
+++ b/src/redux/auth/sagas.ts
@@ -349,10 +349,14 @@ function* loginWithSocial({ token }: ReturnType<typeof authLoginWithSocial>) {
       return;
     }
   } catch (error) {
-    const data = (error as AxiosError<{ needs_register: boolean }>).response?.data;
+    const { dialog }: ReturnType<typeof selectModal> = yield select(selectModal);
+    const data = (error as AxiosError<{
+      needs_register: boolean;
+      errors: Record<'username' | 'password', string>;
+    }>).response?.data;
 
     // Backend asks us for account registration
-    if (data?.needs_register) {
+    if (dialog !== DIALOGS.LOGIN_SOCIAL_REGISTER && data?.needs_register) {
       yield put(authSetRegisterSocial({ token }));
       yield put(modalShowDialog(DIALOGS.LOGIN_SOCIAL_REGISTER));
       return;
@@ -391,11 +395,6 @@ function* authRegisterSocial({ username, password }: ReturnType<typeof authSendR
       password,
     });
 
-    if (data?.errors) {
-      yield put(authSetRegisterSocialErrors(data.errors));
-      return;
-    }
-
     if (data.token) {
       yield put(authSetToken(data.token));
       yield call(refreshUser);
@@ -403,6 +402,16 @@ function* authRegisterSocial({ username, password }: ReturnType<typeof authSendR
       return;
     }
   } catch (error) {
+    const data = (error as AxiosError<{
+      needs_register: boolean;
+      errors: Record<'username' | 'password', string>;
+    }>).response?.data;
+
+    if (data?.errors) {
+      yield put(authSetRegisterSocialErrors(data.errors));
+      return;
+    }
+
     yield put(authSetRegisterSocial({ error: error.message }));
   }
 }
diff --git a/src/utils/hooks/useTranslatedError.ts b/src/utils/hooks/useTranslatedError.ts
new file mode 100644
index 00000000..22ef367f
--- /dev/null
+++ b/src/utils/hooks/useTranslatedError.ts
@@ -0,0 +1,17 @@
+import { ERROR_LITERAL } from '~/constants/errors';
+import { has } from 'ramda';
+import { useMemo } from 'react';
+
+export const useTranslatedError = (error: string | undefined) => {
+  return useMemo(() => {
+    if (!error) {
+      return '';
+    }
+
+    if (!has(error, ERROR_LITERAL)) {
+      return error;
+    }
+
+    return ERROR_LITERAL[error];
+  }, [error]);
+};