Convert all pages to Typescript
Convert all files in `client/src/pages` to Typescript
Gitlab: #30
Change-Id: I9b5ec5b042487d732bb7d46b584f797049eb068c
diff --git a/client/src/pages/Messenger.tsx b/client/src/pages/Messenger.tsx
new file mode 100644
index 0000000..c9449cd
--- /dev/null
+++ b/client/src/pages/Messenger.tsx
@@ -0,0 +1,98 @@
+import { Stack } from '@mui/material';
+import { useEffect, useState } from 'react';
+import { useParams } from 'react-router';
+
+import Contact from '../../../model/Contact';
+import Conversation from '../../../model/Conversation';
+import { useAppSelector } from '../../redux/hooks';
+import authManager from '../AuthManager';
+//import Sound from 'react-sound';
+import ConversationList from '../components/ConversationList';
+import ConversationView from '../components/ConversationView';
+import Header from '../components/Header';
+import LoadingPage from '../components/loading';
+import NewContactForm from '../components/NewContactForm';
+import AddContactPage from './AddContactPage';
+
+type MessengerProps = {
+ accountId?: string;
+ conversationId?: string;
+ contactId?: string;
+};
+
+const Messenger = (props: MessengerProps) => {
+ const { refresh } = useAppSelector((state) => state.app);
+
+ const [conversations, setConversations] = useState<Conversation[] | undefined>(undefined);
+ const [searchQuery, setSearchQuery] = useState('');
+ const [searchResult, setSearchResults] = useState<Conversation | undefined>(undefined);
+
+ const params = useParams();
+ const accountId = props.accountId || params.accountId;
+ const conversationId = props.conversationId || params.conversationId;
+ const contactId = props.contactId || params.contactId;
+
+ if (accountId == null) {
+ throw new Error('Missing accountId');
+ }
+
+ useEffect(() => {
+ console.log('REFRESH CONVERSATIONS FROM MESSENGER');
+ const controller = new AbortController();
+ authManager
+ .fetch(`/api/accounts/${accountId}/conversations`, { signal: controller.signal })
+ .then((res) => res.json())
+ .then((result: Conversation[]) => {
+ console.log(result);
+ setConversations(Object.values(result).map((c) => Conversation.from(accountId, c)));
+ });
+ // return () => controller.abort()
+ }, [accountId, refresh]);
+
+ useEffect(() => {
+ if (!searchQuery) return;
+ const controller = new AbortController();
+ authManager
+ .fetch(`/api/accounts/${accountId}/ns/name/${searchQuery}`, { signal: controller.signal })
+ .then((response) => {
+ if (response.status === 200) {
+ return response.json();
+ } else {
+ throw new Error(response.status.toString());
+ }
+ })
+ .then((response) => {
+ console.log(response);
+ const contact = new Contact(response.address);
+ contact.setRegisteredName(response.name);
+ setSearchResults(contact ? Conversation.fromSingleContact(accountId, contact) : undefined);
+ })
+ .catch((e) => {
+ setSearchResults(undefined);
+ });
+ // return () => controller.abort() // crash on React18
+ }, [accountId, searchQuery]);
+
+ console.log('Messenger render');
+ return (
+ <Stack direction="row" height="100vh" width="100vw">
+ <Stack flexGrow={0} flexShrink={0} overflow="auto">
+ <Header />
+ <NewContactForm onChange={setSearchQuery} />
+ {contactId && <AddContactPage accountId={accountId} contactId={contactId} />}
+ {conversations ? (
+ <ConversationList search={searchResult} conversations={conversations} accountId={accountId} />
+ ) : (
+ <div className="rooms-list">
+ <LoadingPage />
+ </div>
+ )}
+ </Stack>
+ <Stack flexGrow={1}>
+ {conversationId && <ConversationView accountId={accountId} conversationId={conversationId} />}
+ </Stack>
+ </Stack>
+ );
+};
+
+export default Messenger;