From aa8d9c5c73574ba6011ee70f7ba28e612f4bb524 Mon Sep 17 00:00:00 2001
From: Spencer Ofwiti <maxspencer56@gmail.com>
Date: Mon, 9 Aug 2021 11:29:33 +0300
Subject: [PATCH 1/4] Break accounts details component onInit function into
 multiple standalone functions.

---
 src/app/_workers/fetch-accounts.worker.ts     |   2 +-
 .../account-details.component.ts              | 217 ++++++++++--------
 2 files changed, 119 insertions(+), 100 deletions(-)

diff --git a/src/app/_workers/fetch-accounts.worker.ts b/src/app/_workers/fetch-accounts.worker.ts
index 078aa80..ed11dec 100644
--- a/src/app/_workers/fetch-accounts.worker.ts
+++ b/src/app/_workers/fetch-accounts.worker.ts
@@ -29,7 +29,7 @@ addEventListener('message', async ({ data }) => {
 async function getAccountByAddress(
   accountAddress: string,
   metaUrl: string,
-  token: string,
+  token: string
 ): Promise<any> {
   const userKey = await User.toKey(add0x(accountAddress));
 
diff --git a/src/app/pages/accounts/account-details/account-details.component.ts b/src/app/pages/accounts/account-details/account-details.component.ts
index 8164c5c..85e44e7 100644
--- a/src/app/pages/accounts/account-details/account-details.component.ts
+++ b/src/app/pages/accounts/account-details/account-details.component.ts
@@ -110,19 +110,7 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
   }
 
   async ngOnInit(): Promise<void> {
-    this.accountInfoForm = this.formBuilder.group({
-      firstName: ['', Validators.required],
-      lastName: ['', Validators.required],
-      phoneNumber: ['', Validators.required],
-      age: [''],
-      type: ['', Validators.required],
-      bio: ['', Validators.required],
-      gender: ['', Validators.required],
-      businessCategory: ['', Validators.required],
-      userLocation: ['', Validators.required],
-      location: ['', Validators.required],
-      locationType: ['', Validators.required],
-    });
+    this.buildAccountsInfoForm();
     this.transactionService.resetTransactionsList();
     await this.blockSyncService.blockSync(this.accountAddress);
     this.userService.resetAccountsList();
@@ -131,35 +119,8 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
         if (res !== undefined) {
           this.account = res;
           this.cdr.detectChanges();
-          this.locationService.areaNamesSubject.subscribe((response) => {
-            this.area = this.locationService.getAreaNameByLocation(
-              this.account.location.area_name,
-              response
-            );
-            this.cdr.detectChanges();
-            this.locationService.areaTypesSubject.subscribe((result) => {
-              this.areaType = this.locationService.getAreaTypeByArea(this.area, result);
-              this.cdr.detectChanges();
-            });
-          });
-          this.userService.categoriesSubject.subscribe((result) => {
-            this.category = this.userService.getCategoryByProduct(this.account.products[0], result);
-            this.cdr.detectChanges();
-          });
-          const fullName = this.account.vcard?.fn[0].value.split(' ');
-          this.accountInfoForm.patchValue({
-            firstName: fullName[0].split(',')[0],
-            lastName: fullName.slice(1).join(' '),
-            phoneNumber: this.account.vcard?.tel[0].value,
-            age: this.account.age,
-            type: this.account.type,
-            bio: this.account.products,
-            gender: this.account.gender,
-            businessCategory: this.account.category || this.category || 'other',
-            userLocation: this.account.location.area_name,
-            location: this.account.location.area || this.area || 'other',
-            locationType: this.account.location.area_type || this.areaType || 'other',
-          });
+          this.queryLocationAndCategory(this.account);
+          this.populateAccountsInfoForm(this.account);
           this.userService
             .getAccountStatus(this.account.vcard?.tel[0].value)
             .pipe(first())
@@ -169,63 +130,8 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
         }
       }
     );
-    this.userService.accountsSubject.subscribe((accounts) => {
-      this.userDataSource = new MatTableDataSource<any>(accounts);
-      this.userDataSource.paginator = this.userTablePaginator;
-      this.userDataSource.sort = this.userTableSort;
-      this.accounts = accounts;
-      if (accounts.length > 0) {
-        this.accountsLoading = false;
-      }
-      this.cdr.detectChanges();
-    });
-
-    this.transactionService.transactionsSubject.subscribe((transactions) => {
-      this.transactionsDataSource = new MatTableDataSource<any>(transactions);
-      this.transactionsDataSource.paginator = this.transactionTablePaginator;
-      this.transactionsDataSource.sort = this.transactionTableSort;
-      this.transactions = transactions;
-      if (transactions.length > 0) {
-        this.transactionsLoading = false;
-      }
-      this.cdr.detectChanges();
-    });
-
-    this.userService.historySubject.subscribe(async (histories) => {
-      this.historyDataSource = new MatTableDataSource<any>(histories);
-      this.historyDataSource.paginator = this.historyTablePaginator;
-      this.historyDataSource.sort = this.historyTableSort;
-      this.histories = histories;
-      if (histories.length > 0) {
-        this.historyLoading = false;
-      }
-      this.cdr.detectChanges();
-    });
-
-    this.userService.getCategories();
-    this.userService.categoriesSubject.subscribe((res) => {
-      this.categories = Object.keys(res);
-    });
-    this.locationService.getAreaNames();
-    this.locationService.areaNamesSubject.subscribe((res) => {
-      this.areaNames = Object.keys(res);
-    });
-    this.locationService.getAreaTypes();
-    this.locationService.areaTypesSubject.subscribe((res) => {
-      this.areaTypes = Object.keys(res);
-    });
-    this.userService
-      .getAccountTypes()
-      .pipe(first())
-      .subscribe((res) => (this.accountTypes = res));
-    this.userService
-      .getTransactionTypes()
-      .pipe(first())
-      .subscribe((res) => (this.transactionsTypes = res));
-    this.userService
-      .getGenders()
-      .pipe(first())
-      .subscribe((res) => (this.genders = res));
+    this.populateDataTables();
+    this.loadSearchData();
     this.tokenService.load.subscribe(async (status: boolean) => {
       if (status) {
         this.tokenSymbol = await this.tokenService.getTokenSymbol();
@@ -355,4 +261,117 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
     }
     return str;
   }
+
+  buildAccountsInfoForm(): void {
+    this.accountInfoForm = this.formBuilder.group({
+      firstName: ['', Validators.required],
+      lastName: ['', Validators.required],
+      phoneNumber: ['', Validators.required],
+      age: [''],
+      type: ['', Validators.required],
+      bio: ['', Validators.required],
+      gender: ['', Validators.required],
+      businessCategory: ['', Validators.required],
+      userLocation: ['', Validators.required],
+      location: ['', Validators.required],
+      locationType: ['', Validators.required],
+    });
+  }
+
+  populateAccountsInfoForm(accountInfo: AccountDetails): void {
+    const fullName = accountInfo.vcard?.fn[0].value.split(' ');
+    this.accountInfoForm.patchValue({
+      firstName: fullName[0].split(',')[0],
+      lastName: fullName.slice(1).join(' '),
+      phoneNumber: accountInfo.vcard?.tel[0].value,
+      age: accountInfo.age,
+      type: accountInfo.type,
+      bio: accountInfo.products,
+      gender: accountInfo.gender,
+      businessCategory: accountInfo.category || this.category || 'other',
+      userLocation: accountInfo.location.area_name,
+      location: accountInfo.location.area || this.area || 'other',
+      locationType: accountInfo.location.area_type || this.areaType || 'other',
+    });
+  }
+
+  populateDataTables(): void {
+    this.userService.accountsSubject.subscribe((accounts) => {
+      this.userDataSource = new MatTableDataSource<any>(accounts);
+      this.userDataSource.paginator = this.userTablePaginator;
+      this.userDataSource.sort = this.userTableSort;
+      this.accounts = accounts;
+      if (accounts.length > 0) {
+        this.accountsLoading = false;
+      }
+      this.cdr.detectChanges();
+    });
+
+    this.transactionService.transactionsSubject.subscribe((transactions) => {
+      this.transactionsDataSource = new MatTableDataSource<any>(transactions);
+      this.transactionsDataSource.paginator = this.transactionTablePaginator;
+      this.transactionsDataSource.sort = this.transactionTableSort;
+      this.transactions = transactions;
+      if (transactions.length > 0) {
+        this.transactionsLoading = false;
+      }
+      this.cdr.detectChanges();
+    });
+
+    this.userService.historySubject.subscribe(async (histories) => {
+      this.historyDataSource = new MatTableDataSource<any>(histories);
+      this.historyDataSource.paginator = this.historyTablePaginator;
+      this.historyDataSource.sort = this.historyTableSort;
+      this.histories = histories;
+      if (histories.length > 0) {
+        this.historyLoading = false;
+      }
+      this.cdr.detectChanges();
+    });
+  }
+
+  queryLocationAndCategory(accountInfo: AccountDetails): void {
+    this.locationService.areaNamesSubject.subscribe((response) => {
+      this.area = this.locationService.getAreaNameByLocation(
+        accountInfo.location.area_name,
+        response
+      );
+      this.cdr.detectChanges();
+      this.locationService.areaTypesSubject.subscribe((result) => {
+        this.areaType = this.locationService.getAreaTypeByArea(this.area, result);
+        this.cdr.detectChanges();
+      });
+    });
+    this.userService.categoriesSubject.subscribe((result) => {
+      this.category = this.userService.getCategoryByProduct(accountInfo.products[0], result);
+      this.cdr.detectChanges();
+    });
+  }
+
+  loadSearchData(): void {
+    this.userService.getCategories();
+    this.userService.categoriesSubject.subscribe((res) => {
+      this.categories = Object.keys(res);
+    });
+    this.locationService.getAreaNames();
+    this.locationService.areaNamesSubject.subscribe((res) => {
+      this.areaNames = Object.keys(res);
+    });
+    this.locationService.getAreaTypes();
+    this.locationService.areaTypesSubject.subscribe((res) => {
+      this.areaTypes = Object.keys(res);
+    });
+    this.userService
+      .getAccountTypes()
+      .pipe(first())
+      .subscribe((res) => (this.accountTypes = res));
+    this.userService
+      .getTransactionTypes()
+      .pipe(first())
+      .subscribe((res) => (this.transactionsTypes = res));
+    this.userService
+      .getGenders()
+      .pipe(first())
+      .subscribe((res) => (this.genders = res));
+  }
 }

From e541a155ffda9c388f25a29a49f64c86990c8451 Mon Sep 17 00:00:00 2001
From: Spencer Ofwiti <maxspencer56@gmail.com>
Date: Mon, 9 Aug 2021 11:35:32 +0300
Subject: [PATCH 2/4] Refactor create account component onInit function.

---
 .../create-account.component.ts               | 28 +++++++++++--------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/src/app/pages/accounts/create-account/create-account.component.ts b/src/app/pages/accounts/create-account/create-account.component.ts
index c29d714..bbdec1c 100644
--- a/src/app/pages/accounts/create-account/create-account.component.ts
+++ b/src/app/pages/accounts/create-account/create-account.component.ts
@@ -38,6 +38,22 @@ export class CreateAccountComponent implements OnInit {
       referrer: ['', Validators.required],
       businessCategory: ['', Validators.required],
     });
+    this.loadSearchData();
+  }
+
+  get createFormStub(): any {
+    return this.createForm.controls;
+  }
+
+  onSubmit(): void {
+    this.submitted = true;
+    if (this.createForm.invalid || !confirm('Create account?')) {
+      return;
+    }
+    this.submitted = false;
+  }
+
+  loadSearchData(): void {
     this.userService.getCategories();
     this.userService.categoriesSubject.subscribe((res) => {
       this.categories = Object.keys(res);
@@ -55,16 +71,4 @@ export class CreateAccountComponent implements OnInit {
       .pipe(first())
       .subscribe((res) => (this.genders = res));
   }
-
-  get createFormStub(): any {
-    return this.createForm.controls;
-  }
-
-  onSubmit(): void {
-    this.submitted = true;
-    if (this.createForm.invalid || !confirm('Create account?')) {
-      return;
-    }
-    this.submitted = false;
-  }
 }

From 563bd20cfeb33c51ced67807173472b3c33bf684 Mon Sep 17 00:00:00 2001
From: Spencer Ofwiti <maxspencer56@gmail.com>
Date: Mon, 9 Aug 2021 11:45:23 +0300
Subject: [PATCH 3/4] Refactor app component init function.

---
 src/app/app.component.ts                     | 53 +++++++++++---------
 src/app/pages/accounts/accounts.component.ts |  1 -
 2 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 878e09d..41e639a 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -61,31 +61,7 @@ export class AppComponent implements OnInit {
         }
       });
     }
-    await this.router.events
-      .pipe(filter((e) => e instanceof NavigationEnd))
-      .forEach(async (routeInfo) => {
-        if (routeInfo instanceof NavigationEnd) {
-          this.url = routeInfo.url;
-          if (!this.url.match(this.accountDetailsRegex) || !this.url.includes('tx')) {
-            await this.blockSyncService.blockSync();
-          }
-          if (!this.url.includes('accounts')) {
-            try {
-              // TODO it feels like this should be in the onInit handler
-              await this.userService.loadAccounts(100);
-            } catch (error) {
-              this.loggingService.sendErrorLevelMessage('Failed to load accounts', this, { error });
-            }
-          }
-          if (!this.url.includes('tokens')) {
-            this.tokenService.load.subscribe(async (status: boolean) => {
-              if (status) {
-                await this.tokenService.getTokens();
-              }
-            });
-          }
-        }
-      });
+    await this.routeManagement();
   }
 
   // Load resize
@@ -124,4 +100,31 @@ export class AppComponent implements OnInit {
     const conversion: any = event.detail.tx;
     await this.transactionService.setConversion(conversion, 100);
   }
+
+  async routeManagement(): Promise<void> {
+    await this.router.events
+      .pipe(filter((e) => e instanceof NavigationEnd))
+      .forEach(async (routeInfo) => {
+        if (routeInfo instanceof NavigationEnd) {
+          this.url = routeInfo.url;
+          if (!this.url.match(this.accountDetailsRegex) || !this.url.includes('tx')) {
+            await this.blockSyncService.blockSync();
+          }
+          if (!this.url.includes('accounts')) {
+            try {
+              await this.userService.loadAccounts(100);
+            } catch (error) {
+              this.loggingService.sendErrorLevelMessage('Failed to load accounts', this, { error });
+            }
+          }
+          if (!this.url.includes('tokens')) {
+            this.tokenService.load.subscribe(async (status: boolean) => {
+              if (status) {
+                await this.tokenService.getTokens();
+              }
+            });
+          }
+        }
+      });
+  }
 }
diff --git a/src/app/pages/accounts/accounts.component.ts b/src/app/pages/accounts/accounts.component.ts
index 2e4c864..77828d4 100644
--- a/src/app/pages/accounts/accounts.component.ts
+++ b/src/app/pages/accounts/accounts.component.ts
@@ -54,7 +54,6 @@ export class AccountsComponent implements OnInit, AfterViewInit {
       }
     });
     try {
-      // TODO it feels like this should be in the onInit handler
       await this.userService.loadAccounts(100);
     } catch (error) {
       this.loggingService.sendErrorLevelMessage('Failed to load accounts', this, { error });

From da6dc6a2965fcc32bfd8b693487d5590a03a3894 Mon Sep 17 00:00:00 2001
From: Spencer Ofwiti <maxspencer56@gmail.com>
Date: Mon, 9 Aug 2021 12:09:59 +0300
Subject: [PATCH 4/4] Refactor user service changeAccountInfo function.

---
 src/app/_services/transaction.service.ts |   2 +-
 src/app/_services/user.service.ts        | 109 ++++++++++++++---------
 2 files changed, 69 insertions(+), 42 deletions(-)

diff --git a/src/app/_services/transaction.service.ts b/src/app/_services/transaction.service.ts
index 4a46e73..c78642e 100644
--- a/src/app/_services/transaction.service.ts
+++ b/src/app/_services/transaction.service.ts
@@ -176,7 +176,7 @@ export class TransactionService {
     const hash = hashFunction.digest();
     const methodSignature = hash.toString('hex').substring(0, 8);
     const abiCoder = new utils.AbiCoder();
-    const abi = await abiCoder.encode(
+    const abi = abiCoder.encode(
       ['address', 'address', 'address', 'uint256'],
       [senderAddress, recipientAddress, tokenAddress, value]
     );
diff --git a/src/app/_services/user.service.ts b/src/app/_services/user.service.ts
index 49c99f4..cf6a044 100644
--- a/src/app/_services/user.service.ts
+++ b/src/app/_services/user.service.ts
@@ -83,47 +83,18 @@ export class UserService {
     locationType: string,
     oldPhoneNumber: string
   ): Promise<any> {
-    const accountInfo: any = {
-      vcard: {
-        fn: [{}],
-        n: [{}],
-        tel: [{}],
-      },
-      location: {},
-    };
-    if (name) {
-      accountInfo.vcard.fn[0].value = name;
-      accountInfo.vcard.n[0].value = name.split(' ');
-    }
-    if (phoneNumber) {
-      accountInfo.vcard.tel[0].value = phoneNumber;
-    }
-    if (bio) {
-      accountInfo.products = [bio];
-    }
-    if (gender) {
-      accountInfo.gender = gender;
-    }
-    if (age) {
-      accountInfo.age = age;
-    }
-    if (type) {
-      accountInfo.type = type;
-    }
-    if (businessCategory) {
-      accountInfo.category = businessCategory;
-    }
-    if (location) {
-      accountInfo.location.area = location;
-    }
-    if (userLocation) {
-      accountInfo.location.area_name = userLocation;
-    }
-    if (locationType) {
-      accountInfo.location.area_type = locationType;
-    }
-    await vcardValidation(accountInfo.vcard);
-    accountInfo.vcard = btoa(vCard.generate(accountInfo.vcard));
+    const accountInfo = await this.loadChangesToAccountStructure(
+      name,
+      phoneNumber,
+      age,
+      type,
+      bio,
+      gender,
+      businessCategory,
+      userLocation,
+      location,
+      locationType
+    );
     const accountKey: string = await User.toKey(address);
     this.getAccountDetailsFromMeta(accountKey)
       .pipe(first())
@@ -357,4 +328,60 @@ export class UserService {
     }
     this.accountsList.next(this.accounts);
   }
+
+  async loadChangesToAccountStructure(
+    name: string,
+    phoneNumber: string,
+    age: string,
+    type: string,
+    bio: string,
+    gender: string,
+    businessCategory: string,
+    userLocation: string,
+    location: string,
+    locationType: string
+  ): Promise<AccountDetails> {
+    const accountInfo: any = {
+      vcard: {
+        fn: [{}],
+        n: [{}],
+        tel: [{}],
+      },
+      location: {},
+    };
+    if (name) {
+      accountInfo.vcard.fn[0].value = name;
+      accountInfo.vcard.n[0].value = name.split(' ');
+    }
+    if (phoneNumber) {
+      accountInfo.vcard.tel[0].value = phoneNumber;
+    }
+    if (bio) {
+      accountInfo.products = [bio];
+    }
+    if (gender) {
+      accountInfo.gender = gender;
+    }
+    if (age) {
+      accountInfo.age = age;
+    }
+    if (type) {
+      accountInfo.type = type;
+    }
+    if (businessCategory) {
+      accountInfo.category = businessCategory;
+    }
+    if (location) {
+      accountInfo.location.area = location;
+    }
+    if (userLocation) {
+      accountInfo.location.area_name = userLocation;
+    }
+    if (locationType) {
+      accountInfo.location.area_type = locationType;
+    }
+    await vcardValidation(accountInfo.vcard);
+    accountInfo.vcard = btoa(vCard.generate(accountInfo.vcard));
+    return accountInfo;
+  }
 }