106 lines
2.5 KiB
TypeScript
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;
|