Last active
November 9, 2023 09:15
-
-
Save hungtrn75/372f650e48771d883cc62123f56bd540 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | |
}, | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | |
}, | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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