Include app source and update .gitignore to exclude local release artifacts and signing files. Made-with: Cursor
156 lines
4.4 KiB
TypeScript
156 lines
4.4 KiB
TypeScript
import React from 'react';
|
||
import { View, StyleSheet, TouchableOpacity, ActivityIndicator } from 'react-native';
|
||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||
|
||
import { Avatar, Text } from '../../../components/common';
|
||
import { colors, spacing, borderRadius, shadows } from '../../../theme';
|
||
|
||
interface GroupInfoSummaryCardProps {
|
||
groupName?: string;
|
||
groupAvatar?: string;
|
||
groupNo?: string;
|
||
groupDescription?: string;
|
||
memberCountText?: string;
|
||
}
|
||
|
||
export const GroupInfoSummaryCard: React.FC<GroupInfoSummaryCardProps> = ({
|
||
groupName,
|
||
groupAvatar,
|
||
groupNo,
|
||
groupDescription,
|
||
memberCountText,
|
||
}) => {
|
||
return (
|
||
<View style={styles.headerCard}>
|
||
<View style={styles.groupHeader}>
|
||
<Avatar source={groupAvatar || ''} size={88} name={groupName} />
|
||
<View style={styles.groupInfo}>
|
||
<Text variant="h3" style={styles.groupName} numberOfLines={1}>{groupName || '群聊'}</Text>
|
||
<View style={styles.groupMeta}>
|
||
<MaterialCommunityIcons name="account-group" size={16} color={colors.text.secondary} />
|
||
<Text variant="caption" color={colors.text.secondary}>
|
||
{memberCountText || '- 人'}
|
||
</Text>
|
||
</View>
|
||
<Text variant="caption" color={colors.text.secondary} style={styles.groupNoText}>
|
||
群号:{groupNo || '-'}
|
||
</Text>
|
||
</View>
|
||
</View>
|
||
<View style={styles.descriptionContainer}>
|
||
<MaterialCommunityIcons name="information-outline" size={16} color={colors.text.secondary} />
|
||
<Text variant="body" color={colors.text.secondary} style={styles.groupDesc}>
|
||
{groupDescription || '暂无群描述'}
|
||
</Text>
|
||
</View>
|
||
</View>
|
||
);
|
||
};
|
||
|
||
interface DecisionFooterProps {
|
||
canAction: boolean;
|
||
submitting: boolean;
|
||
onReject: () => void;
|
||
onApprove: () => void;
|
||
processedText?: string;
|
||
}
|
||
|
||
export const DecisionFooter: React.FC<DecisionFooterProps> = ({
|
||
canAction,
|
||
submitting,
|
||
onReject,
|
||
onApprove,
|
||
processedText = '该请求已处理',
|
||
}) => {
|
||
const insets = useSafeAreaInsets();
|
||
if (canAction) {
|
||
return (
|
||
<View style={[styles.footer, { paddingBottom: Math.max(insets.bottom, spacing.sm) }]}>
|
||
<TouchableOpacity style={[styles.btn, styles.reject]} onPress={onReject} disabled={submitting}>
|
||
<Text variant="body" color={colors.error.main}>拒绝</Text>
|
||
</TouchableOpacity>
|
||
<TouchableOpacity style={[styles.btn, styles.approve]} onPress={onApprove} disabled={submitting}>
|
||
{submitting ? <ActivityIndicator color="#fff" /> : <Text variant="body" color="#fff">同意</Text>}
|
||
</TouchableOpacity>
|
||
</View>
|
||
);
|
||
}
|
||
return (
|
||
<View style={[styles.statusBox, { paddingBottom: Math.max(insets.bottom, spacing.sm) }]}>
|
||
<Text variant="caption" color={colors.text.secondary}>{processedText}</Text>
|
||
</View>
|
||
);
|
||
};
|
||
|
||
const styles = StyleSheet.create({
|
||
headerCard: {
|
||
backgroundColor: colors.background.paper,
|
||
borderRadius: borderRadius.lg,
|
||
padding: spacing.lg,
|
||
marginBottom: spacing.md,
|
||
...shadows.sm,
|
||
},
|
||
groupHeader: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
},
|
||
groupInfo: {
|
||
marginLeft: spacing.lg,
|
||
flex: 1,
|
||
},
|
||
groupName: {
|
||
marginBottom: spacing.xs,
|
||
fontWeight: '700',
|
||
},
|
||
groupMeta: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
gap: spacing.xs,
|
||
},
|
||
groupNoText: {
|
||
marginTop: spacing.xs,
|
||
},
|
||
descriptionContainer: {
|
||
flexDirection: 'row',
|
||
alignItems: 'flex-start',
|
||
backgroundColor: colors.background.default,
|
||
borderRadius: borderRadius.lg,
|
||
padding: spacing.md,
|
||
marginTop: spacing.md,
|
||
},
|
||
groupDesc: {
|
||
marginLeft: spacing.sm,
|
||
flex: 1,
|
||
lineHeight: 20,
|
||
},
|
||
footer: {
|
||
paddingHorizontal: spacing.lg,
|
||
paddingTop: spacing.sm,
|
||
flexDirection: 'row',
|
||
backgroundColor: colors.background.default,
|
||
},
|
||
btn: {
|
||
flex: 1,
|
||
height: 42,
|
||
borderRadius: borderRadius.md,
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
},
|
||
reject: {
|
||
marginRight: spacing.sm,
|
||
backgroundColor: colors.error.light + '25',
|
||
borderWidth: 1,
|
||
borderColor: colors.error.light,
|
||
},
|
||
approve: {
|
||
marginLeft: spacing.sm,
|
||
backgroundColor: colors.primary.main,
|
||
},
|
||
statusBox: {
|
||
alignItems: 'center',
|
||
paddingTop: spacing.sm,
|
||
backgroundColor: colors.background.default,
|
||
},
|
||
});
|