iOS MFE


CardListView Microfrontend (iOS)

Part of the DigitalCardEngineSDK Library for iOS (SwiftUI)

This microfrontend displays a user’s cards. It is embedded into host apps — the host only needs to provide an auth token and the callbacks described below.

Callbacks

CardListView exposes three callbacks that let the host app respond to user actions:

  • onSelect(CardEntity) — fired when the user taps a card row.
  • onAddCard() — fired when the user taps the Add Card button.
  • onError(DCEUIError) — fired when an error occurs while loading cards.

All callbacks are invoked on the main thread to simplify UI navigation.


Callback Signatures

public struct CardListView: View {
    public init(
        onSelect: (CardEntity) -> Void,
        onAddCard: () -> Void,
        onError: ((DCEUIError) -> Void)? = nil
    ) { /* ... */ }
}

onSelect

Triggered when a user selects a card row. Provides a CardEntity containing aggregated information suitable for navigation to a Card Details screen or for subsequent API calls (e.g., via DigitalCardEngineSDK).

onAddCard

Triggered when the user taps the Add Card button. This is an optional button shown when actionButton is enabled in CardListViewProperties.

onError

Triggered when an error occurs while loading the card list. Provides a DCEUIError that wraps the underlying CardProviderException. This optional callback allows the host app to handle errors appropriately (e.g., showing an alert, logging out the user, or displaying custom error UI).

Error Type

public enum DCEUIError: Error {
    case cardProviderxception(CardProviderException)
}

Note: The onError callback is optional. If not provided, errors will be silently caught but not reported to the host app.

CardEntity Type

public class CardEntity: Codable {
    public let receivedCard: ReceivedCard
    public let cardArt: String?             // base64-encoded art (if available)
    public let isReceiver: Bool?            // indicates viewer role
    public let transactionHistory: [Transaction]? // may be nil if not pre-fetched
    public let events: [CardEvent]?         // lifecycle or activity events
    public let assetType: AssetType?        // domain-specific categorization
    public let metadata: CardMetadata?      // extensible key-value info
}

public class ReceivedCard: Codable {
    public let giftCardId: String
    public let expiryDate: String
    public let cardArtId: String
    public let balance: Double?
    public let name: String?
    public let lastName: String?
    public let last4: String?
    public let message: CardMessage?
    public let status: ActivationStatus?
    public let cardLabel: String?
}

Nullability: Many properties are optional to accommodate partial back-end payloads and progressive loading.

Customization

This package exposes lightweight types to configure CardListView behavior and visuals. Customization can be done in two ways:

  1. Global defaults via StyleConfiguration — Applied to all views across the app
  2. Runtime overrides via method parameters — Passed directly when creating a view, overriding global defaults

When both are provided, runtime parameters take precedence over global configuration.

CardListViewProperties

High‑level toggles that control what UI elements appear and which visual style is used.

public struct CardListViewProperties {
    public var title: Bool = true
    public var actionButton: Bool = true
    public var dividers: Bool = true
    public var cardListLayout: CardListViewLayout = .largeLayout
}
PropertyTypeDefaultDescription
titleBooltrueShow the list header/title.
actionButtonBooltrueShow the Add Card button.
dividersBooltrueRender separators between card rows.
cardListLayoutCardListViewLayout.largeLayoutPick between compact (.defaultLayout) and spacious (.largeLayout) list layouts.

CardListViewLayout

Enumeration that defines the overall density and typography scale of the list.

public enum CardListViewLayout {
    case defaultLayout   // Compact rows
    case largeLayout     // Square cards with a larger preview
}
  • .defaultLayout — Best for dashboards or tight layouts.
  • .largeLayout — Ideal for a dedicated "Cards" screen (default option).

Usage

let props = sdk.getStyleConfiguration().cardListViewProperties
props.title = false
props.actionButton = true
props.cardListLayout = .defaultLayout

CardListViewStyle

Low‑level visual tokens that fine‑tune paddings, gaps, and corner radius for the list container and rows.

public struct CardListViewStyle {
    public var internalHorizontalPadding: CGFloat = 16
    public var internalVerticalPadding: CGFloat = 12
    public var externalPadding: CGFloat = 16
    public var internalGap: CGFloat = 16
    public var radius: CGFloat = 12
}
PropertyTypeDefaultApplies to
internalHorizontalPaddingCGFloat16Left/right padding inside each card row.
internalVerticalPaddingCGFloat12Top/bottom padding inside each card row.
externalPaddingCGFloat16Padding around the whole list/container.
internalGapCGFloat16Spacing between stacked elements (e.g., title ↔ list, rows ↔ footer).
radiusCGFloat12Corner radius for card row backgrounds or list container.

Usage

let style = sdk.getStyleConfiguration().cardListViewStyle
style.internalHorizontalPadding = 10
style.radius = 0
style.internalGap = 10

Runtime Customization

In addition to global configuration, you can pass properties and style directly to individual views. This allows per-instance customization without affecting other views.

Method Signature

func getCardListView(
    properties: CardListViewProperties? = nil,
    style: CardListViewStyle? = nil,
    onSelect: @escaping (CardEntity) -> Void,
    onAddCard: @escaping () -> Void,
    onError: ((DCEUIError) -> Void)? = nil
) throws -> AnyView

Parameters

  • properties — Optional. Overrides global CardListViewProperties for this view instance.
  • style — Optional. Overrides global CardListViewStyle for this view instance.

If not provided, the view falls back to the global configuration from sdk.getStyleConfiguration().

Example: Per-View Customization

struct CardsScreen: View {
    let sdk: DigitalCardEngine

    var body: some View {
        // Custom properties for this specific view
        let customProps = CardListViewProperties(
            title: false,
            actionButton: true,
            dividers: false,
            cardListLayout: .defaultLayout
        )
        
        let customStyle = CardListViewStyle(
            internalHorizontalPadding: 8,
            internalVerticalPadding: 8,
            externalPadding: 12,
            internalGap: 8,
            radius: 8
        )
        
        return try? sdk.getCardListView(
            properties: customProps,
            style: customStyle,
            onSelect: { card in print("Selected: \(card)") },
            onAddCard: { print("Add card") }
        )
    }
}

Note: Runtime parameters take precedence over global StyleConfiguration. This allows you to have app-wide defaults while customizing specific screens.


Usage Example

Simple usage:

import SwiftUI
import DigitalCardEngineSDK

struct CardsScreen: View {
    let sdk: DigitalCardEngine

    init(authToken: String) {
        self.sdk = DigitalCardEngine(token: authToken)
    }

    var body: some View {
        sdk.getCardListView(
            onSelect: { card in print("Open card: \(card)") },
            onAddCard: { print("Add new card") }
        )
    }
}

Customization:

import SwiftUI
import DigitalCardEngineSDK

struct CardsScreen: View {
    let sdk: DigitalCardEngine

    init(authToken: String) {
        sdk = DigitalCardEngine(token: authToken)

        let props = sdk.getStyleConfiguration().cardListViewProperties
        props.title = false
        props.actionButton = true
        props.cardListLayout = .defaultLayout

        let style = sdk.getStyleConfiguration().cardListViewStyle
        style.internalHorizontalPadding = 10
        style.radius = 0
        style.internalGap = 10
    }

    var body: some View {
        sdk.getCardListView(
            onSelect: { card in print("Open card: \(card)") },
            onAddCard: { print("Add new card") }
        )
    }
}

Data Source & API Integration

This document describes how the CardListView microfrontend loads its data and maps API responses to UI. The view performs two GET requests:

  1. Gift cardsGET /receiver/v2/gift-cards
  2. Card artGET /receiver/v1/card-arts

Both calls are authenticated via the authToken supplied to DigitalCardEngineSDK.


1) GET /receiver/v2/gift-cards

Example response (abridged)

[
  {
    "value": {
      "giftCardId": "0f2b6046-3784-400d-9a86-a18f9fe09a20",
      "cardLabel": "GiftCard",
      "expiryDate": "2025-12-31",
      "cardArtId": "0b323e0a-a61c-439b-ae69-8ca465961a3e",
      "balance": 500,
      "name": "Desarae",
      "lastName": "Sanderson",
      "message": {
        "receiver": "Dear Friend!",
        "text": "Happy Birthday!"
      },
      "status": "ACTIVE",
      "last4": "3452"
    }
  }
]

Field mapping → CardListView

Source fieldUsed forNotes
value.cardLabelTitle on card rowShown as the main label.
value.balanceBalanceRendered as numeric balance
value.last4Masked PAN (…1234)Displayed as •••• last4 on the card row.
value.cardArtIdCard art lookupUsed to retrieve base64 artwork from the card-arts endpoint.

Other fields (e.g., expiryDate, status) are fetched but not displayed in the cell.


2) GET /receiver/v1/card-arts

Purpose

Returns a list of available card artworks encoded in base64. CardListView finds the matching item by cardArtId obtained from the gift-cards call.

Example response (abridged)

[
  {
    "cardArt": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHg...",
    "cardArtId": "0b323e0a-a61c-439b-ae69-8ca465961a3e"
  }
]

Mapping

  • Match on cardArtId.
  • Decode cardArt (base64) into an image and show as the preview in the card row.