feat: add expo mobile application source code
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
||||
import { View, Text, StyleSheet, TouchableOpacity, SafeAreaView } from 'react-native';
|
||||
import { Feather } from '@expo/vector-icons';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
export class ErrorBoundary extends Component<Props, State> {
|
||||
public state: State = {
|
||||
hasError: false,
|
||||
error: null,
|
||||
};
|
||||
|
||||
public static getDerivedStateFromError(error: Error): State {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error('Uncaught error:', error, errorInfo);
|
||||
|
||||
// Technical fix: Report error to backend logs
|
||||
const { ApiService } = require('../services/api');
|
||||
ApiService.reportError(error.message, 'critical', {
|
||||
componentStack: errorInfo.componentStack,
|
||||
platform: require('react-native').Platform.OS,
|
||||
});
|
||||
}
|
||||
|
||||
private handleReset = () => {
|
||||
this.setState({ hasError: false, error: null });
|
||||
};
|
||||
|
||||
public render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<View key="error-fallback" style={[styles.container, { paddingTop: 60 }]}>
|
||||
<View style={styles.content}>
|
||||
<View style={styles.iconBox}>
|
||||
<Feather name="alert-triangle" size={60} color="#FF4B4B" />
|
||||
</View>
|
||||
<Text style={styles.title}>Oops! Something went wrong</Text>
|
||||
<Text style={styles.desc}>
|
||||
An unexpected error occurred. Don't worry, your data is safe.
|
||||
</Text>
|
||||
{__DEV__ && (
|
||||
<View style={styles.errorBox}>
|
||||
<Text style={styles.errorText}>{this.state.error?.toString()}</Text>
|
||||
</View>
|
||||
)}
|
||||
<TouchableOpacity style={styles.btn} onPress={this.handleReset}>
|
||||
<Text style={styles.btnText}>Try Again</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, backgroundColor: '#FFFFFF' },
|
||||
content: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 40 },
|
||||
iconBox: { width: 120, height: 120, borderRadius: 40, backgroundColor: '#FFF0F0', alignItems: 'center', justifyContent: 'center', marginBottom: 30 },
|
||||
title: { fontSize: 24, fontFamily: 'Outfit_800ExtraBold', color: '#1A1A1A', textAlign: 'center', marginBottom: 12 },
|
||||
desc: { fontSize: 15, fontFamily: 'Outfit_400Regular', color: '#666', textAlign: 'center', lineHeight: 22, marginBottom: 40 },
|
||||
errorBox: { width: '100%', padding: 16, backgroundColor: '#F5F5F5', borderRadius: 12, marginBottom: 30 },
|
||||
errorText: { fontSize: 12, fontFamily: 'Monaco', color: '#888' },
|
||||
btn: { width: '100%', height: 56, borderRadius: 16, backgroundColor: '#1A1A1A', alignItems: 'center', justifyContent: 'center' },
|
||||
btnText: { color: '#FFFFFF', fontSize: 16, fontFamily: 'Outfit_700Bold' },
|
||||
});
|
||||
Reference in New Issue
Block a user