Created
October 15, 2019 15:43
-
-
Save gidox/e01cfe8b302acdf05e4b4321c43902ec 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 React from 'react'; | |
import PropTypes from 'prop-types'; | |
import { Animated, View, StyleSheet, Dimensions, TouchableOpacity } from 'react-native'; | |
import moment from 'moment'; | |
import { Thumbnail } from 'native-base'; | |
import Text from '../theme/Text'; | |
import CountDownTimer from './CountDownReact'; | |
import i18n from '../translations/i18n'; | |
const locale = i18n.currentLocale().split('-')[0]; | |
const name = locale === 'es' ? 'service_name_spanish' : 'service_name'; | |
const DEVICE_HEIGHT = Dimensions.get('window').height; | |
const CARD_HEIGHT = 400; | |
const CARD_VISIBLE_HEIGHT = 50; | |
const CARD_VISIBLE_HEIGHT_COLLAPSED = 30; | |
const CARD_VISIBLE_DELTA = CARD_VISIBLE_HEIGHT - CARD_VISIBLE_HEIGHT_COLLAPSED; | |
const TOP_OFFSET = 0; | |
class AppointmentCard extends React.Component { | |
constructor(props) { | |
super(props); | |
this.offsetY = 0; | |
this.state = { | |
scrollY: new Animated.Value(0), | |
CARD_AMOUNT: props.data.length, | |
STACK_HEIGHT: CARD_VISIBLE_DELTA * props.data.length - CARD_VISIBLE_DELTA, | |
SCROLL_HEIGHT: DEVICE_HEIGHT + CARD_VISIBLE_DELTA * props.data.length - CARD_VISIBLE_DELTA, | |
}; | |
} | |
onPress = e => { | |
console.log("ASdasd", e); | |
const offsetY = this.offsetY | |
const pressY = e.nativeEvent.pageY | |
const currentStackHeight = this.state.STACK_HEIGHT - offsetY + CARD_HEIGHT + (this.state.CARD_AMOUNT - 1) * CARD_VISIBLE_HEIGHT_COLLAPSED | |
let y = TOP_OFFSET | |
if (pressY < y || pressY > currentStackHeight + TOP_OFFSET) { | |
return false | |
} | |
const collapsedCount = Math.floor(offsetY / CARD_VISIBLE_DELTA) | |
const expanedCount = this.state.CARD_AMOUNT - collapsedCount - 2 | |
for (let i = 0; i <= this.state.CARD_AMOUNT; i++) { | |
// if a collapsed card | |
if (i < collapsedCount) y += CARD_VISIBLE_HEIGHT_COLLAPSED | |
// if the last card | |
else if (i === this.state.CARD_AMOUNT - 1) y += CARD_HEIGHT | |
// if a collapsing card | |
else if (i === collapsedCount) y += currentStackHeight - CARD_HEIGHT - collapsedCount * CARD_VISIBLE_HEIGHT_COLLAPSED - expanedCount * CARD_VISIBLE_HEIGHT | |
// if an expanded card | |
else y += CARD_VISIBLE_HEIGHT | |
if (pressY < y) { | |
console.log(this.props.data[i]); | |
return this.setState({ pressed: i }) | |
} | |
} | |
} | |
render() { | |
const { data } = this.props; | |
let { scrollY } = this.state; | |
let cardTransform = i => { | |
if (!i) return { transform: [{ translateY: TOP_OFFSET }] } | |
const translateY = scrollY.interpolate({ | |
inputRange: [ | |
-100, | |
0, | |
CARD_VISIBLE_DELTA * i, | |
this.state.STACK_HEIGHT, | |
this.state.STACK_HEIGHT + 100 | |
], | |
outputRange: [ | |
TOP_OFFSET + i * 100, | |
TOP_OFFSET, | |
TOP_OFFSET - CARD_VISIBLE_DELTA * i, | |
TOP_OFFSET - CARD_VISIBLE_DELTA * i, | |
TOP_OFFSET - CARD_VISIBLE_DELTA * i - i * 5 | |
], | |
}) | |
return { transform: [{ translateY }] } | |
} | |
let cards = []; | |
for (let i = 0; i < this.state.CARD_AMOUNT; i++) { | |
cards.push( | |
<Animated.View | |
key={`card-${i}`} | |
style={[styles.card, cardTransform(i), { | |
top: i * CARD_VISIBLE_HEIGHT, | |
backgroundColor: data[i].backgroundColor, | |
}]} | |
> | |
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 20 }}> | |
<Text style={{ color: data[i].color }} semiBold size={14}> | |
{data[i][name]} | |
</Text> | |
<Text style={{ color: data[i].color }} size={12}> | |
{moment(data[i].dayDate).format('DD / MMM / YY | hh:mm a')} | |
</Text> | |
</View> | |
<View style={{ flexDirection: 'row', justifyContent: 'center' }}> | |
<Thumbnail large source={{ uri: data[i].profile_image }} /> | |
</View> | |
<View style={{ flexDirection: 'row', justifyContent: 'center', marginVertical: 30 }}> | |
<Text semiBold size={16} style={{ color: data[i].color, textAlign: 'center' }}> | |
{data[i].stylist_name} | |
</Text> | |
</View> | |
<View style={{ flexDirection: 'row', justifyContent: 'center', marginBottom: 30 }}> | |
<Text size={12} style={{ color: data[i].lightColor, textAlign: 'center' }}> | |
{data[i].address} | |
</Text> | |
</View> | |
{data[i].status === 0 && ( | |
<View> | |
<View style={{ flexDirection: 'row', justifyContent: 'center', marginBottom: 20 }}> | |
<View style={{ flex: 0.3 }}> | |
<CountDownTimer | |
//date={new Date(parseInt(this.props.appointment.endDate))} | |
date={data.endDate} | |
// onEnd={() => { | |
// this.props.endTimer(this.props.appointment); | |
// }} | |
hours="" | |
mins="" | |
segs=" : " | |
containerStyle={{ | |
flexDirection: 'row', | |
justifyContent: 'center', | |
borderWidth: 1, | |
borderColor: data[i].color, | |
borderRadius: 30, | |
paddingHorizontal: 0, | |
paddingTop: 0, | |
paddingBottom: 5, | |
}} | |
secondColonStyle={{ color: data[i].color, paddingTop: 10 }} | |
firstColonStyle={{ backgroundColor: 'transparent' }} | |
minsStyle={{ color: data[i].color, paddingTop: 10 }} | |
secsStyle={{ color: data[i].color, paddingTop: 10 }} | |
/> | |
</View> | |
</View> | |
<View style={{ flexDirection: 'row' }}> | |
<View style={{ flex: 3, marginHorizontal: 3, flexDirection: 'row', }}> | |
<TouchableOpacity | |
style={{ | |
flex: 1, | |
borderWidth: 1, | |
borderColor: data[i].color, | |
borderRadius: 5, | |
}} | |
> | |
<Text size={14} style={{ textAlign: 'center', color: data[i].color }}>+ 5 min</Text> | |
</TouchableOpacity> | |
</View> | |
<View style={{ flex: 3, marginHorizontal: 3, flexDirection: 'row', }}> | |
<TouchableOpacity | |
onPress={() => alert("asddd")} | |
style={{ | |
elevation: 10, | |
zIndex: 9999, | |
flex: 1, | |
borderWidth: 1, | |
borderColor: data[i].color, | |
borderRadius: 5, | |
}} | |
> | |
<Text size={14} style={{ textAlign: 'center', color: data[i].color }}>+ 5 min</Text> | |
</TouchableOpacity> | |
</View> | |
<View style={{ flex: 3, marginHorizontal: 3, flexDirection: 'row', }}> | |
<TouchableOpacity | |
style={{ | |
flex: 1, | |
borderWidth: 1, | |
borderColor: data[i].color, | |
borderRadius: 5, | |
}} | |
> | |
<Text size={14} style={{ textAlign: 'center', color: data[i].color }}>+ 5 min</Text> | |
</TouchableOpacity> | |
</View> | |
</View> | |
</View> | |
)} | |
</Animated.View> | |
) | |
} | |
return ( | |
<View style={{ flex: 1, backgroundColor: '#F5F5F5' }}> | |
<View style={StyleSheet.absoluteFill}>{cards}</View> | |
<Animated.ScrollView | |
onScroll={Animated.event( | |
[{ nativeEvent: { contentOffset: { y: scrollY } } }], | |
{ | |
useNativeDriver: true, | |
listener: e => this.offsetY = e.nativeEvent.contentOffset.y | |
}, | |
)} | |
scrollEventThrottle={24} | |
showsVerticalScrollIndicator={false} | |
style={[StyleSheet.absoluteFill]} | |
> | |
<TouchableOpacity onPress={this.onPress} style={[{ height: this.state.SCROLL_HEIGHT, zIndex: 2 }]}></TouchableOpacity> | |
</Animated.ScrollView> | |
</View> | |
) | |
} | |
} | |
const styles = StyleSheet.create({ | |
card: { | |
position: 'absolute', | |
borderColor: 'black', | |
backgroundColor: 'white', | |
paddingHorizontal: 15, | |
paddingVertical: 15, | |
left: 20, | |
right: 20, | |
height: CARD_HEIGHT, | |
borderRadius: 25, | |
}, | |
}); | |
AppointmentCard.propTypes = { | |
data: PropTypes.array.isRequired, | |
}; | |
export default AppointmentCard; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment