├── .watchmanconfig
├── README.md
├── assets
├── bg.png
├── bg-blur.png
├── launch.png
├── logo-bg.png
├── logo-sm.png
├── hamburger.png
├── hamburger-sm.png
├── menu_burger.png
└── control-panel.png
├── menu_burger.png
├── ios
├── BVNK
│ ├── Images.xcassets
│ │ ├── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ ├── Icon-App@2x.png
│ │ │ ├── Icon-App@3x.png
│ │ │ ├── Icon-Spotlight@2x.png
│ │ │ ├── Icon-Spotlight@3x.png
│ │ │ ├── Icon-Spotlight@2x-1.png
│ │ │ ├── Icon-Spotlight@3x-1.png
│ │ │ └── Contents.json
│ │ ├── LaunchImage.launchimage
│ │ │ ├── Default@2x.png
│ │ │ ├── Default-568h@2x.png
│ │ │ ├── Default-667h@2x.png
│ │ │ ├── Default-Landscape.png
│ │ │ ├── Default-Portrait.png
│ │ │ ├── Default-Landscape@2x.png
│ │ │ ├── Default-Portrait@2x.png
│ │ │ ├── Default-Landscape-736h@3x.png
│ │ │ ├── Default-Portrait-736h@3x.png
│ │ │ └── Contents.json
│ │ └── Brand Assets.launchimage
│ │ │ └── Contents.json
│ ├── BVNK.entitlements
│ ├── AppDelegate.h
│ ├── main.m
│ ├── Info.plist
│ ├── Base.lproj
│ │ └── LaunchScreen.xib
│ └── AppDelegate.m
├── BVNKTests
│ ├── Info.plist
│ └── BVNKTests.m
└── BVNK.xcodeproj
│ └── xcshareddata
│ └── xcschemes
│ ├── BVNK.xcscheme
│ └── BankReact.xcscheme
├── android
├── app
│ ├── src
│ │ └── main
│ │ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ └── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── com
│ │ │ ├── bvnk
│ │ │ └── MainActivity.java
│ │ │ └── bankreact
│ │ │ └── MainActivity.java
│ ├── proguard-rules.pro
│ ├── react.gradle
│ ├── build.gradle
│ └── app.iml
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── settings.gradle
├── build.gradle
├── android.iml
├── gradle.properties
├── BankReact.iml
├── gradlew.bat
└── gradlew
├── fix_maps_linking.sh
├── style
├── drawer.js
├── tabs.js
├── main.js
├── navbar.js
├── forms.js
├── buttons.js
├── 4s
│ └── loginRegister.js
├── transaction.js
├── controlPanel.js
├── loginRegister.js
└── global.js
├── .gitignore
├── package.json
├── libs
├── device.js
├── RealmDB.js
└── BankClient.js
├── MainSettingsView.js
├── styles.js
├── index.android.js
├── MainAboutView.js
├── TestLandingView.js
├── ContactView.js
├── ControlPanel.js
├── .flowconfig
├── MainContactsView.js
├── LoginRegisterView.js
├── index.ios.js
├── DrawerView.js
├── MainPaymentDepositView.js
├── MainPaymentCreditView.js
├── AddContactView.js
├── CreateAuthView.js
├── MainTransactionsView.js
├── TransactionView.js
├── RegisterView.js
├── FetchAccountView.js
├── LoginView.js
└── MainAccountView.js
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bank-react
2 |
--------------------------------------------------------------------------------
/assets/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/bg.png
--------------------------------------------------------------------------------
/menu_burger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/menu_burger.png
--------------------------------------------------------------------------------
/assets/bg-blur.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/bg-blur.png
--------------------------------------------------------------------------------
/assets/launch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/launch.png
--------------------------------------------------------------------------------
/assets/logo-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/logo-bg.png
--------------------------------------------------------------------------------
/assets/logo-sm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/logo-sm.png
--------------------------------------------------------------------------------
/assets/hamburger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/hamburger.png
--------------------------------------------------------------------------------
/assets/hamburger-sm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/hamburger-sm.png
--------------------------------------------------------------------------------
/assets/menu_burger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/menu_burger.png
--------------------------------------------------------------------------------
/assets/control-panel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/assets/control-panel.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | BankReact
5 |
6 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-App@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-App@2x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-App@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-App@3x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default@2x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-Spotlight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-Spotlight@2x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-Spotlight@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-Spotlight@3x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-Spotlight@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-Spotlight@2x-1.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-Spotlight@3x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/AppIcon.appiconset/Icon-Spotlight@3x-1.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-667h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-667h@2x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Landscape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Landscape.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Portrait.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h@3x.png
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Portrait-736h@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NXRSE/bank-react/HEAD/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Default-Portrait-736h@3x.png
--------------------------------------------------------------------------------
/fix_maps_linking.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | sed -i -e 's/React\/RCTComponent.h/RCTComponent.h/g' ./node_modules/react-native-maps/ios/AirMaps/AIRMap.h
4 | sed -i -e 's/React\/RCTView.h/RCTView.h/g' ./node_modules/react-native-maps/ios/AirMaps/AIRMapCallout.h
5 |
--------------------------------------------------------------------------------
/style/drawer.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var exports = module.exports = {};
4 |
5 | exports.drawerStyles = {
6 | drawer: {
7 | shadowColor: "#000000",
8 | shadowOpacity: 0.8,
9 | shadowRadius: 0,
10 | }
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
6 |
--------------------------------------------------------------------------------
/ios/BVNK/BVNK.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.in-app-payments
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/style/tabs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet } from 'react-native';
5 |
6 | module.exports = StyleSheet.create({
7 | tabContent: {
8 | flex: 1,
9 | alignItems: 'center',
10 | },
11 | tabText: {
12 | color: 'white',
13 | margin: 50,
14 | },
15 | });
16 |
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 | realm/*
25 |
26 | # Android/IJ
27 | #
28 | .idea
29 | .gradle
30 | local.properties
31 |
32 | # node.js
33 | #
34 | node_modules/
35 | npm-debug.log
36 |
--------------------------------------------------------------------------------
/style/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet, Dimensions } from 'react-native';
5 |
6 | var width = Dimensions.get('window').width; //full width
7 | var height = Dimensions.get('window').height; //full height
8 |
9 | module.exports = StyleSheet.create({
10 | base: {
11 | flex: 1,
12 | backgroundColor: '#CCC',
13 | },
14 | backgroundImage: {
15 | flex: 1,
16 | resizeMode: 'cover',
17 | width: width
18 | },
19 | });
20 |
21 |
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/Brand Assets.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "minimum-system-version" : "7.0",
7 | "scale" : "2x"
8 | },
9 | {
10 | "orientation" : "portrait",
11 | "idiom" : "iphone",
12 | "minimum-system-version" : "7.0",
13 | "subtype" : "retina4",
14 | "scale" : "2x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ios/BVNK/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | @interface AppDelegate : UIResponder
13 |
14 | @property (nonatomic, strong) UIWindow *window;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'BVNK'
2 |
3 | include ':app'
4 | include ':react-native-push-notification'
5 | project(':react-native-push-notification').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-push-notification/android')
6 | include ':react-native-maps'
7 | project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android')
8 | include ':realm'
9 | project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
10 |
--------------------------------------------------------------------------------
/ios/BVNK/main.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | #import "AppDelegate.h"
13 |
14 | int main(int argc, char * argv[]) {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BVNK",
3 | "version": "0.0.3",
4 | "private": true,
5 | "scripts": {
6 | "start": "node node_modules/react-native/local-cli/cli.js start"
7 | },
8 | "dependencies": {
9 | "react": "~15.2.1",
10 | "react-addons-pure-render-mixin": "~15.2.1",
11 | "react-native": "~0.31.0",
12 | "react-native-button": "^1.4.2",
13 | "react-native-device": "^1.0.1",
14 | "react-native-drawer": "^2.2.6",
15 | "react-native-maps": "^0.7.1",
16 | "react-native-push-notification": "2.0.2",
17 | "react-native-router-flux": "^3.3.4",
18 | "realm": "^0.14.0"
19 | },
20 | "devDependencies": {
21 | "rnpm-plugin-upgrade": "^0.26.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.1'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | mavenLocal()
18 | jcenter()
19 | maven {
20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
21 | url "$projectDir/../../node_modules/react-native/android"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/style/navbar.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet } from 'react-native';
5 |
6 | module.exports = StyleSheet.create({
7 | mainContainer: {
8 | flex: 1
9 | },
10 | base: {
11 | backgroundColor: 'transparent',
12 | borderColor: 'transparent',
13 | borderBottomWidth: 0,
14 | flexDirection: 'column',
15 | },
16 | title: {
17 | color: 'white',
18 | textAlign: 'center',
19 | borderColor: 'transparent',
20 | borderWidth: 0,
21 | fontWeight: 'bold',
22 | },
23 | buttonText: {
24 | borderColor: 'transparent',
25 | borderWidth: 0,
26 | },
27 | buttonIcon: {
28 | borderColor: 'transparent',
29 | borderWidth: 0,
30 | },
31 | });
32 |
--------------------------------------------------------------------------------
/android/android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/style/forms.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet } from 'react-native';
5 |
6 | module.exports = StyleSheet.create({
7 | input: {
8 | fontFamily: 'Berlin',
9 | borderColor: '#515152',
10 | height: 40,
11 | borderWidth: 40,
12 | flex: 1
13 | },
14 | inputText: {
15 | fontFamily: 'ArticulatCF-Light',
16 | borderColor: '#0b5a87',
17 | backgroundColor: 'rgba(255,255,255,0.15)',
18 | height: 40,
19 | borderWidth: 1,
20 | borderRadius: 20,
21 | marginLeft: 50,
22 | marginRight: 50,
23 | marginTop: 10,
24 | marginBottom: 10,
25 | color: 'white',
26 | paddingLeft: 20,
27 | paddingRight: 20,
28 | paddingTop: 0,
29 | paddingBottom: 0,
30 | }
31 | });
32 |
33 |
34 |
--------------------------------------------------------------------------------
/ios/BVNKTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | android.useDeprecatedNdk=true
21 |
--------------------------------------------------------------------------------
/android/BankReact.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-Spotlight@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-Spotlight@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "40x40",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-Spotlight@2x-1.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-Spotlight@3x-1.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "60x60",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App@2x.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App@3x.png",
37 | "scale" : "3x"
38 | }
39 | ],
40 | "info" : {
41 | "version" : 1,
42 | "author" : "xcode"
43 | }
44 | }
--------------------------------------------------------------------------------
/android/app/src/main/java/com/bvnk/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.bvnk;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.facebook.react.ReactPackage;
5 | import com.facebook.react.shell.MainReactPackage;
6 |
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | public class MainActivity extends ReactActivity {
11 |
12 | /**
13 | * Returns the name of the main component registered from JavaScript.
14 | * This is used to schedule rendering of the component.
15 | */
16 | @Override
17 | protected String getMainComponentName() {
18 | return "BVNK";
19 | }
20 |
21 | /**
22 | * Returns whether dev mode should be enabled.
23 | * This enables e.g. the dev menu.
24 | */
25 | @Override
26 | protected boolean getUseDeveloperSupport() {
27 | return BuildConfig.DEBUG;
28 | }
29 |
30 | /**
31 | * A list of packages used by the app. If the app uses additional views
32 | * or modules besides the default ones, add more packages here.
33 | */
34 | @Override
35 | protected List getPackages() {
36 | return Arrays.asList(
37 | new MainReactPackage()
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/libs/device.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Device = require('react-native-device');
4 |
5 | function DeviceLib() {
6 |
7 | this.get = function() {
8 | let deviceV = Device.deviceVersion;
9 | var device = "";
10 |
11 | switch(deviceV) {
12 | case "4,1":
13 | device = "4s";
14 | break;
15 | case "5,1":
16 | case "5,2":
17 | device = "5";
18 | break;
19 | case "5,3":
20 | case "5,4":
21 | device = "5c";
22 | break;
23 | case "6,1":
24 | case "6,2":
25 | device = "5s";
26 | break;
27 | case "7,1":
28 | device = "6+";
29 | break;
30 | case "7,2":
31 | device = "6";
32 | break;
33 | case "8,2":
34 | device = "6s+";
35 | break;
36 | case "8,1":
37 | default:
38 | device = "6s";
39 | break;
40 | }
41 |
42 | // TESTING
43 | device = "4s";
44 | return device;
45 | }
46 | }
47 |
48 | module.exports = DeviceLib;
49 |
--------------------------------------------------------------------------------
/MainSettingsView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | ListView,
12 | Image,
13 | TouchableOpacity,
14 | Alert
15 | } from 'react-native';
16 |
17 | import Button from 'react-native-button'
18 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
19 | import Drawer from 'react-native-drawer'
20 |
21 | let styles = require('./styles');
22 | let BankClient = require('./libs/BankClient');
23 | let bc = new BankClient();
24 | let db = require('./libs/RealmDB');
25 | let dismissKeyboard = require('dismissKeyboard');
26 |
27 | var MainSettingsView = React.createClass({
28 | render: function() {
29 | return(
30 |
31 |
32 |
33 |
34 |
35 |
36 | SETTINGS
37 |
38 |
39 |
40 | )
41 | }
42 | });
43 |
44 | module.exports = MainSettingsView;
45 |
46 |
--------------------------------------------------------------------------------
/ios/BVNK/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "extent": "full-screen",
5 | "idiom": "iphone",
6 | "filename": "Default-568h@2x.png",
7 | "minimum-system-version": "7.0",
8 | "orientation": "portrait",
9 | "scale": "2x",
10 | "subtype": "retina4"
11 | },
12 | {
13 | "extent": "full-screen",
14 | "idiom": "iphone",
15 | "filename": "Default-667h@2x.png",
16 | "minimum-system-version": "8.0",
17 | "orientation": "portrait",
18 | "scale": "2x",
19 | "subtype": "667h"
20 | },
21 | {
22 | "extent": "full-screen",
23 | "idiom": "iphone",
24 | "filename": "Default-Landscape-736h@3x.png",
25 | "minimum-system-version": "8.0",
26 | "orientation": "landscape",
27 | "scale": "3x",
28 | "subtype": "736h"
29 | },
30 | {
31 | "extent": "full-screen",
32 | "idiom": "iphone",
33 | "filename": "Default-Portrait-736h@3x.png",
34 | "minimum-system-version": "8.0",
35 | "orientation": "portrait",
36 | "scale": "3x",
37 | "subtype": "736h"
38 | },
39 | {
40 | "extent": "full-screen",
41 | "idiom": "iphone",
42 | "filename": "Default@2x.png",
43 | "minimum-system-version": "7.0",
44 | "orientation": "portrait",
45 | "scale": "2x"
46 | }
47 | ],
48 | "info": {
49 | "version": 1,
50 | "author": "xcode"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/style/buttons.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet } from 'react-native';
5 |
6 | module.exports = StyleSheet.create({
7 | containerFilled: {
8 | padding:10,
9 | height:45,
10 | borderRadius: 20,
11 | overflow:'hidden',
12 | backgroundColor: '#031d2c',
13 | paddingTop: 17,
14 | paddingBottom: 20,
15 | marginTop: 15,
16 | marginBottom: 15,
17 | marginLeft: 50,
18 | marginRight: 50,
19 | },
20 | containerBase: {
21 | padding:10,
22 | height:45,
23 | overflow:'hidden',
24 | borderRadius: 20,
25 | borderColor: '#515152',
26 | borderWidth: 1,
27 | backgroundColor: 'transparent',
28 | paddingTop: 13,
29 | paddingBottom: 20,
30 | marginTop: 15,
31 | marginBottom: 15,
32 | marginLeft: 50,
33 | marginRight: 50,
34 | },
35 | containerBaseNoBorder: {
36 | padding:10,
37 | height:45,
38 | overflow:'hidden',
39 | borderRadius: 20,
40 | borderWidth: 0,
41 | backgroundColor: 'transparent',
42 | paddingTop: 17,
43 | paddingBottom: 20,
44 | marginTop: 15,
45 | marginBottom: 15,
46 | marginLeft: 50,
47 | marginRight: 50,
48 | },
49 | containerNotification: {
50 | backgroundColor: 'transparent',
51 | },
52 | base: {
53 | fontSize: 12,
54 | color: 'white'
55 | },
56 | });
57 |
--------------------------------------------------------------------------------
/ios/BVNK/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | co.bvnk.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 5
23 | LSApplicationCategoryType
24 |
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 |
32 | NSLocationWhenInUseUsageDescription
33 |
34 | UIAppFonts
35 |
36 | Berlin.ttf
37 | ArticulatCF-Light.otf
38 |
39 | UILaunchStoryboardName
40 | LaunchScreen
41 | UIRequiredDeviceCapabilities
42 |
43 | armv7
44 |
45 | UISupportedInterfaceOrientations
46 |
47 | UIInterfaceOrientationPortrait
48 |
49 | UIViewControllerBasedStatusBarAppearance
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/style/4s/loginRegister.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { StyleSheet, Dimensions } from 'react-native';
4 |
5 | var width = Dimensions.get('window').width; //full width
6 | var height = Dimensions.get('window').height; //full height
7 |
8 | module.exports = StyleSheet.create({
9 | base: {
10 | flex: 1,
11 | backgroundColor: '#CCC',
12 | },
13 | backgroundImage: {
14 | flex: 1,
15 | resizeMode: 'cover',
16 | width: width
17 | },
18 | bigLogoWrap: {
19 | alignItems: 'center',
20 | justifyContent: 'center',
21 | marginBottom: -120,
22 | },
23 | bigLogo: {
24 | resizeMode: 'contain',
25 | width: 100,
26 | marginTop: -80,
27 | },
28 | smallLogoWrap: {
29 | alignItems: 'center',
30 | justifyContent: 'center',
31 | },
32 | smallLogo: {
33 | resizeMode: 'contain',
34 | marginTop: 5,
35 | width: 80,
36 | },
37 | buttonsLoginRegister: {
38 | paddingTop: 20,
39 | paddingBottom: 20,
40 | paddingLeft: 50,
41 | paddingRight: 50,
42 | flexDirection: 'column'
43 | },
44 | buttonsLogin: {
45 | flex: 1,
46 | borderColor: 'black',
47 | borderStyle: 'solid',
48 | borderWidth: 1,
49 | paddingTop: 5,
50 | paddingBottom:5
51 | },
52 | buttonsRegister: {
53 | flex: 1,
54 | borderColor: 'black',
55 | borderStyle: 'solid',
56 | borderWidth: 1,
57 | paddingTop: 5,
58 | paddingBottom: 5
59 | },
60 | buttonText: {
61 | textAlign: 'center',
62 | }
63 | });
64 |
65 |
--------------------------------------------------------------------------------
/styles.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { StyleSheet } from 'react-native';
4 |
5 | module.exports = {
6 | global: require('./style/global'),
7 | navbar: require('./style/navbar'),
8 | landingPage: require('./style/loginRegister'),
9 | buttons: require('./style/buttons'),
10 | forms: require('./style/forms'),
11 | main: require('./style/main'),
12 | tabs: require('./style/tabs'),
13 | controlPanel: require('./style/controlPanel'),
14 | transaction: require('./style/transaction'),
15 | };
16 |
17 | /*
18 | let deviceLib = require('./libs/device');
19 | // Get device
20 | let deviceC = new deviceLib();
21 | let device = deviceC.get();
22 |
23 | if (device == "4s") {
24 | module.exports = {
25 | global: require('./style/global'),
26 | navbar: require('./style/navbar'),
27 | landingPage: require('./style/4s/loginRegister'),
28 | buttons: require('./style/buttons'),
29 | forms: require('./style/forms'),
30 | main: require('./style/main'),
31 | tabs: require('./style/tabs'),
32 | controlPanel: require('./style/controlPanel'),
33 | transaction: require('./style/transaction'),
34 | };
35 | } else {
36 | module.exports = {
37 | global: require('./style/global'),
38 | navbar: require('./style/navbar'),
39 | landingPage: require('./style/loginRegister'),
40 | buttons: require('./style/buttons'),
41 | forms: require('./style/forms'),
42 | main: require('./style/main'),
43 | tabs: require('./style/tabs'),
44 | controlPanel: require('./style/controlPanel'),
45 | transaction: require('./style/transaction'),
46 | };
47 | }
48 | */
49 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/bankreact/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.bankreact;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
5 | import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
6 | import com.airbnb.android.react.maps.MapsPackage;
7 | import io.realm.react.RealmReactPackage;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.shell.MainReactPackage;
10 |
11 | import java.util.Arrays;
12 | import java.util.List;
13 |
14 | public class MainActivity extends ReactActivity {
15 |
16 | /**
17 | * Returns the name of the main component registered from JavaScript.
18 | * This is used to schedule rendering of the component.
19 | */
20 | @Override
21 | protected String getMainComponentName() {
22 | return "BankReact";
23 | }
24 |
25 | /**
26 | * Returns whether dev mode should be enabled.
27 | * This enables e.g. the dev menu.
28 | */
29 | @Override
30 | protected boolean getUseDeveloperSupport() {
31 | return BuildConfig.DEBUG;
32 | }
33 |
34 | /**
35 | * A list of packages used by the app. If the app uses additional views
36 | * or modules besides the default ones, add more packages here.
37 | */
38 | @Override
39 | protected List getPackages() {
40 | return Arrays.asList(
41 | new MainReactPackage(),
42 | new ReactNativePushNotificationPackage(this),
43 | new ReactNativePushNotificationPackage(this),
44 | new MapsPackage(),
45 | new RealmReactPackage()
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/style/transaction.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet, Dimensions } from 'react-native';
5 |
6 | var width = Dimensions.get('window').width; //full width
7 | var height = Dimensions.get('window').height; //full height
8 |
9 | module.exports = StyleSheet.create({
10 | container: {
11 | flex: 1,
12 | flexDirection: 'column',
13 | alignItems: 'stretch',
14 | backgroundColor: 'transparent',
15 | borderRadius: 15,
16 | borderWidth: 0,
17 | borderBottomColor: 'white',
18 | borderBottomWidth: 1,
19 | borderColor: 'transparent',
20 | paddingTop: 5,
21 | paddingBottom: 5,
22 | marginLeft: 40,
23 | marginRight: 40,
24 | marginTop: 10,
25 | marginBottom: 10,
26 | },
27 | list: {
28 | marginTop: 0,
29 | paddingTop: 0,
30 | flex: 1,
31 | flexDirection: 'column',
32 | // @FIXME Find element that is forcing negative margins
33 | marginTop: -950,
34 | },
35 | desc: {
36 | textAlign: 'left',
37 | fontFamily: 'ArticulatCF-Light',
38 | fontSize: 20,
39 | color: 'white',
40 | marginLeft: 10,
41 | backgroundColor: 'transparent',
42 | },
43 | time: {
44 | textAlign: 'right',
45 | fontFamily: 'ArticulatCF-Light',
46 | fontSize: 10,
47 | color: 'white',
48 | backgroundColor: 'transparent',
49 | marginLeft: 0,
50 | paddingTop: 5,
51 | paddingBottom: 5,
52 | },
53 | map: {
54 | alignItems: 'center',
55 | height: 300,
56 | width: width,
57 | flex: 0,
58 | },
59 | });
60 |
--------------------------------------------------------------------------------
/style/controlPanel.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet, Dimensions } from 'react-native';
5 |
6 | var width = Dimensions.get('window').width; //full width
7 | var height = Dimensions.get('window').height; //full height
8 |
9 | module.exports = StyleSheet.create({
10 | backgroundImage: {
11 | flex: 1,
12 | resizeMode: 'cover',
13 | width: width,
14 | height: height,
15 | },
16 | containerFilled: {
17 | padding:10,
18 | height:45,
19 | borderRadius: 20,
20 | overflow:'hidden',
21 | backgroundColor: '#031d2c',
22 | paddingTop: 17,
23 | paddingBottom: 20,
24 | marginTop: 15,
25 | marginBottom: 15,
26 | marginLeft: 50,
27 | marginRight: 50,
28 | },
29 | containerBase: {
30 | padding:10,
31 | height:45,
32 | overflow:'hidden',
33 | borderRadius: 20,
34 | backgroundColor: 'transparent',
35 | paddingTop: 17,
36 | paddingBottom: 20,
37 | marginTop: 15,
38 | marginBottom: 15,
39 | marginLeft: 50,
40 | marginRight: 50,
41 | },
42 | exitContainer: {
43 | padding:10,
44 | height:60,
45 | overflow:'hidden',
46 | borderRadius: 20,
47 | borderWidth: 0,
48 | backgroundColor: 'transparent',
49 | paddingTop: 17,
50 | paddingBottom: 20,
51 | marginTop: 40,
52 | marginBottom: 20,
53 | marginLeft: 50,
54 | marginRight: 50,
55 | },
56 | exit: {
57 | fontSize: 20,
58 | color: '#494949',
59 | },
60 | containerNotification: {
61 | backgroundColor: 'transparent',
62 | },
63 | base: {
64 | fontSize: 12,
65 | color: 'white'
66 | },
67 | });
68 |
--------------------------------------------------------------------------------
/index.android.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | Navigator
11 | } from 'react-native';
12 |
13 | import {Actions, Scene, Router, TabBar} from 'react-native-router-flux';
14 |
15 | StatusBar.setBarStyle('light-content');
16 |
17 | class BVNK extends Component {
18 | render() {
19 | return
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | }
32 | }
33 |
34 | var styles = require('./styles');
35 | // Views
36 | var LoginRegisterView = require('./LoginRegisterView');
37 | var LoginView = require('./LoginView');
38 | var RegisterView = require('./RegisterView');
39 | var CreateAuthView = require('./CreateAuthView');
40 | var MainAccountTabs = require('./MainAccountTabs');
41 | var ContactView = require('./ContactView');
42 | var MainPaymentCreditView = require('./MainPaymentCreditView');
43 | var MainPaymentDepositView = require('./MainPaymentDepositView');
44 |
45 | // DB
46 | var db = require('./libs/RealmDB');
47 | //console.log(db.path);
48 |
49 | AppRegistry.registerComponent('BVNK', () => BVNK);
50 |
--------------------------------------------------------------------------------
/MainAboutView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | ListView,
12 | Image,
13 | TouchableOpacity,
14 | Alert
15 | } from 'react-native';
16 |
17 | import Button from 'react-native-button'
18 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
19 | import Drawer from 'react-native-drawer'
20 |
21 | let styles = require('./styles');
22 | let BankClient = require('./libs/BankClient');
23 | let bc = new BankClient();
24 | let db = require('./libs/RealmDB');
25 | let dismissKeyboard = require('dismissKeyboard');
26 |
27 | var MainAboutView = React.createClass({
28 | render: function() {
29 | return(
30 |
31 |
32 |
33 |
34 |
35 |
36 | ABOUT
37 | BVNK is a project to build core banking infrastructure using modern standards. To find out more, go to https://bvnk.co.
38 | All code is available on Github at https://github.com/BVNK
39 | Feel free to get in touch at hello@bvnk.co
40 |
41 |
42 |
43 | )
44 | }
45 | });
46 |
47 | module.exports = MainAboutView;
48 |
49 |
--------------------------------------------------------------------------------
/TestLandingView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Image,
12 | Alert
13 | } from 'react-native';
14 |
15 | import Button from 'react-native-button'
16 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
17 |
18 | import ControlPanel from './ControlPanel'
19 | import DrawerView from './DrawerView'
20 | import MainContactsView from './MainContactsView'
21 |
22 | let styles = require('./styles');
23 | let BankClient = require('./libs/BankClient');
24 | let bc = new BankClient();
25 | let db = require('./libs/RealmDB');
26 | let dismissKeyboard = require('dismissKeyboard');
27 |
28 | var TestLandingView = React.createClass({
29 | getInitialState() {
30 | dismissKeyboard();
31 | return {
32 | balance: "nil",
33 | drawerOpen: false,
34 | }
35 | },
36 |
37 | updateStateListener: function() {
38 | // Fetch account
39 | let user = db.objects('Account');
40 | var userAccount = user.slice(0,1);
41 | userAccount = userAccount[0];
42 | console.log(userAccount.AccountBalance);
43 | this.setState({ 'balance' : userAccount.AccountBalance });
44 | },
45 |
46 | componentDidMount: function() {
47 | // Observe Realm Change Events
48 | db.addListener('change', this.updateStateListener);
49 | },
50 |
51 | componentWillUnmount: function() {
52 | // Remove the listener
53 | db.removeListener('change', this.updateStateListener);
54 | },
55 |
56 | closeDrawer() {
57 | this._drawer.close()
58 | },
59 |
60 | openDrawer() {
61 | this._drawer.open()
62 | },
63 |
64 | render: function() {
65 |
66 | return (
67 |
68 | )
69 | }
70 | });
71 |
72 | module.exports = TestLandingView;
73 |
--------------------------------------------------------------------------------
/style/loginRegister.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet, Dimensions } from 'react-native';
5 | //let deviceLib = require('./../libs/device');
6 |
7 | var width = Dimensions.get('window').width; //full width
8 | var height = Dimensions.get('window').height; //full height
9 | // Get device
10 | //let deviceC = new deviceLib();
11 | //let device = deviceC.get();
12 |
13 | var buttonMarginOffset = (height < 1000) ? -150 : 0;
14 | var logoMarginOffset = (height < 1000) ? -40 : 0;
15 |
16 | module.exports = StyleSheet.create({
17 | base: {
18 | flex: 1,
19 | backgroundColor: '#CCC',
20 | },
21 | backgroundImage: {
22 | flex: 1,
23 | resizeMode: 'cover',
24 | width: width,
25 | height: height,
26 | },
27 | bigLogoWrap: {
28 | alignItems: 'center',
29 | justifyContent: 'center',
30 | marginBottom: buttonMarginOffset,
31 | },
32 | bigLogo: {
33 | resizeMode: 'contain',
34 | width: 150,
35 | marginTop: logoMarginOffset,
36 | },
37 | smallLogoWrap: {
38 | alignItems: 'center',
39 | justifyContent: 'center',
40 | },
41 | smallLogo: {
42 | resizeMode: 'contain',
43 | marginTop: 5,
44 | width: 80,
45 | },
46 | buttonsLoginRegister: {
47 | paddingTop: 40,
48 | paddingBottom: 40,
49 | paddingLeft: 50,
50 | paddingRight: 50,
51 | flexDirection: 'column'
52 | },
53 | buttonsLogin: {
54 | flex: 1,
55 | borderColor: 'black',
56 | borderStyle: 'solid',
57 | borderWidth: 1,
58 | paddingTop: 10,
59 | paddingBottom: 10
60 | },
61 | buttonsRegister: {
62 | flex: 1,
63 | borderColor: 'black',
64 | borderStyle: 'solid',
65 | borderWidth: 1,
66 | paddingTop: 10,
67 | paddingBottom: 10
68 | },
69 | buttonText: {
70 | textAlign: 'center',
71 | }
72 | });
73 |
74 |
--------------------------------------------------------------------------------
/ContactView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 |
5 | import {
6 | AppRegistry,
7 | Text,
8 | View,
9 | StatusBar,
10 | StyleSheet,
11 | TextInput,
12 | Image,
13 | Alert
14 | } from 'react-native';
15 |
16 | import Button from 'react-native-button'
17 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
18 |
19 | let styles = require('./styles');
20 | let BankClient = require('./libs/BankClient');
21 | let bc = new BankClient();
22 | let db = require('./libs/RealmDB');
23 | let dismissKeyboard = require('dismissKeyboard');
24 |
25 | var ContactView = React.createClass({
26 | getInitialState() {
27 | dismissKeyboard();
28 | return {
29 | data: { ContactName: "nil" }
30 | }
31 | },
32 |
33 | render: function() {
34 |
35 | return (
36 |
37 |
38 |
39 |
40 |
41 |
42 | {this.props.data.ContactName}
43 | Account Number:
44 | {this.props.data.ContactAccountNumber}
45 | Bank Number:
46 | {this.props.data.ContactBankNumber}
47 |
48 |
51 |
52 |
53 |
54 | )
55 | }
56 | });
57 |
58 | module.exports = ContactView;
59 |
--------------------------------------------------------------------------------
/ControlPanel.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import {
3 | ScrollView,
4 | StyleSheet,
5 | Text,
6 | TouchableOpacity,
7 | Image,
8 | View,
9 | } from 'react-native'
10 |
11 | import Button from 'react-native-button'
12 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
13 |
14 | let styles = require('./styles');
15 |
16 | export default class ControlPanel extends Component {
17 | static propTypes = {
18 | closeDrawer: PropTypes.func.isRequired
19 | };
20 |
21 | render() {
22 | let {closeDrawer} = this.props
23 | return (
24 |
25 |
26 |
30 |
31 |
33 |
35 |
37 |
39 |
41 |
43 |
44 |
45 | )
46 | }
47 | }
48 |
49 |
50 |
--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 |
3 | # We fork some components by platform.
4 | .*/*.web.js
5 | .*/*.android.js
6 |
7 | # Some modules have their own node_modules with overlap
8 | .*/node_modules/node-haste/.*
9 |
10 | # Ugh
11 | .*/node_modules/babel.*
12 | .*/node_modules/babylon.*
13 | .*/node_modules/invariant.*
14 |
15 | # Ignore react and fbjs where there are overlaps, but don't ignore
16 | # anything that react-native relies on
17 | .*/node_modules/fbjs/lib/Map.js
18 | .*/node_modules/fbjs/lib/fetch.js
19 | .*/node_modules/fbjs/lib/ExecutionEnvironment.js
20 | .*/node_modules/fbjs/lib/ErrorUtils.js
21 |
22 | # Flow has a built-in definition for the 'react' module which we prefer to use
23 | # over the currently-untyped source
24 | .*/node_modules/react/react.js
25 | .*/node_modules/react/lib/React.js
26 | .*/node_modules/react/lib/ReactDOM.js
27 |
28 | .*/__mocks__/.*
29 | .*/__tests__/.*
30 |
31 | .*/commoner/test/source/widget/share.js
32 |
33 | # Ignore commoner tests
34 | .*/node_modules/commoner/test/.*
35 |
36 | # See https://github.com/facebook/flow/issues/442
37 | .*/react-tools/node_modules/commoner/lib/reader.js
38 |
39 | # Ignore jest
40 | .*/node_modules/jest-cli/.*
41 |
42 | # Ignore Website
43 | .*/website/.*
44 |
45 | [include]
46 |
47 | [libs]
48 | node_modules/react-native/Libraries/react-native/react-native-interface.js
49 |
50 | [options]
51 | module.system=haste
52 |
53 | esproposal.class_static_fields=enable
54 | esproposal.class_instance_fields=enable
55 |
56 | munge_underscores=true
57 |
58 | module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
59 | 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\)$' -> 'RelativeImageStub'
60 |
61 | suppress_type=$FlowIssue
62 | suppress_type=$FlowFixMe
63 | suppress_type=$FixMe
64 |
65 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
66 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
67 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
68 |
69 | [version]
70 | 0.21.0
71 |
--------------------------------------------------------------------------------
/ios/BVNKTests/BVNKTests.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 | #import
12 |
13 | #import "RCTLog.h"
14 | #import "RCTRootView.h"
15 |
16 | #define TIMEOUT_SECONDS 240
17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
18 |
19 | @interface BVNKTests : XCTestCase
20 |
21 | @end
22 |
23 | @implementation BVNKTests
24 |
25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
26 | {
27 | if (test(view)) {
28 | return YES;
29 | }
30 | for (UIView *subview in [view subviews]) {
31 | if ([self findSubviewInView:subview matching:test]) {
32 | return YES;
33 | }
34 | }
35 | return NO;
36 | }
37 |
38 | - (void)testRendersWelcomeScreen
39 | {
40 | UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
42 | BOOL foundElement = NO;
43 |
44 | __block NSString *redboxError = nil;
45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
46 | if (level >= RCTLogLevelError) {
47 | redboxError = message;
48 | }
49 | });
50 |
51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
54 |
55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
57 | return YES;
58 | }
59 | return NO;
60 | }];
61 | }
62 |
63 | RCTSetLogFunction(RCTDefaultLogFunction);
64 |
65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
67 | }
68 |
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/MainContactsView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | ListView,
12 | Image,
13 | TouchableOpacity,
14 | Alert
15 | } from 'react-native';
16 |
17 | import Button from 'react-native-button'
18 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
19 |
20 | let styles = require('./styles');
21 | let BankClient = require('./libs/BankClient');
22 | let bc = new BankClient();
23 | let db = require('./libs/RealmDB');
24 | let dismissKeyboard = require('dismissKeyboard');
25 |
26 | var MainContactsView = React.createClass({
27 |
28 | getInitialState: function() {
29 | dismissKeyboard();
30 | let contacts = db.objects('Contacts');
31 | var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
32 | return {
33 | dataSource: ds.cloneWithRows(contacts),
34 | };
35 | },
36 |
37 | componentDidMount: function() {
38 | },
39 |
40 | render: function() {
41 | return (
42 |
43 |
44 |
45 |
46 |
47 |
48 | CONTACTS
49 |
51 |
55 |
57 | Actions.contact({ data: rowData })}
58 | style={styles.global.contactItemText}>{rowData.ContactName}
59 | }
60 | />
61 |
62 |
63 |
64 | )
65 | }
66 | });
67 |
68 | module.exports = MainContactsView;
69 |
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Disabling obfuscation is useful if you collect stack traces from production crashes
20 | # (unless you are using a system that supports de-obfuscate the stack traces).
21 | -dontobfuscate
22 |
23 | # React Native
24 |
25 | # Keep our interfaces so they can be used by other ProGuard rules.
26 | # See http://sourceforge.net/p/proguard/bugs/466/
27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
29 |
30 | # Do not strip any method/class that is annotated with @DoNotStrip
31 | -keep @com.facebook.proguard.annotations.DoNotStrip class *
32 | -keepclassmembers class * {
33 | @com.facebook.proguard.annotations.DoNotStrip *;
34 | }
35 |
36 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
37 | void set*(***);
38 | *** get*();
39 | }
40 |
41 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
42 | -keep class * extends com.facebook.react.bridge.NativeModule { *; }
43 | -keepclassmembers,includedescriptorclasses class * { native ; }
44 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; }
45 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; }
46 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; }
47 |
48 | -dontwarn com.facebook.react.**
49 |
50 | # okhttp
51 |
52 | -keepattributes Signature
53 | -keepattributes *Annotation*
54 | -keep class com.squareup.okhttp.** { *; }
55 | -keep interface com.squareup.okhttp.** { *; }
56 | -dontwarn com.squareup.okhttp.**
57 |
58 | # okio
59 |
60 | -keep class sun.misc.Unsafe { *; }
61 | -dontwarn java.nio.file.*
62 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
63 | -dontwarn okio.**
64 |
65 | # stetho
66 |
67 | -dontwarn com.facebook.stetho.**
68 |
--------------------------------------------------------------------------------
/ios/BVNK/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/LoginRegisterView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | NavigatorIOS,
11 | TouchableOpacity,
12 | PushNotificationIOS,
13 | Image,
14 | PropTypes,
15 | AlertIOS
16 | } from 'react-native';
17 |
18 | import Button from 'react-native-button'
19 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
20 | import Drawer from 'react-native-drawer'
21 |
22 | import ControlPanel from './ControlPanel'
23 | import DrawerView from './DrawerView'
24 |
25 | var styles = require('./styles');
26 |
27 | let dismissKeyboard = require('dismissKeyboard');
28 | let db = require('./libs/RealmDB');
29 |
30 | //class LoginRegisterView extends Component{
31 | var LoginRegisterView = React.createClass({
32 | getInitialState() {
33 | return {
34 | drawerDisabled: true
35 | }
36 | },
37 |
38 | componentWillMount() {
39 | PushNotificationIOS.addEventListener('notification', this._onNotification);
40 | },
41 |
42 | componentWillUnmount() {
43 | PushNotificationIOS.removeEventListener('notification', this._onNotification);
44 | },
45 |
46 | _sendNotification() {
47 | require('RCTDeviceEventEmitter').emit('remoteNotificationReceived', {
48 | aps: {
49 | alert: 'Sample notification',
50 | badge: '+1',
51 | sound: 'default',
52 | category: 'REACT_NATIVE'
53 | },
54 | });
55 | },
56 |
57 | _onNotification(notification) {
58 | AlertIOS.alert(
59 | 'Notification Received',
60 | 'Alert message: ' + notification.getMessage(),
61 | [{
62 | text: 'Dismiss',
63 | onPress: null,
64 | }]
65 | );
66 | },
67 |
68 | loginOrRetrieve: function() {
69 | let userAccount = db.objects('Account');
70 | if (userAccount.length == 0) {
71 | // There is no account set up yet
72 | // Show fetch account screen
73 | Actions.accountFetch();
74 | return;
75 | }
76 | Actions.login();
77 | },
78 |
79 | render() {
80 | return (
81 |
82 |
83 |
84 |
85 |
86 |
87 |
89 |
91 |
92 |
93 |
94 | )
95 | }
96 | });
97 |
98 | module.exports = LoginRegisterView;
99 |
--------------------------------------------------------------------------------
/ios/BVNK/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import "AppDelegate.h"
11 |
12 | #import "RCTRootView.h"
13 | #import "RCTPushNotificationManager.h"
14 |
15 | @implementation AppDelegate
16 |
17 | // Required to register for notifications
18 | - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
19 | {
20 | [RCTPushNotificationManager didRegisterUserNotificationSettings:notificationSettings];
21 | }
22 | // Required for the register event.
23 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
24 | {
25 | [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
26 | }
27 | // Required for the notification event.
28 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification
29 | {
30 | [RCTPushNotificationManager didReceiveRemoteNotification:notification];
31 | }
32 | // Required for the localNotification event.
33 | - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
34 | {
35 | [RCTPushNotificationManager didReceiveLocalNotification:notification];
36 | }
37 |
38 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
39 | {
40 | NSURL *jsCodeLocation;
41 |
42 | /**
43 | * Loading JavaScript code - uncomment the one you want.
44 | *
45 | * OPTION 1
46 | * Load from development server. Start the server from the repository root:
47 | *
48 | * $ npm start
49 | *
50 | * To run on device, change `localhost` to the IP address of your computer
51 | * (you can get this by typing `ifconfig` into the terminal and selecting the
52 | * `inet` value under `en0:`) and make sure your computer and iOS device are
53 | * on the same Wi-Fi network.
54 | */
55 |
56 | jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
57 |
58 | /**
59 | * OPTION 2
60 | * Load from pre-bundled file on disk. The static bundle is automatically
61 | * generated by the "Bundle React Native code and images" build step when
62 | * running the project on an actual device or running the project on the
63 | * simulator in the "Release" build configuration.
64 | */
65 |
66 | jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
67 |
68 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
69 | moduleName:@"BVNK"
70 | initialProperties:nil
71 | launchOptions:launchOptions];
72 |
73 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
74 | UIViewController *rootViewController = [UIViewController new];
75 | rootViewController.view = rootView;
76 | self.window.rootViewController = rootViewController;
77 | [self.window makeKeyAndVisible];
78 | return YES;
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/index.ios.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | Navigator,
11 | Alert
12 | } from 'react-native';
13 |
14 | import {Actions, Scene, Router, TabBar} from 'react-native-router-flux';
15 |
16 | StatusBar.setBarStyle('light-content');
17 |
18 | class BVNK extends Component {
19 |
20 | render() {
21 | return
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | }
43 | }
44 |
45 | var styles = require('./styles');
46 | // Views
47 | var DrawerView = require('./DrawerView');
48 | var LoginRegisterView = require('./LoginRegisterView');
49 | var LoginView = require('./LoginView');
50 | var RegisterView = require('./RegisterView');
51 | var CreateAuthView = require('./CreateAuthView');
52 | var MainAccountView = require('./MainAccountView');
53 | var ContactView = require('./ContactView');
54 | var MainPaymentCreditView = require('./MainPaymentCreditView');
55 | var MainPaymentDepositView = require('./MainPaymentDepositView');
56 | var MainSettingsView = require('./MainSettingsView');
57 | var MainContactsView = require('./MainContactsView');
58 | var TransactionView = require('./TransactionView');
59 | var MainTransactionView = require('./MainTransactionsView');
60 | var AddContactView = require('./AddContactView');
61 | var FetchAccountView = require('./FetchAccountView');
62 | var MainAboutView = require('./MainAboutView');
63 |
64 | // DB
65 | var db = require('./libs/RealmDB');
66 | //console.log(db.path);
67 |
68 | AppRegistry.registerComponent('BVNK', () => BVNK);
69 |
--------------------------------------------------------------------------------
/DrawerView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component, PropTypes } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | NavigatorIOS,
11 | TouchableOpacity,
12 | PushNotificationIOS,
13 | Image,
14 | AlertIOS
15 | } from 'react-native';
16 |
17 | import Button from 'react-native-button'
18 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer, DefaultRenderer} from 'react-native-router-flux'
19 | import Drawer from 'react-native-drawer'
20 |
21 | import ControlPanel from './ControlPanel'
22 |
23 | var styles = require('./styles');
24 | let dismissKeyboard = require('dismissKeyboard');
25 |
26 | class DrawerView extends Component {
27 | state = {
28 | drawerOpen: false,
29 | drawerDisabled: false,
30 | side: 'left',
31 | };
32 |
33 | closeDrawer = () => {
34 | this._drawer.close()
35 | };
36 |
37 | openDrawer = () => {
38 | this._drawer.open()
39 | };
40 |
41 | render() {
42 | const state = this.props.navigationState;
43 | const children = state.children;
44 |
45 | return (
46 | this._drawer = ref}
48 | type="static"
49 | open={state.open}
50 | content={
51 |
52 | }
53 | acceptDoubleTap
54 | styles={drawerStyles}
55 | onOpen={() => {
56 | console.log('onopen')
57 | //this.setState({drawerOpen: true})
58 | }}
59 | onClose={() => {
60 | console.log('onclose')
61 | //this.setState({drawerOpen: false})
62 | }}
63 | captureGestures={false}
64 | tweenDuration={100}
65 | panThreshold={0.08}
66 | disabled={true}
67 | openDrawerOffset={(viewport) => {
68 | return 0
69 | }}
70 | closedDrawerOffset={(viewport) => {
71 | return 0
72 | }}
73 | panOpenMask={0.2}
74 | tweenHandler={(ratio) => ({
75 | mainOverlay: { opacity:(2-ratio)/2 }
76 | })}
77 | negotiatePan
78 | side={'left'}
79 | >
80 |
81 |
82 | )
83 | }
84 | };
85 |
86 | /*
87 | class DrawerView extends Component {
88 |
89 | closeDrawer = () => {
90 | this._drawer.close()
91 | };
92 |
93 | openDrawer = () => {
94 | this._drawer.open()
95 | };
96 |
97 | render(){
98 | const state = this.props.navigationState;
99 | const children = state.children;
100 | return (
101 | Actions.refresh({key:state.key, open: true})}
105 | onClose={()=>Actions.refresh({key:state.key, open: false})}
106 | type="displace"
107 | content={}
108 | tapToClose={true}
109 | openDrawerOffset={0.2}
110 | panCloseMask={0.2}
111 | negotiatePan={true}
112 | tweenHandler={(ratio) => ({
113 | main: { opacity:Math.max(0.54,1-ratio) }
114 | })}>
115 |
116 |
117 | );
118 | }
119 | }
120 | */
121 |
122 | var drawerStyles = {
123 | drawer: {
124 | shadowColor: "#000000",
125 | shadowOpacity: 0.2,
126 | shadowRadius: 0,
127 | marginRight: 100,
128 | },
129 |
130 | main: {
131 | shadowColor: "#000000",
132 | shadowOpacity: 0.2,
133 | shadowRadius: 0,
134 | },
135 |
136 | mainOverlay: {
137 | }
138 | }
139 |
140 | module.exports = DrawerView;
141 |
--------------------------------------------------------------------------------
/style/global.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import { StyleSheet } from 'react-native';
5 |
6 | module.exports = StyleSheet.create({
7 | container: {
8 | flex: 1,
9 | },
10 | wrap: {
11 | marginTop: 40,
12 | flex: 1
13 | },
14 | heading: {
15 | fontFamily: 'Berlin',
16 | fontSize: 15,
17 | textAlign: 'center',
18 | backgroundColor: 'transparent',
19 | color: 'white',
20 | height: 30,
21 | textDecorationLine: 'underline',
22 | },
23 | notification: {
24 | fontFamily: 'ArticulatCF-Light',
25 | fontSize: 20,
26 | textAlign: 'center',
27 | backgroundColor: 'rgba(0, 0, 0, 0.3)',
28 | color: 'white',
29 | borderRadius: 15,
30 | borderWidth: 0,
31 | borderColor: 'transparent',
32 | paddingTop: 10,
33 | paddingBottom: 10,
34 | marginLeft: 50,
35 | marginRight: 50,
36 | },
37 | balanceContainerWrap: {
38 | flex: 1,
39 | flexDirection: 'column',
40 | alignItems: 'center',
41 | marginLeft: 20,
42 | backgroundColor: 'transparent',
43 | borderWidth: 0,
44 | borderColor: 'transparent',
45 | },
46 | balanceContainer: {
47 | marginTop: 0,
48 | flex: 1,
49 | flexDirection: 'row',
50 | backgroundColor: 'transparent',
51 | borderWidth: 0,
52 | borderColor: 'transparent',
53 | paddingLeft: 20,
54 | paddingRight: 50,
55 | },
56 | balance: {
57 | fontFamily: 'Berlin',
58 | fontSize: 50,
59 | flex: 0,
60 | flexDirection: 'column',
61 | alignItems: 'center',
62 | borderWidth: 0,
63 | borderColor: 'transparent',
64 | marginTop: 10,
65 | marginBottom: 10,
66 | color: 'white',
67 | paddingTop: 0,
68 | paddingBottom: 0,
69 | },
70 | balanceDecimal: {
71 | fontFamily: 'Berlin',
72 | fontSize: 20,
73 | flex: 0,
74 | flexDirection: 'column',
75 | alignItems: 'center',
76 | height: 20,
77 | borderWidth: 0,
78 | borderColor: 'transparent',
79 | marginTop: 10,
80 | marginBottom: 10,
81 | color: 'white',
82 | paddingTop: 0,
83 | paddingBottom: 0,
84 | },
85 | contactItem: {
86 | backgroundColor: 'transparent',
87 | borderRadius: 15,
88 | borderWidth: 0,
89 | borderBottomColor: 'white',
90 | borderBottomWidth: 1,
91 | borderColor: 'transparent',
92 | paddingTop: 5,
93 | paddingBottom: 5,
94 | marginLeft: 40,
95 | marginRight: 40,
96 | marginTop: 10,
97 | marginBottom: 10,
98 | },
99 | contactItemText: {
100 | textAlign: 'left',
101 | fontFamily: 'ArticulatCF-Light',
102 | fontSize: 15,
103 | color: 'white',
104 | marginLeft: 10,
105 | },
106 | contactInfoHeading: {
107 | textAlign: 'left',
108 | fontFamily: 'ArticulatCF-Light',
109 | fontSize: 15,
110 | color: 'white',
111 | backgroundColor: 'transparent',
112 | marginLeft: 20,
113 | textDecorationLine: 'underline',
114 | paddingTop: 5,
115 | paddingBottom: 5,
116 | },
117 | contactInfo: {
118 | textAlign: 'left',
119 | fontFamily: 'ArticulatCF-Light',
120 | fontSize: 15,
121 | color: 'white',
122 | backgroundColor: 'transparent',
123 | marginLeft: 20,
124 | paddingTop: 5,
125 | paddingBottom: 15,
126 | },
127 | generalText: {
128 | textAlign: 'center',
129 | fontFamily: 'ArticulatCF-Light',
130 | fontSize: 15,
131 | color: 'white',
132 | backgroundColor: 'transparent',
133 | marginLeft: 20,
134 | paddingTop: 5,
135 | paddingBottom: 15,
136 | },
137 | aboutText: {
138 | textAlign: 'center',
139 | backgroundColor: 'transparent',
140 | fontFamily: 'ArticulatCF-Light',
141 | fontSize: 25,
142 | color: 'white',
143 | marginLeft: 10,
144 | marginTop: 20,
145 | },
146 | });
147 |
148 |
--------------------------------------------------------------------------------
/libs/RealmDB.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Realm for a database - realm.io
4 | // Encrypt database
5 | var key = new Int8Array(64);
6 | const Realm = require('realm');
7 | //Realm.defaultPath = "/Users/ksred/Documents/Projects/Bank/ReactNative/BankReact/realm/default.realm";
8 |
9 | // @TODO Move schemas into separate file
10 | // Set up schemas
11 | const AccountSchema = {
12 | name: 'Account',
13 | properties: {
14 | AccountNumber: { type: 'string' , indexed: true, optional: true, default: '' },
15 | BankNumber: { type: 'string', optional: true, default: '' },
16 | AccountHolderName: { type: 'string', optional: true, default: '' },
17 | AccountBalance: { type: 'float', optional: true, default: 0 }, // Decimal
18 | Overdraft: { type: 'float', optional: true, default: 0 },
19 | AvailableBalance: { type: 'float', optional: true, default: 0 },
20 | Timestamp: { type: 'int', optional: true, default: 0 },
21 | }
22 | };
23 | const AccountAuthSchema = {
24 | name: 'AccountAuth',
25 | properties: {
26 | AccountNumber: { type: 'string', indexed: true, optional: true, default: '' },
27 | Password: { type: 'string', optional: true, default: '' },
28 | Timestamp: { type: 'int', optional: true, default: '' },
29 | }
30 | };
31 | const AccountTokenSchema = {
32 | name: 'AccountToken',
33 | properties: {
34 | Token: { type: 'string', optional: true, default: '' },
35 | Timestamp: { type: 'int', optional: true, default: '' },
36 | }
37 | };
38 | const DeviceTokenSchema = {
39 | name: 'DeviceToken',
40 | properties: {
41 | Token: { type: 'string', optional: true, default: '' },
42 | Platform: { type: 'string', optional: true, default: '' }
43 | }
44 | };
45 | const AccountMetaSchema = {
46 | name: 'AccountMeta',
47 | properties: {
48 | AccountHolderGivenName: { type: 'string', optional: true, default: '' },
49 | AccountHolderFamilyName: { type: 'string', optional: true, default: '' },
50 | AccountHolderDateOfBirth: { type: 'string', optional: true, default: '' },
51 | AccountHolderIdentificationNumber: { type: 'string', optional: true, default: '' },
52 | AccountHolderContactNumber1: { type: 'string', optional: true, default: '' },
53 | AccountHolderContactNumber2: { type: 'string', optional: true, default: '' },
54 | AccountHolderEmailAddress: { type: 'string', optional: true, default: '' },
55 | AccountHolderAddressLine1: { type: 'string', optional: true, default: '' },
56 | AccountHolderAddressLine2: { type: 'string', optional: true, default: '' },
57 | AccountHolderAddressLine3: { type: 'string', optional: true, default: '' },
58 | AccountHolderPostalCode: { type: 'string', optional: true, default: '' },
59 | }
60 | };
61 | const TransactionsSchema = {
62 | name: 'Transactions',
63 | primaryKey: 'Transaction',
64 | properties: {
65 | Transaction: { type: 'int', indexed: true },
66 | Type: { type: 'int', optional: true, default: '' },
67 | SenderAccountNumber: { type: 'string', optional: true, default: '' },
68 | SenderBankNumber: { type: 'string', optional: true, default: '' },
69 | ReceiverAccountNumber: { type: 'string', optional: true, default: '' },
70 | ReceiverBankNumber: { type: 'string', optional: true, default: '' },
71 | TransactionAmount: 'float',
72 | SenderName: { type: 'string', optional: true, default: '' },
73 | ReceiverName: { type: 'string', optional: true, default: '' },
74 | FeeAmount: { type: 'float', optional: true, default: '' },
75 | Lat: { type: 'float', optional: true, default: 0 },
76 | Lon: { type: 'float', optional: true, default: 0 },
77 | Desc: { type: 'string', optional: true, default: '' },
78 | Status: { type: 'string', optional: true, default: '' },
79 | Timestamp: { type: 'int', optional: true, default: 0 },
80 | }
81 | };
82 | const ContactsSchema = {
83 | name: 'Contacts',
84 | properties: {
85 | ContactName: { type: 'string', indexed: true, optional: true, default: '' },
86 | ContactAccountNumber: { type: 'string', optional: true, default: '' },
87 | ContactBankNumber: { type: 'string', optional: true, default: '' },
88 | ContactEmailAddress: { type: 'string', optional: true, default: '' },
89 | }
90 | };
91 |
92 | let realm = new Realm({ schema: [ AccountSchema, AccountMetaSchema, AccountAuthSchema, AccountTokenSchema, DeviceTokenSchema, TransactionsSchema, ContactsSchema ], schemaVersion: 20 });
93 |
94 | module.exports = realm;
95 |
--------------------------------------------------------------------------------
/android/app/react.gradle:
--------------------------------------------------------------------------------
1 | import org.apache.tools.ant.taskdefs.condition.Os
2 |
3 | def config = project.hasProperty("react") ? project.react : [];
4 |
5 | def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
6 | def entryFile = config.entryFile ?: "index.android.js"
7 |
8 | // because elvis operator
9 | def elvisFile(thing) {
10 | return thing ? file(thing) : null;
11 | }
12 |
13 | def reactRoot = elvisFile(config.root) ?: file("../../")
14 | def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
15 |
16 | void runBefore(String dependentTaskName, Task task) {
17 | Task dependentTask = tasks.findByPath(dependentTaskName);
18 | if (dependentTask != null) {
19 | dependentTask.dependsOn task
20 | }
21 | }
22 |
23 | gradle.projectsEvaluated {
24 | // Grab all build types and product flavors
25 | def buildTypes = android.buildTypes.collect { type -> type.name }
26 | def productFlavors = android.productFlavors.collect { flavor -> flavor.name }
27 |
28 | // When no product flavors defined, use empty
29 | if (!productFlavors) productFlavors.add('')
30 |
31 | productFlavors.each { productFlavorName ->
32 | buildTypes.each { buildTypeName ->
33 | // Create variant and target names
34 | def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}"
35 | def targetPath = productFlavorName ?
36 | "${productFlavorName}/${buildTypeName}" :
37 | "${buildTypeName}"
38 |
39 | // React js bundle directories
40 | def jsBundleDirConfigName = "jsBundleDir${targetName}"
41 | def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
42 | file("$buildDir/intermediates/assets/${targetPath}")
43 |
44 | def resourcesDirConfigName = "resourcesDir${targetName}"
45 | def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?:
46 | file("$buildDir/intermediates/res/merged/${targetPath}")
47 | def jsBundleFile = file("$jsBundleDir/$bundleAssetName")
48 |
49 | // Bundle task name for variant
50 | def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets"
51 |
52 | def currentBundleTask = tasks.create(
53 | name: bundleJsAndAssetsTaskName,
54 | type: Exec) {
55 | group = "react"
56 | description = "bundle JS and assets for ${targetName}."
57 |
58 | // Create dirs if they are not there (e.g. the "clean" task just ran)
59 | doFirst {
60 | jsBundleDir.mkdirs()
61 | resourcesDir.mkdirs()
62 | }
63 |
64 | // Set up inputs and outputs so gradle can cache the result
65 | inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
66 | outputs.dir jsBundleDir
67 | outputs.dir resourcesDir
68 |
69 | // Set up the call to the react-native cli
70 | workingDir reactRoot
71 |
72 | // Set up dev mode
73 | def devEnabled = !targetName.toLowerCase().contains("release")
74 | if (Os.isFamily(Os.FAMILY_WINDOWS)) {
75 | commandLine "cmd", "/c", "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}",
76 | "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir
77 | } else {
78 | commandLine "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}",
79 | "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir
80 | }
81 |
82 | enabled config."bundleIn${targetName}" ||
83 | config."bundleIn${buildTypeName.capitalize()}" ?:
84 | targetName.toLowerCase().contains("release")
85 | }
86 |
87 | // Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process
88 | currentBundleTask.dependsOn("merge${targetName}Resources")
89 | currentBundleTask.dependsOn("merge${targetName}Assets")
90 |
91 | runBefore("processArmeabi-v7a${targetName}Resources", currentBundleTask)
92 | runBefore("processX86${targetName}Resources", currentBundleTask)
93 | runBefore("processUniversal${targetName}Resources", currentBundleTask)
94 | runBefore("process${targetName}Resources", currentBundleTask)
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/ios/BVNK.xcodeproj/xcshareddata/xcschemes/BVNK.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
78 |
80 |
86 |
87 |
88 |
89 |
90 |
91 |
97 |
99 |
105 |
106 |
107 |
108 |
110 |
111 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/ios/BVNK.xcodeproj/xcshareddata/xcschemes/BankReact.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
78 |
80 |
86 |
87 |
88 |
89 |
90 |
91 |
97 |
99 |
105 |
106 |
107 |
108 |
110 |
111 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/MainPaymentDepositView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Image,
12 | TouchableOpacity,
13 | Alert
14 | } from 'react-native';
15 |
16 | import Button from 'react-native-button'
17 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
18 |
19 | let styles = require('./styles');
20 | let BankClient = require('./libs/BankClient');
21 | let bc = new BankClient();
22 | let db = require('./libs/RealmDB');
23 | let dismissKeyboard = require('dismissKeyboard');
24 |
25 | var MainPaymentDepositView = React.createClass({
26 | getInitialState() {
27 | dismissKeyboard();
28 | return {
29 | depositAmount: '',
30 | depositDesc: '',
31 | initialPosition: 'unknown',
32 | lastPosition: 'unknown',
33 | }
34 | },
35 |
36 | componentDidMount: function() {
37 | navigator.geolocation.getCurrentPosition(
38 | (position) => {
39 | var initialPosition = JSON.stringify(position);
40 | this.setState({initialPosition});
41 | },
42 | (error) => console.log(error.message),
43 | {enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
44 | );
45 |
46 | this.watchID = navigator.geolocation.watchPosition((position) => {
47 | var lastPosition = JSON.stringify(position); this.setState({lastPosition});
48 | });
49 | },
50 |
51 | componentWillUnmount: function() {
52 | navigator.geolocation.clearWatch(this.watchID);
53 | },
54 |
55 | _doDeposit: function() {
56 | let user = db.objects('Account');
57 | if (user.length > 0) {
58 | var userAccount = user.slice(0,1);
59 | userAccount = userAccount[0];
60 | var lat = 0;
61 | var lon = 0;
62 | let lastPosState = this.state.lastPosition;
63 | if (lastPosState != 'unknown') {
64 | let lastPos = JSON.parse(this.state.lastPosition);
65 | lat = lastPos.coords.latitude;
66 | lon = lastPos.coords.longitude;
67 | }
68 | // Replace , with . in payment amount
69 | let paymentAmount = this.state.depositAmount.replace(",", ".");
70 | let data = {
71 | AccountDetails: userAccount.AccountNumber+'@'+userAccount.BankNumber,
72 | Amount: paymentAmount,
73 | Lat: lat,
74 | Lon: lon,
75 | Desc: this.state.depositDesc
76 | };
77 |
78 | let res = bc.paymentDeposit(data, function(res) {
79 | console.log(res);
80 | if (typeof res.error == 'undefined') {
81 | console.log('Go to main...');
82 | dismissKeyboard();
83 | Actions.main({ type: "reset", message: "🎉 Deposit successful"});
84 | } else {
85 | // Show error
86 | dismissKeyboard();
87 | Actions.main({ type : "reset", message: "❌ Error: "+res.error });
88 | }
89 | });
90 | }
91 | },
92 |
93 | render: function() {
94 | return (
95 |
96 |
97 |
98 |
99 |
100 |
101 | DEPOSIT PAYMENT
102 | this.setState({depositAmount})}
105 | value={this.state.depositAmount}
106 | autoCorrect={false}
107 | autoCapitalize="none"
108 | keyboardType='decimal-pad'
109 | placeholder="Deposit Amount"
110 | />
111 | this.setState({depositDesc})}
114 | value={this.state.depositDesc}
115 | autoCorrect={false}
116 | placeholder="Description"
117 | />
118 |
120 |
121 |
122 |
123 | )
124 | }
125 | });
126 |
127 | module.exports = MainPaymentDepositView;
128 |
--------------------------------------------------------------------------------
/MainPaymentCreditView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Image,
12 | TouchableOpacity,
13 | Alert
14 | } from 'react-native';
15 |
16 | import Button from 'react-native-button'
17 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
18 |
19 | let styles = require('./styles');
20 | let BankClient = require('./libs/BankClient');
21 | let bc = new BankClient();
22 | let db = require('./libs/RealmDB');
23 | let dismissKeyboard = require('dismissKeyboard');
24 |
25 | var MainPaymentCreditView = React.createClass({
26 | getInitialState() {
27 | dismissKeyboard();
28 | return {
29 | paymentAmount: '',
30 | paymentDesc: '',
31 | initialPosition: 'unknown',
32 | lastPosition: 'unknown',
33 | }
34 | },
35 |
36 | componentDidMount: function() {
37 | navigator.geolocation.getCurrentPosition(
38 | (position) => {
39 | var initialPosition = JSON.stringify(position);
40 | this.setState({initialPosition});
41 | },
42 | (error) => console.log(error.message),
43 | {enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
44 | );
45 |
46 | this.watchID = navigator.geolocation.watchPosition((position) => {
47 | var lastPosition = JSON.stringify(position); this.setState({lastPosition});
48 | });
49 | },
50 |
51 | componentWillUnmount: function() {
52 | navigator.geolocation.clearWatch(this.watchID);
53 | },
54 |
55 | _doPayment: function() {
56 | let user = db.objects('Account');
57 | if (user.length > 0) {
58 | var userAccount = user.slice(0,1);
59 | userAccount = userAccount[0];
60 | var lat = 0;
61 | var lon = 0;
62 | let lastPosState = this.state.lastPosition;
63 | if (lastPosState != 'unknown') {
64 | let lastPos = JSON.parse(this.state.lastPosition);
65 | lat = lastPos.coords.latitude;
66 | lon = lastPos.coords.longitude;
67 | }
68 | // Replace , with . in payment amount
69 | let paymentAmount = this.state.paymentAmount.replace(",", ".");
70 | let data = {
71 | SenderDetails: userAccount.AccountNumber+'@'+userAccount.BankNumber,
72 | RecipientDetails: this.props.data.ContactAccountNumber+'@'+this.props.data.ContactBankNumber,
73 | Amount: paymentAmount,
74 | Lat: lat,
75 | Lon: lon,
76 | Desc: this.state.paymentDesc
77 | };
78 |
79 | let res = bc.paymentCredit(data, function(res) {
80 | console.log(res);
81 | if (typeof res.error == 'undefined') {
82 | dismissKeyboard();
83 | Actions.main({ type : "reset", message: "💸 Payment successful" });
84 | } else {
85 | // Show error
86 | Actions.main({ type : "reset", message: "❌ Error: "+res.error });
87 | dismissKeyboard();
88 | return;
89 | }
90 | });
91 | }
92 | },
93 |
94 | render: function() {
95 | return (
96 |
97 |
98 |
99 |
100 |
101 |
102 | CREDIT PAYMENT
103 | Make payment to: {this.props.data.ContactName}
104 | this.setState({paymentAmount})}
107 | value={this.state.paymentAmount}
108 | autoCorrect={false}
109 | keyboardType='decimal-pad'
110 | autoCapitalize="none"
111 | placeholder="Payment Amount"
112 | />
113 | this.setState({paymentDesc})}
116 | value={this.state.paymentDesc}
117 | autoCorrect={false}
118 | placeholder="Description"
119 | />
120 |
122 |
123 |
124 |
125 | )
126 | }
127 | });
128 |
129 | module.exports = MainPaymentCreditView;
130 |
--------------------------------------------------------------------------------
/AddContactView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import {
4 | AppRegistry,
5 | Text,
6 | View,
7 | StatusBar,
8 | StyleSheet,
9 | TextInput,
10 | Image,
11 | TouchableOpacity,
12 | ListView,
13 | Alert
14 | } from 'react-native';
15 |
16 | import React, { Component } from 'react';
17 |
18 | import Button from 'react-native-button'
19 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
20 |
21 | let styles = require('./styles');
22 | let BankClient = require('./libs/BankClient');
23 | let bc = new BankClient();
24 | let db = require('./libs/RealmDB');
25 | let dismissKeyboard = require('dismissKeyboard');
26 |
27 | var AddContactView = React.createClass({
28 | getInitialState() {
29 | dismissKeyboard();
30 | let contacts = [];
31 | var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
32 | return {
33 | search: '',
34 | message: '',
35 | dataSource: ds.cloneWithRows(contacts),
36 | }
37 | },
38 |
39 | componentDidMount: function() {
40 | },
41 |
42 | componentWillUnmount: function() {
43 | },
44 |
45 | _doSearch: function() {
46 | let data = {
47 | Search: this.state.search,
48 | };
49 |
50 | var self = this;
51 | let res = bc.accountSearch(data, function(res) {
52 | console.log(res);
53 | if (typeof res.error == 'undefined') {
54 | if (res.response.length == 0) {
55 | self.setState({ 'message' : 'No contacts found' });
56 | self.setState({
57 | dataSource: self.state.dataSource.cloneWithRows([])
58 | })
59 | return;
60 | }
61 | self.setState({ 'message' : '' });
62 | var newDs = res.response;
63 | self.setState({
64 | dataSource: self.state.dataSource.cloneWithRows(newDs)
65 | })
66 | dismissKeyboard();
67 | } else {
68 | // Show error
69 | self.setState({ 'message' : res.error });
70 | dismissKeyboard();
71 | return;
72 | }
73 | });
74 | },
75 |
76 | addContact: function(data) {
77 | db.write(() => {
78 | // Check if contact exists
79 | var contactDB = db.objects('Contacts').filtered('ContactName == $0 && ContactAccountNumber == $1 && ContactBankNumber == $2', (data.FamilyName + ',' + data.GivenName), data.AccountNumber, data.BankNumber);
80 |
81 | if (contactDB.length == 0) {
82 | db.create('Contacts', { ContactName: (data.FamilyName+','+data.GivenName), ContactAccountNumber: data.AccountNumber, ContactBankNumber: data.BankNumber, ContactEmailAddress: data.EmailAddress });
83 | // Fetch contact
84 | contactDB = db.objects('Contacts').filtered('ContactName == $0 && ContactAccountNumber == $1 && ContactBankNumber == $2', (data.FamilyName + ',' + data.GivenName), data.AccountNumber, data.BankNumber);
85 | };
86 |
87 | Actions.contact({data: contactDB[0], type: 'reset'});
88 | return;
89 | });
90 | },
91 |
92 | render: function() {
93 | var notificationMessage;
94 | if (this.state.message != '') {
95 | notificationMessage = {this.state.message};
96 | }
97 |
98 | return (
99 |
100 |
101 |
102 |
103 |
104 |
105 | CONTACT SEARCH
106 | this.setState({search})}
109 | value={this.state.search}
110 | autoCorrect={false}
111 | placeholder="Email, ID or Name"
112 | />
113 |
115 | {notificationMessage}
116 |
117 |
121 |
123 | this.addContact(rowData)}
124 | style={styles.global.contactItemText}>{rowData.FamilyName}, {rowData.GivenName}
125 | }
126 | />
127 |
128 |
129 |
130 | )
131 | }
132 | });
133 |
134 | module.exports = AddContactView;
135 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // the entry file for bundle generation
19 | * entryFile: "index.android.js",
20 | *
21 | * // whether to bundle JS and assets in debug mode
22 | * bundleInDebug: false,
23 | *
24 | * // whether to bundle JS and assets in release mode
25 | * bundleInRelease: true,
26 | *
27 | * // whether to bundle JS and assets in another build variant (if configured).
28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
29 | * // The configuration property can be in the following formats
30 | * // 'bundleIn${productFlavor}${buildType}'
31 | * // 'bundleIn${buildType}'
32 | * // bundleInFreeDebug: true,
33 | * // bundleInPaidRelease: true,
34 | * // bundleInBeta: true,
35 | *
36 | * // the root of your project, i.e. where "package.json" lives
37 | * root: "../../",
38 | *
39 | * // where to put the JS bundle asset in debug mode
40 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
41 | *
42 | * // where to put the JS bundle asset in release mode
43 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
44 | *
45 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
46 | * // require('./image.png')), in debug mode
47 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
48 | *
49 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
50 | * // require('./image.png')), in release mode
51 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
52 | *
53 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
54 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
55 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
56 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
57 | * // for example, you might want to remove it from here.
58 | * inputExcludes: ["android/**", "ios/**"]
59 | * ]
60 | */
61 |
62 | apply from: "react.gradle"
63 |
64 | /**
65 | * Set this to true to create two separate APKs instead of one:
66 | * - An APK that only works on ARM devices
67 | * - An APK that only works on x86 devices
68 | * The advantage is the size of the APK is reduced by about 4MB.
69 | * Upload all the APKs to the Play Store and people will download
70 | * the correct one based on the CPU architecture of their device.
71 | */
72 | def enableSeparateBuildPerCPUArchitecture = false
73 |
74 | /**
75 | * Run Proguard to shrink the Java bytecode in release builds.
76 | */
77 | def enableProguardInReleaseBuilds = false
78 |
79 | android {
80 | compileSdkVersion 23
81 | buildToolsVersion "23.0.1"
82 |
83 | defaultConfig {
84 | applicationId "com.bvnk"
85 | minSdkVersion 16
86 | targetSdkVersion 22
87 | versionCode 1
88 | versionName "1.0"
89 | ndk {
90 | abiFilters "armeabi-v7a", "x86"
91 | }
92 | }
93 | splits {
94 | abi {
95 | reset()
96 | enable enableSeparateBuildPerCPUArchitecture
97 | universalApk false // If true, also generate a universal APK
98 | include "armeabi-v7a", "x86"
99 | }
100 | }
101 | buildTypes {
102 | release {
103 | minifyEnabled enableProguardInReleaseBuilds
104 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
105 | }
106 | }
107 | // applicationVariants are e.g. debug, release
108 | applicationVariants.all { variant ->
109 | variant.outputs.each { output ->
110 | // For each separate APK per architecture, set a unique version code as described here:
111 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
112 | def versionCodes = ["armeabi-v7a":1, "x86":2]
113 | def abi = output.getFilter(OutputFile.ABI)
114 | if (abi != null) { // null for the universal-debug, universal-release variants
115 | output.versionCodeOverride =
116 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
117 | }
118 | }
119 | }
120 | }
121 |
122 | dependencies {
123 | compile project(':react-native-push-notification')
124 | compile project(':react-native-maps')
125 | compile project(':realm')
126 | compile fileTree(dir: "libs", include: ["*.jar"])
127 | compile "com.android.support:appcompat-v7:23.0.1"
128 | compile "com.facebook.react:react-native:+" // From node_modules
129 | }
130 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/CreateAuthView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Image,
12 | Alert
13 | } from 'react-native';
14 |
15 | import Button from 'react-native-button'
16 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
17 |
18 | let styles = require('./styles');
19 | let BankClient = require('./libs/BankClient');
20 | let bc = new BankClient();
21 | let db = require('./libs/RealmDB');
22 | let dismissKeyboard = require('dismissKeyboard');
23 |
24 | var CreateAuthView = React.createClass({
25 | getInitialState() {
26 | dismissKeyboard();
27 | return {
28 | password: ''
29 | }
30 | },
31 |
32 | doLogin: function() {
33 | console.log('Do login called');
34 | let userAuth = db.objects('AccountAuth');
35 | if (userAuth.length > 0) {
36 | var userAccount = userAuth.slice(0,1);
37 | userAccount = userAccount[0];
38 |
39 | let data = { User: userAccount.AccountNumber, Password: userAccount.Password };
40 | let res = bc.authLogin(data, function(res) {
41 | if (typeof res.error == 'undefined') {
42 | console.log(res);
43 | console.log(res.response);
44 | // Get token
45 | let token = res.response;
46 | db.write(() => {
47 | // Delete tokens
48 | let allTokens = db.objects('AccountToken');
49 | db.delete(allTokens);
50 |
51 | db.create('AccountToken', {
52 | Token: token,
53 | //Timestamp: Math.floor(Date.now())
54 | Timestamp: 1
55 | });
56 | });
57 | // Go to account landing view
58 | dismissKeyboard();
59 | Actions.main({type : "reset"});
60 | } else {
61 | // Show error
62 | Alert.alert('Error', res.error);
63 | dismissKeyboard();
64 | return;
65 | }
66 | });
67 | }
68 | },
69 |
70 | _doCreateAuth: function() {
71 | //Alert.alert('Password', this.state.password);
72 | // Get user account number
73 | let user = db.objects('Account');
74 | // Check if there is a result
75 | if (user.length > 0)
76 | {
77 | // Get first user account
78 | var userAccount = user.slice(0,1);
79 | userAccount = userAccount[0];
80 | let data = {User: userAccount.AccountNumber, Password: this.state.password};
81 | let res = bc.authCreate(data, this.authCreateCallback);
82 | }
83 | },
84 |
85 | authCreateCallback: function(res) {
86 | let user = db.objects('Account');
87 | // Check if there is a result
88 | if (user.length > 0)
89 | {
90 | // Get first user account
91 | var userAccount = user.slice(0,1);
92 | userAccount = userAccount[0];
93 | let data = {User: userAccount.AccountNumber, Password: this.state.password};
94 | console.log(res);
95 | if (typeof res.error == 'undefined') {
96 | console.log('before insert');
97 | // Save account auth details
98 | db.write(() => {
99 | let auth = db.objects('AccountAuth');
100 | db.delete(auth);
101 |
102 | db.create('AccountAuth', {
103 | AccountNumber: data.User,
104 | Password: data.Password,
105 | //Timestamp: Math.floor(Date.now())
106 | Timestamp: 1
107 | });
108 | });
109 | // Log user in
110 | console.log('after insert');
111 | this.doLogin();
112 | } else if (res.error == 'appauth.CreateUserPassword: Account already exists'){
113 | // Log user in
114 | console.log('at error, show login');
115 | this.doLogin();
116 | } else {
117 | // Show error
118 | Alert.alert('Error', res.error);
119 | return;
120 | }
121 | }
122 | },
123 |
124 | render: function() {
125 | return (
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | this.setState({password})}
136 | value={this.state.password}
137 | autoCorrect={false}
138 | keyboardAppearance="dark"
139 | autoCapitalize="none"
140 | secureTextEntry={true}
141 | placeholder="Password"
142 | />
143 |
145 |
146 |
147 |
148 |
149 | )
150 | }
151 | });
152 |
153 | module.exports = CreateAuthView;
154 |
--------------------------------------------------------------------------------
/MainTransactionsView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | ListView,
12 | Image,
13 | TouchableOpacity,
14 | Alert
15 | } from 'react-native';
16 |
17 | import Button from 'react-native-button'
18 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
19 |
20 | let styles = require('./styles');
21 | let BankClient = require('./libs/BankClient');
22 | let bc = new BankClient();
23 | let db = require('./libs/RealmDB');
24 | let dismissKeyboard = require('dismissKeyboard');
25 |
26 | var MainTransactionsView = React.createClass({
27 |
28 | getInitialState: function() {
29 | dismissKeyboard();
30 | // Limit to 100 transactions
31 | let transactions = db.objects('Transactions').sorted('Timestamp', 'reverse').slice(0, 100);
32 | var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
33 | return {
34 | dataSource: ds.cloneWithRows(transactions),
35 | };
36 | },
37 |
38 | timeConverter: function(UNIX_timestamp) {
39 | var a = new Date(UNIX_timestamp * 1000);
40 | var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
41 | var year = a.getFullYear();
42 | var month = months[a.getMonth()];
43 | var date = a.getDate();
44 | var hour = a.getHours();
45 | var min = a.getMinutes();
46 | var sec = a.getSeconds();
47 | var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ;
48 | return time;
49 | },
50 |
51 |
52 | componentDidMount: function() {
53 | // Get latest transactions
54 | let transactionsRes = db.objects('Transactions');
55 | var transactionsResSorted = transactionsRes.sorted('Timestamp');
56 | var timestamp = 0
57 | if (transactionsResSorted.length > 0) {
58 | // Get latest
59 | let latestTransaction = transactionsResSorted.slice(transactionsResSorted.length - 1, transactionsResSorted.length);
60 | if (latestTransaction.length > 0) {
61 | timestamp = latestTransaction[0].Timestamp;
62 | }
63 | }
64 |
65 | // We set up the data to fetch 20 records
66 | // @TODO implement pagination/inifinte scrolling
67 | let data = {
68 | perPage : 20,
69 | page : 0,
70 | timestamp : timestamp
71 | };
72 |
73 | let res = bc.transactionsListAfterTimestamp(data, function(res) {
74 | if (typeof res.error == 'undefined') {
75 | let transactionList = res.response;
76 | db.write(() => {
77 | transactionList.forEach(function(t) {
78 | // Check if transaction exists
79 | let trDB = db.objects('Transactions').filtered('Transaction == $0', t.ID);
80 |
81 | if (trDB.length == 0) {
82 | var senderName = "";
83 | var receiverName = "";
84 |
85 | var contact = db.objects('Contacts').filtered('ContactAccountNumber == $0 && ContactBankNumber == $1', t.Receiver.AccountNumber, t.Receiver.BankNumber);
86 | if (contact.length > 0) {
87 | receiverName = contact[0].ContactName;
88 | }
89 |
90 | contact = db.objects('Contacts').filtered('ContactAccountNumber == $0 && ContactBankNumber == $1', t.Sender.AccountNumber, t.Sender.BankNumber);
91 | if (contact.length > 0) {
92 | senderName = contact[0].ContactName;
93 | }
94 | db.create('Transactions', {
95 | Transaction: t.ID,
96 | Type: t.PainType,
97 | SenderAccountNumber: t.Sender.AccountNumber,
98 | SenderBankNumber: t.Sender.BankNumber,
99 | ReceiverAccountNumber: t.Receiver.AccountNumber,
100 | ReceiverBankNumber: t.Receiver.BankNumber,
101 | TransactionAmount: t.Amount,
102 | FeeAmount: t.Fee,
103 | Lat: t.Geo[0],
104 | Lon: t.Geo[1],
105 | Desc: t.Desc,
106 | Status: t.Status,
107 | Timestamp: t.Timestamp,
108 | });
109 | }
110 | });
111 | });
112 | } else {
113 | Alert.alert('Error', 'Could not update account details: '+res.error);
114 | console.log(res);
115 | dismissKeyboard();
116 | return;
117 | }
118 | });
119 | },
120 |
121 | render: function() {
122 | return (
123 |
124 |
125 |
126 |
127 |
128 |
129 | TRANSACTIONS
130 |
134 |
136 | Actions.transaction({ data: rowData })} style={styles.transaction.desc}>{rowData.Desc}
137 | Actions.transaction({ data: rowData })} style={styles.transaction.time}>{this.timeConverter(rowData.Timestamp)}
138 | }
139 | />
140 |
141 |
142 |
143 | )
144 | }
145 | });
146 |
147 | module.exports = MainTransactionsView;
148 |
--------------------------------------------------------------------------------
/TransactionView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Image,
12 | Alert
13 | } from 'react-native';
14 |
15 | import Button from 'react-native-button'
16 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
17 | import MapView from 'react-native-maps';
18 |
19 | let styles = require('./styles');
20 | let BankClient = require('./libs/BankClient');
21 | let bc = new BankClient();
22 | let db = require('./libs/RealmDB');
23 | let dismissKeyboard = require('dismissKeyboard');
24 |
25 | var TransactionView = React.createClass({
26 | getInitialState() {
27 | dismissKeyboard();
28 | return {
29 | data: { },
30 | transaction: { },
31 | }
32 | },
33 |
34 | timeConverter: function(UNIX_timestamp) {
35 | var a = new Date(UNIX_timestamp * 1000);
36 | var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
37 | var year = a.getFullYear();
38 | var month = months[a.getMonth()];
39 | var date = a.getDate();
40 | var hour = a.getHours();
41 | var min = a.getMinutes();
42 | var sec = a.getSeconds();
43 | var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ;
44 | return time;
45 | },
46 |
47 | checkTransactionDetails: function() {
48 | db.write(() => {
49 | // Check if transaction exists
50 | let trDB = db.objects('Transactions').filtered('Transaction == $0', this.props.data.Transaction);
51 | console.log("Check length of transaction");
52 | console.log(trDB.length);
53 | console.log(this.props.data);
54 |
55 | if ((trDB.length == 1) && (this.props.data.ReceiverName == "") && (this.props.data.SenderName == "")) {
56 | let transaction = trDB[0];
57 | var senderName = "";
58 | var receiverName = "";
59 |
60 | var contact = db.objects('Contacts').filtered('ContactAccountNumber == $0 && ContactBankNumber == $1', transaction.ReceiverAccountNumber, transaction.ReceiverBankNumber);
61 | if (contact.length > 0) {
62 | receiverName = contact[0].ContactName;
63 | }
64 |
65 | contact = db.objects('Contacts').filtered('ContactAccountNumber == $0 && ContactBankNumber == $1', transaction.SenderAccountNumber, transaction.SenderBankNumber);
66 | if (contact.length > 0) {
67 | senderName = contact[0].ContactName;
68 | }
69 |
70 | db.create('Transactions', {
71 | Transaction: transaction.Transaction,
72 | Type: transaction.Type,
73 | SenderAccountNumber: transaction.SenderAccountNumber,
74 | SenderBankNumber: transaction.SenderBankNumber,
75 | ReceiverAccountNumber: transaction.ReceiverAccountNumber,
76 | ReceiverBankNumber: transaction.ReceiverBankNumber,
77 | TransactionAmount: transaction.TransactionAmount,
78 | SenderName: senderName,
79 | ReceiverName: receiverName,
80 | FeeAmount: transaction.FeeAmount,
81 | Lat: transaction.Lat,
82 | Lon: transaction.Lon,
83 | Desc: transaction.Desc,
84 | Status: transaction.Status,
85 | Timestamp: transaction.Timestamp,
86 | }, true);
87 | }
88 | });
89 | },
90 |
91 | updateStateListener: function() {
92 | let id = parseInt(this.props.data.Transaction);
93 | let trDB = db.objects('Transactions').filtered('Transaction == $0', id);
94 | var transArr = trDB.slice(0,1);
95 | let transaction = transArr[0];
96 | this.setState({ 'transaction' : transaction });
97 | },
98 |
99 | componentDidMount: function() {
100 | // Update transaction list
101 | this.checkTransactionDetails();
102 | this.updateStateListener();
103 | // Observe Realm Change Events
104 | db.addListener('change', this.updateStateListener);
105 | },
106 |
107 | componentWillUnmount: function() {
108 | // Remove the listener
109 | db.removeListener('change', this.updateStateListener);
110 | },
111 |
112 | render: function() {
113 |
114 | let marker = { latitude: this.props.data.Lat, longitude: this.props.data.Lon };
115 | //let marker = { latitude: 37.7749, longitude: -122.4194 };
116 | console.log(marker);
117 |
118 | return (
119 |
120 |
121 |
122 |
123 |
124 |
125 |
136 |
141 |
142 | Sender: {this.props.data.SenderName}
143 | Receipient: {this.props.data.ReceiverName}
144 | {this.props.data.Desc}
145 | Amount: {this.props.data.TransactionAmount.toFixed(4)}
146 | Fee: {this.props.data.FeeAmount.toFixed(4)}
147 | {this.timeConverter(this.props.data.Timestamp)}
148 |
149 |
152 |
153 |
154 |
155 | )
156 | }
157 | });
158 |
159 | module.exports = TransactionView;
160 |
--------------------------------------------------------------------------------
/RegisterView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | TextInput,
8 | View,
9 | StatusBar,
10 | StyleSheet,
11 | Image,
12 | Alert
13 | } from 'react-native';
14 |
15 | import Button from 'react-native-button'
16 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
17 |
18 | var styles = require('./styles');
19 | let BankClient = require('./libs/BankClient');
20 | let bc = new BankClient();
21 | let db = require('./libs/RealmDB');
22 | let dismissKeyboard = require('dismissKeyboard');
23 |
24 | var RegisterView = React.createClass({
25 | getInitialState() {
26 | dismissKeyboard();
27 | return {
28 | givenName: '',
29 | familyName: '',
30 | idNumber: '',
31 | email: ''
32 | }
33 | },
34 |
35 | _doRegister: function() {
36 | let data = {
37 | AccountHolderGivenName: this.state.givenName,
38 | AccountHolderFamilyName: this.state.familyName,
39 | AccountHolderDateOfBirth: '',
40 | AccountHolderIdentificationNumber: this.state.idNumber,
41 | AccountHolderContactNumber1: '',
42 | AccountHolderContactNumber2: '',
43 | AccountHolderEmailAddress: this.state.email,
44 | AccountHolderAddressLine1: '',
45 | AccountHolderAddressLine2: '',
46 | AccountHolderAddressLine3: '',
47 | AccountHolderPostalCode: '',
48 | };
49 | let res = bc.accountCreate(data, function(res) {
50 | console.log("At register");
51 | console.log(res);
52 | console.log('One');
53 | console.log(res.response);
54 | console.log('Two');
55 | console.log(typeof res.response);
56 | console.log('Three');
57 | if (typeof res.response != 'undefined') {
58 | let accountId = res.response;
59 | console.log('AccountID: '+accountId);
60 | // Set in DB
61 | db.write(() => {
62 | // Delete all other accounts for now
63 | let accounts = db.objects('Account');
64 | db.delete(accounts);
65 | let contacts = db.objects('Contacts');
66 | db.delete(contacts);
67 | let transactions = db.objects('Transactions');
68 | db.delete(transactions);
69 | let auth = db.objects('AccountAuth');
70 | db.delete(auth);
71 | let authToken = db.objects('AccountToken');
72 | db.delete(authToken);
73 | let accountMeta = db.objects('AccountMeta');
74 | db.delete(accountMeta);
75 | let deviceToken = db.objects('DeviceToken');
76 | db.delete(deviceToken);
77 |
78 | db.create('Account', {
79 | AccountNumber: accountId,
80 | BankNumber: '',
81 | AccountHolderName: data.AccountHolderFamilyName+','+data.AccountHolderGivenName,
82 | AccountBalance: 0,
83 | Overdraft: 0,
84 | AvailableBalance: 0,
85 | //Timestamp: Math.floor(Date.now())
86 | Timestamp: 1
87 | });
88 | });
89 | console.log('Written');
90 | // Read the account value from DB
91 | let user = db.objects('Account');
92 | let userAccount = user.filtered('AccountNumber == $0', accountId);
93 | console.log('User?');
94 | console.log(userAccount);
95 | dismissKeyboard();
96 | if (userAccount.length == 1) {
97 | console.log("Successfull")
98 | console.log(userAccount[0]);
99 | Actions.createAuth();
100 | }
101 | // Alert token value
102 | // Load new page
103 | } else if (typeof res.error != 'undefined') {
104 | dismissKeyboard();
105 | Alert.alert('Error', res.error);
106 | console.log('Error');
107 | }
108 | });
109 | },
110 |
111 | render() {
112 | return (
113 |
114 |
115 |
116 |
117 |
118 | this.setState({givenName})}
121 | value={this.state.givenName}
122 | autoCorrect={false}
123 | placeholder="Given Name"
124 | />
125 | this.setState({familyName})}
128 | value={this.state.familyName}
129 | autoCorrect={false}
130 | placeholder="Family Name"
131 | />
132 | this.setState({idNumber})}
135 | value={this.state.idNumber}
136 | autoCorrect={false}
137 | keyboardType='number-pad'
138 | placeholder="ID Number"
139 | />
140 | this.setState({email})}
143 | value={this.state.email}
144 | autoCorrect={false}
145 | autoCapitalize="none"
146 | keyboardType='email-address'
147 | placeholder="Email"
148 | />
149 |
151 |
152 |
153 | )
154 | }
155 | });
156 |
157 | module.exports = RegisterView;
158 |
--------------------------------------------------------------------------------
/FetchAccountView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Image,
12 | Alert
13 | } from 'react-native';
14 |
15 | import Button from 'react-native-button'
16 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
17 |
18 | let styles = require('./styles');
19 | let BankClient = require('./libs/BankClient');
20 | let bc = new BankClient();
21 | let db = require('./libs/RealmDB');
22 | let dismissKeyboard = require('dismissKeyboard');
23 |
24 | var FetchAccountView = React.createClass({
25 | getInitialState() {
26 | dismissKeyboard();
27 | return {
28 | givenName: '',
29 | familyName: '',
30 | idNumber: '',
31 | email: ''
32 | }
33 | },
34 |
35 | _doFetchAccount: function() {
36 | let data = {
37 | AccountHolderGivenName: this.state.givenName,
38 | AccountHolderFamilyName: this.state.familyName,
39 | AccountHolderDateOfBirth: '',
40 | AccountHolderIdentificationNumber: this.state.idNumber,
41 | AccountHolderContactNumber1: '',
42 | AccountHolderContactNumber2: '',
43 | AccountHolderEmailAddress: this.state.email,
44 | AccountHolderAddressLine1: '',
45 | AccountHolderAddressLine2: '',
46 | AccountHolderAddressLine3: '',
47 | AccountHolderPostalCode: '',
48 | };
49 | let res = bc.fetchAccount(data, function(res) {
50 | if (typeof res.response != 'undefined') {
51 | let accountId = res.response;
52 | if (accountId == "") {
53 | // Account not found
54 | alert("Account not found");
55 | }
56 | console.log('AccountID: '+accountId);
57 | // Set in DB
58 | db.write(() => {
59 | // Delete all other accounts for now
60 | let accounts = db.objects('Account');
61 | db.delete(accounts);
62 | let contacts = db.objects('Contacts');
63 | db.delete(contacts);
64 | let transactions = db.objects('Transactions');
65 | db.delete(transactions);
66 | let auth = db.objects('AccountAuth');
67 | db.delete(auth);
68 | let authToken = db.objects('AccountToken');
69 | db.delete(authToken);
70 | let accountMeta = db.objects('AccountMeta');
71 | db.delete(accountMeta);
72 | let deviceToken = db.objects('DeviceToken');
73 | db.delete(deviceToken);
74 |
75 | db.create('Account', {
76 | AccountNumber: accountId,
77 | BankNumber: '',
78 | AccountHolderName: data.AccountHolderFamilyName+','+data.AccountHolderGivenName,
79 | AccountBalance: 0,
80 | Overdraft: 0,
81 | AvailableBalance: 0,
82 | //Timestamp: Math.floor(Date.now())
83 | Timestamp: 1
84 | });
85 | });
86 |
87 | // Read the account value from DB
88 | let user = db.objects('Account');
89 | let userAccount = user.filtered('AccountNumber == $0', accountId);
90 | console.log('User?');
91 | console.log(userAccount);
92 | dismissKeyboard();
93 | if (userAccount.length == 1) {
94 | console.log("Successfull")
95 | console.log(userAccount[0]);
96 | Actions.login();
97 | }
98 | // Alert token value
99 | // Load new page
100 | } else if (typeof res.error != 'undefined') {
101 | dismissKeyboard();
102 | Alert.alert('Error', res.error);
103 | console.log('Error');
104 | }
105 | });
106 | },
107 |
108 | render: function() {
109 | return (
110 |
111 |
112 |
113 |
114 |
115 |
116 | this.setState({givenName})}
119 | value={this.state.givenName}
120 | autoCorrect={false}
121 | placeholder="Given Name"
122 | />
123 | this.setState({familyName})}
126 | value={this.state.familyName}
127 | autoCorrect={false}
128 | placeholder="Family Name"
129 | />
130 | this.setState({idNumber})}
133 | value={this.state.idNumber}
134 | autoCorrect={false}
135 | keyboardType='number-pad'
136 | placeholder="ID Number"
137 | />
138 | this.setState({email})}
141 | value={this.state.email}
142 | autoCorrect={false}
143 | autoCapitalize="none"
144 | keyboardType='email-address'
145 | placeholder="Email"
146 | />
147 |
149 |
151 |
152 |
153 |
154 | )
155 | }
156 | });
157 |
158 | module.exports = FetchAccountView;
159 |
--------------------------------------------------------------------------------
/libs/BankClient.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, {
4 | AppRegistry,
5 | Component,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Alert
12 | } from 'react-native';
13 |
14 | let db = require('./RealmDB');
15 | import {Scene, Router, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
16 |
17 | // @TODO Local testing
18 | const url = 'https://bvnk.co:8443';
19 | //const url = 'https://bvnk.co:8443/';
20 |
21 | //var BankClient = React.createClass({
22 | function BankClient() {
23 |
24 | this._doCallNoAuthGet = function(route, method, callback) {
25 | console.log('Route: noauth get :'+url+route);
26 | fetch(url+route, {
27 | method: method,
28 | headers: {
29 | 'Accept': 'application/json',
30 | 'Content-Type': 'application/json',
31 | },
32 | })
33 | .then((response) => response.json())
34 | .then((responseText) => {
35 | console.log('Called: '+route);
36 | callback(responseText);
37 | })
38 | .catch((error) => {
39 | callback(error);
40 | });
41 | },
42 |
43 | this._doCallNoAuth = function(route, method, data, callback) {
44 | console.log('Route: noauth post :'+url+route);
45 | var formData = new FormData();
46 | for ( var key in data ) {
47 | formData.append(key, data[key]);
48 | }
49 |
50 | fetch(url+route, {
51 | method: method,
52 | headers: {
53 | 'Accept': 'application/json',
54 | 'Content-Type': 'application/json',
55 | },
56 | //body: JSON.stringify(data)
57 | body: formData
58 | })
59 | .then((response) => response.json())
60 | .then((responseText) => {
61 | console.log('Called: '+route);
62 | callback(responseText);
63 | })
64 | .catch((error) => {
65 | callback(error);
66 | });
67 | },
68 |
69 | this._doCallAuthGet = function(route, method, token, callback) {
70 | console.log('Route: auth get :'+url+route);
71 | return fetch(url+route, {
72 | method: method,
73 | headers: {
74 | 'Accept': 'application/json',
75 | 'Content-Type': 'application/json',
76 | 'X-Auth-Token': token
77 | },
78 | })
79 | .then((response) => response.json())
80 | .then((responseText) => {
81 | callback(responseText);
82 | })
83 | .catch((error) => {
84 | callback(error);
85 | });
86 | },
87 |
88 | this._doCallAuth = function(route, method, data, token, callback) {
89 | console.log('Route: auth post :'+url+route);
90 | var formData = new FormData();
91 | for ( var key in data ) {
92 | formData.append(key, data[key]);
93 | }
94 |
95 | return fetch(url+route, {
96 | method: method,
97 | headers: {
98 | 'Accept': 'application/json',
99 | 'Content-Type': 'application/json',
100 | 'X-Auth-Token': token
101 | },
102 | body: formData
103 | })
104 | .then((response) => response.json())
105 | .then((responseText) => {
106 | callback(responseText);
107 | })
108 | .catch((error) => {
109 | callback(error);
110 | });
111 | },
112 |
113 | this._doCallFetchAccount = function(route, method, data, callback) {
114 | return fetch(url+route, {
115 | method: method,
116 | headers: {
117 | 'Accept': 'application/json',
118 | 'Content-Type': 'application/json',
119 | 'X-IDNumber': data.AccountHolderIdentificationNumber,
120 | 'X-GivenName': data.AccountHolderGivenName,
121 | 'X-FamilyName': data.AccountHolderFamilyName,
122 | 'X-EmailAddress': data.AccountHolderEmailAddress,
123 | },
124 | })
125 | .then((response) => response.json())
126 | .then((responseText) => {
127 | callback(responseText);
128 | })
129 | .catch((error) => {
130 | callback(error);
131 | });
132 | },
133 |
134 | this.authLogin = function (data, cb) {
135 | this._doCallNoAuth('/auth/login', 'POST', data, cb);
136 | },
137 |
138 | this.authCreate = function(data, cb) {
139 | this._doCallNoAuth('/auth/account', 'POST', data, cb);
140 | },
141 |
142 | this.fetchAccount = function(data, cb) {
143 | this._doCallFetchAccount('/accountRetrieve', 'GET', data, cb);
144 | },
145 |
146 | this.authExtend = function(token, cb) {
147 | this._doCallAuth('/auth', 'POST', {}, token, cb);
148 | },
149 |
150 | this.accountCreate = function(data, cb) {
151 | console.log(JSON.stringify(data));
152 | this._doCallNoAuth('/account', 'POST', data, cb);
153 | },
154 |
155 | this.paymentCredit = function(data, cb) {
156 | let token = this.getToken();
157 | this._doCallAuth('/transaction/credit', 'POST', data, token, cb);
158 | },
159 |
160 | this.paymentDeposit = function(data, cb) {
161 | let token = this.getToken();
162 | this._doCallAuth('/transaction/deposit', 'POST', data, token, cb);
163 | },
164 |
165 | this.accountGet = function(data, cb) {
166 | let token = this.getToken();
167 | this._doCallAuthGet('/account', 'GET', token, cb);
168 | },
169 |
170 | this.accountGetById = function(data, cb) {
171 | let token = this.getToken();
172 | this._doCallAuthGet('/account/'+data.accountID, 'GET', token, cb);
173 | },
174 |
175 | this.accountGetAll = function(data, cb) {
176 | let token = this.getToken();
177 | this._doCallAuthGet('/account/all', 'GET', token, cb);
178 | },
179 |
180 | this.authRemove = function(data, cb) {
181 | let token = this.getToken();
182 | this._doCallAuth('/auth/account', 'DELETE', data, token, cb);
183 | }
184 |
185 | this.addPushToken = function(data, cb) {
186 | let token = this.getToken();
187 | this._doCallAuth('/accountPushToken', 'POST', data, token, cb);
188 | }
189 |
190 | this.removePushToken = function(data, cb) {
191 | let token = this.getToken();
192 | this._doCallAuth('/accountPushToken', 'DELETE', data, token, cb);
193 | }
194 |
195 | this.transactionsList = function(data, cb) {
196 | let token = this.getToken();
197 | this._doCallAuthGet('/transaction/list/'+data.perPage+'/'+data.page, 'GET', token, cb);
198 | },
199 |
200 | this.transactionsListAfterTimestamp = function(data, cb) {
201 | let token = this.getToken();
202 | this._doCallAuthGet('/transaction/list/'+data.perPage+'/'+data.page+'/'+data.timestamp, 'GET', token, cb);
203 | },
204 |
205 | this.accountSearch = function(data, cb) {
206 | let token = this.getToken();
207 | this._doCallAuth('/account/search', 'POST', data, token, cb);
208 | },
209 |
210 | // Token
211 | this.getToken = function() {
212 | let tokenResult = db.objects('AccountToken');
213 | if (tokenResult.length > 0) {
214 | let tokenDB = tokenResult.slice(0,1);
215 | let tokenObj = tokenDB[0];
216 | var token = tokenObj.Token;
217 | console.log("Get token");
218 | console.log(token);
219 |
220 | // Check token
221 | this.authExtend(token, this.extendTokenInBackground);
222 | // Return
223 | console.log("After extend: "+token);
224 | return token;
225 | }
226 | },
227 |
228 | this.extendTokenInBackground = function(res) {
229 |
230 | if (typeof res.error != 'undefined') {
231 | if (res.error == 'httpApiHandlers: Token invalid') {
232 | Actions.login({ type : "reset" });
233 | console.log("Token invalid, go to login");
234 | return;
235 | /*
236 | console.log("token invalid");
237 | let userAuth = db.objects('AccountAuth');
238 | if (userAuth.length > 0) {
239 | var userAccount = userAuth.slice(0,1);
240 | userAccount = userAccount[0];
241 |
242 | console.log("User account in extend");
243 | let data = { User: userAccount.AccountNumber, Password: userAccount.Password };
244 | //@FIXME Missing context, cannot see "this" probably due to being passed as a callback
245 | let res = this.authLogin(data, function(res) {
246 | console.log("At second login: ");
247 | console.log(res);
248 | if (typeof res.error == 'undefined') {
249 | // Get token
250 | tokenRes = res.response;
251 | console.log("New token: "+tokenRes);
252 | db.write(() => {
253 | // Delete tokens
254 | let allTokens = db.objects('AccountToken');
255 | db.delete(allTokens);
256 |
257 | db.create('AccountToken', {
258 | Token: tokenRes,
259 | //Timestamp: Math.floor(Date.now())
260 | Timestamp: 1
261 | });
262 | });
263 | return tokenRes;
264 | } else {
265 | // Show error
266 | Alert.alert('Error', res.error);
267 | dismissKeyboard();
268 | return;
269 | }
270 | });
271 | }
272 | */
273 | }
274 | }
275 | }
276 | }
277 |
278 | module.exports = BankClient;
279 |
--------------------------------------------------------------------------------
/LoginView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Image,
12 | Alert
13 | } from 'react-native';
14 |
15 | import Button from 'react-native-button'
16 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
17 |
18 | let styles = require('./styles');
19 | let BankClient = require('./libs/BankClient');
20 | let bc = new BankClient();
21 | let db = require('./libs/RealmDB');
22 | let dismissKeyboard = require('dismissKeyboard');
23 |
24 | let PushNotification = require('react-native-push-notification');
25 |
26 | PushNotification.configure({
27 |
28 | // (optional) Called when Token is generated (iOS and Android)
29 | onRegister: function(token) {
30 | let tokenString = token.token;
31 | console.log( 'TOKEN:', tokenString );
32 |
33 | if (typeof tokenString != undefined) {
34 | // Save in database
35 | db.write(() => {
36 | // Delete tokens
37 | let allTokens = db.objects('DeviceToken');
38 | db.delete(allTokens);
39 |
40 | db.create('DeviceToken', {
41 | Token: tokenString,
42 | Platform: "ios"
43 | });
44 | });
45 | }
46 | },
47 |
48 | // (required) Called when a remote or local notification is opened or received
49 | onNotification: function(notification) {
50 | console.log( 'NOTIFICATION:', notification );
51 | alert(notification.message);
52 | },
53 |
54 | // ANDROID ONLY: (optional) GCM Sender ID.
55 | senderID: "YOUR GCM SENDER ID",
56 |
57 | // IOS ONLY (optional): default: all - Permissions to register.
58 | permissions: {
59 | alert: true,
60 | badge: true,
61 | sound: true
62 | },
63 |
64 | // Should the initial notification be popped automatically
65 | // default: true
66 | popInitialNotification: true,
67 |
68 | /**
69 | * IOS ONLY: (optional) default: true
70 | * - Specified if permissions will requested or not,
71 | * - if not, you must call PushNotificationsHandler.requestPermissions() later
72 | */
73 | requestPermissions: true,
74 | });
75 |
76 | var LoginView = React.createClass({
77 | getInitialState() {
78 | dismissKeyboard();
79 | this.addPushTokenInit();
80 | return {
81 | password: ''
82 | }
83 | },
84 |
85 | _doLogin: function() {
86 | // Check password
87 | let userAuth = db.objects('AccountAuth');
88 | if (userAuth.length > 0) {
89 | var userAccount = userAuth.slice(0,1);
90 | userAccount = userAccount[0];
91 |
92 | console.log(userAccount.Password);
93 | if (userAccount.Password != this.state.password) {
94 | Alert.alert('Auth Failure', 'Password incorrect');
95 | return;
96 | }
97 |
98 | // @TODO Maybe check and try to extend existing auth token?
99 | // For now we just delete and get a new one
100 | // Repeated logging in will fill up Redis with tokens
101 | let data = { User: userAccount.AccountNumber, Password: userAccount.Password };
102 | let res = bc.authLogin(data, function(res) {
103 | console.log(res);
104 | if (typeof res.error == 'undefined') {
105 | // Get token
106 | let token = res.response;
107 | db.write(() => {
108 | // Delete tokens
109 | let allTokens = db.objects('AccountToken');
110 | db.delete(allTokens);
111 |
112 | db.create('AccountToken', {
113 | Token: token,
114 | //Timestamp: Math.floor(Date.now())
115 | Timestamp: 1
116 | });
117 | });
118 | // Go to account landing view
119 | dismissKeyboard();
120 | Actions.main({type : "reset"});
121 | //Actions.refresh({key: 'drawer', open: value => !value});
122 | } else {
123 | // Show error
124 | Alert.alert('Error', res.error);
125 | dismissKeyboard();
126 | return;
127 | }
128 | });
129 | } else {
130 | dismissKeyboard();
131 | // Check if an account exists
132 | let userAccount = db.objects('Account');
133 | if (userAccount.length == 0) {
134 | Actions.register();
135 | return;
136 | }
137 | // Send login
138 | let data = { User: userAccount[0].AccountNumber, Password: this.state.password };
139 | let res = bc.authLogin(data, function(res) {
140 | console.log(res);
141 | if (typeof res.error == 'undefined') {
142 | // Get token
143 | let token = res.response;
144 | db.write(() => {
145 | // Delete tokens
146 | let allTokens = db.objects('AccountToken');
147 | db.delete(allTokens);
148 |
149 | db.create('AccountToken', {
150 | Token: token,
151 | //Timestamp: Math.floor(Date.now())
152 | Timestamp: 1
153 | });
154 | });
155 | // Go to account landing view
156 | dismissKeyboard();
157 | Actions.main({type : "reset"});
158 | //Actions.refresh({key: 'drawer', open: value => !value});
159 | } else {
160 | // Show error
161 | Alert.alert('Error', res.error);
162 | dismissKeyboard();
163 | return;
164 | }
165 | });
166 | }
167 | },
168 |
169 | checkAccount: function() {
170 | let userAccount = db.objects('Account');
171 | if (userAccount.length == 0) {
172 | // There is no account set up yet
173 | // Show fetch account screen
174 | Actions.accountFetch();
175 | }
176 | },
177 |
178 | addPushTokenInit: function() {
179 | // Testing
180 | /*
181 | let pushToken = "test-push-token-ios-2";
182 | let platform = "ios";
183 | let data = { PushToken: pushToken, Platform: platform };
184 | bc.addPushToken(data, () => {
185 | console.log("push token added");
186 | });
187 | */
188 |
189 | // Fetch token
190 | // * @FIXME This is currently throwing "Error: Object type 'DeviceToken' not present in Realm"
191 | let pushTokenObj = db.objects('DeviceToken');
192 | console.log('Push token:');
193 | console.log(pushTokenObj);
194 | if (pushTokenObj.length > 0) {
195 | var pushTokenArr = pushTokenObj.slice(0,1);
196 | let pushToken = pushTokenArr[0];
197 | console.log(pushToken);
198 | let pToken = pushToken.Token;
199 | let platform = pushToken.Platform;
200 | let data = { PushToken: pToken, Platform: platform };
201 | console.log(data);
202 | bc.addPushToken(data, () => {
203 | console.log("push token added");
204 | });
205 | } else {
206 | console.log("No token, get the token");
207 | PushNotification.checkPermissions(function(res) {
208 | console.log(res);
209 | });
210 | PushNotification.abandonPermissions();
211 | PushNotification.requestPermissions();
212 | }
213 | },
214 |
215 | render: function() {
216 | return (
217 |
218 |
219 |
220 |
221 |
222 |
223 | this.setState({password})}
226 | value={this.state.password}
227 | autoCorrect={false}
228 | keyboardAppearance="dark"
229 | secureTextEntry={true}
230 | autoCapitalize="none"
231 | placeholder="Password"
232 | />
233 |
235 |
236 |
237 |
238 | )
239 | }
240 | });
241 |
242 | module.exports = LoginView;
243 |
--------------------------------------------------------------------------------
/android/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/MainAccountView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | AppRegistry,
6 | Text,
7 | View,
8 | StatusBar,
9 | StyleSheet,
10 | TextInput,
11 | Image,
12 | TouchableOpacity,
13 | ListView,
14 | Alert
15 | } from 'react-native';
16 |
17 | import Button from 'react-native-button'
18 | import {Scene, Router, TabBar, Modal, Schema, Actions, Reducer} from 'react-native-router-flux'
19 |
20 | let styles = require('./styles');
21 | let BankClient = require('./libs/BankClient');
22 | let bc = new BankClient();
23 | let db = require('./libs/RealmDB');
24 | let dismissKeyboard = require('dismissKeyboard');
25 |
26 | let PushNotification = require('react-native-push-notification');
27 |
28 | var MainAccountView = React.createClass({
29 | getInitialState() {
30 | console.log('create db:', db.path)
31 | dismissKeyboard();
32 | let transactions = db.objects('Transactions').sorted('Timestamp', 'reverse').slice(0, 5);
33 | var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
34 | return {
35 | balance: "",
36 | balanceDecimal: "",
37 | dataSource: ds.cloneWithRows(transactions),
38 | }
39 | },
40 |
41 | getInitialBalance: function() {
42 | let user = db.objects('Account');
43 | var userAccount = user;
44 | //var userAccount = user.slice(0,1).first;
45 | if (userAccount.length == 0) {
46 | actions.login({ type: "reset" });
47 | return;
48 | }
49 | userAccount = userAccount[0];
50 | console.log(userAccount);
51 |
52 | var balance = Math.floor(userAccount.AccountBalance);
53 | let balanceDecimal = Math.round((userAccount.AccountBalance - balance) * 100);
54 | balance = this.numberWithCommas(balance);
55 | this.setState({ 'balance' : balance });
56 | this.setState({ 'balanceDecimal' : balanceDecimal });
57 | },
58 |
59 | _updateAccount: function() {
60 | console.log('updating account...');
61 | // Get latest balances
62 | let data = {};
63 | let res = bc.accountGet(data, function(res) {
64 | if (typeof res.error == 'undefined') {
65 | console.log(res.response);
66 | let userAccountDetails = res.response;
67 |
68 | db.write(() => {
69 | // Update Main Account
70 | let userUpdate = db.objects('Account');
71 | var userAccountUpdate = userUpdate.filtered('AccountNumber == $0', userAccountDetails.AccountNumber);
72 | console.log("User from response:");
73 | console.log(userAccountDetails);
74 | console.log("UserAccountNumber from response:");
75 | console.log(userAccountDetails.AccountNumber);
76 | console.log("User from DB:");
77 | console.log(userAccountUpdate);
78 | //var userAccountUpdate = userUpdate.slice(0,1).first;
79 | if (userAccountUpdate.length == 0) {
80 | // @FIXME There are cases where the user stored in the accounts table and the user sent to log in
81 | // are two different users. Find the cause and fix. For now we throw an error and send the user out
82 | alert("Account stored in database is not the same as login!");
83 | // Delete all other accounts for now
84 | let accounts = db.objects('Account');
85 | db.delete(accounts);
86 | let contacts = db.objects('Contacts');
87 | db.delete(contacts);
88 | let transactions = db.objects('Transactions');
89 | db.delete(transactions);
90 | let auth = db.objects('AccountAuth');
91 | db.delete(auth);
92 | let authToken = db.objects('AccountToken');
93 | db.delete(authToken);
94 | let accountMeta = db.objects('AccountMeta');
95 | db.delete(accountMeta);
96 | let deviceToken = db.objects('DeviceToken');
97 | db.delete(deviceToken);
98 | Actions.login({ type: "reset" });
99 | return;
100 | }
101 |
102 | userAccountUpdate = userAccountUpdate[0];
103 |
104 | let accountBalance = parseFloat(userAccountDetails.AvailableBalance);
105 | let overdraft = parseFloat(userAccountDetails.Overdraft);
106 | let availableBalance = parseFloat(userAccountDetails.AccountBalance);
107 |
108 | userAccountUpdate.AccountHolderName = userAccountDetails.AccountHolderName;
109 | userAccountUpdate.Overdraft = overdraft;
110 | userAccountUpdate.AvailableBalance = availableBalance;
111 | userAccountUpdate.AccountBalance = accountBalance;
112 |
113 | });
114 | } else {
115 | Alert.alert('Error', 'Could not update account details: '+res.error);
116 | console.log(res);
117 | dismissKeyboard();
118 | return;
119 | }
120 | });
121 | },
122 |
123 | _updateTransactions: function() {
124 | console.log('updating transcations...');
125 | // Get latest transactions
126 | let transactionsRes = db.objects('Transactions');
127 | var transactionsResSorted = transactionsRes.sorted('Timestamp');
128 | var timestamp = 0
129 | if (transactionsResSorted.length > 0) {
130 | // Get latest
131 | let latestTransaction = transactionsResSorted.slice(transactionsResSorted.length - 1, transactionsResSorted.length);
132 | if (latestTransaction.length > 0) {
133 | timestamp = latestTransaction[0].Timestamp;
134 | }
135 | }
136 |
137 | // We set up the data to fetch 5 records
138 | let data = {
139 | perPage : 5,
140 | page : 0,
141 | timestamp : timestamp
142 | };
143 | console.log(data);
144 |
145 | let res = bc.transactionsListAfterTimestamp(data, function(res) {
146 | console.log("After transactions...");
147 | if (typeof res.error == 'undefined') {
148 | let transactionList = res.response;
149 | db.write(() => {
150 | transactionList.forEach(function(t) {
151 | console.log(t);
152 | // Check if transaction exists
153 | let trDB = db.objects('Transactions').filtered('Transaction == $0', t.ID);
154 |
155 | if (trDB.length == 0) {
156 | var senderName = "";
157 | var receiverName = "";
158 |
159 | var contact = db.objects('Contacts').filtered('ContactAccountNumber == $0 && ContactBankNumber == $1', t.Receiver.AccountNumber, t.Receiver.BankNumber);
160 | if (contact.length > 0) {
161 | receiverName = contact[0].ContactName;
162 | }
163 |
164 | contact = db.objects('Contacts').filtered('ContactAccountNumber == $0 && ContactBankNumber == $1', t.Sender.AccountNumber, t.Sender.BankNumber);
165 | if (contact.length > 0) {
166 | senderName = contact[0].ContactName;
167 | }
168 |
169 | let transactionAmount = parseFloat(t.Amount);
170 | let feeAmount = parseFloat(t.Fee);
171 |
172 | db.create('Transactions', {
173 | Transaction: t.ID,
174 | Type: t.PainType,
175 | SenderAccountNumber: t.Sender.AccountNumber,
176 | SenderBankNumber: t.Sender.BankNumber,
177 | ReceiverAccountNumber: t.Receiver.AccountNumber,
178 | ReceiverBankNumber: t.Receiver.BankNumber,
179 | TransactionAmount: transactionAmount,
180 | SenderName: senderName,
181 | ReceiverName: receiverName,
182 | FeeAmount: feeAmount,
183 | Lat: t.Geo[0],
184 | Lon: t.Geo[1],
185 | Desc: t.Desc,
186 | Status: t.Status,
187 | Timestamp: t.Timestamp,
188 | });
189 | }
190 | });
191 | });
192 | } else {
193 | Alert.alert('Error', 'Could not update account details: '+res.error);
194 | console.log(res);
195 | dismissKeyboard();
196 | return;
197 | }
198 | });
199 | },
200 |
201 | updateStateListener: function() {
202 | // Fetch account
203 | let user = db.objects('Account');
204 | var userAccount = user.slice(0,1);
205 | userAccount = userAccount[0];
206 | var balance = Math.floor(userAccount.AccountBalance);
207 | let balanceDecimal = Math.round((userAccount.AccountBalance - balance) * 100);
208 | balance = this.numberWithCommas(balance);
209 | this.setState({ 'balance' : balance });
210 | this.setState({ 'balanceDecimal' : balanceDecimal });
211 | },
212 |
213 | updateTransactionListener: function() {
214 | // Fetch transactions
215 | let transactions = db.objects('Transactions').sorted('Timestamp', 'reverse').slice(0, 5);
216 | var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
217 | this.setState({ dataSource: ds.cloneWithRows(transactions) });
218 | },
219 |
220 | componentWillMount: function() {
221 | this.getInitialBalance();
222 | // Clear notification count
223 | PushNotification.setApplicationIconBadgeNumber(0);
224 | },
225 |
226 | componentDidMount: function() {
227 | // Update balance
228 | this._updateAccount();
229 | // Update transaction list
230 | this._updateTransactions();
231 | // Observe Realm Change Events
232 | db.addListener('change', this.updateStateListener);
233 | db.addListener('change', this.updateTransactionListener);
234 | },
235 |
236 | componentWillUnmount: function() {
237 | // Remove the listener
238 | db.removeListener('change', this.updateStateListener);
239 | db.removeListener('change', this.updateTransactionListener);
240 | },
241 |
242 | numberWithCommas: function(x) {
243 | return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
244 | },
245 |
246 | timeConverter: function(UNIX_timestamp) {
247 | var a = new Date(UNIX_timestamp * 1000);
248 | var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
249 | var year = a.getFullYear();
250 | var month = months[a.getMonth()];
251 | var date = a.getDate();
252 | var hour = a.getHours();
253 | var min = a.getMinutes();
254 | var sec = a.getSeconds();
255 | var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ;
256 | return time;
257 | },
258 |
259 | render: function() {
260 | var notificationMessage;
261 | if (typeof(this.props.message) != 'undefined') {
262 | notificationMessage = {this.props.message};
263 | }
264 |
265 | return (
266 |
267 |
268 |
269 |
270 |
271 |
272 | ACCOUNT
273 | {notificationMessage}
274 |
275 |
276 | {this.state.balance}
277 | . {this.state.balanceDecimal}
278 |
279 |
280 |
285 |
287 | Actions.transaction({ data: rowData })} style={styles.transaction.desc}>{rowData.Desc}
288 | Actions.transaction({ data: rowData })} style={styles.transaction.time}>{this.timeConverter(rowData.Timestamp)}
289 | }
290 | />
291 |
292 |
293 |
294 | )
295 | }
296 | });
297 |
298 | module.exports = MainAccountView;
299 |
--------------------------------------------------------------------------------