Skip to content

Commit

Permalink
Update UI and Refactor
Browse files Browse the repository at this point in the history
This cleans up a lot of the hacks that we did just to get things
going along with updating the styling to make the Messages page
at least look presentable
  • Loading branch information
Tim Roberts committed Feb 10, 2024
1 parent b93fb57 commit fc24735
Show file tree
Hide file tree
Showing 8 changed files with 657 additions and 444 deletions.
87 changes: 87 additions & 0 deletions client/src/hooks/usegroupmessages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { useUser, useSession } from '@clerk/clerk-react'
import { useState, useContext, useEffect } from 'react'
import WebSocketContext from '../contexts/websocket'
import { mapDatabaseToWebsocket, sortMessages } from '../pages/Messages/utils'
import {
getMessageGroupsForUser,
getMessageForGroup,
} from '../services/messages'
import { MessageGroup } from '../services/messages.schema'
import { WebSocketMessage } from './usewebsocket'

import Log from '../log'

const useGroupMessages = () => {
const [messages, setMessages] = useState<WebSocketMessage[]>([])
const [groups, setGroups] = useState<MessageGroup[]>([])
const [selectedGroup, setSelectedGroup] = useState<MessageGroup>()

const { sendMessage, lastMessage } = useContext(WebSocketContext)
const { user } = useUser()
const { session } = useSession()

useEffect(() => {
const getGroups = async () => {
const token = await session?.getToken()

if (token) {
try {
const result = await getMessageGroupsForUser(token)

setGroups(result)
} catch (err) {
Log.warn({ err }, 'Error getting message groups')
}
}
}

if (session) {
getGroups()
}
}, [session])

useEffect(() => {
if (lastMessage) {
setMessages((msgs) => [...msgs, lastMessage])
}
}, [lastMessage])

useEffect(() => {
const getPastMessages = async () => {
const token = await session?.getToken()

if (token && selectedGroup?._id) {
try {
const result = await getMessageForGroup(selectedGroup?._id, token)

const mapped: WebSocketMessage[] = result.map(mapDatabaseToWebsocket)

setMessages(() => {
return mapped.sort(sortMessages)
})
} catch (err) {
Log.warn({ err }, 'Error when trying to get messages')
}
} else {
setMessages([])
}
}

if (session && user) {
getPastMessages()
}
}, [user, setMessages, selectedGroup?._id, session])

return {
messages,
groups,
sendMessage,
setSelectedGroup,
selectedGroup,
user,
session,
setGroups,
}
}

export default useGroupMessages
33 changes: 33 additions & 0 deletions client/src/pages/Messages/components/GroupCreator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { FormEventHandler } from 'react'
import styled from '@emotion/styled'
import { Button, TextField } from '@mui/material'
import GroupAddIcon from '@mui/icons-material/GroupAdd'
const Form = styled.form`
width: 100%;
button {
margin-top: 0.5rem;
}
`

interface Props {
createNewGroup: FormEventHandler<HTMLFormElement>
}

const GroupCreator = ({ createNewGroup }: Props) => {
return (
<Form onSubmit={createNewGroup}>
<TextField name="name" fullWidth label="New Group Name" required />
<Button
type="submit"
variant="contained"
startIcon={<GroupAddIcon />}
fullWidth
>
Create
</Button>
</Form>
)
}

export default GroupCreator
43 changes: 43 additions & 0 deletions client/src/pages/Messages/components/GroupSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react'
import styled from '@emotion/styled'
import List from '@mui/material/List'
import ListItemButton from '@mui/material/ListItemButton'
import ListItemText from '@mui/material/ListItemText'

const Form = styled.form`
width: 100%;
display: flex;
flex-direction: column;
margin-bottom: 5rem;
`

interface Props {
selectedGroupId?: string
groups: {
_id: string
name: string
}[]
setSelectedGroup: (group: { _id: string; name: string } | undefined) => void
}

const GroupSelector = ({
selectedGroupId,
groups,
setSelectedGroup,
}: Props) => (
<List>
{groups.map((group) => (
<ListItemButton
key={group._id}
selected={selectedGroupId === group._id}
onClick={() => {
setSelectedGroup(groups.find(({ _id }) => _id === group._id))
}}
>
<ListItemText primary={group.name} />
</ListItemButton>
))}
</List>
)

export default GroupSelector
54 changes: 54 additions & 0 deletions client/src/pages/Messages/components/Message.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react'
import { MessageTimestamp, Message as MessageWrap } from './styled'
import { formatDistanceToNow } from 'date-fns'
import Markdown from 'react-markdown'
import SyntaxHighlighter from 'react-syntax-highlighter'
import { a11yDark } from 'react-syntax-highlighter/dist/esm/styles/hljs'
import remarkGfm from 'remark-gfm'

interface Props {
payload: {
message: string
}
metadata: {
receivedAt: string
}
}

const Message = ({ payload, metadata }: Props) => {
return (
<MessageWrap>
<Markdown
remarkPlugins={[remarkGfm]}
components={{
code({ node, inline, className, children, ...props }: any) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
style={a11yDark}
language={match[1]}
PreTag="div"
{...props}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className="md-post-code" {...props}>
{children}
</code>
)
},
}}
>
{payload.message}
</Markdown>
<MessageTimestamp dateTime={metadata.receivedAt}>
{formatDistanceToNow(new Date(metadata.receivedAt), {
addSuffix: true,
})}
</MessageTimestamp>
</MessageWrap>
)
}

export default Message
38 changes: 38 additions & 0 deletions client/src/pages/Messages/components/MessageInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react'
import { TextField } from '@mui/material'
import styled from '@emotion/styled'

const Input = styled(TextField)`
max-width: 95%;
margin: 0 auto;
margin-top: 4rem;
`

interface Props {
handleUpdate: (value: any) => void
onSend: () => void
currentValue: any
}

const MessageInput = ({ handleUpdate, onSend, currentValue = '' }: Props) => (
<Input
label="Message"
name="message"
multiline
value={currentValue}
onChange={handleUpdate}
variant="filled"
onKeyUp={(event) => {
if (event.key.toLowerCase() == 'enter') {
if (event.shiftKey) {
//
} else {
onSend()
}
}
}}
fullWidth
/>
)

export default MessageInput
Loading

0 comments on commit fc24735

Please sign in to comment.