348 lines
9.0 KiB
TypeScript
348 lines
9.0 KiB
TypeScript
/*
|
|
* File: CustomModal.tsx
|
|
* Description: Custom modal component with matching UI design
|
|
* Design & Developed by Tech4Biz Solutions
|
|
* Copyright (c) Spurrin Innovations. All rights reserved.
|
|
*/
|
|
|
|
import React from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
TouchableOpacity,
|
|
Modal,
|
|
TouchableWithoutFeedback,
|
|
Dimensions,
|
|
} from 'react-native';
|
|
import { theme } from '../../theme/theme';
|
|
import Icon from 'react-native-vector-icons/Feather';
|
|
|
|
// ============================================================================
|
|
// INTERFACES
|
|
// ============================================================================
|
|
|
|
/**
|
|
* CustomModalProps Interface
|
|
*
|
|
* Purpose: Defines the props required by the CustomModal component
|
|
*
|
|
* Props:
|
|
* - visible: Whether the modal is visible
|
|
* - title: Modal title
|
|
* - message: Modal message/content
|
|
* - type: Modal type (success, error, warning, info, confirm)
|
|
* - onConfirm: Callback for confirm action
|
|
* - onCancel: Callback for cancel action
|
|
* - confirmText: Text for confirm button
|
|
* - cancelText: Text for cancel button
|
|
* - onClose: Callback for closing modal
|
|
* - showCancel: Whether to show cancel button
|
|
* - icon: Custom icon name
|
|
*/
|
|
interface CustomModalProps {
|
|
visible: boolean;
|
|
title: string;
|
|
message: string;
|
|
type?: 'success' | 'error' | 'warning' | 'info' | 'confirm';
|
|
onConfirm?: () => void;
|
|
onCancel?: () => void;
|
|
confirmText?: string;
|
|
cancelText?: string;
|
|
onClose?: () => void;
|
|
showCancel?: boolean;
|
|
icon?: string;
|
|
}
|
|
|
|
// ============================================================================
|
|
// CUSTOM MODAL COMPONENT
|
|
// ============================================================================
|
|
|
|
/**
|
|
* CustomModal Component
|
|
*
|
|
* Purpose: Displays a custom modal with consistent UI design
|
|
*
|
|
* Features:
|
|
* - Multiple modal types (success, error, warning, info, confirm)
|
|
* - Customizable buttons and text
|
|
* - Consistent theme styling
|
|
* - Backdrop tap to close
|
|
* - Icon support
|
|
* - Responsive design
|
|
*/
|
|
export const CustomModal: React.FC<CustomModalProps> = ({
|
|
visible,
|
|
title,
|
|
message,
|
|
type = 'info',
|
|
onConfirm,
|
|
onCancel,
|
|
confirmText = 'OK',
|
|
cancelText = 'Cancel',
|
|
onClose,
|
|
showCancel = false,
|
|
icon,
|
|
}) => {
|
|
// ============================================================================
|
|
// MODAL CONFIGURATION
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Get modal configuration based on type
|
|
*/
|
|
const getModalConfig = () => {
|
|
switch (type) {
|
|
case 'success':
|
|
return {
|
|
icon: icon || 'check-circle',
|
|
iconColor: theme.colors.success,
|
|
backgroundColor: theme.colors.background,
|
|
borderColor: theme.colors.success,
|
|
};
|
|
case 'error':
|
|
return {
|
|
icon: icon || 'alert-circle',
|
|
iconColor: theme.colors.error,
|
|
backgroundColor: theme.colors.background,
|
|
borderColor: theme.colors.error,
|
|
};
|
|
case 'warning':
|
|
return {
|
|
icon: icon || 'alert-triangle',
|
|
iconColor: theme.colors.warning,
|
|
backgroundColor: theme.colors.background,
|
|
borderColor: theme.colors.warning,
|
|
};
|
|
case 'confirm':
|
|
return {
|
|
icon: icon || 'help-circle',
|
|
iconColor: theme.colors.primary,
|
|
backgroundColor: theme.colors.background,
|
|
borderColor: theme.colors.primary,
|
|
};
|
|
default:
|
|
return {
|
|
icon: icon || 'info',
|
|
iconColor: theme.colors.info,
|
|
backgroundColor: theme.colors.background,
|
|
borderColor: theme.colors.info,
|
|
};
|
|
}
|
|
};
|
|
|
|
const config = getModalConfig();
|
|
|
|
// ============================================================================
|
|
// EVENT HANDLERS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Handle confirm action
|
|
*/
|
|
const handleConfirm = () => {
|
|
if (onConfirm) {
|
|
onConfirm();
|
|
}
|
|
if (onClose) {
|
|
onClose();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handle cancel action
|
|
*/
|
|
const handleCancel = () => {
|
|
if (onCancel) {
|
|
onCancel();
|
|
}
|
|
if (onClose) {
|
|
onClose();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handle backdrop press
|
|
*/
|
|
const handleBackdropPress = () => {
|
|
if (onClose) {
|
|
onClose();
|
|
}
|
|
};
|
|
|
|
// ============================================================================
|
|
// RENDER
|
|
// ============================================================================
|
|
|
|
return (
|
|
<Modal
|
|
visible={visible}
|
|
transparent
|
|
animationType="fade"
|
|
onRequestClose={onClose}
|
|
>
|
|
<TouchableWithoutFeedback onPress={handleBackdropPress}>
|
|
<View style={styles.backdrop}>
|
|
<TouchableWithoutFeedback>
|
|
<View style={[
|
|
styles.modalContainer,
|
|
{
|
|
backgroundColor: config.backgroundColor,
|
|
borderColor: config.borderColor,
|
|
}
|
|
]}>
|
|
{/* Icon */}
|
|
<View style={[styles.iconContainer, { backgroundColor: config.iconColor + '20' }]}>
|
|
<Icon name={config.icon} size={32} color={config.iconColor} />
|
|
</View>
|
|
|
|
{/* Title */}
|
|
<Text style={styles.title}>{title}</Text>
|
|
|
|
{/* Message */}
|
|
<Text style={styles.message}>{message}</Text>
|
|
|
|
{/* Buttons */}
|
|
<View style={styles.buttonContainer}>
|
|
{showCancel && (
|
|
<TouchableOpacity
|
|
style={[styles.button, styles.cancelButton]}
|
|
onPress={handleCancel}
|
|
activeOpacity={0.7}
|
|
>
|
|
<Text style={styles.cancelButtonText}>{cancelText}</Text>
|
|
</TouchableOpacity>
|
|
)}
|
|
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.button,
|
|
styles.confirmButton,
|
|
{ backgroundColor: config.iconColor },
|
|
showCancel && styles.confirmButtonWithCancel,
|
|
]}
|
|
onPress={handleConfirm}
|
|
activeOpacity={0.7}
|
|
>
|
|
<Text style={styles.confirmButtonText}>{confirmText}</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
</TouchableWithoutFeedback>
|
|
</View>
|
|
</TouchableWithoutFeedback>
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
// ============================================================================
|
|
// STYLES
|
|
// ============================================================================
|
|
|
|
const { width: screenWidth } = Dimensions.get('window');
|
|
|
|
const styles = StyleSheet.create({
|
|
// Backdrop
|
|
backdrop: {
|
|
flex: 1,
|
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
paddingHorizontal: theme.spacing.lg,
|
|
},
|
|
|
|
// Modal container
|
|
modalContainer: {
|
|
width: screenWidth - theme.spacing.lg * 2,
|
|
backgroundColor: theme.colors.background,
|
|
borderRadius: theme.borderRadius.large,
|
|
padding: theme.spacing.xl,
|
|
alignItems: 'center',
|
|
borderWidth: 2,
|
|
...theme.shadows.large,
|
|
},
|
|
|
|
// Icon container
|
|
iconContainer: {
|
|
width: 80,
|
|
height: 80,
|
|
borderRadius: 40,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
marginBottom: theme.spacing.lg,
|
|
},
|
|
|
|
// Title
|
|
title: {
|
|
fontSize: theme.typography.fontSize.displaySmall,
|
|
fontFamily: theme.typography.fontFamily.bold,
|
|
color: theme.colors.textPrimary,
|
|
textAlign: 'center',
|
|
marginBottom: theme.spacing.md,
|
|
},
|
|
|
|
// Message
|
|
message: {
|
|
fontSize: theme.typography.fontSize.bodyLarge,
|
|
fontFamily: theme.typography.fontFamily.regular,
|
|
color: theme.colors.textSecondary,
|
|
textAlign: 'center',
|
|
lineHeight: theme.typography.fontSize.bodyLarge * 1.4,
|
|
marginBottom: theme.spacing.xl,
|
|
},
|
|
|
|
// Button container
|
|
buttonContainer: {
|
|
flexDirection: 'row',
|
|
width: '100%',
|
|
gap: theme.spacing.md,
|
|
},
|
|
|
|
// Button base
|
|
button: {
|
|
flex: 1,
|
|
paddingVertical: theme.spacing.md,
|
|
paddingHorizontal: theme.spacing.lg,
|
|
borderRadius: theme.borderRadius.medium,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
...theme.shadows.primary,
|
|
},
|
|
|
|
// Cancel button
|
|
cancelButton: {
|
|
backgroundColor: theme.colors.backgroundAlt,
|
|
borderWidth: 1,
|
|
borderColor: theme.colors.border,
|
|
},
|
|
|
|
// Cancel button text
|
|
cancelButtonText: {
|
|
fontSize: theme.typography.fontSize.bodyLarge,
|
|
fontFamily: theme.typography.fontFamily.medium,
|
|
color: theme.colors.textSecondary,
|
|
},
|
|
|
|
// Confirm button
|
|
confirmButton: {
|
|
backgroundColor: theme.colors.primary,
|
|
},
|
|
|
|
// Confirm button with cancel
|
|
confirmButtonWithCancel: {
|
|
flex: 1,
|
|
},
|
|
|
|
// Confirm button text
|
|
confirmButtonText: {
|
|
fontSize: theme.typography.fontSize.bodyLarge,
|
|
fontFamily: theme.typography.fontFamily.bold,
|
|
color: theme.colors.background,
|
|
},
|
|
});
|
|
|
|
/*
|
|
* End of File: CustomModal.tsx
|
|
* Design & Developed by Tech4Biz Solutions
|
|
* Copyright (c) Spurrin Innovations. All rights reserved.
|
|
*/
|