Alert component code improvement

1. Removed redundant alert component, it now passes alert color as variable
2. Added related translations
3. The missing the alert content for login and register responses will be added once the login flow is clear
4. Made alert component a context provider to be globally accessible

Change-Id: Iab3c822b6296a4060c38c4a2a1fdb2fa937dec52
diff --git a/client/src/contexts/AlertSnackbarProvider.tsx b/client/src/contexts/AlertSnackbarProvider.tsx
new file mode 100644
index 0000000..e5da7be
--- /dev/null
+++ b/client/src/contexts/AlertSnackbarProvider.tsx
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+import { Alert, AlertColor, AlertProps, AlertTitle, Snackbar, SnackbarProps } from '@mui/material';
+import { createContext, useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { SetState, WithChildren } from '../utils/utils';
+type AlertSnackbarProps = AlertProps & {
+  severity: AlertColor;
+  open?: boolean;
+  snackBarProps?: Partial<SnackbarProps>;
+};
+
+export type AlertContent = {
+  messageI18nKey: AlertMessageKeys;
+  messageI18nContext?: object;
+  severity: AlertColor;
+  alertOpen: boolean;
+};
+
+export function AlertSnackbar({ severity, open, snackBarProps, children, ...alertProps }: AlertSnackbarProps) {
+  const { t } = useTranslation();
+
+  return (
+    <Snackbar
+      open={open}
+      {...snackBarProps}
+      anchorOrigin={{
+        vertical: 'top',
+        horizontal: 'center',
+        ...snackBarProps?.anchorOrigin,
+      }}
+    >
+      <Alert severity={severity} {...alertProps}>
+        <AlertTitle>{t('severity', { context: `${severity}` })}</AlertTitle>
+        {children}
+      </Alert>
+    </Snackbar>
+  );
+}
+
+type IAlertSnackbarContext = {
+  alertContent: AlertContent;
+  setAlertContent: SetState<AlertContent>;
+};
+
+const defaultAlertSnackbarContext: IAlertSnackbarContext = {
+  alertContent: {
+    messageI18nKey: '',
+    messageI18nContext: {},
+    severity: 'info',
+    alertOpen: false,
+  },
+  setAlertContent: () => {},
+};
+
+type AlertMessageKeys =
+  | 'missed_incoming_call'
+  | 'unknown_error_alert'
+  | 'username_input_helper_text_empty'
+  | 'password_input_helper_text_empty'
+  | 'login_invalid_password'
+  | 'registration_success'
+  | '';
+
+export const AlertSnackbarContext = createContext<IAlertSnackbarContext>(defaultAlertSnackbarContext);
+
+const AlertSnackbarProvider = ({ children }: WithChildren) => {
+  const { t } = useTranslation();
+  const [alertContent, setAlertContent] = useState<AlertContent>(defaultAlertSnackbarContext.alertContent);
+  const closeAlert = () => {
+    setAlertContent((prev) => {
+      return {
+        ...prev,
+        alertOpen: false,
+      };
+    });
+  };
+
+  //This is to explicitly let i18n know that these keys should be extracted
+  const getAlertMessageText = useCallback(
+    (messageI18nKey: AlertMessageKeys, messageI18nContext?: object): string => {
+      switch (messageI18nKey) {
+        case 'missed_incoming_call':
+          return t('missed_incoming_call', { ...messageI18nContext });
+        case 'unknown_error_alert':
+          return t('unknown_error_alert');
+        case 'username_input_helper_text_empty':
+          return t('username_input_helper_text_empty');
+        case 'password_input_helper_text_empty':
+          return t('password_input_helper_text_empty');
+        case 'login_invalid_password':
+          return t('login_invalid_password');
+        case 'registration_success':
+          return t('registration_success');
+        default:
+          return t('unknown_error_alert');
+      }
+    },
+    [t]
+  );
+
+  const value = {
+    alertContent,
+    setAlertContent,
+  };
+
+  return (
+    <>
+      <AlertSnackbar severity={alertContent.severity} open={alertContent.alertOpen} onClose={closeAlert}>
+        {getAlertMessageText(alertContent.messageI18nKey, alertContent.messageI18nContext)}
+      </AlertSnackbar>
+      <AlertSnackbarContext.Provider value={value}>{children}</AlertSnackbarContext.Provider>
+    </>
+  );
+};
+
+export default AlertSnackbarProvider;