# Required Components ## TextInput Component ```typescript // src/components/common/TextInput/TextInput.tsx import React, {useState} from 'react'; import { TextInput as RNTextInput, View, Text, StyleSheet, TextInputProps, } from 'react-native'; interface CustomTextInputProps extends TextInputProps { label?: string; error?: string; required?: boolean; } export const TextInput: React.FC = ({ label, error, required, style, ...props }) => { const [isFocused, setIsFocused] = useState(false); return ( {label && ( {label} {required && *} )} setIsFocused(true)} onBlur={() => setIsFocused(false)} {...props} /> {error && {error}} ); }; const styles = StyleSheet.create({ container: { marginBottom: 16, }, label: { fontSize: 14, fontWeight: '500', marginBottom: 8, color: '#333', }, required: { color: '#FF3B30', }, input: { borderWidth: 1, borderColor: '#E5E5E7', borderRadius: 8, paddingHorizontal: 16, paddingVertical: 12, fontSize: 16, backgroundColor: '#FFFFFF', }, focused: { borderColor: '#007AFF', }, error: { borderColor: '#FF3B30', }, errorText: { fontSize: 12, color: '#FF3B30', marginTop: 4, }, }); ``` ## Header Component (CHeader) ```typescript // src/components/common/CHeader/CHeader.tsx import React from 'react'; import {View, Text, TouchableOpacity, StyleSheet, StatusBar} from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; interface CHeaderProps { title: string; showBackButton?: boolean; onBackPress?: () => void; rightComponent?: React.ReactNode; backgroundColor?: string; } export const CHeader: React.FC = ({ title, showBackButton = true, onBackPress, rightComponent, backgroundColor = '#FFFFFF', }) => { const insets = useSafeAreaInsets(); return ( {showBackButton && ( )} {title} {rightComponent} ); }; const styles = StyleSheet.create({ container: { borderBottomWidth: 1, borderBottomColor: '#E5E5E7', }, header: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, }, backButton: { padding: 8, }, backText: { fontSize: 24, color: '#007AFF', }, title: { flex: 1, fontSize: 18, fontWeight: '600', textAlign: 'center', color: '#000', }, rightContainer: { minWidth: 40, alignItems: 'flex-end', }, }); ``` ## AlertModal Component ```typescript // src/components/common/AlertModal/AlertModal.tsx import React from 'react'; import { Modal, View, Text, TouchableOpacity, StyleSheet, Dimensions, } from 'react-native'; interface AlertModalProps { visible: boolean; title: string; message: string; onConfirm?: () => void; onCancel?: () => void; confirmText?: string; cancelText?: string; type?: 'info' | 'warning' | 'error' | 'success'; } export const AlertModal: React.FC = ({ visible, title, message, onConfirm, onCancel, confirmText = 'OK', cancelText = 'Cancel', type = 'info', }) => { return ( {title} {message} {onCancel && ( {cancelText} )} {onConfirm && ( {confirmText} )} ); }; const styles = StyleSheet.create({ overlay: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.5)', justifyContent: 'center', alignItems: 'center', }, container: { backgroundColor: '#FFFFFF', borderRadius: 12, padding: 20, width: Dimensions.get('window').width - 40, maxWidth: 400, }, title: { fontSize: 18, fontWeight: '600', marginBottom: 12, textAlign: 'center', }, infoTitle: { color: '#007AFF', }, warningTitle: { color: '#FF9500', }, errorTitle: { color: '#FF3B30', }, successTitle: { color: '#34C759', }, message: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 20, lineHeight: 22, }, buttonContainer: { flexDirection: 'row', justifyContent: 'space-between', }, cancelButton: { flex: 1, paddingVertical: 12, marginRight: 8, borderRadius: 8, borderWidth: 1, borderColor: '#E5E5E7', }, confirmButton: { flex: 1, paddingVertical: 12, marginLeft: 8, borderRadius: 8, }, infoButton: { backgroundColor: '#007AFF', }, warningButton: { backgroundColor: '#FF9500', }, errorButton: { backgroundColor: '#FF3B30', }, successButton: { backgroundColor: '#34C759', }, cancelText: { textAlign: 'center', fontSize: 16, color: '#666', }, confirmText: { textAlign: 'center', fontSize: 16, color: '#FFFFFF', fontWeight: '600', }, }); ``` ## Dropdown Component ```typescript // src/components/common/Dropdown/Dropdown.tsx import React, {useState} from 'react'; import { View, Text, TouchableOpacity, FlatList, StyleSheet, Modal, } from 'react-native'; interface DropdownItem { label: string; value: string; } interface DropdownProps { items: DropdownItem[]; selectedValue?: string; onSelect: (item: DropdownItem) => void; placeholder?: string; label?: string; } export const Dropdown: React.FC = ({ items, selectedValue, onSelect, placeholder = 'Select an option', label, }) => { const [isVisible, setIsVisible] = useState(false); const selectedItem = items.find(item => item.value === selectedValue); return ( {label && {label}} setIsVisible(true)}> {selectedItem ? selectedItem.label : placeholder} setIsVisible(false)}> item.value} renderItem={({item}) => ( { onSelect(item); setIsVisible(false); }}> {item.label} )} /> ); }; const styles = StyleSheet.create({ container: { marginBottom: 16, }, label: { fontSize: 14, fontWeight: '500', marginBottom: 8, color: '#333', }, selector: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', borderWidth: 1, borderColor: '#E5E5E7', borderRadius: 8, paddingHorizontal: 16, paddingVertical: 12, backgroundColor: '#FFFFFF', }, selectorText: { fontSize: 16, color: '#333', }, placeholder: { color: '#999', }, arrow: { fontSize: 12, color: '#666', }, overlay: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.5)', justifyContent: 'center', alignItems: 'center', }, dropdown: { backgroundColor: '#FFFFFF', borderRadius: 8, maxHeight: 200, width: '80%', }, item: { paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#F0F0F0', }, itemText: { fontSize: 16, color: '#333', }, }); ``` ## RadioButton Component ```typescript // src/components/common/RadioButton/RadioButton.tsx import React from 'react'; import {View, Text, TouchableOpacity, StyleSheet} from 'react-native'; interface RadioOption { label: string; value: string; } interface RadioButtonProps { options: RadioOption[]; selectedValue?: string; onSelect: (value: string) => void; label?: string; } export const RadioButton: React.FC = ({ options, selectedValue, onSelect, label, }) => { return ( {label && {label}} {options.map(option => ( onSelect(option.value)}> {selectedValue === option.value && } {option.label} ))} ); }; const styles = StyleSheet.create({ container: { marginBottom: 16, }, label: { fontSize: 14, fontWeight: '500', marginBottom: 8, color: '#333', }, option: { flexDirection: 'row', alignItems: 'center', paddingVertical: 8, }, radio: { width: 20, height: 20, borderRadius: 10, borderWidth: 2, borderColor: '#007AFF', marginRight: 12, alignItems: 'center', justifyContent: 'center', }, selected: { width: 10, height: 10, borderRadius: 5, backgroundColor: '#007AFF', }, optionText: { fontSize: 16, color: '#333', }, }); ```