iOS MFE

CardDetailsView Microfrontend (iOS)

Part of the DigitalCardEngineSDK Library for iOS (SwiftUI)

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

Callbacks

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

CardDetailsView exposes four callbacks that let the host app respond to user actions:

  • onLockCard(CardEntity) — fired when the user taps the Lock Card button.
  • onManageCard(CardEntity) — fired when the user taps the Manage Card button.
  • onFocusedCardChange(CardEntity) — fired when the card slider focuses a new card, allowing hosts to react to the card currently in view (for example, updating surrounding content).
  • onError(DCEUIError) — fired when an error occurs while loading cards (when slider is enabled).

Callback Signatures

public struct CardDetailsView: View {
    public init(
        onLockCard: (CardEntity) -> Void,
        onManageCard: (CardEntity) -> Void,
        onFocusedCardChange: ((CardEntity) -> Void)? = nil,
        onError: ((DCEUIError) -> Void)? = nil
    ) { /* ... */ }
}

onLockCard

Triggered when a user presses the Lock button. Provides a CardEntity containing aggregated information suitable for subsequent API calls (e.g., via DigitalCardEngineSDK).

onManageCard

Triggered when a user presses the Manage button. Provides a CardEntity containing aggregated information suitable for subsequent API calls (e.g., via DigitalCardEngineSDK).

onFocusedCardChange

Triggered whenever a visible card in the slider becomes focused (for hosts that enable the slider). Receives the focused CardEntity, so you can refresh transaction lists or other contextual UI in sync with the slider position.

onError

Triggered when an error occurs while loading cards for the slider (only applies when slider mode is enabled). 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 CardDetailsView 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.

CardDetailsViewProperties

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

public struct CardDetailsViewProperties {
    public var actionButton: Bool = true
    public var slider: Bool = false
    public var cardInfoLayout: CardDetailsViewLayout = .detailLayout
}
PropertyTypeDefaultDescription
actionButtonBooltrueShow the action buttons.
sliderBoolfalseShow the horizontal slider that lets users swipe through cards.
cardInfoLayoutCardDetailsViewLayout.detailLayoutChoose between compact (.briefLayout) and expanded (.detailLayout) layouts.

CardDetailsViewLayout

Defines the layout of card information display.

public enum CardDetailsViewLayout {
    case briefLayout   // Compact representation
    case detailLayout  // Full description with all available fields
}

Usage

let props = sdk.getStyleConfiguration().cardDetailsViewProperties
props.actionButton = false
props.slider = true
props.cardInfoLayout = .briefLayout

CardDetailsViewStyle

Low‑level visual tokens that fine‑tune padding, spacing, and corner radius for the card container and its sections.

public struct CardDetailsViewStyle {
    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 the card details container.
internalVerticalPaddingCGFloat12Top/bottom padding inside the container.
externalPaddingCGFloat16Outer padding around the card details container.
internalGapCGFloat16Spacing between stacked elements (e.g., title ↔ list, rows ↔ footer).
radiusCGFloat12Corner radius for the card image and container.

Usage

let style = sdk.getStyleConfiguration().cardDetailsViewStyle
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 getCardDetailsView(
    card: CardEntity,
    properties: CardDetailsViewProperties? = nil,
    style: CardDetailsViewStyle? = nil,
    onLockCard: @escaping (CardEntity) -> Void,
    onManageCard: @escaping (CardEntity) -> Void,
    onFocusedCardChange: ((CardEntity) -> Void)?,
    onError: ((DCEUIError) -> Void)? = nil
) throws -> AnyView

Parameters

  • properties — Optional. Overrides global CardDetailsViewProperties for this view instance.
  • style — Optional. Overrides global CardDetailsViewStyle for this view instance.

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

Example: Per-View Customization

struct CardDetailsScreen: View {
    let sdk: DigitalCardEngine
    let card: CardEntity

    var body: some View {
        // Custom properties for this specific view
        let customProps = CardDetailsViewProperties(
            actionButton: false,
            slider: true,
            cardInfoLayout: .briefLayout
        )
        
        let customStyle = CardDetailsViewStyle(
            internalHorizontalPadding: 12,
            internalVerticalPadding: 10,
            externalPadding: 8,
            internalGap: 12,
            radius: 16
        )
        
        return try? sdk.getCardDetailsView(
            card: card,
            properties: customProps,
            style: customStyle,
            onLockCard: { card in print("Lock: \(card)") },
            onManageCard: { card in print("Manage: \(card)") },
            onFocusedCardChange: nil
        )
    }
}

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 CardScreen: View {
    let sdk: DigitalCardEngine
    let card: CardEntity

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

    var body: some View {
        sdk.getCardDetailsView(
            card: card,
            onLockCard: { print("Lock card: \($0)") },
            onManageCard: { print("Manage card: \($0)") },
            onFocusedCardChange: { print("Focused card: \($0)") }
        )
    }
}