Commit 9a865792 by OuiAtichat

remake structrue app & migate navigate flux to react navigation

parent 04fc9d9b
import { AppLoading } from 'expo';
import * as Font from 'expo-font';
import React, { useState } from 'react';
import { Ionicons } from '@expo/vector-icons';
import AppRouter from './src/navigation/AppRouter';
import { mapping } from '@eva-design/eva';
import { ApplicationProvider } from 'react-native-ui-kitten';
import AppContainer from './AppNavigation';
import { myTheme } from './custom-theme';
import { Provider } from 'react-redux';
import rootStore from './reduxStore';
// import { default as customMapping } from './custom-mapping.json';
const loadResourcesAsync = async () => {
await Promise.all([
......@@ -11,16 +15,12 @@ const loadResourcesAsync = async () => {
Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
...Ionicons.font,
Avenir_Roman: require('./src/assets/fonts/Avenir-Roman.ttf'),
}),
]);
};
const handleLoadingError = (error: Error) => {
// In this case, you might want to report the error to your error reporting
// service, for example Sentry
const handleLoadingError = error => {
console.warn(error);
};
......@@ -40,7 +40,17 @@ const Application = props => {
/>
);
} else {
return <AppRouter />;
return (
<ApplicationProvider
mapping={mapping}
theme={myTheme}
// customMapping={customMapping}
>
<Provider store={rootStore}>
<AppContainer />
</Provider>
</ApplicationProvider>
);
}
};
......
import React from 'react';
import { Icon, View } from 'native-base';
import {
createStackNavigator,
createAppContainer,
createBottomTabNavigator,
createSwitchNavigator,
} from 'react-navigation';
import { BottomNavigation, BottomNavigationTab } from 'react-native-ui-kitten';
import SmartMeterPage from './screens/Private/SmartMeterPage/SmartMeterPage';
import SmartMeterDetailPage from './screens/Private/SmartMeterPage/SmartMeterDetailPage';
import HomeScreen from './screens/Private/HomeScreen';
import PageOne from './screens/Private/PageOne';
import PageTwo from './screens/Private/PageTwo';
import PageTree from './screens/Private/PageTree';
import PageFour from './screens/Private/PageFour';
import AuthLoadingScreen from './screens/Public/AuthLoadingScreen';
import OnboardingPage from './screens/Public/OnboardingPage';
import ForgotPassword from './screens/Public/ForgotPassword';
import LoginPage from './screens/Public/LoginPage';
import Register from './screens/Public/Register';
import SendEmail from './screens/Public/SendEmail';
const defaultNavigationOptions = {
headerStyle: {
backgroundColor: '#f44c4c',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
};
const HomeStack = createStackNavigator(
{
Home: SmartMeterPage,
SmartMeterDetail: SmartMeterDetailPage,
},
{
headerLayoutPreset: 'center',
navigationOptions: {
tabBarLabel: 'Home',
// tabBarVisible: false,
},
defaultNavigationOptions,
}
);
const FirstStack = createStackNavigator(
{
One: PageOne,
},
{
headerLayoutPreset: 'center',
navigationOptions: { tabBarLabel: 'First' },
defaultNavigationOptions,
}
);
const SecondStack = createStackNavigator(
{
Two: PageTwo,
},
{
headerLayoutPreset: 'center',
navigationOptions: { tabBarLabel: 'Second' },
defaultNavigationOptions,
}
);
const ThirdStack = createStackNavigator(
{
Tree: PageTree,
},
{
headerLayoutPreset: 'center',
navigationOptions: { tabBarLabel: 'Third' },
defaultNavigationOptions,
}
);
const FourthStack = createStackNavigator(
{
Four: PageFour,
},
{
headerLayoutPreset: 'center',
navigationOptions: { tabBarLabel: 'Fourth' },
defaultNavigationOptions,
}
);
const BottomNavigationTabs = props => {
const onTabSelect = selectedIndex => {
const { routeName } = props.navigation.state.routes[selectedIndex];
props.navigation.navigate(routeName);
};
const BottomTabs = [
{ label: 'Smart Meter', icon: { name: 'home' } },
{ label: 'Time', icon: { name: 'md-time' } },
{ label: 'History', icon: { type: 'SimpleLineIcons', name: 'chart' } },
{ label: 'Share', icon: { name: 'ios-share-alt' } },
{ label: 'Setting', icon: { type: 'SimpleLineIcons', name: 'settings' } },
];
return (
<View style={{ paddingHorizontal: 20 }}>
<BottomNavigation
{...props}
selectedIndex={props.navigation.state.index}
onSelect={onTabSelect}
indicatorStyle={{ borderRadius: 5 }}
>
{BottomTabs.map((tab, index) => (
<BottomNavigationTab
key={index + tab.label}
title={tab.label}
titleStyle={{ fontFamily: 'Avenir_Roman' }}
icon={props => {
const color = props.tintColor;
delete props.tintColor; // To remove warning
return (
<Icon
style={{
marginTop: 5,
textAlign: 'center',
fontSize: 20,
color,
}}
type={tab.icon.type || 'Ionicons'}
name={tab.icon.name}
/>
);
}}
/>
))}
</BottomNavigation>
</View>
);
};
const MainApp = createBottomTabNavigator(
{
Home: HomeStack,
One: FirstStack,
Two: SecondStack,
Tree: ThirdStack,
Four: FourthStack,
},
{
initialRouteName: 'Home',
tabBarComponent: props => <BottomNavigationTabs {...props} />,
tabBarOptions: {
keyboardHidesTabBar: true,
},
navigationOptions: { header: null },
}
);
const IntroStack = createStackNavigator(
{
Login: LoginPage,
Onboarding: OnboardingPage,
Forget: ForgotPassword,
Register: Register,
SendEmail: SendEmail,
},
{
initialRouteName: 'Login',
navigationOptions: { header: null },
}
);
const AppStack = createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
Intro: IntroStack,
Main: MainApp,
},
{
initialRouteName: 'Main',
}
);
const AppContainer = createAppContainer(AppStack);
export default AppContainer;
......@@ -7,9 +7,13 @@
"platforms": ["ios", "android"],
"version": "1.0.0",
"orientation": "portrait",
"icon": "./src/assets/images/icon.png",
"icon": "./assets/images/icon.png",
"splash": {
<<<<<<< HEAD
"image": "./src/assets/images/logo2.png",
=======
"image": "./assets/images/logo2.png",
>>>>>>> 9f7dd8c... remake structrue app & migate navigate flux to react navigation
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
......@@ -20,7 +24,11 @@
"ios": {
"supportsTablet": true
},
<<<<<<< HEAD
"primaryColor": "#ffffff",
=======
>>>>>>> 9f7dd8c... remake structrue app & migate navigate flux to react navigation
"description": ""
}
}
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
import React from 'react';
import { TextInput, Text, View } from 'react-native';
import { Icon } from 'native-base';
import { color, theme } from '../constants/Styles';
const InputField = ({
name, // field name - required
customStyle,
onChangeText, // event
value, // field value
disabled,
placeholder,
errors, // this array prop is automatically passed down to this component from <Form />
isPass,
}) => {
return (
<View>
<View>
<TextInput
value={value && value}
onChangeText={onChangeText ? val => onChangeText(val) : null}
placeholder={placeholder ? placeholder : ''}
placeholderTextColor={color.grey2}
disabled={disabled}
style={customStyle ? customStyle : {}}
secureTextEntry={isPass}
/>
{errors &&
errors.length > 0 &&
errors.map((item, index) =>
item.field === name && item.error ? (
<Icon key={`${index}`} name="close" style={theme.inputErrIcon} />
) : null
)}
</View>
{errors &&
errors.length > 0 &&
errors.map((item, index) =>
item.field === name && item.error ? (
<Text key={`${index}`} style={theme.inputErrText}>
{item.error}
</Text>
) : null
)}
</View>
);
};
export default InputField;
import React from 'react';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { HeaderButton } from 'react-navigation-header-buttons';
export default (IoniconsHeaderButton = props => (
<HeaderButton {...props} IconComponent={Ionicons} iconSize={30} color="#fff" />
));
import React, { Component } from 'react';
import { Header } from 'react-native-elements';
class HeaderComponent extends Component {
render() {
const { leftComponent, centerComponent, rightComponent, ...rest } = this.props;
return (
<Header
statusBarProps={{ barStyle: 'light-content' }}
backgroundColor="#f44c4c"
leftComponent={leftComponent}
centerComponent={centerComponent}
rightComponent={rightComponent}
{...rest}
/>
);
}
}
export default HeaderComponent;
import React, { Component } from 'react';
import { Container, Icon, Text } from 'native-base';
import HeaderComponent from './HeaderComponent';
import FooterCompenent from '../../screens/Private/PrivateContent';
import { Actions } from 'react-native-router-flux';
const LeftComponent = () => <Icon name="menu" style={{ color: 'white', fontSize: 24 }} />;
const CenterComponent = () => <Text>Untitled</Text>;
const RightComponent = () => <Icon name="notifications" style={{ color: 'white', fontSize: 24 }} />;
class LayoutComponent extends Component {
render() {
const { children } = this.props;
return (
<Container>
<HeaderComponent
leftComponent={<LeftComponent />}
centerComponent={<CenterComponent />}
rightComponent={<RightComponent />}
/>
</Container>
);
}
}
export default LayoutComponent;
import React from 'react';
import { Card, View, Row, Icon, Text } from 'native-base';
import { Image, StyleSheet, TouchableOpacity } from 'react-native';
import { color } from '../constants/Styles';
import { withNavigation } from 'react-navigation';
const MeterCard = props => {
return (
<TouchableOpacity
onPress={() => props.navigation.navigate('SmartMeterDetail', { deviceName: props.deviceName })}
>
<Card style={[styles.cardContainer]}>
<View style={[styles.imgContainer]}>
{props.isOn ? (
<View style={[styles.onContainer, { backgroundColor: 'rgba(65, 204, 0, 0.59)' }]}>
<Text style={[styles.onText]}>ON</Text>
</View>
) : (
<View style={[styles.onContainer, { backgroundColor: 'rgba(223, 0, 0, 0.59)' }]}>
<Text style={[styles.onText]}>OFF</Text>
</View>
)}
<Image
source={{
uri: props.img,
}}
style={[styles.imgStyle]}
/>
</View>
<View style={[styles.textContainer]}>
{props.isOnline ? <View style={[styles.online]} /> : null}
<Row style={[styles.alignCenter]}>
<Text style={[styles.nameStyle]}>{props.deviceName}</Text>
<Icon name="people" style={{ color: color.grey3 }} />
</Row>
<Text style={[styles.descStyle]} numberOfLines={2}>
{props.description}
</Text>
<Row style={{ marginTop: 10 }}>
<View style={[styles.iconCover]}>
<Icon name="notifications" style={[styles.iconStyle]} />
</View>
<View style={[styles.iconCover]}>
<Icon name="time" style={[styles.iconStyle]} />
</View>
</Row>
</View>
</Card>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
cardContainer: {
flexDirection: 'row',
borderRadius: 8,
height: 135,
marginBottom: 20,
},
imgContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
imgStyle: {
width: 50,
height: 80,
resizeMode: 'contain',
},
textContainer: {
flex: 2,
padding: 20,
},
alignCenter: {
alignItems: 'center',
},
nameStyle: {
fontSize: 18,
marginRight: 15,
},
descStyle: {
fontSize: 10,
color: color.grey3,
},
iconCover: {
backgroundColor: '#eeeeee',
width: 32,
height: 32,
borderRadius: 100,
alignItems: 'center',
justifyContent: 'center',
marginRight: 20,
},
iconStyle: {
fontSize: 15,
color: '#d8d8d8',
},
online: {
backgroundColor: '#7ed321',
width: 8,
height: 8,
position: 'absolute',
left: 0,
top: 30,
borderRadius: 10,
},
onContainer: {
width: 30,
height: 12,
borderRadius: 9.6,
position: 'absolute',
top: 7,
left: 5,
alignItems: 'center',
justifyContent: 'center',
},
onText: {
fontSize: 8.3,
color: 'white',
},
});
export default withNavigation(MeterCard);
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
export default class Button extends Component {
render({ onPress } = this.props) {
return (
<TouchableOpacity onPress={onPress}>
<View style={styles.button}>
{this.props.text ? (
<Text style={styles.text}>{this.props.text.toUpperCase()}</Text>
) : (
this.props.children
)}
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
button: {
width: 85,
height: 50,
borderRadius: 30,
backgroundColor: 'rgba(255,255,255,0.3)',
alignItems: 'center',
justifyContent: 'center',
},
text: {
color: '#FFFFFF',
fontWeight: 'bold',
// fontFamily: 'Avenir',
},
});
import React, { Component } from 'react';
import { StyleSheet, Text, Image } from 'react-native';
import Swiper from './Swiper';
import { LinearGradient } from 'expo-linear-gradient';
const pages = [
{
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
description:
'Coventry is a city with a thousand years of history that has plenty to offer the visiting tourist.',
},
{
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
description:
'Coventry2 is a city with a thousand years of history that has plenty to offer the visiting tourist.',
},
{
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
description:
'Coventry3 is a city with a thousand years of history that has plenty to offer the visiting tourist.',
},
{
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
description:
'Coventry4 is a city with a thousand years of history that has plenty to offer the visiting tourist.',
},
];
export default class Onboarding extends Component {
static navigationOptions = {
header: null,
};
render() {
return (
<Swiper>
{pages.map((page, index) => (
<LinearGradient
key={index}
colors={['#f66969', '#f44c4c']}
start={[0, 0]}
end={[1, 0]}
style={[styles.slide]}
>
<Image source={{ uri: page.img }} style={[styles.img]} />
<Text style={styles.text}>{page.description}</Text>
</LinearGradient>
))}
</Swiper>
);
}
}
const styles = StyleSheet.create({
slide: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
color: '#FFFFFF',
// fontFamily: 'Avenir',
fontSize: 18,
marginHorizontal: 30,
position: 'absolute',
top: '71%',
lineHeight: 24,
},
img: {
position: 'absolute',
top: '16%',
width: '50%',
height: '50%',
resizeMode: 'contain',
},
});
import React, { Component } from 'react';
import { Dimensions, Platform, ScrollView, View, StyleSheet } from 'react-native';
import ObButton from './Button';
import { withNavigation } from 'react-navigation';
import { Icon } from 'native-base';
import { Button, Text } from 'native-base';
const { width, height } = Dimensions.get('window');
class OnboardingScreens extends Component {
static defaultProps = {
horizontal: true,
pagingEnabled: true,
showsHorizontalScrollIndicator: false,
showsVerticalScrollIndicator: false,
bounces: false,
scrollsToTop: false,
removeClippedSubviews: true,
automaticallyAdjustContentInsets: false,
index: 0,
};
state = this.initState(this.props);
initState(props) {
const total = props.children ? props.children.length || 1 : 0,
index = total > 1 ? Math.min(props.index, total - 1) : 0,
offset = width * index;
const state = {
total,
index,
offset,
width,
height,
};
this.internals = {
isScrolling: false,
offset,
};
return state;
}
onScrollBegin = e => {
this.internals.isScrolling = true;
};
onScrollEnd = e => {
this.internals.isScrolling = false;
this.updateIndex(
e.nativeEvent.contentOffset ? e.nativeEvent.contentOffset.x : e.nativeEvent.position * this.state.width
);
};
onScrollEndDrag = e => {
const {
contentOffset: { x: newOffset },
} = e.nativeEvent,
{ children } = this.props,
{ index } = this.state,
{ offset } = this.internals;
if (offset === newOffset && (index === 0 || index === children.length - 1)) {
this.internals.isScrolling = false;
}
};
updateIndex = offset => {
const state = this.state,
diff = offset - this.internals.offset,
step = state.width;
let index = state.index;
if (!diff) {
return;
}
index = parseInt(index + Math.round(diff / step), 10);
this.internals.offset = offset;
this.setState({
index,
});
};
swipe = () => {
if (this.internals.isScrolling || this.state.total < 2) {
return;
}
const state = this.state,
diff = this.state.index + 1,
x = diff * state.width,
y = 0;
this.scrollView && this.scrollView.scrollTo({ x, y, animated: true });
this.internals.isScrolling = true;
if (Platform.OS === 'android') {
setImmediate(() => {
this.onScrollEnd({
nativeEvent: {
position: diff,
},
});
});
}
};
renderScrollView = pages => {
return (
<ScrollView
ref={component => {
this.scrollView = component;
}}
{...this.props}
contentContainerStyle={[styles.wrapper, this.props.style]}
onScrollBeginDrag={this.onScrollBegin}
onMomentumScrollEnd={this.onScrollEnd}
onScrollEndDrag={this.onScrollEndDrag}
>
{pages.map((page, i) => (
<View style={[styles.fullScreen, styles.slide]} key={i}>
{page}
</View>
))}
</ScrollView>
);
};
renderPagination = () => {
if (this.state.total <= 1) {
return null;
}
const ActiveDot = (
<View style={[styles.activeDotBorder]}>
<View style={[styles.activeDot]} />
</View>
),
Dot = <View style={[styles.dot]} />;
let dots = [];
for (let key = 0; key < this.state.total; key++) {
dots.push(
key === this.state.index ? React.cloneElement(ActiveDot, { key }) : React.cloneElement(Dot, { key })
);
}
return (
<View pointerEvents="none" style={[styles.pagination, styles.fullScreen]}>
{dots}
</View>
);
};
renderButton = () => {
const lastScreen = this.state.index === this.state.total - 1;
return (
<View pointerEvents="box-none" style={[styles.buttonWrapper, styles.fullScreen]}>
{lastScreen ? (
<ObButton
text="START"
onPress={() => {
// Actions.LoginPage()
this.props.navigation.navigate('Login');
}}
/>
) : (
<ObButton onPress={() => this.swipe()}>
<Icon style={{ color: 'white' }} name="arrow-forward" />
</ObButton>
)}
</View>
);
};
renderSkip = () => {
const lastScreen = this.state.index === this.state.total - 1;
return (
<View style={[styles.skipContainer]}>
{lastScreen ? null : (
<Button
transparent
onPress={() => {
// Actions.LoginPage()
this.props.navigation.navigate('Login');
}}
>
<Text style={[styles.skipText]}>SKIP</Text>
</Button>
)}
</View>
);
};
render() {
return (
<View style={[styles.container, styles.fullScreen]}>
{this.renderScrollView(this.props.children)}
{this.renderPagination()}
{this.renderButton()}
{this.renderSkip()}
</View>
);
}
}
export default withNavigation(OnboardingScreens);
const styles = StyleSheet.create({
fullScreen: {
width: width,
height: height,
},
container: {
backgroundColor: 'transparent',
position: 'relative',
},
slide: {
backgroundColor: 'transparent',
},
pagination: {
position: 'absolute',
bottom: '10%',
left: 30,
right: 0,
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'flex-end',
backgroundColor: 'transparent',
},
dot: {
width: 9,
height: 9,
backgroundColor: 'white',
borderRadius: 100,
marginHorizontal: 6,
opacity: 0.2,
marginBottom: 6,
},
activeDot: {
width: 11,
height: 11,
backgroundColor: 'white',
borderRadius: 100,
},
activeDotBorder: {
width: 21,
height: 21,
borderWidth: 2,
borderColor: 'rgba(255, 255, 255, 0.3)',
borderRadius: 100,
marginHorizontal: 6,
alignItems: 'center',
justifyContent: 'center',
},
buttonWrapper: {
backgroundColor: 'transparent',
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-end',
alignItems: 'flex-end',
position: 'absolute',
bottom: '8%',
right: 30,
},
skipContainer: {
position: 'absolute',
top: '8%',
right: 15,
},
skipText: {
color: '#fff',
fontSize: 12,
},
});
import React, { Component } from 'react';
import { Modal, Image, StyleSheet } from 'react-native';
import { View, Button, Text, H1 } from 'native-base';
export default class SuccessModal extends Component {
constructor(props) {
super(props);
this.state = {
modalVisible: false,
};
}
setModalVisible(visible) {
this.setState({ modalVisible: visible });
}
render() {
const styles = StyleSheet.create({
dimBg: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(0,0,0,0.5)',
},
modalContainer: {
backgroundColor: 'white',
width: '90%',
borderRadius: 10,
paddingHorizontal: 20,
paddingBottom: 40,
paddingTop: 60,
alignItems: 'center',
},
img: {
width: 90,
height: 90,
},
textContainer: {
alignItems: 'center',
marginTop: 20,
marginBottom: 40,
},
btnStyle: {
borderRadius: 30,
marginTop: 30,
},
});
return (
<View>
<Modal animationType="fade" transparent={true} visible={this.state.modalVisible}>
<View style={styles.dimBg}>
<View style={styles.modalContainer}>
<Image
style={styles.img}
source={{
uri: 'https://www.stickpng.com/assets/images/5aa78e387603fc558cffbf1d.png',
}}
/>
<View style={styles.textContainer}>
<H1>Success!</H1>
<Text style={{ color: '#cacaca', marginTop: 10 }}>Thansdfgksjdfo;gjs;dfjsdfgsdfg</Text>
<Text style={{ color: '#cacaca' }}>Thansdfgksjdfo;gjs;dfjsdfgsdfg</Text>
</View>
<Button
full
danger
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
console.log('hide modal!');
}}
style={{ borderRadius: 40 }}
>
<Text>GO TO HOME</Text>
</Button>
</View>
</View>
</Modal>
{this.props.isRegister ? (
<Button
danger
full
style={styles.btnStyle}
onPress={() => {
this.setModalVisible(true);
}}
>
<Text>CONTINUE</Text>
</Button>
) : (
<View />
)}
</View>
);
}
}
import { StyleSheet } from 'react-native';
export const color = {
grey1: '#808080',
grey2: '#cacaca',
grey3: '#4a4a4a',
primary: '#f44c4c',
red1: '#fc3d3d',
};
export const theme = StyleSheet.create({
startContainer: {
top: '15%',
paddingHorizontal: 50,
},
startTitle: {
textAlign: 'center',
color: color.grey3,
fontSize: 36,
},
startFormContainer: {
paddingRight: 10,
marginBottom: 10,
marginTop: 40,
},
roundedBtn: {
alignItems: 'center',
borderRadius: 24,
},
input: {
width: 300,
marginLeft: 5,
color: color.grey1,
marginTop: 30,
fontSize: 17,
},
inputErrIcon: {
color: color.red1,
position: 'absolute',
right: 5,
bottom: 5,
fontSize: 20,
},
inputErrText: {
color: color.red1,
fontSize: 10,
},
inputContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'flex-end',
borderBottomColor: '#cfd7db',
borderBottomWidth: 1,
paddingBottom: 5,
},
});
{
"components": {
"Button": {
"meta": {},
"appearances": {}
}
}
}
import { light as lightTheme } from '@eva-design/eva';
export const myTheme = {
...lightTheme,
'color-primary-100': '#FEE7DB',
'color-primary-200': '#FDCAB7',
'color-primary-300': '#FBA593',
'color-primary-400': '#F88378',
'color-primary-500': '#F44C4C', // main
'color-primary-600': '#D13744',
'color-primary-700': '#AF263E',
'color-primary-800': '#8D1836',
'color-primary-900': '#750E32',
'color-success-100': '#ECFDDC',
'color-success-200': '#D6FBB9',
'color-success-300': '#B6F394',
'color-success-400': '#97E776',
'color-success-500': '#6AD84B',
'color-success-600': '#4AB936',
'color-success-700': '#2E9B25',
'color-success-800': '#187D17',
'color-success-900': '#0E6714',
'color-info-100': '#CCF9FF',
'color-info-200': '#99EEFF',
'color-info-300': '#66DCFF',
'color-info-400': '#3FC7FF',
'color-info-500': '#00A5FF',
'color-info-600': '#0080DB',
'color-info-700': '#005FB7',
'color-info-800': '#004393',
'color-info-900': '#00307A',
'color-warning-100': '#FFFCCE',
'color-warning-200': '#FFF99D',
'color-warning-300': '#FFF56D',
'color-warning-400': '#FFF048',
'color-warning-500': '#FFEA0C',
'color-warning-600': '#DBC708',
'color-warning-700': '#B7A506',
'color-warning-800': '#938303',
'color-warning-900': '#7A6B02',
'color-danger-100': '#FEEAD5',
'color-danger-200': '#FED0AD',
'color-danger-300': '#FEB083',
'color-danger-400': '#FD9164',
'color-danger-500': '#FC5E32',
'color-danger-600': '#D83E24',
'color-danger-700': '#B52419',
'color-danger-800': '#920F10',
'color-danger-900': '#780911',
};
{
<<<<<<< HEAD
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
......@@ -44,4 +45,37 @@
"jest-expo": "^33.0.0"
},
"private": true
=======
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"@eva-design/eva": "^1.0.1",
"@react-native-community/async-storage": "^1.5.1",
"expo": "^33.0.0",
"expo-linear-gradient": "^5.0.1",
"native-base": "^2.12.1",
"react": "16.8.3",
"react-dom": "^16.8.6",
"react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
"react-native-ui-kitten": "^4.1.0",
"react-native-validate-form": "^1.1.3",
"react-native-vector-icons": "^6.6.0",
"react-native-web": "^0.11.4",
"react-navigation": "^3.11.1",
"react-navigation-header-buttons": "^3.0.1",
"react-redux": "^7.1.0",
"redux": "^4.0.4",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"babel-preset-expo": "^5.1.1"
},
"private": true
>>>>>>> 9f7dd8c... remake structrue app & migate navigate flux to react navigation
}
import { combineReducers } from 'redux';
// import routes from './routes';
import countReducer from './countReducer.js';
import countReducer from './countReducer';
export default combineReducers({
// routes,
......
import React, { Component } from 'react';
import { Text, View, TextInput } from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { HeaderButtons, HeaderButton, Item } from 'react-navigation-header-buttons';
const IoniconsHeaderButton = props => <HeaderButton {...props} IconComponent={Ionicons} iconSize={30} color="#fff" />;
export default class HomeScreen extends Component {
static navigationOptions = ({ navigation }) => ({
title: 'Home',
headerLeft: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => console.log('menu')} />
</HeaderButtons>
),
headerRight: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="search" iconName="ios-search" onPress={() => alert('search')} />
</HeaderButtons>
),
});
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'pink' }}>
<Text>Hello</Text>
</View>
);
}
}
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { HeaderButtons, HeaderButton, Item } from 'react-navigation-header-buttons';
const IoniconsHeaderButton = props => <HeaderButton {...props} IconComponent={Ionicons} iconSize={30} color="#fff" />;
export default class PageFour extends Component {
static navigationOptions = ({ navigation }) => ({
title: 'PageFour',
headerLeft: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => console.log('menu')} />
</HeaderButtons>
),
headerRight: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="search" iconName="ios-search" onPress={() => alert('search')} />
</HeaderButtons>
),
});
render() {
return (
<View>
<Text> PageFour </Text>
</View>
);
}
}
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { HeaderButtons, HeaderButton, Item } from 'react-navigation-header-buttons';
const IoniconsHeaderButton = props => <HeaderButton {...props} IconComponent={Ionicons} iconSize={30} color="#fff" />;
export default class PageOne extends Component {
static navigationOptions = ({ navigation }) => ({
title: 'PageOne',
headerLeft: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => console.log('menu')} />
</HeaderButtons>
),
headerRight: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="search" iconName="ios-search" onPress={() => alert('search')} />
</HeaderButtons>
),
});
render() {
return (
<View>
<Text> textInComponent </Text>
</View>
);
}
}
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { HeaderButtons, HeaderButton, Item } from 'react-navigation-header-buttons';
const IoniconsHeaderButton = props => <HeaderButton {...props} IconComponent={Ionicons} iconSize={30} color="#fff" />;
export default class PageTree extends Component {
static navigationOptions = ({ navigation }) => ({
title: 'PageTree',
headerLeft: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => console.log('menu')} />
</HeaderButtons>
),
headerRight: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="search" iconName="ios-search" onPress={() => alert('search')} />
</HeaderButtons>
),
});
render() {
return (
<View>
<Text> PageTree </Text>
</View>
);
}
}
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { HeaderButtons, HeaderButton, Item } from 'react-navigation-header-buttons';
const IoniconsHeaderButton = props => <HeaderButton {...props} IconComponent={Ionicons} iconSize={30} color="#fff" />;
export default class PageTwo extends Component {
static navigationOptions = ({ navigation }) => ({
title: 'PageTwo',
headerLeft: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => console.log('menu')} />
</HeaderButtons>
),
headerRight: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="search" iconName="ios-search" onPress={() => alert('search')} />
</HeaderButtons>
),
});
render() {
return (
<View>
<Text> PageTwo </Text>
</View>
);
}
}
import React, { Component } from 'react';
import { View, Text, Container, Content, Card, Footer, Row, Right, Left, Switch, Icon } from 'native-base';
import { color } from '../../../constants/Styles';
import { FlatList } from 'react-native';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import IoniconsHeaderButton from '../../../components/IoniconsHeaderButton';
// Main Breaker mock data
const MainBreaker = {
name: 'Main Breaker',
description: 'Lorem ipsum dolorsit amet,consectetur adipiscing elit. Cras sagitti.',
current: '10mA',
status: true,
Ecurrent: [
{ name: 'AC Volt', number: 250, unit: 'V' },
{ name: 'AC Current', number: 118, unit: 'A' },
{ name: 'Watt', number: 5890, unit: 'V' },
{ name: 'Leakage Current', number: 25, unit: 'mA' },
{ name: 'Watthour', number: 999999, unit: 'mA' },
],
MCB: [
{
title: 'MCB Link 1',
sub: [
{ title: 'Sub Breaker 1-1', description: 'Description', status: false },
{ title: 'Sub Breaker 1-2', description: 'Description', status: true },
{ title: 'Sub Breaker 1-3', description: 'Description', status: false },
{ title: 'Sub Breaker 1-4', description: 'Description', status: true },
{ title: 'Sub Breaker 1-5', description: 'Description', status: false },
{ title: 'Sub Breaker 1-6', description: 'Description', status: true },
{ title: 'Sub Breaker 1-7', description: 'Description', status: false },
{ title: 'Sub Breaker 1-8', description: 'Description', status: true },
],
},
{
title: 'MCB Link 2',
sub: [
{ title: 'Sub Breaker 2-1', description: 'Description', status: false },
{ title: 'Sub Breaker 2-2', description: 'Description', status: true },
{ title: 'Sub Breaker 2-3', description: 'Description', status: false },
{ title: 'Sub Breaker 2-4', description: 'Description', status: true },
{ title: 'Sub Breaker 2-5', description: 'Description', status: false },
{ title: 'Sub Breaker 2-6', description: 'Description', status: true },
{ title: 'Sub Breaker 2-7', description: 'Description', status: false },
{ title: 'Sub Breaker 2-8', description: 'Description', status: true },
],
},
{
title: 'MCB Link 3',
sub: [
{ title: 'Sub Breaker 3-1', description: 'Description', status: false },
{ title: 'Sub Breaker 3-2', description: 'Description', status: true },
{ title: 'Sub Breaker 3-3', description: 'Description', status: false },
{ title: 'Sub Breaker 3-4', description: 'Description', status: true },
{ title: 'Sub Breaker 3-5', description: 'Description', status: false },
{ title: 'Sub Breaker 3-6', description: 'Description', status: true },
{ title: 'Sub Breaker 3-7', description: 'Description', status: false },
{ title: 'Sub Breaker 3-8', description: 'Description', status: true },
],
},
{
title: 'MCB Link 4',
sub: [
{ title: 'Sub Breaker 4-1', description: 'Description', status: false },
{ title: 'Sub Breaker 4-2', description: 'Description', status: true },
{ title: 'Sub Breaker 4-3', description: 'Description', status: false },
{ title: 'Sub Breaker 4-4', description: 'Description', status: true },
{ title: 'Sub Breaker 4-5', description: 'Description', status: false },
{ title: 'Sub Breaker 4-6', description: 'Description', status: true },
{ title: 'Sub Breaker 4-7', description: 'Description', status: false },
{ title: 'Sub Breaker 4-8', description: 'Description', status: true },
],
},
],
};
export default class SmartMeterDetail extends Component {
static navigationOptions = ({ navigation }) => {
const deviceName = navigation.getParam('deviceName', '');
return {
title: deviceName,
headerLeft: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="back" iconName="ios-arrow-back" onPress={() => navigation.goBack()} />
</HeaderButtons>
),
headerRight: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="search" iconName="ios-search" onPress={() => alert('search')} />
</HeaderButtons>
),
};
};
state = {
mbOn: false,
sb: [
{
expand: true,
},
{
expand: false,
},
{
expand: false,
},
{
expand: false,
},
],
};
// full incomplete row
formatGridData(unformatData) {
let data = unformatData;
const numberOfFullRows = Math.floor(data.length / 3);
let numberOfElementsLastRow = data.length - numberOfFullRows * 3;
while (numberOfElementsLastRow !== 3 && numberOfElementsLastRow !== 0) {
data.push({ name: 'empty', number: null, unit: null });
numberOfElementsLastRow = numberOfElementsLastRow + 1;
}
return data;
}
render() {
// Electric Current card
const Meter = props => {
return (
<Card style={{ padding: 10, borderRadius: 6, flex: 1 }}>
<Text style={{ fontSize: 9, color: '#9b9b9b' }}>{props.name}</Text>
<Text style={{ fontSize: 20, color: color.grey3, textAlign: 'right', marginTop: 10 }}>
{props.number} <Text style={{ fontSize: 10 }}>{props.unit}</Text>
</Text>
</Card>
);
};
// MCB Link
const MCBLink = props => {
const index = props.index;
return (
<View>
<Row
style={{ padding: 10 }}
onPress={() =>
this.setState(() => {
return (sb[index].expand = !sb[index].expand);
})
}
>
<Left>
<Text style={{ fontSize: 14, color: '#4a4a4a' }}>{props.item.title}</Text>
</Left>
<Right>
<Icon
style={{ fontSize: 18, color: '#5B5B5B' }}
name={sb[index].expand ? 'arrow-up' : 'arrow-down'}
/>
</Right>
</Row>
{sb[index].expand
? props.item.sub.map((subItem, index) => (
<SubBreaker
key={index}
title={subItem.title}
description={subItem.description}
status={subItem.status}
/>
))
: null}
</View>
);
};
// Sub Breaker
const SubBreaker = props => {
return (
<View
style={{
padding: 20,
paddingVertical: 20,
backgroundColor: 'rgba(216,216,216,0.3)',
}}
>
<Row>
<Left>
<View>
<Text style={{ fontSize: 14, color: '#4a4a4a' }}>{props.title}</Text>
<Text style={{ fontSize: 12, color: '#9b9b9b' }}>{props.description}</Text>
</View>
</Left>
<Right>
<Switch
value={props.status}
trackColor={{ true: 'rgba(238,84,84,0.5)' }}
ios_backgroundColor={'#dfdfdf'}
thumbColor={'#ee5454'}
/>
</Right>
</Row>
</View>
);
};
const sb = this.state.sb;
return (
<Content style={{ padding: 20, backgroundColor: '#fbfbfb' }}>
{/* Main Breaker */}
<Card style={{ paddingHorizontal: 10, paddingVertical: 15, borderRadius: 10 }}>
<Row>
<Left>
<Text style={{ fontSize: 18, color: color.grey3 }}>
{MainBreaker.name}{' '}
<Text style={{ fontSize: 12, color: color.primary }}>({MainBreaker.current})</Text>
</Text>
</Left>
<Right>
<Switch
value={this.state.mbOn}
onValueChange={() =>
this.setState(() => {
return (this.state.mbOn = !this.state.mbOn);
})
}
trackColor={{ true: 'rgba(238,84,84,0.5)' }}
ios_backgroundColor={'#dfdfdf'}
thumbColor={'#ee5454'}
/>
</Right>
</Row>
<Text style={{ fontSize: 12, color: '#9b9b9b', marginTop: 10 }}>{MainBreaker.description}</Text>
</Card>
{/* Electric Current */}
<FlatList
data={this.formatGridData(MainBreaker.Ecurrent)}
renderItem={({ item }) => {
if (item.name == 'empty') {
return <Card transparent style={{ flex: 1, padding: 10 }} />;
} else {
return <Meter name={item.name} number={item.number} unit={item.unit} />;
}
}}
numColumns={3}
keyExtractor={(item, index) => index}
style={{ paddingTop: 20 }}
/>
{/* MCB Link */}
<Card style={{ borderRadius: 6, overflow: 'hidden', marginTop: 20 }}>
{MainBreaker.MCB.map((item, index) => (
<MCBLink item={item} key={index} index={index} />
))}
</Card>
<Footer style={{ backgroundColor: 'transparent' }} />
</Content>
);
}
}
import React, { Component } from 'react';
import { Container, Content, Text, Card, Header, Body, Button, Title, CardItem, View, Row, Icon } from 'native-base';
import { Image, FlatList } from 'react-native';
import { connect } from 'react-redux';
import { increment, decrement } from '../../../reduxStore/actions';
import { color } from '../../../constants/Styles';
import MeterCard from '../../../components/MeterCard';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import IoniconsHeaderButton from '../../../components/IoniconsHeaderButton';
const Meter = [
{
deviceName: 'Device 1',
description: 'Lorem ipsum dolorsit amet,consectetur adipiscing elit. Cras sagitti.',
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
isOnline: true,
isOn: true,
},
{
deviceName: 'Device 2',
description: 'Lorem ipsum dolorsit amet,consectetur adipiscing elit. Cras sagitti.',
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
isOnline: false,
isOn: true,
},
{
deviceName: 'Device 3',
description: 'Lorem ipsum dolorsit amet,consectetur adipiscing elit. Cras sagitti.',
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
isOnline: true,
isOn: false,
},
{
deviceName: 'Device 4',
description: 'Lorem ipsum dolorsit amet,consectetur adipiscing elit. Cras sagitti.',
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
isOnline: false,
isOn: false,
},
];
class SmartMeterPage extends Component {
static navigationOptions = ({ navigation }) => ({
title: 'Home',
headerLeft: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="menu" iconName="ios-menu" onPress={() => console.log('menu')} />
</HeaderButtons>
),
headerRight: (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item title="search" iconName="ios-search" onPress={() => alert('search')} />
</HeaderButtons>
),
});
render() {
return (
<Content padder>
<Text style={{ fontSize: 16, color: color.grey3, marginVertical: 20 }}>Smart meter</Text>
<FlatList
data={Meter}
keyExtractor={item => item.deviceName}
renderItem={({ item, index }) => (
<MeterCard
key={index + item.deviceName}
deviceName={item.deviceName}
description={item.description}
img={item.img}
isOnline={item.isOnline}
isOn={item.isOn}
index={index + 1}
/>
)}
/>
</Content>
);
}
}
const mapStateToProps = state => {
return {
count: state.count,
};
};
const mapDispatchToProps = { increment, decrement };
export default connect(
mapStateToProps,
mapDispatchToProps
)(SmartMeterPage);
import React, { Component } from 'react';
import { AsyncStorage, ActivityIndicator, View, StatusBar } from 'react-native';
// import AsyncStorage from '@react-native-community/async-storage'; //expo not yet support
export default class AuthLoadingScreen extends Component {
static navigationOptions = {
header: null,
};
swichingRoute = async () => {
const alreadyLaunched = await AsyncStorage.getItem('alreadyLaunched');
this.props.navigation.navigate(alreadyLaunched ? 'Login' : 'Onboarding');
};
componentDidMount() {
this.swichingRoute();
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#f44c4c" />
<StatusBar barStyle="default" />
</View>
);
}
}
import React, { Component } from 'react';
import { Container, Text, Content, Input, View, Form, Item, Button } from 'native-base';
import { theme, color } from '../../constants/Styles';
import { LinearGradient } from 'expo-linear-gradient';
export default class ForgotPassword extends Component {
static navigationOptions = {
header: null,
};
render() {
return (
<Container>
<Content style={theme.startContainer}>
<Text style={[theme.startTitle, { fontSize: 22, fontWeight: 'bold' }]}>Forgot Password</Text>
<View style={{ paddingHorizontal: 15, marginTop: 40 }}>
<Text style={{ color: color.grey1 }}>Please enter your email address.</Text>
<Text style={{ color: color.grey1 }}>
You will receive a link to create a new password via email.
</Text>
</View>
<Form style={theme.startFormContainer}>
<Item>
<Input
placeholder="Your E-mail"
placeholderTextColor={color.grey2}
style={{ color: color.grey1 }}
/>
</Item>
</Form>
<LinearGradient
colors={['#f97070', '#f44c4c']}
start={[0, 0]}
end={[1, 0]}
style={[theme.roundedBtn, { marginTop: 75 }]}
>
<Button
full
transparent
onPress={() => {
// Actions.SendEmail();
this.props.navigation.navigate('SendEmail')
}}
>
<Text style={{ color: 'white' }}>SEND</Text>
</Button>
</LinearGradient>
</Content>
</Container>
);
}
}
import React, { Component } from 'react';
import { Container, Text, Content, Input, Radio, Item, Left, Right, Button, Row, CheckBox } from 'native-base';
import { theme } from '../../constants/Styles';
import { LinearGradient } from 'expo-linear-gradient';
import { Form, Field } from 'react-native-validate-form';
import InputField from '../../components/InputField';
import { AsyncStorage } from 'react-native';
const required = value => (value ? undefined : 'This is a required field.');
const minChar = value => (value && !/^.{6,}$/i.test(value) ? 'At least 6 characters' : undefined);
export default class LoginPage extends Component {
static navigationOptions = {
header: null,
};
state = {
isCheck: false,
};
submitForm() {
let submitResults = this.registerForm.validate();
let errors = [];
submitResults.forEach(item => {
errors.push({ field: item.fieldName, error: item.error });
});
this.setState({ errors: errors });
}
async submitSuccess() {
console.log('Submit Success!');
await AsyncStorage.setItem('alreadyLaunched', 'true');
this.props.navigation.navigate('Home');
}
submitFailed() {
console.log('Submit Failed!');
}
render() {
return (
<Container>
<Content style={theme.startContainer}>
<Text style={theme.startTitle}>Login</Text>
<Form
ref={ref => (this.registerForm = ref)}
validate={true}
submit={this.submitSuccess.bind(this)}
failed={this.submitFailed.bind(this)}
errors={this.state.errors}
style={theme.startFormContainer}
>
{/* ---Username--- */}
<Field
required
component={InputField}
validations={[required]}
name="Username"
value={this.state.username}
onChangeText={val => this.setState({ username: val })}
customStyle={theme.input}
placeholder="Username"
/>
{/* ---password--- */}
<Field
required
component={InputField}
validations={[required, minChar]}
name="password"
value={this.state.password}
onChangeText={val => this.setState({ password: val })}
customStyle={theme.input}
placeholder="Password"
isPass={true}
/>
</Form>
<Row style={{ marginTop: 30 }}>
<Left>
<Row style={{ alignItems: 'center' }}>
<CheckBox
color={'#cacaca'}
checked={this.state.isCheck}
onPress={() =>
this.setState(() => {
return (this.state.isCheck = !this.state.isCheck);
})
}
/>
<Text style={{ color: '#cacaca', marginLeft: 12, fontSize: 13 }}>Remember me</Text>
</Row>
</Left>
<Right>
<Text
style={{ color: '#cacaca', fontSize: 13, marginRight: 10 }}
onPress={() => {
// Actions.ForgotPass();
this.props.navigation.navigate('Forget');
}}
>
Forgot password?
</Text>
</Right>
</Row>
<LinearGradient
colors={['#f97070', '#f44c4c']}
start={[0, 0]}
end={[1, 0]}
style={[theme.roundedBtn, { marginTop: 75 }]}
>
<Button full transparent onPress={this.submitForm.bind(this)}>
<Text style={{ color: 'white' }}>LOGIN</Text>
</Button>
</LinearGradient>
<Text style={{ color: '#4a4a4a', textAlign: 'center', marginTop: 20 }}>
Don't have an account?{' '}
<Text
style={{ color: '#f44c4c', fontWeight: 'bold' }}
onPress={() => {
// Actions.Register();
this.props.navigation.navigate('Register');
}}
>
Register
</Text>
</Text>
</Content>
</Container>
);
}
}
import React, { Component } from 'react';
import { StyleSheet, Text, Image } from 'react-native';
import Swiper from '../../components/Onboarding/Swiper';
import { LinearGradient } from 'expo-linear-gradient';
const pages = [
{
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
description:
'Coventry is a city with a thousand years of history that has plenty to offer the visiting tourist.',
},
{
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
description:
'Coventry2 is a city with a thousand years of history that has plenty to offer the visiting tourist.',
},
{
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
description:
'Coventry3 is a city with a thousand years of history that has plenty to offer the visiting tourist.',
},
{
img: 'https://www.tunnelbear.com/static/img/android@2x.b83f4df.png',
description:
'Coventry4 is a city with a thousand years of history that has plenty to offer the visiting tourist.',
},
];
export default class OnboardingPage extends Component {
static navigationOptions = {
header: null,
};
render() {
return (
<Swiper>
{pages.map((page, index) => (
<LinearGradient
key={index}
colors={['#f66969', '#f44c4c']}
start={[0, 0]}
end={[1, 0]}
style={[styles.slide]}
>
<Image source={{ uri: page.img }} style={[styles.img]} />
<Text style={styles.text}>{page.description}</Text>
</LinearGradient>
))}
</Swiper>
);
}
}
const styles = StyleSheet.create({
slide: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
color: '#FFFFFF',
// fontFamily: 'Avenir',
fontSize: 18,
marginHorizontal: 30,
position: 'absolute',
top: '71%',
lineHeight: 24,
},
img: {
position: 'absolute',
top: '16%',
width: '50%',
height: '50%',
resizeMode: 'contain',
},
});
import React, { Component } from 'react';
import { Container, Text, Content, Button, Row, CheckBox } from 'native-base';
import { theme } from '../../constants/Styles';
import { Form, Field } from 'react-native-validate-form';
import InputField from '../../components/InputField';
import { LinearGradient } from 'expo-linear-gradient';
import { Alert } from 'react-native';
// validations
const required = value => (value ? undefined : 'This is a required field.');
const minChar = value => (value && !/^.{6,}$/i.test(value) ? 'At least 6 characters' : undefined);
const email = value =>
value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,5}$/i.test(value)
? 'Please provide a valid email address.'
: undefined;
const phoneNum = value => (value && !/^[0][689][0-9]{8}$/i.test(value) ? 'Invalid number' : undefined);
const cfPassword = value => (value && value == this.password ? 'Password not match' : undefined); //how??
export default class Register extends Component {
static navigationOptions = {
header: null,
};
state = {
errors: [],
isCheck: false,
name: '',
surName: '',
email: '',
password: '',
cfPassword: '',
phoneNum: '',
};
submitForm() {
let submitResults = this.registerForm.validate();
let errors = [];
submitResults.forEach(item => {
errors.push({ field: item.fieldName, error: item.error });
});
this.setState({ errors: errors });
}
submitSuccess() {
console.log('Submit Success!');
Alert.alert(
'Completed!',
'You have completed your registration',
[
// {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
// {
// text: 'Cancel',
// onPress: () => console.log('Cancel Pressed'),
// style: 'cancel',
// },
{
text: 'Go to Login',
onPress: () => {
// Actions.LoginPage();
this.props.navigation.navigate('Login');
},
},
],
{ cancelable: false }
);
// Actions.LoginPage();
}
submitFailed() {
console.log('Submit Failed!');
}
render() {
return (
<Container>
<Content contentContainerStyle={theme.startContainer}>
<Text style={theme.startTitle}>Register</Text>
<Form
ref={ref => (this.registerForm = ref)}
validate={true}
submit={this.submitSuccess.bind(this)}
failed={this.submitFailed.bind(this)}
errors={this.state.errors}
style={theme.startFormContainer}
>
{/* ---name--- */}
<Field
required
component={InputField}
validations={[required]}
name="name"
value={this.state.name}
onChangeText={val => this.setState({ name: val })}
customStyle={[theme.input, { marginTop: 0 }]}
placeholder="Name"
/>
{/* ---surName--- */}
<Field
required
component={InputField}
validations={[required]}
name="surName"
value={this.state.surName}
onChangeText={val => this.setState({ surName: val })}
customStyle={theme.input}
placeholder="Surname"
/>
{/* ---email--- */}
<Field
required
component={InputField}
validations={[required, email]}
name="email"
value={this.state.email}
onChangeText={val => this.setState({ email: val })}
customStyle={theme.input}
placeholder="E-mail"
/>
{/* ---password--- */}
<Field
required
component={InputField}
validations={[required, minChar]}
name="password"
value={this.state.password}
onChangeText={val => this.setState({ password: val })}
customStyle={theme.input}
placeholder="Password"
isPass={true}
/>
{/* ---cf password--- */}
<Field
required
component={InputField}
validations={[required, cfPassword, minChar]}
name="cfPassword"
value={this.state.cfPassword}
onChangeText={val => this.setState({ cfPassword: val })}
customStyle={theme.input}
placeholder="Confirm password"
isPass={true}
/>
{/* ---phone no--- */}
<Field
required
component={InputField}
validations={[required, phoneNum]}
name="phoneNum"
value={this.state.phoneNum}
onChangeText={val => this.setState({ phoneNum: val })}
customStyle={theme.input}
placeholder="Phone number"
/>
</Form>
<Row style={{ marginTop: 30 }}>
<CheckBox
color={'#888888'}
checked={this.state.isCheck}
onPress={() =>
this.setState(() => {
return (this.state.isCheck = !this.state.isCheck);
})
}
/>
<Text style={{ color: '#9ea0a5', marginLeft: 15, fontSize: 14 }}>
I have read the{' '}
<Text style={{ textDecorationLine: 'underline', color: '#56575a', fontSize: 14 }}>
Terms and Conditions
</Text>
.
</Text>
</Row>
<LinearGradient
colors={['#f97070', '#f44c4c']}
start={[0, 0]}
end={[1, 0]}
style={[theme.roundedBtn, { marginTop: 50 }]}
>
<Button full transparent onPress={this.submitForm.bind(this)}>
<Text style={{ color: 'white' }}>CONTINUE</Text>
</Button>
</LinearGradient>
</Content>
</Container>
);
}
}
import React, { Component } from 'react';
import { Container, Text, Content, View, Button } from 'native-base';
import { Image } from 'react-native';
import { theme } from '../../constants/Styles';
// import { Actions } from 'react-native-router-flux';
import { LinearGradient } from 'expo-linear-gradient';
export default class SendEmail extends Component {
static navigationOptions = {
header: null,
};
render() {
return (
<Container>
<Content style={theme.startContainer}>
<Image
style={{
width: 135,
height: 135,
alignSelf: 'center',
borderRadius: 65,
}}
source={{
uri:
'https://constructioncompanieslebanon.com/wp-content/uploads/2018/02/6ba96ffc82c13a9c4271233ab23e9afe.jpg',
}}
/>
<Text style={[theme.startTitle, { marginTop: 45 }]}>Check you email</Text>
<View style={{ paddingHorizontal: 15, marginTop: 40 }}>
<Text style={{ color: '#808080' }}>
We sent an email with instructions for resetting your password.
</Text>
</View>
<LinearGradient
colors={['#f97070', '#f44c4c']}
start={[0, 0]}
end={[1, 0]}
style={[theme.roundedBtn, { marginTop: 60 }]}
>
<Button
full
transparent
onPress={() => {
// Actions.LoginPage();
this.props.navigation.navigate('Login');
}}
>
<Text style={{ color: 'white' }}>DONE</Text>
</Button>
</LinearGradient>
<Button transparent style={{ marginTop: 40, alignSelf: 'center' }}>
<Text style={{ color: '#9b9b9b' }}>RESEND</Text>
</Button>
</Content>
</Container>
);
}
}
import React, { useState } from 'react';
import { Container, Header, Footer } from 'native-base';
const LayoutComponent = props => {
return (
<Container>
<Header transparent />
{props.children}
<Footer />
</Container>
);
};
export default LayoutComponent;
import { createStackNavigator } from 'react-navigation';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import {
createReduxContainer,
createReactNavigationReduxMiddleware,
createNavigationReducer,
} from 'react-navigation-redux-helpers';
import { Provider, connect } from 'react-redux';
import React from 'react';
import PageOne from '../screens/private/PageOne';
import PageTwo from '../screens/private/PageTwo';
import LoginPage from '../screens/public/LoginPage';
import HomePage from '../screens/private/HomePage';
const AppNavigator = createStackNavigator(
{
HomePage: { screen: HomePage },
LoginPage: { screen: LoginPage },
PageOne: { screen: PageOne },
PageTwo: { screen: PageTwo },
},
{
headerMode: 'none',
initialRouteName: 'HomePage',
}
);
const navReducer = createNavigationReducer(AppNavigator);
const appReducer = combineReducers({
nav: navReducer,
});
const middleware = createReactNavigationReduxMiddleware(state => state.nav);
const App = createReduxContainer(AppNavigator);
const mapStateToProps = state => ({
state: state.nav,
});
const AppWithNavigationState = connect(mapStateToProps)(App);
const store = createStore(appReducer, applyMiddleware(middleware));
class AppRouterComponent extends React.Component {
render() {
return (
<Provider store={store}>
<AppWithNavigationState />
</Provider>
);
}
}
export default AppRouterComponent;
import React, { Component } from 'react';
import { Container, Content, Text, Card, Header, Body, Button, Title, CardItem } from 'native-base';
import { Actions } from 'react-native-router-flux';
class PageTwo extends Component {
render() {
return (
<Container>
<Header>
<Body>
<Title>PageTwo</Title>
</Body>
</Header>
<Content padder>
<Card>
<CardItem>
<Body>
<Text>This is Page Two, Press button to goto page one</Text>
</Body>
</CardItem>
</Card>
<Button
dark
bordered
style={{ alignSelf: 'center', margin: 30 }}
onPress={() => {
Actions.pop();
// this.props.navigation.navigate('PageOne');
}}
>
<Text>Goto Page 1</Text>
</Button>
</Content>
</Container>
);
}
}
export default PageTwo;
import React, { Component } from 'react';
import { Container, Content, Text, Card, Header, H1 } from 'native-base';
class LoginPage extends Component {
state = {};
render() {
return (
<Container>
<Header transparent />
<Content padder style={{ paddingHorizontal: 16 }}>
<Text style={{ textAlign: 'center', fontFamily: 'Avenir_Roman', fontSize: 36 }}>Login</Text>
<Card style={{ marginTop: 40 }}>
<Text>Hello</Text>
</Card>
</Content>
</Container>
);
}
}
export default LoginPage;
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment