first commit
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
[android]
|
||||||
|
target = Google Inc.:Google APIs:23
|
||||||
|
|
||||||
|
[maven_repositories]
|
||||||
|
central = https://repo1.maven.org/maven2
|
|
@ -0,0 +1,2 @@
|
||||||
|
BUNDLE_PATH: "vendor/bundle"
|
||||||
|
BUNDLE_FORCE_RUBY_PLATFORM: 1
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: '@react-native-community',
|
||||||
|
};
|
|
@ -0,0 +1,67 @@
|
||||||
|
[ignore]
|
||||||
|
; We fork some components by platform
|
||||||
|
.*/*[.]android.js
|
||||||
|
|
||||||
|
; Ignore "BUCK" generated dirs
|
||||||
|
<PROJECT_ROOT>/\.buckd/
|
||||||
|
|
||||||
|
; Ignore polyfills
|
||||||
|
node_modules/react-native/Libraries/polyfills/.*
|
||||||
|
|
||||||
|
; Flow doesn't support platforms
|
||||||
|
.*/Libraries/Utilities/LoadingView.js
|
||||||
|
|
||||||
|
.*/node_modules/resolve/test/resolver/malformed_package_json/package\.json$
|
||||||
|
|
||||||
|
[untyped]
|
||||||
|
.*/node_modules/@react-native-community/cli/.*/.*
|
||||||
|
|
||||||
|
[include]
|
||||||
|
|
||||||
|
[libs]
|
||||||
|
node_modules/react-native/interface.js
|
||||||
|
node_modules/react-native/flow/
|
||||||
|
|
||||||
|
[options]
|
||||||
|
emoji=true
|
||||||
|
|
||||||
|
exact_by_default=true
|
||||||
|
|
||||||
|
format.bracket_spacing=false
|
||||||
|
|
||||||
|
module.file_ext=.js
|
||||||
|
module.file_ext=.json
|
||||||
|
module.file_ext=.ios.js
|
||||||
|
|
||||||
|
munge_underscores=true
|
||||||
|
|
||||||
|
module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/node_modules/react-native/\1'
|
||||||
|
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'
|
||||||
|
|
||||||
|
suppress_type=$FlowIssue
|
||||||
|
suppress_type=$FlowFixMe
|
||||||
|
suppress_type=$FlowFixMeProps
|
||||||
|
suppress_type=$FlowFixMeState
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
sketchy-null-number=warn
|
||||||
|
sketchy-null-mixed=warn
|
||||||
|
sketchy-number=warn
|
||||||
|
untyped-type-import=warn
|
||||||
|
nonstrict-import=warn
|
||||||
|
deprecated-type=warn
|
||||||
|
unsafe-getters-setters=warn
|
||||||
|
unnecessary-invariant=warn
|
||||||
|
signature-verification-failure=warn
|
||||||
|
|
||||||
|
[strict]
|
||||||
|
deprecated-type
|
||||||
|
nonstrict-import
|
||||||
|
sketchy-null
|
||||||
|
unclear-type
|
||||||
|
unsafe-getters-setters
|
||||||
|
untyped-import
|
||||||
|
untyped-type-import
|
||||||
|
|
||||||
|
[version]
|
||||||
|
^0.170.0
|
|
@ -0,0 +1,61 @@
|
||||||
|
# OSX
|
||||||
|
#
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
build/
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata
|
||||||
|
*.xccheckout
|
||||||
|
*.moved-aside
|
||||||
|
DerivedData
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
||||||
|
*.xcuserstate
|
||||||
|
|
||||||
|
# Android/IntelliJ
|
||||||
|
#
|
||||||
|
build/
|
||||||
|
.idea
|
||||||
|
.gradle
|
||||||
|
local.properties
|
||||||
|
*.iml
|
||||||
|
*.hprof
|
||||||
|
|
||||||
|
# node.js
|
||||||
|
#
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# BUCK
|
||||||
|
buck-out/
|
||||||
|
\.buckd/
|
||||||
|
*.keystore
|
||||||
|
!debug.keystore
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
#
|
||||||
|
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||||
|
# screenshots whenever they are needed.
|
||||||
|
# For more information about the recommended setup visit:
|
||||||
|
# https://docs.fastlane.tools/best-practices/source-control/
|
||||||
|
|
||||||
|
*/fastlane/report.xml
|
||||||
|
*/fastlane/Preview.html
|
||||||
|
*/fastlane/screenshots
|
||||||
|
|
||||||
|
# Bundle artifact
|
||||||
|
*.jsbundle
|
||||||
|
|
||||||
|
# Ruby / CocoaPods
|
||||||
|
/ios/Pods/
|
||||||
|
/vendor/bundle/
|
|
@ -0,0 +1,7 @@
|
||||||
|
module.exports = {
|
||||||
|
arrowParens: 'avoid',
|
||||||
|
bracketSameLine: true,
|
||||||
|
bracketSpacing: false,
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: 'all',
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
2.7.4
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -0,0 +1,65 @@
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
|
import { StyleSheet, ScrollView, View, Text, StatusBar } from 'react-native';
|
||||||
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
|
import 'react-native-gesture-handler';
|
||||||
|
import Router from './router';
|
||||||
|
import { configure } from "mobx"
|
||||||
|
import { Provider } from 'mobx-react';
|
||||||
|
import Store from './src/stores/index';
|
||||||
|
import { colors } from './src/assets/styles/colors-theme';
|
||||||
|
import { NavigationContainer, useFocusEffect } from '@react-navigation/native';
|
||||||
|
import { createStackNavigator, HeaderBackButton } from '@react-navigation/stack';
|
||||||
|
import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs';
|
||||||
|
import { LogBox } from 'react-native';
|
||||||
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
|
import {
|
||||||
|
Header,
|
||||||
|
LearnMoreLinks,
|
||||||
|
Colors,
|
||||||
|
DebugInstructions,
|
||||||
|
ReloadInstructions,
|
||||||
|
} from 'react-native/Libraries/NewAppScreen';
|
||||||
|
import NetInfo from "@react-native-community/netinfo";
|
||||||
|
import { NotifierWrapper } from 'react-native-notifier';
|
||||||
|
|
||||||
|
const App: () => React$Node = () => {
|
||||||
|
configure({
|
||||||
|
enforceActions: "never",
|
||||||
|
})
|
||||||
|
LogBox.ignoreLogs(['Warning: ...']); // Ignore log notification by message
|
||||||
|
LogBox.ignoreAllLogs();//Ignore all log notifications
|
||||||
|
NetInfo.addEventListener(networkState => {
|
||||||
|
Store.appStore.networkConnect(networkState)
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Provider {...Store}>
|
||||||
|
|
||||||
|
<SafeAreaProvider>
|
||||||
|
<StatusBar
|
||||||
|
animated={true}
|
||||||
|
barStyle={'dark-content'}
|
||||||
|
backgroundColor={'black'}
|
||||||
|
translucent={true}
|
||||||
|
/>
|
||||||
|
<NotifierWrapper>
|
||||||
|
|
||||||
|
<NavigationContainer
|
||||||
|
onStateChange={state => Store.appStore.setRouterState(state)}
|
||||||
|
ref={navigatorRef => Store.appStore.setRouterRef(navigatorRef)}
|
||||||
|
>
|
||||||
|
<Router />
|
||||||
|
</NavigationContainer>
|
||||||
|
</NotifierWrapper>
|
||||||
|
</SafeAreaProvider>
|
||||||
|
</Provider>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default App;
|
|
@ -0,0 +1,6 @@
|
||||||
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
|
||||||
|
ruby '2.7.4'
|
||||||
|
|
||||||
|
gem 'cocoapods', '~> 1.11', '>= 1.11.2'
|
|
@ -0,0 +1,100 @@
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
CFPropertyList (3.0.5)
|
||||||
|
rexml
|
||||||
|
activesupport (6.1.5.1)
|
||||||
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
|
i18n (>= 1.6, < 2)
|
||||||
|
minitest (>= 5.1)
|
||||||
|
tzinfo (~> 2.0)
|
||||||
|
zeitwerk (~> 2.3)
|
||||||
|
addressable (2.8.0)
|
||||||
|
public_suffix (>= 2.0.2, < 5.0)
|
||||||
|
algoliasearch (1.27.5)
|
||||||
|
httpclient (~> 2.8, >= 2.8.3)
|
||||||
|
json (>= 1.5.1)
|
||||||
|
atomos (0.1.3)
|
||||||
|
claide (1.1.0)
|
||||||
|
cocoapods (1.11.3)
|
||||||
|
addressable (~> 2.8)
|
||||||
|
claide (>= 1.0.2, < 2.0)
|
||||||
|
cocoapods-core (= 1.11.3)
|
||||||
|
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||||
|
cocoapods-downloader (>= 1.4.0, < 2.0)
|
||||||
|
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||||
|
cocoapods-search (>= 1.0.0, < 2.0)
|
||||||
|
cocoapods-trunk (>= 1.4.0, < 2.0)
|
||||||
|
cocoapods-try (>= 1.1.0, < 2.0)
|
||||||
|
colored2 (~> 3.1)
|
||||||
|
escape (~> 0.0.4)
|
||||||
|
fourflusher (>= 2.3.0, < 3.0)
|
||||||
|
gh_inspector (~> 1.0)
|
||||||
|
molinillo (~> 0.8.0)
|
||||||
|
nap (~> 1.0)
|
||||||
|
ruby-macho (>= 1.0, < 3.0)
|
||||||
|
xcodeproj (>= 1.21.0, < 2.0)
|
||||||
|
cocoapods-core (1.11.3)
|
||||||
|
activesupport (>= 5.0, < 7)
|
||||||
|
addressable (~> 2.8)
|
||||||
|
algoliasearch (~> 1.0)
|
||||||
|
concurrent-ruby (~> 1.1)
|
||||||
|
fuzzy_match (~> 2.0.4)
|
||||||
|
nap (~> 1.0)
|
||||||
|
netrc (~> 0.11)
|
||||||
|
public_suffix (~> 4.0)
|
||||||
|
typhoeus (~> 1.0)
|
||||||
|
cocoapods-deintegrate (1.0.5)
|
||||||
|
cocoapods-downloader (1.6.3)
|
||||||
|
cocoapods-plugins (1.0.0)
|
||||||
|
nap
|
||||||
|
cocoapods-search (1.0.1)
|
||||||
|
cocoapods-trunk (1.6.0)
|
||||||
|
nap (>= 0.8, < 2.0)
|
||||||
|
netrc (~> 0.11)
|
||||||
|
cocoapods-try (1.2.0)
|
||||||
|
colored2 (3.1.2)
|
||||||
|
concurrent-ruby (1.1.10)
|
||||||
|
escape (0.0.4)
|
||||||
|
ethon (0.15.0)
|
||||||
|
ffi (>= 1.15.0)
|
||||||
|
ffi (1.15.5)
|
||||||
|
fourflusher (2.3.1)
|
||||||
|
fuzzy_match (2.0.4)
|
||||||
|
gh_inspector (1.1.3)
|
||||||
|
httpclient (2.8.3)
|
||||||
|
i18n (1.10.0)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
json (2.6.1)
|
||||||
|
minitest (5.15.0)
|
||||||
|
molinillo (0.8.0)
|
||||||
|
nanaimo (0.3.0)
|
||||||
|
nap (1.1.0)
|
||||||
|
netrc (0.11.0)
|
||||||
|
public_suffix (4.0.7)
|
||||||
|
rexml (3.2.5)
|
||||||
|
ruby-macho (2.5.1)
|
||||||
|
typhoeus (1.4.0)
|
||||||
|
ethon (>= 0.9.0)
|
||||||
|
tzinfo (2.0.4)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
xcodeproj (1.21.0)
|
||||||
|
CFPropertyList (>= 2.3.3, < 4.0)
|
||||||
|
atomos (~> 0.1.3)
|
||||||
|
claide (>= 1.0.2, < 2.0)
|
||||||
|
colored2 (~> 3.1)
|
||||||
|
nanaimo (~> 0.3.0)
|
||||||
|
rexml (~> 3.2.4)
|
||||||
|
zeitwerk (2.5.4)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
cocoapods (~> 1.11, >= 1.11.2)
|
||||||
|
|
||||||
|
RUBY VERSION
|
||||||
|
ruby 2.7.4p191
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.2.27
|
|
@ -0,0 +1,172 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
Image,
|
||||||
|
TextInput,
|
||||||
|
Keyboard,
|
||||||
|
} from 'react-native';
|
||||||
|
import { inject, observer } from 'mobx-react';
|
||||||
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons';
|
||||||
|
import { observable } from 'mobx';
|
||||||
|
import { colors } from './src/assets/styles/colors-theme';
|
||||||
|
import I18n from './src/services/i18n'
|
||||||
|
import { images } from './src/assets/images/imageIndex'
|
||||||
|
Icon.loadFont();
|
||||||
|
|
||||||
|
|
||||||
|
const MyTabBar = inject("appStore")(observer(class MyTabBar extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
langLabelReturn(label) {
|
||||||
|
switch (label) {
|
||||||
|
case 'main':
|
||||||
|
return 'main'
|
||||||
|
break;
|
||||||
|
case 'coupon':
|
||||||
|
return 'cartCoupon'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'menu':
|
||||||
|
return 'menu'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'setting':
|
||||||
|
return 'settingsTitle'
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iconHandler(name, active) {
|
||||||
|
if (active) {
|
||||||
|
switch (name) {
|
||||||
|
case 'main':
|
||||||
|
return images.bottomBar.home
|
||||||
|
break;
|
||||||
|
case 'coupon':
|
||||||
|
return images.bottomBar.coupon
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'menu':
|
||||||
|
return images.bottomBar.menu
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'setting':
|
||||||
|
return images.bottomBar.setting
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (name) {
|
||||||
|
case 'main':
|
||||||
|
return images.bottomBar.home_active
|
||||||
|
break;
|
||||||
|
case 'coupon':
|
||||||
|
return images.bottomBar.coupon_active
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'menu':
|
||||||
|
return images.bottomBar.menu_active
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'setting':
|
||||||
|
return images.bottomBar.setting_active
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
var { state, descriptors, navigation, logined } = this.props;
|
||||||
|
return (
|
||||||
|
<View style={{ flexDirection: 'row', backgroundColor: colors.mainColor }}>
|
||||||
|
{state.routes.map((route, index) => {
|
||||||
|
const { options } = descriptors[route.key];
|
||||||
|
const label =
|
||||||
|
options.tabBarLabel !== undefined
|
||||||
|
? options.tabBarLabel
|
||||||
|
: options.title !== undefined
|
||||||
|
? options.title
|
||||||
|
: route.name;
|
||||||
|
let iconName;
|
||||||
|
switch (label) {
|
||||||
|
case 'main':
|
||||||
|
iconName = images.bottomBar.home;
|
||||||
|
break;
|
||||||
|
case 'coupon':
|
||||||
|
iconName = images.bottomBar.coupon;
|
||||||
|
break;
|
||||||
|
case 'menu':
|
||||||
|
iconName = images.bottomBar.menu;
|
||||||
|
break;
|
||||||
|
case 'setting':
|
||||||
|
iconName = images.bottomBar.setting;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isFocused = state.index === index;
|
||||||
|
|
||||||
|
const onPress = () => {
|
||||||
|
const event = navigation.emit({
|
||||||
|
type: 'tabPress',
|
||||||
|
target: route.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isFocused && !event.defaultPrevented) {
|
||||||
|
console.log(route.name);
|
||||||
|
if (route.name == 'Coupon' && !this.store.logined) {
|
||||||
|
navigation.navigate('Signin');
|
||||||
|
} else {
|
||||||
|
navigation.navigate(route.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onLongPress = () => {
|
||||||
|
navigation.emit({
|
||||||
|
type: 'tabLongPress',
|
||||||
|
target: route.key,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityStates={isFocused ? ['selected'] : []}
|
||||||
|
accessibilityLabel={options.tabBarAccessibilityLabel}
|
||||||
|
testID={options.tabBarTestID}
|
||||||
|
onPress={onPress}
|
||||||
|
onLongPress={onLongPress}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 15,
|
||||||
|
}}>
|
||||||
|
{/* <Icon
|
||||||
|
name={iconName}
|
||||||
|
size={28}
|
||||||
|
color={isFocused ? colors.fontColor : '#98AD86'}
|
||||||
|
/> */}
|
||||||
|
|
||||||
|
<Image source={this.iconHandler(label,isFocused)} />
|
||||||
|
<Text style={{ color: isFocused ? colors.fontColor : '#CA9D66', fontSize: 12 }}>
|
||||||
|
{I18n.t(this.langLabelReturn(label))}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
export default MyTabBar
|
|
@ -0,0 +1,91 @@
|
||||||
|
## Soya 3.3
|
||||||
|
|
||||||
|
## Description
|
||||||
|
This mobile application is designed for ordering at physical stores. Its features include displaying the address of the physical store, joining as a member to receive coupons, and using the coupons.
|
||||||
|
|
||||||
|
### Screenshot
|
||||||
|
<img src="./src/assets/screenshot/1.png" width="40%" height="40%">
|
||||||
|
<img src="./src/assets/screenshot/2.png" width="40%" height="40%">
|
||||||
|
<img src="./src/assets/screenshot/3.png" width="40%" height="40%">
|
||||||
|
<img src="./src/assets/screenshot/4.png" width="40%" height="40%">
|
||||||
|
<img src="./src/assets/screenshot/banner.png" >
|
||||||
|
|
||||||
|
This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
|
||||||
|
|
||||||
|
# Getting Started
|
||||||
|
|
||||||
|
>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
|
||||||
|
|
||||||
|
## Step 1: Start the Metro Server
|
||||||
|
|
||||||
|
First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.
|
||||||
|
|
||||||
|
To start Metro, run the following command from the _root_ of your React Native project:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# using npm
|
||||||
|
npm start
|
||||||
|
|
||||||
|
# OR using Yarn
|
||||||
|
yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 2: Start your Application
|
||||||
|
|
||||||
|
Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:
|
||||||
|
|
||||||
|
### For Android
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# using npm
|
||||||
|
npm run android
|
||||||
|
|
||||||
|
# OR using Yarn
|
||||||
|
yarn android
|
||||||
|
```
|
||||||
|
|
||||||
|
### For iOS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# using npm
|
||||||
|
npm run ios
|
||||||
|
|
||||||
|
# OR using Yarn
|
||||||
|
yarn ios
|
||||||
|
```
|
||||||
|
|
||||||
|
If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.
|
||||||
|
|
||||||
|
This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.
|
||||||
|
|
||||||
|
## Step 3: Modifying your App
|
||||||
|
|
||||||
|
Now that you have successfully run the app, let's modify it.
|
||||||
|
|
||||||
|
1. Open `App.tsx` in your text editor of choice and edit some lines.
|
||||||
|
2. For **Android**: Press the <kbd>R</kbd> key twice or select **"Reload"** from the **Developer Menu** (<kbd>Ctrl</kbd> + <kbd>M</kbd> (on Window and Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (on macOS)) to see your changes!
|
||||||
|
|
||||||
|
For **iOS**: Hit <kbd>Cmd ⌘</kbd> + <kbd>R</kbd> in your iOS Simulator to reload the app and see your changes!
|
||||||
|
|
||||||
|
## Congratulations! :tada:
|
||||||
|
|
||||||
|
You've successfully run and modified your React Native App. :partying_face:
|
||||||
|
|
||||||
|
### Now what?
|
||||||
|
|
||||||
|
- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
|
||||||
|
- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started).
|
||||||
|
|
||||||
|
# Troubleshooting
|
||||||
|
|
||||||
|
If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
|
||||||
|
|
||||||
|
# Learn More
|
||||||
|
|
||||||
|
To learn more about React Native, take a look at the following resources:
|
||||||
|
|
||||||
|
- [React Native Website](https://reactnative.dev) - learn more about React Native.
|
||||||
|
- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
|
||||||
|
- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
|
||||||
|
- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
|
||||||
|
- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
|
|
@ -0,0 +1,3 @@
|
||||||
|
const appVersion = '1.0'
|
||||||
|
|
||||||
|
export default appVersion
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
presets: ['module:metro-react-native-babel-preset'],
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
/**
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {AppRegistry} from 'react-native';
|
||||||
|
import App from './App';
|
||||||
|
import codePush from "react-native-code-push";
|
||||||
|
import {name as appName} from './app.json';
|
||||||
|
|
||||||
|
AppRegistry.registerComponent(appName, () => codePush(App));
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
preset: 'react-native',
|
||||||
|
// setupFiles: ['./node_modules/@testing-library/jest-native/extend-expect'],
|
||||||
|
};
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* Metro configuration for React Native
|
||||||
|
* https://github.com/facebook/react-native
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
transformer: {
|
||||||
|
getTransformOptions: async () => ({
|
||||||
|
transform: {
|
||||||
|
experimentalImportSupport: false,
|
||||||
|
inlineRequires: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,99 @@
|
||||||
|
{
|
||||||
|
"name": "soya",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"android": "react-native run-android",
|
||||||
|
"ios": "react-native run-ios",
|
||||||
|
"start": "react-native start",
|
||||||
|
"test": "jest",
|
||||||
|
"lint": "eslint ."
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/preset-flow": "^7.18.6",
|
||||||
|
"@freakycoder/react-native-progressive-fast-image": "^1.0.0",
|
||||||
|
"@react-native-community/async-storage": "^1.12.1",
|
||||||
|
"@react-native-community/checkbox": "^0.5.14",
|
||||||
|
"@react-native-community/masked-view": "^0.1.11",
|
||||||
|
"@react-native-community/netinfo": "^9.3.9",
|
||||||
|
"@react-native-firebase/app": "^17.4.2",
|
||||||
|
"@react-native-firebase/messaging": "^17.4.2",
|
||||||
|
"@react-navigation/bottom-tabs": "^6.4.1",
|
||||||
|
"@react-navigation/material-bottom-tabs": "^6.2.5",
|
||||||
|
"@react-navigation/native": "^6.0.14",
|
||||||
|
"@react-navigation/stack": "^6.3.5",
|
||||||
|
"@testing-library/jest-native": "^5.4.2",
|
||||||
|
"@testing-library/react-native": "^12.0.1",
|
||||||
|
"axios": "^1.2.0",
|
||||||
|
"axios-digest": "^0.3.0",
|
||||||
|
"jest-environment-jsdom": "^29.5.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"lottie-react-native": "^5.1.4",
|
||||||
|
"mobx": "^6.7.0",
|
||||||
|
"mobx-react": "^7.6.0",
|
||||||
|
"moment": "^2.29.4",
|
||||||
|
"needle": "^3.2.0",
|
||||||
|
"qs": "^6.11.0",
|
||||||
|
"react": "17.0.2",
|
||||||
|
"react-native": "0.68.2",
|
||||||
|
"react-native-background-timer": "^2.4.1",
|
||||||
|
"react-native-base64": "^0.2.1",
|
||||||
|
"react-native-code-push": "^7.0.5",
|
||||||
|
"react-native-codegen": "^0.71.3",
|
||||||
|
"react-native-confirmation-code-field": "^7.3.1",
|
||||||
|
"react-native-date-picker": "^4.2.6",
|
||||||
|
"react-native-digest-fetch": "^1.0.5",
|
||||||
|
"react-native-easy-grid": "^0.2.2",
|
||||||
|
"react-native-easy-toast": "^2.3.0",
|
||||||
|
"react-native-fast-image": "^8.6.3",
|
||||||
|
"react-native-gesture-handler": "^2.8.0",
|
||||||
|
"react-native-htmlview": "^0.16.0",
|
||||||
|
"react-native-i18n": "^2.0.15",
|
||||||
|
"react-native-image-modal": "^2.0.4",
|
||||||
|
"react-native-image-picker": "^4.10.1",
|
||||||
|
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
||||||
|
"react-native-maps": "^1.3.2",
|
||||||
|
"react-native-modal": "^13.0.1",
|
||||||
|
"react-native-modals": "^0.22.3",
|
||||||
|
"react-native-notifier": "^1.9.0",
|
||||||
|
"react-native-paper": "^4.12.5",
|
||||||
|
"react-native-popup-menu": "^0.16.1",
|
||||||
|
"react-native-qrcode-svg": "^6.1.2",
|
||||||
|
"react-native-reanimated": "^2.13.0",
|
||||||
|
"react-native-safe-area-context": "^4.4.1",
|
||||||
|
"react-native-safe-area-view": "^1.1.1",
|
||||||
|
"react-native-safearea-height": "^1.0.6",
|
||||||
|
"react-native-screens": "^3.18.2",
|
||||||
|
"react-native-size-matters": "^0.4.0",
|
||||||
|
"react-native-snap-carousel": "^3.9.1",
|
||||||
|
"react-native-status-bar-height": "^2.6.0",
|
||||||
|
"react-native-svg": "^13.6.0",
|
||||||
|
"react-native-swiper": "^1.6.0",
|
||||||
|
"react-native-tab-view": "^3.3.0",
|
||||||
|
"react-native-textinput-effects": "^0.6.3",
|
||||||
|
"react-native-uuid": "^2.0.1",
|
||||||
|
"react-native-vector-icons": "^9.2.0",
|
||||||
|
"react-native-webview": "^11.26.0",
|
||||||
|
"react-theme-provider": "^0.1.3",
|
||||||
|
"underscore": "^1.13.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.21.4",
|
||||||
|
"@babel/preset-env": "^7.21.4",
|
||||||
|
"@babel/preset-react": "^7.18.6",
|
||||||
|
"@babel/runtime": "^7.20.1",
|
||||||
|
"@react-native-community/eslint-config": "^3.2.0",
|
||||||
|
"@types/jest": "^29.5.1",
|
||||||
|
"babel-jest": "^29.5.0",
|
||||||
|
"enzyme": "^3.11.0",
|
||||||
|
"enzyme-adapter-react-16": "^1.15.7",
|
||||||
|
"eslint": "^8.28.0",
|
||||||
|
"jest": "^29.3.1",
|
||||||
|
"jest-environment-enzyme": "^7.1.2",
|
||||||
|
"jest-enzyme": "^7.1.2",
|
||||||
|
"jest-mock-axios": "^4.7.1",
|
||||||
|
"metro-react-native-babel-preset": "^0.73.3",
|
||||||
|
"react-test-renderer": "17.0.2",
|
||||||
|
"ts-jest": "^29.1.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
http {
|
||||||
|
upstream philip-cat {
|
||||||
|
server 134.209.158.35:3000;
|
||||||
|
}
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name philip-cat.com www.philip-cat.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://134.209.158.35:3000/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,251 @@
|
||||||
|
/**
|
||||||
|
* Sample React Native App
|
||||||
|
* https://github.com/facebook/react-native
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
* @flow strict-local
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
|
import { colors } from './src/assets/styles/colors-theme';
|
||||||
|
import {
|
||||||
|
StyleSheet,
|
||||||
|
ScrollView,
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
StatusBar,
|
||||||
|
TouchableOpacity,
|
||||||
|
ImageBackground
|
||||||
|
} from 'react-native';
|
||||||
|
import MyTabBar from './MyTabBar';
|
||||||
|
import SafeAreaView from 'react-native-safe-area-view';
|
||||||
|
import { Provider, inject, observer } from 'mobx-react';
|
||||||
|
import Store from './src/stores/index';
|
||||||
|
import { NavigationContainer, useFocusEffect } from '@react-navigation/native';
|
||||||
|
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
import { createStackNavigator, HeaderBackButton, CardStyleInterpolators } from '@react-navigation/stack';
|
||||||
|
import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs';
|
||||||
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
|
import I18n from './src/services/i18n';
|
||||||
|
import {
|
||||||
|
Header,
|
||||||
|
LearnMoreLinks,
|
||||||
|
Colors,
|
||||||
|
DebugInstructions,
|
||||||
|
ReloadInstructions,
|
||||||
|
} from 'react-native/Libraries/NewAppScreen';
|
||||||
|
|
||||||
|
import Main from './src/page/main/main'
|
||||||
|
import Coupon from './src/page/coupon/coupon'
|
||||||
|
import CouponDetails from './src/page/coupon/couponDetails'
|
||||||
|
import Menu from './src/page/menu/menu'
|
||||||
|
import Setting from './src/page/setting/setting'
|
||||||
|
import Signin from './src/page/signin/signin'
|
||||||
|
import Signup from './src/page/signup/signup'
|
||||||
|
import SignUpVerify from './src/page/signup/signUpVerify'
|
||||||
|
import SplashScreen from './src/page/splash/splashScreen'
|
||||||
|
import About from './src/page/setting/about'
|
||||||
|
import PrivacyPolicy from './src/page/setting/privacyPolicy'
|
||||||
|
import LoyaltyProgramTerms from './src/page/setting/loyaltyProgramTerms'
|
||||||
|
import StoreInfo from './src/page/setting/storeInfo'
|
||||||
|
import NewsDetails from './src/page/news/newsDetails'
|
||||||
|
import NewsList from './src/page/news/newsList'
|
||||||
|
import Profile from './src/page/profile/profile'
|
||||||
|
import Testui from './src/page/camTest/testui'
|
||||||
|
|
||||||
|
Icon.loadFont();
|
||||||
|
|
||||||
|
const Stack = createStackNavigator();
|
||||||
|
const BottomTab = createBottomTabNavigator();
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
animation: 'mass',
|
||||||
|
config: {
|
||||||
|
stiffness: 1000,
|
||||||
|
damping: 500,
|
||||||
|
mass: 3,
|
||||||
|
overshootClamping: true,
|
||||||
|
restDisplacementThreshold: 0.01,
|
||||||
|
restSpeedThreshold: 0.01,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Router = inject("appStore")(observer(class Router extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
I18n.locale = 'zh_hk'
|
||||||
|
}
|
||||||
|
|
||||||
|
BottomTabScreen = () => {
|
||||||
|
return (
|
||||||
|
<BottomTab.Navigator
|
||||||
|
screenOptions={{
|
||||||
|
gestureEnabled: false,
|
||||||
|
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
|
||||||
|
}}
|
||||||
|
tabBar={props => <MyTabBar {...props} />}>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Main"
|
||||||
|
component={Main}
|
||||||
|
options={{
|
||||||
|
tabBarLabel: 'main', headerShown: false,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Coupon"
|
||||||
|
component={Coupon}
|
||||||
|
options={{ tabBarLabel: 'coupon', headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Menu"
|
||||||
|
component={Menu}
|
||||||
|
options={{ tabBarLabel: 'menu', headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Setting"
|
||||||
|
component={Setting}
|
||||||
|
options={{ tabBarLabel: 'setting', headerShown: false }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</BottomTab.Navigator>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, }}>
|
||||||
|
|
||||||
|
<Stack.Navigator initialRouteName="splash"
|
||||||
|
>
|
||||||
|
{!this.store.splash ? (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
name="SplashScreen"
|
||||||
|
component={SplashScreen}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</>
|
||||||
|
) : (<>
|
||||||
|
<Stack.Screen
|
||||||
|
name="BottomTabScreen"
|
||||||
|
component={this.BottomTabScreen}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="Signin"
|
||||||
|
component={Signin}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="Signup"
|
||||||
|
component={Signup}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="SignUpVerify"
|
||||||
|
component={SignUpVerify}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="About"
|
||||||
|
component={About}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack.Screen
|
||||||
|
name="PrivacyPolicy"
|
||||||
|
component={PrivacyPolicy}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="LoyaltyProgramTerms"
|
||||||
|
component={LoyaltyProgramTerms}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="StoreInfo"
|
||||||
|
component={StoreInfo}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="NewsDetails"
|
||||||
|
component={NewsDetails}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="NewsList"
|
||||||
|
component={NewsList}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Profile"
|
||||||
|
component={Profile}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="CouponDetails"
|
||||||
|
component={CouponDetails}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Testui"
|
||||||
|
component={Testui}
|
||||||
|
options={{ headerShown: false }}
|
||||||
|
/>
|
||||||
|
</>)}
|
||||||
|
</Stack.Navigator>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
scrollView: {
|
||||||
|
backgroundColor: Colors.lighter,
|
||||||
|
},
|
||||||
|
engine: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
},
|
||||||
|
sectionContainer: {
|
||||||
|
marginTop: 32,
|
||||||
|
paddingHorizontal: 24,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: Colors.black,
|
||||||
|
},
|
||||||
|
sectionDescription: {
|
||||||
|
marginTop: 8,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '400',
|
||||||
|
color: Colors.dark,
|
||||||
|
},
|
||||||
|
highlight: {
|
||||||
|
fontWeight: '700',
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
color: Colors.dark,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: '600',
|
||||||
|
padding: 4,
|
||||||
|
paddingRight: 12,
|
||||||
|
textAlign: 'right',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Router;
|
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 190 KiB |
After Width: | Height: | Size: 252 KiB |
After Width: | Height: | Size: 462 KiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,21 @@
|
||||||
|
export const images = {
|
||||||
|
bottomBar: {
|
||||||
|
home: require('./ico-home-2.png'),
|
||||||
|
home_active: require('./ico-home.png'),
|
||||||
|
coupon: require('./ico-coupon-2.png'),
|
||||||
|
coupon_active: require('./ico-coupon.png'),
|
||||||
|
menu: require('./ico-menu-2.png'),
|
||||||
|
menu_active: require('./ico-menu.png'),
|
||||||
|
setting: require('./ico-setting-2.png'),
|
||||||
|
setting_active: require('./ico-setting.png'),
|
||||||
|
},
|
||||||
|
titleBarLogo: require('./logo.png'),
|
||||||
|
titleLogo: require('./Mascot-mini.png'),
|
||||||
|
logo: require('./Mascot.png'),
|
||||||
|
topbgc: require('./background-navbar-1.png'),
|
||||||
|
hot: require('./ico-hot.png'),
|
||||||
|
new: require('./ico-new.png'),
|
||||||
|
sweet: require('./ico-sweet.png'),
|
||||||
|
coupon: require('./couponImage.png'),
|
||||||
|
|
||||||
|
};
|
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 872 KiB |
After Width: | Height: | Size: 939 KiB |
After Width: | Height: | Size: 564 KiB |
After Width: | Height: | Size: 698 KiB |
After Width: | Height: | Size: 570 KiB |
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* 控制全app的颜色
|
||||||
|
* @type {{statusBarColor: string}}
|
||||||
|
*/
|
||||||
|
export const colors = {
|
||||||
|
bgc: '#FFFFFF',
|
||||||
|
aboutColor:'#CAB99E',
|
||||||
|
catColor: '#D0B895',
|
||||||
|
historyListColor: '#F6EFE0',
|
||||||
|
statusBarColor: '#23A2FF',
|
||||||
|
inputBgc: '#E6E7E8',
|
||||||
|
signupInputBgc: '#F0E1C9',
|
||||||
|
shoppingcartColor: '#F0DEC1',
|
||||||
|
inputText: '#4D4D4D',
|
||||||
|
profileBg: '#D29686',
|
||||||
|
mainColor: '#FFF8ED',
|
||||||
|
otherGreen: '#6EB7A0',
|
||||||
|
maingray: '#95a5a6',
|
||||||
|
lineColor: '#E5E5E5',
|
||||||
|
textColor: '#603913',
|
||||||
|
subTextColor: '#98AD86',
|
||||||
|
baseColor: '#1BBC9B',
|
||||||
|
line2Color: '#9EA3A6',
|
||||||
|
borderLineColor: '#E6E6E6',
|
||||||
|
loginButtonColor: '#3E9B42',
|
||||||
|
titleColor: '#57A75A',
|
||||||
|
grayTextColor: '#797979',
|
||||||
|
fontColor:'#532C0E',
|
||||||
|
listItemsbgc:'#FFC76E',
|
||||||
|
listItemsbgc2:'#FFEED3',
|
||||||
|
couponbgc:'#FFC76F',
|
||||||
|
};
|
|
@ -0,0 +1,92 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Platform,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
Modal,
|
||||||
|
ActivityIndicator,
|
||||||
|
Image
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
import { colors } from '../assets/styles/colors-theme';
|
||||||
|
import Lottie from 'lottie-react-native';
|
||||||
|
import { width, height } from '../services/screen';
|
||||||
|
|
||||||
|
export default class Loading extends Component {
|
||||||
|
state = {
|
||||||
|
spinner: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
transparent={true}
|
||||||
|
animationType={'none'}
|
||||||
|
visible={this.props.loading}
|
||||||
|
onRequestClose={() => {
|
||||||
|
console.log('c lose modal');
|
||||||
|
}}>
|
||||||
|
<View style={styles.modalBackground}>
|
||||||
|
<View style={styles.activityIndicatorWrapper}>
|
||||||
|
{/* <ActivityIndicator animating={this.props.loading} /> */}
|
||||||
|
<Lottie
|
||||||
|
ref={animation => {
|
||||||
|
this.animation = animation;
|
||||||
|
}}
|
||||||
|
colorFilters={[
|
||||||
|
{
|
||||||
|
keypath: 'Left',
|
||||||
|
color: colors.mainColor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keypath: 'Center',
|
||||||
|
color: colors.mainColor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keypath: 'Rigth',
|
||||||
|
color: colors.mainColor,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
style={{ height: 50, width: 50 }}
|
||||||
|
source={require('../assets/lottie/loading')}
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.flatten({
|
||||||
|
wrapper: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: height / 2 - 100,
|
||||||
|
left: width / 2 - 70,
|
||||||
|
width: 140,
|
||||||
|
height: 140,
|
||||||
|
},
|
||||||
|
modalBackground: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
activityIndicatorWrapper: {
|
||||||
|
height: 200,
|
||||||
|
width: 200,
|
||||||
|
borderRadius: 10,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,58 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View, StyleSheet, Animated } from 'react-native';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
imageOverlay: {
|
||||||
|
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
backgroundColor: '#e1e4e8',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
class ProgressiveImage extends React.Component {
|
||||||
|
thumbnailAnimated = new Animated.Value(0);
|
||||||
|
|
||||||
|
imageAnimated = new Animated.Value(0);
|
||||||
|
|
||||||
|
handleThumbnailLoad = () => {
|
||||||
|
Animated.timing(this.thumbnailAnimated, {
|
||||||
|
toValue: 1,
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
onImageLoad = () => {
|
||||||
|
Animated.timing(this.imageAnimated, {
|
||||||
|
toValue: 1,
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
thumbnailSource,
|
||||||
|
source,
|
||||||
|
style,
|
||||||
|
...props
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Animated.Image
|
||||||
|
{...props}
|
||||||
|
source={thumbnailSource}
|
||||||
|
style={[style, { opacity: this.thumbnailAnimated }]}
|
||||||
|
onLoad={this.handleThumbnailLoad}
|
||||||
|
blurRadius={1}
|
||||||
|
/>
|
||||||
|
<Animated.Image
|
||||||
|
{...props}
|
||||||
|
source={source}
|
||||||
|
style={[styles.imageOverlay, { opacity: this.imageAnimated }, style]}
|
||||||
|
onLoad={this.onImageLoad}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProgressiveImage;
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { DeviceEventEmitter, NativeAppEventEmitter, Platform } from 'react-native';
|
||||||
|
import _BackgroundTimer from 'react-native-background-timer';
|
||||||
|
|
||||||
|
const EventEmitter = Platform.select({
|
||||||
|
ios: () => NativeAppEventEmitter,
|
||||||
|
android: () => DeviceEventEmitter,
|
||||||
|
})();
|
||||||
|
|
||||||
|
class BackgroundTimer {
|
||||||
|
static setInterval(callback, delay) {
|
||||||
|
_BackgroundTimer.start();
|
||||||
|
this.backgroundListener = EventEmitter.addListener("backgroundTimer", () => {
|
||||||
|
this.backgroundTimer = _BackgroundTimer.setInterval(callback, delay);
|
||||||
|
});
|
||||||
|
return this.backgroundListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clearInterval(timer) {
|
||||||
|
if (timer) timer.remove();
|
||||||
|
if (this.backgroundTimer)
|
||||||
|
_BackgroundTimer.clearInterval(this.backgroundTimer);
|
||||||
|
_BackgroundTimer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BackgroundTimer;
|
|
@ -0,0 +1,49 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {TextInput, View} from 'react-native';
|
||||||
|
import {colors} from '../assets/styles/colors-theme';
|
||||||
|
import {width, height} from '../services/screen';
|
||||||
|
|
||||||
|
const CommonTextInput = props => {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderBottomColor: colors.textColor,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
marginLeft: 30,
|
||||||
|
marginRight: 30,
|
||||||
|
marginTop: 20,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 5,
|
||||||
|
}}>
|
||||||
|
<TextInput
|
||||||
|
style={{
|
||||||
|
// backgroundColor:theme.inputBgc,
|
||||||
|
color: colors.textColor,
|
||||||
|
height: 35,
|
||||||
|
marginBottom: 30,
|
||||||
|
paddingBottom: 0,
|
||||||
|
fontSize: 13,
|
||||||
|
paddingRight: 20,
|
||||||
|
paddingLeft: 20,
|
||||||
|
|
||||||
|
}}
|
||||||
|
key={props.key}
|
||||||
|
value={props.value}
|
||||||
|
underlineColorAndroid="rgba(0,0,0,0)"
|
||||||
|
onChangeText={props.onChangeText}
|
||||||
|
placeholder={props.placeholder}
|
||||||
|
placeholderStyle={{fontWeight: 'bold'}}
|
||||||
|
placeholderTextColor={colors.textColor}
|
||||||
|
secureTextEntry={props.secureTextEntry}
|
||||||
|
blurOnSubmit={false}
|
||||||
|
{...props}
|
||||||
|
ref={input => props.inputRef && props.inputRef(input)}
|
||||||
|
returnKeyType={props.returnKeyType}
|
||||||
|
onSubmitEditing={props.onSubmitEditing && props.onSubmitEditing}
|
||||||
|
onFocus={props.onFocus}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CommonTextInput;
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { View, Text, TextInput, TouchableOpacity, Platform } from 'react-native';
|
||||||
|
import { colors } from '../assets/styles/colors-theme';
|
||||||
|
import { width, height } from '../services/screen';
|
||||||
|
import { s, vs, ms } from 'react-native-size-matters';
|
||||||
|
class CustomLoginButton extends Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => this.props.onPress && this.props.onPress()}
|
||||||
|
style={{
|
||||||
|
backgroundColor:
|
||||||
|
this.props.color != null ? this.props.color : colors.fontColor,
|
||||||
|
height: s(35),
|
||||||
|
borderRadius: 30,
|
||||||
|
width: s(210),
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: 10,
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color:
|
||||||
|
this.props.textColor != null ? this.props.textColor : 'white',
|
||||||
|
fontSize: s(13),
|
||||||
|
}}>
|
||||||
|
{this.props.title}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default CustomLoginButton;
|
|
@ -0,0 +1,46 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {View, Text, TextInput, TouchableOpacity, Platform} from 'react-native';
|
||||||
|
import {colors} from '../assets/styles/colors-theme';
|
||||||
|
import {width, height} from '../services/screen';
|
||||||
|
|
||||||
|
class CustomSignupInput extends Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: colors.signupInputBgc,
|
||||||
|
height: 50,
|
||||||
|
borderRadius: 30,
|
||||||
|
width: width - 100,
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: 20,
|
||||||
|
}}>
|
||||||
|
<TextInput
|
||||||
|
underlineColorAndroid="rgba(0,0,0,0)"
|
||||||
|
keyboardType={this.props.keyboardType}
|
||||||
|
onChangeText={this.props.onChangeText}
|
||||||
|
secureTextEntry={this.props.secureTextEntry}
|
||||||
|
placeholderStyle={{fontWeight: 'bold'}}
|
||||||
|
placeholderTextColor={colors.inputText}
|
||||||
|
ref={input => this.props.inputRef && this.props.inputRef(input)}
|
||||||
|
returnKeyType={this.props.returnKeyType}
|
||||||
|
onSubmitEditing={
|
||||||
|
this.props.onSubmitEditing && this.props.onSubmitEditing
|
||||||
|
}
|
||||||
|
onFocus={this.props.onFocus}
|
||||||
|
placeholder={this.props.title}
|
||||||
|
value={this.props.content}
|
||||||
|
style={{
|
||||||
|
color: colors.inputText,
|
||||||
|
fontSize: 14,
|
||||||
|
|
||||||
|
marginBottom: Platform.OS === 'ios' ? 3 : 0,
|
||||||
|
paddingVertical: 0,
|
||||||
|
marginLeft: 15,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default CustomSignupInput;
|
|
@ -0,0 +1,49 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {View, Text, TextInput, TouchableOpacity, Platform} from 'react-native';
|
||||||
|
import {colors} from '../assets/styles/colors-theme';
|
||||||
|
import {width, height} from '../services/screen';
|
||||||
|
|
||||||
|
class CustomTextInput extends Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'white',
|
||||||
|
height: 50,
|
||||||
|
borderRadius: 15,
|
||||||
|
width: width - 100,
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: 20,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: colors.line2Color,
|
||||||
|
}}>
|
||||||
|
<TextInput
|
||||||
|
underlineColorAndroid="rgba(0,0,0,0)"
|
||||||
|
keyboardType={this.props.keyboardType}
|
||||||
|
onChangeText={this.props.onChangeText}
|
||||||
|
secureTextEntry={this.props.secureTextEntry}
|
||||||
|
placeholderStyle={{fontWeight: 'bold'}}
|
||||||
|
// placeholderTextColor={colors.titleColor}
|
||||||
|
ref={input => this.props.inputRef && this.props.inputRef(input)}
|
||||||
|
returnKeyType={this.props.returnKeyType}
|
||||||
|
onSubmitEditing={
|
||||||
|
this.props.onSubmitEditing && this.props.onSubmitEditing
|
||||||
|
}
|
||||||
|
onFocus={this.props.onFocus}
|
||||||
|
placeholder={this.props.title}
|
||||||
|
placeholderTextColor={colors.grayTextColor}
|
||||||
|
value={this.props.content}
|
||||||
|
style={{
|
||||||
|
color: colors.inputText,
|
||||||
|
fontSize: 14,
|
||||||
|
|
||||||
|
marginBottom: Platform.OS === 'ios' ? 3 : 0,
|
||||||
|
paddingVertical: 0,
|
||||||
|
marginLeft: 15,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default CustomTextInput;
|
|
@ -0,0 +1,53 @@
|
||||||
|
import React, { Component } from 'react'
|
||||||
|
import { TextInput, View, TouchableOpacity } from 'react-native';
|
||||||
|
import { colors } from '../assets/styles/colors-theme';
|
||||||
|
import { width, height } from '../services/screen';
|
||||||
|
import { Hoshi } from 'react-native-textinput-effects';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import Icon from 'react-native-vector-icons/dist/Ionicons';
|
||||||
|
|
||||||
|
const HoshiTextInput = inject("appStore")(observer(class HoshiTextInput extends React.Component {
|
||||||
|
|
||||||
|
pwDisable = true
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
pwDisable: observable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={{ alignItems: 'center', justifyContent: 'center', }}>
|
||||||
|
<Hoshi
|
||||||
|
style={{ width: width - 60, marginTop: 10 }}
|
||||||
|
labelStyle={{ fontSize: 12, color: colors.fontColor }}
|
||||||
|
inputStyle={{ color: 'black', fontWeight: '300', fontSize: 12 }}
|
||||||
|
label={this.props.placeholder}
|
||||||
|
inputPadding={16}
|
||||||
|
labelHeight={24}
|
||||||
|
borderColor={colors.fontColor}
|
||||||
|
passiveColor = {colors.line2Color }
|
||||||
|
value={this.props.value}
|
||||||
|
onChangeText={this.props.onChangeText}
|
||||||
|
borderHeight={1}
|
||||||
|
secureTextEntry={this.props.password ? this.pwDisable : this.props.secureTextEntry}
|
||||||
|
returnKeyType={this.props.returnKeyType}
|
||||||
|
ref={input => this.props.inputRef && this.props.inputRef(input)}
|
||||||
|
onFocus={this.props.onFocus}
|
||||||
|
onBlur = {this.props.onBlur}
|
||||||
|
onSubmitEditing={this.props.onSubmitEditing && this.props.onSubmitEditing} />
|
||||||
|
{this.props.password ? (<TouchableOpacity style={{ position: 'absolute', right: 10, bottom: 15 }}
|
||||||
|
onPress={() => { this.pwDisable = !this.pwDisable }}>
|
||||||
|
<Icon name={this.pwDisable ? 'eye-off-outline' : 'eye-outline'} size={20} color = {colors.line2Color} />
|
||||||
|
</TouchableOpacity>) : (<View></View>)}
|
||||||
|
</View>
|
||||||
|
// />
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
export default HoshiTextInput
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { SafeAreaView, Text, Image, Alert, Linking, TouchableOpacity, StyleSheet, View, TextInput, Platform, ScrollView } from 'react-native';
|
||||||
|
import { colors } from '../assets/styles/colors-theme';
|
||||||
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
|
import { width, height } from '../services/screen';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import Icon from 'react-native-vector-icons/dist/AntDesign';
|
||||||
|
import GoogleIcon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
import FontAwesome from 'react-native-vector-icons/dist/FontAwesome5'
|
||||||
|
import FastImage from 'react-native-fast-image'
|
||||||
|
import { getStatusBarHeight } from 'react-native-status-bar-height';
|
||||||
|
import { color } from 'react-native-reanimated';
|
||||||
|
import { images } from '../assets/images/imageIndex'
|
||||||
|
import I18n from '../services/i18n'
|
||||||
|
|
||||||
|
Icon.loadFont();
|
||||||
|
GoogleIcon.loadFont()
|
||||||
|
const ListTitle = inject("appStore")(observer(class ListTitle extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={{
|
||||||
|
flex: 1,
|
||||||
|
marginHorizontal: 20,
|
||||||
|
height:20,
|
||||||
|
marginTop: 20,
|
||||||
|
}}>
|
||||||
|
<View style={{ flexDirection: "row", flex: 1, }}>
|
||||||
|
|
||||||
|
|
||||||
|
<View style={{ flex: 0.7, justifyContent: 'flex-start', alignItems: 'center', flexDirection: 'row',height:20 }}>
|
||||||
|
<Image source={images.titleLogo} />
|
||||||
|
<Text style={{color: colors.fontColor, fontWeight: '800',marginLeft:10 }}>
|
||||||
|
{this.props.title}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity style={{ flex: 0.3, justifyContent: 'center', alignItems: 'flex-end',height:20 }}
|
||||||
|
onPress={() => this.props.onPress && this.props.onPress()}
|
||||||
|
>
|
||||||
|
<Text style={{ color: colors.fontColor,fontSize:11 }}>
|
||||||
|
{I18n.t('showAll')}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
const styles = StyleSheet.flatten({
|
||||||
|
|
||||||
|
home_rectanglecd25b34b: {
|
||||||
|
opacity: 1,
|
||||||
|
flex: 1,
|
||||||
|
paddingVertical: 10,
|
||||||
|
marginTop: 50,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default ListTitle
|
|
@ -0,0 +1,22 @@
|
||||||
|
import React from 'react';
|
||||||
|
import MapView from 'react-native-maps'
|
||||||
|
import { StyleSheet } from 'react-native'
|
||||||
|
|
||||||
|
export const MapsComponent = ({latitude, longitude }) => {
|
||||||
|
const region = {
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
latitudeDelta: 0.0009,
|
||||||
|
longitudeDelta: 0.0009
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MapView
|
||||||
|
style = {{...StyleSheet.absoluteFillObject}}
|
||||||
|
region={region}
|
||||||
|
>
|
||||||
|
<MapView.Marker
|
||||||
|
coordinate={region} />
|
||||||
|
</MapView>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,89 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { View, Text, TextInput, TouchableOpacity, Platform, Image } from 'react-native';
|
||||||
|
import { colors } from '../assets/styles/colors-theme';
|
||||||
|
import { width, height } from '../services/screen';
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import I18n from '../services/i18n'
|
||||||
|
import { images } from '../assets/images/imageIndex';
|
||||||
|
import ProgressiveFastImage from "@freakycoder/react-native-progressive-fast-image";
|
||||||
|
class RenderProducts extends Component {
|
||||||
|
|
||||||
|
|
||||||
|
hotOrNewHandler(item) {
|
||||||
|
if (item.newest && item.hot) {
|
||||||
|
return images.hot
|
||||||
|
} else if (item.newest && !item.hot) {
|
||||||
|
return images.new
|
||||||
|
} else if (!item.newest && item.hot) {
|
||||||
|
return images.hot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCandy(num) {
|
||||||
|
var candys = []
|
||||||
|
for (var i = 0; i < num; i++) {
|
||||||
|
candys.push(<View key={i}><Image source={images.sweet} /></View>)
|
||||||
|
}
|
||||||
|
|
||||||
|
return candys
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
var item = this.props.item
|
||||||
|
return (
|
||||||
|
|
||||||
|
<Col>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
marginHorizontal: 10,
|
||||||
|
height: s(210),
|
||||||
|
alignItems: 'flex-end',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ width: s(110), height: s(160), backgroundColor: colors.listItemsbgc2, borderRadius: s(20) }}>
|
||||||
|
<View style={{ height: '70%', width: '100%', alignItems: 'flex-end' }}>
|
||||||
|
<View style={{ width: '50%', height: '100%', marginRight: 3, marginTop: s(45) }}>
|
||||||
|
<Text style={{ fontSize: s(9), color: colors.fontColor }}>
|
||||||
|
{I18n.t('sweet')}
|
||||||
|
</Text>
|
||||||
|
<View >
|
||||||
|
<View style={{ flexDirection: 'row' }}>
|
||||||
|
{
|
||||||
|
item.sweetIcon[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ flexDirection: 'row' }}>
|
||||||
|
{
|
||||||
|
item.sweetIcon[1]
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={{ height: '30%', width: '100%', }}>
|
||||||
|
<Text style={{ marginHorizontal: 10, fontSize: s(11), color: colors.fontColor }}>
|
||||||
|
{'SOYA 3.3' + " " + item.sweet}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ marginHorizontal: 10, marginTop: 5, fontSize: s(11), color: colors.fontColor }} numberOfLines={1}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{item.images != undefined ? (<ProgressiveFastImage resize = 'contrain' source={{ uri: item.images[0].src }} style={{ position: 'absolute', top: s(10), left: s(5), width: s(80), height: s(120) }} />) : (<View />)}
|
||||||
|
<Image source={this.hotOrNewHandler(item)} style={{ position: 'absolute', top: s(20), right: s(5), }} />
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</Col >
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default RenderProducts;
|
|
@ -0,0 +1,104 @@
|
||||||
|
|
||||||
|
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Animated,
|
||||||
|
Dimensions,
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
Image } from "react-native";
|
||||||
|
|
||||||
|
const ratio = 228 / 250;
|
||||||
|
export const MARGIN = 5;
|
||||||
|
const { width } = Dimensions.get("window");
|
||||||
|
export const CARD_WIDTH = width * 0.6;
|
||||||
|
export const CARD_HEIGHT = CARD_WIDTH * ratio;
|
||||||
|
export const HEIGHT = CARD_HEIGHT + MARGIN * 2;
|
||||||
|
|
||||||
|
const Store = ({item, x, index, updateRangePositions }) => {
|
||||||
|
|
||||||
|
const contentInset = () => {
|
||||||
|
const insetHorizontal = ( width - CARD_WIDTH) / 2
|
||||||
|
return {
|
||||||
|
top: 0,
|
||||||
|
right: insetHorizontal,
|
||||||
|
bottom: 0,
|
||||||
|
left: insetHorizontal
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const offsetForItem = (index) => {
|
||||||
|
return CARD_WIDTH * index - contentInset().left;
|
||||||
|
};
|
||||||
|
|
||||||
|
const offsetCenter = offsetForItem(index);
|
||||||
|
const offsetStart = offsetCenter - CARD_WIDTH / 2;
|
||||||
|
const offsetEnd = offsetCenter + CARD_WIDTH / 2;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
index === 0 && updateRangePositions(offsetStart)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
style={[styles.storeCard,
|
||||||
|
{
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
scale: x.interpolate({
|
||||||
|
inputRange: [ offsetStart, offsetCenter, offsetEnd ],
|
||||||
|
outputRange: [ 0.9, 1.0, 0.9 ],
|
||||||
|
extrapolate: "clamp"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
key={index}>
|
||||||
|
<View>
|
||||||
|
<Image
|
||||||
|
style={styles.image}
|
||||||
|
source={{ uri: item.image }}
|
||||||
|
resizeMode="stretch"
|
||||||
|
/>
|
||||||
|
<Text style={styles.name}>{item.name}</Text>
|
||||||
|
</View>
|
||||||
|
</Animated.View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
storeCard: {
|
||||||
|
flex:1,
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: {
|
||||||
|
width: 0,
|
||||||
|
height: 3,
|
||||||
|
},
|
||||||
|
shadowOpacity: 0.29,
|
||||||
|
shadowRadius: 4.65,
|
||||||
|
elevation: 3,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor:'white',
|
||||||
|
marginVertical: MARGIN,
|
||||||
|
width: CARD_WIDTH,
|
||||||
|
height: CARD_HEIGHT,
|
||||||
|
position: 'relative',
|
||||||
|
borderRadius: 10,
|
||||||
|
},
|
||||||
|
image: {
|
||||||
|
width:190,
|
||||||
|
height:120,
|
||||||
|
borderRadius:10
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
fontSize:20,
|
||||||
|
color: 'black',
|
||||||
|
textAlign:'center'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Store;
|
|
@ -0,0 +1,78 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { SafeAreaView, Text, Image, Alert, Linking, TouchableOpacity, StyleSheet, View, TextInput, Platform, ScrollView } from 'react-native';
|
||||||
|
import { colors } from '../assets/styles/colors-theme';
|
||||||
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
|
import { width, height } from '../services/screen';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import Icon from 'react-native-vector-icons/dist/AntDesign';
|
||||||
|
import GoogleIcon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
import FontAwesome from 'react-native-vector-icons/dist/FontAwesome5'
|
||||||
|
import FastImage from 'react-native-fast-image'
|
||||||
|
import { getStatusBarHeight } from "react-native-safearea-height";
|
||||||
|
import { color } from 'react-native-reanimated';
|
||||||
|
import { images } from '../assets/images/imageIndex'
|
||||||
|
Icon.loadFont();
|
||||||
|
GoogleIcon.loadFont()
|
||||||
|
const TitleBar = inject("appStore")(observer(class TitleBar extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
userInfoPressAction() {
|
||||||
|
if (this.store.logined) {
|
||||||
|
this.props.navigation.navigate('Profile')
|
||||||
|
} else {
|
||||||
|
this.props.navigation.navigate('Signin')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={{
|
||||||
|
width: width,
|
||||||
|
height: 50,
|
||||||
|
marginTop: this.props.inside ? 20 : Platform.OS == 'ios' ? getStatusBarHeight() : getStatusBarHeight() + 15,
|
||||||
|
}}>
|
||||||
|
<View style={{ flexDirection: "row", flex: 1, height: 30 }}>
|
||||||
|
{this.props.back ? (<TouchableOpacity style={{ flex: 0.2, justifyContent: 'flex-start', }}
|
||||||
|
onPress={() => { this.props.navigation.goBack() }}>
|
||||||
|
<Icon name='arrowleft' size={20} color={colors.fontColor} style={{ marginLeft: 30 }} />
|
||||||
|
</TouchableOpacity>) : (<View style={{ flex: 0.2 }} />)}
|
||||||
|
|
||||||
|
<View style={{ flex: 0.6, justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
<Image source={images.titleBarLogo} style={{ height: 50, }} resizeMode='contain' />
|
||||||
|
</View>
|
||||||
|
{this.props.user ? (
|
||||||
|
<TouchableOpacity style={{ flex: 0.2, height: 50, justifyContent: 'center', alignItems: 'flex-end', }}
|
||||||
|
onPress={() => this.userInfoPressAction()}
|
||||||
|
>
|
||||||
|
<GoogleIcon name='account' size={35} color={colors.fontColor} style={{ marginRight: 20 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
) : (<View style={{ flex: 0.2 }} />)}
|
||||||
|
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
const styles = StyleSheet.flatten({
|
||||||
|
|
||||||
|
home_rectanglecd25b34b: {
|
||||||
|
opacity: 1,
|
||||||
|
flex: 1,
|
||||||
|
paddingVertical: 10,
|
||||||
|
marginTop: 50,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default TitleBar
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
const api = {
|
||||||
|
alarm: 'alarm.cgi'
|
||||||
|
}
|
||||||
|
export default api
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { toInteger } from 'lodash';
|
||||||
|
import api from './api'
|
||||||
|
import Common from './common';
|
||||||
|
import config from './config'
|
||||||
|
import Fetch from './fetch'
|
||||||
|
import moment from 'moment';
|
||||||
|
const common = new Common()
|
||||||
|
class CamMethods {
|
||||||
|
|
||||||
|
|
||||||
|
async get_states_of_Alarm_Output_Channels() {
|
||||||
|
const fetch = new Fetch()
|
||||||
|
const parms = {
|
||||||
|
'action': 'getOutState'
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const data = await fetch.callGetApi(config.host + api.alarm, parms)
|
||||||
|
console.log(data)
|
||||||
|
var channel = data.replace('result=', '')
|
||||||
|
channel = await common.convertToBinary(toInteger(channel))
|
||||||
|
console.log('channel: ' + channel)
|
||||||
|
if (channel !== '0') {
|
||||||
|
console.log('something happened')
|
||||||
|
const channels = await common.checkWhichChannelsIsTrue('11')
|
||||||
|
const result = {
|
||||||
|
id: moment().format('DDMMYYYYhhmmss').toString(),
|
||||||
|
date: moment().format('DD/MM/YYYY hh:mm:ss').toString(),
|
||||||
|
channels: channels,
|
||||||
|
detection: await common.detectionHandler(channels),
|
||||||
|
}
|
||||||
|
console.log(result)
|
||||||
|
//return the result
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
console.log('safe')
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CamMethods
|
|
@ -0,0 +1,57 @@
|
||||||
|
class Common {
|
||||||
|
// program to convert decimal to binary
|
||||||
|
convertToBinary(x) {
|
||||||
|
if (x !== 1) {
|
||||||
|
let bin = 0;
|
||||||
|
let rem, i = 1, step = 1;
|
||||||
|
while (x != 0) {
|
||||||
|
rem = x % 2;
|
||||||
|
x = parseInt(x / 2);
|
||||||
|
bin = bin + rem * i;
|
||||||
|
i = i * 10;
|
||||||
|
}
|
||||||
|
console.log(String(bin))
|
||||||
|
return String(bin)
|
||||||
|
} else {
|
||||||
|
console.log('01')
|
||||||
|
return '01'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get which channels
|
||||||
|
async checkWhichChannelsIsTrue(bin) {
|
||||||
|
var channels = [];
|
||||||
|
|
||||||
|
for (let index = 0; index < bin.length; index++) {
|
||||||
|
if (bin[index] === '1') {
|
||||||
|
channels.push(index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return await Promise.all(channels)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1 = Fall Detection, 2 = N/A */
|
||||||
|
async detectionHandler(channels) {
|
||||||
|
var detection = ''
|
||||||
|
for (var i = 0; i < channels.length; i++) {
|
||||||
|
|
||||||
|
switch (channels[i]) {
|
||||||
|
case 1:
|
||||||
|
detection += 'Fall Detection,'
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
detection += ' N/A,'
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detection = detection.slice(0, -1);
|
||||||
|
detection = detection.substring(0, 0) + detection.substring(1, detection.length);
|
||||||
|
return detection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default Common
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'admin888888',
|
||||||
|
host: 'http://tsct.ddns.net:81/cgi-bin/',
|
||||||
|
}
|
||||||
|
export default config
|
|
@ -0,0 +1,26 @@
|
||||||
|
import digestFetch from 'react-native-digest-fetch';
|
||||||
|
import config from './config';
|
||||||
|
class Fetch {
|
||||||
|
|
||||||
|
async callGetApi(url, params) {
|
||||||
|
try {
|
||||||
|
const response = await digestFetch(url + "?" + new URLSearchParams(params), {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
username: config.username,
|
||||||
|
password: config.password,
|
||||||
|
});
|
||||||
|
const data = await response.text();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Fetch
|
|
@ -0,0 +1,169 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
ScrollView
|
||||||
|
} from 'react-native';
|
||||||
|
var _ = require('lodash');
|
||||||
|
import { width, height } from '../../services/screen';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
||||||
|
import ListTitle from '../../components/listTitle';
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { images } from '../../assets/images/imageIndex';
|
||||||
|
import RenderProducts from '../../components/renderProducts';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import moment from 'moment';
|
||||||
|
import ProgressiveFastImage from "@freakycoder/react-native-progressive-fast-image";
|
||||||
|
import CamMethods from './api/camMethods';
|
||||||
|
import Common from './api/common';
|
||||||
|
const camMethods = new CamMethods()
|
||||||
|
const common = new Common()
|
||||||
|
|
||||||
|
const alarmInfoFakeData = [
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-16 12:08:53',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-16 11:42:14',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-16 11:41:32',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-16 11:41:26',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-16 09:44:04',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-16 07:47:05',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:47:14',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:47:08',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:44:49',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:43:19',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:42:49',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:40:47',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:28:38',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:28:34',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'Fall Detection',
|
||||||
|
'time': '2023-05-15 15:28:15',
|
||||||
|
'Channel': '1'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const Testui = inject("appStore")(observer(class Testui extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc, justifyContent: 'center', alignItems: 'center' }} source={require('../../assets/images/background.png')} >
|
||||||
|
|
||||||
|
<TouchableOpacity onPress={() => { camMethods.get_states_of_Alarm_Output_Channels() }}>
|
||||||
|
<Text>
|
||||||
|
get channel
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity onPress={() => { common.convertToBinary(1) }}>
|
||||||
|
<Text>
|
||||||
|
test
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -30, fontSize: 18, },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Testui
|
|
@ -0,0 +1,260 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
ScrollView
|
||||||
|
} from 'react-native';
|
||||||
|
var _ = require('lodash');
|
||||||
|
import { width, height } from '../../services/screen';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
||||||
|
import ListTitle from '../../components/listTitle';
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { images } from '../../assets/images/imageIndex';
|
||||||
|
import RenderProducts from '../../components/renderProducts';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import moment from 'moment';
|
||||||
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
|
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
import ProgressiveFastImage from "@freakycoder/react-native-progressive-fast-image";
|
||||||
|
const Coupon = inject("appStore")(observer(class Coupon extends React.Component {
|
||||||
|
|
||||||
|
selected = 'all'
|
||||||
|
coupons = []
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
selected: observable,
|
||||||
|
coupons: observable
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
await this.store.getCoupons(this)
|
||||||
|
await this.couponsHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
selectCatAction(id) {
|
||||||
|
this.selected = id
|
||||||
|
this.couponsHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFilter() {
|
||||||
|
const filter = [
|
||||||
|
{ id: 'all', name: '全部' }, { id: 'usable', name: '可使用' },
|
||||||
|
{ id: 'used', name: '已使用' }, { id: 'expired', name: '已過期' },
|
||||||
|
{ id: 'willUsable', name: '將能使用' }
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<View style={{ height: s(30), width: width, backgroundColor: colors.catColor, marginTop: 10 }}>
|
||||||
|
<ScrollView horizontal={true}>
|
||||||
|
{filter.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={{ height: s(30), justifyContent: 'center', backgroundColor: this.selected == item.id ? '#F9F4EE' : colors.catColor }}
|
||||||
|
onPress={() => { this.selectCatAction(item.id) }}>
|
||||||
|
<Text style={{ color: colors.fontColor, marginHorizontal: 20 }}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
couponStatusLabelHandler(item) {
|
||||||
|
if (moment(item.end, 'YYYY-MM-DD').toDate() < moment().toDate()) {
|
||||||
|
return '已過期'
|
||||||
|
} else if (moment(item.start, 'YYYY-MM-DD').toDate() > moment().toDate()) {
|
||||||
|
return '將能使用'
|
||||||
|
} else if (item.used >= item.personUsed) {
|
||||||
|
return '已使用'
|
||||||
|
} else if (moment(item.end, 'YYYY-MM-DD').toDate() > moment().toDate() &&
|
||||||
|
moment(item.start, 'YYYY-MM-DD').toDate() <= moment().toDate() &&
|
||||||
|
item.used < item.personUsed) {
|
||||||
|
return '可使用'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
couponsHandler() {
|
||||||
|
this.coupons = []
|
||||||
|
switch (this.selected) {
|
||||||
|
case 'all':
|
||||||
|
this.store.coupons.map((item, index) => {
|
||||||
|
this.coupons.push(item)
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'usable':
|
||||||
|
this.store.coupons.map((item, index) => {
|
||||||
|
if (moment(item.end, 'YYYY-MM-DD').toDate() > moment().toDate() &&
|
||||||
|
moment(item.start, 'YYYY-MM-DD').toDate() <= moment().toDate() &&
|
||||||
|
item.used < item.personUsed) {
|
||||||
|
this.coupons.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'used':
|
||||||
|
this.store.coupons.map((item, index) => {
|
||||||
|
if (item.used >= item.personUsed) {
|
||||||
|
this.coupons.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'expired':
|
||||||
|
this.store.coupons.map((item, index) => {
|
||||||
|
if (moment(item.end, 'YYYY-MM-DD').toDate() < moment().toDate()) {
|
||||||
|
this.coupons.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'willUsable':
|
||||||
|
this.store.coupons.map((item, index) => {
|
||||||
|
if (moment(item.end, 'YYYY-MM-DD').toDate() < moment().toDate()) {
|
||||||
|
this.coupons.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
renderStatusLabel(item) {
|
||||||
|
return (
|
||||||
|
<View style={{ marginRight: 10, marginTop: 10, backgroundColor: '#FFFFFFA0', borderRadius: 7 }}>
|
||||||
|
<Text style={{ marginHorizontal: 4, marginVertical: 2, fontSize: s(10), color: colors.textColor }}>
|
||||||
|
{this.couponStatusLabelHandler(item)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCouponList() {
|
||||||
|
if (this.coupons.length > 0) {
|
||||||
|
return (
|
||||||
|
this.coupons.map((item, index) => {
|
||||||
|
return this.renderCoupons(item)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
couponTypeHandler(item) {
|
||||||
|
if (item.discountAmount > 0) {
|
||||||
|
return '$' + item.discountAmount + "現金券"
|
||||||
|
} else {
|
||||||
|
return item.discountRate * 100 + "%折扣優惠"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCouponButtons(item) {
|
||||||
|
return (
|
||||||
|
<View style={{ width: '80%', height: s(40), backgroundColor: colors.textColor, justifyContent: 'center', alignItems: 'center', borderRadius: s(10) }}>
|
||||||
|
<Text style={{ color: 'white', fontWeight: '400' }}>
|
||||||
|
{this.couponTypeHandler(item)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCoupons(item) {
|
||||||
|
return (
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginVertical: 10 }}>
|
||||||
|
<TouchableOpacity style={{ width: s(300), height: s(150), flexDirection: 'row' }}
|
||||||
|
onPress={() => { this.props.navigation.navigate('CouponDetails', { data: item }) }}>
|
||||||
|
<View style={{ flex: 0.6 }}>
|
||||||
|
{item.hasOwnProperty('imgURL') ? (<ProgressiveFastImage style={{ width: '100%', height: '100%', borderTopLeftRadius: s(20), borderBottomLeftRadius: s(20) }} source={{uri:item.imgURL}} />) :
|
||||||
|
(<ProgressiveFastImage style={{ width: '100%', height: '100%', borderTopLeftRadius: s(20), borderBottomLeftRadius: s(20) }} source={images.coupon} />)}
|
||||||
|
|
||||||
|
</View>
|
||||||
|
<View style={{ width: s(140), height: s(150), backgroundColor: colors.couponbgc, borderRadius: s(20), position: 'absolute', right: 0 }}>
|
||||||
|
<View style={{ width: '100%', alignItems: 'flex-end' }}>
|
||||||
|
{this.renderStatusLabel(item)}
|
||||||
|
</View>
|
||||||
|
<View style={{ width: '100%', alignItems: 'center', marginTop: 5 }}>
|
||||||
|
<Text style={{ fontSize: s(10), color: colors.textColor }}>
|
||||||
|
{moment(item.start, 'YYYY-MM-DD').format('DD/MM/YYYY') + " - " + moment(item.end, 'YYYY-MM-DD').format('DD/MM/YYYY')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{ width: '100%', height: s(40), alignItems: 'center', marginTop: 5, }}>
|
||||||
|
<Text style={{ fontSize: s(14), color: colors.textColor, marginHorizontal: 10, fontWeight: '500' }} numberOfLines={2}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{ width: '100%', height: s(40), alignItems: 'center', marginTop: 5, }}>
|
||||||
|
{this.renderCouponButtons(item)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Image source={images.titleLogo} style={{ position: 'absolute', bottom: s(-10), right: s(20) }} />
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={true} user={false} />
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30, }}>
|
||||||
|
<Text style={{ fontWeight: '800', color: colors.fontColor, fontSize: 15 }}>
|
||||||
|
{I18n.t('cartCoupon')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
{this.renderFilter()}
|
||||||
|
|
||||||
|
<ScrollView style={{ marginVertical: 10 }}>
|
||||||
|
{this.renderCouponList()}
|
||||||
|
</ScrollView>
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.mainColor }}
|
||||||
|
position="center"
|
||||||
|
positionValue={100}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -30, fontSize: 18, },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Coupon
|
|
@ -0,0 +1,153 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
ScrollView
|
||||||
|
} from 'react-native';
|
||||||
|
var _ = require('lodash');
|
||||||
|
import { width, height } from '../../services/screen';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
||||||
|
import ListTitle from '../../components/listTitle';
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { images } from '../../assets/images/imageIndex';
|
||||||
|
import RenderProducts from '../../components/renderProducts';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import moment from 'moment';
|
||||||
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
|
import CustomLoginButton from '../../components/customLoginButton'
|
||||||
|
import ProgressiveFastImage from "@freakycoder/react-native-progressive-fast-image";
|
||||||
|
const CouponDetails = inject("appStore")(observer(class CouponDetails extends React.Component {
|
||||||
|
|
||||||
|
data = this.props.route.params.data
|
||||||
|
couponText = '<ul><li><p>條款及細則</p><p>・憑此券於⾹港SOYA 3.3分店使⽤。</p><p>・此券有效期由2022年2⽉1⽇⾄2023年1⽉31⽇。</p><p>・此券不能兌換現⾦及找贖。</p><p>・此券如有過期即作廢無效,恕不補發。</p><p>・付款前請先出示此券。</p><p>・此券只可使⽤⼀次。</p><p>・此券需於有效期內使⽤,逾期作廢。</p><p>・資料及圖⽚由商⼾提供,只供參考。</p><p>・如分店地址有任何更改,恕不另⾏通知。</p><p>・如有任何爭議,SOYA 3.3將保留最終決定權。</p></li></ul>'
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
couponTypeHandler(item) {
|
||||||
|
if (item.discountAmount > 0) {
|
||||||
|
return '$' + item.discountAmount + "現金券"
|
||||||
|
} else {
|
||||||
|
return item.discountRate * 100 + "%折扣優惠"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
renderImage() {
|
||||||
|
return (
|
||||||
|
<View style={{ justifyContent: 'center', alignItems: 'center', width: width, marginTop: 20 }}>
|
||||||
|
{this.data.hasOwnProperty('imgURL') ? (<Image source={{ uri: this.data.imgURL }} style={{ width: width - 40, height: s(200), borderRadius: s(30) }} resizeMode='contain' />) :
|
||||||
|
(<Image source={images.coupon} style={{ width: width - 40, height: s(200), borderRadius: s(30) }} resizeMode='contain' />)}
|
||||||
|
|
||||||
|
</View>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
renderContent() {
|
||||||
|
return (
|
||||||
|
<View style={{ backgroundColor: '#FFC76F', marginHorizontal: 20, marginVertical: 30, borderRadius: width / 20 }}>
|
||||||
|
<View style={{ margin: 20, marginBottom: 50, }}>
|
||||||
|
<Text style={{ color: colors.fontColor, fontSize: 11 }}>
|
||||||
|
{I18n.t('offerPeriod') + ": " + moment(this.data.start, 'YYYY-MM-DD').format('DD/MM/YYYY') + " - " + moment(this.data.end, 'YYYY-MM-DD').format('DD/MM/YYYY')}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: colors.fontColor, fontSize: 15, fontWeight: '800', marginTop: 5 }}>
|
||||||
|
{this.data.name}
|
||||||
|
</Text>
|
||||||
|
<View style={{ width: '100%', alignItems: 'center', marginVertical: 20 }}>
|
||||||
|
<View style={{ width: '90%', height: s(50), borderRadius: s(10), backgroundColor: colors.fontColor, justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
<Text style={{ color: 'white', fontSize: 15, fontWeight: '800', marginTop: 5 }}>
|
||||||
|
{this.couponTypeHandler(this.data)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
<HTMLView
|
||||||
|
style={{ marginTop: 10, }}
|
||||||
|
value={this.couponText}
|
||||||
|
stylesheet={styles.content}
|
||||||
|
textComponentProps={{ style: { color: colors.fontColor, fontSize: 11, marginTop: -40 } }}
|
||||||
|
/>
|
||||||
|
<View style={{ width: '100%', alignItems: 'center', marginVertical: 20 }}>
|
||||||
|
<QRCode
|
||||||
|
value={this.store.loginUserData?.id + "," + this.data.number}
|
||||||
|
size={140}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Image source={images.titleLogo} style={{ position: 'absolute', bottom: -20, right: 0 }} />
|
||||||
|
</View >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={true} user={true} />
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30, }}>
|
||||||
|
<Text style={{ fontWeight: '800', color: colors.fontColor, fontSize: 15 }}>
|
||||||
|
{I18n.t('cartCoupon')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView>
|
||||||
|
{this.renderImage()}
|
||||||
|
{this.renderContent()}
|
||||||
|
</ScrollView>
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.mainColor }}
|
||||||
|
position="center"
|
||||||
|
positionValue={100}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -120, fontSize: 12, },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default CouponDetails
|
|
@ -0,0 +1,51 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { ScrollView } from 'react-native';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import Main from '../main';
|
||||||
|
|
||||||
|
describe('Main', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<Main />);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper.unmount();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a ScrollView component', () => {
|
||||||
|
expect(wrapper.find(ScrollView)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render the news list', () => {
|
||||||
|
const newsList = wrapper.instance().renderNewsList();
|
||||||
|
expect(newsList.props.style.width).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a news item', () => {
|
||||||
|
const item = {
|
||||||
|
imageURL: 'https://example.com/image.jpg',
|
||||||
|
date: '2022-01-01',
|
||||||
|
title: 'Example News',
|
||||||
|
content: '<p>Example content</p>'
|
||||||
|
};
|
||||||
|
const newsItem = wrapper.instance().renderNews(item);
|
||||||
|
expect(newsItem.props.style.height).toBeDefined();
|
||||||
|
expect(newsItem.props.style.width).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render the banner list', () => {
|
||||||
|
const bannerList = wrapper.instance().renderBannerList();
|
||||||
|
expect(bannerList.props.style.width).toBeDefined();
|
||||||
|
expect(bannerList.props.style.justifyContent).toEqual('center');
|
||||||
|
expect(bannerList.props.style.alignItems).toEqual('center');
|
||||||
|
expect(bannerList.props.style.marginTop).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render the recommend list', () => {
|
||||||
|
const recommendList = wrapper.instance().renderRecommendList();
|
||||||
|
expect(recommendList.props.style.width).toBeDefined();
|
||||||
|
expect(recommendList.props.style.marginTop).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,219 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
ScrollView
|
||||||
|
} from 'react-native';
|
||||||
|
var _ = require('lodash');
|
||||||
|
import { width, height } from '../../services/screen';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
||||||
|
import ListTitle from '../../components/listTitle';
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { images } from '../../assets/images/imageIndex';
|
||||||
|
import RenderProducts from '../../components/renderProducts';
|
||||||
|
import ProgressiveFastImage from "@freakycoder/react-native-progressive-fast-image";
|
||||||
|
const Main = inject("appStore")(observer(class Main extends React.Component {
|
||||||
|
|
||||||
|
activeSlide = 0;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
activeSlide: observable
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
renderBanner({ item, index }) {
|
||||||
|
return (
|
||||||
|
<View style={{}}>
|
||||||
|
<ProgressiveFastImage
|
||||||
|
resizeMode='cover'
|
||||||
|
source={{ uri: item.img_url }}
|
||||||
|
style={{ width: width - 40, height: width / 2.5, borderRadius: 30 }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get pagination() {
|
||||||
|
return (
|
||||||
|
<Pagination
|
||||||
|
dotsLength={this.store.topBanners.length}
|
||||||
|
activeDotIndex={this.activeSlide}
|
||||||
|
containerStyle={{ marginTop: -20 }}
|
||||||
|
dotStyle={{
|
||||||
|
width: 10,
|
||||||
|
height: 5,
|
||||||
|
borderRadius: 5,
|
||||||
|
marginHorizontal: 1,
|
||||||
|
backgroundColor: 'black'
|
||||||
|
}}
|
||||||
|
dotContainerStyle={
|
||||||
|
{ marginHorizontal: 0.1 }
|
||||||
|
}
|
||||||
|
inactiveDotStyle={
|
||||||
|
{
|
||||||
|
// Define styles for inactive dots here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inactiveDotOpacity={0.4}
|
||||||
|
inactiveDotScale={0.6}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
renderRecommend(item) {
|
||||||
|
return (
|
||||||
|
<RenderProducts item={item} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRecommendList() {
|
||||||
|
if (this.store.recommendProducts.length > 0) {
|
||||||
|
return (
|
||||||
|
<View style={{ width: width, marginTop: 20,marginBottom:20}}>
|
||||||
|
<ListTitle title={I18n.t('homeFeatureProducts')} />
|
||||||
|
<View style={{ height: 20 }} />
|
||||||
|
{this.store.recommendProducts.map((items, index, array) => {
|
||||||
|
const newRow = !(index % 2);
|
||||||
|
const secondItem = index + 1 < array.length ? array[index + 1] : undefined;
|
||||||
|
return (
|
||||||
|
<View style={{ marginHorizontal: 10, }}>
|
||||||
|
<Row key={items.id} style={{ width: '100%', justifyContent: 'space-between', marginTop: 10 }} >
|
||||||
|
{!!newRow ? (
|
||||||
|
<>
|
||||||
|
{this.renderRecommend(items)}
|
||||||
|
{secondItem == undefined ? (<View style={{ width: s(170), height: s(210) }} />) : (this.renderRecommend(secondItem))}
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
</Row>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderBannerList() {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: width,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: 40,
|
||||||
|
|
||||||
|
}}>
|
||||||
|
<Carousel
|
||||||
|
data={this.store.topBanners}
|
||||||
|
renderItem={this.renderBanner}
|
||||||
|
onSnapToItem={index => {
|
||||||
|
this.activeSlide = index;
|
||||||
|
}}
|
||||||
|
sliderWidth={width}
|
||||||
|
itemWidth={width - 40}
|
||||||
|
|
||||||
|
|
||||||
|
/>
|
||||||
|
{this.pagination}
|
||||||
|
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNews(item) {
|
||||||
|
console.log(item)
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={{ height: s(280), width: s(150), marginLeft: 10, borderRadius: 15 }}
|
||||||
|
onPress={() => { this.props.navigation.navigate('NewsDetails', { data: item }) }}>
|
||||||
|
<View style={{ width: '100%', height: '70%' }}>
|
||||||
|
<ProgressiveFastImage source={{ uri: item.imageURL }} style={{ width: '100%', height: '100%', borderTopLeftRadius: 15, borderTopRightRadius: 15 }} />
|
||||||
|
</View>
|
||||||
|
<View style={{ position: 'absolute', width: '100%', height: '35%', backgroundColor: colors.listItemsbgc, bottom: 0, borderRadius: 15 }}>
|
||||||
|
<View style={{ marginVertical: 5, marginHorizontal: 10 }}>
|
||||||
|
<Text style={{ fontSize: 11, color: colors.fontColor }}>
|
||||||
|
{item.date}
|
||||||
|
</Text>
|
||||||
|
<Text numberOfLines={2} style={{ fontSize: 13, color: colors.fontColor, marginTop: 3, fontWeight: '800' }}>
|
||||||
|
{item.title}
|
||||||
|
</Text>
|
||||||
|
<Text numberOfLines={2} style={{ fontSize: 11, color: colors.fontColor, marginTop: 5, }}>
|
||||||
|
{item.content.replace(/(<([^>]+)>)/ig, "")}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNewsList() {
|
||||||
|
return (
|
||||||
|
<View style={{ width: width }}>
|
||||||
|
<ListTitle title={I18n.t('news')} onPress = {()=>{this.props.navigation.navigate('NewsList')}} />
|
||||||
|
<ScrollView horizontal={true} style={{ marginTop: 50 }}>
|
||||||
|
{this.store.news.map((item, index) => {
|
||||||
|
return (
|
||||||
|
this.renderNews(item)
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={false} user={true} />
|
||||||
|
<ScrollView style = {{marginTop:15}}>
|
||||||
|
{this.renderBannerList()}
|
||||||
|
{this.renderNewsList()}
|
||||||
|
{this.renderRecommendList()}
|
||||||
|
</ScrollView>
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.mainColor }}
|
||||||
|
position="center"
|
||||||
|
positionValue={100}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Main
|
|
@ -0,0 +1,177 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
ScrollView
|
||||||
|
} from 'react-native';
|
||||||
|
var _ = require('lodash');
|
||||||
|
import { width, height } from '../../services/screen';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
||||||
|
import ListTitle from '../../components/listTitle';
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { images } from '../../assets/images/imageIndex';
|
||||||
|
import RenderProducts from '../../components/renderProducts';
|
||||||
|
const Menu = inject("appStore")(observer(class Menu extends React.Component {
|
||||||
|
|
||||||
|
activeSlide = 0;
|
||||||
|
selected = null;
|
||||||
|
subCatSelected = null;
|
||||||
|
subcategory = []
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
activeSlide: observable,
|
||||||
|
selected: observable,
|
||||||
|
subCatSelected: observable,
|
||||||
|
subcategory: observable
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
this.selectCatAction(this.store.mainCategories[0].id, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectCatAction(id, parent) {
|
||||||
|
if (parent) {
|
||||||
|
this.selected = id
|
||||||
|
this.store.getcategoriesProducts(this.selected, this)
|
||||||
|
this.subCatSelected = this.store.mainCategories[this.store.mainCategories.findIndex(e => e.id == id)].subCat[0].id
|
||||||
|
this.subcategory = this.store.mainCategories[this.store.mainCategories.findIndex(e => e.id == id)].subCat
|
||||||
|
console.log(this.subCatSelected)
|
||||||
|
} else {
|
||||||
|
this.subCatSelected = id
|
||||||
|
this.store.getcategoriesProducts(this.subCatSelected, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCategory() {
|
||||||
|
return (
|
||||||
|
<View style={{ height: s(30), width: width, backgroundColor: colors.catColor, marginTop: 10 }}>
|
||||||
|
<ScrollView horizontal={true}>
|
||||||
|
{this.store.mainCategories.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={{ height: s(30), justifyContent: 'center', backgroundColor: this.selected == item.id ? '#F9F4EE' : colors.catColor }}
|
||||||
|
onPress={() => { this.selectCatAction(item.id, item.parent === '') }}>
|
||||||
|
<Text style={{ color: colors.fontColor, marginHorizontal: 20 }}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSubCategory() {
|
||||||
|
return (
|
||||||
|
<View style={{ height: s(30), width: width, backgroundColor: colors.catColor,}}>
|
||||||
|
<ScrollView horizontal={true}>
|
||||||
|
{this.subcategory.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={{ height: s(30), justifyContent: 'center', backgroundColor: this.subCatSelected == item.id ? '#F9F4EE' : colors.catColor }}
|
||||||
|
onPress={() => { this.selectCatAction(item.id, item.parent === '') }}>
|
||||||
|
<Text style={{ color: colors.fontColor, marginHorizontal: 20 }}>
|
||||||
|
{item.name.replace(/(\r\n|\n|\r)/gm, "")}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
renderProduct(item) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RenderProducts item={item} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderProductsList() {
|
||||||
|
if (this.store.allProducts.length > 0) {
|
||||||
|
return (
|
||||||
|
<View style={{ width: width, marginTop: 20 }}>
|
||||||
|
{/* <View style={{ justifyContent: 'flex-start', alignItems: 'center', flexDirection: 'row', height: 20 ,marginLeft:20}}>
|
||||||
|
<Image source={images.titleLogo} />
|
||||||
|
<Text style={{ color: colors.fontColor, fontWeight: '800', marginLeft: 10 }}>
|
||||||
|
{I18n.t('homeFeatureProducts')}
|
||||||
|
</Text>
|
||||||
|
</View> */}
|
||||||
|
{/* <ListTitle title={I18n.t('homeFeatureProducts')} /> */}
|
||||||
|
<View style={{ height: 20 }} />
|
||||||
|
{this.store.allProducts.map((items, index, array) => {
|
||||||
|
const newRow = !(index % 2);
|
||||||
|
const secondItem = index + 1 < array.length ? array[index + 1] : undefined;
|
||||||
|
return (
|
||||||
|
<View style={{ marginHorizontal: 10, }}>
|
||||||
|
<Row key={items.id} style={{ width: '100%', justifyContent: 'space-between', marginTop: 10 }} >
|
||||||
|
{!!newRow ? (
|
||||||
|
<>
|
||||||
|
{this.renderProduct(items)}
|
||||||
|
{secondItem == undefined ? (<View style={{ width: s(170), height: s(210) }} />) : (this.renderProduct(secondItem))}
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
</Row>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={false} user={true} />
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30, }}>
|
||||||
|
<Text style={{ fontWeight: '800', color: colors.fontColor, fontSize: 15 }}>
|
||||||
|
{I18n.t('menu')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
{this.renderCategory()}
|
||||||
|
{this.renderSubCategory()}
|
||||||
|
<ScrollView>
|
||||||
|
{this.renderProductsList()}
|
||||||
|
</ScrollView>
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.mainColor }}
|
||||||
|
position="center"
|
||||||
|
positionValue={100}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Menu
|
|
@ -0,0 +1,122 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
ScrollView
|
||||||
|
} from 'react-native';
|
||||||
|
var _ = require('lodash');
|
||||||
|
import { width, height } from '../../services/screen';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
||||||
|
import ListTitle from '../../components/listTitle';
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { images } from '../../assets/images/imageIndex';
|
||||||
|
import RenderProducts from '../../components/renderProducts';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import moment from 'moment';
|
||||||
|
import ProgressiveFastImage from "@freakycoder/react-native-progressive-fast-image";
|
||||||
|
const NewsDetails = inject("appStore")(observer(class NewsDetails extends React.Component {
|
||||||
|
|
||||||
|
data = this.props.route.params.data
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNewsImage() {
|
||||||
|
return (
|
||||||
|
<View style={{ justifyContent: 'center', alignItems: 'center', width: width, marginTop: 20 }}>
|
||||||
|
<ProgressiveFastImage source={{ uri: this.data.imageURL }} style={{ width: width - 40, height:s(200), borderRadius: s(30) }} resizeMode = 'contain' />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
renderContent() {
|
||||||
|
return (
|
||||||
|
<View style={{ backgroundColor: '#FFC76F', marginHorizontal: 20, marginVertical: 30, borderRadius: width / 20 }}>
|
||||||
|
<View style={{ margin: 20, marginBottom: 50, }}>
|
||||||
|
<Text style={{ color: colors.fontColor }}>
|
||||||
|
{moment(this.data.date).format('YYYY/MM/DD').toString('DD/MM/YYYY')}
|
||||||
|
</Text>
|
||||||
|
<HTMLView
|
||||||
|
style={{ marginTop: 5, fontColor: colors.fontColor }}
|
||||||
|
value={this.data.content}
|
||||||
|
stylesheet={styles.content}
|
||||||
|
textComponentProps={{ style: { color: colors.fontColor } }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Image source={images.titleLogo} style={{ position: 'absolute', bottom: -20, right: 0 }} />
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={true} user={true} />
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30, }}>
|
||||||
|
<Text style={{ fontWeight: '800', color: colors.fontColor, fontSize: 15 }}>
|
||||||
|
{I18n.t('news')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView>
|
||||||
|
{this.renderNewsImage()}
|
||||||
|
{this.renderContent()}
|
||||||
|
</ScrollView>
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.mainColor }}
|
||||||
|
position="center"
|
||||||
|
positionValue={100}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -30, fontSize: 18, },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default NewsDetails
|
|
@ -0,0 +1,131 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
ScrollView
|
||||||
|
} from 'react-native';
|
||||||
|
var _ = require('lodash');
|
||||||
|
import { width, height } from '../../services/screen';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
||||||
|
import ListTitle from '../../components/listTitle';
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { images } from '../../assets/images/imageIndex';
|
||||||
|
import RenderProducts from '../../components/renderProducts';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import moment from 'moment';
|
||||||
|
import ProgressiveFastImage from "@freakycoder/react-native-progressive-fast-image";
|
||||||
|
const NewsList = inject("appStore")(observer(class NewsList extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
|
||||||
|
}
|
||||||
|
renderNews(item) {
|
||||||
|
console.log(item)
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={{ height: s(250), width:width-40, borderRadius: 15,marginTop:20 }}
|
||||||
|
onPress={() => { this.props.navigation.navigate('NewsDetails', { data: item }) }}>
|
||||||
|
<View style={{ width: '100%', height: '65%' }}>
|
||||||
|
<ProgressiveFastImage source={{ uri: item.imageURL }} style={{ width: '100%', height: '100%', borderTopLeftRadius: 15, borderTopRightRadius: 15 }} />
|
||||||
|
</View>
|
||||||
|
<View style={{ position: 'absolute', width: '100%', height: '40%', backgroundColor: colors.listItemsbgc, bottom: 0, borderRadius: 15 }}>
|
||||||
|
<View style={{ marginVertical: 5, marginHorizontal: 10 }}>
|
||||||
|
<Text style={{ fontSize: 11, color: colors.fontColor }}>
|
||||||
|
{item.date}
|
||||||
|
</Text>
|
||||||
|
<Text numberOfLines={2} style={{ fontSize: 13, color: colors.fontColor, marginTop: 3, fontWeight: '800' }}>
|
||||||
|
{item.title}
|
||||||
|
</Text>
|
||||||
|
<Text numberOfLines={3} style={{ fontSize: 11, color: colors.fontColor, marginTop: 5, }}>
|
||||||
|
{item.content.replace(/(<([^>]+)>)/ig, "")}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Image source={images.titleLogo} style={{ position: 'absolute', top: -30, right: 0 }} />
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
renderNewsList() {
|
||||||
|
return (
|
||||||
|
<View style={{ width: width ,alignItems:'center'}}>
|
||||||
|
|
||||||
|
{this.store.news.map((item, index) => {
|
||||||
|
return (
|
||||||
|
this.renderNews(item)
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={true} user={true} />
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30, }}>
|
||||||
|
<Text style={{ fontWeight: '800', color: colors.fontColor, fontSize: 15 }}>
|
||||||
|
{I18n.t('news')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView>
|
||||||
|
{this.renderNewsList()}
|
||||||
|
</ScrollView>
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.mainColor }}
|
||||||
|
position="center"
|
||||||
|
positionValue={100}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -30, fontSize: 18, },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default NewsList
|
|
@ -0,0 +1,152 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
ScrollView
|
||||||
|
} from 'react-native';
|
||||||
|
var _ = require('lodash');
|
||||||
|
import { width, height } from '../../services/screen';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import { Col, Grid, Row } from "react-native-easy-grid";
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
||||||
|
import ListTitle from '../../components/listTitle';
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import { images } from '../../assets/images/imageIndex';
|
||||||
|
import RenderProducts from '../../components/renderProducts';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import moment from 'moment';
|
||||||
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
|
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
const Profile = inject("appStore")(observer(class Profile extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore;
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUserInfo() {
|
||||||
|
return (
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30 }}>
|
||||||
|
<Text style={{ color: colors.textColor, fontSize: 16, fontWeight: '800' }}>
|
||||||
|
{this.store.loginUserData?.display_name}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={{ color: colors.textColor, marginTop: 10 }}>
|
||||||
|
{this.store.loginUserData?.email}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: colors.textColor, marginTop: 10 }}>
|
||||||
|
{I18n.t('cartPoints') + ": " + this.store.loginUserData?.points}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={{ color: colors.textColor, marginTop: 20 }}>
|
||||||
|
{I18n.t('userId') + ": " + this.store.loginUserData?.id}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: colors.textColor, marginTop: 10 }}>
|
||||||
|
{I18n.t('settingsPhoneNumber') + ": " + this.store.loginUserData?.mobile}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderQrCode() {
|
||||||
|
return (
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30 }}>
|
||||||
|
<QRCode
|
||||||
|
value={this.store.loginUserData?.id}
|
||||||
|
size={140}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderProfileSelection() {
|
||||||
|
return (
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30 }}>
|
||||||
|
<TouchableOpacity style={{ width: width - 80, marginHorizontal: 40, marginVertical: 10, borderBottomWidth: 1, borderColor: colors.line2Color, height: 50, justifyContent: 'center', }}
|
||||||
|
onPress={() => { }}>
|
||||||
|
<Text style={styles.titleText}>
|
||||||
|
{I18n.t('EditUserInfo')}
|
||||||
|
</Text>
|
||||||
|
<View style={{ position: 'absolute', right: 0 }}>
|
||||||
|
<Icon name='chevron-right' color={colors.fontColor} size={30} />
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={{ width: width - 80, marginHorizontal: 40, marginVertical: 10, borderBottomWidth: 1, borderColor: colors.line2Color, height: 50, justifyContent: 'center', }}
|
||||||
|
onPress={() => { this.store.logoutPost(this) }}>
|
||||||
|
<Text style={styles.titleText}>
|
||||||
|
{I18n.t('settingsLogout')}
|
||||||
|
</Text>
|
||||||
|
<View style={{ position: 'absolute', right: 0 }}>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={true} user={false} />
|
||||||
|
<View style={{ width: width, justifyContent: 'center', alignItems: 'center', marginTop: 40 }}>
|
||||||
|
<Image source={images.titleLogo} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView>
|
||||||
|
{this.renderUserInfo()}
|
||||||
|
{this.renderQrCode()}
|
||||||
|
{this.renderProfileSelection()}
|
||||||
|
</ScrollView>
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.mainColor }}
|
||||||
|
position="center"
|
||||||
|
positionValue={100}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -30, fontSize: 18, },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Profile
|
|
@ -0,0 +1,93 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { Image, ScrollView, Text, View, TouchableOpacity, TextInput, Keyboard, TouchableWithoutFeedback, Platform, ImageBackground, StyleSheet } from "react-native";
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import { width, height } from '../../services/screen'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import {images} from '../../assets/images/imageIndex'
|
||||||
|
Icon.loadFont();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const About = inject("appStore")(observer(class About extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
// settingItems: observable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
this.store.getAbout()
|
||||||
|
}
|
||||||
|
|
||||||
|
renderContent() {
|
||||||
|
return (
|
||||||
|
<View style={{ backgroundColor: colors.aboutColor, marginHorizontal: 20, marginVertical: 30, borderRadius: width / 20 }}>
|
||||||
|
<HTMLView
|
||||||
|
style={{ margin: 20, marginBottom:50 ,fontColor: colors.fontColor }}
|
||||||
|
value={this.store.about}
|
||||||
|
stylesheet={styles.content}
|
||||||
|
textComponentProps={{ style: { color: colors.fontColor } }}
|
||||||
|
/>
|
||||||
|
<Image source={images.titleLogo} style = {{position:'absolute',bottom:-20,right:0}}/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log(this.store.lang)
|
||||||
|
return (
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={true} user={true} />
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30, }}>
|
||||||
|
<Text style={{ fontWeight: '800', color: colors.fontColor, fontSize: 15 }}>
|
||||||
|
{I18n.t('aboutSoya')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<ScrollView >
|
||||||
|
{this.renderContent()}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.BORDER_PINK }}
|
||||||
|
position="center"
|
||||||
|
positionValue={200}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
const styles = StyleSheet.flatten({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -30, fontSize: 18, },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default About
|
|
@ -0,0 +1,91 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { Image, ScrollView, Text, View, TouchableOpacity, TextInput, Keyboard, TouchableWithoutFeedback, Platform, ImageBackground, StyleSheet } from "react-native";
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import { width, height } from '../../services/screen'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { images } from '../../assets/images/imageIndex'
|
||||||
|
Icon.loadFont();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const loyaltyProgramTerms = inject("appStore")(observer(class loyaltyProgramTerms extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
// settingItems: observable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
this.store.getLoyaltyProgramTerms()
|
||||||
|
}
|
||||||
|
|
||||||
|
renderContent() {
|
||||||
|
return (
|
||||||
|
<View style={{ backgroundColor: colors.listItemsbgc2, marginHorizontal: 20, marginVertical: 30, borderRadius: width / 20 }}>
|
||||||
|
<HTMLView
|
||||||
|
style={{ margin: 20, marginBottom: 50, fontColor: colors.fontColor }}
|
||||||
|
value={this.store.loyaltyProgramTerms}
|
||||||
|
stylesheet={styles.content}
|
||||||
|
textComponentProps={{ style: { color: colors.fontColor } }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log(this.store.lang)
|
||||||
|
return (
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={true} user={true} />
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30, }}>
|
||||||
|
<Text style={{ fontWeight: '800', color: colors.fontColor, fontSize: 15 }}>
|
||||||
|
{I18n.t('loyaltyProgramTermsAndConditions')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<ScrollView >
|
||||||
|
{this.renderContent()}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.BORDER_PINK }}
|
||||||
|
position="center"
|
||||||
|
positionValue={200}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
const styles = StyleSheet.flatten({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -30, fontSize: 18, },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default loyaltyProgramTerms
|
|
@ -0,0 +1,91 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { Image, ScrollView, Text, View, TouchableOpacity, TextInput, Keyboard, TouchableWithoutFeedback, Platform, ImageBackground, StyleSheet } from "react-native";
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import { width, height } from '../../services/screen'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import HTMLView from 'react-native-htmlview';
|
||||||
|
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
import { images } from '../../assets/images/imageIndex'
|
||||||
|
Icon.loadFont();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const PrivacyPolicy = inject("appStore")(observer(class PrivacyPolicy extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
// settingItems: observable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
this.store.getPivacyPolicy()
|
||||||
|
}
|
||||||
|
|
||||||
|
renderContent() {
|
||||||
|
return (
|
||||||
|
<View style={{ backgroundColor: colors.listItemsbgc2, marginHorizontal: 20, marginVertical: 30, borderRadius: width / 20 }}>
|
||||||
|
<HTMLView
|
||||||
|
style={{ margin: 20, marginBottom: 50, fontColor: colors.fontColor }}
|
||||||
|
value={this.store.privacyPolicy}
|
||||||
|
stylesheet={styles.content}
|
||||||
|
textComponentProps={{ style: { color: colors.fontColor } }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log(this.store.lang)
|
||||||
|
return (
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
<Loading loading={this.store.loading} />
|
||||||
|
<TitleBar navigation={this.props.navigation} back={true} user={true} />
|
||||||
|
<View style={{ width: width, alignItems: 'center', marginTop: 30, }}>
|
||||||
|
<Text style={{ fontWeight: '800', color: colors.fontColor, fontSize: 15 }}>
|
||||||
|
{I18n.t('privacyPolicyAndStatement')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<ScrollView >
|
||||||
|
{this.renderContent()}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.BORDER_PINK }}
|
||||||
|
position="center"
|
||||||
|
positionValue={200}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
const styles = StyleSheet.flatten({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 20,
|
||||||
|
br: { marginTop: -30, fontSize: 18, },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default PrivacyPolicy
|
|
@ -0,0 +1,143 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { Image, ScrollView, Text, View, TouchableOpacity, TextInput, Keyboard, TouchableWithoutFeedback, Platform, ImageBackground, StyleSheet } from "react-native";
|
||||||
|
import { inject, observer } from "mobx-react"
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
import { observable, makeObservable } from 'mobx'
|
||||||
|
import Toast, { DURATION } from 'react-native-easy-toast';
|
||||||
|
import { colors } from '../../assets/styles/colors-theme';
|
||||||
|
import { width, height } from '../../services/screen'
|
||||||
|
import { s, vs, ms, mvs } from 'react-native-size-matters';
|
||||||
|
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons'
|
||||||
|
import I18n from '../../services/i18n'
|
||||||
|
import TitleBar from '../../components/titleBar'
|
||||||
|
Icon.loadFont();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const Setting = inject("appStore")(observer(class Setting extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.store = props.appStore
|
||||||
|
makeObservable(this, {
|
||||||
|
|
||||||
|
// settingItems: observable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
userInfoPressAction() {
|
||||||
|
if (this.store.logined) {
|
||||||
|
this.props.navigation.navigate('Profile')
|
||||||
|
} else {
|
||||||
|
this.props.navigation.navigate('Signin')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUserInfo() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={{ marginHorizontal: 40, marginVertical: 10, borderBottomWidth: 1, borderColor: colors.line2Color, height: 50, justifyContent: 'center', marginBottom: 40 }}
|
||||||
|
onPress={() => { this.userInfoPressAction() }}>
|
||||||
|
<Text style={styles.titleText}>
|
||||||
|
{this.store.logined ? (this.store.loginUserData?.display_name) : I18n.t('loginTitle')}
|
||||||
|
</Text>
|
||||||
|
<View style={{ position: 'absolute', right: 0 }}>
|
||||||
|
<Icon name='chevron-right' color={colors.fontColor} size={30} />
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSettingList() {
|
||||||
|
const settingItems = [{ id: 'news', name: 'news' }, { id: 'shop', name: 'storeInformation' }, { id: 'about', name: 'aboutSoya' },
|
||||||
|
{ id: 'privacyPolicy', name: 'privacyPolicyAndStatement' }, { id: 'loyaltyProgram', name: 'loyaltyProgramTermsAndConditions' }, { id: 'version', name: 'version' }]
|
||||||
|
return (
|
||||||
|
settingItems.map((item, index) => {
|
||||||
|
console.log(this.store.lang)
|
||||||
|
return (
|
||||||
|
this.renderListItem(item, index)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
settingItemsClickAction(id) {
|
||||||
|
switch (id) {
|
||||||
|
case 'order':
|
||||||
|
this.store.getOrderHistory(this)
|
||||||
|
break;
|
||||||
|
case 'shop':
|
||||||
|
this.props.navigation.navigate('StoreInfo')
|
||||||
|
break;
|
||||||
|
case 'about':
|
||||||
|
this.props.navigation.navigate('About')
|
||||||
|
break;
|
||||||
|
case 'privacyPolicy':
|
||||||
|
this.props.navigation.navigate('PrivacyPolicy')
|
||||||
|
break;
|
||||||
|
case 'loyaltyProgram':
|
||||||
|
this.props.navigation.navigate('LoyaltyProgramTerms')
|
||||||
|
break;
|
||||||
|
case 'coupon':
|
||||||
|
this.props.navigation.navigate('Coupons', { selectMode: false })
|
||||||
|
break;
|
||||||
|
case 'setting':
|
||||||
|
this.props.navigation.navigate('AppSetting')
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderListItem(item, index) {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={{ marginHorizontal: 40, marginVertical: 10, borderBottomWidth: 1, borderColor: colors.line2Color, height: 50, justifyContent: 'center', }}
|
||||||
|
onPress={() => { this.settingItemsClickAction(item.id) }}>
|
||||||
|
<Text style={styles.titleText}>
|
||||||
|
{I18n.t(item.name)}
|
||||||
|
</Text>
|
||||||
|
<View style={{ position: 'absolute', right: 0 }}>
|
||||||
|
<Icon name='chevron-right' color={colors.fontColor} size={30} />
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log(this.store.lang)
|
||||||
|
return (
|
||||||
|
<ImageBackground resizeMode='cover' style={{ flex: 1, backgroundColor: colors.bgc }} source={require('../../assets/images/background.png')} >
|
||||||
|
{/* <Loading loading={this.store.loading} /> */}
|
||||||
|
<TitleBar navigation={this.props.navigation} back={false} user={true} />
|
||||||
|
|
||||||
|
<ScrollView style={{ marginTop: s(70) }}>
|
||||||
|
{this.renderUserInfo()}
|
||||||
|
{this.renderSettingList()}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
|
||||||
|
<Toast
|
||||||
|
ref="toast"
|
||||||
|
style={{ backgroundColor: colors.BORDER_PINK }}
|
||||||
|
position="center"
|
||||||
|
positionValue={200}
|
||||||
|
fadeInDuration={750}
|
||||||
|
fadeOutDuration={2000}
|
||||||
|
opacity={0.8}
|
||||||
|
textStyle={{ color: 'white' }}
|
||||||
|
/>
|
||||||
|
</ImageBackground>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
const styles = StyleSheet.flatten({
|
||||||
|
titleText: {
|
||||||
|
color: colors.fontColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '800'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default Setting
|