Completed form handling.

This commit is contained in:
Spencer Ofwiti 2021-02-08 14:47:07 +03:00
parent e372921439
commit 94d2976e6c
19 changed files with 431 additions and 84 deletions

View File

@ -1,3 +1,4 @@
export * from './mock-backend';
export * from './array-sum';
export * from './accountIndex';
export * from './custom-error-state-matcher';

View File

@ -83,4 +83,15 @@ export class TransactionService {
console.log(error);
});
}
transferRequest(tokenAddress: string, senderAddress: string, recipientAddress: string, value: number): Observable<any> {
return this.http.post(
`${environment.cicEthUrl}/transfer`,
{
tokenAddress: tokenAddress,
from: senderAddress,
to: recipientAddress,
value: value,
});
}
}

View File

@ -22,6 +22,37 @@ export class UserService {
constructor(private http: HttpClient) { }
resetPin(phone: string): Observable<any> {
const params = new HttpParams().set('phoneNumber', phone);
return this.http.get(`${environment.cicUssdUrl}/pin`, { params });
}
createAccount(accountType: string, idNumber: string, phoneNumber: string, givenName: string, surname: string, directoryEntry: string,
location: string, gender: string, referrer: string, businessCategory: string): Observable<any> {
console.log(accountType);
return this.http.post(
`${environment.cicUssdUrl}/user`,
{
accountType: accountType,
idNumber: idNumber,
phone: phoneNumber,
givenName: givenName,
surname: surname,
directoryEntry: directoryEntry,
location: location,
gender: gender,
referrer: referrer,
businessCategory: businessCategory
}
);
}
changeAccountInfo(status: string, name: string, phoneNumber: string, type: string, token: string, failedPinAttempts: string, bio: string,
gender: string, businessCategory: string, userLocation: string, location: string, referrer: string): Observable<any> {
console.log(status);
return ;
}
getAccounts(): void {
this.http.get(`${environment.cicCacheUrl}/accounts`).pipe(first()).subscribe(accounts => this.accountsList.next(accounts));
}

View File

@ -27,7 +27,8 @@
<span class="ml-2"><strong>Address:</strong> {{account?.address}}</span>
</div>
</div>
<app-disbursement *ngIf="isDisbursing" (cancelDisbursmentEvent)="addTransfer()"></app-disbursement>
<app-disbursement *ngIf="isDisbursing" (cancelDisbursmentEvent)="addTransfer()" [account]="account">
</app-disbursement>
<div *ngIf="!account" class="text-center">
<div class="spinner-grow text-primary m-1" role="status" style="width: 3rem; height: 3rem;">
<span class="sr-only">Loading...</span>
@ -43,90 +44,110 @@
<mat-card-title class="card-header">
<div class="row">
DETAILS
<button mat-raised-button color="primary" type="button" class="btn btn-outline-primary ml-auto" (click)="addTransfer()"> NEW TRANSFER </button>
<button mat-raised-button color="primary" type="button" class="btn btn-outline-primary ml-2" (click)="saveInfo()"> SAVE </button>
<button mat-raised-button color="primary" type="button" class="btn btn-outline-primary ml-auto"
(click)="addTransfer()"> NEW TRANSFER </button>
</div>
</mat-card-title>
<div class="card-body">
<form>
<form [formGroup]="accountInfoForm" (ngSubmit)="saveInfo()">
<div class="row form-inline">
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label> STATUS </mat-label>
<mat-select id="status" [(value)]="account.status">
<mat-select id="status" [(value)]="account.status" formControlName="status"
[errorStateMatcher]="matcher">
<mat-option value="unapproved">Unapproved</mat-option>
<mat-option value="approved">Approved</mat-option>
</mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.status.errors">Status is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Name(s): *</mat-label>
<input matInput type="text" id="givenNames" placeholder="{{account?.name}}" value="{{account?.name}}">
<input matInput type="text" id="givenNames" placeholder="{{account?.name}}" value="{{account?.name}}"
formControlName="name" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && accountInfoFormStub.name.errors">Name is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Phone Number: </mat-label>
<input matInput type="text" id="phoneNumber" placeholder="{{account?.phone}}" value="{{account?.phone}}">
<input matInput type="text" id="phoneNumber" placeholder="{{account?.phone}}"
value="{{account?.phone}}" formControlName="phoneNumber" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && accountInfoFormStub.phoneNumber.errors">Phone Number is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label> ACCOUNT TYPE: </mat-label>
<mat-select id="accountType" [(value)]="account.type">
<mat-select id="accountType" [(value)]="account.type" formControlName="type"
[errorStateMatcher]="matcher">
<mat-option value="user"> USER </mat-option>
<mat-option value="cashier"> CASHIER </mat-option>
<mat-option value="vendor"> VENDOR </mat-option>
<mat-option value="tokenAgent"> TOKENAGENT </mat-option>
<mat-option value="group"> GROUPACCOUNT </mat-option>
</mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.type.errors">Type is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label> USER TOKEN: </mat-label>
<mat-select id="token" [(value)]="account.token">
<mat-select id="token" [(value)]="account.token" formControlName="token"
[errorStateMatcher]="matcher">
<mat-option value="RSV"> RESERVE </mat-option>
<mat-option value="ERN"> ERNIE </mat-option>
<mat-option value="BRT"> BERT </mat-option>
</mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.token.errors">Token is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Failed Pin Attempts: </mat-label>
<input matInput type="text" id="failedPinAttempts" placeholder="{{account?.failedPinAttempts}}" value="{{account?.failedPinAttempts}}">
<input matInput type="text" id="failedPinAttempts" placeholder="{{account?.failedPinAttempts}}"
value="{{account?.failedPinAttempts}}" formControlName="failedPinAttempts" required
[errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && accountInfoFormStub.failedPinAttempts.errors">
Failed Pin Attempts is required.
</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Bio: </mat-label>
<input matInput type="text" id="bio" placeholder="{{account?.bio}}" value="{{account?.bio}}">
<input matInput type="text" id="bio" placeholder="{{account?.bio}}" value="{{account?.bio}}"
formControlName="bio" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && accountInfoFormStub.bio.errors">Bio is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label> GENDER: </mat-label>
<mat-select id="gender" [(value)]="account.gender">
<mat-select id="gender" [(value)]="account.gender" formControlName="gender"
[errorStateMatcher]="matcher">
<mat-option value="male"> MALE </mat-option>
<mat-option value="female"> FEMALE </mat-option>
<mat-option value="other"> OTHER </mat-option>
</mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.gender.errors">Gender is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label> BUSINESS CATEGORY: </mat-label>
<mat-select id="businessCategory" [(value)]="account.category">
<mat-select id="businessCategory" [(value)]="account.category" formControlName="businessCategory"
[errorStateMatcher]="matcher">
<mat-option value="food/water">Food/Water</mat-option>
<mat-option value="fuel/energy">Fuel/Energy</mat-option>
<mat-option value="education">Education</mat-option>
@ -138,23 +159,32 @@
<mat-option value="savings">Savings Group</mat-option>
<mat-option value="other">Savings Group</mat-option>
</mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.businessCategory.errors">
Category is required.
</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>User Location: </mat-label>
<input matInput type="text" id="userLocation" placeholder="{{account?.userLocation}}" value="{{account?.userLocation}}">
<input matInput type="text" id="userLocation" placeholder="{{account?.userLocation}}"
value="{{account?.userLocation}}" formControlName="userLocation" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && accountInfoFormStub.userLocation.errors">
User Location is required.
</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label> LOCATION: </mat-label>
<mat-select id="location" [(value)]="account.location">
<mat-select id="location" [(value)]="account.location" formControlName="location"
[errorStateMatcher]="matcher">
<div *ngFor="let county of locations">
<div *ngFor="let district of county.districts">
<mat-optgroup *ngFor="let location of district.locations" [label]="county.name + ' / ' + district.name + ' / ' + location.name">
<mat-optgroup *ngFor="let location of district.locations" [label]="county.name + ' / ' +
district.name + ' / ' + location.name">
<mat-option *ngFor="let village of location.villages" [value]="village">
{{village}}
</mat-option>
@ -162,26 +192,42 @@
</div>
</div>
</mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.location.errors">Location is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Referred By: </mat-label>
<input matInput type="text" id="referredBy" placeholder="{{account?.referrer}}" value="{{account?.referrer}}" readonly>
<input matInput type="text" id="referredBy" placeholder="{{account?.referrer}}" readonly
value="{{account?.referrer}}" formControlName="referrer" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && accountInfoFormStub.referrer.errors">Referrer is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<button mat-raised-button color="primary" type="button" class="btn btn btn-outline-primary mb-3"> Add User KYC </button>
<button mat-raised-button color="primary" type="button" class="btn btn btn-outline-primary mb-3">
Add User KYC
</button>
</div>
<div *ngIf="account.failedPinAttempts != 0" class="col-md-6 col-lg-4">
<button mat-raised-button color="primary" type="button" class="btn btn btn-outline-success mb-3"> Reset Pin </button>
<button mat-raised-button color="primary" type="button" class="btn btn btn-outline-success mb-3"
(click)="resetPin()">
Reset Pin
</button>
</div>
<div class="col-md-6 col-lg-4">
<button mat-raised-button color="warn" type="button" class="btn btn-outline-danger"> Delete User </button>
<button mat-raised-button color="warn" type="button" class="btn btn-outline-danger">
Delete User
</button>
</div>
<div class="col-md-6 col-lg-4">
<button mat-raised-button color="primary" type="submit" class="btn btn-outline-primary ml-2">
SAVE
</button>
</div>
</div>
</form>
@ -210,8 +256,12 @@
<td>{{account?.type}}</td>
<td>{{account?.created}}</td>
<td>
<span *ngIf="account?.status === 'approved'" class="badge badge-success badge-pill"> {{account?.status}} </span>
<span *ngIf="account?.status === 'unapproved'" class="badge badge-danger badge-pill"> {{account?.status}} </span>
<span *ngIf="account?.status === 'approved'" class="badge badge-success badge-pill">
{{account?.status}}
</span>
<span *ngIf="account?.status === 'unapproved'" class="badge badge-danger badge-pill">
{{account?.status}}
</span>
</td>
</tr>
</tbody>
@ -291,8 +341,8 @@
<mat-icon matSuffix>search</mat-icon>
</mat-form-field>
<mat-table class="mat-elevation-z10" [dataSource]="transactionsDataSource" matSort #TransactionTableSort="matSort"
matSortActive="created" matSortDirection="asc" matSortDisableClear>
<mat-table class="mat-elevation-z10" [dataSource]="transactionsDataSource" matSort matSortActive="created"
#TransactionTableSort="matSort" matSortDirection="asc" matSortDisableClear>
<ng-container matColumnDef="view">
<mat-header-cell *matHeaderCellDef> View </mat-header-cell>
@ -350,7 +400,8 @@
</ng-container>
<mat-header-row *matHeaderRowDef="transactionsDisplayedColumns"></mat-header-row>
<mat-row *matRowDef="let transaction; columns: transactionsDisplayedColumns" matRipple (click)="viewTransaction(transaction)"></mat-row>
<mat-row *matRowDef="let transaction; columns: transactionsDisplayedColumns" matRipple
(click)="viewTransaction(transaction)"></mat-row>
</mat-table>
<mat-paginator #TransactionTablePaginator="matPaginator" [pageSize]="10"
@ -417,8 +468,12 @@
<ng-container matColumnDef="status">
<mat-header-cell *matHeaderCellDef mat-sort-header> STATUS </mat-header-cell>
<mat-cell *matCellDef="let user">
<span *ngIf="user.status === 'approved'" class="badge badge-success badge-pill"> {{user.status}} </span>
<span *ngIf="user.status === 'unapproved'" class="badge badge-danger badge-pill"> {{user.status}} </span>
<span *ngIf="user.status === 'approved'" class="badge badge-success badge-pill">
{{user.status}}
</span>
<span *ngIf="user.status === 'unapproved'" class="badge badge-danger badge-pill">
{{user.status}}
</span>
</mat-cell>
</ng-container>
@ -433,10 +488,12 @@
</ng-container>
<mat-header-row *matHeaderRowDef=userDisplayedColumns></mat-header-row>
<mat-row *matRowDef="let account; columns: userDisplayedColumns" (click)="viewAccount(account)" matRipple></mat-row>
<mat-row *matRowDef="let account; columns: userDisplayedColumns" (click)="viewAccount(account)"
matRipple></mat-row>
</mat-table>
<mat-paginator #UserTablePaginator="matPaginator" [pageSize]="10" [pageSizeOptions]="[10, 20, 50, 100]" showFirstLastButtons></mat-paginator>
<mat-paginator #UserTablePaginator="matPaginator" [pageSize]="10" [pageSizeOptions]="[10, 20, 50, 100]"
showFirstLastButtons></mat-paginator>
</div>
</div>
</mat-tab>

View File

@ -7,6 +7,8 @@ import {MatSort} from '@angular/material/sort';
import {LocationService, TransactionService, UserService} from '../../../_services';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {first} from 'rxjs/operators';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CustomErrorStateMatcher} from '../../../_helpers';
@Component({
selector: 'app-account-details',
@ -29,6 +31,7 @@ export class AccountDetailsComponent implements OnInit {
@ViewChild('HistoryTablePaginator', {static: true}) historyTablePaginator: MatPaginator;
@ViewChild('HistoryTableSort', {static: true}) historyTableSort: MatSort;
accountInfoForm: FormGroup;
account: any;
accounts: any[] = [];
accountsType = 'all';
@ -42,14 +45,31 @@ export class AccountDetailsComponent implements OnInit {
transaction: any;
transactions: any[];
transactionsType = 'all';
matcher = new CustomErrorStateMatcher();
submitted: boolean = false;
constructor(
private formBuilder: FormBuilder,
private locationService: LocationService,
private transactionService: TransactionService,
private userService: UserService,
private route: ActivatedRoute,
private router: Router
) {
this.accountInfoForm = this.formBuilder.group({
status: ['', Validators.required],
name: ['', Validators.required],
phoneNumber: ['', Validators.required],
type: ['', Validators.required],
token: ['', Validators.required],
failedPinAttempts: ['', Validators.required],
bio: ['', Validators.required],
gender: ['', Validators.required],
businessCategory: ['', Validators.required],
userLocation: ['', Validators.required],
location: ['', Validators.required],
referrer: ['', Validators.required]
});
this.route.paramMap.subscribe((params: Params) => {
this.userService.getAccountById(params.get('id')).pipe(first()).subscribe(account => {
this.account = account;
@ -58,6 +78,20 @@ export class AccountDetailsComponent implements OnInit {
this.historyDataSource.paginator = this.historyTablePaginator;
this.historyDataSource.sort = this.historyTableSort;
});
this.accountInfoForm.patchValue({
status: account.status,
name: account.name,
phoneNumber: account.phone,
type: account.type,
token: account.token,
failedPinAttempts: account.failedPinAttempts,
bio: account.bio,
gender: account.gender,
businessCategory: account.category,
// userLocation: account.userLocation,
location: account.location,
referrer: account.referrer
});
});
});
this.userService.getAccounts();
@ -120,7 +154,30 @@ export class AccountDetailsComponent implements OnInit {
this.router.navigateByUrl(`/accounts/${account.id}`);
}
saveInfo(): void {}
get accountInfoFormStub(): any { return this.accountInfoForm.controls; }
saveInfo(): void {
this.submitted = true;
console.log(this.accountInfoFormStub.userLocation.value);
if (this.accountInfoForm.invalid) { return; }
this.userService.changeAccountInfo(
this.accountInfoFormStub.status.value,
this.accountInfoFormStub.name.value,
this.accountInfoFormStub.phoneNumber.value,
this.accountInfoFormStub.type.value,
this.accountInfoFormStub.token.value,
this.accountInfoFormStub.failedPinAttempts.value,
this.accountInfoFormStub.bio.value,
this.accountInfoFormStub.gender.value,
this.accountInfoFormStub.businessCategory.value,
this.accountInfoFormStub.userLocation.value,
this.accountInfoFormStub.location.value,
this.accountInfoFormStub.referrer.value,
).pipe(first()).subscribe(res => {
console.log(res);
});
this.submitted = false;
}
filterAccounts(): void {
if (this.accountsType === 'all') {
@ -143,4 +200,14 @@ export class AccountDetailsComponent implements OnInit {
this.transactionsDataSource.data = this.transactions.filter(transaction => transaction.type === this.transactionsType);
}
}
resetPin(): void {
this.userService.resetPin(this.account.phone).pipe(first()).subscribe(res => {
console.log(res);
});
}
setDefault(formStub: any, name: string, value: string): void {
formStub[name].value = value;
}
}

View File

@ -23,29 +23,31 @@ import {TransactionsModule} from '../transactions/transactions.module';
import {MatTabsModule} from '@angular/material/tabs';
import {MatRippleModule} from '@angular/material/core';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {ReactiveFormsModule} from '@angular/forms';
@NgModule({
declarations: [AccountsComponent, AccountDetailsComponent, CreateAccountComponent, DisbursementComponent, ExportAccountsComponent],
imports: [
CommonModule,
AccountsRoutingModule,
SharedModule,
DataTablesModule,
MatTableModule,
MatSortModule,
MatCheckboxModule,
MatPaginatorModule,
MatInputModule,
MatFormFieldModule,
MatButtonModule,
MatCardModule,
MatIconModule,
MatSelectModule,
TransactionsModule,
MatTabsModule,
MatRippleModule,
MatProgressSpinnerModule
]
imports: [
CommonModule,
AccountsRoutingModule,
SharedModule,
DataTablesModule,
MatTableModule,
MatSortModule,
MatCheckboxModule,
MatPaginatorModule,
MatInputModule,
MatFormFieldModule,
MatButtonModule,
MatCardModule,
MatIconModule,
MatSelectModule,
TransactionsModule,
MatTabsModule,
MatRippleModule,
MatProgressSpinnerModule,
ReactiveFormsModule
]
})
export class AccountsModule { }

View File

@ -22,84 +22,103 @@
CREATE A USER ACCOUNT
</mat-card-title>
<div class="card-body">
<form class="row form-inline">
<form class="row form-inline" [formGroup]="createForm" (ngSubmit)="onSubmit()">
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Account Type: </mat-label>
<mat-select id="accountType">
<mat-select id="accountType" formControlName="accountType" [errorStateMatcher]="matcher">
<mat-option value="user">USER</mat-option>
<mat-option value="cashier">CASHIER</mat-option>
<mat-option value="vendor">VENDOR</mat-option>
<mat-option value="tokenAgent">TOKENAGENT</mat-option>
<mat-option value="group">GROUPACCOUNT</mat-option>
</mat-select>
<mat-error *ngIf="submitted && createFormStub.accountType.errors">Account type is required.</mat-error>
</mat-form-field><br>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>ID Number: </mat-label>
<input matInput type="text" id="idNumber" placeholder="ID Number">
<input matInput type="text" id="idNumber" placeholder="ID Number" formControlName="idNumber" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && createFormStub.idNumber.errors">ID Number is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Phone Number: </mat-label>
<input matInput type="text" id="phoneNumber" placeholder="Phone Number">
<input matInput type="text" id="phoneNumber" placeholder="Phone Number" formControlName="phoneNumber" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && createFormStub.phoneNumber.errors">Phone Number is required.</mat-error>
</mat-form-field><br>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Given Name(s):* </mat-label>
<input matInput type="text" id="givenNames" placeholder="Given Names">
<input matInput type="text" id="givenNames" placeholder="Given Names" formControlName="givenName" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && createFormStub.givenName.errors">Given Names are required.</mat-error>
</mat-form-field><br>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Family/Surname: </mat-label>
<input matInput type="text" id="surname" placeholder="Surname">
<input matInput type="text" id="surname" placeholder="Surname" formControlName="surname" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && createFormStub.surname.errors">Surname is required.</mat-error>
</mat-form-field><br>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Directory Entry: </mat-label>
<input matInput type="text" id="directoryEntry" placeholder="Directory Entry">
<input matInput type="text" id="directoryEntry" placeholder="Directory Entry" formControlName="directoryEntry" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && createFormStub.directoryEntry.errors">Directory Entry is required.</mat-error>
</mat-form-field><br>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Location: </mat-label>
<input matInput type="text" id="location" placeholder="Location">
<mat-select id="location" formControlName="location" [errorStateMatcher]="matcher">
<div *ngFor="let county of locations">
<div *ngFor="let district of county.districts">
<mat-optgroup *ngFor="let location of district.locations" [label]="county.name + ' / ' + district.name + ' / ' + location.name">
<mat-option *ngFor="let village of location.villages" [value]="village">
{{village}}
</mat-option>
</mat-optgroup>
</div>
</div>
</mat-select>
<mat-error *ngIf="submitted && createFormStub.location.errors">Location is required.</mat-error>
</mat-form-field><br>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Gender: </mat-label>
<mat-select id="gender">
<mat-select id="gender" formControlName="gender" [errorStateMatcher]="matcher">
<mat-option value="female">FEMALE</mat-option>
<mat-option value="male">MALE</mat-option>
<mat-option value="other">OTHER</mat-option>
</mat-select>
<mat-error *ngIf="submitted && createFormStub.gender.errors">Gender is required.</mat-error>
</mat-form-field><br>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Referrer Phone Number: </mat-label>
<input matInput type="text" id="referredBy" placeholder="Reffered By">
<input matInput type="text" id="referredBy" placeholder="Reffered By" formControlName="referrer" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && createFormStub.referrer.errors">Referrer is required.</mat-error>
</mat-form-field><br>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Business Category: </mat-label>
<mat-select id="businessCategory">
<mat-select id="businessCategory" formControlName="businessCategory" [errorStateMatcher]="matcher">
<mat-option value="food/water">Food/Water</mat-option>
<mat-option value="fuel/energy">Fuel/Energy</mat-option>
<mat-option value="education">Education</mat-option>
@ -111,6 +130,7 @@
<mat-option value="savings">Savings Group</mat-option>
<mat-option value="other">Other</mat-option>
</mat-select>
<mat-error *ngIf="submitted && createFormStub.businessCategory.errors">Business Category is required.</mat-error>
</mat-form-field>
</div>

View File

@ -1,5 +1,10 @@
import { Component, OnInit } from '@angular/core';
import {Router} from '@angular/router';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {ErrorStateMatcher} from '@angular/material/core';
import {LocationService, UserService} from '../../../_services';
import {first} from 'rxjs/operators';
import {CustomErrorStateMatcher} from '../../../_helpers';
@Component({
selector: 'app-create-account',
@ -7,15 +12,57 @@ import {Router} from '@angular/router';
styleUrls: ['./create-account.component.scss']
})
export class CreateAccountComponent implements OnInit {
createForm: FormGroup;
matcher = new CustomErrorStateMatcher();
submitted: boolean = false;
locations: any;
constructor(
private router: Router
private formBuilder: FormBuilder,
private router: Router,
private userService: UserService,
private locationService: LocationService
) { }
ngOnInit(): void {
this.createForm = this.formBuilder.group({
accountType: ['', Validators.required],
idNumber: ['', Validators.required],
phoneNumber: ['', Validators.required],
givenName: ['', Validators.required],
surname: ['', Validators.required],
directoryEntry: ['', Validators.required],
location: ['', Validators.required],
gender: ['', Validators.required],
referrer: ['', Validators.required],
businessCategory: ['', Validators.required]
});
this.locationService.getLocations();
this.locationService.locationsSubject.subscribe(locations => {
this.locations = locations;
});
}
get createFormStub(): any { return this.createForm.controls; }
onSubmit(): void {
this.router.navigateByUrl(`/accounts`);
this.submitted = true;
if (this.createForm.invalid) { return; }
this.userService.createAccount(
this.createFormStub.accountType.value,
this.createFormStub.idNumber.value,
this.createFormStub.phoneNumber.value,
this.createFormStub.givenName.value,
this.createFormStub.surname.value,
this.createFormStub.directoryEntry.value,
this.createFormStub.location.value,
this.createFormStub.gender.value,
this.createFormStub.referrer.value,
this.createFormStub.businessCategory.value,
).pipe(first()).subscribe(res => {
console.log(res);
});
// this.router.navigateByUrl(`/accounts`);
this.submitted = false;
}
}

View File

@ -6,22 +6,28 @@
</div>
</mat-card-title>
<div class="card-body">
<form>
<form [formGroup]="disbursementForm" (ngSubmit)="createTransfer()">
<div class="row form-inline">
<mat-form-field appearance="outline">
<mat-label> TRANSACTION TYPE </mat-label>
<mat-select id="accountType">
<mat-select id="transactionType" formControlName="transactionType" [errorStateMatcher]="matcher">
<mat-option value="disbursement">DISBURSEMENT</mat-option>
<mat-option value="transfer">TRANSFER</mat-option>
<mat-option value="deposit">DEPOSIT</mat-option>
<mat-option value="reclamation">RECLAMATION</mat-option>
</mat-select>
<mat-error *ngIf="submitted && disbursementFormStub.transactionType.errors">Transaction type is required.</mat-error>
</mat-form-field>
<mat-form-field *ngIf="disbursementFormStub.transactionType.value === 'transfer'" appearance="outline" class="ml-3">
<mat-label>Enter Recipient: </mat-label>
<input matInput type="text" id="recipient" placeholder="Recipient" formControlName="recipient">
</mat-form-field>
<mat-form-field appearance="outline" class="ml-3">
<mat-label>Enter Amount: </mat-label>
<input matInput type="text" id="amount" placeholder="Amount">
<input matInput type="text" id="amount" placeholder="Amount" formControlName="amount" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && disbursementFormStub.amount.errors">Amount is required.</mat-error>
</mat-form-field>
<button mat-raised-button color="primary" type="submit" class="btn btn-outline-primary ml-3" style="margin-bottom: 1.2rem;" (click)="createTransfer()">
<button mat-raised-button color="primary" type="submit" class="btn btn-outline-primary ml-3" style="margin-bottom: 1.2rem;">
CREATE TRANSFER
</button>
</div>

View File

@ -1,4 +1,8 @@
import {Component, OnInit, EventEmitter, Output} from '@angular/core';
import {Component, OnInit, EventEmitter, Output, Input} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CustomErrorStateMatcher} from '../../../_helpers';
import {TransactionService} from '../../../_services';
import {first} from 'rxjs/operators';
@Component({
selector: 'app-disbursement',
@ -6,14 +10,43 @@ import {Component, OnInit, EventEmitter, Output} from '@angular/core';
styleUrls: ['./disbursement.component.scss']
})
export class DisbursementComponent implements OnInit {
@Input() account;
@Output() cancelDisbursmentEvent = new EventEmitter();
disbursementForm: FormGroup;
matcher = new CustomErrorStateMatcher();
submitted: boolean = false;
constructor() { }
constructor(
private formBuilder: FormBuilder,
private transactionService: TransactionService
) { }
ngOnInit(): void {
this.disbursementForm = this.formBuilder.group({
transactionType: ['', Validators.required],
recipient: '',
amount: ['', Validators.required]
});
}
createTransfer(): void {}
get disbursementFormStub(): any { return this.disbursementForm.controls; }
createTransfer(): void {
this.submitted = true;
if (this.disbursementForm.invalid) { return; }
if (this.disbursementFormStub.transactionType.value === 'transfer') {
this.transactionService.transferRequest(
this.account.token,
this.account.address,
this.disbursementFormStub.recipient.value,
this.disbursementFormStub.amount.value
).pipe(first()).subscribe(res => {
console.log(res);
});
}
console.log(this.disbursementFormStub.transactionType.value);
this.submitted = false;
}
cancel(): void {
this.cancelDisbursmentEvent.emit();

View File

@ -22,21 +22,22 @@
EXPORT ACCOUNTS
</mat-card-title>
<div class="card-body">
<form>
<form [formGroup]="exportForm" (ngSubmit)="export()">
<div class="form-inline mb-2">
<mat-form-field appearance="outline">
<mat-label>Export : </mat-label>
<mat-select id="accountType">
<mat-select id="accountType" formControlName="accountType" [errorStateMatcher]="matcher">
<mat-option value="vendors">VENDORS</mat-option>
<mat-option value="partners">PARTNERS</mat-option>
<mat-option value="selected">SELECTED</mat-option>
</mat-select>
<mat-error *ngIf="submitted && exportFormStub.accountType.errors">Account Type is required.</mat-error>
</mat-form-field>
</div>
<div class="form-inline mb-3">
<div class="form-group form-check">
<label class="form-check-label mr-2" for="transfers">Include transfers?</label>
<mat-checkbox id="transfers"></mat-checkbox>
<mat-checkbox id="transfers" formControlName="transfers"></mat-checkbox>
</div>
</div>
<button mat-raised-button color="primary" type="submit" class="btn btn-outline-primary"> EXPORT </button>

View File

@ -1,4 +1,6 @@
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CustomErrorStateMatcher} from '../../../_helpers';
@Component({
selector: 'app-export-accounts',
@ -6,10 +8,26 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./export-accounts.component.scss']
})
export class ExportAccountsComponent implements OnInit {
exportForm: FormGroup;
matcher = new CustomErrorStateMatcher();
submitted: boolean = false;
constructor() { }
constructor(
private formBuilder: FormBuilder
) { }
ngOnInit(): void {
this.exportForm = this.formBuilder.group({
accountType: ['', Validators.required],
transfers: ['']
});
}
get exportFormStub(): any { return this.exportForm.controls; }
export(): void {
this.submitted = true;
if (this.exportForm.invalid) { return; }
this.submitted = false;
}
}

View File

@ -23,17 +23,20 @@
INVITE NEW USERS
</mat-card-title>
<div class="card-body">
<form>
<form [formGroup]="inviteForm" (ngSubmit)="invite()">
<mat-form-field appearance="outline">
<mat-label>Email Address: </mat-label>
<input matInput type="email" id="email" placeholder="Email">
<input matInput type="email" id="email" placeholder="Email" formControlName="email"
[errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && inviteFormStub.email.errors">Email is required.</mat-error>
</mat-form-field><br>
<mat-radio-group aria-label="Select a role">
<mat-radio-group aria-label="Select a role" formControlName="role">
<mat-radio-button value="Superadmin">Superadmin</mat-radio-button><br>
<mat-radio-button value="Admin">Admin</mat-radio-button><br>
<mat-radio-button value="Subadmin">Subadmin</mat-radio-button><br>
<mat-radio-button value="View">View</mat-radio-button><br>
</mat-radio-group>
<mat-error *ngIf="submitted && inviteFormStub.role.errors">Role is required.</mat-error>
<button mat-raised-button color="primary" type="submit" class="btn btn-outline-primary">INVITE</button>
</form>
</div>

View File

@ -1,4 +1,6 @@
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CustomErrorStateMatcher} from '../../../_helpers';
@Component({
selector: 'app-invite',
@ -6,10 +8,26 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./invite.component.scss']
})
export class InviteComponent implements OnInit {
inviteForm: FormGroup;
submitted: boolean = false;
matcher = new CustomErrorStateMatcher();
constructor() { }
constructor(
private formBuilder: FormBuilder
) { }
ngOnInit(): void {
this.inviteForm = this.formBuilder.group({
email: ['', Validators.required],
role: ['', Validators.required]
});
}
get inviteFormStub(): any { return this.inviteForm.controls; }
invite(): void {
this.submitted = true;
if (this.inviteForm.invalid) { return; }
this.submitted = false;
}
}

View File

@ -23,24 +23,31 @@
DEFAULT ORGANISATION SETTINGS
</mat-card-title>
<div class="card-body">
<form>
<form [formGroup]="organizationForm" (ngSubmit)="onSubmit()">
<mat-form-field appearance="outline">
<mat-label>Default Disbursement *</mat-label>
<input matInput type="text" id="amount" placeholder="Amount">
<input matInput type="text" id="amount" placeholder="Amount" formControlName="disbursement"
[errorStateMatcher]="matcher">
<span matSuffix>RCU</span>
<mat-error *ngIf="submitted && organizationFormStub.disbursement.errors">
Default Disbursement is required.
</mat-error>
</mat-form-field>
<div class="form-group form-check">
<mat-checkbox id="transferCard">Require Transfer Card *</mat-checkbox>
<mat-checkbox id="transferCard" formControlName="transfer">Require Transfer Card *</mat-checkbox>
</div>
<mat-form-field appearance="outline">
<mat-label>Default Country Code *</mat-label>
<mat-select id="countryCode">
<mat-select id="countryCode" formControlName="countryCode" [errorStateMatcher]="matcher">
<mat-option value="KE">KE Kenya</mat-option>
<mat-option value="US">US United States</mat-option>
<mat-option value="ETH">ETH Ethiopia</mat-option>
<mat-option value="GER">GER Germany</mat-option>
<mat-option value="UG">UG Uganda</mat-option>
</mat-select>
<mat-error *ngIf="submitted && organizationFormStub.countryCode.errors">
Country Code is required.
</mat-error>
</mat-form-field><br>
<button mat-raised-button color="primary" type="submit" class="btn btn-primary">Submit</button>
</form>

View File

@ -1,4 +1,6 @@
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CustomErrorStateMatcher} from '../../../_helpers';
@Component({
selector: 'app-organization',
@ -6,10 +8,27 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./organization.component.scss']
})
export class OrganizationComponent implements OnInit {
organizationForm: FormGroup;
submitted: boolean = false;
matcher = new CustomErrorStateMatcher();
constructor() { }
constructor(
private formBuilder: FormBuilder
) { }
ngOnInit(): void {
this.organizationForm = this.formBuilder.group({
disbursement: ['', Validators.required],
transfer: '',
countryCode: ['', Validators.required]
});
}
get organizationFormStub(): any { return this.organizationForm.controls; }
onSubmit(): void {
this.submitted = true;
if (this.organizationForm.invalid) { return; }
this.submitted = false;
}
}

View File

@ -18,6 +18,7 @@ import {MatRadioModule} from '@angular/material/radio';
import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatSelectModule} from '@angular/material/select';
import {MatMenuModule} from '@angular/material/menu';
import {ReactiveFormsModule} from '@angular/forms';
@NgModule({
@ -37,7 +38,8 @@ import {MatMenuModule} from '@angular/material/menu';
MatRadioModule,
MatCheckboxModule,
MatSelectModule,
MatMenuModule
MatMenuModule,
ReactiveFormsModule
]
})
export class SettingsModule { }

View File

@ -3,6 +3,8 @@ export const environment = {
cicCacheUrl: 'http://localhost:5555',
cicScriptsUrl: 'http://localhost:9999',
web3Provider: 'ws://localhost:63545',
cicUssdUrl: 'http://localhost:63315',
cicEthUrl: 'http://localhost:63314',
contractAddress: '0x35Ef60C4624Eaf6AeEBeBec9Ddd3CBA6b24C4b17',
signerAddress: '0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C',
registryAddress: '0xb708175e3f6Cd850643aAF7B32212AFad50e2549'

View File

@ -7,6 +7,8 @@ export const environment = {
cicCacheUrl: 'http://localhost:5555',
cicScriptsUrl: 'http://localhost:9999',
web3Provider: 'ws://localhost:63545',
cicUssdUrl: 'http://localhost:63315',
cicEthUrl: 'http://localhost:63314',
contractAddress: '0x35Ef60C4624Eaf6AeEBeBec9Ddd3CBA6b24C4b17',
signerAddress: '0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C',
registryAddress: '0xb708175e3f6Cd850643aAF7B32212AFad50e2549'