Seller Card Pages
Two routes serve the card product. Which one a supplier lands on is decided by
SellerCardListGuard.
Routing decision
canActivate(): Observable<boolean | UrlTree> {
this.store.dispatch(loadPaymentMethods());
this.store.dispatch(loadAirwallexCards());
return combineLatest([
this.store.pipe(select(selectIsPaymentMethodsLoaded)),
this.store.pipe(select(selectPaymentsMethodLoading)),
this.store.pipe(select(selectAirwallexCardsLoaded)),
]).pipe(
filter(([loaded, loading, awxLoaded]) => loaded && !loading && awxLoaded), (1)
take(1),
withLatestFrom(
this.store.pipe(select(selectPcardsPaymentMethods)),
this.store.pipe(select(selectHasAirwallexCards)),
),
map(([_, methods, hasAirwallexCards]) => {
const hasPcards = isArray(methods) && !isEmpty(methods);
if (hasPcards || hasAirwallexCards) { return true; }
return this.router.parseUrl('newcard'); (2)
}),
);
}
| 1 | The guard waits until both card sources have settled, so it never routes on a half-loaded picture. |
| 2 | No cards from either issuer → the ordering funnel. |
/seller-card
├─ has Marqeta p-cards or Airwallex cards ──▶ SellerCardListComponent
└─ has neither ─────────────────────────────▶ redirect to /newcard
/seller-card — the list page
SellerCardModule → SellerCardPage → SellerCardListComponent.
Imports and composition:
|
The |
|
The unified "Your Cards" panel rendering both issuers. |
|
Embedded transaction grid with card-specific empty-state copy. |
|
Shared report scaffolding. |
|
Presentation. |
Card operations are routed by provider. UnifiedSupplierCard.raw carries the
original provider model, so the page dispatches to the Marqeta or Airwallex
service accordingly:
| Action | Marqeta | Airwallex |
|---|---|---|
Block |
|
|
Unblock |
|
|
View details |
|
|
Activate |
|
|
Every one of them requires a passed 2FA challenge — see Seller Card.
/newcard — the ordering funnel
NewCardModule (views/pages/newcard/).
|
The ordering page. |
|
Layout shell. |
|
Card benefits presentation. |
|
Page copy and option constants. |
|
Physical-card delivery address. |
Backed by the cardOrder slice:
loadCardProviders → loadCardProvidersSuccess which CardProvider / CardFormFactor combinations are available → supplier picks provider + form factor → (Airwallex only) accept cardholder terms → AirwallexCardService.saveConsent() → (physical only) shipping address + optional expedite → orderCard → AirwallexCardService.newCard() → orderCardSuccess
export enum CardProvider { Marqeta = 'marqeta', Airwallex = 'airwallex' }
export enum CardFormFactor { Physical = 'PHYSICAL', Virtual = 'VIRTUAL' }
|
Airwallex consent must be recorded before the order is placed. The new-card page
reads |
Request shaping differs by issuer — recipient_address and expedite_card are
only sent for issuers that ship a physical card; Airwallex uses the cardholder
address already on file.
Related surfaces
|
Standalone transaction report. |
|
Dashboard summary card. |
|
The unified card panel. |
|
Card artwork. |
|
Marqeta activation. |
|
Order or replace. |
|
Block and unblock confirmations. |
|
Reveal card details. |
|
Marqeta → Airwallex migration. |
|
Provider terms acceptance. |
Full business rules: Seller Card.