Merge tag 'v0.0.1-alpha.1'
This commit is contained in:
commit
091179f627
503 changed files with 28671 additions and 1651 deletions
58
.angular-cli.json
Normal file
58
.angular-cli.json
Normal file
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"project": {
|
||||
"version": "1.0.0-alpha.4",
|
||||
"name": "coreui-angular"
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"root": "src",
|
||||
"outDir": "dist",
|
||||
"assets": ["assets"],
|
||||
"index": "index.html",
|
||||
"main": "main.ts",
|
||||
"polyfills": "polyfills.ts",
|
||||
"test": "test.ts",
|
||||
"tsconfig": "tsconfig.app.json",
|
||||
"testTsconfig": "tsconfig.spec.json",
|
||||
"prefix": "app",
|
||||
"scripts": [
|
||||
"../node_modules/moment/min/moment.min.js"
|
||||
],
|
||||
"styles": [
|
||||
"scss/style.scss"
|
||||
],
|
||||
"environmentSource": "environments/environment.ts",
|
||||
"environments": {
|
||||
"dev": "environments/environment.ts",
|
||||
"prod": "environments/environment.prod.ts",
|
||||
"local": "environments/environment.local.ts"
|
||||
}
|
||||
}
|
||||
],
|
||||
"e2e": {
|
||||
"protractor": {
|
||||
"config": "./protractor.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": [
|
||||
{
|
||||
"project": "src/tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"project": "src/tsconfig.spec.json"
|
||||
},
|
||||
{
|
||||
"project": "e2e/tsconfig.e2e.json"
|
||||
}
|
||||
],
|
||||
"test": {
|
||||
"karma": {
|
||||
"config": "./karma.conf.js"
|
||||
}
|
||||
},
|
||||
"defaults": {
|
||||
"styleExt": "scss",
|
||||
"prefixInterfaces": false
|
||||
}
|
||||
}
|
14
.editorconfig
Normal file
14
.editorconfig
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = 0
|
||||
trim_trailing_whitespace = false
|
27
.gitignore
vendored
27
.gitignore
vendored
|
@ -17,6 +17,33 @@ $RECYCLE.BIN/
|
|||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/bower_components
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
*.launch
|
||||
.settings/
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage/*
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# e2e
|
||||
/e2e/*.js
|
||||
/e2e/*.map
|
||||
|
||||
# local env variable
|
||||
/src/environments/environment.local.ts
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 creativeLabs Lukasz Holeczek.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the Software), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, andor sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
65
README.md
65
README.md
|
@ -1,2 +1,63 @@
|
|||
# FoodLoop-Web
|
||||
For information on how to edit the CoreUI, see here: http://coreui.io/docs/getting-started/introduction
|
||||
# LocalLoop Web Interface
|
||||
|
||||
This is the repository for the LocalLoop web interface, for traders and
|
||||
customers to see and submit data to the service.
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started with development, you will need an up to date version of
|
||||
node.js, git, and access to either the backend dev server, or a local running
|
||||
copy of the backend server from [LocalLoop Server][LocalLoop-Server].
|
||||
|
||||
For your local node.js, We reccomend using [n][tj/n] on \*nix and Mac, for
|
||||
Windows take a look at [nodist][marcelklehr/nodist] - although other options
|
||||
exist. We reccomend Node.js version 8.0.0+ and npm version 5.3.0+.
|
||||
|
||||
To get this repository set up, first clone it and then run the following
|
||||
commands:
|
||||
|
||||
```
|
||||
npm install -g @angular/cli
|
||||
npm install
|
||||
```
|
||||
|
||||
[LocalLoop-Server]:https://github.com/Pear-Trading/Foodloop-Server
|
||||
[tj/n]:https://github.com/tj/n
|
||||
[marcelklehr/nodist]:https://github.com/marcelklehr/nodist
|
||||
|
||||
## Environments
|
||||
|
||||
The app defaults to using the development server. For other options, see
|
||||
`src/environments/environments.ts`
|
||||
|
||||
# Old README
|
||||
|
||||
This is the old README with some minor tips on getting started, and more reading.
|
||||
|
||||
## Angular2DevelopmentCLI
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.0-beta.32.3.
|
||||
|
||||
### Development server
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
### Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`.
|
||||
|
||||
### Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
|
||||
|
||||
### Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
### Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||
Before running the tests make sure you are serving the app via `ng serve`.
|
||||
|
||||
### Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||
|
|
149
app.js
149
app.js
|
@ -1,149 +0,0 @@
|
|||
var app = angular.module(
|
||||
"FoodLoop",
|
||||
[
|
||||
'ngRoute',
|
||||
'ui.router'
|
||||
]
|
||||
);
|
||||
|
||||
// calling order
|
||||
// 1-> app.config()
|
||||
// 2-> app.run()
|
||||
// 3-> directive's compile functions (if they are found in the dom)
|
||||
// 4-> app.controller()
|
||||
// 5-> directive's link functions (again, if found)
|
||||
|
||||
|
||||
app.config(function($stateProvider, $urlRouterProvider) {
|
||||
// use $urlRouterProvider to catch all the illeage cases
|
||||
// $urlRouterProvider.otherwise("/login");
|
||||
|
||||
$stateProvider
|
||||
// if loggin as user
|
||||
.state('user',{
|
||||
url:"/user",
|
||||
views:{
|
||||
'': {templateUrl:'pages/home/home.html',controller:'userCtrl'},
|
||||
'header@user': {templateUrl:'pages/user/header.user.html'}, // nested view
|
||||
'sidebar@user': {templateUrl:'pages/user/sidebar.user.html'},
|
||||
'main@user': {templateUrl:'pages/user/main.user.html'},
|
||||
},data:{
|
||||
requireLogin: false
|
||||
}
|
||||
})
|
||||
.state('user.receipt',{
|
||||
url:"",
|
||||
views:{
|
||||
'main@user': {templateUrl:'pages/receipt/receipt.html',controller:"receiptCtrl"},
|
||||
}
|
||||
})
|
||||
.state('user.leaderboard',{
|
||||
url:"",
|
||||
views:{
|
||||
'main@user': {templateUrl:'pages/user/main.leaderboard.html'},
|
||||
}
|
||||
})
|
||||
.state('user.settings',{
|
||||
url:"",
|
||||
views:{
|
||||
'main@user': {templateUrl:'pages/user/main.settings.html'},
|
||||
}
|
||||
})
|
||||
.state('user.help',{
|
||||
url:"",
|
||||
views:{
|
||||
'main@user': {templateUrl:'pages/user/main.settings.html'},
|
||||
}
|
||||
})
|
||||
.state('admin.view_receipt',{
|
||||
url:"",
|
||||
params: {
|
||||
receipt: null,
|
||||
},
|
||||
views:{
|
||||
'main@admin': {
|
||||
templateUrl:'pages/admin/main.receipt.html',
|
||||
controller: function($scope,$stateParams){
|
||||
$scope.receipt = $stateParams.receipt;
|
||||
console.log($scope.receipt);
|
||||
}},
|
||||
},data:{
|
||||
requireLogin: false
|
||||
}
|
||||
}
|
||||
)
|
||||
.state('admin',{
|
||||
url:"/admin",
|
||||
controller: 'adminCtrl',
|
||||
views:{
|
||||
'': { templateUrl: 'pages/home/home.html',controller:'adminCtrl'}, // default view}
|
||||
'header@admin': {templateUrl:'pages/admin/header.admin.html'}, // nested view
|
||||
'sidebar@admin': {templateUrl:'pages/admin/sidebar.admin.html'},
|
||||
'main@admin': {templateUrl:'pages/admin/main.admin.html'},
|
||||
},data:{
|
||||
requireLogin: false
|
||||
}
|
||||
})
|
||||
.state('trader',{
|
||||
url:"/trader",
|
||||
views:{
|
||||
'': { templateUrl: 'pages/home/home.html',controller:'traderCtrl'}, // default view}
|
||||
'header@trader': {templateUrl:'pages/trader/header.trader.html'}, // nested view
|
||||
'sidebar@trader': {templateUrl:'pages/trader/sidebar.trader.html'},
|
||||
'main@trader': {templateUrl:'pages/trader/main.trader.html'},
|
||||
},data:{
|
||||
requireLogin: false
|
||||
}
|
||||
})
|
||||
|
||||
.state('map',{
|
||||
url: '/map',
|
||||
templateUrl: 'pages/map/map.html',
|
||||
controller: 'mapCtrl',
|
||||
data: {
|
||||
requireLogin : false
|
||||
}
|
||||
})
|
||||
.state('login',{
|
||||
url: '',
|
||||
templateUrl: 'pages/login/login.html',
|
||||
controller: 'loginCtrl',
|
||||
data: {
|
||||
requireLogin : false
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
/* redirects to different page based on whether the user is login or not and */
|
||||
/* if log on, check user type and redirect/construct a custom dashboard page */
|
||||
/* to extend, users may have a custome dashboard with different layout, this */
|
||||
/* needs to be handled using HTML page which is specifically constucted by */
|
||||
/* page'controller and obtain variable setting from server */
|
||||
// /* if not, redirect to login in page */
|
||||
app.run(function ($rootScope,$state,authService) { // kickstart the application
|
||||
// listening to the when a state change start
|
||||
console.log("State changes");
|
||||
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
|
||||
console.log(toState);
|
||||
// var requireLogin = toState.data.requireLogin;
|
||||
// redirect to login page if satisfy the following conditions
|
||||
// 1. seesion expired and user tries to access a page
|
||||
// if ((requireLogin && typeof $rootScope.currentUser === 'undefined')) {
|
||||
// event.preventDefault();
|
||||
// $state.transitionTo('login');
|
||||
// }
|
||||
});
|
||||
// Testing, configuration to firebase
|
||||
var config = {
|
||||
apiKey: "AIzaSyDypwjmMD818GQTTfyhTpx76ChJpDsZGek",
|
||||
authDomain: "foodloop-666db.firebaseapp.com",
|
||||
databaseURL: "https://foodloop-666db.firebaseio.com",
|
||||
storageBucket: "foodloop-666db.appspot.com",
|
||||
messagingSenderId: "832579459759"
|
||||
};
|
||||
firebase.initializeApp(config);
|
||||
|
||||
})
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[0212/144844:ERROR:tcp_listen_socket.cc(76)] Could not bind socket to 127.0.0.1:6004
|
||||
[0212/144844:ERROR:node_debugger.cc(86)] Cannot start debugger server
|
24
e2e/login.e2e-spec.ts
Normal file
24
e2e/login.e2e-spec.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { LoginPageObject } from './login.po';
|
||||
|
||||
describe('Login Page', () => {
|
||||
let page: LoginPageObject;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new LoginPageObject();
|
||||
page.navigateTo();
|
||||
});
|
||||
|
||||
it('should have a header saying login', () => {
|
||||
expect(page.getLoginHeaderText()).toEqual('Login');
|
||||
});
|
||||
|
||||
it('should have a username box of type text', () => {
|
||||
expect(page.isUsernameFieldPresent()).toBeTruthy();
|
||||
expect(page.getUsernameFieldType()).toBe('text');
|
||||
});
|
||||
|
||||
it('should have a password box of type password', () => {
|
||||
expect(page.isPasswordFieldPresent()).toBeTruthy();
|
||||
expect(page.getPasswordFieldType()).toBe('password');
|
||||
});
|
||||
});
|
20
e2e/login.po.ts
Normal file
20
e2e/login.po.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { browser, element, by } from 'protractor';
|
||||
|
||||
export class LoginPageObject {
|
||||
navigateTo() {
|
||||
return browser.get('/login');
|
||||
}
|
||||
|
||||
getLoginHeaderText() {
|
||||
return element(by.css('app-root h1')).getText();
|
||||
}
|
||||
|
||||
getUsernameField() { return element(by.id('username')); }
|
||||
getPasswordField() { return element(by.id('password')); }
|
||||
|
||||
isUsernameFieldPresent() { return this.getUsernameField().isPresent(); }
|
||||
isPasswordFieldPresent() { return this.getPasswordField().isPresent(); }
|
||||
|
||||
getUsernameFieldType() { return this.getUsernameField().getAttribute('type'); }
|
||||
getPasswordFieldType() { return this.getPasswordField().getAttribute('type'); }
|
||||
}
|
13
e2e/tsconfig.e2e.json
Normal file
13
e2e/tsconfig.e2e.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/e2e",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
75
index.html
75
index.html
|
@ -1,75 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html ng-app="FoodLoop" >
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
|
||||
|
||||
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
|
||||
<head>
|
||||
<title>FoodLoop Login</title>
|
||||
|
||||
<!-- Bootstrap and jQuery js -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="app.js"></script>
|
||||
|
||||
<!-- Include the ui-router script -->
|
||||
<script src="//unpkg.com/angular-ui-router/release/angular-ui-router.min.js"></script>
|
||||
|
||||
<!-- D3 chart js -->
|
||||
<script src="https://d3js.org/d3.v4.min.js"></script>
|
||||
|
||||
<!-- Map js dependecies -->
|
||||
<script src="https://d3js.org/topojson.v2.min.js"></script>
|
||||
|
||||
<!-- Chart js -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
|
||||
|
||||
|
||||
|
||||
<!-- MVC for FoodLoop app -->
|
||||
<script src="pages/login/loginCtrl.js"></script>
|
||||
<!--<link rel="stylesheet" href="pages/login/login.css">-->
|
||||
|
||||
<script src="pages/home/homeCtrl.js"></script>
|
||||
<link rel="stylesheet" href="pages/home/home.css">
|
||||
|
||||
<script src="pages/admin/adminCtrl.js"></script>
|
||||
<!--<link rel="stylesheet" href="pages/admin/admin.css">-->
|
||||
|
||||
<script src="pages/receipt/receiptCtrl.js"></script>
|
||||
<!--<link rel="stylesheet" href="pages/receipt/receipt.css">-->
|
||||
|
||||
<script src="pages/user/userCtrl.js"></script>
|
||||
<!--<link rel="stylesheet" href="pages/user/user.css">-->
|
||||
|
||||
<script src="pages/trader/traderCtrl.js"></script>
|
||||
<!--<link rel="stylesheet" href="pages/trader/trader.css">-->
|
||||
|
||||
<script src="pages/map/mapCtrl.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
|
||||
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.33.0/mapbox-gl.js'></script>
|
||||
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.33.0/mapbox-gl.css' rel='stylesheet' />
|
||||
<!-- Import services-->
|
||||
<script src="services/authService.js"></script>
|
||||
<script src="services/chartService.js"></script>
|
||||
<script src="services/uploadReceiptservice.js"></script>
|
||||
|
||||
<!-- firebase for testing -->
|
||||
<script src="https://www.gstatic.com/firebasejs/3.6.9/firebase.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body >
|
||||
|
||||
<!-- Dsiplay the main content -->
|
||||
<ui-view></ui-view>
|
||||
</body>
|
||||
</html>
|
44
karma.conf.js
Normal file
44
karma.conf.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/0.13/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular/cli'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular/cli/plugins/karma')
|
||||
],
|
||||
client:{
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
files: [
|
||||
{ pattern: './src/test.ts', watched: false }
|
||||
],
|
||||
preprocessors: {
|
||||
'./src/test.ts': ['@angular/cli']
|
||||
},
|
||||
mime: {
|
||||
'text/x-typescript': ['ts','tsx']
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
reports: [ 'html', 'lcovonly' ],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
angularCli: {
|
||||
environment: 'dev'
|
||||
},
|
||||
reporters: config.angularCli && config.angularCli.codeCoverage
|
||||
? ['progress', 'coverage-istanbul']
|
||||
: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false
|
||||
});
|
||||
};
|
9984
package-lock.json
generated
Normal file
9984
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
63
package.json
Normal file
63
package.json
Normal file
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"name": "coreui-angular",
|
||||
"version": "1.0.0-alpha.5",
|
||||
"description": "Open Source Bootstrap Admin Template",
|
||||
"author": "",
|
||||
"url": "http://coreui.io",
|
||||
"copyright": "Copyright 2017 creativeLabs Łukasz Holeczek",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/common": "4.0.3",
|
||||
"@angular/compiler": "4.0.3",
|
||||
"@angular/core": "4.0.3",
|
||||
"@angular/forms": "4.0.3",
|
||||
"@angular/http": "4.0.3",
|
||||
"@angular/platform-browser": "4.0.3",
|
||||
"@angular/platform-browser-dynamic": "4.0.3",
|
||||
"@angular/router": "4.0.3",
|
||||
"@angular/upgrade": "4.0.3",
|
||||
"@types/moment": "^2.13.0",
|
||||
"angular-in-memory-web-api": "^0.3.1",
|
||||
"chart.js": "2.5.0",
|
||||
"core-js": "2.4.1",
|
||||
"moment": "^2.18.1",
|
||||
"ng2-charts": "1.6.0",
|
||||
"ng2-validation-manager": "^0.3.1",
|
||||
"ngx-bootstrap": "1.6.6",
|
||||
"ngx-pagination": "^3.0.1",
|
||||
"rxjs": "5.4.2",
|
||||
"ts-helpers": "1.1.2",
|
||||
"webpack": "3.5.4",
|
||||
"webpack-dev-server": "2.7.1",
|
||||
"zone.js": "0.8.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.3.0",
|
||||
"@angular/compiler-cli": "4.0.3",
|
||||
"@types/jasmine": "2.5.54",
|
||||
"@types/jasminewd2": "2.0.2",
|
||||
"@types/node": "8.0.24",
|
||||
"codelyzer": "2.1.1",
|
||||
"jasmine-core": "2.7.0",
|
||||
"jasmine-spec-reporter": "4.2.1",
|
||||
"karma": "1.7.0",
|
||||
"karma-chrome-launcher": "2.2.0",
|
||||
"karma-cli": "1.0.1",
|
||||
"karma-coverage-istanbul-reporter": "1.3.0",
|
||||
"karma-jasmine": "1.1.0",
|
||||
"karma-jasmine-html-reporter": "0.2.2",
|
||||
"protractor": "5.1.2",
|
||||
"ts-node": "3.3.0",
|
||||
"tslint": "4.5.1",
|
||||
"typescript": "2.4.2"
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
<div ui-view="header"></div>
|
||||
<div ui-view="sidebar"></div>
|
||||
<div ui-view="main"></div>
|
|
@ -1,67 +0,0 @@
|
|||
/* this controller specifies the logic layer of the admin page */
|
||||
/* including the content to be display, sidebar, header */
|
||||
/* functionailities involve for an admin */
|
||||
app.controller('adminCtrl', function($scope,$state) {
|
||||
$scope.users;
|
||||
$scope.controllby = "admin";
|
||||
// Initialize Firebase
|
||||
$scope.pending_receipt_sum = 2;
|
||||
$scope.pending_receipt = [
|
||||
{
|
||||
receipt_ref: "r1",
|
||||
submitted_by : "John Lemon",
|
||||
submitted_time: "31",
|
||||
submitted_amount: "8.66",
|
||||
details: "sjadsjoiadsj iasdn aisdn alsdi jadi jasdi ajsdoi ndi snd"
|
||||
}
|
||||
,
|
||||
{
|
||||
submitted_by : "User007",
|
||||
submitted_time: "21",
|
||||
submitted_amount: "22.22"
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
/* section for receipt management start * /
|
||||
/* review a pending receipt */
|
||||
/* fetch a list of pending receipt from server */
|
||||
/* fetch a list of approve receipt from server */
|
||||
$scope.reviewReceipt = function(myReceipt){
|
||||
// testing
|
||||
console.log("[DEBUG]: reviewReceipt called");
|
||||
// show page for review this receipt
|
||||
$state.go('admin.view_receipt', {receipt: myReceipt})
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
$scope.approve_receipt = function(receipt_ref){
|
||||
// call api to approve a pending receipt
|
||||
// notify user
|
||||
}
|
||||
|
||||
|
||||
$scope.fetch_pending_receipt = function(){
|
||||
|
||||
}
|
||||
|
||||
$scope.fetch_submitted_receipt = function(){
|
||||
|
||||
}
|
||||
/* section for receipt management end */
|
||||
|
||||
|
||||
// Get a reference to the database service
|
||||
var database = firebase.database();
|
||||
firebase.database().ref('/users/').once('value').then(function(snapshot) {
|
||||
$scope.users = snapshot.val();
|
||||
});
|
||||
|
||||
$scope.test = function(){
|
||||
|
||||
console.log("CLiced ");
|
||||
console.log($scope.users);
|
||||
}
|
||||
});
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<nav class="navbar navbar-toggleable-md fixed-top navbar-inverse" style="background-color:#0091EA;">
|
||||
<button class="navbar-toggler navbar-toggler-right hidden-lg-up" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">FoodLoop</a>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Profile</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Help</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="form-inline mt-2 mt-md-0">
|
||||
<input class="form-control mr-sm-2" type="text" placeholder="Search">
|
||||
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
|
@ -1,50 +0,0 @@
|
|||
<main class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 pt-3">
|
||||
|
||||
<div class="row no-gutters">
|
||||
<div class="col-2">
|
||||
<div class="rankCard">
|
||||
<div class="receiptCardHeader"> Section toolbox </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="receiptCard">
|
||||
<div class="receiptCardHeader"> List/Table </div>
|
||||
<div class="tableCard">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Action</th>
|
||||
<th>#</th>
|
||||
<th>From</th>
|
||||
<th>When</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat-start="receipt in pending_receipt">
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" ng-if="receipt.expanded" ng-click="receipt.expanded = false">review</button>
|
||||
<button type="button" class="btn btn-primary" ng-if="!receipt.expanded" ng-click="receipt.expanded = true">review</button>
|
||||
</td>
|
||||
<td>{{$index + 1}}</td>
|
||||
<td>{{receipt.submitted_by}}</td>
|
||||
<td>{{receipt.submitted_time}} minutes ago</td>
|
||||
<td>£{{receipt.submitted_amount}}</td>
|
||||
</tr>
|
||||
<tr ng-if="receipt.expanded" ng-repeat-end="">
|
||||
<td colspan="5">
|
||||
<div class="receiptDetailCard">
|
||||
{{receipt.details}}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- row first -->
|
||||
|
||||
</main>
|
|
@ -1,43 +0,0 @@
|
|||
<main class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 pt-3">
|
||||
|
||||
<div class="row no-gutters">
|
||||
<div class="col-2">
|
||||
<div class="rankCard">
|
||||
<div class="receiptCardHeader"> Section toolbox </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="receiptCard">
|
||||
<div class="receiptCardHeader">{{receipt.receipt_ref}}</div>
|
||||
<div class="tableCard">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>From</th>
|
||||
<th>When</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{$index + 1}}</td>
|
||||
<td>{{receipt.submitted_by}}</td>
|
||||
<td>{{receipt.submitted_time}} minutes ago</td>
|
||||
<td>£{{receipt.submitted_amount}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- table card-->
|
||||
<div class="receiptImageCard">
|
||||
<div> </div>
|
||||
</div>
|
||||
<!-- receiptImageCard-->
|
||||
</div>
|
||||
<!-- receipt card -->
|
||||
</div>
|
||||
<!-- col -->
|
||||
</div>
|
||||
<!-- row first -->
|
||||
</main>
|
|
@ -1,46 +0,0 @@
|
|||
<!-- This page defines a side bar for admin -->
|
||||
<nav class="col-sm-3 col-md-2 hidden-xs-down bg-faded sidebar">
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#">Admin Portal <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">User Management</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Trader Management</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Sign out</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav nav-pills flex-column" id="meq">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#">Receipt Management</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Pending receipt
|
||||
<span class="badge badge-danger">{{pending_receipt_sum}}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Option 2</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Option 3</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Nav item again</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">One more nav</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Another nav item</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
|
@ -1,353 +0,0 @@
|
|||
/*
|
||||
* Base structure
|
||||
*/
|
||||
|
||||
/* Move down content because we have a fixed navbar that is 50px tall */
|
||||
body {
|
||||
padding-top: 50px;
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
/*
|
||||
* Typography
|
||||
*/
|
||||
|
||||
h1 {
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 9px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
main{
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 51px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
padding: 20px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
|
||||
border-right: 1px solid #eee;
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
|
||||
}
|
||||
|
||||
/* Sidebar navigation */
|
||||
.sidebar {
|
||||
margin-top: -16px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.sidebar .nav {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sidebar .nav-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar .nav-item + .nav-item {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.profile-pic {
|
||||
border-radius: 80%;
|
||||
background-color: transparent;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: dodgerblue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.profilePic{
|
||||
padding: 16px;
|
||||
background-color: transparent;
|
||||
max-width: 100%;
|
||||
height: 130px;
|
||||
background-color: dodgerblue;
|
||||
}
|
||||
|
||||
.profileInfo{
|
||||
color:white;
|
||||
padding: 16px;
|
||||
padding-top: 30px;
|
||||
height: 130px;
|
||||
background-color: dodgerblue;
|
||||
}
|
||||
|
||||
.profileTitle{
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dashboard
|
||||
*/
|
||||
|
||||
/* Placeholders */
|
||||
.placeholders {
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
||||
.placeholder img {
|
||||
padding-top: 1.5rem;
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
.title{
|
||||
color: black;
|
||||
}
|
||||
.flCard{
|
||||
color:black;
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
/*width: 100%;*/
|
||||
height: 110px;;
|
||||
margin-top: 16px;
|
||||
background-color: white;
|
||||
border: green;
|
||||
padding:16px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.rankCard{
|
||||
color:black;
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
height: 300px;;
|
||||
margin-top: 16px;
|
||||
background-color: white;
|
||||
border: green;
|
||||
|
||||
}
|
||||
|
||||
.rankCardHeader{
|
||||
border-radius: 3px 3px 0 0;
|
||||
padding: 3px;
|
||||
color:white;
|
||||
height:30px;
|
||||
background-color: dodgerblue;
|
||||
}
|
||||
|
||||
.chartCardHeader{
|
||||
border-radius: 3px 3px 0 0;
|
||||
padding: 3px;
|
||||
color:white;
|
||||
height:30px;
|
||||
background-color: orangered;
|
||||
}
|
||||
|
||||
.rankCardContent{
|
||||
padding: 3px;
|
||||
/*color:white;*/
|
||||
/*background-color: dodgerblue;*/
|
||||
}
|
||||
|
||||
.flCardHeader{
|
||||
height: 25px;
|
||||
}
|
||||
.flCardMain{
|
||||
margin: -16px;
|
||||
font-size: 3.0em;
|
||||
color: dimgray;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.chartCard{
|
||||
color:black;
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
height: 300px;;
|
||||
margin-top: 16px;
|
||||
background-color: white;
|
||||
|
||||
}
|
||||
.flCardNote{
|
||||
font-size: 0.8em;
|
||||
color: dodgerblue;
|
||||
text-align: right;
|
||||
}
|
||||
#receiptTable{
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
|
||||
/* CSS FOR RECEIPT */
|
||||
|
||||
.receiptItem{
|
||||
color:black;
|
||||
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
padding: 16px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.receiptCard{
|
||||
color:black;
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
margin-top: 16px;
|
||||
padding:16px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.receiptCardHeader{
|
||||
border-radius: 3px 3px 0 0;
|
||||
padding: 3px;
|
||||
color:white;
|
||||
padding: 16px;
|
||||
background-color: dodgerblue;
|
||||
}
|
||||
|
||||
|
||||
.receiptDetailCard{
|
||||
color:black;
|
||||
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
height: 300px;
|
||||
margin-top: 16px;
|
||||
background-color: lightcyan;
|
||||
}
|
||||
|
||||
.addButton{
|
||||
background-color: transparent;
|
||||
font-size: 1.0em;
|
||||
margin-left: 50%;
|
||||
|
||||
}
|
||||
|
||||
.dragImageBox:hover{
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
.dragImageBox{
|
||||
border: 2px dashed dodgerblue;
|
||||
border-radius: 4px;
|
||||
background-color:white;
|
||||
height: 150px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
|
||||
.thumb{
|
||||
color:black;
|
||||
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
background-color: white;
|
||||
width: 50px;
|
||||
height: 130px;
|
||||
}
|
||||
|
||||
/* TEMPALTE CSS FOR DISPLAY A CUSTOM CARD */
|
||||
|
||||
.pearCard{
|
||||
color:black;
|
||||
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
/* On mouse-over, add a deeper shadow */
|
||||
.pearCard:hover {
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.pearCardFooter{
|
||||
width: 100%;
|
||||
margin-bottom: -16px;
|
||||
background-color: lightcyan;
|
||||
}
|
||||
.pearAutoHeight{
|
||||
height: auto;
|
||||
}
|
||||
.pearCardHeader{
|
||||
border-radius: 3px 3px 0 0;
|
||||
padding: 9px;
|
||||
color:white;
|
||||
background-color: dodgerblue;
|
||||
}
|
||||
|
||||
.pearOrange{
|
||||
background-color: orangered;
|
||||
}
|
||||
.pearBlue{
|
||||
background-color: dodgerblue;
|
||||
}
|
||||
.pearGreen{
|
||||
background-color: lawngreen;
|
||||
}
|
||||
.pearYellow{
|
||||
background-color: yellow;
|
||||
}
|
||||
.pearPurple{
|
||||
background-color: purple;
|
||||
}
|
||||
|
||||
.padding16{
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.margin16{
|
||||
margin-top:16px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* LOGIN CSS */
|
||||
.mainSection{
|
||||
margin-top: 20%;
|
||||
padding:16px;
|
||||
color:black;
|
||||
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
/*height: 150px;*/
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.mainItem{
|
||||
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.mainItem input[type=text] {
|
||||
/*border: 2px solid ;*/
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.mainItem input[type=password] {
|
||||
/*border: 2px solid ;*/
|
||||
border-radius: 4px;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
<!-- ideally, this page would be the tempalte for all user types, admin -->
|
||||
<!-- user, trader etc. this home page will defines the common html structure-->
|
||||
<!-- among differnet user page -->
|
||||
|
||||
|
||||
<!-- use ui-view to display header,sidebar and main content of differnet types -->
|
||||
<!-- this would the common layout, header, siderbar, main -->
|
||||
<!-- the actual content and logic within will be managed by -->
|
||||
<!-- seperate controller,css, html files -->
|
||||
|
||||
<div ui-view="header"></div>
|
||||
<div ui-view="sidebar"></div>
|
||||
<div ui-view="main"></div>
|
|
@ -1,18 +0,0 @@
|
|||
app.controller('homeCtrl', function($scope) {
|
||||
|
||||
// $stateProvider.state('contacts', {
|
||||
// template: '<h1>My Contacts</h1>'
|
||||
// }) $scope.username = "user";
|
||||
$scope.controllby = "home";
|
||||
|
||||
// $rootScope.userType = "admin";
|
||||
// $scope.getViewByUserType = function(){
|
||||
// return {
|
||||
// '': {templateUrl: 'pages/home/home.html',controller:'adminCtrl'}, // default view
|
||||
// 'header@home-admin': {templateUrl:'pages/admin/header.admin.html'}, // nested view
|
||||
// 'sidebar@home-admin': {templateUrl:'pages/admin/sidebar.admin.html'},
|
||||
// 'main@home-admin': {templateUrl:'pages/admin/main.admin.html'},
|
||||
// }
|
||||
// }
|
||||
// $scope.header = "i m not a header";
|
||||
});
|
|
@ -1,69 +0,0 @@
|
|||
<nav class="navbar fixed-top navbar-light bg-faded">
|
||||
|
||||
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Navbar</a>
|
||||
<div class="collapse navbar-collapse" id="navbarNavDropdown">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Features</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Pricing</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="http://example.com" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Dropdown link
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
||||
<a class="dropdown-item" href="#">Action</a>
|
||||
<a class="dropdown-item" href="#">Another action</a>
|
||||
<a class="dropdown-item" href="#">Something else here</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container-fluid">
|
||||
<div class="row justify-content-center">
|
||||
<!-- Fluid Gird, this login box stay in the middle of screen -->
|
||||
<div class="col-5">
|
||||
|
||||
<div class="mainSection" ng-controller="loginCtrl">
|
||||
<div class="row">
|
||||
<div class="col-3 mainItem">
|
||||
Username/Email
|
||||
</div>
|
||||
|
||||
<div class="col mainItem">
|
||||
<input type="text" ng-model="username" >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 mainItem">
|
||||
Password
|
||||
</div>
|
||||
|
||||
<div class="col mainItem">
|
||||
<input type="password" ng-model="password" >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mainItem">
|
||||
<button type="button" class="btn btn-primary" ng-click="signin()"> S2ign I1n </button>
|
||||
|
||||
<button type="button" class="btn btn-danger" ng-click="createAccount()">Create an account
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div><!-- Container fluid-->
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
app.controller('loginCtrl', function($scope,$state,$http,$rootScope,authService) {
|
||||
/* login variables */
|
||||
$scope.username = "user";
|
||||
$scope.password = "Doe";
|
||||
$scope.fullName = function() {
|
||||
return $scope.firstName + " " + $scope.lastName;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// 1. send request to server to authenticate login information
|
||||
// 2. on succeed, redirect to page
|
||||
// 2.1 on failed, display error message
|
||||
$scope.signin = function(){
|
||||
var foodloop_token_url_login = "http://192.168.2.172:3000/login";
|
||||
var loginData = JSON.stringify({
|
||||
email : this.username,
|
||||
password: this.password
|
||||
});
|
||||
console.log("Attempting to login in");
|
||||
|
||||
$http.post(foodloop_token_url_login,loginData).success(function(repsonse){
|
||||
console.log("Resolving response from server");
|
||||
console.log(repsonse.data);
|
||||
},function(repsonse){
|
||||
console.log("Ooops, Something went wrong");
|
||||
});
|
||||
authService.setUsername($scope.username);
|
||||
// $state.go("user");
|
||||
// if($scope.username === "admin"){
|
||||
// $state.go('admin');
|
||||
// }
|
||||
// else if($scope.username === "user"){
|
||||
// $state.go('user');
|
||||
// }
|
||||
// else{
|
||||
// $state.go('home');
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
$scope.createAccount = function(){
|
||||
|
||||
console.log("Create account button clicked");
|
||||
}
|
||||
|
||||
});
|
|
@ -1,7 +0,0 @@
|
|||
{"objects":[
|
||||
{"circle":{"coordinates":[54.0472, -2.8018]}},
|
||||
{"circle":{"coordinates":[-41.29,174.76]}},
|
||||
{"circle":{"coordinates":[-41.30,174.79]}},
|
||||
{"circle":{"coordinates":[-41.27,174.80]}},
|
||||
{"circle":{"coordinates":[-41.29,174.78]}}
|
||||
]}
|
|
@ -1,3 +0,0 @@
|
|||
#mapid { height: 180px; }
|
||||
|
||||
#map { width:600px; height: 600px }
|
|
@ -1,15 +0,0 @@
|
|||
<div id="map" style="width: 100%; height: 400px"></div>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<button class="btn btn-secondary btn-block" type="button">Track my spent</button>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="Search for...">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-secondary" type="button">Go!</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,61 +0,0 @@
|
|||
app.controller('mapCtrl',function($scope,$http,uploadReceiptService) {
|
||||
|
||||
|
||||
// data
|
||||
var traderGeoData = [
|
||||
{ Latitude:54.04,Longitude:2.80,trader:"sample_1" },
|
||||
{ Latitude:54.04,Longitude:2.80,trader:"sample_2" },
|
||||
{ Latitude:54.01,Longitude:2.78,trader:"sample_3" },
|
||||
];
|
||||
|
||||
var map = L.map('map').setView([54.0472, -2.8018], 13);
|
||||
mapLink =
|
||||
'<a href="http://openstreetmap.org">OpenStreetMap</a>';
|
||||
L.tileLayer(
|
||||
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© ' + mapLink + ' Contributors',
|
||||
maxZoom: 18,
|
||||
}).addTo(map);
|
||||
|
||||
var svgLayer = L.svg();
|
||||
svgLayer.addTo(map);
|
||||
|
||||
var svg = d3.select("#map").select("svg");
|
||||
var g = d3.select("#map").select("svg").select('g');
|
||||
g.attr("class", "leaflet-zoom-hide");
|
||||
|
||||
|
||||
/* We simply pick up the SVG from the map object */
|
||||
var svg = d3.select("#map").select("svg"),
|
||||
g = svg.append("g");
|
||||
|
||||
d3.json("../pages/map/circles.json", function(collection) {
|
||||
/* Add a LatLng object to each item in the dataset */
|
||||
collection.objects.forEach(function(d) {
|
||||
d.LatLng = new L.LatLng(d.circle.coordinates[0],
|
||||
d.circle.coordinates[1])
|
||||
})
|
||||
|
||||
var feature = g.selectAll("circle")
|
||||
.data(collection.objects)
|
||||
.enter().append("circle")
|
||||
.style("stroke", "black")
|
||||
.style("opacity", .6)
|
||||
.style("fill", "red")
|
||||
.attr("r", 20);
|
||||
|
||||
map.on("viewreset", update);
|
||||
update();
|
||||
|
||||
function update() {
|
||||
console.log("update!");
|
||||
feature.attr("transform",
|
||||
function(d) {
|
||||
return "translate("+
|
||||
map.latLngToLayerPoint(d.LatLng).x +","+
|
||||
map.latLngToLayerPoint(d.LatLng).y +")";
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,108 +0,0 @@
|
|||
<main class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 pt-3">
|
||||
<form>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-7">
|
||||
<div class="pearCard">
|
||||
<div class="pearCardHeader .pearGreen">Fill in to submit </div>
|
||||
<div class="padding16">
|
||||
<!-- from group start -->
|
||||
<div class="form-group row">
|
||||
<label for="example-text-input" class="col-2 col-form-label">Store name</label>
|
||||
<div class="col">
|
||||
<input class="form-control" type="text" ng-model="storename" placeholder="e.g. Three" id="example-text-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col">
|
||||
<div class="searchList">
|
||||
<ul class="list-group" ng-repeat="store in storeList">
|
||||
<li class="list-group-item ">{{store.store_id}}</li>
|
||||
<li class="list-group-item ">{{store.store_name}}</li>
|
||||
<li class="list-group-item ">{{store.store_address}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="example-search-input" class="col-2 col-form-label">amount</label>
|
||||
<div class="col">
|
||||
<input class="form-control" type="decimal" ng-model="amount" placeholder="e.g. 6.66" id="example-search-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row justify-content-center">
|
||||
<label for="example-email-input" class="col col-form-label">Image(Click 'Add' button or Drag an image into the box below)</label>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input type='file' ng-model ="receiptPhoto" accept="image/*"
|
||||
onchange="angular.element(this).scope().getImage(this)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="dragImageBox">
|
||||
<div class="row no-gutters">
|
||||
<img class="col-2 thumb" ng-src="{{receiptPhotoSrc}}"/>
|
||||
<!-- image details, progress bar etc. -->
|
||||
<div class="col-5 thumb">
|
||||
filename:{{receiptPhoto.filename}}<br> filesize:{{receiptPhoto.filesize}}<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="pearCardFooter">
|
||||
<button type="button" ng-click="uploadReceipt()" class="btn btn-primary"> Submit </button>
|
||||
<button type="button" class="btn btn-danger"> Reset </button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- from group end -->
|
||||
</div>
|
||||
<!-- PADDING -->
|
||||
</div>
|
||||
<!-- pear card -->
|
||||
</div>
|
||||
<!-- first col-5 -->
|
||||
|
||||
<div class="col">
|
||||
<div class="pearCard">
|
||||
<div class="pearCardHeader pearOrange"> Pending receipt
|
||||
<span class="badge badge-info">5 </span> </div>
|
||||
<!-- content start here -->
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>When</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="receipt in pending_list">
|
||||
<td>{{$index + 1}}</td>
|
||||
<td>{{receipt.submitted_time}}</td>
|
||||
<td>{{receipt.submitted_amount}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- second col -->
|
||||
</div>
|
||||
<!-- first row-->
|
||||
|
||||
|
||||
|
||||
</main>
|
|
@ -1,62 +0,0 @@
|
|||
app.controller('receiptCtrl',function($scope,$http,uploadReceiptService) {
|
||||
|
||||
// display the list of all exsiting store, validated and not validated
|
||||
$scope.storelist;
|
||||
|
||||
// require param for upload api
|
||||
$scope.microCurrencyValue;
|
||||
$scope.transactionAdditionType;
|
||||
$scope.addValidatedId;
|
||||
|
||||
$scope.storename;
|
||||
|
||||
// photo and path to the photo
|
||||
$scope.receiptPhoto;
|
||||
$scope.receiptPhotoSrc;
|
||||
|
||||
// list of pending reciepts await for approval from admin
|
||||
$scope.pending_list = [
|
||||
{submitted_time: 30 },{submitted_time:20},{submitted_time:10},{submitted_time:5},{submitted_time:1}
|
||||
];
|
||||
|
||||
|
||||
var foodloop_token_url_search = "http://192.168.2.172:3000/search";
|
||||
|
||||
|
||||
// get the latest store list
|
||||
$scope.getStoreList = function(){
|
||||
var data = {
|
||||
"searchName": "",
|
||||
"searchLocation": ""
|
||||
};
|
||||
$http.post(foodloop_token_url_search,data).then(function(response){
|
||||
console.log(response);
|
||||
});
|
||||
|
||||
// API call to /search to fetch a list of store
|
||||
}
|
||||
|
||||
$scope.storelist = $scope.getStoreList();
|
||||
|
||||
// select the image
|
||||
$scope.getImage = function(element) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
$scope.$apply(function($scope) {
|
||||
$scope.receiptPhoto = element.files[0];
|
||||
$scope.receiptPhotoSrc = event.target.result
|
||||
});
|
||||
}
|
||||
reader.readAsDataURL(element.files[0]);
|
||||
}
|
||||
|
||||
// upload the receipt to the server
|
||||
$scope.uploadReceipt = function(){
|
||||
uploadReceiptService.uploadReceipt();
|
||||
}
|
||||
|
||||
|
||||
// test
|
||||
// firebase api to upload an image
|
||||
|
||||
});
|
|
@ -1,27 +0,0 @@
|
|||
<nav class="navbar navbar-toggleable-md fixed-top navbar-inverse" style="background-color:#0091EA;">
|
||||
<button class="navbar-toggler navbar-toggler-right hidden-lg-up" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">FoodLoop</a>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Profile</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Help</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="form-inline mt-2 mt-md-0">
|
||||
<input class="form-control mr-sm-2" type="text" placeholder="Search">
|
||||
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
|
@ -1,6 +0,0 @@
|
|||
<main class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 pt-3">
|
||||
<div id="layouter">
|
||||
i m the main content in trader page
|
||||
</div>
|
||||
<!-- Layouter -->
|
||||
</main>
|
|
@ -1,44 +0,0 @@
|
|||
<!-- This page defines a side bar for admin -->
|
||||
<nav class="col-sm-3 col-md-2 hidden-xs-down bg-faded sidebar">
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#">Admin Portal <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Add User</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Add Trader</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Sign out</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav nav-pills flex-column" id="meq">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#">Receipt Management</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">View receipt</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Option 2</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Option 3</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Nav item again</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">One more nav</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Another nav item</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
|
@ -1,15 +0,0 @@
|
|||
app.controller('traderCtrl', function($scope,$location) {
|
||||
|
||||
$scope.content = "I am not a header";
|
||||
$scope.headerContent = "FoodLoop Admin Portal";
|
||||
|
||||
|
||||
/* This block of code handles recepit management */
|
||||
$scope.receiptNumber = 0;
|
||||
|
||||
|
||||
/* This block of code handles user management */
|
||||
/* Including the management of registered user, trader */
|
||||
$scope.registeredUsers = 1;
|
||||
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
<nav class="navbar navbar-toggleable-md fixed-top navbar-inverse" style="background-color:#0091EA;">
|
||||
<button class="navbar-toggler navbar-toggler-right hidden-lg-up" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">FoodLoop</a>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" ui-sref="user">Home <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" ui-sref=".settings">Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href=".help">Help</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="form-inline mt-2 mt-md-0">
|
||||
<input class="form-control mr-sm-2" type="text" placeholder="Search">
|
||||
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
|
@ -1,28 +0,0 @@
|
|||
<main class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 pt-3">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Position</th>
|
||||
<th>Name</th>
|
||||
<th>Pear points</th>
|
||||
<th>Retailers spent with</th>
|
||||
<th>Receipt submitted</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="user in leaderboard">
|
||||
<td>{{$index + 1}}</td>
|
||||
<td>{{user.name}}</td>
|
||||
<td>{{user.pear_points}}</td>
|
||||
<td>{{user.retailer_spent}}</td>
|
||||
<td>{{user.receipt_submitted}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- col -->
|
||||
</div>
|
||||
<!-- row first -->
|
||||
</main>
|
|
@ -1,21 +0,0 @@
|
|||
<main class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 pt-3">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="pearCard pearAutoHeight">
|
||||
<div class="pearCardHeader"> Personal details </div>
|
||||
<div class="pearCardContent">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-2">
|
||||
<label>Username</label>
|
||||
</div>
|
||||
<div class="col">
|
||||
<input type="text" placeholder="{{username}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- col -->
|
||||
</div>
|
||||
<!-- row first -->
|
||||
</main>
|
|
@ -1,90 +0,0 @@
|
|||
<main class="col-sm-9 offset-sm-3 col-md-10 offset-md-2 pt-3">
|
||||
<!--display my ranking -->
|
||||
<div class="row">
|
||||
|
||||
<div class="col-3">
|
||||
<div class="flCard">
|
||||
<div class="flCardHeader">
|
||||
<div class="title">Rank</div>
|
||||
</div>
|
||||
<div class="flCardMain"> 1 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-3">
|
||||
<div class="flCard">
|
||||
<div class="flCardHeader">Points</div>
|
||||
<div class="flCardMain"> 888 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-3">
|
||||
<div class="flCard">
|
||||
<div class="flCardHeader">Spend</div>
|
||||
<div class="flCardMain"> £100 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-3">
|
||||
<div class="flCard">
|
||||
<div class="flCardHeader">Re-spend</div>
|
||||
<div class="flCardMain"> £5.00 </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- first row end -->
|
||||
|
||||
<div class="row">
|
||||
|
||||
|
||||
<div class="col-3">
|
||||
<div class="pearCard margin16">
|
||||
<div class="pearCardHeader"> My receipt </div>
|
||||
<div class="receiptItem">
|
||||
Pending receipt <span class="badge badge-danger">5</span>
|
||||
</div>
|
||||
<div class="receiptItem">
|
||||
Submit a receipt
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-5">
|
||||
<div class="pearCard margin16">
|
||||
<div class="pearCardHeader"> Personal overview </div>
|
||||
<flChart> </flChart>
|
||||
<canvas id="myChart"></canvas>
|
||||
</div>
|
||||
<!-- flCard-->
|
||||
</div>
|
||||
<!-- col-5 receipt-->
|
||||
|
||||
<div class="col">
|
||||
<div class="pearCard margin16">
|
||||
<div class="pearCardHeader"> Top players of the month </div>
|
||||
<div class="rankCardContent">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Username</th>
|
||||
<th>Points</th>
|
||||
<th>Receipts submitted</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- col for pending receipt -->
|
||||
</div>
|
||||
<!-- row -->
|
||||
<!--<button ng-click="displayChart()"> Hit me </button>-->
|
||||
</main>
|
|
@ -1,30 +0,0 @@
|
|||
<!-- This page defines a side bar for admin -->
|
||||
<nav class="col-sm-3 col-md-2 hidden-xs-down bg-faded sidebar">
|
||||
|
||||
<!--<div class="row no-gutters">
|
||||
<div class="col-5">
|
||||
<div class="profilePic">
|
||||
<img src="../../pages/user/icon1.png" class="profile-pic">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<div class="profileInfo">
|
||||
<h6>{{username}}</h6>
|
||||
<div class="profileTitle">{{email}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<ul class="nav nav-pills flex-column" id="meq">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#">Key features</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" ui-sref=".receipt">Submit a receipt</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" ui-sref=".leaderboard">View Leaderboard</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</nav>
|
|
@ -1,3 +0,0 @@
|
|||
<user-header> </user-header>
|
||||
<user-sidebar> </user-sidebar>
|
||||
<user-main> </user-main>
|
|
@ -1,65 +0,0 @@
|
|||
app.controller('userCtrl', function($scope,$location) {
|
||||
$scope.user_rank = 1;
|
||||
$scope.controllby = "user";
|
||||
$scope.username = "John Smith";
|
||||
$scope.email = "test007@test.com";
|
||||
$scope.createChart = function(){
|
||||
var ctx = document.getElementById("myChart");
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||
datasets: [{
|
||||
label: '# of Votes',
|
||||
data: [12, 19, 3, 5, 2, 3],
|
||||
backgroundColor: [
|
||||
'rgba(255, 99, 132, 0.2)',
|
||||
'rgba(54, 162, 235, 0.2)',
|
||||
'rgba(255, 206, 86, 0.2)',
|
||||
'rgba(75, 192, 192, 0.2)',
|
||||
'rgba(153, 102, 255, 0.2)',
|
||||
'rgba(255, 159, 64, 0.2)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(255,99,132,1)',
|
||||
'rgba(54, 162, 235, 1)',
|
||||
'rgba(255, 206, 86, 1)',
|
||||
'rgba(75, 192, 192, 1)',
|
||||
'rgba(153, 102, 255, 1)',
|
||||
'rgba(255, 159, 64, 1)'
|
||||
],
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero:true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$scope.displayChart = function(){
|
||||
// chart sample
|
||||
var flData = [{x: 100, y: 100}, {x: 200, y: 200}, {x: 300, y: 300}];
|
||||
var svg = d3.select("flChart").append("svg")
|
||||
.attr("width","300px").attr("height","300px");
|
||||
svg
|
||||
.selectAll("circle").data(flData)
|
||||
.enter().append("circle")
|
||||
.attr("cx", function(d) { return d.x; })
|
||||
.attr("cy", function(d) { return d.y; })
|
||||
.attr("r", 2.5);
|
||||
|
||||
console.log(svg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
30
protractor.conf.js
Normal file
30
protractor.conf.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./e2e/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
'browserName': 'chrome'
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:4200/',
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
showColors: true,
|
||||
defaultTimeoutInterval: 30000,
|
||||
print: function() {}
|
||||
},
|
||||
beforeLaunch: function() {
|
||||
require('ts-node').register({
|
||||
project: 'e2e/tsconfig.e2e.json'
|
||||
});
|
||||
},
|
||||
onPrepare() {
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
/* this service handles all the authentication between client and server */
|
||||
app.service('authService', function ($http) {
|
||||
// send a login information to server
|
||||
// upon success, set sessionToken and store data in dataService
|
||||
// upon failed, return error
|
||||
this.username = "";
|
||||
this.getUsername = function(){
|
||||
return this.username;
|
||||
}
|
||||
|
||||
this.setUsername = function(setTo){
|
||||
this.username = setTo;
|
||||
}
|
||||
});
|
|
@ -1,56 +0,0 @@
|
|||
/* this service handles all the authentication between client and server */
|
||||
app.service('chartService', function () {
|
||||
// send a login information to server
|
||||
// upon success, set sessionToken and store data in dataService
|
||||
// upon failed, return error
|
||||
this.username = "";
|
||||
this.getUsername = function(){
|
||||
return this.username;
|
||||
}
|
||||
|
||||
this.setUsername = function(setTo){
|
||||
this.username = setTo;
|
||||
}
|
||||
|
||||
|
||||
this.createChart = function(){
|
||||
var ctx = document.getElementById("myChart");
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||
datasets: [{
|
||||
label: '# of Votes',
|
||||
data: [12, 19, 3, 5, 2, 3],
|
||||
backgroundColor: [
|
||||
'rgba(255, 99, 132, 0.2)',
|
||||
'rgba(54, 162, 235, 0.2)',
|
||||
'rgba(255, 206, 86, 0.2)',
|
||||
'rgba(75, 192, 192, 0.2)',
|
||||
'rgba(153, 102, 255, 0.2)',
|
||||
'rgba(255, 159, 64, 0.2)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(255,99,132,1)',
|
||||
'rgba(54, 162, 235, 1)',
|
||||
'rgba(255, 206, 86, 1)',
|
||||
'rgba(75, 192, 192, 1)',
|
||||
'rgba(153, 102, 255, 1)',
|
||||
'rgba(255, 159, 64, 1)'
|
||||
],
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero:true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1,6 +0,0 @@
|
|||
/* this service handles receipt upload process */
|
||||
app.service('uploadReceiptService', function () {
|
||||
this.uploadReceipt = function(){
|
||||
console.log("Upload successful");
|
||||
}
|
||||
});
|
21
src/app/_guards/auth.guard.ts
Normal file
21
src/app/_guards/auth.guard.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard implements CanActivate {
|
||||
|
||||
constructor(private router: Router) { }
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
if (localStorage.getItem('sessionKey')) {
|
||||
console.log('session key found')
|
||||
// logged in so return true
|
||||
return true;
|
||||
}
|
||||
|
||||
// not logged in so redirect to login page with the return url
|
||||
console.log('no session key found')
|
||||
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
|
||||
return false;
|
||||
}
|
||||
}
|
22
src/app/_guards/customer.guard.ts
Normal file
22
src/app/_guards/customer.guard.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class CustomerGuard implements CanActivate {
|
||||
|
||||
constructor(private router: Router) { }
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
if (localStorage.getItem('usertype') === 'customer') {
|
||||
console.log('Customer logged in');
|
||||
// customer logged in so return true
|
||||
return true;
|
||||
} else if (localStorage.getItem('usertype') === 'organisation') {
|
||||
console.log('not an customer');
|
||||
this.router.navigate(['/dashboard']);
|
||||
return false;
|
||||
}
|
||||
this.router.navigate(['/login']);
|
||||
return false;
|
||||
}
|
||||
}
|
22
src/app/_guards/org.guard.ts
Normal file
22
src/app/_guards/org.guard.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class OrgGuard implements CanActivate {
|
||||
|
||||
constructor(private router: Router) { }
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
if (localStorage.getItem('usertype') === 'organisation') {
|
||||
console.log('Organisation logged in');
|
||||
// org logged in so return true
|
||||
return true;
|
||||
} else if (localStorage.getItem('usertype') === 'customer') {
|
||||
console.log('not an organisation');
|
||||
this.router.navigate(['/dashboard-customer']);
|
||||
return false;
|
||||
}
|
||||
this.router.navigate(['/login']);
|
||||
return false;
|
||||
}
|
||||
}
|
4
src/app/_interfaces/chart-data.ts
Normal file
4
src/app/_interfaces/chart-data.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
export interface ChartData {
|
||||
data: Array<number>;
|
||||
label: string;
|
||||
}
|
44
src/app/app.component.spec.ts
Normal file
44
src/app/app.component.spec.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { TestBed, ComponentFixture, async } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
// Items under test
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
let fixture: ComponentFixture<AppComponent>;
|
||||
let app: AppComponent;
|
||||
let de: DebugElement;
|
||||
let appDocument: any;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
RouterTestingModule.withRoutes(
|
||||
[{path: '', component: AppComponent}]
|
||||
)
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
app = fixture.componentInstance;
|
||||
de = fixture.debugElement;
|
||||
appDocument = de.nativeElement;
|
||||
});
|
||||
|
||||
it('should create the app', async(() => {
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should have a router-outlet', async(() => {
|
||||
expect(appDocument.querySelector('router-outlet')).toBeTruthy();
|
||||
}));
|
||||
});
|
7
src/app/app.component.ts
Normal file
7
src/app/app.component.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: '<router-outlet></router-outlet>'
|
||||
})
|
||||
export class AppComponent { }
|
75
src/app/app.module.ts
Normal file
75
src/app/app.module.ts
Normal file
|
@ -0,0 +1,75 @@
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||
import { TabsModule } from 'ngx-bootstrap/tabs';
|
||||
import { NgxPaginationModule } from 'ngx-pagination';
|
||||
import { NAV_DROPDOWN_DIRECTIVES } from './shared/nav-dropdown.directive';
|
||||
|
||||
import { SIDEBAR_TOGGLE_DIRECTIVES } from './shared/sidebar.directive';
|
||||
import { AsideToggleDirective } from './shared/aside.directive';
|
||||
import { BreadcrumbsComponent } from './shared/breadcrumb.component';
|
||||
|
||||
// Routing & Guard Module
|
||||
import { AppRoutingModule } from './app.routing';
|
||||
import { AuthGuard } from './_guards/auth.guard';
|
||||
import { OrgGuard } from './_guards/org.guard';
|
||||
import { CustomerGuard } from './_guards/customer.guard';
|
||||
import { ApiService } from './providers/api-service';
|
||||
|
||||
import { OrgGraphsService } from './providers/org-graphs.service';
|
||||
import { OrgSnippetsService } from './providers/org-snippets.service';
|
||||
|
||||
// Layouts
|
||||
import { FullLayoutComponent } from './layouts/full-layout.component';
|
||||
import { SimpleLayoutComponent } from './layouts/simple-layout.component';
|
||||
|
||||
// Error Pages
|
||||
import { P404Component } from './pages/404.component';
|
||||
import { P500Component } from './pages/500.component';
|
||||
|
||||
// Submodules
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { DashboardModule } from './dashboard/dashboard.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
HttpModule,
|
||||
NgxPaginationModule,
|
||||
BsDropdownModule.forRoot(),
|
||||
TabsModule.forRoot(),
|
||||
AuthModule,
|
||||
DashboardModule,
|
||||
// Loaded last to allow for 404 catchall
|
||||
AppRoutingModule,
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
FullLayoutComponent,
|
||||
SimpleLayoutComponent,
|
||||
NAV_DROPDOWN_DIRECTIVES,
|
||||
BreadcrumbsComponent,
|
||||
SIDEBAR_TOGGLE_DIRECTIVES,
|
||||
AsideToggleDirective,
|
||||
P404Component,
|
||||
P500Component,
|
||||
],
|
||||
providers: [
|
||||
AuthGuard,
|
||||
OrgGuard,
|
||||
CustomerGuard,
|
||||
ApiService,
|
||||
OrgGraphsService,
|
||||
OrgSnippetsService,
|
||||
{
|
||||
provide: LocationStrategy,
|
||||
useClass: HashLocationStrategy
|
||||
}
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
17
src/app/app.routing.ts
Normal file
17
src/app/app.routing.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { P404Component } from './pages/404.component';
|
||||
import { P500Component } from './pages/500.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: '404', component: P404Component },
|
||||
{ path: '500', component: P500Component },
|
||||
{ path: '**', redirectTo: '/404' },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forRoot(routes) ],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class AppRoutingModule {}
|
21
src/app/auth/auth.module.ts
Normal file
21
src/app/auth/auth.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { LoginComponent } from './login.component';
|
||||
import { RegisterComponent } from './register.component';
|
||||
import { AuthRoutingModule } from './auth.routing';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
AuthRoutingModule,
|
||||
],
|
||||
declarations: [
|
||||
LoginComponent,
|
||||
RegisterComponent,
|
||||
]
|
||||
})
|
||||
export class AuthModule {}
|
15
src/app/auth/auth.routing.ts
Normal file
15
src/app/auth/auth.routing.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { LoginComponent } from './login.component';
|
||||
import { RegisterComponent } from './register.component';
|
||||
|
||||
const authRoutes: Routes = [
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: 'register', component: RegisterComponent },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(authRoutes) ],
|
||||
exports: [ RouterModule ],
|
||||
})
|
||||
export class AuthRoutingModule {}
|
53
src/app/auth/login.component.html
Normal file
53
src/app/auth/login.component.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<div class="app flex-row align-items-center">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card-group mb-0">
|
||||
<div class="card p-4">
|
||||
<div class="card-block">
|
||||
<h1>Login</h1>
|
||||
<p class="text-muted">Sign In to your account</p>
|
||||
<form [formGroup]="signin" (ngSubmit)="onSubmit()">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon">@</span>
|
||||
<input id="username" type="text" class="form-control" formControlName="email" placeholder="Email">
|
||||
</div>
|
||||
<div class="input-group mb-4">
|
||||
<span class="input-group-addon"><i class="icon-lock"></i></span>
|
||||
<input id="password" type="password" class="form-control" formControlName="password" placeholder="Password">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div [ngSwitch]="loginStatus">
|
||||
<div *ngSwitchCase="'success'" class="alert alert-success" role="alert">
|
||||
Login Succeeded, routing to homepage.
|
||||
</div>
|
||||
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
|
||||
Error received, please try again.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<button type="submit" [disabled]="!signin.valid" class="btn btn-primary px-4">Login</button>
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
<button type="button" class="btn btn-link px-0">Forgot password?</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card card-inverse card-primary py-5 d-md-down-none" style="width:44%">
|
||||
<div class="card-block text-center">
|
||||
<div>
|
||||
<h2>Sign up</h2>
|
||||
<p>Click the "Register Now" button to register your user account. Be sure to have a token!</p>
|
||||
<button type="button" class="btn btn-primary active mt-3" routerLinkActive="active" [routerLink]="['/register']">Register Now!</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
63
src/app/auth/login.component.ts
Normal file
63
src/app/auth/login.component.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'login.component.html',
|
||||
})
|
||||
export class LoginComponent implements OnInit {
|
||||
signin: FormGroup;
|
||||
returnUrl: string;
|
||||
loginStatus: any;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private api: ApiService
|
||||
) {
|
||||
this.signin = this.formBuilder.group({
|
||||
email: ['', [Validators.required]],
|
||||
password: ['', [Validators.required]],
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
// reset login status
|
||||
this.api
|
||||
.logout()
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('Logged out!');
|
||||
localStorage.clear();
|
||||
}
|
||||
);
|
||||
|
||||
// get return url from route parameters or default to '/'
|
||||
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
console.log(this.signin.value);
|
||||
|
||||
this.api
|
||||
.login(this.signin.value)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('logged in!');
|
||||
this.loginStatus = 'success';
|
||||
console.log(this.loginStatus);
|
||||
this.router.navigate([this.returnUrl]);
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.loginStatus = 'send_failed';
|
||||
console.log(this.loginStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
148
src/app/auth/register.component.html
Normal file
148
src/app/auth/register.component.html
Normal file
|
@ -0,0 +1,148 @@
|
|||
<div class="app flex-row align-items-center">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card mx-4">
|
||||
<div class="card-block p-4">
|
||||
<h1>Register</h1>
|
||||
<p class="text-muted">Create your account</p>
|
||||
|
||||
<!-- <div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-people"></i></span>
|
||||
<select required class="form-control" type="text" formControlName="usertype">
|
||||
<option value=''>Please select</option>
|
||||
<option value='organisation'>Organisation</option>
|
||||
<option value='customer'>Customer</option>
|
||||
</select>
|
||||
</div> -->
|
||||
<form [formGroup]="signupForm.getForm()">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-key"></i></span>
|
||||
<input type="text" class="form-control" formControlName="token" placeholder="Token">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon">@</span>
|
||||
<input type="text" class="form-control" formControlName="email" placeholder="Email">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-lock"></i></span>
|
||||
<input type="password" class="form-control" formControlName="password" placeholder="Password">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-4">
|
||||
<span class="input-group-addon"><i class="icon-lock"></i></span>
|
||||
<input type="password" class="form-control" formControlName="confirmpassword" placeholder="Repeat password">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-people"></i></span>
|
||||
<select required class="form-control" type="text" formControlName="usertype">
|
||||
<option value=''>Please select</option>
|
||||
<option value='organisation'>Organisation</option>
|
||||
<option value='customer'>Customer</option>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div [ngSwitch]="signupForm.getForm().value.usertype">
|
||||
<div *ngSwitchCase="'customer'" >
|
||||
<form [formGroup]="customerForm.getForm()" (ngSubmit)="onSubmitCustomer()">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-user"></i></span>
|
||||
<input type="text" class="form-control" formControlName="display_name" placeholder="Display Name">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-user"></i></span>
|
||||
<input type="text" class="form-control" formControlName="full_name" placeholder="Full Name">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-user"></i></span>
|
||||
<input type="text" class="form-control" formControlName="postcode" placeholder="Postcode">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon">Year of Birth</span>
|
||||
<select class="form-control" type="text" formControlName="year_of_birth">
|
||||
<option *ngFor="let range of years" [value]="range">{{ range }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-block btn-success">Create Account</button>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngSwitchCase="'organisation'">
|
||||
<form [formGroup]="organisationForm.getForm()" (ngSubmit)="onSubmitOrganisation()">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-user"></i></span>
|
||||
<input type="text" class="form-control" formControlName="name" placeholder="Organisation Name">
|
||||
</div>
|
||||
|
||||
<!-- Uses the UK SIC 2007 classifications for sector as used by ONS -->
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<select required class="form-control" type="text" formControlName="sector">
|
||||
<option value=''>Select Organisation Sector</option>
|
||||
<option value='A'>Agriculture, Forestry & Fishing</option>
|
||||
<option value='B'>Mining & Quarrying</option>
|
||||
<option value='C'>Manufacturing</option>
|
||||
<option value='D'>Electricity, Gas, Steam & Air Conditioning</option>
|
||||
<option value='E'>Water & Waste Management</option>
|
||||
<option value='F'>Construction</option>
|
||||
<option value='G'>Wholesale & Retail Trade</option>
|
||||
<option value='H'>Transportation & Storage</option>
|
||||
<option value='I'>Accomodation & Food Services</option>
|
||||
<option value='J'>Information & Communication</option>
|
||||
<option value='K'>Financial & Insurance Activities</option>
|
||||
<option value='L'>Real Estate</option>
|
||||
<option value='M'>Professional, Scientfic & Technical</option>
|
||||
<option value='N'>Administrative & Support Services</option>
|
||||
<option value='O'>Public Administration, Defence & Social Security</option>
|
||||
<option value='P'>Education</option>
|
||||
<option value='Q'>Human Health & Social Work</option>
|
||||
<option value='R'>Arts, Entertainment & Recreation</option>
|
||||
<option value='S'>Other Service Activities</option>
|
||||
<option value='T'>Household Domestic Business</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-user"></i></span>
|
||||
<input type="text" class="form-control" formControlName="street_name" placeholder="Street Name">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-user"></i></span>
|
||||
<input type="text" class="form-control" formControlName="town" placeholder="Town">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-addon"><i class="icon-user"></i></span>
|
||||
<input type="text" class="form-control" formControlName="postcode" placeholder="Postcode">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-block btn-success">Create Account</button>
|
||||
</form>
|
||||
</div>
|
||||
<div heading="Pending" *ngSwitchDefault>Please Select a User Type</div>
|
||||
</div>
|
||||
<div class="mb-3" [ngSwitch]="registerStatus">
|
||||
<div *ngSwitchCase="'success'" class="alert alert-success" role="alert">
|
||||
Register Succeeded.
|
||||
</div>
|
||||
<div *ngSwitchCase="'validation_failed'" class="alert alert-danger" role="alert">
|
||||
Form validation failed, please ensure the form is filled correctly.
|
||||
</div>
|
||||
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
|
||||
Failed to send to server, please try again later.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
136
src/app/auth/register.component.ts
Normal file
136
src/app/auth/register.component.ts
Normal file
|
@ -0,0 +1,136 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { ValidationManager } from "ng2-validation-manager";
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import {Router } from '@angular/router';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'register.component.html',
|
||||
})
|
||||
|
||||
export class RegisterComponent {
|
||||
signupForm: ValidationManager;
|
||||
customerForm: ValidationManager;
|
||||
organisationForm: ValidationManager;
|
||||
years: Object[];
|
||||
registerStatus: any;
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.years = [];
|
||||
let max = new Date().getFullYear() - 10,
|
||||
min = max - 140;
|
||||
|
||||
for (let i = max; i>=min; i--){
|
||||
this.years.push(i);
|
||||
}
|
||||
this.signupForm = new ValidationManager({
|
||||
token: 'required',
|
||||
usertype: 'required',
|
||||
email: 'required|email',
|
||||
password: 'required',
|
||||
confirmpassword: 'required|equalTo:password'
|
||||
});
|
||||
this.customerForm = new ValidationManager({
|
||||
display_name: 'required',
|
||||
full_name: 'required',
|
||||
postcode: 'required',
|
||||
year_of_birth:'required',
|
||||
});
|
||||
this.organisationForm = new ValidationManager({
|
||||
name: 'required',
|
||||
sector: 'required',
|
||||
street_name: 'required',
|
||||
town: 'required',
|
||||
postcode: 'required',
|
||||
});
|
||||
}
|
||||
|
||||
onSubmitCustomer() {
|
||||
|
||||
console.log(this.signupForm.isValid());
|
||||
if (!this.signupForm.isValid() && !this.customerForm.isValid()) {
|
||||
console.log("Not Valid!");
|
||||
this.registerStatus = "validation_failed";
|
||||
console.log(this.registerStatus);
|
||||
return;
|
||||
}
|
||||
let signupForm = this.signupForm.getForm().value;
|
||||
let customerForm = this.customerForm.getForm().value;
|
||||
|
||||
let data = {
|
||||
token: signupForm.token,
|
||||
usertype: signupForm.usertype,
|
||||
email: signupForm.email,
|
||||
password: signupForm.password,
|
||||
display_name: customerForm.display_name,
|
||||
full_name: customerForm.full_name,
|
||||
postcode: customerForm.postcode,
|
||||
year_of_birth:customerForm.year_of_birth,
|
||||
};
|
||||
console.log(data);
|
||||
this.api
|
||||
.register(data)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('registered!');
|
||||
this.registerStatus = "success";
|
||||
console.log(this.registerStatus);
|
||||
this.router.navigate(['/dashboard']);
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.registerStatus = "send_failed";
|
||||
console.log(this.registerStatus)
|
||||
}
|
||||
);
|
||||
}
|
||||
onSubmitOrganisation() {
|
||||
|
||||
console.log(this.signupForm.isValid());
|
||||
if (!this.signupForm.isValid() || !this.organisationForm.isValid()) {
|
||||
console.log("Not Valid!");
|
||||
this.registerStatus = "validation_failed";
|
||||
console.log(this.registerStatus);
|
||||
return;
|
||||
}
|
||||
let signupForm = this.signupForm.getForm().value;
|
||||
let organisationForm = this.organisationForm.getForm().value;
|
||||
|
||||
let data = {
|
||||
token: signupForm.token,
|
||||
usertype: signupForm.usertype,
|
||||
email: signupForm.email,
|
||||
password: signupForm.password,
|
||||
name: organisationForm.name,
|
||||
sector: organisationForm.sector,
|
||||
street_name: organisationForm.street_name,
|
||||
town: organisationForm.town,
|
||||
postcode: organisationForm.postcode,
|
||||
};
|
||||
console.log(data);
|
||||
this.api
|
||||
.register(data)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('registered!');
|
||||
this.registerStatus = "success";
|
||||
console.log(this.registerStatus);
|
||||
this.router.navigate(['/dashboard']);
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.registerStatus = "send_failed";
|
||||
console.log(this.registerStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
176
src/app/dashboard/account-edit.component.html
Normal file
176
src/app/dashboard/account-edit.component.html
Normal file
|
@ -0,0 +1,176 @@
|
|||
<div class="animated fadeIn">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<strong>Update Account Info</strong>
|
||||
<small>Required Data marked in <strong>bold</strong>.</small>
|
||||
</div>
|
||||
<form class="form-horizontal" [formGroup]="settingForm">
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Confirm Current Password</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="password" class="form-control" formControlName="password">
|
||||
<span class="help-block">Required for security purposes.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Email</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="email">
|
||||
<span class="help-block">Change this to alter your current account email.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input">Enter New Password</label>
|
||||
<div class="col-md-9">
|
||||
<input type="password" class="form-control" formControlName="new_password">
|
||||
<span class="help-block">Enter a new password here if you wish to alter your current one.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Postcode</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="postcode">
|
||||
<span class="help-block">Change this if your location of residence has changed.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="file-input">Profile Picture</label>
|
||||
<div class="col-md-9">
|
||||
<input type="file" #fileInput formControlName="profile_picture">
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</form>
|
||||
<div [ngSwitch]="accountType">
|
||||
<div *ngSwitchCase="'organisation'">
|
||||
<form class="form-horizontal" [formGroup]="settingOrganisationForm" (ngSubmit)="onSubmitOrganisation()">
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Business Name</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="name">
|
||||
<span class="help-block">Change this if your business name has changed.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Street Name</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="street_name">
|
||||
<span class="help-block">Change this if your located street has changed.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Industry Sector</strong></label>
|
||||
<div class="col-md-9">
|
||||
<select required class="form-control" type="text" formControlName="sector">
|
||||
<option value=''>Select Organisation Sector</option>
|
||||
<option value='A'>Agriculture, Forestry & Fishing</option>
|
||||
<option value='B'>Mining & Quarrying</option>
|
||||
<option value='C'>Manufacturing</option>
|
||||
<option value='D'>Electricity, Gas, Steam & Air Conditioning</option>
|
||||
<option value='E'>Water & Waste Management</option>
|
||||
<option value='F'>Construction</option>
|
||||
<option value='G'>Wholesale & Retail Trade</option>
|
||||
<option value='H'>Transportation & Storage</option>
|
||||
<option value='I'>Accomodation & Food Services</option>
|
||||
<option value='J'>Information & Communication</option>
|
||||
<option value='K'>Financial & Insurance Activities</option>
|
||||
<option value='L'>Real Estate</option>
|
||||
<option value='M'>Professional, Scientfic & Technical</option>
|
||||
<option value='N'>Administrative & Support Services</option>
|
||||
<option value='O'>Public Administration, Defence & Social Security</option>
|
||||
<option value='P'>Education</option>
|
||||
<option value='Q'>Human Health & Social Work</option>
|
||||
<option value='R'>Arts, Entertainment & Recreation</option>
|
||||
<option value='S'>Other Service Activities</option>
|
||||
<option value='T'>Household Domestic Business</option>
|
||||
</select>
|
||||
<span class="help-block">Alter this if your business sector has changed.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>City/Town Location</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="town">
|
||||
<span class="help-block">Change this if the city or town your business is located at has changed.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div [ngSwitch]="submitStatus">
|
||||
<div *ngSwitchCase="'success'" class="alert alert-success" role="alert">
|
||||
Account Update Succeeded.
|
||||
</div>
|
||||
<div *ngSwitchCase="'validation_failed'" class="alert alert-danger" role="alert">
|
||||
Form validation failed, please ensure the form is filled correctly.
|
||||
</div>
|
||||
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
|
||||
Failed to send to server, please try again later.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngSwitchCase="'customer'">
|
||||
<form class="form-horizontal" [formGroup]="settingCustomerForm" (ngSubmit)="onSubmitCustomer()">
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Full Name</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="full_name">
|
||||
<span class="help-block">Change this if your full name has changed.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Display Name</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="display_name">
|
||||
<span class="help-block">Change this if wish to alter your user display name.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div [ngSwitch]="submitStatus">
|
||||
<div *ngSwitchCase="'success'" class="alert alert-success" role="alert">
|
||||
Account Update Succeeded.
|
||||
</div>
|
||||
<div *ngSwitchCase="'validation_failed'" class="alert alert-danger" role="alert">
|
||||
Form validation failed, please ensure the form is filled correctly.
|
||||
</div>
|
||||
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
|
||||
Failed to send to server, please try again later.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.row-->
|
||||
</div>
|
169
src/app/dashboard/account-edit.component.ts
Normal file
169
src/app/dashboard/account-edit.component.ts
Normal file
|
@ -0,0 +1,169 @@
|
|||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'account-edit.component.html',
|
||||
})
|
||||
export class AccountEditComponent implements OnInit {
|
||||
settingForm: FormGroup;
|
||||
settingOrganisationForm: FormGroup;
|
||||
settingCustomerForm: FormGroup;
|
||||
accountType: any;
|
||||
// @ViewChild('fileInput') fileInput;
|
||||
submitStatus: any;
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.settingForm = this.formBuilder.group({
|
||||
email : ['', [Validators.required]],
|
||||
postcode : ['', [Validators.required]],
|
||||
password : ['', [Validators.required]],
|
||||
new_password : [''],
|
||||
});
|
||||
this.settingOrganisationForm = this.formBuilder.group({
|
||||
name : ['', [Validators.required]],
|
||||
street_name : ['', [Validators.required]],
|
||||
town : ['', [Validators.required]],
|
||||
sector : ['', [Validators.required]],
|
||||
});
|
||||
this.settingCustomerForm = this.formBuilder.group({
|
||||
full_name : ['', [Validators.required]],
|
||||
display_name : ['', [Validators.required]],
|
||||
});
|
||||
this.accountType = localStorage.getItem('usertype');
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.api.accountFullLoad().subscribe(
|
||||
result => {
|
||||
console.log(result);
|
||||
this.settingForm.patchValue({
|
||||
email: result.email,
|
||||
postcode: result.postcode,
|
||||
password: '',
|
||||
new_password: '',
|
||||
});
|
||||
this.settingOrganisationForm.patchValue({
|
||||
name: result.name,
|
||||
street_name: result.street_name,
|
||||
town: result.town,
|
||||
sector: result.sector,
|
||||
});
|
||||
this.settingCustomerForm.patchValue({
|
||||
full_name: result.full_name,
|
||||
display_name: result.display_name,
|
||||
});
|
||||
this.api.setUserInfo( result.email, result.display_name || result.name );
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onSubmitOrganisation() {
|
||||
console.log(this.settingForm.valid);
|
||||
if (!this.settingForm.valid && !this.settingOrganisationForm.valid) {
|
||||
console.log('Not Valid!');
|
||||
this.submitStatus = "validation_failed";
|
||||
console.log(this.submitStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
const settingForm = this.settingForm.value;
|
||||
const settingOrganisationForm = this.settingOrganisationForm.value;
|
||||
|
||||
// image upload code
|
||||
// const fi = this.fileInput.nativeElement;
|
||||
// const data = new FormData();
|
||||
|
||||
// if (fi.files && fi.files[0]) {
|
||||
// const fileToUpload = fi.files[0];
|
||||
// data.append('file', fileToUpload);
|
||||
// }
|
||||
|
||||
const submitData = {
|
||||
email: settingForm.email,
|
||||
postcode: settingForm.postcode,
|
||||
password: settingForm.password,
|
||||
new_password: settingForm.new_password,
|
||||
name: settingOrganisationForm.name,
|
||||
street_name: settingOrganisationForm.street_name,
|
||||
town: settingOrganisationForm.town,
|
||||
sector: settingOrganisationForm.sector,
|
||||
};
|
||||
|
||||
// data.append('form', JSON.stringify(submitData));
|
||||
|
||||
console.log(submitData);
|
||||
this.api
|
||||
.accountEditUpdate(submitData)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('data submitted!');
|
||||
this.submitStatus = "success";
|
||||
console.log(this.submitStatus);
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.submitStatus = "send_failed";
|
||||
console.log(this.submitStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onSubmitCustomer() {
|
||||
console.log(this.settingForm.valid);
|
||||
if (!this.settingForm.valid && !this.settingCustomerForm.valid) {
|
||||
console.log('Not Valid!');
|
||||
this.submitStatus = "validation_failed";
|
||||
console.log(this.submitStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
const settingForm = this.settingForm.value;
|
||||
const settingCustomerForm = this.settingCustomerForm.value;
|
||||
|
||||
// image upload code
|
||||
// const fi = this.fileInput.nativeElement;
|
||||
const data = new FormData();
|
||||
|
||||
// if (fi.files && fi.files[0]) {
|
||||
// const fileToUpload = fi.files[0];
|
||||
// data.append('file', fileToUpload);
|
||||
// }
|
||||
|
||||
const submitData = {
|
||||
email: settingForm.email,
|
||||
postcode: settingForm.postcode,
|
||||
password: settingForm.password,
|
||||
new_password: settingForm.new_password,
|
||||
full_name: settingCustomerForm.full_name,
|
||||
display_name: settingCustomerForm.display_name,
|
||||
};
|
||||
|
||||
// data.append('form', JSON.stringify(submitData));
|
||||
|
||||
this.api
|
||||
.accountEditUpdate(submitData)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('data submitted!');
|
||||
this.submitStatus = "success";
|
||||
console.log(this.submitStatus);
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.submitStatus = "send_failed";
|
||||
console.log(this.submitStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
272
src/app/dashboard/add-data.component.html
Normal file
272
src/app/dashboard/add-data.component.html
Normal file
|
@ -0,0 +1,272 @@
|
|||
<div class="animated fadeIn">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<strong>Submit Transaction</strong>
|
||||
<small>Required Data marked in <strong>bold</strong>.</small>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Time of Transaction</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="datetime-local" class="form-control" [min]="minDate" [(ngModel)]="myDate" (ngModelChange)="transactionFormValidate()">
|
||||
<span class="help-block">Enter the date and time the transaction occurred.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Amount</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" placeholder="0.00" [(ngModel)]="amount" (ngModelChange)="transactionFormValidate()">
|
||||
</div>
|
||||
<span class="help-block">Enter the amount spent, such as 5.35 for £5.35.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Organisation Name</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" placeholder="Organisation Name" [(ngModel)]="submitOrg.name" (input)="organisationSearch($event)" (ngModelChange)="transactionFormValidate()">
|
||||
<span class="help-block">Enter the name of the organisation money was spent. Choose existing ones from below or if not found, enter the details below.</span>
|
||||
</div>
|
||||
</div>
|
||||
<org-table *ngIf="storeList != null" [orgList]="storeList" (onClick)="addStore($event)"></org-table>
|
||||
<div *ngIf="showAddStore">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Organisation Street Name</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" placeholder="Which Street?" [(ngModel)]="submitOrg.street_name" (ngModelChange)="transactionFormValidate()">
|
||||
<span class="help-block">Enter the street name where the organisation is located at.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Organisation Town</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" placeholder="Which Town?" [(ngModel)]="submitOrg.town" (ngModelChange)="transactionFormValidate()">
|
||||
<span class="help-block">Enter the name of the town where the organisation is located at.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Organisation Postcode</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" placeholder="Postcode if known" [(ngModel)]="submitOrg.postcode" (ngModelChange)="transactionFormValidate()">
|
||||
<span class="help-block">Enter the postcode where the organisation is located at.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-9">
|
||||
<div [ngSwitch]="transactionFormStatus">
|
||||
<div *ngSwitchCase="'success'" class="alert alert-success" role="alert">
|
||||
Submit Succeeded.
|
||||
</div>
|
||||
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
|
||||
{{transactionFormStatusError}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" (click)="postTransaction()" [disabled]="transactionFormInvalid" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="false" class="card">
|
||||
<div class="card-header">
|
||||
<strong>Profile & Payroll Data</strong>
|
||||
<small>Required Data marked in <strong>bold</strong>.</small>
|
||||
</div>
|
||||
<form class="form-horizontal" [formGroup]="payrollForm" (ngSubmit)="onSubmitPayroll()">
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Period of entry month</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="month" class="form-control" formControlName="entry_period">
|
||||
<span class="help-block">Enter the month and year for this information.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of Employees</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="number" class="form-control" formControlName="employee_amount" placeholder="0">
|
||||
<span class="help-block">Enter the amount of employees the organisation has for the entry month.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of local Employees</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="number" class="form-control" formControlName="local_employee_amount" placeholder="0">
|
||||
<span class="help-block">Enter the amount of employees that live locally to the organisation for the entry month.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Gross Payroll</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="gross_payroll" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Enter the Gross Payroll for the organisation for the entry month.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total Income Tax</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="payroll_income_tax" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Enter the organisation's total income tax for the entry month.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Employees Total NI</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="payroll_employee_ni" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Total of Employees National Insurance contributions for the entry month</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Employers Total NI</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="payroll_employer_ni" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Employers National Insurance contributions for the entry month</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total Pensions</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="payroll_total_pension" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Total spent on employee pensions by the organisation for the entry month</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total Other Benefits</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="payroll_other_benefit" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">A total of other payments such as refunded fuel etc. for the entry month</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-9">
|
||||
<div [ngSwitch]="payrollFormStatus">
|
||||
<div *ngSwitchCase="'success'" class="alert alert-success" role="alert">
|
||||
Submit Succeeded.
|
||||
</div>
|
||||
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
|
||||
Error received, please try again.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" [disabled]="!payrollForm.valid" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngIf="false" class="card">
|
||||
<div class="card-header">
|
||||
<strong>Individual Employee Data</strong>
|
||||
<small>Required Data marked in <strong>bold</strong>.</small>
|
||||
</div>
|
||||
<form class="form-horizontal" [formGroup]="employeeForm" (ngSubmit)="onSubmitEmployee()">
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Period of entry month</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="month" class="form-control" formControlName="entry_period">
|
||||
<span class="help-block">Enter the month and year for this information.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Employee number</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="number" class="form-control" formControlName="employee_no" placeholder="0">
|
||||
<span class="help-block">Used to identify employee anonymously</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Gross Wage</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="employee_gross_wage" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Enter the gross wage of the employee for the entry month.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total Income Tax</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="employee_income_tax" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Enter the total income tax of the employee for the entry month</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total Employee NI</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="employee_ni" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Individual Employees National Insurance Contributions for the entry month</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Employee's Pension</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="employee_pension" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">Individual Employees Pension contributions for the entry month</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total Employee Other Benefits</strong></label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-gbp"></i></span>
|
||||
<input type="number" min="0.00" step="0.01" class="form-control" formControlName="employee_other_benefit" placeholder="0.00">
|
||||
</div>
|
||||
<span class="help-block">A total of other payments such as refunded fuel etc. for the entry month</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-9">
|
||||
<div [ngSwitch]="employeeFormStatus">
|
||||
<div *ngSwitchCase="'success'" class="alert alert-success" role="alert">
|
||||
Submit Succeeded.
|
||||
</div>
|
||||
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
|
||||
Error received, please try again.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" [disabled]="!employeeForm.valid" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.row-->
|
||||
</div>
|
301
src/app/dashboard/add-data.component.ts
Normal file
301
src/app/dashboard/add-data.component.ts
Normal file
|
@ -0,0 +1,301 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { OrgTableComponent } from '../shared/org-table.component';
|
||||
import * as moment from 'moment';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'add-data.component.html',
|
||||
})
|
||||
export class AddDataComponent {
|
||||
payrollForm: FormGroup;
|
||||
singleSupplierForm: FormGroup;
|
||||
employeeForm: FormGroup;
|
||||
transactionForm: FormGroup;
|
||||
payrollFormStatus: any;
|
||||
singleSupplierFormStatus: any;
|
||||
employeeFormStatus: any;
|
||||
transactionFormStatus: any;
|
||||
transactionFormStatusError: string = 'Error received, please try again.';
|
||||
accountType: any;
|
||||
|
||||
submitOrg = {
|
||||
name: '',
|
||||
street_name: '',
|
||||
town: '',
|
||||
postcode: '',
|
||||
};
|
||||
organisationId: number;
|
||||
organisationTown: string;
|
||||
organisationPostcode: string;
|
||||
amount: number;
|
||||
transactionAdditionType = 1;
|
||||
storeList;
|
||||
showAddStore = false;
|
||||
submitReceipt = false;
|
||||
transactionFormInvalid = true;
|
||||
myDate: any;
|
||||
minDate: any;
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.payrollForm = this.formBuilder.group({
|
||||
entry_period: ['', [Validators.required]],
|
||||
employee_amount: ['', [Validators.required]],
|
||||
local_employee_amount: ['', [Validators.required]],
|
||||
gross_payroll: ['', [Validators.required]],
|
||||
payroll_income_tax: ['', [Validators.required]],
|
||||
payroll_employee_ni: ['', [Validators.required]],
|
||||
payroll_employer_ni: ['', [Validators.required]],
|
||||
payroll_total_pension: ['', [Validators.required]],
|
||||
payroll_other_benefit: ['', [Validators.required]],
|
||||
});
|
||||
this.employeeForm = this.formBuilder.group({
|
||||
entry_period: ['', [Validators.required]],
|
||||
employee_no: ['', [Validators.required]],
|
||||
employee_income_tax: ['', [Validators.required]],
|
||||
employee_gross_wage: ['', [Validators.required]],
|
||||
employee_ni: ['', [Validators.required]],
|
||||
employee_pension: ['', [Validators.required]],
|
||||
employee_other_benefit: ['', [Validators.required]],
|
||||
});
|
||||
this.myDate = moment().format('YYYY-MM-DD[T]HH:mm');
|
||||
// this.myDate = new Date().toISOString().slice(0, 16);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getMinDate();
|
||||
this.accountType = localStorage.getItem('usertype');
|
||||
}
|
||||
|
||||
getMinDate(){
|
||||
// gets the April 1st date of the current year
|
||||
let aprilDate = moment().month(3).date(1);
|
||||
let now = moment();
|
||||
// Checks if current time is before April 1st, if so returns true
|
||||
let beforeApril = now.isBefore(aprilDate);
|
||||
if ( beforeApril == true ) {
|
||||
this.minDate = aprilDate.subtract(2, 'years').format('YYYY-MM-DD');
|
||||
} else {
|
||||
this.minDate = aprilDate.subtract(1, 'years').format('YYYY-MM-DD');
|
||||
}
|
||||
}
|
||||
|
||||
initializeItems() {
|
||||
// Dont bother searching for an empty or undefined string
|
||||
if ( this.submitOrg.name == '' ) {
|
||||
return;
|
||||
}
|
||||
var searchData = {
|
||||
search_name: this.submitOrg.name,
|
||||
};
|
||||
|
||||
this.api.search(searchData).subscribe(
|
||||
data => {
|
||||
if(data.validated.length > 0) {
|
||||
this.storeList = data.validated;
|
||||
this.showAddStore = false;
|
||||
this.transactionAdditionType = 1;
|
||||
} else {
|
||||
this.storeList = data.unvalidated;
|
||||
this.showAddStore = false;
|
||||
this.transactionAdditionType = 2;
|
||||
}
|
||||
// handle the case when the storelist is empty
|
||||
if(this.storeList.length < 1 ) {
|
||||
this.storeList = null;
|
||||
this.showAddStore = true;
|
||||
this.transactionAdditionType = 3;
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// if user select a item from the list
|
||||
addStore(store){
|
||||
this.submitOrg = store;
|
||||
this.transactionFormValidate();
|
||||
this.organisationId = store.id;
|
||||
}
|
||||
|
||||
// search for store
|
||||
organisationSearch(ev) {
|
||||
// Reset items back to all of the items
|
||||
this.initializeItems();
|
||||
|
||||
// set val to the value of the searchbar
|
||||
let val = ev.target.value;
|
||||
|
||||
// Filter the store list so search seems quicker
|
||||
if (val && val.trim() != '' && this.storeList != null) {
|
||||
this.storeList = this.storeList.filter(
|
||||
(item) => {
|
||||
return ( item.name.toLowerCase().indexOf( val.toLowerCase() ) > -1 );
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// if nothing is found
|
||||
if(!this.storeList === null){
|
||||
// display add new store button
|
||||
this.showAddStore = true;
|
||||
}
|
||||
}
|
||||
|
||||
transactionFormValidate() {
|
||||
if( this.submitOrg.name.length == 0 &&
|
||||
this.amount == 0 ) {
|
||||
this.transactionFormInvalid = true;
|
||||
}else{
|
||||
this.transactionFormInvalid = false;
|
||||
}
|
||||
}
|
||||
|
||||
public postTransaction() {
|
||||
|
||||
var myParams: any;
|
||||
let purchaseTime: string;
|
||||
purchaseTime = moment(this.myDate, 'YYYY-MM-DD[T]HH:mm').local().format('YYYY-MM-DD[T]HH:mm:ss.SSSZ');
|
||||
switch(this.transactionAdditionType){
|
||||
case 1:
|
||||
myParams = {
|
||||
transaction_type : this.transactionAdditionType,
|
||||
transaction_value : this.amount,
|
||||
purchase_time : purchaseTime,
|
||||
organisation_id : this.organisationId,
|
||||
};
|
||||
break;
|
||||
case 2:
|
||||
myParams = {
|
||||
transaction_type : this.transactionAdditionType,
|
||||
transaction_value : this.amount,
|
||||
purchase_time : purchaseTime,
|
||||
organisation_id : this.organisationId,
|
||||
};
|
||||
break;
|
||||
case 3:
|
||||
myParams = {
|
||||
transaction_type : this.transactionAdditionType,
|
||||
transaction_value : this.amount,
|
||||
purchase_time : purchaseTime,
|
||||
organisation_name : this.submitOrg.name,
|
||||
street_name : this.submitOrg.street_name,
|
||||
town : this.submitOrg.town,
|
||||
postcode : this.submitOrg.postcode,
|
||||
};
|
||||
break;
|
||||
}
|
||||
/******************************/
|
||||
|
||||
this.api
|
||||
.upload(myParams)
|
||||
.subscribe(
|
||||
result => {
|
||||
if ( result.success == true ) {
|
||||
console.log('Successful Upload');
|
||||
console.log(result);
|
||||
this.transactionFormStatus = "success";
|
||||
console.log(this.transactionFormStatus);
|
||||
this.resetForm();
|
||||
} else {
|
||||
console.log('Upload Error');
|
||||
this.transactionFormStatusError = JSON.stringify(result.status) + 'Error, ' + JSON.stringify(result.message);
|
||||
this.transactionFormStatus = "send_failed";
|
||||
console.log(this.transactionFormStatus);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.log('Upload Error');
|
||||
console.log(error);
|
||||
try {
|
||||
console.log(error.error);
|
||||
let jsonError = error.json();
|
||||
console.log("boop");
|
||||
this.transactionFormStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message;
|
||||
} catch(e) {
|
||||
this.transactionFormStatusError = 'There was a server error, please try again later.';
|
||||
}
|
||||
this.transactionFormStatus = "send_failed";
|
||||
console.log(this.transactionFormStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private resetForm() {
|
||||
this.submitOrg = {
|
||||
name: '',
|
||||
street_name: '',
|
||||
town: '',
|
||||
postcode: '',
|
||||
};
|
||||
this.storeList = null;
|
||||
this.amount = null;
|
||||
this.transactionFormInvalid = true;
|
||||
}
|
||||
|
||||
onSubmitPayroll() {
|
||||
console.log(this.payrollForm.value);
|
||||
|
||||
this.api
|
||||
.orgPayroll(this.payrollForm.value)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('data submitted!');
|
||||
this.payrollFormStatus = "success";
|
||||
console.log(this.payrollFormStatus);
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.payrollFormStatus = "send_failed";
|
||||
console.log(this.payrollFormStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onSubmitSingleSupplier() {
|
||||
console.log(this.singleSupplierForm.value);
|
||||
|
||||
this.api
|
||||
.orgSupplier(this.singleSupplierForm.value)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('data submitted!');
|
||||
this.singleSupplierFormStatus = "success";
|
||||
console.log(this.singleSupplierFormStatus);
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.singleSupplierFormStatus = "send_failed";
|
||||
console.log(this.singleSupplierFormStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onSubmitEmployee() {
|
||||
console.log(this.employeeForm.value);
|
||||
|
||||
this.api
|
||||
.orgEmployee(this.employeeForm.value)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('data submitted!');
|
||||
this.employeeFormStatus = "success";
|
||||
console.log(this.employeeFormStatus);
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.employeeFormStatus = "send_failed";
|
||||
console.log(this.employeeFormStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
131
src/app/dashboard/dashboard-customer.component.html
Normal file
131
src/app/dashboard/dashboard-customer.component.html
Normal file
|
@ -0,0 +1,131 @@
|
|||
<div class="animated fadeIn">
|
||||
<div class="card">
|
||||
<div class="card-footer">
|
||||
<ul>
|
||||
<li>
|
||||
<div class="text-muted">My Points</div>
|
||||
<strong>{{ basicStats.user_sum / 10 | number:'1.0-0' }}</strong>
|
||||
</li>
|
||||
<li>
|
||||
<div class="text-muted">My Rank</div>
|
||||
<div *ngIf="basicStats.user_position == 0" class="statuscontent">
|
||||
<strong>Unranked</strong>
|
||||
</div>
|
||||
<div *ngIf="basicStats.user_position != 0" class="statuscontent">
|
||||
<strong>{{ basicStats.user_position }}</strong>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<ul>
|
||||
<li>
|
||||
<div class="text-muted">My Total Spend</div>
|
||||
<strong>{{ basicStats.user_sum | currency:'GBP':true:'1.2-2' }}</strong>
|
||||
</li>
|
||||
<li>
|
||||
<div class="text-muted">Value to Local Economy</div>
|
||||
<strong>{{ basicStats.user_sum * 2.3 | currency:'GBP':true:'1.2-2' }}</strong>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.today_sum | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div>Total Today</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="text-muted">Lorem ipsum dolor sit amet enim.</small> -->
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.today_sum / (basicStats.today_count ? basicStats.today_count : 1) | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div>Avg. Spend Today</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="text-muted">Lorem ipsum dolor sit amet enim.</small> -->
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.week_sum | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div>Last Week Total</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="text-muted">Lorem ipsum dolor sit amet enim.</small> -->
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.week_sum / (basicStats.week_count ? basicStats.week_count : 1) | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div>Last Week Avg. Spend</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="text-muted">Lorem ipsum dolor sit amet enim.</small> -->
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.month_sum | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div>Last Month Total</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="text-muted">Lorem ipsum dolor sit amet enim.</small> -->
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.month_sum / (basicStats.month_count ? basicStats.month_count : 1) | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div>Last Month Avg. Spend</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="text-muted">Lorem ipsum dolor sit amet enim.</small> -->
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.user_sum | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div>User Total</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="text-muted">Lorem ipsum dolor sit amet enim.</small> -->
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.user_sum / (basicStats.user_count ? basicStats.user_count : 1) | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div>User Avg. Spend</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="text-muted">Lorem ipsum dolor sit amet enim.</small> -->
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
</div><!--/.row-->
|
||||
</div>
|
55
src/app/dashboard/dashboard-customer.component.ts
Normal file
55
src/app/dashboard/dashboard-customer.component.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import { Directive, Component, OnInit } from '@angular/core';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { Router } from '@angular/router';
|
||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'dashboard-customer.component.html'
|
||||
})
|
||||
export class DashboardCustomerComponent implements OnInit {
|
||||
customersThisMonth: any;
|
||||
moneySpentThisMonth: any;
|
||||
pointsTotal: any;
|
||||
averageTransactionToday: any;
|
||||
|
||||
/* Setting up dashboard's main variables*/
|
||||
name: any;
|
||||
email:any;
|
||||
myPearPoints: any;
|
||||
trends: any;
|
||||
myRank: any;
|
||||
username: any;
|
||||
|
||||
basicStats = {
|
||||
today_sum: 0,
|
||||
today_count: 0,
|
||||
week_sum: 0,
|
||||
week_count: 0,
|
||||
month_sum: 0,
|
||||
month_count: 0,
|
||||
user_sum: 0,
|
||||
user_count: 0,
|
||||
global_sum: 0,
|
||||
global_count: 0,
|
||||
user_position: 0,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.api.basicStats().subscribe(
|
||||
result => {
|
||||
this.basicStats = result;
|
||||
},
|
||||
error => {
|
||||
console.log('Retrieval Error');
|
||||
console.log( error._body );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
}
|
13
src/app/dashboard/dashboard.component.html
Normal file
13
src/app/dashboard/dashboard.component.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<div class="animated fadeIn">
|
||||
<snippet-bar-org></snippet-bar-org>
|
||||
<div class="row">
|
||||
<div *ngFor="let widget of widgetList" class="col-sm-6 col-lg-3">
|
||||
<widget-graph *ngIf="widget.type == 'graph'"
|
||||
[graphName]="widget.name"
|
||||
[graphTitle]="widget.title"
|
||||
[graphIcon]="widget.icon"
|
||||
[dataType]="widget.dataType"></widget-graph>
|
||||
</div><!--/.col-->
|
||||
</div><!--/.row-->
|
||||
<panel-graph></panel-graph>
|
||||
</div>
|
55
src/app/dashboard/dashboard.component.ts
Normal file
55
src/app/dashboard/dashboard.component.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||
import { GraphPanel } from '../panels/graph-panel.component';
|
||||
import { DataType } from '../shared/data-types.enum';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'dashboard.component.html'
|
||||
})
|
||||
export class DashboardComponent {
|
||||
|
||||
public widgetList = [
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'customers_last_7_days',
|
||||
icon: 'icon-people',
|
||||
title: 'Customers Last 7 Days',
|
||||
},
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'customers_last_30_days',
|
||||
icon: 'icon-people',
|
||||
title: 'Customers Last 30 Days',
|
||||
},
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'sales_last_7_days',
|
||||
icon: 'icon-diamond',
|
||||
title: 'Sales Last 7 Days',
|
||||
dataType: DataType.currency,
|
||||
},
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'sales_last_30_days',
|
||||
icon: 'icon-diamond',
|
||||
title: 'Sales Last 30 Days',
|
||||
dataType: DataType.currency,
|
||||
},
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'purchases_last_7_days',
|
||||
title: 'Purchases Last 7 Days',
|
||||
dataType: DataType.currency,
|
||||
},
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'purchases_last_30_days',
|
||||
title: 'Purchases Last 30 Days',
|
||||
dataType: DataType.currency,
|
||||
},
|
||||
];
|
||||
|
||||
constructor() { }
|
||||
}
|
55
src/app/dashboard/dashboard.module.ts
Normal file
55
src/app/dashboard/dashboard.module.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ChartsModule } from 'ng2-charts/ng2-charts';
|
||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||
import { NgxPaginationModule } from 'ngx-pagination';
|
||||
|
||||
import { CurrencyPipe } from '@angular/common';
|
||||
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { DashboardCustomerComponent } from './dashboard-customer.component';
|
||||
import { AccountEditComponent } from './account-edit.component';
|
||||
import { AddDataComponent } from './add-data.component';
|
||||
import { FeedbackComponent } from './feedback.component';
|
||||
import { TransactionLogComponent } from './transaction-log.component';
|
||||
|
||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||
import { GraphPanel } from '../panels/graph-panel.component';
|
||||
|
||||
import { DashboardRoutingModule } from './dashboard.routing';
|
||||
import { OrgResultComponent } from '../shared/org-result.component';
|
||||
import { OrgTableComponent } from '../shared/org-table.component';
|
||||
import { TransactionResultComponent } from '../shared/transaction-result.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
// Angular imports
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
ChartsModule,
|
||||
BsDropdownModule,
|
||||
NgxPaginationModule,
|
||||
DashboardRoutingModule,
|
||||
],
|
||||
declarations: [
|
||||
DashboardComponent,
|
||||
DashboardCustomerComponent,
|
||||
AccountEditComponent,
|
||||
AddDataComponent,
|
||||
OrgResultComponent,
|
||||
OrgTableComponent,
|
||||
TransactionLogComponent,
|
||||
TransactionResultComponent,
|
||||
FeedbackComponent,
|
||||
GraphWidget,
|
||||
OrgBarSnippetComponent,
|
||||
GraphPanel,
|
||||
],
|
||||
providers: [
|
||||
CurrencyPipe
|
||||
],
|
||||
})
|
||||
export class DashboardModule { }
|
64
src/app/dashboard/dashboard.routing.ts
Normal file
64
src/app/dashboard/dashboard.routing.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { AuthGuard } from '../_guards/auth.guard';
|
||||
import { OrgGuard } from '../_guards/org.guard';
|
||||
import { CustomerGuard } from '../_guards/customer.guard';
|
||||
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { DashboardCustomerComponent } from './dashboard-customer.component';
|
||||
import { FullLayoutComponent } from '../layouts/full-layout.component';
|
||||
import { AccountEditComponent } from './account-edit.component';
|
||||
import { AddDataComponent } from './add-data.component';
|
||||
import { FeedbackComponent } from './feedback.component';
|
||||
import { TransactionLogComponent } from './transaction-log.component';
|
||||
|
||||
// Using child path to allow for FullLayout theming
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
||||
{
|
||||
path: '',
|
||||
component: FullLayoutComponent,
|
||||
canActivate: [AuthGuard],
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: DashboardComponent,
|
||||
data: { title: 'Dashboard' },
|
||||
canActivate: [OrgGuard],
|
||||
},
|
||||
{
|
||||
path: 'dashboard-customer',
|
||||
component: DashboardCustomerComponent,
|
||||
data: { title: 'Customer Dashboard' },
|
||||
canActivate: [CustomerGuard],
|
||||
},
|
||||
{
|
||||
path: 'account-edit',
|
||||
component: AccountEditComponent,
|
||||
data: { title: 'Leaderboards' },
|
||||
},
|
||||
{
|
||||
path: 'add-data',
|
||||
component: AddDataComponent,
|
||||
data: { title: 'Add Transaction' },
|
||||
},
|
||||
{
|
||||
path: 'transaction-log',
|
||||
component: TransactionLogComponent,
|
||||
data: { title: 'Transaction Log' },
|
||||
},
|
||||
{
|
||||
path: 'feedback',
|
||||
component: FeedbackComponent,
|
||||
data: { title: 'Give Feedback' },
|
||||
}
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class DashboardRoutingModule {}
|
45
src/app/dashboard/feedback.component.html
Normal file
45
src/app/dashboard/feedback.component.html
Normal file
|
@ -0,0 +1,45 @@
|
|||
<div class="animated fadeIn">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<strong>Submit Transaction</strong>
|
||||
<small>Required Data marked in <strong>bold</strong>.</small>
|
||||
</div>
|
||||
<form class="form-horizontal" [formGroup]="feedbackForm" (ngSubmit)="onSubmit()">
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Email</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" name="email" formControlName="email" placeholder="Enter Account Email Here" [(ngModel)]="loggedInEmail" [disabled]="noEmail">
|
||||
<span class="help-block">Enter your email here if it doesn't show.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Enter Feedback Here</strong></label>
|
||||
<div class="col-md-9">
|
||||
<textarea rows="7" class="form-control" formControlName="feedbacktext"></textarea>
|
||||
<span class="help-block">Please enter your feedback in this textbox.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-9">
|
||||
<div [ngSwitch]="feedbackFormStatus">
|
||||
<div *ngSwitchCase="'success'" class="alert alert-success" role="alert">
|
||||
Thank you for submitting feedback!
|
||||
</div>
|
||||
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
|
||||
{{feedbackFormStatusError}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" [disabled]="!feedbackForm.valid" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.row-->
|
||||
</div>
|
90
src/app/dashboard/feedback.component.ts
Normal file
90
src/app/dashboard/feedback.component.ts
Normal file
|
@ -0,0 +1,90 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'feedback.component.html',
|
||||
})
|
||||
export class FeedbackComponent {
|
||||
feedbackForm: FormGroup;
|
||||
loggedInEmail: string;
|
||||
noEmail: boolean = false;
|
||||
username: any;
|
||||
feedbackFormStatus: any;
|
||||
feedbackFormStatusError: string = 'Error received, please try again.';
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.feedbackForm = this.formBuilder.group({
|
||||
email: ['', [Validators.required]],
|
||||
feedbacktext: ['', [Validators.required]],
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
if(localStorage.getItem('email')) {
|
||||
this.loggedInEmail = localStorage.getItem('email');
|
||||
}
|
||||
console.log('loggedInEmail: ' + this.loggedInEmail);
|
||||
if (this.loggedInEmail) {
|
||||
console.log('email not found in storage');
|
||||
this.api.accountFullLoad().subscribe(
|
||||
result => {
|
||||
console.log(result);
|
||||
this.feedbackForm.patchValue({
|
||||
email: result.email,
|
||||
});
|
||||
this.api.setUserInfo( result.email, result.display_name || result.name );
|
||||
},
|
||||
error => {
|
||||
console.log( error._body );
|
||||
this.noEmail = true;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.api
|
||||
.feedback(this.feedbackForm.value)
|
||||
.subscribe(
|
||||
result => {
|
||||
if ( result.success == true ) {
|
||||
console.log('Successful Upload');
|
||||
console.log(result);
|
||||
this.feedbackFormStatus = "success";
|
||||
console.log(this.feedbackFormStatus);
|
||||
this.feedbackForm.patchValue({
|
||||
feedbacktext: '',
|
||||
});
|
||||
} else {
|
||||
console.log('Upload Error');
|
||||
this.feedbackFormStatusError = JSON.stringify(result.status) + 'Error, ' + JSON.stringify(result.message);
|
||||
this.feedbackFormStatus = "send_failed";
|
||||
console.log(this.feedbackFormStatus);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.log('Upload Error');
|
||||
console.log(error);
|
||||
try {
|
||||
console.log(error.error);
|
||||
let jsonError = error.json();
|
||||
console.log("boop");
|
||||
this.feedbackFormStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message;
|
||||
} catch(e) {
|
||||
this.feedbackFormStatusError = 'There was a server error, please try again later.';
|
||||
}
|
||||
this.feedbackFormStatus = "send_failed";
|
||||
console.log(this.feedbackFormStatus);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
49
src/app/dashboard/transaction-log.component.html
Normal file
49
src/app/dashboard/transaction-log.component.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<div class="animated fadeIn">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<strong>Log of Outgoing Transactions</strong>
|
||||
<small>This lists all purchases that have been submitted.</small>
|
||||
</div>
|
||||
<div *ngIf="!noTransactionList" class="card-block">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Seller</th>
|
||||
<th>Value</th>
|
||||
<th>Purchase Time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr transaction-result *ngFor="let transaction of transactionList | paginate: paginateConfig" [transaction]="transaction"></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<pagination-template #p="paginationApi"
|
||||
[id]="paginateConfig.id"
|
||||
(pageChange)="loadTransactions($event)">
|
||||
<ul class="pagination">
|
||||
<li class="page-item" [class.disabled]="p.isFirstPage()">
|
||||
<a class="page-link clickable" *ngIf="!p.isFirstPage()" (click)="p.previous()">Prev</a>
|
||||
</li>
|
||||
<li *ngFor="let page of p.pages" class="page-item" [class.active]="p.getCurrent() === page.value">
|
||||
<a class="page-link clickable" (click)="p.setCurrent(page.value)" *ngIf="p.getCurrent() !== page.value">
|
||||
<span>{{ page.label }}</span>
|
||||
</a>
|
||||
<div class="page-link" *ngIf="p.getCurrent() === page.value">
|
||||
<span>{{ page.label }}</span>
|
||||
</div>
|
||||
</li>
|
||||
<li class="page-item" [class.disabled]="p.isLastPage()">
|
||||
<a class="page-link clickable" *ngIf="!p.isLastPage()" (click)="p.next()">Next</a>
|
||||
</li>
|
||||
</ul>
|
||||
</pagination-template>
|
||||
</div>
|
||||
<div *ngIf="noTransactionList" class="card-block">
|
||||
No Transactions available.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
77
src/app/dashboard/transaction-log.component.ts
Normal file
77
src/app/dashboard/transaction-log.component.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
// import { PaginatePipe } from 'ngx-pagination';
|
||||
import {PaginationInstance} from 'ngx-pagination';
|
||||
// import { PaginationControlsComponent } from 'ngx-pagination';
|
||||
// import { PaginationControlsDirective } from 'ngx-pagination';
|
||||
// import { TransactionResultComponent } from '../shared/transaction-result.component';
|
||||
import * as moment from 'moment';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'transaction-log.component.html',
|
||||
})
|
||||
export class TransactionLogComponent {
|
||||
|
||||
transactionList;
|
||||
noTransactionList = true;
|
||||
myDate: any;
|
||||
minDate: any;
|
||||
|
||||
public paginateConfig: PaginationInstance = {
|
||||
id: 'transpaginate',
|
||||
itemsPerPage: 10,
|
||||
currentPage: 1,
|
||||
totalItems: 0
|
||||
};
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.myDate = moment().format('YYYY-MM-DD[T]HH:mm');
|
||||
// this.myDate = new Date().toISOString().slice(0, 16);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getMinDate();
|
||||
this.loadTransactions(1);
|
||||
}
|
||||
|
||||
getMinDate(){
|
||||
// gets the April 1st date of the current year
|
||||
let aprilDate = moment().month(3).date(1);
|
||||
let now = moment();
|
||||
// Checks if current time is before April 1st, if so returns true
|
||||
let beforeApril = now.isBefore(aprilDate);
|
||||
if ( beforeApril == true ) {
|
||||
this.minDate = aprilDate.subtract(2, 'years').format('YYYY-MM-DD');
|
||||
} else {
|
||||
this.minDate = aprilDate.subtract(1, 'years').format('YYYY-MM-DD');
|
||||
}
|
||||
}
|
||||
|
||||
loadTransactions(logPage: number) {
|
||||
console.log(logPage);
|
||||
this.api.transList(logPage).subscribe(
|
||||
result => {
|
||||
if(result.transactions.length > 0) {
|
||||
this.transactionList = result.transactions;
|
||||
//TODO Rename in server
|
||||
this.paginateConfig.totalItems = result.page_no;
|
||||
this.paginateConfig.currentPage = logPage;
|
||||
this.noTransactionList = false;
|
||||
} else {
|
||||
// handle the case when the transactionList is empty
|
||||
this.transactionList = null;
|
||||
this.noTransactionList = true;
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
71
src/app/layouts/full-layout.component.html
Normal file
71
src/app/layouts/full-layout.component.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<header class="app-header navbar">
|
||||
<button class="navbar-toggler d-lg-none" type="button" appMobileSidebarToggler>☰</button>
|
||||
<a class="navbar-brand" href="#"></a>
|
||||
<ul class="nav navbar navbar-nav">
|
||||
<li class="nav-item dropdown" dropdown (onToggle)="toggled($event)">
|
||||
<a href class="nav-link dropdown-toggle" dropdownToggle (click)="false">
|
||||
<img src="assets/img/avatars/default.png" class="img-avatar" alt="avatar-image">
|
||||
<span class="d-md-down-none">{{displayName}}</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right" *dropdownMenu aria-labelledby="simple-dropdown">
|
||||
|
||||
<div class="dropdown-header text-center"><strong>Settings</strong></div>
|
||||
|
||||
<a class="dropdown-item" routerLinkActive="active" [routerLink]="['/account-edit']">
|
||||
<i class="fa fa-user"></i> Account Settings
|
||||
</a>
|
||||
<div class="divider"></div>
|
||||
<a class="dropdown-item" (click)="userLogout()" href="#"><i class="fa fa-lock"></i> Logout</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<div class="app-body">
|
||||
<div class="sidebar">
|
||||
<nav class="sidebar-nav">
|
||||
<ul class="nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/dashboard']">
|
||||
<i class="icon-speedometer"></i> Dashboard
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/add-data']">
|
||||
<i class="icon-basket"></i> Add Transaction
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/feedback']">
|
||||
<i class="icon-envelope-letter"></i> Enter Feedback
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/transaction-log']">
|
||||
<i class="icon-basket"></i> Transaction Log
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<main class="main">
|
||||
|
||||
<!-- Breadcrumb -->
|
||||
<ol class="breadcrumb">
|
||||
<app-breadcrumbs></app-breadcrumbs>
|
||||
<!-- Breadcrumb Menu-->
|
||||
</ol>
|
||||
|
||||
<div class="container-fluid">
|
||||
<router-outlet></router-outlet>
|
||||
</div><!-- /.conainer-fluid -->
|
||||
</main>
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="app-footer">
|
||||
<a href="http://coreui.io">CoreUI</a> © 2017 creativeLabs.
|
||||
<span class="float-right">Powered by <a href="http://coreui.io">CoreUI</a></span>
|
||||
</footer>
|
47
src/app/layouts/full-layout.component.ts
Normal file
47
src/app/layouts/full-layout.component.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
templateUrl: './full-layout.component.html',
|
||||
})
|
||||
export class FullLayoutComponent implements OnInit {
|
||||
displayName: any;
|
||||
|
||||
constructor(
|
||||
private api: ApiService,
|
||||
private router: Router,
|
||||
) {}
|
||||
|
||||
public disabled = false;
|
||||
public status: {isopen: boolean} = {isopen: false};
|
||||
|
||||
public toggled(open: boolean): void {
|
||||
console.log('Dropdown is now: ', open);
|
||||
}
|
||||
|
||||
public toggleDropdown($event: MouseEvent): void {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
this.status.isopen = !this.status.isopen;
|
||||
}
|
||||
|
||||
// getDisplayName function from api didnt work
|
||||
ngOnInit(): void {
|
||||
this.displayName = localStorage.getItem('displayname') || 'User';
|
||||
}
|
||||
|
||||
userLogout() {
|
||||
console.log('logout clicked');
|
||||
this.api
|
||||
.logout()
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('Logged out!');
|
||||
localStorage.clear();
|
||||
this.router.navigate(['/login']);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
12
src/app/layouts/simple-layout.component.ts
Normal file
12
src/app/layouts/simple-layout.component.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
template: '<router-outlet></router-outlet>',
|
||||
})
|
||||
export class SimpleLayoutComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void { }
|
||||
}
|
16
src/app/pages/404.component.html
Normal file
16
src/app/pages/404.component.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<div class="app flex-row align-items-center">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="clearfix">
|
||||
<h1 class="float-left display-3 mr-4">404</h1>
|
||||
<h4 class="pt-3">Oops! You're lost.</h4>
|
||||
<p class="text-muted">The page you are looking for was not found.</p>
|
||||
</div>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary btn-lg" type="button"(click)="goBack()">Go Back</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
17
src/app/pages/404.component.ts
Normal file
17
src/app/pages/404.component.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
templateUrl: '404.component.html'
|
||||
})
|
||||
export class P404Component {
|
||||
|
||||
constructor(
|
||||
private location: Location
|
||||
) {
|
||||
}
|
||||
|
||||
goBack(): void {
|
||||
this.location.back();
|
||||
}
|
||||
}
|
16
src/app/pages/500.component.html
Normal file
16
src/app/pages/500.component.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<div class="app flex-row align-items-center">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="clearfix">
|
||||
<h1 class="float-left display-3 mr-4">500</h1>
|
||||
<h4 class="pt-3">Houston, we have a problem!</h4>
|
||||
<p class="text-muted">The page you are looking for is temporarily unavailable.</p>
|
||||
</div>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary btn-lg" type="button"(click)="goBack()">Go Back</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
17
src/app/pages/500.component.ts
Normal file
17
src/app/pages/500.component.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
templateUrl: '500.component.html'
|
||||
})
|
||||
export class P500Component {
|
||||
|
||||
constructor(
|
||||
private location: Location
|
||||
) {
|
||||
}
|
||||
|
||||
goBack(): void {
|
||||
this.location.back();
|
||||
}
|
||||
}
|
29
src/app/panels/graph-panel.component.html
Normal file
29
src/app/panels/graph-panel.component.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
<div class="card">
|
||||
<div class="card-block">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<h4 class="card-title mb-0">Customers</h4>
|
||||
</div><!--/.col-->
|
||||
<div class="col-sm-7 hidden-sm-down">
|
||||
<div class="btn-toolbar float-right" role="toolbar" aria-label="Toolbar with button groups">
|
||||
<div class="btn-group mr-3" data-toggle="buttons" aria-label="First group">
|
||||
<label class="btn btn-outline-secondary active">
|
||||
<input type="radio" name="options" id="option2" checked> Week
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
</div><!--/.row-->
|
||||
<div class="chart-wrapper" style="height:300px;margin-top:40px;">
|
||||
<canvas baseChart class="chart"
|
||||
[datasets]="chartData"
|
||||
[labels]="chartLabels"
|
||||
[options]="mainChartOptions"
|
||||
[colors]="mainChartColours"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="chartType"
|
||||
(chartHover)="chartHovered($event)"
|
||||
(chartClick)="chartClicked($event)"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
145
src/app/panels/graph-panel.component.ts
Normal file
145
src/app/panels/graph-panel.component.ts
Normal file
|
@ -0,0 +1,145 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { OrgGraphsService } from '../providers/org-graphs.service';
|
||||
import { DataType } from '../shared/data-types.enum';
|
||||
import { ChartData } from '../_interfaces/chart-data';
|
||||
import * as moment from 'moment';
|
||||
|
||||
@Component({
|
||||
selector: 'panel-graph',
|
||||
templateUrl: 'graph-panel.component.html',
|
||||
})
|
||||
export class GraphPanel implements OnInit {
|
||||
|
||||
public chartType = 'line';
|
||||
public chartLegend = true;
|
||||
|
||||
public rawChartData: Array<number> = [];
|
||||
|
||||
public chartData: Array<ChartData> = [
|
||||
{
|
||||
data: [],
|
||||
label: 'This Week'
|
||||
},
|
||||
{
|
||||
data: [],
|
||||
label: 'Last Week'
|
||||
},
|
||||
{
|
||||
data: [],
|
||||
label: 'Week Before Last'
|
||||
}
|
||||
];
|
||||
|
||||
public rawChartLabels: Array<string> = [];
|
||||
public chartLabels: Array<string> = [];
|
||||
|
||||
public brandSuccess = '#4dbd74';
|
||||
public brandInfo = '#63c2de';
|
||||
public brandDanger = '#f86c6b';
|
||||
|
||||
public mainChartElements = 7;
|
||||
|
||||
public mainChartOptions: any = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'day',
|
||||
displayFormats: {
|
||||
day: 'dddd',
|
||||
},
|
||||
tooltipFormat: 'dddd',
|
||||
},
|
||||
gridLines: {
|
||||
drawOnChartArea: false,
|
||||
},
|
||||
}],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
stepSize: 1,
|
||||
}
|
||||
}]
|
||||
},
|
||||
elements: {
|
||||
line: {
|
||||
borderWidth: 2
|
||||
},
|
||||
point: {
|
||||
radius: 0,
|
||||
hitRadius: 10,
|
||||
hoverRadius: 4,
|
||||
hoverBorderWidth: 3,
|
||||
}
|
||||
},
|
||||
};
|
||||
public mainChartColours: Array<any> = [
|
||||
{ // brandInfo
|
||||
backgroundColor: this.convertHex(this.brandInfo, 10),
|
||||
borderColor: this.brandInfo,
|
||||
pointHoverBackgroundColor: '#fff'
|
||||
},
|
||||
{ // brandSuccess
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: this.brandSuccess,
|
||||
pointHoverBackgroundColor: '#fff'
|
||||
},
|
||||
{ // brandDanger
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: this.brandDanger,
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
borderWidth: 1,
|
||||
borderDash: [8, 5]
|
||||
}
|
||||
];
|
||||
|
||||
constructor(
|
||||
private graphService: OrgGraphsService,
|
||||
) { }
|
||||
|
||||
public ngOnInit(): void {
|
||||
const end = moment().startOf('day');
|
||||
const start = end.clone().subtract(this.mainChartElements * 3, 'days');
|
||||
this.graphService.getGraph('customers_range', {
|
||||
start: start.format('YYYY-MM-DD'),
|
||||
end: end.format('YYYY-MM-DD'),
|
||||
}).subscribe( result => this.setData(result.graph) );
|
||||
}
|
||||
|
||||
private setData(data: any) {
|
||||
this.chartLabels = data.labels.slice(this.mainChartElements * 2, this.mainChartElements * 3);
|
||||
this.chartData[2].data = data.data.slice(0, this.mainChartElements);
|
||||
this.chartData[1].data = data.data.slice(this.mainChartElements, this.mainChartElements * 2);
|
||||
this.chartData[0].data = data.data.slice(this.mainChartElements * 2, this.mainChartElements * 3);
|
||||
}
|
||||
|
||||
// convert Hex to RGBA
|
||||
public convertHex(hex: string, opacity: number) {
|
||||
hex = hex.replace('#', '');
|
||||
const r = parseInt(hex.substring(0, 2), 16);
|
||||
const g = parseInt(hex.substring(2, 4), 16);
|
||||
const b = parseInt(hex.substring(4, 6), 16);
|
||||
|
||||
const rgba = 'rgba(' + r + ', ' + g + ', ' + b + ', ' + opacity / 100 + ')';
|
||||
return rgba;
|
||||
}
|
||||
|
||||
// events
|
||||
public chartClicked(e: any): void {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
public chartHovered(e: any): void {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
// mainChart
|
||||
|
||||
public random(min: number, max: number) {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min);
|
||||
}
|
||||
|
||||
|
||||
}
|
264
src/app/providers/api-service.ts
Normal file
264
src/app/providers/api-service.ts
Normal file
|
@ -0,0 +1,264 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { environment } from '../../environments/environment';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
/* this provider handles the interaction between server and client */
|
||||
|
||||
@Injectable()
|
||||
export class ApiService {
|
||||
private apiUrl = environment.apiUrl;
|
||||
private sessionKey: string = null;
|
||||
constructor(
|
||||
private http: Http,
|
||||
) {
|
||||
if (localStorage.getItem('sessionKey') ) {
|
||||
this.sessionKey = localStorage.getItem('sessionKey');
|
||||
}
|
||||
}
|
||||
|
||||
public post(url: string, data: any = {}) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + url,
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
// Login API
|
||||
|
||||
public getSessionKey() {
|
||||
console.log('get key');
|
||||
return this.sessionKey;
|
||||
}
|
||||
|
||||
public setSessionKey(key) {
|
||||
console.log('set key');
|
||||
this.sessionKey = key;
|
||||
localStorage.setItem('sessionKey', this.sessionKey);
|
||||
}
|
||||
|
||||
public removeSessionKey() {
|
||||
console.log('remove key');
|
||||
this.sessionKey = null;
|
||||
localStorage.removeItem('sessionKey');
|
||||
}
|
||||
|
||||
public register(data) {
|
||||
return this.http.post(
|
||||
this.apiUrl + '/register',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
public login(data) {
|
||||
return this.http
|
||||
.post(
|
||||
this.apiUrl + '/login',
|
||||
data
|
||||
)
|
||||
.map(
|
||||
result => {
|
||||
const json = result.json();
|
||||
this.setSessionKey(json.session_key);
|
||||
this.setUserInfo(
|
||||
json.email,
|
||||
json.display_name || json.name
|
||||
);
|
||||
this.setUserType(json.user_type);
|
||||
return json;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public logout() {
|
||||
console.log(this.sessionKey);
|
||||
const key = this.sessionKey;
|
||||
return this.http
|
||||
.post(
|
||||
this.apiUrl + '/logout',
|
||||
{ session_key : key },
|
||||
)
|
||||
.map(
|
||||
response => {
|
||||
localStorage.clear();
|
||||
this.sessionKey = null;
|
||||
return response.json();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Submits feedback
|
||||
|
||||
public feedback(data) {
|
||||
data.app_name = 'Foodloop Web';
|
||||
data.package_name = 'Foodloop Web';
|
||||
data.version_code = 'dev';
|
||||
data.version_number = 'dev';
|
||||
console.log(data);
|
||||
return this.http.post(
|
||||
this.apiUrl + '/feedback',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
// gets transaction list for log
|
||||
|
||||
public transList(data) {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/outgoing-transactions',
|
||||
{
|
||||
session_key : key,
|
||||
page : data
|
||||
}
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
// Searches organisations used for transaction submission
|
||||
|
||||
public search(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/search',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
// Uploads a transaction
|
||||
|
||||
public upload(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/upload',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
// handles Org data added
|
||||
|
||||
public orgPayroll(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/org/payroll',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
public orgSupplier(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/org/supplier',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
public orgEmployee(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/org/employee',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
// Handles user data interaction
|
||||
|
||||
// Checks for login status
|
||||
|
||||
public hasLoggedIn() {
|
||||
return this.getSessionKey() ? true : false;
|
||||
}
|
||||
|
||||
// Pulls user info to store locally on login
|
||||
|
||||
public setUserInfo(
|
||||
email: string,
|
||||
display_name: string) {
|
||||
console.log('set UserInfo');
|
||||
localStorage.setItem('email', email);
|
||||
localStorage.setItem('displayname', display_name);
|
||||
}
|
||||
|
||||
// Sets usertype
|
||||
|
||||
public setUserType(user_type: string) {
|
||||
console.log('set UserType');
|
||||
localStorage.setItem('usertype', user_type);
|
||||
}
|
||||
|
||||
// Used for getting account details and updating
|
||||
|
||||
public accountFullLoad() {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/user',
|
||||
{ session_key : key },
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
public accountEditUpdate(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/user/account',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
// Deletes account details on logout
|
||||
|
||||
public removeUserInfo() {
|
||||
console.log('remove UserInfo');
|
||||
localStorage.removeItem('email');
|
||||
localStorage.removeItem('displayname');
|
||||
}
|
||||
|
||||
public getFullName() {
|
||||
console.log('get Full Name');
|
||||
localStorage.getItem('fullname');
|
||||
}
|
||||
|
||||
public getDisplayName() {
|
||||
console.log('get Display Name');
|
||||
localStorage.getItem('displayname');
|
||||
}
|
||||
|
||||
public getPostcode() {
|
||||
console.log('get Postcode');
|
||||
localStorage.getItem('postcode');
|
||||
}
|
||||
|
||||
public getYearOfBirth() {
|
||||
console.log('get Year of Birth');
|
||||
localStorage.getItem('yearofbirth');
|
||||
}
|
||||
|
||||
public getEmail() {
|
||||
console.log('get email');
|
||||
localStorage.getItem('email');
|
||||
}
|
||||
|
||||
// Leaderboard Api
|
||||
|
||||
public leaderboard_fetch(data) {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/stats/leaderboard',
|
||||
{
|
||||
session_key : key,
|
||||
type : data
|
||||
}
|
||||
).map( response => response.json() );
|
||||
}
|
||||
|
||||
// Basic Customer User stats API
|
||||
public basicStats() {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
this.apiUrl + '/stats',
|
||||
{
|
||||
session_key : key,
|
||||
}
|
||||
).map( response => response.json() );
|
||||
}
|
||||
}
|
14
src/app/providers/org-graphs.service.ts
Normal file
14
src/app/providers/org-graphs.service.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { ApiService } from './api-service';
|
||||
|
||||
@Injectable()
|
||||
export class OrgGraphsService {
|
||||
private orgGraphUrl = '/v1/organisation/graphs';
|
||||
|
||||
constructor(private api: ApiService) { }
|
||||
|
||||
public getGraph(name: string, data: any = {}) {
|
||||
data.graph = name;
|
||||
return this.api.post(this.orgGraphUrl, data);
|
||||
}
|
||||
}
|
14
src/app/providers/org-snippets.service.ts
Normal file
14
src/app/providers/org-snippets.service.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { ApiService } from './api-service';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
@Injectable()
|
||||
export class OrgSnippetsService {
|
||||
private orgSnippetsUrl = '/v1/organisation/snippets';
|
||||
|
||||
constructor(private api: ApiService) { }
|
||||
|
||||
public getData(): Observable<any> {
|
||||
return this.api.post(this.orgSnippetsUrl);
|
||||
}
|
||||
}
|
17
src/app/shared/aside.directive.ts
Normal file
17
src/app/shared/aside.directive.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Directive, HostListener } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Allows the aside to be toggled via click.
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[appAsideMenuToggler]',
|
||||
})
|
||||
export class AsideToggleDirective {
|
||||
constructor() { }
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
toggleOpen($event: any) {
|
||||
$event.preventDefault();
|
||||
document.querySelector('body').classList.toggle('aside-menu-hidden');
|
||||
}
|
||||
}
|
42
src/app/shared/breadcrumb.component.ts
Normal file
42
src/app/shared/breadcrumb.component.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
|
||||
import 'rxjs/add/operator/filter';
|
||||
|
||||
@Component({
|
||||
selector: 'app-breadcrumbs',
|
||||
template: `
|
||||
<ng-template ngFor let-breadcrumb [ngForOf]="breadcrumbs" let-last = last>
|
||||
<li class="breadcrumb-item"
|
||||
*ngIf="breadcrumb.label.title&&breadcrumb.url.substring(breadcrumb.url.length-1) == '/'||breadcrumb.label.title&&last"
|
||||
[ngClass]="{active: last}">
|
||||
<a *ngIf="!last" [routerLink]="breadcrumb.url">{{breadcrumb.label.title}}</a>
|
||||
<span *ngIf="last" [routerLink]="breadcrumb.url">{{breadcrumb.label.title}}</span>
|
||||
</li>
|
||||
</ng-template>`
|
||||
})
|
||||
export class BreadcrumbsComponent implements OnInit {
|
||||
breadcrumbs: Array<Object>;
|
||||
constructor(private router: Router, private route: ActivatedRoute) {}
|
||||
ngOnInit(): void {
|
||||
this.router.events.filter(event => event instanceof NavigationEnd).subscribe(event => {
|
||||
this.breadcrumbs = [];
|
||||
let currentRoute = this.route.root,
|
||||
url = '';
|
||||
do {
|
||||
const childrenRoutes = currentRoute.children;
|
||||
currentRoute = null;
|
||||
childrenRoutes.forEach(route => {
|
||||
if (route.outlet === 'primary') {
|
||||
const routeSnapshot = route.snapshot;
|
||||
url += '/' + routeSnapshot.url.map(segment => segment.path).join('/');
|
||||
this.breadcrumbs.push({
|
||||
label: route.snapshot.data,
|
||||
url: url
|
||||
});
|
||||
currentRoute = route;
|
||||
}
|
||||
});
|
||||
} while (currentRoute);
|
||||
});
|
||||
}
|
||||
}
|
4
src/app/shared/data-types.enum.ts
Normal file
4
src/app/shared/data-types.enum.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
export enum DataType {
|
||||
number,
|
||||
currency,
|
||||
}
|
31
src/app/shared/nav-dropdown.directive.ts
Normal file
31
src/app/shared/nav-dropdown.directive.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { Directive, HostListener, ElementRef } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[appNavDropdown]'
|
||||
})
|
||||
export class NavDropdownDirective {
|
||||
|
||||
constructor(private el: ElementRef) { }
|
||||
|
||||
toggle() {
|
||||
this.el.nativeElement.classList.toggle('open');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the dropdown to be toggled via click.
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[appNavDropdownToggle]'
|
||||
})
|
||||
export class NavDropdownToggleDirective {
|
||||
constructor(private dropdown: NavDropdownDirective) {}
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
toggleOpen($event: any) {
|
||||
$event.preventDefault();
|
||||
this.dropdown.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
export const NAV_DROPDOWN_DIRECTIVES = [NavDropdownDirective, NavDropdownToggleDirective];
|
4
src/app/shared/org-result.component.html
Normal file
4
src/app/shared/org-result.component.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
<td (click)="orgClick()">{{org.name}}</td>
|
||||
<td (click)="orgClick()">{{org.street_name}}</td>
|
||||
<td (click)="orgClick()">{{org.town}}</td>
|
||||
<td (click)="orgClick()">{{org.postcode}}</td>
|
24
src/app/shared/org-result.component.ts
Normal file
24
src/app/shared/org-result.component.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
|
||||
interface OrgData {
|
||||
id: number;
|
||||
name: string;
|
||||
street_name: string;
|
||||
town: string;
|
||||
postcode: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: '[org-result]',
|
||||
templateUrl: 'org-result.component.html',
|
||||
})
|
||||
export class OrgResultComponent {
|
||||
@Input() public org: OrgData;
|
||||
@Output() public onClick = new EventEmitter();
|
||||
|
||||
public orgClick(): void {
|
||||
this.onClick.emit(
|
||||
this.org
|
||||
)
|
||||
}
|
||||
}
|
19
src/app/shared/org-table.component.html
Normal file
19
src/app/shared/org-table.component.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Organisation Search Results</strong></label>
|
||||
<div class="col-md-9">
|
||||
<span class="help-block"><strong>Select an Organisation from the table below</strong></span>
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Organisation Name</th>
|
||||
<th>Street Name</th>
|
||||
<th>Town</th>
|
||||
<th>Postcode</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr org-result *ngFor="let org of orgList" [org]="org" (onClick)="orgClick($event)"></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
23
src/app/shared/org-table.component.ts
Normal file
23
src/app/shared/org-table.component.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { OrgResultComponent } from '../shared/org-result.component';
|
||||
|
||||
interface OrgData {
|
||||
id: number;
|
||||
name: string;
|
||||
street_name: string;
|
||||
town: string;
|
||||
postcode: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'org-table',
|
||||
templateUrl: 'org-table.component.html',
|
||||
})
|
||||
export class OrgTableComponent {
|
||||
@Input() public orgList: Array<OrgData>;
|
||||
@Output() public onClick = new EventEmitter();
|
||||
|
||||
public orgClick(event: any): void {
|
||||
this.onClick.emit( event );
|
||||
}
|
||||
}
|
92
src/app/shared/sidebar.directive.ts
Normal file
92
src/app/shared/sidebar.directive.ts
Normal file
|
@ -0,0 +1,92 @@
|
|||
import { Directive, HostListener } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Allows the sidebar to be toggled via click.
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[appSidebarToggler]'
|
||||
})
|
||||
export class SidebarToggleDirective {
|
||||
constructor() { }
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
toggleOpen($event: any) {
|
||||
$event.preventDefault();
|
||||
document.querySelector('body').classList.toggle('sidebar-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
selector: '[appSidebarMinimizer]'
|
||||
})
|
||||
export class SidebarMinimizeDirective {
|
||||
constructor() { }
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
toggleOpen($event: any) {
|
||||
$event.preventDefault();
|
||||
document.querySelector('body').classList.toggle('sidebar-minimized');
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
selector: '[appMobileSidebarToggler]'
|
||||
})
|
||||
export class MobileSidebarToggleDirective {
|
||||
constructor() { }
|
||||
|
||||
// Check if element has class
|
||||
private hasClass(target: any, elementClassName: string) {
|
||||
return new RegExp('(\\s|^)' + elementClassName + '(\\s|$)').test(target.className);
|
||||
}
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
toggleOpen($event: any) {
|
||||
$event.preventDefault();
|
||||
document.querySelector('body').classList.toggle('sidebar-mobile-show');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the off-canvas sidebar to be closed via click.
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[appSidebarClose]'
|
||||
})
|
||||
export class SidebarOffCanvasCloseDirective {
|
||||
constructor() { }
|
||||
|
||||
// Check if element has class
|
||||
private hasClass(target: any, elementClassName: string) {
|
||||
return new RegExp('(\\s|^)' + elementClassName + '(\\s|$)').test(target.className);
|
||||
}
|
||||
|
||||
// Toggle element class
|
||||
private toggleClass(elem: any, elementClassName: string) {
|
||||
let newClass = ' ' + elem.className.replace( /[\t\r\n]/g, ' ' ) + ' ';
|
||||
if (this.hasClass(elem, elementClassName)) {
|
||||
while (newClass.indexOf(' ' + elementClassName + ' ') >= 0 ) {
|
||||
newClass = newClass.replace( ' ' + elementClassName + ' ' , ' ' );
|
||||
}
|
||||
elem.className = newClass.replace(/^\s+|\s+$/g, '');
|
||||
} else {
|
||||
elem.className += ' ' + elementClassName;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
toggleOpen($event: any) {
|
||||
$event.preventDefault();
|
||||
|
||||
if (this.hasClass(document.querySelector('body'), 'sidebar-off-canvas')) {
|
||||
this.toggleClass(document.querySelector('body'), 'sidebar-opened');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const SIDEBAR_TOGGLE_DIRECTIVES = [
|
||||
SidebarToggleDirective,
|
||||
SidebarMinimizeDirective,
|
||||
SidebarOffCanvasCloseDirective,
|
||||
MobileSidebarToggleDirective
|
||||
];
|
3
src/app/shared/transaction-result.component.html
Normal file
3
src/app/shared/transaction-result.component.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<td>{{transaction.seller}}</td>
|
||||
<td>{{transaction.value | currency:'GBP':true:'1.2-2' }}</td>
|
||||
<td>{{transactionDate}}</td>
|
21
src/app/shared/transaction-result.component.ts
Normal file
21
src/app/shared/transaction-result.component.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import * as moment from 'moment';
|
||||
|
||||
interface TransactionData {
|
||||
seller: number;
|
||||
value: string;
|
||||
purchase_time: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: '[transaction-result]',
|
||||
templateUrl: 'transaction-result.component.html',
|
||||
})
|
||||
export class TransactionResultComponent implements OnInit {
|
||||
@Input() public transaction: TransactionData;
|
||||
public transactionDate: string;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.transactionDate = moment(this.transaction.purchase_time).format('llll');
|
||||
}
|
||||
}
|
22
src/app/snippets/org-snippet-bar.component.html
Normal file
22
src/app/snippets/org-snippet-bar.component.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<div class="card">
|
||||
<div class="card-footer">
|
||||
<ul>
|
||||
<li class="hidden-sm-down">
|
||||
<div class="text-muted">Customers This Month</div>
|
||||
<strong>{{ thisMonthSalesCount }}</strong>
|
||||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
<div class="text-muted">Money Spent This Month</div>
|
||||
<strong>{{ thisMonthPurchasesTotal | currency:'GBP':true:'1.2-2'}}</strong>
|
||||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
<div class="text-muted">Customers Today</div>
|
||||
<strong>{{ todaySalesCount }}</strong>
|
||||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
<div class="text-muted">Average Transaction Today</div>
|
||||
<strong>{{ ( todaySalesTotal / todaySalesCount ) || 0 | currency:'GBP':true:'1.2-2'}}</strong>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue