bw-expo-app/components/ErrorRetry.tsx

106 lines
2.5 KiB
TypeScript

import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet, StyleProp, ViewStyle } from 'react-native';
import { AlertCircle, RefreshCw } from 'lucide-react';
import { Colors, Spacing, BorderRadius, FontSize, Shadow } from '@/constants/theme';
interface ErrorRetryProps {
message: string;
onRetry: () => void;
subMessage?: string;
style?: StyleProp<ViewStyle>;
showIcon?: boolean;
buttonText?: string;
}
export function ErrorRetry({
message,
onRetry,
subMessage,
style,
showIcon = true,
buttonText = '重试',
}: ErrorRetryProps) {
return (
<View style={[styles.container, style]}>
<View style={styles.content}>
{showIcon && (
<View style={styles.iconContainer}>
<AlertCircle size={48} color={Colors.brand.danger} strokeWidth={1.5} />
</View>
)}
<Text style={styles.title}>{message}</Text>
{subMessage && <Text style={styles.subtitle}>{subMessage}</Text>}
<TouchableOpacity
style={styles.button}
onPress={onRetry}
activeOpacity={0.7}
>
<RefreshCw size={18} color={Colors.brand.primary} style={styles.buttonIcon} />
<Text style={styles.buttonText}>{buttonText}</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
width: '100%',
height: '100%',
backgroundColor: Colors.background.secondary,
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: Spacing.xl,
},
content: {
alignItems: 'center',
maxWidth: 280,
},
iconContainer: {
width: 80,
height: 80,
borderRadius: 40,
backgroundColor: Colors.background.tertiary,
justifyContent: 'center',
alignItems: 'center',
marginBottom: Spacing.lg,
},
title: {
fontSize: FontSize.lg,
fontWeight: '600',
color: Colors.text.primary,
textAlign: 'center',
marginBottom: Spacing.sm,
},
subtitle: {
fontSize: FontSize.sm,
color: Colors.text.tertiary,
textAlign: 'center',
lineHeight: 20,
marginBottom: Spacing.xl,
},
button: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Colors.background.tertiary,
paddingHorizontal: Spacing.xl,
paddingVertical: Spacing.md,
borderRadius: BorderRadius.full,
...Shadow.small,
},
buttonIcon: {
marginRight: Spacing.sm,
},
buttonText: {
fontSize: FontSize.md,
fontWeight: '600',
color: Colors.brand.primary,
},
});
export default ErrorRetry;