Add querying of location mappings and categories from API endpoint.

- Implement stub in mock backend for testing purposes.
This commit is contained in:
Spencer Ofwiti 2021-04-28 15:53:25 +03:00
parent 9e03990334
commit 292b64c1e0
7 changed files with 304 additions and 201 deletions

View File

@ -3,14 +3,6 @@ import {Injectable} from '@angular/core';
import {Observable, of, throwError} from 'rxjs'; import {Observable, of, throwError} from 'rxjs';
import {delay, dematerialize, materialize, mergeMap} from 'rxjs/operators'; import {delay, dematerialize, materialize, mergeMap} from 'rxjs/operators';
const accounts = [
{id: 1, name: 'John Doe', phone: '+25412345678', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'user', age: 43, created: '08/16/2020', balance: '12987', failedPinAttempts: 1, status: 'active', bio: 'Bodaboda', category: 'transport', gender: 'male', location: 'Bofu', locationType: 'Rural', token: 'RSV', referrer: '+25412341234'},
{id: 2, name: 'Jane Buck', phone: '+25412341234', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9866', type: 'vendor', age: 25, created: '04/02/2020', balance: '56281', failedPinAttempts: 0, status: 'active', bio: 'Groceries', category: 'food/water', gender: 'female', location: 'Lindi', locationType: 'Urban', token: 'ERN', referrer: ''},
{id: 3, name: 'Mc Donald', phone: '+25498765432', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9867', type: 'group', age: 31, created: '11/16/2020', balance: '450', failedPinAttempts: 2, status: 'blocked', bio: 'Food', category: 'food/water', gender: 'male', location: 'Miyani', locationType: 'Rural', token: 'RSV', referrer: '+25498769876'},
{id: 4, name: 'Hera Cles', phone: '+25498769876', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9868', type: 'user', age: 38, created: '05/28/2020', balance: '5621', failedPinAttempts: 3, status: 'active', bio: 'Shop', category: 'shop', gender: 'female', location: 'Kayaba', locationType: 'Urban', token: 'BRT', referrer: '+25412341234'},
{id: 5, name: 'Silver Fia', phone: '+25462518374', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9869', type: 'tokenAgent', age: 19, created: '10/10/2020', balance: '817', failedPinAttempts: 0, status: 'blocked', bio: 'Electronics', category: 'shop', gender: 'male', location: 'Mkanyeni', locationType: 'Rural', token: 'RSV', referrer: '+25412345678'},
];
const actions = [ const actions = [
{ id: 1, user: 'Tom', role: 'enroller', action: 'Disburse RSV 100', approval: false }, { 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: 2, user: 'Christine', role: 'admin', action: 'Change user phone number', approval: true },
@ -20,59 +12,222 @@ const actions = [
{ id: 6, user: 'Patience', role: 'enroller', action: 'Change user information', approval: false } { id: 6, user: 'Patience', role: 'enroller', action: 'Change user information', approval: false }
]; ];
const histories = [ const tokens = [
{ 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()}, name: 'Giftable Reserve', symbol: 'GRZ', address: '0xa686005CE37Dce7738436256982C3903f2E4ea8E', supply: '1000000001000000000000000000',
{ id: 3, userId: 4, userName: 'Hera Cles', action: 'Completed user profile', staff: 'Vivian', timestamp: Date.now() }, decimals: '18', reserves: {}
];
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: 'Demo Token', symbol: 'DEMO', address: '0xc80D6aFF8194114c52AEcD84c9f15fd5c8abb187', supply: '99999999999999998976',
{ name: 'Dagorreti', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '99999999999999998976'}},
locations: [ reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'
{ name: 'Kawangware', villages: ['Congo']}, },
] {
}, name: 'Foo Token', symbol: 'FOO', address: '0x9ceD86089f7aBB5A97B40eb0E7521e7aa308d354', supply: '1000000000000000001014',
{ name: 'Ngong', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '1000000000000000001014'}},
locations: [ reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'
{ name: 'Kibera', villages: ['Kibera', 'Lindi']}, },
] {
}, name: 'testb', symbol: 'tstb', address: '0xC63cFA91A3BFf41cE31Ff436f67D3ACBC977DB95', supply: '99000', decimals: '18',
{ name: 'South B', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '99000'}}, reserveRatio: '1000000',
locations: [ owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'
{ name: 'Mukuru', villages: ['Kayaba']}, },
{ name: 'South B', villages: ['South B']}, {
] 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'
} }
]; ];
const staffMembers = [ const categories = [
{ 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'}, name: 'system',
{ id: 3, name: 'spence@grassecon.org', accountType: 'Enroller', created: '17/11/2020', status: 'activated'}, products: ['system', 'office main', 'office main phone']
{ id: 4, name: 'admin@redcross.org', accountType: 'View', created: '17/11/2020', status: 'activated'} },
{
name: 'education',
products: ['book', 'coach', 'teacher', 'sch', 'school', 'pry', 'education', 'student', 'mwalimu', 'maalim', 'consultant', 'consult',
'college', 'university', 'lecturer', 'primary', 'secondary', 'daycare', 'babycare', 'baby care', 'elim', 'eimu', 'nursery',
'red cross', 'volunteer', 'instructor', 'journalist', 'lesson', 'academy', 'headmistress', 'headteacher', 'cyber', 'researcher',
'professor', 'demo', 'expert', 'tution', 'tuition', 'children', 'headmaster', 'educator', 'Marital counsellor', 'counsellor',
'trainer', 'vijana', 'youth', 'intern', 'redcross', 'KRCS', 'danish', 'science', 'data', 'facilitator', 'vitabu', 'kitabu']
},
{
name: 'faith',
products: ['pastor', 'imam', 'madrasa', 'religous', 'religious', 'ustadh', 'ustadhi', 'Marital counsellor', 'counsellor', 'church',
'kanisa', 'mksiti', 'donor']
},
{
name: 'government',
products: ['elder', 'chief', 'police', 'government', 'country', 'county', 'soldier', 'village admin', 'ward', 'leader', 'kra',
'mailman', 'immagration', 'immigration']
},
{
name: 'environment',
products: ['conservation', 'toilet', 'choo', 'garbage', 'fagio', 'waste', 'tree', 'taka', 'scrap', 'cleaning', 'gardener', 'rubbish',
'usafi', 'mazingira', 'miti', 'trash', 'cleaner', 'plastic', 'collection', 'seedling', 'seedlings', 'recycling']
},
{
name: 'farming',
products: ['farm', 'farmer', 'farming', 'mkulima', 'kulima', 'ukulima', 'wakulima', 'jembe', 'shamba']
},
{
name: 'labour',
products: ['artist', 'agent', 'guard', 'askari', 'accountant', 'baker', 'beadwork', 'beauty', 'business', 'barber', 'casual',
'electrian', 'caretaker', 'car wash', 'capenter', 'construction', 'chef', 'catering', 'cobler', 'cobbler', 'carwash', 'dhobi',
'landlord', 'design', 'carpenter', 'fundi', 'hawking', 'hawker', 'househelp', 'hsehelp', 'house help', 'help', 'housegirl', 'kushona',
'juakali', 'jualikali', 'juacali', 'jua kali', 'shepherd', 'makuti', 'kujenga', 'kinyozi', 'kazi', 'knitting', 'kufua', 'fua',
'hustler', 'biashara', 'labour', 'labor', 'laundry', 'repair', 'hair', 'posho', 'mill', 'mtambo', 'uvuvi', 'engineer', 'manager',
'tailor', 'nguo', 'mason', 'mtumba', 'garage', 'mechanic', 'mjenzi', 'mfugaji', 'painter', 'receptionist', 'printing', 'programming',
'plumb', 'charging', 'salon', 'mpishi', 'msusi', 'mgema', 'footballer', 'photocopy', 'peddler', 'staff', 'sales', 'service', 'saloon',
'seremala', 'security', 'insurance', 'secretary', 'shoe', 'shepard', 'shephard', 'tout', 'tv', 'mvuvi', 'mawe', 'majani', 'maembe',
'freelance', 'mjengo', 'electronics', 'photographer', 'programmer', 'electrician', 'washing', 'bricks', 'welder', 'welding',
'working', 'worker', 'watchman', 'waiter', 'waitress', 'viatu', 'yoga', 'guitarist', 'house', 'artisan', 'musician', 'trade',
'makonge', 'ujenzi', 'vendor', 'watchlady', 'marketing', 'beautician', 'photo', 'metal work', 'supplier', 'law firm', 'brewer']
},
{
name: 'food',
products: ['avocado', 'bhajia', 'bajia', 'mbonga', 'bofu', 'beans', 'biscuits', 'biringanya', 'banana', 'bananas', 'crisps', 'chakula',
'coconut', 'chapati', 'cereal', 'chipo', 'chapo', 'chai', 'chips', 'cassava', 'cake', 'cereals', 'cook', 'corn', 'coffee', 'chicken',
'dagaa', 'donut', 'dough', 'groundnuts', 'hotel', 'holel', 'hoteli', 'butcher', 'butchery', 'fruit', 'food', 'fruits', 'fish',
'githeri', 'grocery', 'grocer', 'pojo', 'papa', 'goats', 'mabenda', 'mbenda', 'poultry', 'soda', 'peanuts', 'potatoes', 'samosa',
'soko', 'samaki', 'tomato', 'tomatoes', 'mchele', 'matunda', 'mango', 'melon', 'mellon', 'nyanya', 'nyama', 'omena', 'umena', 'ndizi',
'njugu', 'kamba kamba', 'khaimati', 'kaimati', 'kunde', 'kuku', 'kahawa', 'keki', 'muguka', 'miraa', 'milk', 'choma', 'maziwa',
'mboga', 'mbog', 'busaa', 'chumvi', 'cabbages', 'mabuyu', 'machungwa', 'mbuzi', 'mnazi', 'mchicha', 'ngombe', 'ngano', 'nazi',
'oranges', 'peanuts', 'mkate', 'bread', 'mikate', 'vitungu', 'sausages', 'maize', 'mbata', 'mchuzi', 'mchuuzi', 'mandazi', 'mbaazi',
'mahindi', 'maandazi', 'mogoka', 'meat', 'mhogo', 'mihogo', 'muhogo', 'maharagwe', 'miwa', 'mahamri', 'mitumba', 'simsim', 'porridge',
'pilau', 'vegetable', 'egg', 'mayai', 'mifugo', 'unga', 'good', 'sima', 'sweet', 'sweats', 'sambusa', 'snacks', 'sugar', 'suger',
'ugoro', 'sukari', 'soup', 'spinach', 'smokie', 'smokies', 'sukuma', 'tea', 'uji', 'ugali', 'uchuzi', 'uchuuzi', 'viazi', 'yoghurt',
'yogurt', 'wine', 'marondo', 'maandzi', 'matoke', 'omeno', 'onions', 'nzugu', 'korosho', 'barafu', 'juice']
},
{
name: 'water',
products: ['maji', 'water']
},
{
name: 'health',
products: ['agrovet', 'dispensary', 'barakoa', 'chemist', 'Chemicals', 'chv', 'doctor', 'daktari', 'dawa', 'hospital', 'herbalist',
'mganga', 'sabuni', 'soap', 'nurse', 'heath', 'community health worker', 'clinic', 'clinical', 'mask', 'medicine', 'lab technician',
'pharmacy', 'cosmetics', 'veterinary', 'vet', 'sickly', 'emergency response', 'emergency']
},
{
name: 'savings',
products: ['chama', 'group', 'savings', 'loan', 'silc', 'vsla', 'credit', 'finance']
},
{
name: 'shop',
products: ['bag', 'bead', 'belt', 'bedding', 'jik', 'bed', 'cement', 'botique', 'boutique', 'lines', 'kibanda', 'kiosk', 'spareparts',
'candy', 'cloth', 'electricals', 'mutumba', 'cafe', 'leso', 'lesso', 'duka', 'spare parts', 'socks', 'malimali', 'mitungi',
'mali mali', 'hardware', 'detergent', 'detergents', 'dera', 'retail', 'kamba', 'pombe', 'pampers', 'pool', 'phone', 'simu', 'mangwe',
'mikeka', 'movie', 'shop', 'acces', 'mchanga', 'uto', 'airtime', 'matress', 'mattress', 'mattresses', 'mpsea', 'mpesa', 'shirt',
'wholesaler', 'perfume', 'playstation', 'tissue', 'vikapu', 'uniform', 'flowers', 'vitenge', 'utencils', 'utensils', 'station',
'jewel', 'pool table', 'club', 'pub', 'bar', 'furniture', 'm-pesa', 'vyombo']
},
{
name: 'transport',
products: ['kebeba', 'beba', 'bebabeba', 'bike', 'bicycle', 'matatu', 'boda', 'bodaboda', 'cart', 'carrier', 'tour', 'travel', 'driver',
'dereva', 'tout', 'conductor', 'kubeba', 'tuktuk', 'taxi', 'piki', 'pikipiki', 'manamba', 'trasportion', 'mkokoteni', 'mover',
'motorist', 'motorbike', 'transport', 'transpoter', 'gari', 'magari', 'makanga', 'car']
},
{
name: 'fuel/energy',
products: ['timber', 'timberyard', 'biogas', 'charcol', 'charcoal', 'kuni', 'mbao', 'fuel', 'makaa', 'mafuta', 'moto', 'solar', 'stima',
'fire', 'firewood', 'wood', 'oil', 'taa', 'gas', 'paraffin', 'parrafin', 'parafin', 'petrol', 'petro', 'kerosine', 'kerosene',
'diesel']
},
{
name: 'other',
products: ['other', 'none', 'unknown', 'none']
}
]; ];
const tokens = [ const areaNames = [
{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: 'Mukuru Nairobi',
{name: 'Foo Token', symbol: 'FOO', address: '0x9ceD86089f7aBB5A97B40eb0E7521e7aa308d354', supply: '1000000000000000001014', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '1000000000000000001014'}}, reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'}, locations: ['kayaba', 'kayba', 'kambi', 'mukuru', 'masai', 'hazina', 'south', 'tetra', 'tetrapak', 'ruben', 'rueben', 'kingston',
{name: 'testb', symbol: 'tstb', address: '0xC63cFA91A3BFf41cE31Ff436f67D3ACBC977DB95', supply: '99000', decimals: '18', reserves: {'0xa686005CE37Dce7738436256982C3903f2E4ea8E': {weight: '1000000', balance: '99000'}}, reserveRatio: '1000000', owner: '0x3Da99AAD2D9CA01D131eFc3B17444b832B31Ff4a'}, 'korokocho', 'kingstone', 'kamongo', 'lungalunga', 'sinai', 'sigei', 'lungu', 'lunga lunga', 'owino road', 'seigei']
{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'} {
name: 'Kinango Kwale',
locations: ['amani', 'bofu', 'chibuga', 'chikomani', 'chilongoni', 'chigojoni', 'chinguluni', 'chigato', 'chigale', 'chikole',
'chilongoni', 'chilumani', 'chigojoni', 'chikomani', 'chizini', 'chikomeni', 'chidzuvini', 'chidzivuni', 'chikuyu', 'chizingo',
'doti', 'dzugwe', 'dzivani', 'dzovuni', 'hanje', 'kasemeni', 'katundani', 'kibandaogo', 'kibandaongo', 'kwale', 'kinango',
'kidzuvini', 'kalalani', 'kafuduni', 'kaloleni', 'kilibole', 'lutsangani', 'peku', 'gona', 'guro', 'gandini', 'mkanyeni', 'myenzeni',
'miyenzeni', 'miatsiani', 'mienzeni', 'mnyenzeni', 'minyenzeni', 'miyani', 'mioleni', 'makuluni', 'mariakani', 'makobeni', 'madewani',
'mwangaraba', 'mwashanga', 'miloeni', 'mabesheni', 'mazeras', 'mazera', 'mlola', 'muugano', 'mulunguni', 'mabesheni', 'miatsani',
'miatsiani', 'mwache', 'mwangani', 'mwehavikonje', 'miguneni', 'nzora', 'nzovuni', 'vikinduni', 'vikolani', 'vitangani', 'viogato',
'vyogato', 'vistangani', 'yapha', 'yava', 'yowani', 'ziwani', 'majengo', 'matuga', 'vigungani', 'vidziweni', 'vinyunduni', 'ukunda',
'kokotoni', 'mikindani']
},
{
name: 'Misc Nairobi',
locations: ['nairobi', 'west', 'lindi', 'kibera', 'kibira', 'kibra', 'makina', 'soweto', 'olympic', 'kangemi', 'ruiru', 'congo',
'kawangware', 'kwangware', 'donholm', 'dagoreti', 'dandora', 'kabete', 'sinai', 'donhom', 'donholm', 'huruma', 'kitengela',
'makadara', ',mlolongo', 'kenyatta', 'mlolongo', 'tassia', 'tasia', 'gatina', '56', 'industrial', 'kariobangi', 'kasarani', 'kayole',
'mathare', 'pipe', 'juja', 'uchumi', 'jogoo', 'umoja', 'thika', 'kikuyu', 'stadium', 'buru buru', 'ngong', 'starehe', 'mwiki',
'fuata', 'kware', 'kabiro', 'embakassi', 'embakasi', 'kmoja', 'east', 'githurai', 'landi', 'langata', 'limuru', 'mathere',
'dagoretti', 'kirembe', 'muugano', 'mwiki', 'toi market']
},
{
name: 'Misc Mombasa',
locations: ['mombasa', 'likoni', 'bangla', 'bangladesh', 'kizingo', 'old town', 'makupa', 'mvita', 'ngombeni', 'ngómbeni', 'ombeni',
'magongo', 'miritini', 'changamwe', 'jomvu', 'ohuru', 'tudor', 'diani']
},
{
name: 'Kisauni',
locations: ['bamburi', 'kisauni', 'mworoni', 'nyali', 'shanzu', 'bombolulu', 'mtopanga', 'mjambere', 'majaoni', 'manyani', 'magogoni',
'junda', 'mwakirunge', 'mshomoroni']
},
{
name: 'Kilifi',
locations: ['kilfi', 'kilifi', 'mtwapa', 'takaungu', 'makongeni', 'mnarani', 'mnarani', 'office', 'g.e', 'ge', 'raibai', 'ribe']
},
{
name: 'Kakuma',
locations: ['kakuma']
},
{
name: 'Kitui',
locations: ['kitui', 'mwingi']
},
{
name: 'Nyanza',
locations: ['busia', 'nyalgunga', 'mbita', 'siaya', 'kisumu', 'nyalenda', 'hawinga', 'rangala', 'uyoma', 'mumias', 'homabay', 'homaboy',
'migori', 'kusumu']
},
{
name: 'Misc Rural Counties',
locations: ['makueni', 'meru', 'kisii', 'bomet', 'machakos', 'bungoma', 'eldoret', 'kakamega', 'kericho', 'kajiado', 'nandi', 'nyeri',
'wote', 'kiambu', 'mwea', 'nakuru', 'narok']
},
{
name: 'other',
locations: ['other', 'none', 'unknown']
}
];
const areaTypes = [
{
name: 'urban',
area: ['urban', 'nairobi', 'mombasa']
},
{
name: 'rural',
area: ['rural', 'kakuma', 'kwale', 'kinango', 'kitui', 'nyanza']
},
{
name: 'periurban',
area: ['kilifi', 'periurban']
},
{
name: 'other',
area: ['other']
}
]; ];
@Injectable() @Injectable()
@ -90,32 +245,28 @@ export class MockBackendInterceptor implements HttpInterceptor {
function handleRoute(): Observable<any> { function handleRoute(): Observable<any> {
switch (true) { 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': case url.endsWith('/actions') && method === 'GET':
return getActions(); return getActions();
case url.match(/\/actions\/\d+$/) && method === 'GET': case url.match(/\/actions\/\d+$/) && method === 'GET':
return getActionById(); return getActionById();
case url.match(/\/actions\/\d+$/) && method === 'POST': case url.match(/\/actions\/\d+$/) && method === 'POST':
return approveAction(); 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': case url.endsWith('/tokens') && method === 'GET':
return getTokens(); return getTokens();
case url.match(/\/tokens\/\w+$/) && method === 'GET': case url.match(/\/tokens\/\w+$/) && method === 'GET':
return getTokenBySymbol(); return getTokenBySymbol();
case url.endsWith('/categories') && method === 'GET':
return getCategories();
case url.match(/\/categories\/\w+$/) && method === 'GET':
return getCategoryByProduct();
case url.endsWith('/areanames') && method === 'GET':
return getAreaNames();
case url.match(/\/areanames\/\w+$/) && method === 'GET':
return getAreaNameByLocation();
case url.endsWith('/areatypes') && method === 'GET':
return getAreaTypes();
case url.match(/\/areatypes\/\w+$/) && method === 'GET':
return getAreaTypeByArea();
default: default:
// pass through any requests not handled above // pass through any requests not handled above
return next.handle(request); return next.handle(request);
@ -124,15 +275,6 @@ export class MockBackendInterceptor implements HttpInterceptor {
// route functions // route functions
function getAccounts(): Observable<any> {
return ok(accounts);
}
function getAccountById(): Observable<any> {
const queriedAccount = accounts.find(account => account.id === idFromUrl());
return ok(queriedAccount);
}
function getActions(): Observable<any> { function getActions(): Observable<any> {
return ok(actions); return ok(actions);
} }
@ -149,38 +291,6 @@ export class MockBackendInterceptor implements HttpInterceptor {
return ok(message); return ok(message);
} }
function getHistoryByUser(): Observable<any> {
const queriedUserHistory = histories.filter(history => history.userId === idFromUrl());
return ok(queriedUserHistory);
}
function getLocations(): Observable<any> {
return ok(locations);
}
function getStaff(): Observable<any> {
return ok(staffMembers);
}
function getStaffById(): Observable<any> {
const queriedStaff = staffMembers.find(staff => staff.id === idFromUrl());
return ok(queriedStaff);
}
function changeStaffStatus(): Observable<any> {
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<any> {
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<any> { function getTokens(): Observable<any> {
return ok(tokens); return ok(tokens);
} }
@ -190,6 +300,36 @@ export class MockBackendInterceptor implements HttpInterceptor {
return ok(queriedToken); return ok(queriedToken);
} }
function getCategories(): Observable<any> {
const categoryList = categories.map(category => category.name);
return ok(categoryList);
}
function getCategoryByProduct(): Observable<any> {
const queriedCategory = categories.find(category => category.products.includes(stringFromUrl()));
return ok(queriedCategory.name);
}
function getAreaNames(): Observable<any> {
const areaNameList = areaNames.map(areaName => areaName.name);
return ok(areaNameList);
}
function getAreaNameByLocation(): Observable<any> {
const queriedAreaName = areaNames.find(areaName => areaName.locations.includes(stringFromUrl()));
return ok(queriedAreaName.name);
}
function getAreaTypes(): Observable<any> {
const areaTypeList = areaTypes.map(areaType => areaType.name);
return ok(areaTypeList);
}
function getAreaTypeByArea(): Observable<any> {
const queriedAreaType = areaTypes.find(areaType => areaType.area.includes(stringFromUrl()));
return ok(queriedAreaType.name);
}
// helper functions // helper functions
function ok(body): Observable<any> { function ok(body): Observable<any> {

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import {BehaviorSubject} from 'rxjs'; import {Observable} from 'rxjs';
import {environment} from '@src/environments/environment'; import {environment} from '@src/environments/environment';
import {first} from 'rxjs/operators'; import {first} from 'rxjs/operators';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
@ -8,15 +8,24 @@ import {HttpClient} from '@angular/common/http';
providedIn: 'root' providedIn: 'root'
}) })
export class LocationService { export class LocationService {
locations: any = '';
private locationsList = new BehaviorSubject<any>(this.locations);
locationsSubject = this.locationsList.asObservable();
constructor( constructor(
private httpClient: HttpClient, private httpClient: HttpClient,
) { } ) { }
getLocations(): void { getAreaNames(): Observable<any> {
this.httpClient.get(`${environment.cicCacheUrl}/locations`).pipe(first()).subscribe(res => this.locationsList.next(res)); return this.httpClient.get(`${environment.cicCacheUrl}/areanames`);
}
getAreaNameByLocation(location: string): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/areanames/${location.toLowerCase()}`);
}
getAreaTypes(): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/areatypes`).pipe(first());
}
getAreaTypeByArea(area: string): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/areatypes/${area.toLowerCase()}`).pipe(first());
} }
} }

View File

@ -117,14 +117,6 @@ export class UserService {
}); });
} }
getAccounts(): void {
this.httpClient.get(`${environment.cicCacheUrl}/accounts`).pipe(first()).subscribe(res => this.accountsList.next(res));
}
getAccountById(id: number): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/accounts/${id}`);
}
getActions(): void { getActions(): void {
this.httpClient.get(`${environment.cicCacheUrl}/actions`).pipe(first()).subscribe(res => this.actionsList.next(res)); this.httpClient.get(`${environment.cicCacheUrl}/actions`).pipe(first()).subscribe(res => this.actionsList.next(res));
} }
@ -141,21 +133,10 @@ export class UserService {
return this.httpClient.post(`${environment.cicCacheUrl}/actions/${id}`, { approval: false }); return this.httpClient.post(`${environment.cicCacheUrl}/actions/${id}`, { approval: false });
} }
getHistoryByUser(id: string): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/history/${id}`);
}
getAccountDetailsFromMeta(userKey: string): Observable<any> { getAccountDetailsFromMeta(userKey: string): Observable<any> {
return this.httpClient.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers }); return this.httpClient.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers });
} }
getUser(userKey: string): any {
return this.httpClient.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers })
.pipe(first()).subscribe(async res => {
return Envelope.fromJSON(JSON.stringify(res)).unwrap();
});
}
wrap(syncable: Syncable, signer: Signer): Promise<Envelope> { wrap(syncable: Syncable, signer: Signer): Promise<Envelope> {
return new Promise<Envelope>(async (whohoo, doh) => { return new Promise<Envelope>(async (whohoo, doh) => {
syncable.setSigner(signer); syncable.setSigner(signer);
@ -220,4 +201,12 @@ export class UserService {
} }
searchAccountByName(name: string): any { return; } searchAccountByName(name: string): any { return; }
getCategories(): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/categories`);
}
getCategoryByProduct(product: string): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/categories/${product.toLowerCase()}`);
}
} }

View File

@ -115,16 +115,9 @@
<mat-label> BUSINESS CATEGORY: </mat-label> <mat-label> BUSINESS CATEGORY: </mat-label>
<mat-select id="businessCategory" [(value)]="account.category" formControlName="businessCategory" <mat-select id="businessCategory" [(value)]="account.category" formControlName="businessCategory"
[errorStateMatcher]="matcher"> [errorStateMatcher]="matcher">
<mat-option value="food/water">Food/Water</mat-option> <mat-option *ngFor="let category of categories" [value]="category">
<mat-option value="fuel/energy">Fuel/Energy</mat-option> {{category | titlecase}}
<mat-option value="education">Education</mat-option> </mat-option>
<mat-option value="health">Health</mat-option>
<mat-option value="shop">Shop</mat-option>
<mat-option value="environment">Environment</mat-option>
<mat-option value="transport">Transport</mat-option>
<mat-option value="farming/labour">Farming/Labour</mat-option>
<mat-option value="savings">Savings Group</mat-option>
<mat-option value="other">Savings Group</mat-option>
</mat-select> </mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.businessCategory.errors"> <mat-error *ngIf="submitted && accountInfoFormStub.businessCategory.errors">
Category is required. Category is required.
@ -149,16 +142,9 @@
<mat-label> LOCATION: </mat-label> <mat-label> LOCATION: </mat-label>
<mat-select id="location" [(value)]="account.location.area" formControlName="location" <mat-select id="location" [(value)]="account.location.area" formControlName="location"
[errorStateMatcher]="matcher"> [errorStateMatcher]="matcher">
<div *ngFor="let county of locations; trackBy: trackByName"> <mat-option *ngFor="let area of areaNames" [value]="area">
<div *ngFor="let district of county.districts; trackBy: trackByName"> {{area | uppercase}}
<mat-optgroup *ngFor="let location of district.locations; trackBy: trackByName" [label]="county.name + ' / ' + </mat-option>
district.name + ' / ' + location.name">
<mat-option *ngFor="let village of location.villages; trackBy: trackByName" [value]="village">
{{village}}
</mat-option>
</mat-optgroup>
</div>
</div>
</mat-select> </mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.location.errors">Location is required.</mat-error> <mat-error *ngIf="submitted && accountInfoFormStub.location.errors">Location is required.</mat-error>
</mat-form-field> </mat-form-field>
@ -169,10 +155,9 @@
<mat-label> LOCATION TYPE: </mat-label> <mat-label> LOCATION TYPE: </mat-label>
<mat-select id="locationType" [(value)]="account.location.area_type" formControlName="locationType" <mat-select id="locationType" [(value)]="account.location.area_type" formControlName="locationType"
[errorStateMatcher]="matcher"> [errorStateMatcher]="matcher">
<mat-option value="Urban"> URBAN </mat-option> <mat-option *ngFor="let type of areaTypes" [value]="type">
<mat-option value="Periurban"> PERIURBAN </mat-option> {{type | uppercase}}
<mat-option value="Rural"> RURAL </mat-option> </mat-option>
<mat-option value="Other"> OTHER </mat-option>
</mat-select> </mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.locationType.errors">Location Type is required.</mat-error> <mat-error *ngIf="submitted && accountInfoFormStub.locationType.errors">Location Type is required.</mat-error>
</mat-form-field> </mat-form-field>

View File

@ -37,7 +37,9 @@ export class AccountDetailsComponent implements OnInit {
accountStatus: any; accountStatus: any;
accounts: any[] = []; accounts: any[] = [];
accountsType = 'all'; accountsType = 'all';
locations: any; categories: any[];
areaNames: any[];
areaTypes: any[];
transaction: any; transaction: any;
transactions: any[]; transactions: any[];
transactionsType = 'all'; transactionsType = 'all';
@ -97,11 +99,9 @@ export class AccountDetailsComponent implements OnInit {
}); });
this.blockSyncService.blockSync(this.accountAddress); this.blockSyncService.blockSync(this.accountAddress);
}); });
this.userService.getAccounts(); this.userService.getCategories().pipe(first()).subscribe(res => this.categories = res);
this.locationService.getLocations(); this.locationService.getAreaNames().pipe(first()).subscribe(res => this.areaNames = res);
this.locationService.locationsSubject.subscribe(locations => { this.locationService.getAreaTypes().pipe(first()).subscribe(res => this.areaTypes = res);
this.locations = locations;
});
} }
ngOnInit(): void { ngOnInit(): void {
@ -186,10 +186,6 @@ export class AccountDetailsComponent implements OnInit {
}); });
} }
public trackByName(index, item): string {
return item.name;
}
downloadCsv(data: any, filename: string): void { downloadCsv(data: any, filename: string): void {
exportCsv(data, filename); exportCsv(data, filename);
} }

View File

@ -81,15 +81,9 @@
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Location: </mat-label> <mat-label>Location: </mat-label>
<mat-select id="location" formControlName="location" [errorStateMatcher]="matcher"> <mat-select id="location" formControlName="location" [errorStateMatcher]="matcher">
<div *ngFor="let county of locations; trackBy: trackByName"> <mat-option *ngFor="let area of areaNames" [value]="area">
<div *ngFor="let district of county.districts; trackBy: trackByName"> {{area | uppercase}}
<mat-optgroup *ngFor="let location of district.locations; trackBy: trackByName" [label]="county.name + ' / ' + district.name + ' / ' + location.name"> </mat-option>
<mat-option *ngFor="let village of location.villages; trackBy: trackByName" [value]="village">
{{village}}
</mat-option>
</mat-optgroup>
</div>
</div>
</mat-select> </mat-select>
<mat-error *ngIf="submitted && createFormStub.location.errors">Location is required.</mat-error> <mat-error *ngIf="submitted && createFormStub.location.errors">Location is required.</mat-error>
</mat-form-field><br> </mat-form-field><br>
@ -119,16 +113,9 @@
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Business Category: </mat-label> <mat-label>Business Category: </mat-label>
<mat-select id="businessCategory" formControlName="businessCategory" [errorStateMatcher]="matcher"> <mat-select id="businessCategory" formControlName="businessCategory" [errorStateMatcher]="matcher">
<mat-option value="food/water">Food/Water</mat-option> <mat-option *ngFor="let category of categories" [value]="category">
<mat-option value="fuel/energy">Fuel/Energy</mat-option> {{category | titlecase}}
<mat-option value="education">Education</mat-option> </mat-option>
<mat-option value="health">Health</mat-option>
<mat-option value="shop">Shop</mat-option>
<mat-option value="environment">Environment</mat-option>
<mat-option value="transport">Transport</mat-option>
<mat-option value="farming/labour">Farming/Labour</mat-option>
<mat-option value="savings">Savings Group</mat-option>
<mat-option value="other">Other</mat-option>
</mat-select> </mat-select>
<mat-error *ngIf="submitted && createFormStub.businessCategory.errors">Business Category is required.</mat-error> <mat-error *ngIf="submitted && createFormStub.businessCategory.errors">Business Category is required.</mat-error>
</mat-form-field> </mat-form-field>

View File

@ -1,7 +1,8 @@
import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core'; import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {LocationService} from '@app/_services'; import {LocationService, UserService} from '@app/_services';
import {CustomErrorStateMatcher} from '@app/_helpers'; import {CustomErrorStateMatcher} from '@app/_helpers';
import {first} from 'rxjs/operators';
@Component({ @Component({
selector: 'app-create-account', selector: 'app-create-account',
@ -13,11 +14,13 @@ export class CreateAccountComponent implements OnInit {
createForm: FormGroup; createForm: FormGroup;
matcher = new CustomErrorStateMatcher(); matcher = new CustomErrorStateMatcher();
submitted: boolean = false; submitted: boolean = false;
locations: any; categories: any[];
areaNames: any[];
constructor( constructor(
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private locationService: LocationService private locationService: LocationService,
private userService: UserService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
@ -33,10 +36,8 @@ export class CreateAccountComponent implements OnInit {
referrer: ['', Validators.required], referrer: ['', Validators.required],
businessCategory: ['', Validators.required] businessCategory: ['', Validators.required]
}); });
this.locationService.getLocations(); this.userService.getCategories().pipe(first()).subscribe(res => this.categories = res);
this.locationService.locationsSubject.subscribe(locations => { this.locationService.getAreaNames().pipe(first()).subscribe(res => this.areaNames = res);
this.locations = locations;
});
} }
get createFormStub(): any { return this.createForm.controls; } get createFormStub(): any { return this.createForm.controls; }
@ -46,8 +47,4 @@ export class CreateAccountComponent implements OnInit {
if (this.createForm.invalid || !confirm('Create account?')) { return; } if (this.createForm.invalid || !confirm('Create account?')) { return; }
this.submitted = false; this.submitted = false;
} }
public trackByName(index, item): string {
return item.name;
}
} }