Skip to content

Commit

Permalink
fix: Fix UI for Virtual Cards (#2782)
Browse files Browse the repository at this point in the history
  • Loading branch information
bistaastha authored Mar 11, 2024
1 parent 7493bfd commit 1c6e82b
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 20 deletions.
8 changes: 7 additions & 1 deletion src/app/fyle/dashboard/card-stats/card-stats.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
></app-spent-cards>
</ng-container>
<ng-container *ngIf="isVirtualCardsEnabled.enabled">
<ng-container *ngIf="virtualCardDetails$ | async as cardDetails">
<ng-container *ngIf="virtualCardDetails$ | async as cardDetails; else shimmers">
<app-spent-cards
[cardDetails]="cardDetails"
[homeCurrency]="homeCurrency$ | async"
Expand All @@ -26,6 +26,12 @@
</ng-container>
</ng-container>

<ng-template #shimmers>
<div class="card-stats__shimmers">
<ion-skeleton-text data-testid="shimmer" animated class="card-stats__shimmers__card"></ion-skeleton-text>
<ion-skeleton-text data-testid="shimmer" animated class="card-stats__shimmers__card-lg"></ion-skeleton-text>
</div>
</ng-template>
<!-- Show add card empty state when the user doesn't have any cards, and has visa / mastercard rtf enabled to allow adding cards -->
<ng-container *ngIf="cardDetails?.length === 0 && (canAddCorporateCards$ | async)">
<div class="card-stats__header">CARD SPEND</div>
Expand Down
21 changes: 21 additions & 0 deletions src/app/fyle/dashboard/card-stats/card-stats.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,25 @@
padding-inline: 16px;
padding-bottom: 8px;
}

&__shimmers {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&__card {
height: 180px;
width: 280px;
border-radius: 16px;
margin-right: 24px;
margin-top: 20px;
}
&__card-lg {
height: 220px;
width: 80%;
border-radius: 16px;
margin-right: 24px;
bottom: 50px;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@
</ion-header>

<div *ngIf="isVirtualCardsEnabled$ | async as isVirtualCardsEnabled">
<div *ngIf="isVirtualCardsEnabled.enabled" class="manage-corporate-cards__segment-container">
<ion-segment (ionChange)="segmentChanged($event)" [value]="segmentValue" class="manage-corporate-cards__segment">
<ion-segment-button [value]="Segment.CORPORATE_CARDS" class="text-capitalize">Corporate Cards</ion-segment-button>
<ion-segment-button [value]="Segment.VIRTUAL_CARDS" class="text-capitalize">Virtual Cards</ion-segment-button>
</ion-segment>
<div *ngIf="corporateCards$ | async as corporateCards">
<div
*ngIf="isVirtualCardsEnabled.enabled && areVirtualCardsPresent(corporateCards)"
class="manage-corporate-cards__segment-container"
>
<ion-segment (ionChange)="segmentChanged($event)" [value]="segmentValue" class="manage-corporate-cards__segment">
<ion-segment-button [value]="Segment.CORPORATE_CARDS" class="text-capitalize"
>Corporate Cards</ion-segment-button
>
<ion-segment-button [value]="Segment.VIRTUAL_CARDS" class="text-capitalize">Virtual Cards</ion-segment-button>
</ion-segment>
</div>
</div>
</div>

Expand Down Expand Up @@ -80,7 +87,11 @@
</ng-container>

<ng-template #shimmers>
<ion-skeleton-text data-testid="shimmer" animated class="manage-corporate-cards__shimmer"></ion-skeleton-text>
<ion-skeleton-text
data-testid="shimmer"
animated
class="manage-corporate-cards__virtual-card-shimmer"
></ion-skeleton-text>
</ng-template>
</div>
</ion-content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

&__tab-available {
padding-top: 0;
display: flex;
align-items: center;
}

&__cards-list {
Expand Down Expand Up @@ -61,6 +63,12 @@
border-radius: 16px;
}

&__virtual-card-shimmer {
height: 180px;
width: 280px;
border-radius: 16px;
}

&__zero-state-container {
margin: auto;
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import { noop } from 'lodash';
import { TrackingService } from 'src/app/core/services/tracking.service';
import { cardUnenrolledProperties } from 'src/app/core/mock-data/corporate-card-trackers.data';
import { VirtualCardsService } from 'src/app/core/services/virtual-cards.service';
import { Virtual } from 'swiper';
import { ManageCardsPageSegment } from 'src/app/core/enums/manage-cards-page-segment.enum';
import { virtualCardCombinedResponse } from 'src/app/core/mock-data/virtual-card-combined-response.data';
import { virtualCardDetailsCombined } from 'src/app/core/mock-data/platform-corporate-card-detail.data';
Expand Down Expand Up @@ -235,6 +234,11 @@ describe('ManageCorporateCardsPage', () => {
});
});

it('areVirtualCardsPresent(): check in corporateCards list if any of the cards is a virtual card', () => {
const response = component.areVirtualCardsPresent([virtualCard]);
expect(response).toEqual(true);
});

describe('add card flow', () => {
let addCardPopoverSpy: jasmine.SpyObj<HTMLIonPopoverElement>;
let cardAddedPopoverSpy: jasmine.SpyObj<HTMLIonPopoverElement>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ export class ManageCorporateCardsPage {
}
}

areVirtualCardsPresent(corporateCards: PlatformCorporateCard[]) {
return corporateCards.filter((corporateCard) => corporateCard.virtual_card_id).length > 0;
}

refresh(event: RefresherCustomEvent): void {
this.corporateCreditCardExpenseService.clearCache().subscribe(() => {
this.loadCorporateCards$.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
{{ cardNumber | slice : 10 : 15 }}
</div>
<ion-icon
*ngIf="cardStatus !== CardStatus.DELETED && cardStatus !== CardStatus.EXPIRED"
src="../../../../../assets/svg/duplicate.svg"
(press)="toggleShowCardNumber()"
(pressup)="hideCardNumberAndCopy()"
Expand All @@ -41,6 +42,7 @@
<div *ngIf="!showCvv" class="virtual-card__card-fields__cvv-mask">****</div>
<div *ngIf="showCvv" class="virtual-card__card-fields__cvv-number">{{ cvv }}</div>
<ion-icon
*ngIf="cardStatus !== CardStatus.DELETED && cardStatus !== CardStatus.EXPIRED"
class="virtual-card__card-fields__cvv-copy-icon"
src="../../../../../assets/svg/duplicate.svg"
(press)="toggleShowCvv()"
Expand Down
14 changes: 10 additions & 4 deletions src/app/shared/components/virtual-card/virtual-card.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

&__card-number {
color: $pure-white;
margin-top: 30px;
margin-top: 40px;
display: flex;
flex-direction: column;
align-items: center;
Expand All @@ -27,6 +27,10 @@
font-weight: 500;
font-size: 12px;
}
&__copy-icon {
height: 22px;
width: 22px;
}
&__card-number-container {
display: flex;
align-items: center;
Expand Down Expand Up @@ -84,6 +88,7 @@
display: flex;
justify-content: center;
align-items: center;
margin-top: 4px;
}
&__cvv-number {
font-size: 12px;
Expand All @@ -93,11 +98,12 @@
display: flex;
justify-content: center;
align-items: start;
margin-top: 2px;
}
&__cvv-copy-icon {
height: 12px;
width: 12px;
margin: 2px 0 0 2px;
height: 20px;
width: 20px;
margin-left: 6px;
}
}
&__status-pill {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,27 +110,31 @@ describe('VirtualCardComponent', () => {
});
});

it('hideCvvAndCopy(): should hide cvv and call method to copy text to clipboard', () => {
it('hideCvvAndCopy(): should hide cvv and call method to copy text to clipboard', fakeAsync(() => {
component.cvv = '1234';
component.showCvv = true;
const copyToClipboardSpy = spyOn(component, 'copyToClipboard');

component.hideCvvAndCopy();

tick(1000);

expect(component.showCvv).toBeFalse();
expect(copyToClipboardSpy).toHaveBeenCalledOnceWith(component.cvv);
});
}));

it('hideCardNumberAndCopy(): should hide cvv and call method to copy text to clipboard', () => {
it('hideCardNumberAndCopy(): should hide cvv and call method to copy text to clipboard', fakeAsync(() => {
component.cardNumber = '123451234512345';
component.showCardNumber = true;
const copyToClipboardSpy = spyOn(component, 'copyToClipboard');

component.hideCardNumberAndCopy();

tick(1000);

expect(component.showCardNumber).toBeFalse();
expect(copyToClipboardSpy).toHaveBeenCalledOnceWith(component.cardNumber);
});
}));

it('toggleShowCardNumber(): should show card number if card number is hidden', () => {
component.showCardNumber = false;
Expand Down
15 changes: 11 additions & 4 deletions src/app/shared/components/virtual-card/virtual-card.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ClipboardService } from 'src/app/core/services/clipboard.service';
import { SnackbarPropertiesService } from 'src/app/core/services/snackbar-properties.service';
import { ToastMessageComponent } from '../toast-message/toast-message.component';
import { CardStatus } from 'src/app/core/enums/card-status.enum';
import { CardAddedComponent } from 'src/app/fyle/manage-corporate-cards/card-added/card-added.component';

@Component({
selector: 'app-virtual-card',
Expand Down Expand Up @@ -59,20 +60,26 @@ export class VirtualCardComponent implements OnInit {
}

hideCvvAndCopy() {
this.showCvv = false;
setTimeout(() => {
this.showCvv = false;
}, 1000);

this.copyToClipboard(this.cvv);
}

hideCardNumberAndCopy() {
this.showCardNumber = false;
setTimeout(() => {
this.showCardNumber = false;
}, 1000);

this.copyToClipboard(this.cardNumber);
}

toggleShowCardNumber() {
this.showCardNumber = !this.showCardNumber;
this.showCardNumber = true;
}

toggleShowCvv() {
this.showCvv = !this.showCvv;
this.showCvv = true;
}
}

0 comments on commit 1c6e82b

Please sign in to comment.