import React from 'react'; import { View, StyleSheet, Modal } from 'react-native'; import { useTheme } from '~/features/theme/ThemeProvider'; import { useTranslation } from 'react-i18next'; import Text from './Text'; import { SpinnerAnimation } from '../molecules/SpinnerAnimation'; interface LoadingOverlayProps { /** * Ob das Loading-Overlay sichtbar ist */ visible: boolean; /** * Nachricht die angezeigt werden soll */ message?: string; /** * Ob ein Modal verwendet werden soll (blockiert komplette App) * Standard: false (nur als Overlay über aktueller View) */ modal?: boolean; /** * Größe des ActivityIndicator */ size?: 'small' | 'large'; /** * Ob das Overlay abgebrochen werden kann (nur bei modal: true) */ cancelable?: boolean; /** * Callback wenn das Overlay abgebrochen wird */ onCancel?: () => void; } /** * Wiederverwendbare Loading-Overlay-Komponente * * Kann als Overlay über einer View oder als vollständiges Modal verwendet werden. * Unterstützt verschiedene Größen, Nachrichten und Theme-angepasste Farben. * * @example * // Als Overlay über einer View * * * * * * @example * // Als blockierendes Modal * setCanceled(true)} * /> */ const LoadingOverlay: React.FC = ({ visible, message, modal = false, size = 'large', cancelable = false, onCancel }) => { const { isDark } = useTheme(); const { t } = useTranslation(); // Standard-Nachricht falls keine angegeben const displayMessage = message || t('common.loading', 'Wird geladen...'); // Dynamische Styles basierend auf Theme const styles = StyleSheet.create({ overlay: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'transparent', justifyContent: 'center', alignItems: 'center', zIndex: 9999, }, modalOverlay: { flex: 1, backgroundColor: isDark ? 'rgba(0, 0, 0, 0.8)' : 'rgba(255, 255, 255, 0.8)', justifyContent: 'center', alignItems: 'center', }, content: { backgroundColor: isDark ? '#2C2C2C' : '#FFFFFF', borderRadius: 16, padding: 24, paddingHorizontal: 32, alignItems: 'center', minWidth: 200, marginHorizontal: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5, }, message: { marginTop: 16, textAlign: 'center', fontSize: 16, color: isDark ? '#FFFFFF' : '#000000', }, cancelButton: { marginTop: 16, paddingVertical: 8, paddingHorizontal: 16, borderRadius: 8, backgroundColor: isDark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)', }, cancelText: { color: isDark ? '#FFFFFF' : '#000000', fontSize: 14, }, }); // Spinner Animation mit Theme-Farbe const spinnerSize = size === 'large' ? 60 : 40; // Content-Bereich const content = ( {displayMessage} {cancelable && onCancel && ( {t('common.cancel', 'Abbrechen')} )} ); // Nicht sichtbar if (!visible) { return null; } // Als Modal rendern if (modal) { return ( {content} ); } // Als Overlay rendern return ( {content} ); }; export default LoadingOverlay;