testing
This commit is contained in:
+57
-49
@@ -27,8 +27,6 @@ import { ApiResponse } from "./home/UserProfileStatus";
|
||||
import * as Keychain from "react-native-keychain";
|
||||
const { width } = Dimensions.get('window');
|
||||
|
||||
|
||||
|
||||
// --- Types ---
|
||||
interface Group {
|
||||
id: string;
|
||||
@@ -39,46 +37,66 @@ interface Group {
|
||||
contributionAmount: number;
|
||||
cycleType: string;
|
||||
createdByName: string;
|
||||
imageBlob: string
|
||||
}
|
||||
|
||||
// --- UI Components ---
|
||||
const GroupCard = ({ item, onJoin, onView, isGrid }: { item: Group; onJoin: (groupId: string) => void; onView: (group: Group) => void; isGrid?: boolean; }) => {
|
||||
const GroupCard = ({ item, onJoin, onView, isGrid }: { item: Group; onJoin:()=>void; onView: (group: Group) => void; isGrid?: boolean; }) => {
|
||||
const isFull = item.currentParticipants >= item.maxParticipants;
|
||||
const cardStyle = isGrid ? styles.gridCard : styles.listCard;
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const navigation = useNavigation()
|
||||
|
||||
return (
|
||||
<View style={cardStyle}>
|
||||
<Text style={styles.groupName} numberOfLines={1}>{item.groupName}</Text>
|
||||
<Text style={styles.groupDescription} numberOfLines={isGrid ? 2 : 1}>{item.description}</Text>
|
||||
{/* <TouchableOpacity onPress={()=> navigation.navigate("GroupDetails" as never)}> */}
|
||||
<View style={{ flex: 1, flexDirection: 'row', justifyContent: "space-between" }}>
|
||||
<View>
|
||||
<Text style={[styles.groupName,{width:isGrid?"50%":"100%"}]} numberOfLines={isGrid ? 2 : 1}>{item.groupName}</Text>
|
||||
<Text style={styles.groupDescription} numberOfLines={isGrid ? 2 : 1}>{item.description}</Text>
|
||||
</View>
|
||||
<Image
|
||||
source={{ uri: item?.imageBlob !== null ? `data:image/jpeg;base64,${item?.imageBlob}` : `https://i.pravatar.cc/150?u=${item.id}` }}
|
||||
style={{ width: 50, borderWidth: 1, height: 50, borderColor: colors.pastelGreen, borderRadius: 25, }}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.groupMeta}>
|
||||
<Text style={styles.groupMetaText}>{item.currentParticipants}/{item.maxParticipants} Members</Text>
|
||||
<Text style={styles.groupMetaText}>{item.cycleType}</Text>
|
||||
</View>
|
||||
{/* </TouchableOpacity> */}
|
||||
<View style={styles.buttonContainer}>
|
||||
<TouchableOpacity style={styles.viewButton} onPress={() => onView(item)}>
|
||||
{/* <TouchableOpacity style={styles.viewButton} onPress={() => onView(item)}>
|
||||
<Text style={styles.viewButtonText}>View</Text>
|
||||
</TouchableOpacity>
|
||||
</TouchableOpacity> */}
|
||||
<TouchableOpacity
|
||||
style={[styles.joinButton, isFull && styles.joinButtonDisabled]}
|
||||
onPress={() => onJoin(item.id)}
|
||||
disabled={isFull}
|
||||
onPress={async () => {
|
||||
setLoading(true);
|
||||
await onJoin(item.id);
|
||||
setLoading(false);
|
||||
}}
|
||||
disabled={isFull || loading} // Also disable button while loading
|
||||
>
|
||||
<Text style={styles.joinButtonText}>{isFull ? "Full" : "Join"}</Text>
|
||||
{loading ? <ActivityIndicator color={colors.black} /> : <Text style={styles.joinButtonText}>{isFull ? "Full" : "Join"}</Text>}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const FeaturedGroupCard = ({ item }: { item: Group }) => (
|
||||
<View style={styles.featuredCard}>
|
||||
<Image source={{ uri: `https://i.pravatar.cc/150?u=${item.id}` }} style={styles.featuredImage} />
|
||||
<View style={styles.featuredContent}>
|
||||
<Text style={styles.featuredName} numberOfLines={1}>{item.groupName}</Text>
|
||||
<Text style={styles.featuredCreator}>by {item.createdByName}</Text>
|
||||
const FeaturedGroupCard = ({ item }: { item: Group }) => {
|
||||
return (
|
||||
<View style={styles.featuredCard}>
|
||||
<Image source={{ uri: item?.imageBlob !== null ? `data:image/jpeg;base64${item?.imageBlob}` : `https://i.pravatar.cc/150?u=${item.id}` }} style={styles.featuredImage} />
|
||||
<View style={styles.featuredContent}>
|
||||
<Text style={styles.featuredName} numberOfLines={1}>{item.groupName}</Text>
|
||||
<Text style={styles.featuredCreator}>by {item.createdByName}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
export default function GroupScreen() {
|
||||
const [activeTab, setActiveTab] = useState("Public");
|
||||
@@ -114,6 +132,7 @@ export default function GroupScreen() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const fetchJoinedGroups = async () => {
|
||||
if (loading) return;
|
||||
setLoading(true);
|
||||
@@ -152,21 +171,21 @@ export default function GroupScreen() {
|
||||
try {
|
||||
const url = `${JOIN_GROUP_URL}groups/${groupId}/join/10`;
|
||||
console.log("Joining group URL:", url);
|
||||
const res = await apiCall(url, "POST");
|
||||
const res = await apiCall(url, "POST") as any;
|
||||
|
||||
console.log("JOIN_GROUP_URL response:", res);
|
||||
|
||||
// if (res.statusCode === 200) {
|
||||
// Alert.alert("Success", "You requested to join the group.");
|
||||
// } else {
|
||||
// Alert.alert("Error", res.message || "Failed to join group.");
|
||||
// }
|
||||
if (res.statusCode === 200) {
|
||||
Alert.alert("Success", "You requested to join the group.");
|
||||
} else {
|
||||
Alert.alert("Error", res.message || "Failed to join group.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Join Group Error:", error);
|
||||
Alert.alert("Error", "An unexpected error occurred.");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const userStatus = async () => {
|
||||
try {
|
||||
const credentials = await Keychain.getGenericPassword();
|
||||
@@ -264,13 +283,13 @@ export default function GroupScreen() {
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
|
||||
}
|
||||
// ListFooterComponent={<ActivityIndicator size={'large'} color={colors.Group} />}
|
||||
// ListFooterComponent={<ActivityIndicator size={'large'} color={colors.Group} />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AppView paddingHorizontal={0} style={styles.container}>
|
||||
<AppView paddingHorizontal={0}>
|
||||
{/* Fixed Header */}
|
||||
<View style={styles.headerContainer}>
|
||||
<Text style={styles.title}>Explore Groups</Text>
|
||||
@@ -282,21 +301,11 @@ export default function GroupScreen() {
|
||||
|
||||
{/* Scrollable Content */}
|
||||
<ScrollView style={styles.container}>
|
||||
<Text style={styles.sectionTitle}>Featured</Text>
|
||||
<FlatList
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
data={featuredGroups}
|
||||
keyExtractor={(item) => item.id}
|
||||
renderItem={({ item }) => <FeaturedGroupCard item={item} />}
|
||||
style={styles.featuredList}
|
||||
// ListEmptyComponent={!loading && featuredGroups.length === 0 ? <Text style={styles.emptyFeaturedText}>No featured groups.</Text> : null}
|
||||
/>
|
||||
|
||||
<View style={styles.tabHeader}>
|
||||
<View style={styles.segmentedControl}>
|
||||
|
||||
{role === "ORGANIZER" ? (["My Groups", "Joined", "Public"].map((tab) => (
|
||||
{role === "ORGANIZER" ? (["Public"].map((tab) => (
|
||||
<TouchableOpacity key={tab} style={[styles.segmentButton, activeTab === tab && styles.segmentButtonActive]} onPress={() => setActiveTab(tab)}>
|
||||
<Text style={[styles.segmentText, activeTab === tab && styles.segmentTextActive]}>{tab}</Text>
|
||||
</TouchableOpacity>
|
||||
@@ -312,7 +321,7 @@ export default function GroupScreen() {
|
||||
</View>
|
||||
|
||||
{/* The list now renders inside a simple View, as FlatList handles its own scroll */}
|
||||
<View style={styles.contentArea}>{renderContent()}</View>
|
||||
<View style={{}}>{renderContent()}</View>
|
||||
</ScrollView>
|
||||
{role === "ORGANIZER" && (
|
||||
<FAB style={styles.fab} icon={() => <MaterialIcons name="group-add" size={24} color="#333" />} onPress={() => navigation.navigate('GroupCreation')} />
|
||||
@@ -322,10 +331,10 @@ export default function GroupScreen() {
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, backgroundColor: '#f5f6fa' },
|
||||
|
||||
headerContainer: { backgroundColor: '#f5f6fa', paddingHorizontal: 16 },
|
||||
title: { fontSize: 22, fontWeight: "600", color: colors.Group },
|
||||
searchContainer: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#fff', borderRadius: 12, paddingHorizontal: 10, elevation: 2, marginVertical: 20 },
|
||||
searchContainer: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#fff', borderRadius: 20, paddingHorizontal: 10, elevation: 5, marginVertical: 20 , borderWidth:2,borderColor:colors.pastelGreen },
|
||||
searchIcon: { marginRight: 8 },
|
||||
searchInput: { flex: 1, height: 45, fontSize: 16, color: '#333' },
|
||||
sectionTitle: { fontSize: 20, fontWeight: 'bold', color: colors.Group, marginBottom: 12, paddingHorizontal: 16 },
|
||||
@@ -336,18 +345,17 @@ const styles = StyleSheet.create({
|
||||
featuredName: { fontSize: 14, fontWeight: 'bold', color: '#333' },
|
||||
featuredCreator: { fontSize: 12, color: '#777', marginTop: 2 },
|
||||
tabHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 16, marginBottom: 16 },
|
||||
segmentedControl: { flex: 1, flexDirection: 'row', backgroundColor: '#e9ecef', borderRadius: 10, padding: 4, marginRight: 10 },
|
||||
segmentedControl: { flex: 1, flexDirection: 'row', borderRadius: 10, padding: 4, marginRight: 10 },
|
||||
segmentButton: { flex: 1, paddingVertical: 10, borderRadius: 8, alignItems: 'center' },
|
||||
segmentButtonActive: { backgroundColor: colors.pastelGreen, elevation: 2, shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 5 },
|
||||
segmentButtonActive: { backgroundColor: colors.pastelGreen, elevation: 5, shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 5 , borderRadius:15 },
|
||||
segmentText: { fontSize: 14, fontWeight: '600', color: '#555' },
|
||||
segmentTextActive: { color: '#333' },
|
||||
layoutToggleButton: { padding: 8 },
|
||||
contentArea: { paddingHorizontal: 16 },
|
||||
fab: { position: "absolute", right: 20, bottom: 90, width: 60, height: 60, justifyContent: "center", alignItems: "center", backgroundColor: colors.pastelGreen, borderRadius: 30, elevation: 4 },
|
||||
listCard: { backgroundColor: '#fff', padding: 16, borderRadius: 12, marginBottom: 12, elevation: 1 },
|
||||
gridCard: { backgroundColor: '#fff', padding: 12, borderRadius: 12, marginBottom: 12, elevation: 1, width: (width - 48) / 2 },
|
||||
groupName: { fontSize: 16, fontWeight: 'bold', color: '#333' },
|
||||
groupDescription: { fontSize: 14, color: '#666', marginVertical: 4 },
|
||||
listCard: { backgroundColor: colors.pastelGreen, padding: 16, borderRadius: 20, marginBottom: 12,marginHorizontal:15, elevation: 5 },
|
||||
gridCard: { backgroundColor: colors.pastelGreen, padding: 12, borderRadius: 20, marginBottom: 12,marginHorizontal:15, elevation: 5, width: (width - 48) / 2 },
|
||||
groupName: { fontSize: 16, fontWeight: 'bold', color: '#333', width: '50%' },
|
||||
groupDescription: { fontSize: 14, color: '#666', marginVertical: 4, width: '40%' },
|
||||
groupMeta: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 8, borderTopWidth: 1, borderTopColor: '#f0f0f0', paddingTop: 8, marginBottom: 10 },
|
||||
groupMetaText: { fontSize: 12, color: '#888', fontWeight: '500', textTransform: 'capitalize' },
|
||||
emptyText: { textAlign: 'center', marginTop: 40, fontSize: 16, color: '#888' },
|
||||
@@ -355,7 +363,7 @@ const styles = StyleSheet.create({
|
||||
buttonContainer: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 8 },
|
||||
viewButton: { flex: 1, backgroundColor: '#e9ecef', paddingVertical: 10, borderRadius: 8, alignItems: 'center', marginRight: 5 },
|
||||
viewButtonText: { color: '#333', fontWeight: 'bold', fontSize: 14 },
|
||||
joinButton: { flex: 1, backgroundColor: colors.pastelGreen, paddingVertical: 10, borderRadius: 8, alignItems: 'center', marginLeft: 5 },
|
||||
joinButton: { flex: 1, backgroundColor: colors.white, paddingVertical: 10, borderRadius: 8, alignItems: 'center', marginLeft: 5 },
|
||||
joinButtonDisabled: { backgroundColor: '#bdc3c7' },
|
||||
joinButtonText: { color: '#333', fontWeight: 'bold', fontSize: 14 },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user