add redux setup and typescript configuration

Change-Id: Ibe00e3e969d539d3898e412a0093ee2076bec857
diff --git a/client/package.json b/client/package.json
index b60b40e..3f70bca 100644
--- a/client/package.json
+++ b/client/package.json
@@ -4,42 +4,50 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
-    "@babel/runtime": "^7.17.9",
-    "@emotion/react": "^11.9.0",
-    "@emotion/styled": "^11.8.1",
-    "@mui/icons-material": "^5.6.2",
-    "@mui/lab": "^5.0.0-alpha.79",
-    "@mui/material": "^5.6.3",
-    "@mui/styles": "^5.6.2",
-    "@testing-library/jest-dom": "^4.2.4",
-    "@testing-library/react": "^9.5.0",
-    "@testing-library/user-event": "^7.2.1",
+    "@babel/runtime": "7.18.9",
+    "@emotion/react": "^11.10.0",
+    "@emotion/styled": "^11.10.0",
+    "@mui/icons-material": "^5.10.2",
+    "@mui/lab": "^5.0.0-alpha.96",
+    "@mui/material": "^5.10.2",
+    "@mui/styles": "^5.10.2",
+    "@reduxjs/toolkit": "^1.8.5",
+    "@testing-library/jest-dom": "^5.16.5",
+    "@testing-library/react": "^13.3.0",
+    "@testing-library/user-event": "^14.4.3",
     "dayjs": "^1.11.5",
-    "emoji-picker-react": "^3.5.1",
-    "react": "^17.0.2",
-    "react-dom": "^17.0.2",
+    "@types/jest": "^28.1.8",
+    "emoji-picker-react": "^3.6.1",
+    "framer-motion": "^7.2.1",
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0",
     "react-emoji-render": "^1.2.4",
     "react-fetch-hook": "^1.9.5",
+    "react-redux": "^8.0.2",
     "react-router-dom": "^6.3.0",
-    "socket.io-client": "^4.5.0",
-    "framer-motion": "^6.3.2"
+    "socket.io-client": "^4.5.1"
   },
   "devDependencies": {
-    "@babel/core": "^7.17.9",
-    "@babel/plugin-transform-runtime": "^7.17.0",
-    "@babel/preset-env": "^7.16.11",
-    "@babel/preset-react": "^7.16.7",
-    "@pmmmwh/react-refresh-webpack-plugin": "^0.5.5",
-    "babel-loader": "^8.2.2",
-    "copy-webpack-plugin": "^8.1.1",
+    "@babel/core": "^7.18.13",
+    "@babel/plugin-transform-runtime": "^7.18.10",
+    "@babel/preset-env": "^7.18.10",
+    "@babel/preset-react": "^7.18.6",
+    "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
+    "@types/node": "^18.7.13",
+    "@types/react": "^18.0.17",
+    "@types/react-dom": "^18.0.6",
+    "babel-loader": "^8.2.5",
+    "copy-webpack-plugin": "^11.0.0",
     "css-loader": "^6.7.1",
     "html-webpack-plugin": "^5.5.0",
-    "react-refresh": "^0.12.0",
-    "sass": "^1.51.0",
-    "sass-loader": "^12.6.0",
+    "react-refresh": "^0.14.0",
+    "sass": "^1.54.5",
+    "sass-loader": "^13.0.2",
     "style-loader": "^3.3.1",
-    "webpack": "^5.72.0",
-    "webpack-cli": "^4.9.2"
+    "ts-loader": "^9.3.1",
+    "typescript": "^4.7.4",
+    "webpack": "^5.74.0",
+    "webpack-cli": "^4.10.0"
   },
   "scripts": {
     "build": "npx webpack"
diff --git a/client/redux/appSlice.ts b/client/redux/appSlice.ts
new file mode 100644
index 0000000..f0fc628
--- /dev/null
+++ b/client/redux/appSlice.ts
@@ -0,0 +1,37 @@
+import { createSlice, PayloadAction } from "@reduxjs/toolkit";
+import type { RootState } from "./store";
+
+// Define a type for the slice state
+interface appState {
+  value: number;
+}
+
+// Define the initial state using that type
+const initialState: appState = {
+  value: 0,
+};
+
+export const appSlice = createSlice({
+  name: "app",
+  // `createSlice` will infer the state type from the `initialState` argument
+  initialState,
+  reducers: {
+    increment: (state) => {
+      state.value += 1;
+    },
+    decrement: (state) => {
+      state.value -= 1;
+    },
+    // Use the PayloadAction type to declare the contents of `action.payload`
+    incrementByAmount: (state, action: PayloadAction<number>) => {
+      state.value += action.payload;
+    },
+  },
+});
+
+export const { increment, decrement, incrementByAmount } = appSlice.actions;
+
+// Other code such as selectors can use the imported `RootState` type
+export const selectCount = (state: RootState) => state.app.value;
+
+export default appSlice.reducer;
diff --git a/client/redux/hooks.ts b/client/redux/hooks.ts
new file mode 100644
index 0000000..6875ea7
--- /dev/null
+++ b/client/redux/hooks.ts
@@ -0,0 +1,6 @@
+import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
+import type { RootState, AppDispatch } from "./store";
+
+// Use throughout your app instead of plain `useDispatch` and `useSelector`
+export const useAppDispatch: () => AppDispatch = useDispatch;
+export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
diff --git a/client/redux/store.ts b/client/redux/store.ts
new file mode 100644
index 0000000..d28f3d0
--- /dev/null
+++ b/client/redux/store.ts
@@ -0,0 +1,13 @@
+import { configureStore } from "@reduxjs/toolkit";
+import appReducer from "./appSlice";
+
+export const store = configureStore({
+  reducer: {
+    app: appReducer,
+  },
+});
+
+// Infer the `RootState` and `AppDispatch` types from the store itself
+export type RootState = ReturnType<typeof store.getState>;
+// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
+export type AppDispatch = typeof store.dispatch;
diff --git a/client/src/App.js b/client/src/App.js
index b685936..d0043df 100644
--- a/client/src/App.js
+++ b/client/src/App.js
@@ -19,6 +19,9 @@
 import WelcomeAnimation from './components/welcome'
 import defaultTheme from './themes/default'
 
+// import { useSelector, useDispatch } from 'react-redux'
+// import { useAppSelector, useAppDispatch } from '../redux/hooks'
+
 const Home = (props) => {
   console.log(`home ${props}`)
 
@@ -26,48 +29,65 @@
 }
 
 const App = (props) => {
-    const [state, setState] = useState({
-      loaded: false,
-      auth: authManager.getState()
-    })
-    const [displayWelcome, setDisplayWelcome] = useState(true)
+  // const count = useSelector(state => state.counter.value)
+  // const dispatch = useDispatch();
+  // const count = useAppSelector((state) => state.counter.value);
+  // const dispatch = useAppDispatch();
 
-    useEffect(() => {
-      authManager.init(auth => {
-        setState({ loaded: false, auth })
-      })
-      return () => authManager.deinit()
-    }, []);
+  const [state, setState] = useState({
+    loaded: false,
+    auth: authManager.getState(),
+  });
+  const [displayWelcome, setDisplayWelcome] = useState(true);
 
-    console.log("App render")
-    if (displayWelcome) {
-      return <WelcomeAnimation showSetup={!state.auth.setupComplete} onComplete={() => setDisplayWelcome(false)} />
-    } else if (!state.auth.setupComplete) {
-      return <Routes>
-          <Route path="/setup" element={<ServerSetup />} />
-          <Route path="/" element={<Navigate to="/setup" replace />} />
-          <Route index path="*" element={<Navigate to="/setup" replace />} />
-        </Routes>
-    }
+  useEffect(() => {
+    authManager.init((auth) => {
+      setState({ loaded: false, auth });
+    });
+    return () => authManager.deinit();
+  }, []);
 
-    return <ThemeProvider theme={defaultTheme}>
-    <Routes>
-      <Route path="/account">
-        <Route index element={<AccountSelection />} />
-        <Route path=":accountId">
-          <Route index path="*" element={<JamiMessenger />} />
-          <Route path="settings" element={<AccountSettings />} />
+  console.log("App render");
+
+  if (displayWelcome) {
+    return (
+      <WelcomeAnimation
+        showSetup={!state.auth.setupComplete}
+        onComplete={() => setDisplayWelcome(false)}
+      />
+    );
+  } else if (!state.auth.setupComplete) {
+    return (
+      <Routes>
+        <Route path="/setup" element={<ServerSetup />} />
+        <Route path="/" element={<Navigate to="/setup" replace />} />
+        <Route index path="*" element={<Navigate to="/setup" replace />} />
+      </Routes>
+    );
+  }
+
+  return (
+    <ThemeProvider theme={defaultTheme}>
+      <Routes>
+        <Route path="/account">
+          <Route index element={<AccountSelection />} />
+          <Route path=":accountId">
+            <Route index path="*" element={<JamiMessenger />} />
+            <Route path="settings" element={<AccountSettings />} />
+          </Route>
         </Route>
-      </Route>
-      <Route path="/newAccount" element={<AccountCreationDialog />}>
-        <Route path="jami" element={<JamiAccountDialog />} />
-      </Route>
-      <Route path="/setup" element={<ServerSetup />} />
-      <Route path="/" index element={<Home />} />
-      <Route path="*" element={<NotFoundPage />} />
-    </Routes>
-    {!state.auth.authenticated && <SignInPage key="signin" open={!state.auth.authenticated}/>}
+        <Route path="/newAccount" element={<AccountCreationDialog />}>
+          <Route path="jami" element={<JamiAccountDialog />} />
+        </Route>
+        <Route path="/setup" element={<ServerSetup />} />
+        <Route path="/" index element={<Home />} />
+        <Route path="*" element={<NotFoundPage />} />
+      </Routes>
+      {!state.auth.authenticated && (
+        <SignInPage key="signin" open={!state.auth.authenticated} />
+      )}
     </ThemeProvider>
-}
+  );
+};
 
 export default App
diff --git a/client/src/index.js b/client/src/index.js
index e607b8a..27b5591 100644
--- a/client/src/index.js
+++ b/client/src/index.js
@@ -1,28 +1,37 @@
-'use strict'
-import React from 'react'
-import ReactDOM from 'react-dom'
-import { BrowserRouter as Router } from 'react-router-dom'
-import App from './App.js'
-import './index.scss'
+"use strict";
+import React from "react";
+import ReactDOM from "react-dom";
+import { BrowserRouter as Router } from "react-router-dom";
+import App from "./App.js";
+import "./index.scss";
 
-const rootEl = document.getElementById('root')
+import { store } from "../redux/store";
+import { Provider } from "react-redux";
+//import { CssBaseline } from '@mui/material'
 
-const render = Component =>
-ReactDOM.render(
-  <React.StrictMode>
-    <Router>
-    <Component />
-    </Router>
-  </React.StrictMode>,
-  rootEl
-)
+//import * as serviceWorker from './serviceWorker'
+const rootEl = document.getElementById("root");
+var exports = {};
+
+const render = (Component) =>
+  ReactDOM.render(
+    <Provider store={store}>
+      <React.StrictMode>
+        <Router>
+          <Component />
+        </Router>
+      </React.StrictMode>
+    </Provider>,
+    rootEl
+  );
 
 render(App)
 
-if (import.meta.webpackHot) import.meta.webpackHot.accept('./App', () => {
-  try {
-    render(App)
-  } catch (e) {
-    location.reload()
-  }
-})
\ No newline at end of file
+if (import.meta.webpackHot)
+  import.meta.webpackHot.accept("./App", () => {
+    try {
+      render(App);
+    } catch (e) {
+      location.reload();
+    }
+  });
diff --git a/client/tsconfig.json b/client/tsconfig.json
new file mode 100644
index 0000000..c2fd010
--- /dev/null
+++ b/client/tsconfig.json
@@ -0,0 +1,103 @@
+{
+  "compilerOptions": {
+    /* Visit https://aka.ms/tsconfig to read more about this file */
+
+    /* Projects */
+    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
+    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
+    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
+    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
+    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
+
+    /* Language and Environment */
+    "target": "ES6",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
+    // "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
+    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
+    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
+    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
+    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
+
+    /* Modules */
+    // "module": "commonjs",                                /* Specify what module code is generated. */
+    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
+    "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
+    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
+    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
+    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
+    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
+    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
+    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
+    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
+    // "resolveJsonModule": true,                        /* Enable importing .json files. */
+    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
+
+    /* JavaScript Support */
+    "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
+    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+    /* Emit */
+    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
+    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
+    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
+    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+    // "outDir": "./",                                   /* Specify an output folder for all emitted files. */
+    // "removeComments": true,                           /* Disable emitting comments. */
+    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
+    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
+    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
+    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
+    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
+    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
+    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
+    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
+    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
+    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
+    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+    /* Interop Constraints */
+    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
+    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
+    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
+    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
+
+    /* Type Checking */
+    // "strict": true,                                      /* Enable all strict type-checking options. */
+    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
+    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
+    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
+    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
+    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
+    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
+    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
+    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
+    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
+    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
+    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
+    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
+    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
+    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
+    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
+
+    /* Completeness */
+    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
+    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
+  }
+}
diff --git a/client/webpack.config.js b/client/webpack.config.js
index 022b823..7da8fb5 100644
--- a/client/webpack.config.js
+++ b/client/webpack.config.js
@@ -36,44 +36,62 @@
 export default {
   entry,
   output: {
-    path: resolve(__dirname, 'dist'),
-    filename: 'bundle.js',
-    publicPath: '/'
+    path: resolve(__dirname, "dist"),
+    filename: "bundle.js",
+    publicPath: "/",
   },
   devtool,
   mode,
   module: {
     rules: [
       {
-        test: /\.jsx?/,
+        // test: /\.jsx?/,
+        test: /\.(js|jsx|ts|tsx)?$/,
         resolve: {
-          fullySpecified: false
+          fullySpecified: false,
         },
         exclude: /node_modules/,
         use: {
-          loader: 'babel-loader',
+          loader: "babel-loader",
           options: {
             plugins: babelLoaderPlugins,
             presets: [
-              ['@babel/preset-env', {
-                useBuiltIns: 'entry',
-                corejs: { version: '3.10', proposals: true },
-              }],
-              ['@babel/preset-react', {
-                runtime: 'automatic'
-              }]]
-          }
-        }
+              [
+                "@babel/preset-env",
+                {
+                  useBuiltIns: "entry",
+                  corejs: { version: "3.10", proposals: true },
+                },
+              ],
+              [
+                "@babel/preset-react",
+                {
+                  runtime: "automatic",
+                },
+              ],
+            ],
+          },
+        },
       },
       {
         test: /\.s[ac]ss$/i,
-        use: ['style-loader', 'css-loader', 'sass-loader'],
+        use: ["style-loader", "css-loader", "sass-loader"],
       },
       {
         test: /\.svg$/,
-        use: ['@svgr/webpack']
-      }
-    ]
+        use: ["@svgr/webpack"],
+      },
+      {
+        // test: /\.tsx?$/,
+        test: /\.(js|jsx|ts|tsx)?$/,
+        exclude: /node_modules/,
+        loader: "ts-loader",
+      },
+    ],
   },
-  plugins
-}
\ No newline at end of file
+  resolve: {
+    modules: ["node_modules", resolve(__dirname)],
+    extensions: [".ts", ".tsx", ".js", ".jsx"],
+  },
+  plugins,
+};
\ No newline at end of file