Skip to content

Commit

Permalink
Merge pull request #1805 from thebiggive/DON-1065-account-page-redesign
Browse files Browse the repository at this point in the history
Don 1065 account page redesign
  • Loading branch information
bdsl authored Dec 19, 2024
2 parents 993f40a + 3ff8f28 commit d717ee5
Show file tree
Hide file tree
Showing 15 changed files with 452 additions and 328 deletions.
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
"@angular/platform-server": "^18.2.8",
"@angular/router": "^18.2.8",
"@angular/ssr": "^18.2.8",
"@biggive/components": "^202412181130.0.0",
"@biggive/components-angular": "^202412181130.0.0",
"@biggive/components": "^202412181555.0.0",
"@biggive/components-angular": "^202412181555.0.0",
"@fortawesome/angular-fontawesome": "~0.15.0",
"@fortawesome/free-brands-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
Expand Down
15 changes: 15 additions & 0 deletions src/app/app-routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {Person} from "./person.model";
import {firstValueFrom} from "rxjs";
import {MandateComponent} from "./mandate/mandate.component";
import {Mandate} from "./mandate.model";
import {MyPaymentMethodsComponent} from "./my-payment-methods/my-payment-methods.component";

export const registerPath = 'register';
export const myAccountPath = 'my-account';
Expand Down Expand Up @@ -182,6 +183,20 @@ const routes: Routes = [
requireLogin,
],
},
{
path: 'my-account/payment-methods',
pathMatch: 'full',
resolve: {
person: async () => await firstValueFrom(inject(IdentityService).getLoggedInPerson()),
paymentMethods: async () => {
return await inject(DonationService).getPaymentMethods();
},
},
component: MyPaymentMethodsComponent,
canActivate: [
requireLogin,
],
},
{
path: ':campaignSlug/:fundSlug',
pathMatch: 'full',
Expand Down
25 changes: 16 additions & 9 deletions src/app/donation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {isPlatformServer} from '@angular/common';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import {Inject, Injectable, InjectionToken, makeStateKey, Optional, PLATFORM_ID, TransferState,} from '@angular/core';
import {SESSION_STORAGE, StorageService} from 'ngx-webstorage-service';
import {Observable, of} from 'rxjs';
import {firstValueFrom, Observable, of} from 'rxjs';
import {ConfirmationToken, PaymentIntent, PaymentMethod} from '@stripe/stripe-js';

import {COUNTRY_CODE} from './country-code.token';
Expand Down Expand Up @@ -170,17 +170,24 @@ export class DonationService {
);
}

getPaymentMethods(
personId?: string,
jwt?: string,
{cacheBust}: { cacheBust?: boolean} = {cacheBust: false}
): Observable<{ data: PaymentMethod[] }> {
async getPaymentMethods(
{cacheBust}: { cacheBust?: boolean } = {cacheBust: false}
): Promise<PaymentMethod[]> {
const jwt = this.identityService.getJWT();
const person = await firstValueFrom(this.identityService.getLoggedInPerson());

if (!person) {
throw new Error("logged in person required");
}

const cacheBuster = cacheBust ? ("?t=" + new Date().getTime()) : '';

return this.http.get<{ data: PaymentMethod[] }>(
`${environment.donationsApiPrefix}/people/${personId}/payment_methods${cacheBuster}`,
const response = await firstValueFrom(this.http.get<{ data: PaymentMethod[] }>(
`${environment.donationsApiPrefix}/people/${person.id}/payment_methods${cacheBuster}`,
getPersonAuthHttpOptions(jwt),
);
));

return response.data;
}

create(donation: Donation, personId?: string, jwt?: string): Observable<DonationCreatedResponse> {
Expand Down
16 changes: 8 additions & 8 deletions src/app/highlight-cards/HighlightCard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ describe('highlightCard', () => {
cardFromApi
);

expect(highlightCardForHomepage.backgroundImageUrl.href).toBe('https://example.com/assets/images/wmg-purple-texture.jpg');
expect(highlightCardForHomepage.iconColor).toBe('brand-wgmf-purple');
expect(highlightCardForHomepage.background.image.href).toBe('https://example.com/assets/images/wmg-purple-texture.jpg');
expect(highlightCardForHomepage.icon?.color).toBe('brand-wgmf-purple');
});

it('should use appropriate colour for emergency campaign', () => {
Expand All @@ -47,8 +47,8 @@ describe('highlightCard', () => {
);

// todo - check what background we had for EMF cards in the past.
expect(highlightCardForHomepage.backgroundImageUrl.href).toBe('https://example.com/assets/images/emergency-card.webp');
expect(highlightCardForHomepage.iconColor).toBe('brand-emf-yellow');
expect(highlightCardForHomepage.background.image.href).toBe('https://example.com/assets/images/emergency-card.webp');
expect(highlightCardForHomepage.icon?.color).toBe('brand-emf-yellow');
});

it('should use blue primary colour by default', () => {
Expand All @@ -69,8 +69,8 @@ describe('highlightCard', () => {
cardFromApi
);

expect(highlightCardForHomepage.backgroundImageUrl.href).toBe('https://example.com/assets/images/blue-texture.jpg');
expect(highlightCardForHomepage.iconColor).toBe('primary');
expect(highlightCardForHomepage.background.image.href).toBe('https://example.com/assets/images/blue-texture.jpg');
expect(highlightCardForHomepage.icon?.color).toBe('primary');
});

function cardLinkingTo(href: string): SfApiHighlightCard {
Expand Down Expand Up @@ -160,8 +160,8 @@ describe('highlightCard', () => {
cardFromApi
);

expect(highlightCardForHomepage.backgroundImageUrl.href).toBe('https://example.com/assets/images/join-mailing-list.webp');
expect(highlightCardForHomepage.iconColor).toBe('primary');
expect(highlightCardForHomepage.background.image.href).toBe('https://example.com/assets/images/join-mailing-list.webp');
expect(highlightCardForHomepage.icon?.color).toBe('primary');
});
});

Expand Down
15 changes: 10 additions & 5 deletions src/app/highlight-cards/HighlightCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import {brandColour} from "@biggive/components/dist/types/globals/brand-colour"
import {environment} from "../../environments/environment";

export type HighlightCard = {
backgroundImageUrl: URL,
background: {
// colour appears 'behind' the image, only seen if image doesn't load or during loading.
color?: brandColour;
image: URL
},
// There is ambiguity in the components library about whether brand-6 is grey or turquoise. Best to avoid using brand-6 and
// use brand-mhf-turquoise instead.
// See https://github.com/thebiggive/donate-frontend/pull/1076#issuecomment-1523472452
// For other colour details see https://github.com/thebiggive/components/blob/develop/src/globals/brand-colour.ts
iconColor: brandColour,
icon?: {color: brandColour},
headerText: string,
bodyText: string,
button: {
Expand All @@ -25,7 +29,7 @@ export type campaignFamilyName =
|'artsforImpact'
|'emergencyMatch';

export type SfApiHighlightCard = Omit<HighlightCard, 'backgroundImageUrl'|'iconColor'|'button'> & {
export type SfApiHighlightCard = Omit<HighlightCard, 'background'|'icon'|'button'> & {
campaignFamily: campaignFamilyName | null
cardStyle: 'DONATE_NOW' | 'SEE_RESULTS' | 'APPLY_NOW' | 'SAVE_THE_DATE' | 'JOIN_MAILING_LIST' | 'REGISTER_INTEREST' | 'EXPLORE',
button: {
Expand Down Expand Up @@ -66,11 +70,12 @@ export const SFAPIHighlightCardToHighlightCard = (experienceUriPrefix: string, b
href = new URL(donateUriPrefix + '/christmas-challenge-2024');
}

const color = iconColor(sfApiHighlightCard, campaignFamilyColours);
return {
headerText: sfApiHighlightCard.headerText,
bodyText: sfApiHighlightCard.bodyText,
iconColor: iconColor(sfApiHighlightCard, campaignFamilyColours),
backgroundImageUrl,
icon: {color},
background: {image: backgroundImageUrl, color },
button: {
text: sfApiHighlightCard.button.text,
href: href,
Expand Down
14 changes: 8 additions & 6 deletions src/app/highlight-cards/highlight-cards.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
[headingLevel]="2"
[buttonColourScheme]="'clear-primary'"
[class]="'basic-card-padding'"
[iconColour]="highlightCards[0]!.iconColor"
[backgroundColour]="highlightCards[0]!.iconColor"
[backgroundImageUrl]="highlightCards[0]!.backgroundImageUrl.toString()"
[iconColour]="highlightCards[0]!.icon?.color"
[icon]="!! highlightCards[0]!.icon"
[backgroundColour]="highlightCards[0]!.icon?.color"
[backgroundImageUrl]="highlightCards[0]!.background.image.toString()"
[mainTitle]="highlightCards[0]!.headerText"
[subtitle]="highlightCards[0]!.bodyText"
[buttonLabel]="highlightCards[0]!.button.text"
Expand All @@ -25,9 +26,10 @@
[headingLevel]="2"
[buttonColourScheme]="'clear-primary'"
[class]="'basic-card-padding'"
[iconColour]="card.iconColor"
[backgroundColour]="card.iconColor"
[backgroundImageUrl]="card.backgroundImageUrl.toString()"
[iconColour]="card.icon?.color"
[icon]="!! card.icon"
[backgroundColour]="card.background.color"
[backgroundImageUrl]="card.background.image.toString()"
[mainTitle]="card.headerText"
[subtitle]="card.bodyText"
[buttonLabel]="card.button.text"
Expand Down
119 changes: 4 additions & 115 deletions src/app/my-account/my-account.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,125 +39,14 @@ <h2>Your Details</h2>

<biggive-page-section>

<div class="account-actions">
<biggive-button
space-above="5"
colour-scheme="white"
label="Explore Campaigns"
full-width="true"
size="medium"
url="/explore"
/>

<biggive-button
space-above="5"
colour-scheme="white"
label="Transfer Donation Funds"
full-width="true"
size="medium"
url="/transfer-funds"
/>

<biggive-button
space-above="5"
colour-scheme="white"
label="Your donations"
full-width="true"
size="medium"
url="/my-account/donations"
/>

@if(flags.regularGivingEnabled) {
<biggive-button
space-above="5"
colour-scheme="white"
label="Your Regular Giving"
full-width="true"
size="medium"
url="/my-account/regular-giving"
/>
}
</div>

<app-highlight-cards
[highlightCards]="actions"
space-above="5">
</app-highlight-cards>

</biggive-page-section>

@if (person) {
<biggive-page-section>
<h2>Your Payment Methods</h2>
@if (hasDonationFunds) {
<h3>Donation Funds</h3>
}
@if (hasDonationFunds) {
<div>
<p>Available balance: <strong>{{ ((person.cash_balance?.gbp || 0) / 100) | exactCurrency:'GBP' }}</strong></p>
</div>
}
@if (registerErrorDescription) {
<p class="error" aria-live="assertive">
<fa-icon [icon]="faExclamationTriangle"></fa-icon>
{{ registerErrorDescription }}
</p>
}
@if (registerSucessMessage) {
<p class="update-success" aria-live="assertive">
{{ registerSucessMessage }}
</p>
}
@if (paymentMethods === undefined) {
<div>
<mat-spinner color="accent" [diameter]="40" aria-label="Loading payment methods"></mat-spinner>
</div>
}
<h3>
Saved Cards
</h3>
@if (hasSavedPaymentMethods) {
<table id="paymentMethods">
@for (method of paymentMethods; track method.id) {
<tr>
<td class="cardBrand">
<div class="cardBrand">{{(method.card?.brand || method.type).toUpperCase()}}</div>
@if (method.card !== undefined) {
<div>
Card Ending: {{method.card.last4}}
</div>
}
@if (method.card !== undefined) {
<div class="cardExpiry">
Expiry Date: {{method.card.exp_month.toString().padStart(2, "0")}}/{{method.card.exp_year}}
</div>
}
</td>
<td class="cardExpiry">
@if (method.card !== undefined) {
<div>
Expiry Date: {{method.card.exp_month.toString().padStart(2, "0")}}/{{method.card.exp_year}}
</div>
}
</td>
@if (method.card !== undefined) {
<td class="cardUpdateButton"
>
<!-- href must be set to make link interactable with keyboard-->
<a href="javascript:void(0);" (click)="updateCard(method.id, method.card, method.billing_details)">
Edit
</a>
</td>
}
<td class="cardDeleteButton">
<a href="javascript:void(0);" (click)="deleteMethod(method)">Delete</a>
</td>
</tr>
}
</table>
}
@if (paymentMethods !== undefined && paymentMethods.length === 0) {
<div>
No saved cards
</div>
}
</biggive-page-section>
}
</div>
</main>
Loading

0 comments on commit d717ee5

Please sign in to comment.