169 lines
5.1 KiB
TypeScript
169 lines
5.1 KiB
TypeScript
|
import { useState, useEffect } from 'react';
|
||
|
import { XStack, Paragraph, YStack, Button, H6, Avatar, Text } from 'tamagui';
|
||
|
import { useRouter } from 'expo-router';
|
||
|
|
||
|
export default function MessagesPage() {
|
||
|
const [friends, setFriends] = useState([]);
|
||
|
const [messages, setMessages] = useState([]);
|
||
|
const [loading, setLoading] = useState(true);
|
||
|
const router = useRouter();
|
||
|
|
||
|
const navigateToChat = (contact) => {
|
||
|
router.push({
|
||
|
pathname: `/chat/${contact.username}`, // Use dynamic route
|
||
|
params: { friendUsername: contact.username }, // Pass necessary params
|
||
|
});
|
||
|
};
|
||
|
|
||
|
useEffect(() => {
|
||
|
const fetchFriends = async () => {
|
||
|
try {
|
||
|
const authToken = localStorage.getItem('jwtToken'); // Retrieve JWT token
|
||
|
if (!authToken) {
|
||
|
console.error('User is not authenticated');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const response = await fetch('http://localhost:4000/friends', {
|
||
|
headers: {
|
||
|
'Authorization': `Bearer ${authToken}`,
|
||
|
},
|
||
|
});
|
||
|
|
||
|
if (!response.ok) {
|
||
|
throw new Error('Failed to fetch friends');
|
||
|
}
|
||
|
|
||
|
const data = await response.json();
|
||
|
setFriends(data); // Set friends list
|
||
|
} catch (err) {
|
||
|
console.error('Error fetching friends:', err);
|
||
|
} finally {
|
||
|
setLoading(false);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
fetchFriends();
|
||
|
}, []);
|
||
|
|
||
|
useEffect(() => {
|
||
|
// Fetch messages for each friend
|
||
|
const fetchMessages = async () => {
|
||
|
const authToken = localStorage.getItem('jwtToken'); // Retrieve JWT token
|
||
|
if (!authToken) {
|
||
|
console.error('User is not authenticated');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
const newMessages = [];
|
||
|
|
||
|
// Fetch the latest message for each friend
|
||
|
for (let friend of friends) {
|
||
|
console.log(friend)
|
||
|
const response = await fetch(`http://localhost:4000/messages?receiverUsername=${friend.username}`, {
|
||
|
headers: {
|
||
|
'Authorization': `Bearer ${authToken}`,
|
||
|
},
|
||
|
});
|
||
|
|
||
|
if (response.ok) {
|
||
|
const messagesData = await response.json();
|
||
|
if (messagesData.length > 0) {
|
||
|
const latestMessage = messagesData[messagesData.length - 1]; // Get the most recent message
|
||
|
newMessages.push({
|
||
|
username: friend.username,
|
||
|
lastMessage: latestMessage.content,
|
||
|
timestamp: latestMessage.createdAt,
|
||
|
avatarUrl: friend.avatarUrl || 'https://i.pravatar.cc/150?img=1', // Default avatar if not available
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
setMessages(newMessages);
|
||
|
} catch (err) {
|
||
|
console.error('Error fetching messages:', err);
|
||
|
} finally {
|
||
|
setLoading(false);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if (friends.length > 0) {
|
||
|
fetchMessages();
|
||
|
} else {
|
||
|
setLoading(false); // If no friends, stop loading
|
||
|
}
|
||
|
}, [friends]);
|
||
|
|
||
|
if (loading) {
|
||
|
return <Text backgroundColor={"black"}>Loading...</Text>;
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<YStack f={1} bg="$background" px="$5" pt="$5">
|
||
|
<H6 fontSize={25} mb="$4" color="$primaryText">People You've Messaged</H6>
|
||
|
|
||
|
{/* Check if there are no friends */}
|
||
|
{friends.length === 0 ? (
|
||
|
<YStack f={1} ai="center" jc="center" mt="$10">
|
||
|
<Text fontSize={18} color="$gray9">
|
||
|
You have no friends yet. Add some friends to start chatting!
|
||
|
</Text>
|
||
|
</YStack>
|
||
|
) : (
|
||
|
// Check if there are no messages
|
||
|
messages.length === 0 ? (
|
||
|
<YStack f={1} ai="center" jc="center" mt="$10">
|
||
|
<Text fontSize={18} color="$gray9">
|
||
|
No messages yet. Start a conversation!
|
||
|
</Text>
|
||
|
</YStack>
|
||
|
) : (
|
||
|
messages.map((message, index) => (
|
||
|
<XStack
|
||
|
key={index}
|
||
|
bg="$backgroundLight"
|
||
|
padding="$4"
|
||
|
borderRadius="$12"
|
||
|
mb="$3"
|
||
|
space="$3"
|
||
|
ai="center"
|
||
|
hoverStyle={{ bg: "$gray8" }} // Hover effect similar to Telegram
|
||
|
>
|
||
|
{/* Profile Picture */}
|
||
|
<Avatar circular size={50}>
|
||
|
<Avatar.Image src={ '/assets/images/Gnome_child.png'} />
|
||
|
</Avatar>
|
||
|
|
||
|
<YStack f={1} ai="flex-start">
|
||
|
{/* Username */}
|
||
|
<Paragraph fontSize={18} fontWeight="bold" color="$primaryText">
|
||
|
{message.username}
|
||
|
</Paragraph>
|
||
|
|
||
|
{/* Last message preview */}
|
||
|
<Text fontSize={14} color="$secondaryText">
|
||
|
{message.lastMessage}
|
||
|
</Text>
|
||
|
</YStack>
|
||
|
|
||
|
{/* Timestamp */}
|
||
|
<YStack ai="flex-end">
|
||
|
<Paragraph fontSize={12} color="$gray10">
|
||
|
{new Date(message.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
|
||
|
</Paragraph>
|
||
|
</YStack>
|
||
|
|
||
|
{/* Button to open chat */}
|
||
|
<Button size="$2" onPress={() => navigateToChat(message)} theme="blue">
|
||
|
Open Chat
|
||
|
</Button>
|
||
|
</XStack>
|
||
|
))
|
||
|
)
|
||
|
)}
|
||
|
</YStack>
|
||
|
);
|
||
|
}
|