Major layout changes: - Remove Card wrappers and padding from all main pages for full-width content - Add proper spacing between tab bars and content (24px) - Fix mobile layout issues and button positioning Header improvements: - Replace avatar dropdown with direct Person icon link to My Account - Move Settings and Logout to My Account page as new tab and bottom button - Clean up unused menu components and imports New Group Info functionality: - Create GroupInfoPage with full group description, member list, and invite button - Make Info icon in GroupDetailPage navigate to new info page - Maintain all existing invite functionality (type name/email or select from network) - Add proper routing and contact selection flow Layout fixes: - Remove horizontal padding from main content areas - Fix vertical alignment issues in group headers on mobile - Add right margin to prevent buttons from touching screen edge - Simplify map view by removing duplicate frames and titles Code cleanup: - Remove unused imports (Paper, People, Container, formatDate) - Remove unused functions (handleInviteToGroup, renderFeedContent, renderActivityView) - Fix TypeScript errors and ensure clean build - Remove @ts-nocheck and improve type safety 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>main
parent
3cbed466a0
commit
052b383c0f
@ -0,0 +1,469 @@ |
|||||||
|
import { useState, useEffect } from 'react'; |
||||||
|
import { useParams, useNavigate, useSearchParams } from 'react-router-dom'; |
||||||
|
import { getContactPhotoStyles } from '../utils/photoStyles'; |
||||||
|
import { |
||||||
|
Typography, |
||||||
|
Box, |
||||||
|
Avatar, |
||||||
|
Button, |
||||||
|
Card, |
||||||
|
CardContent, |
||||||
|
IconButton, |
||||||
|
Chip, |
||||||
|
List, |
||||||
|
ListItem, |
||||||
|
ListItemAvatar, |
||||||
|
ListItemText, |
||||||
|
alpha, |
||||||
|
useTheme, |
||||||
|
} from '@mui/material'; |
||||||
|
import { |
||||||
|
ArrowBack, |
||||||
|
PersonAdd, |
||||||
|
Public, |
||||||
|
Lock, |
||||||
|
} from '@mui/icons-material'; |
||||||
|
import { dataService } from '../services/dataService'; |
||||||
|
import type { Group } from '../types/group'; |
||||||
|
import InviteForm, { type InviteFormData } from '../components/invite/InviteForm'; |
||||||
|
|
||||||
|
// Real NAO member data
|
||||||
|
const getMockMembers = () => [ |
||||||
|
{ |
||||||
|
id: 'oli-sb', |
||||||
|
name: 'Oliver Sylvester-Bradley', |
||||||
|
avatar: '/images/Oli.jpg', |
||||||
|
role: 'Admin', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 365), // 1 year ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'ruben-daniels', |
||||||
|
name: 'Ruben Daniels', |
||||||
|
avatar: '/images/Ruben.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 300), // 300 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'margeigh-novotny', |
||||||
|
name: 'Margeigh Novotny', |
||||||
|
avatar: '/images/Margeigh.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 280), // 280 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'alex-lion', |
||||||
|
name: 'Alex Lion Yes!', |
||||||
|
avatar: '/images/Alex.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 250), // 250 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'day-waterbury', |
||||||
|
name: 'Day Waterbury', |
||||||
|
avatar: '/images/Day.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 200), // 200 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'kevin-triplett', |
||||||
|
name: 'Kevin Triplett', |
||||||
|
avatar: '/images/Kevin.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 180), // 180 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'tim-bansemer', |
||||||
|
name: 'Tim Bansemer', |
||||||
|
avatar: '/images/Tim.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 150), // 150 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'aza-mafi', |
||||||
|
name: 'Aza Mafi', |
||||||
|
avatar: '/images/Aza.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 120), // 120 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'duke-dorje', |
||||||
|
name: 'Duke Dorje', |
||||||
|
avatar: '/images/Duke.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 100), // 100 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'david-thomson', |
||||||
|
name: 'David Thomson', |
||||||
|
avatar: '/images/David.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 80), // 80 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'samuel-gbafa', |
||||||
|
name: 'Samuel Gbafa', |
||||||
|
avatar: '/images/Sam.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 60), // 60 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'meena-seshamani', |
||||||
|
name: 'Meena Seshamani', |
||||||
|
avatar: '/images/Meena.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 40), // 40 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'niko-bonnieure', |
||||||
|
name: 'Niko Bonnieure', |
||||||
|
avatar: '/images/Niko.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 30), // 30 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'tree-willard', |
||||||
|
name: 'Tree Willard', |
||||||
|
avatar: '/images/Tree.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 20), // 20 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'stephane-bancel', |
||||||
|
name: 'Stephane Bancel', |
||||||
|
avatar: '/images/Stephane.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 15), // 15 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'joscha-raue', |
||||||
|
name: 'Joscha Raue', |
||||||
|
avatar: '/images/Joscha.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 10), // 10 days ago
|
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'drummond-reed', |
||||||
|
name: 'Drummond Reed', |
||||||
|
avatar: '/images/Drummond.jpg', |
||||||
|
role: 'Member', |
||||||
|
joinedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5), // 5 days ago
|
||||||
|
}, |
||||||
|
]; |
||||||
|
|
||||||
|
const GroupInfoPage = () => { |
||||||
|
const { groupId } = useParams<{ groupId: string }>(); |
||||||
|
const navigate = useNavigate(); |
||||||
|
const [searchParams, setSearchParams] = useSearchParams(); |
||||||
|
const theme = useTheme(); |
||||||
|
|
||||||
|
const [group, setGroup] = useState<Group | null>(null); |
||||||
|
const [members] = useState(getMockMembers()); |
||||||
|
const [isLoading, setIsLoading] = useState(true); |
||||||
|
const [showInviteForm, setShowInviteForm] = useState(false); |
||||||
|
const [selectedContact, setSelectedContact] = useState<{name: string; email: string} | undefined>(); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
const loadGroupData = async () => { |
||||||
|
if (!groupId) return; |
||||||
|
|
||||||
|
setIsLoading(true); |
||||||
|
try { |
||||||
|
const groupData = await dataService.getGroup(groupId); |
||||||
|
setGroup(groupData || null); |
||||||
|
|
||||||
|
// Handle returning from contact selection
|
||||||
|
const selectedContactName = searchParams.get('selectedContactName'); |
||||||
|
const selectedContactEmail = searchParams.get('selectedContactEmail'); |
||||||
|
if (selectedContactName && selectedContactEmail) { |
||||||
|
setSelectedContact({ |
||||||
|
name: selectedContactName, |
||||||
|
email: selectedContactEmail |
||||||
|
}); |
||||||
|
setShowInviteForm(true); |
||||||
|
|
||||||
|
// Clean up selection parameters
|
||||||
|
const newSearchParams = new URLSearchParams(searchParams); |
||||||
|
newSearchParams.delete('selectedContactName'); |
||||||
|
newSearchParams.delete('selectedContactEmail'); |
||||||
|
setSearchParams(newSearchParams); |
||||||
|
} |
||||||
|
} catch (error) { |
||||||
|
console.error('Failed to load group data:', error); |
||||||
|
} finally { |
||||||
|
setIsLoading(false); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
loadGroupData(); |
||||||
|
}, [groupId, searchParams, setSearchParams]); |
||||||
|
|
||||||
|
const handleBack = () => { |
||||||
|
navigate(`/groups/${groupId}`); |
||||||
|
}; |
||||||
|
|
||||||
|
const handleInviteToGroup = () => { |
||||||
|
setShowInviteForm(true); |
||||||
|
}; |
||||||
|
|
||||||
|
const handleInviteSubmit = (inviteData: InviteFormData) => { |
||||||
|
console.log('Sending invite:', inviteData); |
||||||
|
// TODO: Generate personalized invitation link and send email
|
||||||
|
// For now, navigate to invite page with the data
|
||||||
|
const inviteParams = new URLSearchParams({ |
||||||
|
groupId: groupId!, |
||||||
|
inviteeName: inviteData.inviteeName, |
||||||
|
inviterName: inviteData.inviterName, |
||||||
|
relationshipType: inviteData.relationshipType, |
||||||
|
}); |
||||||
|
|
||||||
|
setShowInviteForm(false); |
||||||
|
navigate(`/invite?${inviteParams.toString()}`); |
||||||
|
}; |
||||||
|
|
||||||
|
const handleSelectFromNetwork = () => { |
||||||
|
// Navigate to contacts page with selection mode and return context
|
||||||
|
setShowInviteForm(false); |
||||||
|
navigate(`/contacts?mode=select&returnTo=group-info&groupId=${groupId}`); |
||||||
|
}; |
||||||
|
|
||||||
|
const formatDate = (date: Date) => { |
||||||
|
return new Intl.DateTimeFormat('en-US', { |
||||||
|
year: 'numeric', |
||||||
|
month: 'short', |
||||||
|
day: 'numeric' |
||||||
|
}).format(date); |
||||||
|
}; |
||||||
|
|
||||||
|
const getPrivacyIcon = (isPrivate: boolean) => { |
||||||
|
return isPrivate ? ( |
||||||
|
<Lock sx={{ fontSize: 20, color: '#ff9800' }} /> |
||||||
|
) : ( |
||||||
|
<Public sx={{ fontSize: 20, color: '#4caf50' }} /> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
if (isLoading) { |
||||||
|
return ( |
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '50vh' }}> |
||||||
|
<Typography variant="h6" color="text.secondary"> |
||||||
|
Loading group... |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
if (!group) { |
||||||
|
return ( |
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '50vh' }}> |
||||||
|
<Typography variant="h6" color="text.secondary"> |
||||||
|
Group not found |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<Box sx={{
|
||||||
|
height: '100%', |
||||||
|
width: '100%', |
||||||
|
maxWidth: { xs: '100vw', md: '100%' }, |
||||||
|
overflow: 'hidden', |
||||||
|
boxSizing: 'border-box', |
||||||
|
pt: { xs: 1.5, md: 2 }, |
||||||
|
pb: 0, |
||||||
|
mx: { xs: 0, md: 'auto' } |
||||||
|
}}> |
||||||
|
{/* Header */} |
||||||
|
<Box sx={{
|
||||||
|
mb: { xs: 1.5, md: 2 }, |
||||||
|
width: '100%', |
||||||
|
overflow: 'hidden', |
||||||
|
px: { xs: '10px', md: 0 } |
||||||
|
}}> |
||||||
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: { xs: 1, md: 2 },
|
||||||
|
mb: { xs: 2, md: 3 }, |
||||||
|
width: '100%', |
||||||
|
maxWidth: '100%', |
||||||
|
overflow: 'hidden', |
||||||
|
minWidth: 0 |
||||||
|
}}> |
||||||
|
<IconButton onClick={handleBack} size="large" sx={{ flexShrink: 0 }}> |
||||||
|
<ArrowBack /> |
||||||
|
</IconButton> |
||||||
|
<Avatar |
||||||
|
src={group.image} |
||||||
|
alt={group.name} |
||||||
|
sx={{
|
||||||
|
width: { xs: 48, md: 64 },
|
||||||
|
height: { xs: 48, md: 64 },
|
||||||
|
bgcolor: 'white', |
||||||
|
border: 1, |
||||||
|
borderColor: 'primary.main', |
||||||
|
color: 'primary.main', |
||||||
|
flexShrink: 0 |
||||||
|
}} |
||||||
|
> |
||||||
|
{group.name.charAt(0)} |
||||||
|
</Avatar> |
||||||
|
<Box sx={{ flex: 1, minWidth: 0, overflow: 'hidden' }}> |
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, justifyContent: 'space-between' }}> |
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, minWidth: 0 }}> |
||||||
|
<Typography
|
||||||
|
variant="h4"
|
||||||
|
component="h1"
|
||||||
|
sx={{
|
||||||
|
fontWeight: 700, |
||||||
|
fontSize: { xs: '1.5rem', md: '2.125rem' }, |
||||||
|
lineHeight: 1.2, |
||||||
|
overflow: 'hidden', |
||||||
|
textOverflow: 'ellipsis', |
||||||
|
whiteSpace: 'nowrap' |
||||||
|
}} |
||||||
|
> |
||||||
|
{group.name} |
||||||
|
</Typography> |
||||||
|
{getPrivacyIcon(group.isPrivate)} |
||||||
|
</Box> |
||||||
|
<Button |
||||||
|
variant="contained" |
||||||
|
startIcon={<PersonAdd />} |
||||||
|
onClick={handleInviteToGroup} |
||||||
|
sx={{
|
||||||
|
borderRadius: 2, |
||||||
|
px: { xs: 1.5, md: 3 }, |
||||||
|
py: { xs: 0.5, md: 1 }, |
||||||
|
fontSize: { xs: '0.75rem', md: '0.875rem' }, |
||||||
|
flexShrink: 0, |
||||||
|
minWidth: { xs: 'auto', md: 'auto' }, |
||||||
|
mr: { xs: 0.5, md: 0 } // Add right margin on mobile
|
||||||
|
}} |
||||||
|
> |
||||||
|
Invite |
||||||
|
</Button> |
||||||
|
</Box> |
||||||
|
</Box> |
||||||
|
</Box> |
||||||
|
</Box> |
||||||
|
|
||||||
|
{/* Content */} |
||||||
|
<Box sx={{ px: { xs: '10px', md: 0 } }}> |
||||||
|
{/* Description Card */} |
||||||
|
<Card sx={{ mb: 3 }}> |
||||||
|
<CardContent sx={{ p: 3 }}> |
||||||
|
<Typography variant="h6" sx={{ fontWeight: 600, mb: 2 }}> |
||||||
|
About this group |
||||||
|
</Typography> |
||||||
|
<Typography variant="body1" sx={{ mb: 3, lineHeight: 1.6 }}> |
||||||
|
{group.description} |
||||||
|
</Typography> |
||||||
|
|
||||||
|
{group.tags && group.tags.length > 0 && ( |
||||||
|
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap', mb: 3 }}> |
||||||
|
{group.tags.map((tag) => ( |
||||||
|
<Chip
|
||||||
|
key={tag}
|
||||||
|
label={tag}
|
||||||
|
size="small"
|
||||||
|
variant="outlined" |
||||||
|
sx={{
|
||||||
|
borderRadius: 1, |
||||||
|
backgroundColor: alpha(theme.palette.primary.main, 0.04), |
||||||
|
borderColor: alpha(theme.palette.primary.main, 0.12), |
||||||
|
color: 'primary.main', |
||||||
|
fontWeight: 500, |
||||||
|
}} |
||||||
|
/> |
||||||
|
))} |
||||||
|
</Box> |
||||||
|
)} |
||||||
|
</CardContent> |
||||||
|
</Card> |
||||||
|
|
||||||
|
{/* Members List */} |
||||||
|
<Card> |
||||||
|
<CardContent sx={{ p: 3 }}> |
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}> |
||||||
|
<Typography variant="h6" sx={{ fontWeight: 600 }}> |
||||||
|
Members ({members.length}) |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
|
|
||||||
|
<List sx={{ width: '100%' }}> |
||||||
|
{members.map((member, index) => ( |
||||||
|
<ListItem |
||||||
|
key={member.id} |
||||||
|
sx={{ |
||||||
|
px: 0, |
||||||
|
py: 1, |
||||||
|
borderBottom: index === members.length - 1 ? 'none' : '1px solid', |
||||||
|
borderColor: 'divider', |
||||||
|
}} |
||||||
|
> |
||||||
|
<ListItemAvatar> |
||||||
|
<Avatar |
||||||
|
src={member.avatar} |
||||||
|
sx={{ |
||||||
|
width: 48, |
||||||
|
height: 48, |
||||||
|
bgcolor: 'white', |
||||||
|
border: 1, |
||||||
|
borderColor: 'primary.main', |
||||||
|
color: 'primary.main', |
||||||
|
backgroundSize: member.avatar ? getContactPhotoStyles(member.name).backgroundSize : 'cover', |
||||||
|
backgroundPosition: member.avatar ? getContactPhotoStyles(member.name).backgroundPosition : 'center', |
||||||
|
}} |
||||||
|
> |
||||||
|
{!member.avatar && member.name.split(' ').map(n => n[0]).join('')} |
||||||
|
</Avatar> |
||||||
|
</ListItemAvatar> |
||||||
|
<ListItemText |
||||||
|
primary={ |
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}> |
||||||
|
<Typography variant="subtitle1" sx={{ fontWeight: 600 }}> |
||||||
|
{member.name} |
||||||
|
</Typography> |
||||||
|
{member.role === 'Admin' && ( |
||||||
|
<Chip
|
||||||
|
label="Admin"
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
sx={{ height: 20, fontSize: '0.7rem' }} |
||||||
|
/> |
||||||
|
)} |
||||||
|
</Box> |
||||||
|
} |
||||||
|
secondary={ |
||||||
|
<Typography variant="body2" color="text.secondary"> |
||||||
|
Joined {formatDate(member.joinedAt)} |
||||||
|
</Typography> |
||||||
|
} |
||||||
|
/> |
||||||
|
</ListItem> |
||||||
|
))} |
||||||
|
</List> |
||||||
|
</CardContent> |
||||||
|
</Card> |
||||||
|
</Box> |
||||||
|
|
||||||
|
{/* Invite Form */} |
||||||
|
{group && ( |
||||||
|
<InviteForm |
||||||
|
open={showInviteForm} |
||||||
|
onClose={() => { |
||||||
|
setShowInviteForm(false); |
||||||
|
setSelectedContact(undefined); |
||||||
|
}} |
||||||
|
onSubmit={handleInviteSubmit} |
||||||
|
onSelectFromNetwork={handleSelectFromNetwork} |
||||||
|
group={group} |
||||||
|
prefilledContact={selectedContact} |
||||||
|
/> |
||||||
|
)} |
||||||
|
</Box> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default GroupInfoPage; |
@ -1,17 +1,46 @@ |
|||||||
import { Box, Typography, Container } from '@mui/material'; |
import { Box, Typography } from '@mui/material'; |
||||||
|
|
||||||
const MessagesPage = () => { |
const MessagesPage = () => { |
||||||
return ( |
return ( |
||||||
<Container maxWidth="lg"> |
<Box sx={{
|
||||||
<Box sx={{ py: 4 }}> |
height: '100%', |
||||||
<Typography variant="h4" sx={{ mb: 3, fontWeight: 600 }}> |
width: '100%', |
||||||
Messages |
maxWidth: { xs: '100vw', md: '100%' }, |
||||||
</Typography> |
overflow: 'hidden', |
||||||
<Typography variant="body1" color="text.secondary"> |
boxSizing: 'border-box', |
||||||
Your messages and conversations will appear here. |
p: { xs: '10px', md: 0 }, |
||||||
</Typography> |
mx: { xs: 0, md: 'auto' } |
||||||
|
}}> |
||||||
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
mb: { xs: 1, md: 1 }, |
||||||
|
width: '100%', |
||||||
|
overflow: 'hidden', |
||||||
|
minWidth: 0 |
||||||
|
}}> |
||||||
|
<Box sx={{ flex: 1, minWidth: 0, overflow: 'hidden' }}> |
||||||
|
<Typography
|
||||||
|
variant="h4"
|
||||||
|
component="h1"
|
||||||
|
sx={{
|
||||||
|
fontWeight: 700,
|
||||||
|
mb: { xs: 0, md: 0 }, |
||||||
|
fontSize: { xs: '1.5rem', md: '2.125rem' }, |
||||||
|
overflow: 'hidden', |
||||||
|
textOverflow: 'ellipsis', |
||||||
|
whiteSpace: 'nowrap' |
||||||
|
}} |
||||||
|
> |
||||||
|
Messages |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
</Box> |
</Box> |
||||||
</Container> |
<Typography variant="body1" color="text.secondary"> |
||||||
|
Your messages and conversations will appear here. |
||||||
|
</Typography> |
||||||
|
</Box> |
||||||
); |
); |
||||||
}; |
}; |
||||||
|
|
||||||
|
Loading…
Reference in new issue