Skip to content

Instantly share code, notes, and snippets.

@hungtrn75
Last active November 9, 2023 09:15
Show Gist options
  • Save hungtrn75/372f650e48771d883cc62123f56bd540 to your computer and use it in GitHub Desktop.
Save hungtrn75/372f650e48771d883cc62123f56bd540 to your computer and use it in GitHub Desktop.
import {colors} from '@constants/theme';
import React, {useMemo} from 'react';
import {StyleSheet, TouchableOpacity, View} from 'react-native';
import {BaseButton} from 'react-native-gesture-handler';
import Animated from 'react-native-reanimated';
const Block = props => {
const {
animated,
children,
center,
disabled,
flex,
middle,
margin,
onPress,
padding,
wrap,
shadow,
style,
space,
row,
ripple,
...rest
} = props;
const getMargins = useMemo(() => {
if (typeof margin === 'number') {
return {
margin,
};
}
if (typeof margin === 'object') {
const marginSize = Object.keys(margin).length;
switch (marginSize) {
case 1:
return {
margin: margin[0],
};
case 2:
return {
marginVertical: margin[0],
marginHorizontal: margin[1],
};
case 3:
return {
marginTop: margin[0],
marginBottom: margin[2],
marginHorizontal: margin[1],
};
default:
return {
marginTop: margin[0],
marginRight: margin[1],
marginBottom: margin[2],
marginLeft: margin[3],
};
}
}
}, [margin]);
const getPaddings = useMemo(() => {
if (typeof padding === 'number') {
return {
padding,
};
}
if (typeof padding === 'object') {
const paddingSize = Object.keys(padding).length;
switch (paddingSize) {
case 1:
return {
padding: padding[0],
};
case 2:
return {
paddingVertical: padding[0],
paddingHorizontal: padding[1],
};
case 3:
return {
paddingTop: padding[0],
paddingBottom: padding[2],
paddingHorizontal: padding[1],
};
default:
return {
paddingTop: padding[0],
paddingRight: padding[1],
paddingBottom: padding[2],
paddingLeft: padding[3],
};
}
}
return {};
}, [padding]);
const blocStyles = [
styles.block,
center && styles.center,
flex && {flex},
middle && styles.middle,
getMargins && getMargins,
padding && getPaddings,
wrap && {flexWrap: 'wrap'},
shadow && {
backgroundColor: colors.WHITE,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.23,
shadowRadius: 2.62,
elevation: 4,
},
space && {justifyContent: `space-${space}`},
row && styles.row,
style && style,
];
if (animated) {
if (onPress)
return (
<TouchableOpacity onPress={onPress}>
<Animated.View {...rest} style={blocStyles}>
{children}
</Animated.View>
</TouchableOpacity>
);
return (
<Animated.View {...rest} style={blocStyles}>
{children}
</Animated.View>
);
}
if (onPress) {
if (ripple)
return (
<BaseButton {...rest} style={blocStyles} onPress={onPress}>
{children}
</BaseButton>
);
return (
<TouchableOpacity {...rest} style={blocStyles} onPress={onPress}>
{children}
</TouchableOpacity>
);
}
return (
<View {...rest} style={blocStyles}>
{children}
</View>
);
};
export default Block;
const styles = StyleSheet.create({
block: {
display: 'flex',
},
row: {
flexDirection: 'row',
},
center: {
alignItems: 'center',
},
middle: {
justifyContent: 'center',
},
});
import React, {useImperativeHandle, useMemo, useState} from 'react';
import {Platform, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import Block from '../../../components/Block';
import Picker from '@gregfrench/react-native-wheel-picker';
import Spacer from '../../../components/Spacer';
import {colors, shareStyles} from '../../../constants/theme';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import moment from 'moment';
const lengthYear = 4;
const currentYear = new Date().getFullYear();
const dates = new Array(31).fill(0).map((_, i) => {
const value = 1 + i;
return {value, label: `${value < 10 ? '0' + value : value}`};
});
const months = new Array(12).fill(0).map((_, i) => {
const value = 1 + i;
return {value, label: `${value < 10 ? '0' + value : value}`};
});
const years = new Array(lengthYear)
.fill(0)
.map((_, i) => {
const value = currentYear - i;
return {value, label: `${value}`};
})
.reverse();
const hours = new Array(24).fill(0).map((_, i) => {
const value = i;
return {value, label: `${value < 10 ? '0' + value : value}`};
});
const minutes = new Array(60).fill(0).map((_, i) => {
const value = i;
return {value, label: `${value < 10 ? '0' + value : value}`};
});
const DateWheelPicker = React.forwardRef(
({modal = false, startTime, endTime, onSelect, onClose}, ref) => {
const initValues = useMemo(() => {
const cDate = startTime.getDate();
const cMonth = startTime.getMonth();
const cYear = startTime.getFullYear();
const id = years.findIndex(el => el.value == cYear);
return [
cDate,
cMonth,
id,
startTime.getHours(),
startTime.getMinutes(),
endTime.getHours(),
endTime.getMinutes(),
];
}, []);
const [date, setDate] = useState(initValues[0]);
const [month, setMonth] = useState(initValues[1]);
const [year, setYear] = useState(initValues[2]);
const [startHour, setStartHour] = useState(initValues[3]);
const [startMinute, setStartMinute] = useState(initValues[4]);
const [endHour, setEndHour] = useState(initValues[5]);
const [endMinute, setEndMinute] = useState(initValues[6]);
useImperativeHandle(ref, () => ({
getValues,
}));
const dateString = () => {
return `${dates[date].label}/${months[month].label}/${years[year].label} ${hours[startHour].label}:${minutes[startMinute].label} -- ${hours[endHour].label}:${minutes[endMinute].label}`;
};
const getValues = () => {
const f = 'DD/MM/YYYY HH:mm';
const start = `${dates[date].label}/${months[month].label}/${years[year].label} ${hours[startHour].label}:${minutes[startMinute].label}`;
const end = `${dates[date].label}/${months[month].label}/${years[year].label} ${hours[endHour].label}:${minutes[endMinute].label}`;
return [moment(start, f).toDate(), moment(end, f).toDate()];
};
const onSubmit = () => {
if (!onSelect || typeof onSelect != 'function') return;
const values = getValues();
onSelect(values[0], values[1]);
};
return (
<Block>
{modal ? (
<Block row space="between" padding={[0, 15, 15]}>
<TouchableOpacity onPress={onClose}>
<View
style={{
backgroundColor: colors.GRAY2,
borderRadius: 20,
padding: 2.5,
}}>
<Icon name="close" color={colors.GRAY} size={18} />
</View>
</TouchableOpacity>
<Text style={styles.t3}>Chọn thời gian</Text>
<TouchableOpacity onPress={onSubmit}>
<Text style={styles.t2}>Chọn</Text>
</TouchableOpacity>
</Block>
) : null}
<Block row center middle>
<Text style={styles.t1}>Thời gian: </Text>
<Text style={[styles.t1, styles.t2]}>{dateString()}</Text>
</Block>
<Spacer height={10} />
<Block row>
<Block flex={1} row space="around">
<Text style={styles.t1}>Ngày</Text>
<Text style={styles.t1}>Tháng</Text>
<Text style={styles.t1}>Năm</Text>
</Block>
<Spacer width={15} />
<Block flex={1} row>
<Block center flex={1}>
<Text style={styles.t1}>Bắt đầu</Text>
</Block>
<Spacer width={24} />
<Block center flex={1}>
<Text style={styles.t1}>Kết thúc</Text>
</Block>
</Block>
</Block>
<Block row style={styles.b1}>
<Block flex={1} row>
<Picker
style={styles.picker}
lineColor="black" //to set top and bottom line color (Without gradients)
lineGradientColorFrom="#f2f2f2" //to set top and bottom starting gradient line color
lineGradientColorTo="#8c8c8c" //to set top and bottom ending gradient
selectedValue={date}
onValueChange={setDate}
itemStyle={styles.t1}>
{dates.map((item, i) => (
<Picker.Item label={item.label} value={i} key={i} />
))}
</Picker>
<Picker
style={styles.picker}
lineColor="gray" //to set top and bottom line color (Without gradients)
lineGradientColorFrom="#f2f2f2" //to set top and bottom starting gradient line color
lineGradientColorTo="#8c8c8c" //to set top and bottom ending gradient
selectedValue={month}
onValueChange={setMonth}
itemStyle={styles.t1}>
{months.map((item, i) => (
<Picker.Item label={item.label} value={i} key={i} />
))}
</Picker>
<Picker
style={styles.picker}
lineColor="gray" //to set top and bottom line color (Without gradients)
lineGradientColorFrom="#f2f2f2" //to set top and bottom starting gradient line color
lineGradientColorTo="#8c8c8c" //to set top and bottom ending gradient
selectedValue={year}
onValueChange={setYear}
itemStyle={styles.t1}>
{years.map((item, i) => (
<Picker.Item label={item.label} value={i} key={i} />
))}
</Picker>
</Block>
<Block flex={1} row>
<Picker
style={styles.picker}
lineColor="black" //to set top and bottom line color (Without gradients)
lineGradientColorFrom="#f2f2f2" //to set top and bottom starting gradient line color
lineGradientColorTo="#8c8c8c" //to set top and bottom ending gradient
selectedValue={startHour}
onValueChange={setStartHour}
itemStyle={styles.t1}>
{hours.map((item, i) => (
<Picker.Item label={item.label} value={i} key={i} />
))}
</Picker>
<Picker
style={styles.picker}
lineColor="black" //to set top and bottom line color (Without gradients)
lineGradientColorFrom="#f2f2f2" //to set top and bottom starting gradient line color
lineGradientColorTo="#8c8c8c" //to set top and bottom ending gradient
selectedValue={startMinute}
onValueChange={setStartMinute}
itemStyle={styles.t1}>
{minutes.map((item, i) => (
<Picker.Item label={item.label} value={i} key={i} />
))}
</Picker>
<View style={styles.v4}>
<Text>--</Text>
</View>
<Picker
style={styles.picker}
lineColor="black" //to set top and bottom line color (Without gradients)
lineGradientColorFrom="#f2f2f2" //to set top and bottom starting gradient line color
lineGradientColorTo="#8c8c8c" //to set top and bottom ending gradient
selectedValue={endHour}
onValueChange={setEndHour}
itemStyle={styles.t1}>
{[...hours].map((item, i) => (
<Picker.Item label={item.label} value={i} key={i} />
))}
</Picker>
<Picker
style={styles.picker}
lineColor="black" //to set top and bottom line color (Without gradients)
lineGradientColorFrom="#f2f2f2" //to set top and bottom starting gradient line color
lineGradientColorTo="#8c8c8c" //to set top and bottom ending gradient
selectedValue={endMinute}
onValueChange={setEndMinute}
itemStyle={styles.t1}>
{[...minutes].map((item, i) => (
<Picker.Item label={item.label} value={i} key={i} />
))}
</Picker>
</Block>
</Block>
</Block>
);
},
);
export default DateWheelPicker;
const styles = StyleSheet.create({
picker: {
flex: 1,
},
t1: {
fontSize: 15,
letterSpacing: 1,
color: 'black',
},
t2: {
color: colors.IOS_BTN,
},
v4: {
width: 24,
alignItems: 'center',
alignSelf: 'center',
justifyContent: 'center',
},
b1: {
height: Platform.select({
ios: 210,
android: 180,
}),
},
t2: {
fontSize: 16,
letterSpacing: 0.5,
color: colors.IOS_BTN,
...shareStyles.bold,
},
t3: {
fontSize: 16,
letterSpacing: 0.5,
},
});
const Spacer = ({height = 0, width = 0}) => <View style={{width,height}} />;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment