From 142654ed6d11e1cb9afc7c5036abef644e1ddbd0 Mon Sep 17 00:00:00 2001 From: Spencer Ofwiti Date: Sat, 5 Dec 2020 09:29:59 +0300 Subject: [PATCH] Add mock backend. --- src/app/_helpers/array-sum.ts | 5 + src/app/_helpers/index.ts | 2 + src/app/_helpers/mock-backend.ts | 219 +++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 src/app/_helpers/array-sum.ts create mode 100644 src/app/_helpers/index.ts create mode 100644 src/app/_helpers/mock-backend.ts diff --git a/src/app/_helpers/array-sum.ts b/src/app/_helpers/array-sum.ts new file mode 100644 index 0000000..44b6856 --- /dev/null +++ b/src/app/_helpers/array-sum.ts @@ -0,0 +1,5 @@ +export class ArraySum { + static arraySum(arr: any[]): number { + return arr.reduce((accumulator, current) => accumulator + current, 0); + } +} diff --git a/src/app/_helpers/index.ts b/src/app/_helpers/index.ts new file mode 100644 index 0000000..2786ec6 --- /dev/null +++ b/src/app/_helpers/index.ts @@ -0,0 +1,2 @@ +export * from './mock-backend'; +export * from './array-sum'; diff --git a/src/app/_helpers/mock-backend.ts b/src/app/_helpers/mock-backend.ts new file mode 100644 index 0000000..7977c1e --- /dev/null +++ b/src/app/_helpers/mock-backend.ts @@ -0,0 +1,219 @@ +import {HTTP_INTERCEPTORS, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {Observable, of, throwError} from 'rxjs'; +import {delay, dematerialize, materialize, mergeMap} from 'rxjs/operators'; + +const accounts = [ + {id: 1, name: 'John Doe', phone: '+25412345678', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'user', created: '08/16/2020', balance: '12987', failedPinAttempts: 1, status: 'approved', bio: 'Bodaboda', category: 'transport', gender: 'male', location: 'Bofu', token: 'RSV', referrer: 'Jane Buck'}, + {id: 2, name: 'Jane Buck', phone: '+25412341234', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'vendor', created: '04/02/2020', balance: '56281', failedPinAttempts: 0, status: 'approved', bio: 'Groceries', category: 'food/water', gender: 'female', location: 'Lindi', token: 'ERN', referrer: ''}, + {id: 3, name: 'Mc Donald', phone: '+25498765432', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'group', created: '11/16/2020', balance: '450', failedPinAttempts: 2, status: 'unapproved', bio: 'Food', category: 'food/water', gender: 'male', location: 'Miyani', token: 'RSV', referrer: 'Hera Cles'}, + {id: 4, name: 'Hera Cles', phone: '+25498769876', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'user', created: '05/28/2020', balance: '5621', failedPinAttempts: 3, status: 'approved', bio: 'Shop', category: 'shop', gender: 'female', location: 'Kayaba', token: 'BRT', referrer: 'Jane Buck'}, + {id: 5, name: 'Silver Fia', phone: '+25462518374', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'tokenAgent', created: '10/10/2020', balance: '817', failedPinAttempts: 0, status: 'unapproved', bio: 'Electronics', category: 'shop', gender: 'male', location: 'Mkanyeni', token: 'RSV', referrer: 'John Doe'}, +]; + +const actions = [ + { id: 1, user: 'Tom', role: 'enroller', action: 'Disburse RSV 100', approval: false }, + { id: 2, user: 'Christine', role: 'admin', action: 'Change user phone number', approval: true }, + { id: 3, user: 'Will', role: 'superadmin', action: 'Reclaim RSV 1000', approval: true }, + { id: 4, user: 'Vivian', role: 'enroller', action: 'Complete user profile', approval: true }, + { id: 5, user: 'Jack', role: 'enroller', action: 'Reclaim RSV 200', approval: false }, + { id: 6, user: 'Patience', role: 'enroller', action: 'Change user information', approval: false } +]; + +const histories = [ + { id: 1, userId: 3, userName: 'Mc Donald', action: 'Receive RSV 100', staff: 'Tom', timestamp: Date.now() }, + { id: 2, userId: 5, userName: 'Silver Fia', action: 'Change phone number from +25412345678 to +25498765432', staff: 'Christine', timestamp: Date.now()}, + { id: 3, userId: 4, userName: 'Hera Cles', action: 'Completed user profile', staff: 'Vivian', timestamp: Date.now() }, +]; + +const locations: any = [ + { name: 'Kwale', + districts: [ + { name: 'Kinango', + locations: [ + { name: 'Bofu', villages: ['Bofu', 'Chidzuvini', 'Mkanyeni']}, + { name: 'Mnyenzeni', villages: ['Miloeni', 'Miyani', 'Mnyenzeni', 'Vikolani', 'Vitangani']} + ] + } + ] + }, + { name: 'Nairobi', + districts: [ + { name: 'Dagorreti', + locations: [ + { name: 'Kawangware', villages: ['Congo']}, + ] + }, + { name: 'Ngong', + locations: [ + { name: 'Kibera', villages: ['Kibera', 'Lindi']}, + ] + }, + { name: 'South B', + locations: [ + { name: 'Mukuru', villages: ['Kayaba']}, + { name: 'South B', villages: ['South B']}, + ] + }, + ] + } +]; + +const staffMembers = [ + { id: 1, name: 'admin@acme.org', accountType: 'Admin', created: '17/11/2020', status: 'activated'}, + { id: 2, name: 'will@grassecon.org', accountType: 'SuperAdmin', created: '17/11/2020', status: 'activated'}, + { id: 3, name: 'spence@grassecon.org', accountType: 'Enroller', created: '17/11/2020', status: 'activated'}, + { id: 4, name: 'admin@redcross.org', accountType: 'View', created: '17/11/2020', status: 'activated'} +]; + +const tokens = [ + {name: 'Giftable Reserve', symbol: 'GRZ', address: '0xa686005CE37Dce7738436256982C3903f2E4ea8E', supply: '1000000001000000000000000000', decimals: '18', reserves: {}}, + {name: 'Demo Token', symbol: 'DEMO', address: '0xc80D6aFF8194114c52AEcD84c9f15fd5c8abb187', supply: '99999999999999998976', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '99999999999999998976'}}, reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'}, + {name: 'Foo Token', symbol: 'FOO', address: '0x9ceD86089f7aBB5A97B40eb0E7521e7aa308d354', supply: '1000000000000000001014', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '1000000000000000001014'}}, reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'}, + {name: 'testb', symbol: 'tstb', address: '0xC63cFA91A3BFf41cE31Ff436f67D3ACBC977DB95', supply: '99000', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '99000'}}, reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'}, + {name: 'testa', symbol: 'tsta', address: '0x8fA4101ef19D0a078239d035659e92b278bD083C', supply: '9981', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '9981'}}, reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'}, + {name: 'testc', symbol: 'tstc', address: '0x4A6fA6bc3BfE4C9661bC692D9798425350C9e3D4', supply: '100990', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '100990'}}, reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'} +]; + +@Injectable() +export class MockBackendInterceptor implements HttpInterceptor { + intercept(request: HttpRequest, next: HttpHandler): Observable> { + const { url, method, headers, body } = request; + + // wrap in delayed observable to simulate server api call\ + // call materialize and dematerialize to ensure delay even is thrown + return of(null) + .pipe(mergeMap(handleRoute)) + .pipe(materialize()) + .pipe(delay(500)) + .pipe(dematerialize()); + + function handleRoute(): Observable { + switch (true) { + case url.endsWith('/accounts') && method === 'GET': + return getAccounts(); + case url.match(/\/accounts\/\d+$/) && method === 'GET': + return getAccountById(); + case url.endsWith('/actions') && method === 'GET': + return getActions(); + case url.match(/\/actions\/\d+$/) && method === 'GET': + return getActionById(); + case url.match(/\/actions\/\d+$/) && method === 'POST': + return approveAction(); + case url.match(/\/history\/\d+$/) && method === 'GET': + return getHistoryByUser(); + case url.endsWith('/locations') && method === 'GET': + return getLocations(); + case url.endsWith('/staff') && method === 'GET': + return getStaff(); + case url.match(/\/staff\/\d+$/) && method === 'GET': + return getStaffById(); + case url.match(/\/staff\/\d+$/) && method === 'POST' && body.status !== undefined: + return changeStaffStatus(); + case url.match(/\/staff\/\d+$/) && method === 'POST' && body.accountType !== undefined: + return changeStaffType(); + case url.endsWith('/tokens') && method === 'GET': + return getTokens(); + case url.match(/\/tokens\/\w+$/) && method === 'GET': + return getTokenBySymbol(); + default: + // pass through any requests not handled above + return next.handle(request); + } + } + + // route functions + + function getAccounts(): Observable { + return ok(accounts); + } + + function getAccountById(): Observable { + const queriedAccount = accounts.find(account => account.id === idFromUrl()); + return ok(queriedAccount); + } + + function getActions(): Observable { + return ok(actions); + } + + function getActionById(): Observable { + const queriedAction = actions.find(action => action.id === idFromUrl()); + return ok(queriedAction); + } + + function approveAction(): Observable { + const queriedAction = actions.find(action => action.id === idFromUrl()); + queriedAction.approval = body.approval; + const message = `Action approval status set to ${body.approval} successfully!`; + return ok(message); + } + + function getHistoryByUser(): Observable { + const queriedUserHistory = histories.filter(history => history.userId === idFromUrl()); + return ok(queriedUserHistory); + } + + function getLocations(): Observable { + return ok(locations); + } + + function getStaff(): Observable { + return ok(staffMembers); + } + + function getStaffById(): Observable { + const queriedStaff = staffMembers.find(staff => staff.id === idFromUrl()); + return ok(queriedStaff); + } + + function changeStaffStatus(): Observable { + const queriedStaff = staffMembers.find(staff => staff.id === idFromUrl()); + queriedStaff.status = body.status; + const message = `Staff account status changed to ${body.status} successfully!`; + return ok(message); + } + + function changeStaffType(): Observable { + const queriedStaff = staffMembers.find(staff => staff.id === idFromUrl()); + queriedStaff.accountType = body.accountType; + const message = `Staff account type changed to ${body.accountType} successfully!`; + return ok(message); + } + + function getTokens(): Observable { + return ok(tokens); + } + + function getTokenBySymbol(): Observable { + const queriedToken = tokens.find(token => token.symbol === stringFromUrl()); + return ok(queriedToken); + } + + // helper functions + + function ok(body): Observable { + return of(new HttpResponse({ status: 200, body })); + } + + function error(message): Observable { + return throwError({ status: 400, error: { message } }); + } + + function idFromUrl(): number { + const urlParts = url.split('/'); + return parseInt(urlParts[urlParts.length - 1], 10); + } + + function stringFromUrl(): string { + const urlParts = url.split('/'); + return urlParts[urlParts.length - 1]; + } + } +} + +export const MockBackendProvider = { + provide: HTTP_INTERCEPTORS, + useClass: MockBackendInterceptor, + multi: true +};