diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..0c46ef6
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "editor.tabSize": 2,
+ "prettier.jsxSingleQuote": true,
+ "javascript.preferences.quoteStyle": "single",
+ "prettier.singleQuote": true
+}
diff --git a/assets/avatar.png b/assets/avatar.png
new file mode 100644
index 0000000..b89c456
Binary files /dev/null and b/assets/avatar.png differ
diff --git a/assets/blur.jpg b/assets/blur.jpg
new file mode 100644
index 0000000..e79c934
Binary files /dev/null and b/assets/blur.jpg differ
diff --git a/assets/empty_box.png b/assets/empty_box.png
new file mode 100644
index 0000000..17abdf2
Binary files /dev/null and b/assets/empty_box.png differ
diff --git a/assets/familyView.png b/assets/familyView.png
new file mode 100644
index 0000000..c26d65c
Binary files /dev/null and b/assets/familyView.png differ
diff --git a/assets/loginBg.png b/assets/loginBg.png
new file mode 100644
index 0000000..c07f2aa
Binary files /dev/null and b/assets/loginBg.png differ
diff --git a/assets/loginIcon.png b/assets/loginIcon.png
new file mode 100644
index 0000000..785ba3e
Binary files /dev/null and b/assets/loginIcon.png differ
diff --git a/assets/loginPage.png b/assets/loginPage.png
new file mode 100644
index 0000000..c23d242
Binary files /dev/null and b/assets/loginPage.png differ
diff --git a/assets/openBankingHead.png b/assets/openBankingHead.png
new file mode 100644
index 0000000..4b0b627
Binary files /dev/null and b/assets/openBankingHead.png differ
diff --git a/assets/personalDefaultPage.png b/assets/personalDefaultPage.png
new file mode 100644
index 0000000..80315f4
Binary files /dev/null and b/assets/personalDefaultPage.png differ
diff --git a/assets/profile.jpg b/assets/profile.jpg
new file mode 100644
index 0000000..2db060d
Binary files /dev/null and b/assets/profile.jpg differ
diff --git a/babel.config.js b/babel.config.js
index f6d217d..58869ad 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,6 +1,9 @@
module.exports = (api) => {
api.cache(true);
return {
- presets: ['babel-preset-expo'],
+ presets: [
+ 'babel-preset-expo',
+ 'module:react-native-dotenv',
+ ],
};
};
diff --git a/package-lock.json b/package-lock.json
index 989d74f..9106219 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2850,6 +2850,14 @@
"requires": {
"react-is": "^16.7.0"
}
+ },
+ "react-native-screens": {
+ "version": "1.0.0-alpha.23",
+ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-1.0.0-alpha.23.tgz",
+ "integrity": "sha512-tOxHGQUN83MTmQB4ghoQkibqOdGiX4JQEmeyEv96MKWO/x8T2PJv84ECUos9hD3blPRQwVwSpAid1PPPhrVEaw==",
+ "requires": {
+ "debounce": "^1.2.0"
+ }
}
}
},
@@ -3634,6 +3642,21 @@
"slash": "^2.0.0"
}
},
+ "babel-plugin-dotenv": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npm.taobao.org/babel-plugin-dotenv/download/babel-plugin-dotenv-0.1.1.tgz",
+ "integrity": "sha1-nI+upnp8A0/n6UCZGHqy51c0ALw=",
+ "requires": {
+ "dotenv": "^2.0.0"
+ },
+ "dependencies": {
+ "dotenv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npm.taobao.org/dotenv/download/dotenv-2.0.0.tgz?cache=0&sync_timestamp=1571190782798&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdotenv%2Fdownload%2Fdotenv-2.0.0.tgz",
+ "integrity": "sha1-vXWcNXqqcDZeAclrewvsCKbg2Uk="
+ }
+ }
+ },
"babel-plugin-dynamic-import-node": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz",
@@ -3880,11 +3903,25 @@
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
},
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
"blueimp-md5": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.12.0.tgz",
"integrity": "sha512-zo+HIdIhzojv6F1siQPqPFROyVy7C50KzHv/k/Iz+BtvtVzSHXiMXOpq2wCfNkeBqdCv+V8XOV96tsEt2W/3rQ=="
},
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+ },
"bplist-creator": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz",
@@ -4428,6 +4465,38 @@
}
}
},
+ "css-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
+ "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
+ "requires": {
+ "boolbase": "^1.0.0",
+ "css-what": "^3.2.1",
+ "domutils": "^1.7.0",
+ "nth-check": "^1.0.2"
+ }
+ },
+ "css-tree": {
+ "version": "1.0.0-alpha.39",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz",
+ "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==",
+ "requires": {
+ "mdn-data": "2.0.6",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "css-what": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz",
+ "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw=="
+ },
"cssom": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
@@ -4605,6 +4674,17 @@
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
+ "deprecated-react-native-listview": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/deprecated-react-native-listview/-/deprecated-react-native-listview-0.0.5.tgz",
+ "integrity": "sha512-Cy7nDdd+KU+nR3tY1BSMuoZpsYC6OVSZyAiUSTDBop2lIgzCseDx7XI57x6h+NXer/8aor2yiQDQfeFcmBMwgQ==",
+ "requires": {
+ "create-react-class": "*",
+ "fbjs": "*",
+ "invariant": "*",
+ "react-clone-referenced-element": "*"
+ }
+ },
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
@@ -4631,11 +4711,32 @@
"esutils": "^2.0.2"
}
},
+ "dom-serializer": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+ "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+ "requires": {
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
+ "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ=="
+ }
+ }
+ },
"dom-walk": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
"integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg="
},
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+ },
"domexception": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
@@ -4645,6 +4746,20 @@
"webidl-conversions": "^4.0.2"
}
},
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "dotenv": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
+ "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
+ },
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -4692,6 +4807,11 @@
"once": "^1.4.0"
}
},
+ "entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
+ "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw=="
+ },
"envinfo": {
"version": "5.12.1",
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-5.12.1.tgz",
@@ -5670,6 +5790,12 @@
"flat-cache": "^2.0.1"
}
},
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "optional": true
+ },
"filename-regex": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
@@ -5852,13 +5978,14 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
- "version": "1.2.9",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
- "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+ "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
"optional": true,
"requires": {
+ "bindings": "^1.5.0",
"nan": "^2.12.1",
- "node-pre-gyp": "^0.12.0"
+ "node-pre-gyp": "*"
},
"dependencies": {
"abbrev": {
@@ -5900,7 +6027,7 @@
}
},
"chownr": {
- "version": "1.1.1",
+ "version": "1.1.3",
"bundled": true,
"optional": true
},
@@ -5925,7 +6052,7 @@
"optional": true
},
"debug": {
- "version": "4.1.1",
+ "version": "3.2.6",
"bundled": true,
"optional": true,
"requires": {
@@ -5948,11 +6075,11 @@
"optional": true
},
"fs-minipass": {
- "version": "1.2.5",
+ "version": "1.2.7",
"bundled": true,
"optional": true,
"requires": {
- "minipass": "^2.2.1"
+ "minipass": "^2.6.0"
}
},
"fs.realpath": {
@@ -5976,7 +6103,7 @@
}
},
"glob": {
- "version": "7.1.3",
+ "version": "7.1.6",
"bundled": true,
"optional": true,
"requires": {
@@ -6002,7 +6129,7 @@
}
},
"ignore-walk": {
- "version": "3.0.1",
+ "version": "3.0.3",
"bundled": true,
"optional": true,
"requires": {
@@ -6019,7 +6146,7 @@
}
},
"inherits": {
- "version": "2.0.3",
+ "version": "2.0.4",
"bundled": true,
"optional": true
},
@@ -6055,7 +6182,7 @@
"optional": true
},
"minipass": {
- "version": "2.3.5",
+ "version": "2.9.0",
"bundled": true,
"optional": true,
"requires": {
@@ -6064,11 +6191,11 @@
}
},
"minizlib": {
- "version": "1.2.1",
+ "version": "1.3.3",
"bundled": true,
"optional": true,
"requires": {
- "minipass": "^2.2.1"
+ "minipass": "^2.9.0"
}
},
"mkdirp": {
@@ -6080,22 +6207,22 @@
}
},
"ms": {
- "version": "2.1.1",
+ "version": "2.1.2",
"bundled": true,
"optional": true
},
"needle": {
- "version": "2.3.0",
+ "version": "2.4.0",
"bundled": true,
"optional": true,
"requires": {
- "debug": "^4.1.0",
+ "debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"sax": "^1.2.4"
}
},
"node-pre-gyp": {
- "version": "0.12.0",
+ "version": "0.14.0",
"bundled": true,
"optional": true,
"requires": {
@@ -6108,7 +6235,7 @@
"rc": "^1.2.7",
"rimraf": "^2.6.1",
"semver": "^5.3.0",
- "tar": "^4"
+ "tar": "^4.4.2"
}
},
"nopt": {
@@ -6121,12 +6248,20 @@
}
},
"npm-bundled": {
- "version": "1.0.6",
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
"bundled": true,
"optional": true
},
"npm-packlist": {
- "version": "1.4.1",
+ "version": "1.4.7",
"bundled": true,
"optional": true,
"requires": {
@@ -6188,7 +6323,7 @@
"optional": true
},
"process-nextick-args": {
- "version": "2.0.0",
+ "version": "2.0.1",
"bundled": true,
"optional": true
},
@@ -6225,7 +6360,7 @@
}
},
"rimraf": {
- "version": "2.6.3",
+ "version": "2.7.1",
"bundled": true,
"optional": true,
"requires": {
@@ -6248,7 +6383,7 @@
"optional": true
},
"semver": {
- "version": "5.7.0",
+ "version": "5.7.1",
"bundled": true,
"optional": true
},
@@ -6294,17 +6429,17 @@
"optional": true
},
"tar": {
- "version": "4.4.8",
+ "version": "4.4.13",
"bundled": true,
"optional": true,
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
- "minipass": "^2.3.4",
- "minizlib": "^1.1.1",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
- "yallist": "^3.0.2"
+ "yallist": "^3.0.3"
}
},
"util-deprecate": {
@@ -6326,7 +6461,7 @@
"optional": true
},
"yallist": {
- "version": "3.0.3",
+ "version": "3.1.1",
"bundled": true,
"optional": true
}
@@ -9728,6 +9863,11 @@
"buffer-alloc": "^1.1.0"
}
},
+ "mdn-data": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz",
+ "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA=="
+ },
"mem": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
@@ -10503,6 +10643,14 @@
"gauge": "~1.2.5"
}
},
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "requires": {
+ "boolbase": "~1.0.0"
+ }
+ },
"nullthrows": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
@@ -10953,6 +11101,11 @@
"pify": "^2.0.0"
}
},
+ "paths-js": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/paths-js/-/paths-js-0.4.10.tgz",
+ "integrity": "sha512-JZoqlRSHtx+bc+xKI9o4bropEbqZBF4ZfYImiB1T9RYpHB73h5I8XZ7FfSBbHbBMtdD1c04ujjAPH8wUuu4+Gw=="
+ },
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -11084,6 +11237,11 @@
"integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
"dev": true
},
+ "point-in-polygon": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/point-in-polygon/-/point-in-polygon-1.0.1.tgz",
+ "integrity": "sha1-1Ztk6P7kHElFiqyCtWcYxZV7Kvc="
+ },
"posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -11482,6 +11640,24 @@
"resolved": "https://registry.npmjs.org/react-native-branch/-/react-native-branch-3.0.1.tgz",
"integrity": "sha512-vbcYxPZlpF5f39GAEUF8kuGQqCNeD3E6zEdvtOq8oCGZunHXlWlKgAS6dgBKCvsHvXgHuMtpvs39VgOp8DaKig=="
},
+ "react-native-chart-kit": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/react-native-chart-kit/-/react-native-chart-kit-4.3.0.tgz",
+ "integrity": "sha512-mVi0jT2bbKJOpmyqdn2+kGiInU+7P+ebi2ddQWm/Vfwbmd0InyPi7wj3F5UN9Ymr2tYQxuqpOJtHKmn1bT3/5w==",
+ "requires": {
+ "lodash": "^4.17.13",
+ "paths-js": "^0.4.10",
+ "point-in-polygon": "^1.0.1"
+ }
+ },
+ "react-native-dotenv": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npm.taobao.org/react-native-dotenv/download/react-native-dotenv-0.2.0.tgz",
+ "integrity": "sha1-MRVRy2o1o9z+3mSL3tVcDj7OV50=",
+ "requires": {
+ "babel-plugin-dotenv": "0.1.1"
+ }
+ },
"react-native-drawer": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/react-native-drawer/-/react-native-drawer-2.5.1.tgz",
@@ -11573,6 +11749,15 @@
"react-native-modal": "^11.0.2"
}
},
+ "react-native-modal-dropdown": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/react-native-modal-dropdown/-/react-native-modal-dropdown-0.7.0.tgz",
+ "integrity": "sha512-h2UrozBByQhL56XDboj/wjc/5Ny787eLQ++4ql7TecBdbLqbf+tlE62VeXKz30XVMN3iUVYUR/XmM/RIwLIXEg==",
+ "requires": {
+ "deprecated-react-native-listview": "0.0.5",
+ "prop-types": "^15.6.0"
+ }
+ },
"react-native-ratings": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/react-native-ratings/-/react-native-ratings-6.5.0.tgz",
@@ -11587,6 +11772,11 @@
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-1.2.0.tgz",
"integrity": "sha512-vkWRHrPK5qfHP/ZawlRoo38oeYe9NZaaOH/lmFxRcsKzaSK6x3H5ZPXI8lK6MfTLveqwo1QhJje3zIKXO4nQQw=="
},
+ "react-native-safe-area-context": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-0.6.2.tgz",
+ "integrity": "sha512-VtBW0JymVCwVt0TGxTv25Co3wtOv3Yb/K5pAUYkjKXNhWFDz5ZwUG/Yho/p0EkWYlFdroJcSqlvVFl2n3AU7SA=="
+ },
"react-native-safe-area-view": {
"version": "0.14.8",
"resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.14.8.tgz",
@@ -11603,9 +11793,9 @@
}
},
"react-native-screens": {
- "version": "1.0.0-alpha.23",
- "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-1.0.0-alpha.23.tgz",
- "integrity": "sha512-tOxHGQUN83MTmQB4ghoQkibqOdGiX4JQEmeyEv96MKWO/x8T2PJv84ECUos9hD3blPRQwVwSpAid1PPPhrVEaw==",
+ "version": "2.0.0-alpha.22",
+ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-2.0.0-alpha.22.tgz",
+ "integrity": "sha512-2U++QrTf8H989ekHbgFuia8LLd8/+SbXra+rqDAOihCNRLFi91+y5QGgc7DP4Ic9MtHTaYRtWopyfyUo4ybD0A==",
"requires": {
"debounce": "^1.2.0"
}
@@ -11615,6 +11805,15 @@
"resolved": "https://registry.npmjs.org/react-native-status-bar-height/-/react-native-status-bar-height-2.4.0.tgz",
"integrity": "sha512-pWvZFlyIHiuxLugLioq97vXiaGSovFXEyxt76wQtbq0gxv4dGXMPqYow46UmpwOgeJpBhqL1E0EKxnfJRrFz5w=="
},
+ "react-native-svg": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-10.0.0.tgz",
+ "integrity": "sha512-7x56ji3oP8+Bh1jVuBtrq/JGxqLBAVf43BCuAbPMKaBlq78TXCMuln7fiBxCUOD4Z5hoZZaVkILhrJPPszfENA==",
+ "requires": {
+ "css-select": "^2.0.2",
+ "css-tree": "^1.0.0-alpha.37"
+ }
+ },
"react-native-tab-view": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-2.11.0.tgz",
@@ -11808,6 +12007,22 @@
}
}
},
+ "react-native-webview": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-8.0.3.tgz",
+ "integrity": "sha512-Uhd3o73HcqiQ0GWxyz5G5+Jkh1dd1A8Kz/rCYHiX/Ctkg3KO9qrZUmzRetq5y9X1+fUH9XJt6+LO3iO/Dxopfw==",
+ "requires": {
+ "escape-string-regexp": "2.0.0",
+ "invariant": "2.2.4"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="
+ }
+ }
+ },
"react-navigation": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-4.0.10.tgz",
@@ -11817,6 +12032,11 @@
"@react-navigation/native": "^3.6.2"
}
},
+ "react-navigation-hooks": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/react-navigation-hooks/-/react-navigation-hooks-1.1.0.tgz",
+ "integrity": "sha512-ZY/aiYJ88KXaOo8iOa4171O/0x6ztGhUPd2OYzdaJhLT/tP64zi5HB/RZFImuKhaBTODXjoSpFaOTA5xpePG4g=="
+ },
"react-navigation-stack": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/react-navigation-stack/-/react-navigation-stack-1.10.3.tgz",
diff --git a/package.json b/package.json
index b12690a..134dca9 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
},
"dependencies": {
"@expo/vector-icons": "^10.0.6",
+ "dotenv": "^8.2.0",
"expo": "^35.0.0",
"expo-font": "~7.0.0",
"expo-linear-gradient": "~7.0.0",
@@ -26,12 +27,20 @@
"react": "16.9.0",
"react-dom": "16.9.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz",
+ "react-native-chart-kit": "^4.3.0",
+ "react-native-dotenv": "^0.2.0",
"react-native-elements": "^1.2.7",
"react-native-gesture-handler": "~1.3.0",
"react-native-modal-datetime-picker": "^7.6.1",
+ "react-native-modal-dropdown": "^0.7.0",
"react-native-reanimated": "~1.2.0",
+ "react-native-safe-area-context": "^0.6.1",
+ "react-native-screens": "^2.0.0-alpha.22",
+ "react-native-svg": "^10.0.0",
"react-native-web": "^0.11.7",
+ "react-native-webview": "^8.0.3",
"react-navigation": "^4.0.10",
+ "react-navigation-hooks": "^1.1.0",
"react-navigation-stack": "^1.10.3",
"react-navigation-tabs": "^2.6.2",
"react-redux": "^7.1.3",
diff --git a/src/App.jsx b/src/App.jsx
index 4429864..5d3b063 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -2,16 +2,13 @@ import React, { useState, useEffect } from 'react';
import { registerRootComponent, AppLoading } from 'expo';
import * as Font from 'expo-font';
import { Provider } from 'react-redux';
-import { createAppContainer } from 'react-navigation';
import { Alert } from 'react-native';
import { PersistGate } from 'redux-persist/integration/react';
-import AppNavigator from './Navigator';
+import AppContainer from './AppContainer';
import { store, persistor } from './reduxStore';
import Roboto from '../assets/Fonts/Roboto/Roboto-Regular.ttf';
import RobotoMedium from '../assets/Fonts/Roboto/Roboto-Medium.ttf';
-const AppContainer = createAppContainer(AppNavigator);
-
const App = () => {
const [fontLoading, setFontLoading] = useState(true);
diff --git a/src/AppContainer.jsx b/src/AppContainer.jsx
new file mode 100644
index 0000000..44c84e5
--- /dev/null
+++ b/src/AppContainer.jsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { useSelector } from 'react-redux';
+import { createAppContainer } from 'react-navigation';
+import AppNavigatorWhite from './Navigator/indexWhite';
+import AppNavigatorBlack from './Navigator/indexBlack';
+import AppNavigatorWhiteProfile from './Navigator/indexWhiteProfile';
+import AppNavigatorBlackProfile from './Navigator/indexBlackProfile';
+
+let assigned = false;
+export default () => {
+ const { themeMode } = useSelector((state) => state.theme);
+ let AppContainer;
+ if (assigned) {
+ AppContainer = themeMode === 'Light' ? createAppContainer(AppNavigatorWhiteProfile) : createAppContainer(AppNavigatorBlackProfile);
+ } else {
+ AppContainer = themeMode === 'Light' ? createAppContainer(AppNavigatorWhite) : createAppContainer(AppNavigatorBlack);
+ }
+ assigned = true;
+ return ;
+};
diff --git a/src/Chart/LineGraph.jsx b/src/Chart/LineGraph.jsx
new file mode 100644
index 0000000..6ae6e56
--- /dev/null
+++ b/src/Chart/LineGraph.jsx
@@ -0,0 +1,45 @@
+import React from 'react';
+import { View, Dimensions } from 'react-native';
+import { LineChart } from 'react-native-chart-kit';
+import PropTypes from 'prop-types';
+
+export default function LineGraph({ dataSet }) {
+ const screenWidth = Dimensions.get('window').width * 0.85;
+
+ const chartConfig = {
+ backgroundGradientFrom: '#e96d9e',
+ backgroundGradientTo: '#ffaa8f',
+ color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
+ strokeWidth: 2,
+ };
+
+ const data = {
+ labels: dataSet.labels,
+ datasets: [{
+ data: dataSet.total,
+ color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
+ strokeWidth: 2,
+ }],
+ };
+ return (
+
+
+
+ );
+}
+
+LineGraph.propTypes = {
+ dataSet: PropTypes.shape({ labels: PropTypes.array, total: PropTypes.array }),
+};
+
+LineGraph.defaultProps = {
+ dataSet: {},
+};
diff --git a/src/Chart/PieGraph.jsx b/src/Chart/PieGraph.jsx
new file mode 100644
index 0000000..2ae63cc
--- /dev/null
+++ b/src/Chart/PieGraph.jsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import { Animated, View, Easing } from 'react-native';
+import { PieChart } from 'react-native-chart-kit';
+import { useSelector } from 'react-redux';
+import PropTypes from 'prop-types';
+import PieLegend from './PieLegend';
+import setThemeStyle from '../Common/theme/setThemeStyle';
+
+export default function PieGraph({ graphDataSet }) {
+ const { themeMode } = useSelector((state) => state.theme);
+ const styles = setThemeStyle(themeMode);
+ const spinValue = new Animated.Value(0);
+ const { dataSet, legendSet } = graphDataSet;
+ Animated.timing(spinValue, {
+ toValue: 1,
+ duration: 900,
+ easing: Easing.bounce,
+ }).start();
+
+ const spin = spinValue.interpolate({
+ inputRange: [0, 1],
+ outputRange: ['0deg', '90deg'],
+ });
+
+ dataSet.forEach((item) => {
+ const value = item;
+ value.legendFontColor = styles.mainColor.color;
+ return value;
+ });
+
+ const chartConfig = {
+ backgroundGradientFrom: '#e96d9e',
+ backgroundGradientTo: '#ffaa8f',
+ decimalPlaces: 2,
+ color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
+ strokeWidth: 2,
+ };
+
+ return (
+
+
+
+
+
+ {legendSet.map((item, idx) => )}
+
+
+ );
+}
+
+PieGraph.propTypes = {
+ graphDataSet: PropTypes.shape({
+ dataSet: PropTypes.array,
+ legendSet: PropTypes.array,
+ }).isRequired,
+};
diff --git a/src/Chart/PieLegend.jsx b/src/Chart/PieLegend.jsx
new file mode 100644
index 0000000..2f04c95
--- /dev/null
+++ b/src/Chart/PieLegend.jsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import { View, Text } from 'react-native';
+import { Icon } from 'react-native-elements';
+import { useSelector } from 'react-redux';
+import PropTypes from 'prop-types';
+import setThemeStyle from '../Common/theme/setThemeStyle';
+
+export default function PieLegend({ text, color }) {
+ const { themeMode } = useSelector((state) => state.theme);
+ const styles = setThemeStyle(themeMode);
+ return (
+
+
+ {text}
+
+ );
+}
+
+PieLegend.propTypes = {
+ text: PropTypes.string,
+ color: PropTypes.string,
+};
+
+PieLegend.defaultProps = {
+ text: '',
+ color: '',
+};
diff --git a/src/Chart/chartUtils.js b/src/Chart/chartUtils.js
new file mode 100644
index 0000000..dbcba35
--- /dev/null
+++ b/src/Chart/chartUtils.js
@@ -0,0 +1,72 @@
+const moment = require('moment');
+
+const convertToLineGraphDataset = (dataList, dataType) => {
+ const labels = [];
+ const total = [];
+ dataList.map((groupedRecordsByDate) => {
+ const filterData = groupedRecordsByDate.filter((item) => item.type === dataType);
+ const result = filterData.reduce((sum, { amount }) => {
+ const parsedAmount = parseFloat(amount);
+ return sum + parsedAmount;
+ }, 0);
+ if (filterData.length !== 0) {
+ const formatDate = moment(groupedRecordsByDate[0].date, 'MMMM Do YYYY').format('D');
+ labels.push(formatDate);
+ total.push(result);
+ }
+ return null;
+ });
+ return { labels: labels.reverse(), total: total.reverse() };
+};
+
+const convertToDatasetByCategory = (dataList, dataType) => {
+ const filterData = dataList.filter((item) => item.type === dataType);
+ if (filterData.length !== 0) {
+ const dataSet = [];
+ const colorSet = [];
+ const legendSet = [];
+ filterData.forEach((item) => {
+ const index = dataSet.findIndex((value) => value.name === item.labelName.name);
+ if (index === -1) {
+ dataSet.push({
+ name: item.labelName.name,
+ total: parseFloat(item.amount),
+ color: item.labelName.color,
+ });
+ colorSet.push(item.labelName.color);
+ legendSet.push({
+ name: item.labelName.name,
+ color: item.labelName.color,
+ });
+ } else {
+ const newValue = parseFloat(dataSet[index].total) + parseFloat(item.amount);
+ dataSet[index].total = newValue;
+ }
+ });
+ return { dataSet, legendSet };
+ }
+ return [];
+};
+
+const filterDataByPeriod = (dataList, range, view) => {
+ const monthRange = range.format('MMM YYYY');
+ const yearRange = range.format('YYYY');
+ let result;
+ switch (view) {
+ case 'month':
+ result = dataList.filter((value) => moment.unix(value.date).format('MMM YYYY') === monthRange);
+ break;
+ case 'year':
+ result = dataList.filter((value) => moment.unix(value.date).format('YYYY') === yearRange);
+ break;
+ default:
+ break;
+ }
+ return result;
+};
+
+export default {
+ convertToLineGraphDataset,
+ convertToDatasetByCategory,
+ filterDataByPeriod,
+};
diff --git a/src/Chart/index.jsx b/src/Chart/index.jsx
new file mode 100644
index 0000000..0dfce16
--- /dev/null
+++ b/src/Chart/index.jsx
@@ -0,0 +1,82 @@
+import React, { useState } from 'react';
+import { View, ScrollView } from 'react-native';
+import { useSelector } from 'react-redux';
+import MainHeader from '../Common/MainHeader';
+import DateSlider from '../Common/DateSlider';
+import DateOverlay from '../Common/DateOverlay';
+import setThemeStyle from '../Common/theme/setThemeStyle';
+import EmptyHistory from '../Stats/EmptyHistory';
+import utils from '../Stats/utils';
+import statsUtils from './chartUtils';
+import LineGraph from './LineGraph';
+import PieGraph from './PieGraph';
+
+const moment = require('moment');
+
+export default function Chart() {
+ const { transactions } = useSelector((state) => state.transactions);
+ const { themeMode } = useSelector((state) => state.theme);
+ const styles = setThemeStyle(themeMode);
+ const [view, setCurrentView] = useState('month');
+ const [timePeriodOptions, setTimePeriod] = useState(utils.getDateSet(moment(), view));
+ const [isOverlayVisible, setOverlayVisibility] = useState(false);
+ const updateHeaderView = (type) => {
+ setCurrentView(type);
+ setTimePeriod(utils.getDateSet(moment(), type));
+ setOverlayVisibility(!isOverlayVisible);
+ };
+
+ const filterListView = (transactionRecords) => {
+ const current = timePeriodOptions[1];
+ return utils.filterData(transactionRecords, current, view);
+ };
+
+
+ const navBarFunc = [
+ {
+ name: 'filter',
+ func: () => setOverlayVisibility(true),
+ },
+ ];
+
+ const filteredDataByDate = filterListView(utils.groupTransactionsByDate(transactions));
+
+ const filterDataByPeriod = statsUtils.filterDataByPeriod(
+ transactions, timePeriodOptions[1], view,
+ );
+
+ const dataSetByDate = statsUtils.convertToLineGraphDataset(filteredDataByDate, 'Expense');
+ const graphDataSet = statsUtils.convertToDatasetByCategory(filterDataByPeriod, 'Expense');
+
+ const isLineChartExist = filterDataByPeriod.length !== 0 && dataSetByDate.labels.length !== 0;
+ const isPieChartExist = filterDataByPeriod.length !== 0 && graphDataSet.length !== 0;
+
+ return (
+
+ updateHeaderView(viewValue)}
+ onPressClose={() => setOverlayVisibility(false)}
+ />
+
+ setTimePeriod(utils.getDateSet(value, type))}
+ viewType={view}
+ />
+
+ {isLineChartExist && isPieChartExist ? (
+ <>
+
+
+
+
+
+
+ >
+ )
+ : }
+
+
+ );
+}
diff --git a/src/Common/Color.js b/src/Common/Color.js
index 738352b..8483fc6 100644
--- a/src/Common/Color.js
+++ b/src/Common/Color.js
@@ -2,6 +2,9 @@ export default {
navColor: {
activeTintColor: '#5C6BC0',
inactiveTintColor: 'gray',
+ style: {
+ backgroundColor: '#e0e0e0',
+ },
},
headerColor: {
@@ -14,5 +17,7 @@ export default {
green: ['#2fc899', '#78ef93'],
purple: ['#a765cf', '#f8b6cc'],
orange: ['#ef6d6b', '#feaa74'],
+ gray: ['#ababab', '#d1d1d1'],
+ white: ['#ffffff', '#ffffff'],
},
};
diff --git a/src/Common/DateOverlay.jsx b/src/Common/DateOverlay.jsx
new file mode 100644
index 0000000..3e93c92
--- /dev/null
+++ b/src/Common/DateOverlay.jsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import { View } from 'react-native';
+import { ListItem, Overlay, Button } from 'react-native-elements';
+import PropTypes from 'prop-types';
+
+export default function DateOverlay(props) {
+ const { isOverlayVisible, onPressClose, onPressBtn } = props;
+
+ return (
+
+
+
+
+
+ onPressBtn('month')} />
+ onPressBtn('year')} />
+
+
+
+ );
+}
+
+DateOverlay.propTypes = {
+ isOverlayVisible: PropTypes.bool,
+ onPressClose: PropTypes.func.isRequired,
+ onPressBtn: PropTypes.func.isRequired,
+};
+
+DateOverlay.defaultProps = {
+ isOverlayVisible: false,
+};
diff --git a/src/Stats/DateSlider.jsx b/src/Common/DateSlider.jsx
similarity index 77%
rename from src/Stats/DateSlider.jsx
rename to src/Common/DateSlider.jsx
index b038018..e50bf20 100644
--- a/src/Stats/DateSlider.jsx
+++ b/src/Common/DateSlider.jsx
@@ -1,15 +1,19 @@
import React from 'react';
import { View, Text } from 'react-native';
-import PropTypes from 'prop-types';
import { Button } from 'react-native-elements';
-import styles from '../Common/themeStyle';
+import { useSelector } from 'react-redux';
+import PropTypes from 'prop-types';
+import setThemeStyle from './theme/setThemeStyle';
+
export default function DateSlider(props) {
+ const { themeMode } = useSelector((state) => state.theme);
+ const styles = setThemeStyle(themeMode);
const { viewSet, onPressBtn, viewType } = props;
const format = viewType === 'month' ? 'MMM YYYY' : 'YYYY';
return (
-
+