245 lines
7.0 KiB
JavaScript
245 lines
7.0 KiB
JavaScript
import React from 'react';
|
|
import { useState, useEffect, useRef } from 'react';
|
|
import {
|
|
Text,
|
|
View,
|
|
Dimensions,
|
|
TouchableOpacity,
|
|
ActivityIndicator,
|
|
SafeAreaView,
|
|
Platform,
|
|
Alert,
|
|
} from 'react-native';
|
|
import { connect } from 'react-redux';
|
|
import { Divider } from 'react-native-elements';
|
|
import Theme from '../../../../components/theme.style.js';
|
|
import Icon from '../../../../components/icons';
|
|
import DB from '../../../../components/storage';
|
|
import REQUEST from '../../../../components/api';
|
|
import { navigate } from '../../../../utils/navigation.js';
|
|
import BottomSheet, { BottomSheetScrollView } from '@gorhom/bottom-sheet';
|
|
import { ScrollView } from 'react-native-gesture-handler';
|
|
const styles = {
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: '#f8f9fa',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
panel: {
|
|
flex: 1,
|
|
backgroundColor: 'white',
|
|
// position: 'relative',
|
|
},
|
|
panelHeader: {
|
|
height: 60,
|
|
backgroundColor: Theme.colors.lightGray,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
};
|
|
|
|
const { height } = Dimensions.get('window');
|
|
|
|
const renderStations = (isGuest, data, onPress, onUpdateFavorite, props) => {
|
|
return data.map((station, index) => {
|
|
let stars = [1, 2, 3, 4, 5].map((star, i) => {
|
|
let name = station.stars >= star ? 'star' : 'staro';
|
|
let mgn = index > 0 ? 5 : 0;
|
|
return (
|
|
<Icon.AntDesign
|
|
name={name}
|
|
style={{ marginLeft: mgn }}
|
|
color={Theme.colors.yellow}
|
|
size={20}
|
|
key={i}
|
|
/>
|
|
);
|
|
});
|
|
return (
|
|
<TouchableOpacity
|
|
key={index}
|
|
activeOpacity={1}
|
|
onPress={() => onPress(station) || null}
|
|
style={{ backgroundColor: props.app_theme?.theme.dark ? Theme.colors.black : Theme.colors.white }}
|
|
>
|
|
<View style={{ flex: 0, padding: 15, flexDirection: 'row' }}>
|
|
<View style={{ flex: 5 }}>
|
|
<Text
|
|
style={{
|
|
fontSize: 16,
|
|
padding: 5,
|
|
color: props.app_theme?.theme.colors.text,
|
|
}}>
|
|
{station.name}
|
|
</Text>
|
|
<Text
|
|
style={{
|
|
color: props.app_theme?.theme.colors.text,
|
|
padding: 5,
|
|
width: '90%',
|
|
fontSize: 13,
|
|
}}>
|
|
{station.address}
|
|
</Text>
|
|
<View style={{ flexDirection: 'row', paddingTop: 7 }}>{stars}</View>
|
|
</View>
|
|
<TouchableOpacity
|
|
onPress={() => {
|
|
if (isGuest) {
|
|
guestError()
|
|
} else {
|
|
updateFavorite(station, index, onUpdateFavorite)
|
|
}
|
|
}}
|
|
style={{ flex: 0, justifyContent: 'center' }}>
|
|
<Icon.FontAwesome
|
|
name={station.favorite ? 'heart' : 'heart-o'}
|
|
size={28}
|
|
color={station.favorite ? 'red' : Theme.colors.darkGray}
|
|
/>
|
|
</TouchableOpacity>
|
|
</View>
|
|
<Divider
|
|
style={{ marginTop: 5, padding: 0, margin: 0, width: Theme.screen.w }}
|
|
/>
|
|
</TouchableOpacity>
|
|
);
|
|
});
|
|
};
|
|
|
|
const guestError = () => {
|
|
Alert.alert(
|
|
"Information",
|
|
`\nApply for a card to enjoy this feature`,
|
|
[
|
|
{
|
|
text: 'Cancel',
|
|
onPress: () => console.log('Cancel Pressed'),
|
|
style: { color: 'red' },
|
|
},
|
|
{
|
|
text: 'Enroll Card',
|
|
onPress: () => navigate('Login')
|
|
},
|
|
]
|
|
);
|
|
}
|
|
|
|
const updateFavorite = async (city, index, callback) => {
|
|
let session = await DB.session();
|
|
let urlTask = city.favorite
|
|
? 'station_delete_favorite'
|
|
: 'station_add_favorite'
|
|
let method = city.favorite ? 'delete' : 'get';
|
|
REQUEST(
|
|
urlTask,
|
|
method, { Authorization: session.token },
|
|
{
|
|
noID: true,
|
|
value: city.station_uuid,
|
|
}, {},
|
|
(res) => {
|
|
callback(index, city.favorite ? false : true);
|
|
},
|
|
(err) => {
|
|
Alert.alert("Information", `\n${err.message}`);
|
|
},
|
|
);
|
|
};
|
|
|
|
const renderStationPanel = (props) => {
|
|
const [snapPoints, setSnapPoints] = useState(['10%', '10%', '3%']);
|
|
const bottomSheetRef = useRef(null);
|
|
|
|
useEffect(() => {
|
|
init();
|
|
if (props.visible) {
|
|
bottomSheetRef.current?.expand();
|
|
} else {
|
|
bottomSheetRef.current?.collapse();
|
|
}
|
|
}, [props.visible, props.data]);
|
|
|
|
|
|
const init = () => {
|
|
if (props.data.length === 0) {
|
|
setSnapPoints(Platform.OS === 'android'
|
|
? ['14%', '14%', '3%']
|
|
: ['14%', '14%', '14%']);
|
|
} else if (props.data.length === 1) {
|
|
setSnapPoints(['22%', '22%', '22%']);
|
|
} else if (props.data.length > 1) {
|
|
setSnapPoints(['35%', '8%', '8%']);
|
|
} else {
|
|
setSnapPoints(props.snapPoints || ['14%', '14%', '14%']);
|
|
}
|
|
};
|
|
|
|
const getPanelTitle = () => {
|
|
if (props.error) return 'There was an error'
|
|
else if (props.loading && !props.isSearched && props.data.length == 0) return 'Getting Nearby Stations'
|
|
else if (!props.loading && props.isFavorite && props.data.length == 0) return 'No Favorite'
|
|
else if (props.isSearched) return 'Unioil Stations found: ' + (props.data.length > 0 ? props.data.length : 0)
|
|
else return 'Unioil Stations found: ' + (props.data.length > 0 ? props.data.length : 0)
|
|
}
|
|
|
|
const renderHeaders = () => {
|
|
return (
|
|
<View style={[styles.panelHeader, { backgroundColor: props.app_theme?.theme.dark ? Theme.colors.darkerGray : Theme.colors.lightGray }]}>
|
|
<View style={{ flexDirection: 'row', justifyContent: 'center', padding: 15 }}>
|
|
<Text style={{
|
|
flex: 4,
|
|
padding: 5,
|
|
color: props.app_theme?.theme.colors.text,
|
|
fontSize: 15,
|
|
}}>
|
|
{getPanelTitle()}
|
|
</Text>
|
|
<View style={{ flex: 0, justifyContent: 'center' }}>
|
|
{props.error ? (
|
|
<TouchableOpacity onPress={props.onError} activeOpacity={1}>
|
|
<Text style={{ color: '#fff' }}>Try Again</Text>
|
|
</TouchableOpacity>
|
|
) : props.loading ? (
|
|
<ActivityIndicator color={Theme.colors.primary} size={25} />
|
|
) : null}
|
|
</View>
|
|
</View>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const renderContents = () => {
|
|
return (
|
|
<ScrollView style={{flex: 1, minHeight:300 }}>
|
|
{props.data.length > 0 ? renderStations(props.isGuest, props.data, props.onClick, props.onUpdateFavorite, props) :
|
|
<View style={{ height: 250, width: '100%', backgroundColor: props.app_theme?.theme.dark ? props.app_theme?.theme.colors.border : Theme.colors.white }}></View>}
|
|
</ScrollView>
|
|
);
|
|
};
|
|
|
|
return (
|
|
// <View style={{ flex: 1 }}>
|
|
<BottomSheet
|
|
ref={bottomSheetRef}
|
|
snapPoints={snapPoints}
|
|
index={0}
|
|
|
|
>
|
|
{renderHeaders()}
|
|
{renderContents()}
|
|
|
|
</BottomSheet>
|
|
// </View>
|
|
);
|
|
}
|
|
|
|
const mapStateToProps = (state) => {
|
|
return {
|
|
app_theme: state.appThemeReducer.theme
|
|
}
|
|
}
|
|
|
|
export default connect(mapStateToProps, null)(renderStationPanel)
|