Redirect user from call page when not in call

When a user tries to access a call page while not in a call, redirect the user to the home page.

Misc changes:

- Add route state to the call route that includes the CallStatus.
- CallProvider redirects to home if the callStatus isn't set (meaning
  the user isn't in a call).
- Remove `beginCall` function in `ConversationProvider`. Added `useStartCall` hook that redirects the user to the call page. The `CallProvider` automatically sends the `BeginCall` message when the user reaches the page for the first time.
- Reorder functions in CallProvider to have `useEffect` functions at the top

GitLab: #164
Change-Id: I6cec1b9f31cb308d92a69112f5b38d1bdf79e05f
diff --git a/client/src/hooks/useStartCall.ts b/client/src/hooks/useStartCall.ts
new file mode 100644
index 0000000..2df6a01
--- /dev/null
+++ b/client/src/hooks/useStartCall.ts
@@ -0,0 +1,38 @@
+/*
+ * 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 { useCallback } from 'react';
+import { useNavigate } from 'react-router-dom';
+
+import { CallStatus } from '../contexts/CallProvider';
+import { CallRouteParams } from '../router';
+
+export const useStartCall = () => {
+  const navigate = useNavigate();
+
+  return useCallback(
+    (conversationId: string, state?: Partial<CallRouteParams['state']>) => {
+      navigate(`/conversation/${conversationId}/call?role=caller`, {
+        state: {
+          callStatus: CallStatus.Default,
+          ...state,
+        },
+      });
+    },
+    [navigate]
+  );
+};
diff --git a/client/src/hooks/useUrlParams.ts b/client/src/hooks/useUrlParams.ts
index f21b60b..243a8c5 100644
--- a/client/src/hooks/useUrlParams.ts
+++ b/client/src/hooks/useUrlParams.ts
@@ -18,13 +18,14 @@
 import { useMemo } from 'react';
 import { useLocation, useParams } from 'react-router-dom';
 
-export type RouteParams<U = Record<string, string>, Q = Record<string, string>> = {
-  urlParams: U;
-  queryParams: Q;
+export type RouteParams<UrlParams = Record<string, string>, QueryParams = Record<string, string>, State = any> = {
+  urlParams: UrlParams;
+  queryParams: QueryParams;
+  state?: State;
 };
 
 export const useUrlParams = <T extends RouteParams>() => {
-  const { search } = useLocation();
+  const { search, state } = useLocation();
   const urlParams = useParams() as T['urlParams'];
 
   return useMemo(() => {
@@ -32,6 +33,7 @@
     return {
       queryParams,
       urlParams,
+      state: state as T['state'],
     };
-  }, [search, urlParams]);
+  }, [search, urlParams, state]);
 };