botton navi...

This commit is contained in:
Abin Toppo
2025-09-24 14:36:44 +05:30
31 changed files with 1622 additions and 412 deletions
+285 -166
View File
@@ -9,11 +9,17 @@ import {
TouchableOpacity,
Alert,
ActivityIndicator,
Share,
} from 'react-native';
import { RootStackParamList } from '../../navigation/AppNavigator'; // Adjust path
import { apiCall } from '../../utils/ApiHelper'; // Adjust path
import AppView from '../../components/AppView';
import { Picker } from '@react-native-picker/picker';
import colors from '../../components/colors';
import Clipboard from '@react-native-clipboard/clipboard';
import { CompositeScreenProps } from '@react-navigation/native';
import { BottomTabScreenProps } from '@react-navigation/bottom-tabs';
import { ManagementTabParamList } from './ManagementTabNavigation'; // Adjust path
// --- Type Definitions ---
interface Participant {
@@ -35,6 +41,8 @@ export interface GroupDetails {
maxParticipants: number;
portalCharge: number | null;
latePaymentCharge: number | null;
lateFeeMode: 'DAILY' | 'FIXED' | null;
lateFeeValue: number | null;
cycleType: 'QUARTERLY' | 'MONTHLY' | 'WEEKLY' | 'CUSTOM';
customCycleDays: number;
withdrawalMethod: 'RANDOM' | 'SEQUENTIAL';
@@ -54,16 +62,23 @@ export interface EditGroupPayload {
cycleType: 'QUARTERLY' | 'MONTHLY' | 'WEEKLY' | 'CUSTOM';
latePaymentCharge: number;
visibility: 'PUBLIC' | 'PRIVATE';
lateFeeMode: 'DAILY' | 'FIXED' | null;
lateFeeValue: number | null;
}
type EditGroupScreenProps = NativeStackScreenProps<RootStackParamList, 'EditGroup'>;
type EditingField = keyof EditGroupPayload | null;
// Correct props for a screen inside a nested Tab Navigator
type EditGroupScreenProps = CompositeScreenProps<
BottomTabScreenProps<ManagementTabParamList, 'EditGroup'>,
NativeStackScreenProps<RootStackParamList>
>;
type EditingCard = 'groupInfo' | 'financialRules' | 'configuration' | null;
// --- Main Screen Component ---
const EditGroupScreen: React.FC<EditGroupScreenProps> = ({ route }) => {
const { groupId } = route.params;
const [editingField, setEditingField] = useState<EditingField>(null);
const [editingCard, setEditingCard] = useState<EditingCard>(null);
const [groupDetails, setGroupDetails] = useState<GroupDetails | null>(null);
const [editableData, setEditableData] = useState<EditGroupPayload>({
groupName: '',
@@ -74,30 +89,41 @@ const EditGroupScreen: React.FC<EditGroupScreenProps> = ({ route }) => {
cycleType: 'MONTHLY',
latePaymentCharge: 0,
visibility: 'PRIVATE',
lateFeeMode: null,
lateFeeValue: null,
});
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [starting, setStarting] = useState(false);
const [inviting, setInviting] = useState(false);
const [error, setError] = useState<string | null>(null);
// ... (All your handler functions: initializeEditableData, fetchGroupDetails, handleCancel, handleSave, etc. remain the same)
const initializeEditableData = (data: GroupDetails) => {
setEditableData({
groupName: data.groupName,
description: data.description,
maxParticipants: data.maxParticipants,
contributionAmount: data.contributionAmount,
customCycleDays: data.customCycleDays,
cycleType: data.cycleType,
latePaymentCharge: data.latePaymentCharge ?? 0,
visibility: data.visibility,
lateFeeMode: data.lateFeeMode ?? null,
lateFeeValue: data.lateFeeValue ?? null,
});
};
const fetchGroupDetails = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await apiCall(`https://api.godemo.in/FundCollect/api/fund/group/details?groupId=${groupId}`, 'GET') as { status: string; data?: GroupDetails; message?: string };
const response = await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/api/fund/group/details?groupId=${groupId}`, 'GET') as { status: string; data?: GroupDetails; message?: string };
console.log("groupDetails",response)
if (response.status === 'success' && response.data) {
setGroupDetails(response.data);
setEditableData({
groupName: response.data.groupName,
description: response.data.description,
maxParticipants: response.data.maxParticipants,
contributionAmount: response.data.contributionAmount,
customCycleDays: response.data.customCycleDays,
cycleType: response.data.cycleType,
latePaymentCharge: response.data.latePaymentCharge ?? 0,
visibility: response.data.visibility,
});
initializeEditableData(response.data);
} else {
throw new Error(response.message || 'Failed to fetch group data.');
}
@@ -114,36 +140,24 @@ const EditGroupScreen: React.FC<EditGroupScreenProps> = ({ route }) => {
const handleCancel = () => {
if (groupDetails) {
setEditableData({
groupName: groupDetails.groupName,
description: groupDetails.description,
maxParticipants: groupDetails.maxParticipants,
contributionAmount: groupDetails.contributionAmount,
customCycleDays: groupDetails.customCycleDays,
cycleType: groupDetails.cycleType,
latePaymentCharge: groupDetails.latePaymentCharge ?? 0,
visibility: groupDetails.visibility,
});
initializeEditableData(groupDetails);
}
setEditingField(null);
setEditingCard(null);
};
const handleSave = async () => {
if (!groupDetails || !editingField) return;
if (!groupDetails) return;
if (editingField === 'maxParticipants') {
const newMaxParticipants = Number(editableData.maxParticipants);
if (newMaxParticipants < groupDetails.totalParticipants) {
Alert.alert('Invalid Input', `Max participants cannot be less than the current count (${groupDetails.totalParticipants}).`);
return;
}
if (editableData.maxParticipants < groupDetails.totalParticipants) {
Alert.alert('Invalid Input', `Max participants cannot be less than the current count (${groupDetails.totalParticipants}).`);
return;
}
setSaving(true);
try {
await apiCall(`https://api.godemo.in/FundCollect/api/fund/groups/${groupDetails.id}/edit`, 'PUT', editableData);
await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/api/fund/groups/${groupDetails.id}/edit`, 'PUT', editableData);
Alert.alert('Success', 'Group has been updated.');
setEditingField(null);
setEditingCard(null);
await fetchGroupDetails();
} catch (e: any) {
Alert.alert('Save Error', e.message || 'An unexpected error occurred.');
@@ -165,7 +179,7 @@ const EditGroupScreen: React.FC<EditGroupScreenProps> = ({ route }) => {
onPress: async () => {
setStarting(true);
try {
await apiCall(`https://api.godemo.in/FundCollect/api/fund/group/start?groupId=${groupDetails.id}`, 'GET');
await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/api/fund/group/start?groupId=${groupDetails.id}`, 'GET');
Alert.alert('Success', 'Group has been started successfully.');
await fetchGroupDetails();
} catch (e: any) {
@@ -179,124 +193,173 @@ const EditGroupScreen: React.FC<EditGroupScreenProps> = ({ route }) => {
]
);
};
const handleInvite = async () => {
if (!groupDetails) return;
setInviting(true);
try {
const response = await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/api/invite/generate?groupId=${groupDetails.id}`, 'GET') as { data?: string };
const inviteLink = response.data;
if (inviteLink) {
Clipboard.setString(inviteLink);
Alert.alert('Copied!', 'Invitation link copied to clipboard.');
await Share.share({
message: `Join my group on CircleCollect! ${inviteLink}`,
url: inviteLink,
title: 'CircleCollect Group Invitation'
});
} else {
throw new Error('Could not generate invitation link.');
}
} catch (error: any) {
Alert.alert('Error', error.message || 'Failed to generate invitation.');
} finally {
setInviting(false);
}
};
const handleUpdateField = (field: keyof EditGroupPayload, value: any) => {
setEditableData(prev => ({ ...prev, [field]: value }));
};
// ... (renderField and renderCard functions also remain the same)
const renderField = (field: keyof EditGroupPayload, label: string, displayValue: string | number, isEditing: boolean) => {
const commonInputProps = { style: styles.input, placeholderTextColor: "#9CA3AF" };
const getInputForField = () => {
switch(field) {
case 'groupName':
return <TextInput {...commonInputProps} value={editableData.groupName} onChangeText={(text) => handleUpdateField('groupName', text)} />;
case 'description':
return <TextInput {...commonInputProps} style={[styles.input, styles.textArea]} value={editableData.description} onChangeText={(text) => handleUpdateField('description', text)} multiline />;
case 'contributionAmount':
return <TextInput {...commonInputProps} value={String(editableData.contributionAmount ?? '')} onChangeText={(text) => handleUpdateField('contributionAmount', text ? Number(text.replace(/[^0-9]/g, '')) : 0)} keyboardType="numeric" />;
case 'maxParticipants':
return <TextInput {...commonInputProps} value={String(editableData.maxParticipants ?? '')} onChangeText={(text) => handleUpdateField('maxParticipants', text ? Number(text.replace(/[^0-9]/g, '')) : 0)} keyboardType="numeric" />;
case 'latePaymentCharge':
return <TextInput {...commonInputProps} value={String(editableData.latePaymentCharge ?? '')} onChangeText={(text) => handleUpdateField('latePaymentCharge', text ? Number(text.replace(/[^0-9]/g, '')) : 0)} keyboardType="numeric" />;
case 'cycleType':
return (
<Picker selectedValue={editableData.cycleType} onValueChange={(itemValue) => handleUpdateField('cycleType', itemValue)} style={styles.picker}>
{['MONTHLY', 'WEEKLY', 'QUARTERLY', 'CUSTOM'].map(c => <Picker.Item key={c} label={c} value={c} />)}
</Picker>
);
case 'customCycleDays':
if (editableData.cycleType !== 'CUSTOM') return null;
return <TextInput {...commonInputProps} value={String(editableData.customCycleDays ?? '')} onChangeText={(text) => handleUpdateField('customCycleDays', text ? Number(text.replace(/[^0-9]/g, '')) : 0)} keyboardType="numeric" />;
case 'visibility':
return (
<Picker selectedValue={editableData.visibility} onValueChange={(itemValue) => handleUpdateField('visibility', itemValue)} style={styles.picker}>
<Picker.Item label="PUBLIC" value="PUBLIC" />
<Picker.Item label="PRIVATE" value="PRIVATE" />
</Picker>
);
default:
return null;
}
};
return (
<View style={styles.fieldContainer}>
<Text style={styles.infoLabel}>{label}</Text>
{isEditing && isEditable ? (
<View style={{marginTop: 8}}>{getInputForField()}</View>
) : (
<Text style={styles.infoValue}>{displayValue}</Text>
)}
</View>
);
}
const renderCard = (title: string, fields: Array<{ field: keyof EditGroupPayload, label: string, displayValue: () => string | number }>, cardKey: EditingCard) => {
const isEditingThisCard = editingCard === cardKey;
return (
<View style={styles.card}>
<View style={styles.cardHeader}>
<Text style={styles.cardTitle}>{title}</Text>
{isEditable && !editingCard && (
<TouchableOpacity onPress={() => setEditingCard(cardKey)} style={styles.editButton}>
<Text style={styles.editButtonText}>✎</Text>
</TouchableOpacity>
)}
</View>
{fields.map(({ field, label, displayValue }) =>
renderField(field, label, displayValue(), isEditingThisCard)
)}
{isEditingThisCard && (
<View style={styles.cardActions}>
<TouchableOpacity style={[styles.button, styles.cancelButton]} onPress={handleCancel} disabled={saving}>
<Text style={[styles.buttonText, { color: '#374151' }]}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.saveButton]} onPress={handleSave} disabled={saving}>
{saving ? <ActivityIndicator color="#FFFFFF" size="small" /> : <Text style={styles.buttonText}>Save</Text>}
</TouchableOpacity>
</View>
)}
</View>
);
}
if (loading) return <View style={styles.centered}><ActivityIndicator size="large" color="#4F46E5" /></View>;
if (error) return <View style={styles.centered}><Text style={styles.errorText}>{error}</Text></View>;
if (!groupDetails) return null;
const isEditable = groupDetails.status === 'PENDING' || groupDetails.status === 'APPROVED';
const isInvitable = groupDetails.status === 'APPROVED';
const canStartGroup = groupDetails.status === 'APPROVED' && groupDetails.totalParticipants >= groupDetails.minParticipants;
const renderInputField = (field: EditingField) => {
if (!field || !editableData) return null;
const commonProps = { style: styles.input, placeholderTextColor: "#9CA3AF" };
switch(field) {
case 'groupName':
return <TextInput {...commonProps} value={editableData.groupName} onChangeText={(text) => handleUpdateField('groupName', text)} />;
case 'description':
return <TextInput {...commonProps} style={[styles.input, styles.textArea]} value={editableData.description} onChangeText={(text) => handleUpdateField('description', text)} multiline />;
case 'contributionAmount':
case 'maxParticipants':
case 'latePaymentCharge':
case 'customCycleDays':
return <TextInput {...commonProps} value={String(editableData[field] ?? '')} onChangeText={(text) => handleUpdateField(field, text ? Number(text.replace(/[^0-9]/g, '')) : 0)} keyboardType="numeric" />;
case 'cycleType':
return <Picker selectedValue={editableData.cycleType} onValueChange={(itemValue) => handleUpdateField('cycleType', itemValue)} style={styles.picker}>
{['MONTHLY', 'WEEKLY', 'QUARTERLY', 'CUSTOM'].map(c => <Picker.Item key={c} label={c} value={c} />)}
</Picker>;
case 'visibility':
return <Picker selectedValue={editableData.visibility} onValueChange={(itemValue) => handleUpdateField('visibility', itemValue)} style={styles.picker}>
<Picker.Item label="PUBLIC" value="PUBLIC" />
<Picker.Item label="PRIVATE" value="PRIVATE" />
</Picker>;
default: return null;
}
}
const renderRow = (field: EditingField, label: string, displayValue: string | number) => {
return (
<View style={styles.fieldContainer}>
<View style={styles.infoRow}>
<Text style={styles.infoLabel}>{label}</Text>
{editingField !== field && (
<View style={styles.valueContainer}>
<Text style={styles.infoValue}>{displayValue}</Text>
{isEditable && <TouchableOpacity onPress={() => setEditingField(field)} style={styles.editButton}>
<Text style={styles.editButtonText}>✎</Text>
</TouchableOpacity>}
</View>
)}
</View>
{editingField === field && isEditable && (
<View style={styles.editingContainer}>
{renderInputField(field)}
<View style={styles.cardActions}>
<TouchableOpacity style={[styles.button, styles.cancelButton]} onPress={handleCancel} disabled={saving}>
<Text style={[styles.buttonText, { color: '#374151' }]}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.saveButton]} onPress={handleSave} disabled={saving}>
{saving ? <ActivityIndicator color="#FFFFFF" size="small" /> : <Text style={styles.buttonText}>Save</Text>}
</TouchableOpacity>
</View>
</View>
)}
</View>
)
}
return (
<AppView paddingHorizontal={0}>
<ScrollView style={styles.container} contentContainerStyle={styles.contentContainer}>
<Text style={styles.headerTitle}>Edit Group</Text>
{canStartGroup && (
<View style={styles.card}>
<Text style={styles.cardTitle}>Ready to Start?</Text>
<Text style={styles.startGroupText}>This group has met the minimum participant requirement.</Text>
<TouchableOpacity style={[styles.button, styles.startButton]} onPress={handleStartGroup} disabled={starting}>
{starting ? <ActivityIndicator color="#FFFFFF" /> : <Text style={styles.buttonText}>Start Group</Text>}
</TouchableOpacity>
</View>
// Use AppView as the root container with flex: 1
<AppView style={{ flex: 1, paddingHorizontal: 0 }}>
<View style={styles.headerContainer}>
<Text style={styles.headerTitle}>Manage Group</Text>
{isInvitable && (
<TouchableOpacity style={[styles.button, styles.inviteButton]} onPress={handleInvite} disabled={inviting}>
{inviting ? <ActivityIndicator color="#FFFFFF" /> : <Text style={styles.buttonText}>Invite</Text>}
</TouchableOpacity>
)}
</View>
<View style={styles.card}>
<Text style={styles.cardTitle}>Group Info</Text>
{renderRow('groupName', 'Group Name', groupDetails.groupName)}
{renderRow('description', 'Description', groupDetails.description)}
</View>
<ScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}
showsVerticalScrollIndicator={false}
>
{renderCard('Group Info', [
{ field: 'groupName', label: 'Group Name', displayValue: () => groupDetails.groupName },
{ field: 'description', label: 'Description', displayValue: () => groupDetails.description },
], 'groupInfo')}
<View style={styles.card}>
<Text style={styles.cardTitle}>Financial Rules</Text>
{renderRow('contributionAmount', 'Contribution', `₹${groupDetails.contributionAmount.toLocaleString('en-IN')}`)}
{renderRow('maxParticipants', 'Max Participants', `${groupDetails.totalParticipants} / ${groupDetails.maxParticipants}`)}
{renderRow('latePaymentCharge', 'Late Fee', `₹${(groupDetails.latePaymentCharge ?? 0).toLocaleString('en-IN')}`)}
</View>
<View style={styles.card}>
<Text style={styles.cardTitle}>Configuration</Text>
{renderRow('cycleType', 'Payment Cycle', groupDetails.cycleType)}
{(editableData.cycleType === 'CUSTOM' || groupDetails.cycleType === 'CUSTOM') && renderRow('customCycleDays', 'Custom Days', `${editableData.customCycleDays ?? groupDetails.customCycleDays} days`)}
{renderRow('visibility', 'Visibility', groupDetails.visibility)}
</View>
{renderCard('Financial Rules', [
{ field: 'contributionAmount', label: 'Contribution', displayValue: () => `₹${groupDetails.contributionAmount.toLocaleString('en-IN')}` },
{ field: 'maxParticipants', label: 'Max Participants', displayValue: () => `${groupDetails.totalParticipants} / ${groupDetails.maxParticipants}` },
{ field: 'latePaymentCharge', label: 'Late Fee', displayValue: () => `₹${(groupDetails.latePaymentCharge ?? 0).toLocaleString('en-IN')}` },
], 'financialRules')}
{renderCard('Configuration', [
{ field: 'cycleType', label: 'Payment Cycle', displayValue: () => groupDetails.cycleType },
{ field: 'customCycleDays', label: 'Custom Days', displayValue: () => `${groupDetails.customCycleDays ?? ''} days` },
{ field: 'visibility', label: 'Visibility', displayValue: () => groupDetails.visibility },
], 'configuration')}
{/* Participants Card ... */}
<View style={styles.card}>
<Text style={styles.cardTitle}>Participants ({groupDetails.totalParticipants})</Text>
{groupDetails.participants.length > 0 ? (
groupDetails.participants.map(p => (
<View key={p.id} style={styles.participantRow}>
<View>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={styles.participantName}>{`${p.firstName} ${p.lastName || ''}`.trim()}</Text>
{p.role === 'ORGANIZER' && <View style={styles.organizerBadge}><Text style={styles.organizerBadgeText}>Organizer</Text></View>}
<View>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={styles.participantName}>{`${p.firstName} ${p.lastName || ''}`.trim()}</Text>
{p.role === 'ORGANIZER' && <View style={styles.organizerBadge}><Text style={styles.organizerBadgeText}>Organizer</Text></View>}
</View>
<Text style={styles.participantMobile}>{p.mobile}</Text>
</View>
<Text style={styles.participantMobile}>{p.mobile}</Text>
</View>
</View>
))
) : (
@@ -304,48 +367,104 @@ const EditGroupScreen: React.FC<EditGroupScreenProps> = ({ route }) => {
)}
</View>
</ScrollView>
{/* --- FLOATING BUTTON AREA --- */}
{/* This View is a sibling of ScrollView, allowing it to float on top */}
{canStartGroup && (
<View style={styles.floatingButtonContainer}>
<TouchableOpacity
style={styles.activateButton}
onPress={handleStartGroup}
disabled={starting}
>
{starting ? (
<ActivityIndicator color="#FFFFFF" size="small" />
) : (
<Text style={styles.activateButtonText}>Activate Group</Text>
)}
</TouchableOpacity>
</View>
)}
</AppView>
);
};
// --- Styles ---
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#F3F4F6' },
contentContainer: { padding: 16, paddingBottom: 40 },
centered: { flex: 1, justifyContent: 'center', alignItems: 'center' },
errorText: { color: '#EF4444', fontSize: 16, textAlign: 'center' },
headerTitle: { fontSize: 28, fontWeight: 'bold', color: '#111827', marginBottom: 20 },
card: { backgroundColor: '#FFFFFF', borderRadius: 16, padding: 20, marginBottom: 16, shadowColor: '#374151', shadowOpacity: 0.05, shadowRadius: 10 },
cardTitle: { fontSize: 18, fontWeight: 'bold', color: '#1F2937', marginBottom: 12, borderBottomWidth: 1, borderBottomColor: '#E5E7EB', paddingBottom: 10 },
editButton: { padding: 8, marginLeft: 8 },
editButtonText: { color: '#4F46E5', fontSize: 20, fontWeight: 'bold' },
fieldContainer: { borderBottomWidth: 1, borderBottomColor: '#F3F4F6', paddingVertical: 12 },
infoRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },
infoLabel: { fontSize: 16, color: '#6B7280' },
infoValue: { fontSize: 16, fontWeight: '600', color: '#111827', textTransform: 'capitalize' },
valueContainer: { flexDirection: 'row', alignItems: 'center' },
container: { flex: 1, backgroundColor: '#F3F4F6' },
// Added more paddingBottom to ensure content doesn't hide behind the button AND the tab bar
contentContainer: { padding: 16, paddingTop: 0, paddingBottom: 150 },
centered: { flex: 1, justifyContent: 'center', alignItems: 'center' },
errorText: { color: '#EF4444', fontSize: 16, textAlign: 'center' },
headerContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 16,
paddingTop: 16,
paddingBottom: 8,
backgroundColor: 'white', // Changed for a cleaner header look
borderBottomWidth: 1,
borderBottomColor: '#E5E7EB',
},
headerTitle: { fontSize: 28, fontWeight: 'bold', color: '#111827' },
card: { backgroundColor: '#FFFFFF', borderRadius: 16, padding: 20, marginBottom: 16, shadowColor: '#374151', shadowOpacity: 0.05, shadowRadius: 10 },
cardHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingBottom: 10,
marginBottom: 12,
},
cardTitle: { fontSize: 18, fontWeight: 'bold', color: '#1F2937' },
editButton: { padding: 8 },
editButtonText: { color: colors.pastelPink, fontSize: 20, fontWeight: 'bold' },
fieldContainer: { borderBottomWidth: 1, borderBottomColor: '#F3F4F6', paddingBottom: 12, marginBottom: 12 },
infoLabel: { fontSize: 16, color: '#6B7280', marginBottom: 4 },
infoValue: { fontSize: 16, fontWeight: '600', color: '#111827', textTransform: 'capitalize' },
input: { backgroundColor: '#F9FAFB', borderWidth: 1, borderColor: '#D1D5DB', borderRadius: 10, padding: 14, fontSize: 16, color: '#111827' },
textArea: { height: 100, textAlignVertical: 'top' },
picker: { backgroundColor: '#F9FAFB', borderWidth: 1, borderColor: '#D1D5DB', borderRadius: 10 },
participantRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#F3F4F6' },
participantName: { fontSize: 16, fontWeight: '600', color: '#111827' },
participantMobile: { fontSize: 14, color: '#6B7280', marginTop: 4 },
organizerBadge: { backgroundColor: '#FEF3C7', paddingHorizontal: 8, paddingVertical: 3, borderRadius: 12, marginLeft: 10 },
organizerBadgeText: { color: '#92400E', fontSize: 12, fontWeight: '500' },
noParticipantsText: { fontSize: 15, color: '#6B7280', textAlign: 'center', paddingVertical: 20 },
cardActions: { flexDirection: 'row', justifyContent: 'flex-end', marginTop: 20, paddingTop: 16, borderTopWidth: 1, borderTopColor: '#E5E7EB' },
button: { borderRadius: 10, paddingVertical: 12, paddingHorizontal: 20, marginLeft: 10, minWidth: 80, alignItems: 'center', justifyContent: 'center' },
saveButton: { backgroundColor: colors.pastelOrange },
cancelButton: { backgroundColor: '#E5E7EB' },
inviteButton: { backgroundColor: colors.primary },
buttonText: { color: '#000000ff', fontSize: 15, fontWeight: '600' },
editingContainer: { marginTop: 12 },
input: { backgroundColor: '#F9FAFB', borderWidth: 1, borderColor: '#D1D5DB', borderRadius: 10, padding: 14, fontSize: 16, color: '#111827' },
textArea: { height: 100, textAlignVertical: 'top' },
picker: { backgroundColor: '#F9FAFB', borderWidth: 1, borderColor: '#D1D5DB', borderRadius: 10, padding: 0, margin:0 },
participantRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#F3F4F6' },
participantName: { fontSize: 16, fontWeight: '600', color: '#111827' },
participantMobile: { fontSize: 14, color: '#6B7280', marginTop: 4 },
organizerBadge: { backgroundColor: '#FEF3C7', paddingHorizontal: 8, paddingVertical: 3, borderRadius: 12, marginLeft: 10 },
organizerBadgeText: { color: '#92400E', fontSize: 12, fontWeight: '500' },
noParticipantsText: { fontSize: 15, color: '#6B7280', textAlign: 'center', paddingVertical: 20 },
cardActions: { flexDirection: 'row', justifyContent: 'flex-end', marginTop: 20, paddingTop: 16, borderTopWidth: 1, borderTopColor: '#E5E7EB' },
button: { borderRadius: 10, paddingVertical: 12, paddingHorizontal: 20, marginLeft: 10, minWidth: 80, alignItems: 'center', justifyContent: 'center' },
saveButton: { backgroundColor: '#4F46E5' },
cancelButton: { backgroundColor: '#E5E7EB' },
startButton: { backgroundColor: '#22c55e', marginTop: 10 },
startGroupText: { fontSize: 15, color: '#6B7280', lineHeight: 22, marginBottom: 10},
buttonText: { color: '#FFFFFF', fontSize: 15, fontWeight: '600' },
// --- FLOATING BUTTON STYLES ---
floatingButtonContainer: {
position: 'absolute',
bottom: 85, // Positioned above the tab bar
left: 20,
right: 20,
alignItems: 'center', // Center the button horizontally
zIndex: 1, // Ensure it's on top
},
activateButton: {
backgroundColor: colors.pastelOrange,
borderRadius: 14,
paddingVertical: 16,
paddingHorizontal: 32,
elevation: 8,
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 4,
width: '90%', // Adjust width as needed
alignItems: 'center',
},
activateButtonText: {
color: '#000000ff',
fontSize: 18,
fontWeight: 'bold',
},
});
export default EditGroupScreen;