managment screen upadte

This commit is contained in:
Abin Toppo
2025-09-17 16:45:20 +05:30
parent 66b509e58e
commit 6bc12ecbbb
14 changed files with 823 additions and 201 deletions
+43
View File
@@ -0,0 +1,43 @@
// src/components/JoinedGroupCard.tsx
import React, { FC } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { JoinedGroup } from '../types';
interface JoinedGroupCardProps {
item: JoinedGroup;
}
export const JoinedGroupCard: FC<JoinedGroupCardProps> = ({ item }) => (
<View style={styles.card}>
<View>
<Text style={styles.cardTitle}>{item.groupName}</Text>
<Text style={styles.cardSubtitle}>Created by {item.createdBy}</Text>
</View>
</View>
);
const styles = StyleSheet.create({
card: {
backgroundColor: '#fff',
borderRadius: 12,
padding: 16,
marginBottom: 12,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
elevation: 2,
shadowColor: '#000',
shadowOpacity: 0.05,
shadowRadius: 4,
},
cardTitle: {
fontSize: 17,
fontWeight: 'bold',
color: '#343a40',
},
cardSubtitle: {
fontSize: 14,
color: '#6c757d',
},
});
+164
View File
@@ -0,0 +1,164 @@
// components/MyGroupCard.tsx
import React from "react";
import {
View,
Text,
StyleSheet,
TouchableOpacity,
} from "react-native";
import { Ionicons } from "@react-native-vector-icons/ionicons";
import colors from "./colors";
interface MyGroup {
id: string;
groupName: string;
description: string;
visibility: "PUBLIC" | "PRIVATE";
createdByName: string;
currentParticipants: number;
maxParticipants: number;
contributionAmount: number;
cycleType: "MONTHLY" | "QUARTERLY" | "YEARLY";
status: "PENDING" | "ACTIVE" | "COMPLETED";
}
interface Props {
item: MyGroup;
onManage: (group: MyGroup) => void;
}
export const MyGroupCard: React.FC<Props> = ({ item, onManage }) => {
const getStatusColor = () => {
switch (item.status) {
case "ACTIVE":
return colors.pastelGreen;
case "PENDING":
return colors.pastelOrange; // amber
case "COMPLETED":
return colors.pastelBlue;
default:
return "#adb5bd";
}
};
return (
<View style={styles.card}>
{/* Left Content */}
<View style={{ flex: 1 }}>
<View style={styles.cardHeader}>
<Text style={styles.cardTitle} numberOfLines={1}>
{item.groupName}
</Text>
<View style={[styles.statusBadge, { backgroundColor: getStatusColor() }]}>
<Text style={styles.statusBadgeText}>{item.status === "ACTIVE" ? "Active" : "Not Active"}</Text>
</View>
</View>
<Text style={styles.cardSubtitle} numberOfLines={2}>
{item.description}
</Text>
<View style={styles.cardMetaContainer}>
<Text style={styles.cardMetaText}>
<Ionicons name="person-outline" size={14} /> {item.currentParticipants}/{item.maxParticipants}
</Text>
<Text style={styles.cardMetaText}>
<Ionicons name="cash-outline" size={14} /> ₹{item.contributionAmount}
</Text>
<Text style={styles.cardMetaText}>
<Ionicons name="time-outline" size={14} /> {item.cycleType}
</Text>
</View>
<Text style={styles.createdBy}>Created by {item.createdByName}</Text>
</View>
{/* Manage Button */}
<TouchableOpacity style={styles.manageButton} onPress={() => onManage(item)}>
<Ionicons name="settings-outline" size={24} color={colors.textDark} />
<Text style={styles.manageButtonText}>Manage</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
card: {
backgroundColor: "#fff",
borderRadius: 12,
padding: 16,
marginBottom: 12,
flexDirection: "row",
alignItems: "center",
elevation: 2,
shadowColor: "#000",
shadowOpacity: 0.05,
shadowRadius: 4,
},
cardHeader: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 6,
},
cardTitle: {
fontSize: 17,
fontWeight: "bold",
color: "#343a40",
flex: 1,
marginRight: 10,
},
cardSubtitle: {
fontSize: 14,
color: "#6c757d",
marginBottom: 8,
},
cardMetaContainer: {
flexDirection: "row",
alignItems: "center",
flexWrap: "wrap",
marginBottom: 6,
},
manageButtonText: {
fontSize: 12,
color: colors.textDark,
},
cardMetaText: {
fontSize: 13,
color: "#495057",
fontWeight: "500",
marginRight: 16,
flexDirection: "row",
alignItems: "center",
},
statusBadge: {
paddingHorizontal: 10,
paddingVertical: 4,
borderRadius: 5,
elevation: 1,
},
statusBadgeText: {
color: colors.textDark,
fontSize: 10,
fontWeight: "bold",
textTransform: "uppercase",
},
manageButton: {
width: 100,
borderRadius:10,
flexDirection:"row",
alignItems: "center",
justifyContent: "space-around",
padding: 6,
marginLeft: 10,
elevation:2,
backgroundColor: colors.pastelOrange,
},
createdBy: {
fontSize: 12,
color: "#868e96",
marginTop: 4,
},
});
export default MyGroupCard;
+139
View File
@@ -0,0 +1,139 @@
// src/components/RequestCard.tsx
import React, { FC } from 'react';
import { View, Text, Image, TouchableOpacity, StyleSheet } from 'react-native';
import { Ionicons } from "@react-native-vector-icons/ionicons";
import colors from './colors'; // Assuming your colors are defined here
import { JoinRequest } from '../types';
interface RequestCardProps {
item: JoinRequest;
onApprove: (req: JoinRequest) => void;
onDecline: (req: JoinRequest) => void;
}
export const RequestCard: FC<RequestCardProps> = ({ item, onApprove, onDecline }) => {
return (
<View style={styles.card}>
{/* Top section with user avatar and info */}
<View style={styles.userInfoSection}>
<Image
source={{ uri: item.userAvatar || `https://i.pravatar.cc/150?u=${item.userId}` }}
style={styles.avatar}
/>
<View style={styles.userInfo}>
<Text style={styles.userName} numberOfLines={1}>{item.userName}</Text>
<Text style={styles.userMeta}><Ionicons name="call-outline" size={14} color={colors.textSecondary} /> {item.mobile}</Text>
</View>
</View>
{/* Middle section for the group name */}
<View style={styles.groupInfoSection}>
<Text style={styles.requestText}>
Wants to join the group: <Text style={styles.groupName}>{item.groupName}</Text>
</Text>
</View>
{/* Bottom section with action buttons */}
<View style={styles.actionsSection}>
<TouchableOpacity style={[styles.actionButton, styles.declineButton]} onPress={() => onDecline(item)}>
<Ionicons name="close-outline" size={20} color={colors.danger} />
<Text style={[styles.actionButtonText, { color: colors.danger }]}>Decline</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.actionButton, styles.approveButton]} onPress={() => onApprove(item)}>
{/* Corrected icon color and updated text color for better contrast */}
<Ionicons name="checkmark-outline" size={20} color={colors.textPrimary} />
<Text style={[styles.actionButtonText, { color: colors.textPrimary }]}>Approve</Text>
</TouchableOpacity>
</View>
</View>
);
};
// Assuming a colors object like this for context:
// const colors = {
// white: '#FFFFFF',
// textPrimary: '#212121',
// textSecondary: '#757575',
// border: '#EEEEEE',
// danger: '#C62828',
// lightDanger: '#FFEBEE',
// pastelOrange: '#FFDAB9', // The requested color
// };
const styles = StyleSheet.create({
card: {
backgroundColor: colors.white,
borderRadius: 16,
marginVertical: 8,
elevation: 4,
shadowColor: '#000',
shadowOpacity: 0.1,
shadowRadius: 10,
shadowOffset: { width: 0, height: 4 },
padding: 8,
},
userInfoSection: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: colors.border,
paddingBottom: 12,
},
avatar: {
width: 50,
height: 50,
borderRadius: 25,
marginRight: 12,
},
userInfo: {
flex: 1,
},
userName: {
fontSize: 17,
fontWeight: 'bold',
color: colors.textDark,
},
userMeta: {
fontSize: 14,
color: colors.textLight,
marginTop: 4,
},
groupInfoSection: {
paddingVertical: 16,
},
requestText: {
fontSize: 15,
color: colors.textDark,
lineHeight: 22,
},
groupName: {
fontWeight: 'bold',
color: colors.textDark,
},
actionsSection: {
flexDirection: 'row',
justifyContent: 'space-between',
gap: 12,
},
actionButton: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 12,
borderRadius: 12,
},
declineButton: {
backgroundColor: colors.lightDanger,
},
approveButton: {
// Set background color as requested
backgroundColor: colors.pastelOrange,
},
actionButtonText: {
fontSize: 16,
fontWeight: '600',
marginLeft: 8,
},
});