Skip to content

Commit

Permalink
Merge pull request #11 from proyecto26/develop
Browse files Browse the repository at this point in the history
Release 1.0
  • Loading branch information
jdnichollsc authored Mar 1, 2024
2 parents 1a8263a + 7384a1b commit 310e5c9
Show file tree
Hide file tree
Showing 69 changed files with 6,046 additions and 408 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ Thumbs.db

.nx/cache
.angular

# Environment Variables
.env
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# ProjectX

<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
<p align="center">
<img width="1289" alt="ProjectX-angular" src="https://github.com/proyecto26/ProjectX-angular/assets/2154886/4487731e-322e-4419-a6c5-65e26ffdb9ae">
</p>

**This workspace has been generated by [Nx, Smart Monorepos · Fast CI.](https://nx.dev)**

Expand Down
1 change: 1 addition & 0 deletions apps/webapp/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NG_APP_SHYFT_API_KEY=fill-this-in
36 changes: 17 additions & 19 deletions apps/webapp/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,34 @@
"tags": [],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": [
"{options.outputPath}"
],
"executor": "@ngx-env/builder:application",
"outputs": ["{options.outputPath}"],
"options": {
"allowedCommonJsDependencies": ["crypto", "stream"],
"outputPath": "dist/apps/webapp",
"index": "apps/webapp/src/index.html",
"browser": "apps/webapp/src/main.ts",
"polyfills": [
"zone.js",
"apps/webapp/src/polyfills.ts"
],
"polyfills": ["apps/webapp/src/polyfills.ts"],
"tsConfig": "apps/webapp/tsconfig.app.json",
"assets": [
"apps/webapp/src/favicon.ico",
"apps/webapp/src/assets"
],
"assets": ["apps/webapp/src/favicon.ico", "apps/webapp/src/assets"],
"styles": [
"@angular/material/prebuilt-themes/purple-green.css",
"apps/webapp/src/styles.css"
],
"scripts": [],
"server": "apps/webapp/src/main.server.ts",
"prerender": true,
"ssr": {
"entry": "apps/webapp/server.ts"
}
"prerender": false,
"ssr": false
},
"configurations": {
"production": {
"polyfills": ["apps/webapp/src/polyfills.ts"],
"fileReplacements": [
{
"replace": "apps/webapp/src/environments/environment.ts",
"with": "apps/webapp/src/environments/environment.prod.ts"
}
],
"budgets": [
{
"type": "initial",
Expand All @@ -60,7 +58,7 @@
"defaultConfiguration": "production"
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"executor": "@ngx-env/builder:dev-server",
"configurations": {
"production": {
"buildTarget": "webapp:build:production"
Expand All @@ -72,7 +70,7 @@
"defaultConfiguration": "development"
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"executor": "@ngx-env/builder:extract-i18n",
"options": {
"buildTarget": "webapp:build"
}
Expand All @@ -85,4 +83,4 @@
}
}
}
}
}
21 changes: 18 additions & 3 deletions apps/webapp/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideWalletAdapter } from '@heavy-duty/wallet-adapter';
import { SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2';

import { appRoutes } from './app.routes';

export const appConfig: ApplicationConfig = {
providers: [provideClientHydration(), provideRouter(appRoutes), provideAnimationsAsync()],
providers: [
provideClientHydration(),
provideRouter(appRoutes),
provideAnimationsAsync(),
provideWalletAdapter({
autoConnect: !!localStorage.getItem('autoConnect'),
}),
provideHttpClient(),
importProvidersFrom([
SweetAlert2Module.forRoot(),
])
],
};
7 changes: 6 additions & 1 deletion apps/webapp/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ export const appRoutes: Route[] = [
{
path: 'home',
loadComponent: () =>
import('./pages/home.page').then((m) => m.HomePage),
import('./pages/home/home.page').then((m) => m.HomePage),
},
{
path: 'account',
loadChildren: () =>
import('./pages/account/account.module').then((m) => m.AccountPageRoutingModule),
},
{
path: '',
Expand Down
36 changes: 36 additions & 0 deletions apps/webapp/src/app/components/account/send/send.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<webapp-forms-transfer
*ngIf="(publicKey$ | async) as publicKey; else elsePublicKey"
[isLoading]="!!(isSendTransactionLoading && isSendTransactionLoading())"
(submitForm)="onSubmitForm($event, publicKey)"
/>

<ng-template #elsePublicKey>
<div *ngIf="(connected$ | async) as connected; else disconnected" class="mt-4 flex justify-center">
<mat-spinner diameter="32"></mat-spinner>
</div>
<ng-template #disconnected>
<p class="text-gray-500 p-5">
Please connect your wallet to be able to send transactions.
</p>
</ng-template>
</ng-template>

<swal
#errorSwal
title="Ops! Something went wrong"
[text]="errorMessage"
icon="error"
[showCancelButton]="false"
[focusCancel]="false"
/>

<swal
#confirmationSwal
title="The transaction has been sent, yay! 🎉"
text="Your transaction has been sent successfully. You can check the status of your transaction in the transaction history."
icon="success"
[showCancelButton]="false"
[focusCancel]="false"
confirmButtonText="Go to transaction history"
(confirm)="onGoToTransactionHistory()"
/>
84 changes: 84 additions & 0 deletions apps/webapp/src/app/components/account/send/send.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Component, effect, inject, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { CommonModule } from '@angular/common';
import { SwalComponent, SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2';
import { PublicKey } from '@solana/web3.js';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import Swal from 'sweetalert2';

import { WalletStore } from '../../../store';
import {
TransferForm,
TransferFormComponent,
} from '../../forms/transfer/transfer.component';
import { environment } from '../../../../environments/environment';

@Component({
selector: 'webapp-account-send',
standalone: true,
imports: [
CommonModule,
TransferFormComponent,
SweetAlert2Module,
MatProgressSpinnerModule,
],
templateUrl: './send.component.html',
providers: [WalletStore],
})
export class SendComponent implements OnInit {
readonly walletStore = inject(WalletStore);
readonly isSendTransactionLoading = this.walletStore.isLoading;
readonly publicKey$ = this.walletStore.wallet().publicKey$;
readonly connected$ = this.walletStore.wallet().connected$;
errorMessage = '';
@ViewChild('errorSwal')
public readonly errorSwal!: SwalComponent;
@ViewChild('confirmationSwal')
public readonly confirmationSwal!: SwalComponent;

constructor(private router: Router) {
effect(() => {
if (this.walletStore.error && this.walletStore.error()) {
const error = this.walletStore.error();
console.error('error', error);
this.errorMessage =
error || 'An error occurred while sending transaction';
this.errorSwal.fire();
}
});
effect(() => {
if (this.walletStore.signature && this.walletStore.signature()) {
console.warn('signature', this.walletStore.signature());
this.confirmationSwal.fire();
}
});
}

ngOnInit() {
this.walletStore.clearSignature();
}

async onSubmitForm(payload: TransferForm, publicKey: PublicKey) {
this.walletStore.sendTransaction({
amount: payload.amount,
memo: payload.memo,
tokenAddress: environment.mintUSDC,
senderAddress: publicKey.toBase58(),
receiverAddress: payload.receiver,
});

Swal.fire({
title: 'Loading...',
html: 'Please wait...',
allowEscapeKey: false,
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
},
});
}

onGoToTransactionHistory() {
this.router.navigate(['/account']);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@

<mat-tab-group preserveContent backgroundColor="primary">
<mat-tab label="Wallet Balance" class="text-black">
<div
*ngIf="(account$ | async) as account; else elseAccount"
class="rounded-lg bg-gray-50 px-4 py-6 sm:flex sm:items-center sm:justify-between sm:space-x-6 sm:px-6 lg:space-x-8">
<dl
class="flex-auto space-y-6 divide-y divide-gray-200 text-sm text-gray-600 sm:grid sm:grid-cols-3 sm:gap-x-6 sm:space-y-0 sm:divide-y-0 lg:w-1/2 lg:flex-none lg:gap-x-8">
<div class="flex justify-between sm:block">
<dd class="sm:mt-1">
<img [src]="account.info.image" alt="account.info.name"
class="h-16 w-16 rounded object-cover object-center" />
</dd>
</div>
<div class="flex justify-between pt-6 sm:block sm:pt-0">
<dt class="font-medium text-gray-900">Balance</dt>
<dd class="sm:mt-1">{{ account.balance }}</dd>
</div>
<div class="flex justify-between pt-6 font-medium text-gray-900 sm:block sm:pt-0">
<dt>Is Frozen</dt>
<dd class="sm:mt-1">
{{ account.isFrozen ? 'Yes' : 'No' }}
</dd>
</div>
</dl>
</div>
<ng-template #elseAccount>
<div *ngIf="(connected$ | async) as connected; else disconnected" class="mt-4 flex justify-center">
<mat-spinner diameter="32"></mat-spinner>
</div>
<ng-template #disconnected>
<p class="text-gray-500 p-5">
Please connect your wallet to see your balance.
</p>
</ng-template>
</ng-template>
</mat-tab>
<mat-tab label="Transaction History" class="text-black">
<p *ngIf="(connected$ | async) === false" class="text-gray-500 p-5">
Please connect your wallet to see your history.
</p>
<div *ngIf="!!isTransactionsLoading?.()" class="mt-4 flex justify-center">
<mat-spinner diameter="32"></mat-spinner>
</div>
<table *ngIf="!!transactions().length && (connected$ | async)" class="mt-4 w-full text-gray-500 sm:mt-6 table-auto">
<thead class="text-left text-sm text-gray-500">
<tr>
<th scope="col" class="py-3 pr-8 font-normal">
Type
</th>
<th scope="col" class="hidden sm:w-2/5 lg:w-1/3 py-3 pr-8 font-normal sm:table-cell">
Memo
</th>
<th scope="col" class="py-3 pr-8 font-normal sm:table-cell">
Amount
</th>
<th scope="col" class="w-0 py-3 font-normal">
Date
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 border-b border-gray-200 text-sm sm:border-t">
<tr class="text-medium items-center" *ngFor="let transaction of transactions()">
<td class="py-6 pr-8">
<div class="flex items-center">
<div>
<div class="font-medium text-gray-900">
{{ transaction.type }}
</div>
</div>
</div>
</td>
<td class="hidden py-6 pr-8 sm:table-cell text-gray-900">
{{ transaction.memo }}
</td>
<td class="py-6 pr-8 sm:table-cell text-gray-900 font-bold text-lg flex flex-row items-center gap-3 h-full align-middle">
{{ transaction.amount }}
<ng-icon
*ngIf="transaction.sign !== undefined"
[name]="transaction.sign > 1 ? 'heroArrowUp' : 'heroArrowDown'"
class="h-4 w-4"
[ngClass]="transaction.sign > 1 ? 'text-green-500' : 'text-red-500'"
aria-hidden="true"
/>
</td>
<td class="py-6 text-gray-900">
{{ transaction.timestamp | date: 'short' }}
</td>
</tr>
</tbody>
</table>
<div *ngIf="error && error()?.length" class="mt-4">
<div class="text-red-600">{{ error() }}</div>
<button (click)="loadTransactions()" class="text-sm font-medium text-indigo-600 hover:text-indigo-500">
Try again
</button>
</div>
</mat-tab>
</mat-tab-group>
32 changes: 32 additions & 0 deletions apps/webapp/src/app/components/account/wallet/wallet.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Component, inject, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatTabsModule } from '@angular/material/tabs';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { heroArrowUp, heroArrowDown } from '@ng-icons/heroicons/outline';
import { NgIconComponent, provideIcons } from '@ng-icons/core';

import { WalletStore } from '../../../store';

@Component({
selector: 'webapp-account-wallet',
standalone: true,
imports: [CommonModule, MatTabsModule, MatProgressSpinnerModule, NgIconComponent],
templateUrl: './wallet.component.html',
providers: [WalletStore, provideIcons({ heroArrowUp, heroArrowDown })],
})
export class WalletComponent implements OnInit {
readonly walletStore = inject(WalletStore);
readonly account$ = this.walletStore.account();
readonly connected$ = this.walletStore.wallet().connected$;
readonly transactions = this.walletStore.transactions;
readonly isTransactionsLoading = this.walletStore.isLoading;
readonly error = this.walletStore.error;

ngOnInit() {
this.loadTransactions();
}

loadTransactions() {
this.walletStore.loadTransactions(10);
}
}
Loading

0 comments on commit 310e5c9

Please sign in to comment.