import React, { useState, useEffect } from 'react';
import {
View,
Text,
FlatList,
StyleSheet,
ActivityIndicator,
TouchableOpacity,
RefreshControl
} from 'react-native';
import { getFeed } from '@contactsmanager/rn';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
const ActivityFeedScreen = () => {
const [feedEvents, setFeedEvents] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [isRefreshing, setIsRefreshing] = useState(false);
const [error, setError] = useState(null);
const [currentPage, setCurrentPage] = useState(0);
const [hasMoreEvents, setHasMoreEvents] = useState(true);
const pageSize = 20;
useEffect(() => {
if (feedEvents.length === 0) {
loadFeed(true);
}
}, []);
const loadFeed = async (refresh = false) => {
if (refresh) {
setCurrentPage(0);
setFeedEvents([]);
}
setIsLoading(!isRefreshing);
setError(null);
try {
const feed = await getFeed(currentPage * pageSize, pageSize);
if (refresh) {
setFeedEvents(feed.items);
} else {
setFeedEvents(prevEvents => [...prevEvents, ...feed.items]);
}
setHasMoreEvents(feed.items.length >= pageSize && feed.total > (currentPage * pageSize + feed.items.length));
setCurrentPage(prev => prev + 1);
} catch (error) {
setError(error.message);
} finally {
setIsLoading(false);
setIsRefreshing(false);
}
};
const handleRefresh = () => {
setIsRefreshing(true);
loadFeed(true);
};
const loadMoreEvents = () => {
if (!isLoading && hasMoreEvents) {
loadFeed(false);
}
};
// Format event time
const formatEventTime = (startTime) => {
if (!startTime) return 'No date';
const date = new Date(startTime);
return date.toLocaleString();
};
// Event row component
const EventRow = ({ event }) => (
<View style={styles.eventCard}>
{/* Event header with creator info */}
<View style={styles.eventHeader}>
<View style={styles.avatar} />
<View style={styles.creatorInfo}>
<Text style={styles.creatorName}>{event.creatorName || 'Unknown'}</Text>
<Text style={styles.eventTime}>{formatEventTime(event.startTime)}</Text>
</View>
</View>
{/* Event content */}
<View style={styles.eventContent}>
<Text style={styles.eventTitle}>{event.title}</Text>
{event.description && (
<Text style={styles.eventDescription} numberOfLines={3}>
{event.description}
</Text>
)}
{event.location && (
<View style={styles.locationContainer}>
<Icon name="map-marker" size={14} color="#666" />
<Text style={styles.locationText}>{event.location}</Text>
</View>
)}
</View>
{/* Action buttons */}
<View style={styles.actionButtons}>
<TouchableOpacity style={styles.actionButton}>
<Icon name="calendar-plus" size={18} color="#007AFF" />
<Text style={styles.actionButtonText}>Calendar</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.actionButton}>
<Icon name="share-variant" size={18} color="#007AFF" />
<Text style={styles.actionButtonText}>Share</Text>
</TouchableOpacity>
</View>
</View>
);
// Empty state component
const EmptyFeed = () => (
<View style={styles.emptyContainer}>
<Icon name="account-group-outline" size={48} color="#999" />
<Text style={styles.emptyTitle}>No events in your feed</Text>
<Text style={styles.emptySubtitle}>Follow more people to see their events</Text>
<TouchableOpacity style={styles.findPeopleButton}>
<Text style={styles.findPeopleButtonText}>Find People to Follow</Text>
</TouchableOpacity>
</View>
);
// Error state component
const ErrorState = () => (
<View style={styles.errorContainer}>
<Text style={styles.errorTitle}>Error loading feed</Text>
<Text style={styles.errorMessage}>{error}</Text>
<TouchableOpacity style={styles.retryButton} onPress={() => loadFeed(true)}>
<Text style={styles.retryButtonText}>Try Again</Text>
</TouchableOpacity>
</View>
);
return (
<View style={styles.container}>
{isLoading && feedEvents.length === 0 ? (
<ActivityIndicator size="large" style={styles.loader} />
) : error ? (
<ErrorState />
) : feedEvents.length === 0 ? (
<EmptyFeed />
) : (
<FlatList
data={feedEvents}
renderItem={({ item }) => <EventRow event={item} />}
keyExtractor={item => item.id}
contentContainerStyle={styles.feedList}
refreshControl={
<RefreshControl refreshing={isRefreshing} onRefresh={handleRefresh} />
}
onEndReached={loadMoreEvents}
onEndReachedThreshold={0.5}
ListFooterComponent={
hasMoreEvents && (
<ActivityIndicator style={styles.footerLoader} size="small" />
)
}
/>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f8f8f8',
},
loader: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
feedList: {
padding: 12,
},
eventCard: {
backgroundColor: '#fff',
borderRadius: 12,
padding: 16,
marginBottom: 12,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 3,
elevation: 2,
},
eventHeader: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 12,
},
avatar: {
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: 'rgba(0,0,0,0.1)',
},
creatorInfo: {
marginLeft: 12,
},
creatorName: {
fontWeight: '600',
fontSize: 15,
},
eventTime: {
fontSize: 12,
color: '#666',
},
eventContent: {
marginBottom: 12,
},
eventTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 4,
},
eventDescription: {
fontSize: 15,
color: '#444',
marginBottom: 8,
},
locationContainer: {
flexDirection: 'row',
alignItems: 'center',
},
locationText: {
fontSize: 14,
color: '#666',
marginLeft: 4,
},
actionButtons: {
flexDirection: 'row',
justifyContent: 'space-between',
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: '#e0e0e0',
paddingTop: 12,
},
actionButton: {
flexDirection: 'row',
alignItems: 'center',
padding: 8,
},
actionButtonText: {
color: '#007AFF',
marginLeft: 6,
fontSize: 14,
},
emptyContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 24,
},
emptyTitle: {
fontSize: 18,
fontWeight: 'bold',
marginTop: 16,
marginBottom: 8,
},
emptySubtitle: {
fontSize: 15,
color: '#666',
textAlign: 'center',
marginBottom: 20,
},
findPeopleButton: {
backgroundColor: '#007AFF',
paddingVertical: 12,
paddingHorizontal: 20,
borderRadius: 8,
},
findPeopleButtonText: {
color: '#fff',
fontWeight: '600',
},
errorContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 24,
},
errorTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 8,
},
errorMessage: {
fontSize: 14,
color: 'red',
textAlign: 'center',
marginBottom: 20,
},
retryButton: {
backgroundColor: '#007AFF',
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 8,
},
retryButtonText: {
color: '#fff',
fontWeight: '600',
},
footerLoader: {
marginVertical: 16,
},
});
export default ActivityFeedScreen;