Intial commit

This commit is contained in:
Mochammad Adhi Buchori
2025-04-18 17:33:44 +07:00
parent a17842fc9e
commit ef2bc641ac
175 changed files with 2904 additions and 137 deletions

View File

@ -0,0 +1,54 @@
import React, {forwardRef} from 'react';
import {TextInput, StyleSheet, View} from 'react-native';
import Colors from '../../assets/styles/Colors';
import FontFamily from '../../assets/styles/FontFamily';
const OTPTextInput = forwardRef((props: any, ref: any) => {
const {value, onChangeText, onKeyPress} = props;
const handleChange = (text: string) => {
if (/^\d?$/.test(text)) {
onChangeText(text);
}
};
return (
<View style={styles.box}>
<TextInput
ref={ref}
value={value}
onChangeText={handleChange}
onKeyPress={onKeyPress}
style={styles.input}
keyboardType="number-pad"
maxLength={1}
selectionColor={Colors.primary30.color}
/>
</View>
);
});
const styles = StyleSheet.create({
box: {
width: 48,
height: 48,
borderRadius: 12,
borderWidth: 1,
borderColor: Colors.primary60.color,
justifyContent: 'center',
alignItems: 'center',
},
input: {
fontSize: 16,
color: 'black',
textAlign: 'center',
padding: 0,
margin: 0,
width: '100%',
height: '100%',
...FontFamily.notoSansBold,
includeFontPadding: false,
},
});
export default OTPTextInput;

View File

@ -0,0 +1,217 @@
import * as React from 'react';
import {Platform, Pressable, StyleSheet, Text, View} from 'react-native';
import {TextInput} from 'react-native-paper';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Colors from '../../assets/styles/Colors';
import FontFamily from '../../assets/styles/FontFamily';
import DateTimePicker from '@react-native-community/datetimepicker';
import {useState} from 'react';
import {Dropdown} from 'react-native-element-dropdown';
interface TextInputComponentProps {
title?: string;
placeholder?: string;
isPassword?: boolean;
isRequired?: boolean;
isDate?: boolean;
isDropdown?: boolean;
}
const genderData = [
{label: 'Laki-Laki', value: '1'},
{label: 'Perempuan', value: '2'},
];
const TextInputComponent: React.FC<TextInputComponentProps> = ({
title,
placeholder,
isPassword = false,
isRequired = false,
isDate = false,
isDropdown = false,
}) => {
const [secureText, setSecureText] = useState(isPassword);
const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);
const [formattedDate, setFormattedDate] = useState<string>('');
const [showPicker, setShowPicker] = useState(false);
const [genderValue, setGenderValue] = useState(null);
const renderGenderItem = (item: any) => {
return (
<View style={styles.genderItem}>
<Text style={styles.genderTextItem}>{item.label}</Text>
</View>
);
};
const handleDateChange = (event: any, date?: Date) => {
if (event.type === 'dismissed') {
setShowPicker(false);
return;
}
if (date) {
setShowPicker(Platform.OS === 'ios');
setSelectedDate(date);
const formatted = `${String(date.getDate()).padStart(2, '0')}/${String(
date.getMonth() + 1,
).padStart(2, '0')}/${date.getFullYear()}`;
setFormattedDate(formatted);
}
};
const renderInput = () => {
if (isDropdown) {
return (
<View>
{title && (
<View style={styles.titleContainer}>
<Text style={styles.title}>{title}</Text>
{isRequired && <Text style={styles.required}>*</Text>}
</View>
)}
<Dropdown
style={styles.dropdown}
placeholderStyle={styles.placeholderDropdownStyle}
selectedTextStyle={styles.selectedTextStyle}
iconStyle={styles.iconStyle}
data={genderData}
maxHeight={300}
labelField="label"
valueField="value"
placeholder="Jenis Kelamin"
value={genderValue}
onChange={item => {
setGenderValue(item.value);
}}
renderRightIcon={() => <Icon name="arrow-drop-down" size={20} />}
renderItem={renderGenderItem}
/>
</View>
);
}
if (isDate) {
return (
<View>
<View style={styles.titleContainer}>
{title && <Text style={styles.title}>{title}</Text>}
{isRequired && <Text style={styles.required}>*</Text>}
</View>
<Pressable onPress={() => setShowPicker(true)}>
<TextInput
mode="outlined"
placeholder={placeholder}
style={[styles.containerBackground, styles.placeholderText]}
theme={{roundness: 12}}
placeholderTextColor={Colors.primary60.color}
editable={false}
value={formattedDate}
right={<TextInput.Icon icon="calendar" />}
multiline={false}
/>
</Pressable>
{showPicker && (
<DateTimePicker
value={selectedDate || new Date()}
mode="date"
display="calendar"
onChange={handleDateChange}
/>
)}
</View>
);
}
return (
<View>
{title && (
<View style={styles.titleContainer}>
<Text style={styles.title}>{title}</Text>
{isRequired && <Text style={styles.required}>*</Text>}
</View>
)}
<TextInput
mode="outlined"
placeholder={placeholder}
style={[styles.containerBackground, styles.placeholderText]}
theme={{roundness: 12}}
placeholderTextColor={Colors.primary60.color}
activeOutlineColor={Colors.primary10.color}
secureTextEntry={secureText}
right={
isPassword ? (
<TextInput.Icon
icon={secureText ? 'eye-off' : 'eye'}
onPress={() => setSecureText(prev => !prev)}
forceTextInputFocus={false}
/>
) : null
}
multiline={false}
/>
</View>
);
};
return <View>{renderInput()}</View>;
};
const styles = StyleSheet.create({
containerBackground: {
backgroundColor: Colors.neutral100.color,
marginTop: 8,
},
title: {
...FontFamily.notoSansBold,
fontSize: 12,
},
titleContainer: {
flexDirection: 'row',
gap: 5,
},
required: {
...FontFamily.notoSansBold,
fontSize: 12,
color: Colors.indicatorRed.color,
},
placeholderText: {
fontSize: 13,
...FontFamily.notoSansRegular,
},
genderItem: {
padding: 16,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
genderTextItem: {
flex: 1,
fontSize: 13,
},
dropdown: {
marginTop: 8,
backgroundColor: 'white',
borderRadius: 12,
paddingVertical: 16,
paddingStart: 16,
paddingEnd: 8,
borderWidth: 1,
borderColor: Colors.primary40.color,
},
placeholderDropdownStyle: {
fontSize: 13,
...FontFamily.notoSansRegular,
color: Colors.primary60.color,
},
selectedTextStyle: {
fontSize: 13,
...FontFamily.notoSansRegular,
},
iconStyle: {
width: 20,
height: 20,
},
});
export default TextInputComponent;