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,
|
|||
|
|
},
|
|||
|
|
});
|