iOS SDK
Requirements
- Minimum operating system requirement is iOS 13
- Written in SwiftUI but can be used with UIKit
How to Integrate
Swift Package Manager
- The url is: https://github.com/Beam-Impact/BeamKit use up to next major version 1.0.0
- If you have a Package.swift file and want to add BeamKit as a dependency through that you may
dependencies: [
.package(url: "https://github.com/Beam-Impact/BeamKit", .upToNextMajor(from: "1.0.0"))
]
Carthage
- Add BeamKit to your Cartfile
github "Beam-Impact/BeamKit" ~> 1.0.0
- run
carthage update —use-xcframeworks - Add
BeamKit.xcframeworkto Frameworks, Libraries, and Embedded Content in your target
Import BeamKit
In any file that needs BeamKit, include import BeamKit at top.
Setup
Initialization
The main way that you interact with the BeamKit SDK is through the BKManager. Add BKManager as a var in the AppDelegate or SceneDelegate class then initialize the BKManager in your AppDelegate. This is necessary to set up the SDK as soon as possible. The apiKey & chainId can be acquired from your companies POC for the Beam integration.
BKManager(apiKey: String, // Unique key used for authorization
chainId: Int, // Unique identifier to your company
environment: BKAppEnvironment, // Indicates which endpoint to hit
logLevel: BKLogLevel, // What level of logging is preferred
fontRegular: FontInfo?, // Custom font struct for regular weight
fontSemiBold: FontInfo?, // Custom font struct for semi-bold weight
fontBold: FontInfo?, // Custom font struct for bold weight
progressBarConfig: BKProgressBarConfiguration, // Configuration for progress bar shown on widgets (defaults to standard)
schemaVersion: String, // The version number for any copy that has been customized using our remote config service (if none then pass in 1.0)
placeholderImage: String? = nil) // The name of the asset desired to be a placeholder image which will be shown while a remote image is being fetched asynchronously
class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
var bkManager: BKManager?
override init() {
self.bkManager = BKManager(apiKey: "publicKey.privateKey",
chainId: 1,
environment: .production,
logLevel: .debug,
fontRegular: FontInfo(fontFileName: "Regular-Font",
bundle: .main,
fileExtension: ".otf",
fontFamilyName: "Regular-Font-Name"),
fontSemiBold: FontInfo(fontFileName: "SemiBold-Font",
bundle: .main,
fileExtension: ".otf",
fontFamilyName: "SemiBold-Font-Name"),
fontBold: FontInfo(fontFileName: "Bold-Font",
bundle: .main,
fileExtension: ".otf",
fontFamilyName: "Bold-Font-Name"),
progressBarConfig: BKProgressBarConfiguration(height: 5.0,
borderConfig: BKBorderConfiguration(width: 0, color: .black, cornerRadius: 45),
gradient: [.red, .yellow, .orange],
backgroundColor: .gray),
schemaVersion: "1.0",
placeholderImage: "Placeholder.png")
}
}
Customization
Fonts
BeamKit gives you the ability to add a custom font for three different weights which are used throughout the SDK: regular, semi-bold, & bold.
- Add the font file to the project somewhere in the filesystem
- Create an instance of the class FontInfo for each weight
- Pass the FontInfo instance into the BKManager init corresponding to the desired weight
FontInfo(fontFileName: String, // The exact name for the file containing the font excluding the extension
bundle: Bundle, // This should be .main
fileExtension: String, // Either ".otf" or ".ttf"
fontFamilyName: String? = nil) // This often differs from the file name
let regularFont = FontInfo(fontFileName: "Regular-Font",
bundle: .main,
fileExtension: ".otf",
fontFamilyName: "Regular-Font-Name")
To get the family name, which isn’t always obvious and often is different than the file name you can add the following bit of code somewhere in your app and XCode will print all of the available family names in the terminal. (See the section in Apple’s documentation named Use Your Custom Font in Source Code)
for family in UIFont.familyNames.sorted() {
let names = UIFont.fontNames(forFamilyName: family)
print("Family: \(family) Font names: \(names)")
}
Progress Bar
The progress bar can be fully customized using the BKProgressBarConfiguration which is passed into the BKManager on init.
BKProgressBarConfiguration(height: CGFloat,
borderConfig: BKBorderConfiguration,
gradient: [Color]?,
backgroundColor: Color?)
let progressBarConfig = BKProgressBarConfiguration(height: 5.0,
borderConfig: BKBorderConfiguration(width: 0, color: .black, cornerRadius: 45),
gradient: [.red, .yellow, .orange],
backgroundColor: .gray)
Text
You can customize each section of text within the views and this is done with a BKTextConfiguration which is then passed into each views corresponding configuration struct. Allowing you to configure the color, size, and weight. As previously mentioned, the only weights supported are regular, semi-bold, and bold.
public struct BKTextConfiguration {
var color: Color // default: .black
var size: CGFloat // default: 12
var weight: Font.Weight // default: .regular
}
let textConfig = BKTextConfiguration(color: Color(gray: 0.5, opacity: 0.7),
size: 12.0,
weight: .regular)
Images
Image customization is done by creating a BKImageConfiguration and passing it into a views corresponding configuration struct. For the shape, it can be either square or circle.
public struct BKImageConfiguration {
var cornerRadius: CGFloat // default: 0
var shape: BKImageShape // default: .circle
var size: CGSize // default: CGSize(width: 50.0, height: 50.0)
}
public enum BKImageShape {
case circle
case square
}
let imageConfig = BKImageConfiguration(cornerRadius: 20,
shape: .square,
size: CGSize(width: 100, height: 100))
Borders
Border customization is done by creating a BKBorderConfiguration and passing it into a views corresponding configuration struct.
public struct BKBorderConfiguration {
var width: CGFloat // default: 2
var color: Color // default: .black
var cornerRadius: CGFloat // default: 10
}
let borderConfig = BKBorderConfiguration(width: 5,
color: Color(gray: 0.6, opacity: 0.4),
cornerRadius: 20)
Buttons
Button customization is done by creating a BKButtonConfiguration and passing it into a views corresponding configuration struct.
public struct BKButtonConfiguration {
var unselectedColor: Color // Color of the button when unselected default: Color(gray: 0.8)
var selectedColor: Color // Color of the button when selected default: .black
var borderConfig: BKBorderConfiguration // Border configuration
var textConfig: BKTextConfiguration // Text configuration
var size: CGSize // Height & width of the button default: CGSize(width: 100.0, height: 50.0)
}
let buttonConfig = BKButtonConfiguration(unselectedColor: .green,
selectedColor: .blue,
borderConfig: BKBorderConfiguration(color: .clear),
textConfig: BKTextConfiguration(color: .white,
size: 16.0,
weight: .bold),
size: CGSize(width: 100.0, height: 100.0))
Icons
Border customization is done by creating a BKIconConfiguration and passing it into a views corresponding configuration struct.
public struct BKIconConfiguration {
var size: CGSize // default: CGSize(width: 20.0, height: 20.0)
var unselectedColor: Color // default: .black
var selectedColor: Color // default: .white
}
let iconConfig = BKIconConfiguration(size: CGSize(width: 60.0, height: 60.0),
unselectedColor: .red,
selectedColor: .green)
Logo Header
A few of the widgets have the company and Beam’s logo at the top which is customizable by creating a BKLogoHeaderConfiguration and passing it into a views corresponding configuration struct.
public struct BKLogoHeaderConfiguration {
/// The configurable width for the company's logo
///
/// Since the contentMode is set to .fit only one dimension
/// is necessary to configure logo to the desired look.
/// the height will adjust so that the aspect ratio is maintained.
var chainLogoWidth: CGFloat
/// The configurable width for the Beam logo
///
/// Recommended not to change this width but to adjust the chainLogoWidth
/// to a size that looks proprotionate to the Beam logo.
var beamLogoWidth: CGFloat
/// The amount of padding added to the bottom of the company logo
///
/// Adjust this as required to get the logo centered
var chainLogoBottomPadding: CGFloat
/// The amount of padding added to the bottom of the Beam logo
///
/// Adjust this as required to get the logo centered
var beamLogoBottomPadding: CGFloat
var backgroundColor: Color
}
let logoConfig = BKLogoHeaderConfiguration(chainLogoWidth: 75.0,
beamLogoWidth: 75.0,
chainLogoBottomPadding: 0.0,
beamLogoBottomPadding: 0.0,
backgroundColor: .white)
Interface
Using BKManager
There are several different ways to access an AppDelegate from within an app. Once you do you can access the bkManager property and make function calls.
This is an example using SwiftUI
struct ContentView: View {
@EnvironmentObject private var appDelegate: AppDelegate
var body: some View {
// content
}
.onAppear {
if let bkManager = appDelegate.bkManager {
// method calls
}
}
}
Registering a User
At some point a user email has to be submitted in order to make a transaction valid, it’s easiest if this is just done after initialization through the registerUser call on the BKManager if the user is logged in. If a user isn’t logged in then an email can be passed in during the transaction phase, this would be expected when the user is performing a transaction as a guest.
/// Registers a user for a given email address
/// - Parameters:
/// - email: Users email address
/// - completion: Optional completion handler that returns true
/// if successful & false if not
public func registerUser(email: String, _ completion: ((Bool) -> Void)? = nil)
bkManager.registerUser(email: "AAA@test.com") { success in
// completion code
}
Deregistering a User
This will clear the current active user so that all of the impact views are blank. It is essentially a “logout” function.
/// Clears all information about the current user from the app state
///
/// - Parameters:
/// - completion: Optional completion handler that returns true
/// if successful & false if not
public func deregisterUser(_ completion: ((Bool) -> Void)? = nil)
bkManager.deregisterUser() { success in
// completion code
}
Transactions
The transaction methods are how donations are sent to nonprofits through Beam. All transactions must have information corresponding to the BKTransaction model.
public struct BKTransaction {
let cartTotal: Float // The cart total
let currencyCode: String // The currency code
let storeId: Int // The store id
let email: String? // The email of the user, defaults to nil
let postalCode: String? // Users postal code, defaults to nil
let countryCode: String? // Users country code, defaults to nil
}
To start a transaction you must call startTransaction(transaction:completion) on BKManager with the required data for a BKTransaction. Then once the purchase is complete and you have an order number you call finishTransaction(orderId:email) . An orderId is required but an email is optional. Passing in an email here would be used for the case where this is a guest shopper, isn’t logged in, and registerUser(email) wasn’t called.
let transaction = BKTransaction(cartTotal: 20.0,
currencyCode: "USD",
storeId: 1,
email: "aaa@test.com",
postalCode: "97123",
countryCode: "US")
bkManager.startTransaction(transaction) { success in
// completion code
}
bkManager.finishTransaction(orderId: "9991", email: "aaa@test.com") { success in
// completion code
}
Start Transaction
Should be called once you have all of the info needed to create a BKTransaction.
/// Stores a current transaction which will be used when finishTransaction
/// is called
///
/// - Parameters:
/// - transaction: A BKTransaction with relevant transaction information
/// - completion: Optional completion handler that returns true if successful
/// & false if not
public func startTransaction(_ transaction: BKTransaction,
_ completion: ((Bool) -> Void)? = nil)
let transaction = BKTransaction(cartTotal: 20.0,
currencyCode: "USD",
storeId: 1,
email: "aaa@test.com",
postalCode: "97123",
countryCode: "US")
bkManager.startTransaction(transaction) { success in
// completion code
}
Finishing a Transaction
Once the purchase is complete and you have an order number you call finishTransaction(orderId:email) . An orderId is required but an email is optional. Passing in an email here would be used for the case where this is a guest shopper, isn’t logged in, and registerUser(email) wasn’t called.
/// Completes the stored transaction with the stored nonprofit id.
/// startTransaction must be called prior to this method
///
/// - Parameters:
/// - orderId: A unique order ID that is associated with this transaction
/// - email: Optionally, provide an email address if there is not one
/// associated with the registered user
/// - completion: Optional completion handler that returns true
/// if successful & false if not
public func finishTransaction(orderId: String,
email: String? = nil,
_ completion: ((Bool) -> Void)? = nil)
bkManager.finishTransaction(orderId: "ABCD1", email: "aaa@test.com") { success in
// completion code
}
Canceling a Transaction
Transaction can be cancelled after they are created by passing in the unique orderId you provided during finishTransaction.
/// Cancels the transaction for the provided order ID
///
/// - Parameters:
/// - orderId: A unique order ID that is associated with this transaction
/// - completion: Optional completion handler that returns true
/// if successful & false if not
public func cancelTransaction(orderId: String,
_ completion: ((Bool) -> Void)? = nil)
bkManager.cancelTransaction(orderId: "ABCD1", email: "aaa@test.com") { success in
// completion code
}
Redeeming a Transaction
A transaction can also be updated with the selected nonprofit. This is useful if a user never selected a nonprofit before the transaction was created.
/// Updates an existing transaction with the stored nonprofit ID.
/// Should be called if the user adds or changes their nonprofit selection
///
/// - Parameters:
/// - transaction: A BKTransaction with relevant transaction information
/// - orderId: A unique order ID that is associated with this transaction
/// - completion: Optional completion handler that returns true
/// if successful & false if not
public func redeemTransaction(transaction: BKTransaction,
orderId: String,
_ completion: ((Bool) -> Void)? = nil)
let transaction = BKTransaction(cartTotal: 20.0,
currencyCode: "USD",
storeId: 1,
email: "aaa@test.com",
postalCode: "97123",
countryCode: "US")
bkManager.redeemTransaction(transaction: transaction, orderId: "ABCD1") { success in
// completion code
}
Error States
At some point during the creation of a transaction, an email must be provided. This can be done via registerUser, startTransaction, or finishTransaction. Note that an error will occur for the following scenarios:
- A transaction was started with a different email than the one belonging to the registered user.
- A transaction was finished without being started.
- A transaction was finished without a registered user and without providing an email when starting or finishing the transaction.
- A transaction was started with a different email than the one used to finish it.
- A transaction was finished with a different email than the one belonging to the registered user.
Getting Selected Nonprofit
At any point after a user has selected a nonprofit, you can get the name and cause of the selected nonprofit if you choose to display it somewhere.
/// Returns the user's currently selected nonprofit and cause, if it exists
public func getSelectedNonprofit() -> (nonprofitName: String?, nonprofitCause: String?)
let nonprofitInfo = bkManager.getSelectedNonprofit()
print(nonprofitInfo.nonprofitName)
print(nonprofitInfo.nonprofitCause)
Widgets
- BKMinimalNonprofitSelectionView
- BKFullScreenNonprofitSelectionView
- BKImpactListView
- BKSelectedNonprofitView
- BKPersonalImpactView
- BKCommunityImpactView
- BKOrderPageView
BKMinimalNonprofitSelectionView
A compact way to allow a user to select a nonprofit; can go in cart or on an order confirmation page (if the user hasn’t selected a nonprofit yet). The isPrepurchase boolean is used to determine if the view is used anytime during the pre-purchase flow or not. For pre-purchase there is no confirm button, post-purchase the confirm button is active.

no confirm button pre selection

no confirm button post selection

confirm button pre selection

confirm button post selection
-
Toggle for details on Usage, Customization, & Delegate
Usage
SwiftUI
BKMinimalNonprofitSelectionView(config: BKMinimalNonprofitViewConfiguration(),delegate: delegate,isPrePurchase: true)UIKit
let bkView = BKMinimalNonprofitSelectionView(config: BKMinimalNonprofitViewConfiguration(),delegate: delegate,isPrePurchase: true)let childView = UIHostingController(rootView: bkView)addChild(childView)childView.view.frame = view.frameview.addSubview(childView.view)childView.didMove(toParent: self)Customization
You can customize almost all of the aspects of the view using BKMinimalNonprofitViewConfiguration which gets passed in on init.
public struct BKMinimalNonprofitViewConfiguration {var widgetTitleConfig: BKTextConfiguration // "Choose your Impact"var widgetSubtitleConfig: BKTextConfiguration // "Select a nonprofit.."var confirmButtonConfig: BKButtonConfiguration // Customize the CONFIRM buttonvar iconConfig: BKIconConfiguration // Cause iconsvar causeButtonConfig: BKButtonConfiguration // Cause buttonvar causeTitleConfig: BKTextConfiguration // "Combat child hunger"var causeDescriptionConfig: BKTextConfiguration // "Fund 2,000 meals.."var beamTextConfig: BKTextConfiguration // "Powered By Beam"/// The vertical padding between each of the major elementsvar verticalPadding: CGFloat/// BG Color for the entire viewvar backgroundColor: ColorDelegate
The protocol you must conform to in order to receive a callback is BKNonprofitSelectionDelegate which gets passed in during init.
public protocol BKNonprofitSelectionViewDelegate: AnyObject {/// Method which is called after user taps the confirm button returning/// the name of the nonprofit and the cause////// - Parameters:/// - nonprofitName: The name of the nonprofit selected/// - nonprofitCause: The cause which that nonprofit supportsfunc onConfirmTap(nonprofitName: String, nonprofitCause: String)}
BKFullScreenNonprofitSelectionView
This is another option for allowing a user to select a nonprofit but is meant to take up the whole screen. The isPrepurchase boolean is used to determine if the view is used anytime during the pre-purchase flow or not.

.list style

.grid style
-
Toggle for details on Usage, Customization, & Delegate
Usage
SwiftUI
BKFullScreenNonprofitSelectionView(config: BKFullScreenNonprofitViewConfiguration(),delegate: delegate,isPrePurchase: true)UIKit
let bkView = BKFullScreenNonprofitSelectionView(config: BKFullScreenNonprofitViewConfiguration(),delegate: delegate,isPrePurchase: true)let childView = UIHostingController(rootView: bkView)addChild(childView)childView.view.frame = view.frameview.addSubview(childView.view)childView.didMove(toParent: self)Customization
You can customize almost all of the aspects of the view using BKFullScreenViewConfiguration which gets passed in on init.
public struct BKFullScreenNonprofitViewConfiguration {var widgetTitleConfig: BKTextConfiguration // "Choose your Impact"var widgetSubtitleConfig: BKTextConfiguration // "Select a nonprofit and.."var imageConfig: BKImageConfiguration // The image on the left of nonprofit tilevar causeConfig: BKTextConfiguration // "Combat child hunger, Feed Seniors"var nonprofitConfig: BKTextConfiguration // "Arkansas Food Bank, etc.."var impactDescriptionConfig: BKTextConfiguration // "Fund <n> meals.."var confirmButtonConfig: BKButtonConfiguration // Confirm button at bottom (width not honored)var confirmButtonHorizontalPadding: CGFloat // Determines width of confirm buttonvar unselectedBorderConfig: BKBorderConfiguration // Border for unselected tilesvar selectedBorderConfig: BKBorderConfiguration // Border for selected tilesvar unselectedBackgroundColor: Color // Bg color for unselected tilesvar selectedBackgroundColor: Color // Bg color for selected tilesvar beamTextConfig: BKTextConfiguration // "Powered by Beam"var headerHeight: CGFloat // Height of the header if there is oneb/// Set whether or not the header should ignore safe areavar headerIgnoresSafeArea: Bool/// Alignment for the title and subtitlevar textAlignment: Alignment/// Items can appear in a list or gridvar style: BKSelectionViewStyle/// The vertical padding between each of the major elementsvar verticalPadding: CGFloat/// BG Color for the entire viewvar backgroundColor: ColorDelegate
The protocol you must conform to in order to receive a callback is BKNonprofitSelectionDelegate which gets passed in during init.
public protocol BKNonprofitSelectionViewDelegate: AnyObject {/// Method which is called after user taps the confirm button returning the name of the nonprofit and the cause////// - Parameters:/// - nonprofitName: The name of the nonprofit selected/// - nonprofitCause: The cause which that nonprofit supportsfunc onConfirmTap(nonprofitName: String, nonprofitCause: String)}
BKImpactListView
This widget is a tabbed view which shows both a summary of users personal impact as well as the impact the community has made. It is scrollable vertically and is meant to take up a whole screen. If there is no personal impact made yet, only community is shown.

-
Toggle for details on Usage, Customization, & Delegate
Usage
SwiftUI
BKImpactListView(config: BKMinimalNonprofitViewConfiguration(),delegate: delegate)UIKit
let bkView = BKImpactListView(config: BKMinimalNonprofitViewConfiguration(),delegate: delegate)let childView = UIHostingController(rootView: bkView)addChild(childView)childView.view.frame = view.frameview.addSubview(childView.view)childView.didMove(toParent: self)Customization
public struct BKImpactListConfiguration {var selectedTabTitleConfig: BKTextConfigurationvar unselectedTabTitleConfig: BKTextConfigurationvar tabHeight: CGFloatvar selectedTabBackgroundColor: Colorvar unselectedTabBackgroundColor: Colorvar imageConfig: BKImageConfiguration // Nonprofit card imagevar causeTitleConfig: BKTextConfiguration // "Combat child hungervar nonprofitTitleConfig: BKTextConfiguration // "Atlanta Community Food.."var progressBarTextConfig: BKTextConfiguration // "14% funded"var causeDescriptionConfig: BKTextConfiguration // "Fund <n> meals.."var goalCompletionTextConfig: BKTextConfiguration // "Funded <n> times.."var websiteLinkTextConfig: BKTextConfiguration // "Learn more"/// Configure elements of the brands logo in the header sectionvar logoHeaderConfig: BKLogoHeaderConfiguration/// This is the config for the border surrounding each tilevar tileBorderConfig: BKBorderConfiguration/// The vertical padding between each of the major elementsvar verticalPadding: CGFloat/// BG Color for the entire viewvar backgroundColor: ColorDelegate
The protocol to conform to is BKImpactListViewDelegate
public protocol BKImpactListViewDelegate: AnyObject {/// Delegate method which is called after the user taps the link to/// visit a nonprofit's website////// - Parameters:/// - website: The nonproift's website url in the form of a Stringfunc onWebsiteLinkTap(website: String)}
BKSelectedNonprofitView
A compact way to show the user their currently selected nonprofit. Great way to remind the user who their donation is going to in their cart. Two styles to choose from with the option to allow the user to change who they have selected.

regular style

.outToLunch style with square image, divider, & change button
-
Toggle for details on Usage, Customization, & Delegate
Usage
SwiftUI
BKSelectedNonprofitView(config: BKSelectedNonprofitViewConfiguration(),delegate: delegate)UIKit
let bkView = BKSelectedNonprofitView(config: BKSelectedNonprofitViewConfiguration(),delegate: delegate)let childView = UIHostingController(rootView: bkView)addChild(childView)childView.view.frame = view.frameview.addSubview(childView.view)childView.didMove(toParent: self)Customization
This view has two configurable styles
.regular&.outToLunch. You can also configure whether or not to show a change button which gets a callback you can use to show one of our selection views to allow the user the ability to change their selected nonprofit. All this and more is done via the BKSelectedNonprofitViewConfiguration struct.public struct BKSelectedNonprofitViewConfiguration {var impactDescriptionTextConfig: BKTextConfiguration // "1 meal going.."var goalDescriptionTextConfig: BKTextConfiguration // "Fund 5 meals.."var progressStringTextConfig: BKTextConfiguration // "8% funded"var changeButtonTextConfig: BKTextConfiguration/// This will set the vertical padding between all different elementvar verticalPadding: CGFloatvar imageConfig: BKImageConfigurationvar showChangeButton: Bool/// The config for widgets bordervar widgetBorderConfig: BKBorderConfiguration/// BG Color for the entire viewvar backgroundColor: Colorvar style: Style/// outToLunch configs, only available for that stylevar shouldShowDivider: Boolvar dividerColor: Colorvar dividerHeight: CGFloatDelegate
The protocol which to conform is BKSelectedNonprofitViewDelegate.
public protocol BKSelectedNonprofitViewDelegate: AnyObject {/// This method is called on the delegate when the user taps to change/// their selected nonprofitfunc onChangeTap()}
BKPersonalImpactView
A simple, compact way to show the user their impact. This will always show the last impacted nonprofit, not the currently selected nonprofit, if those should differ. If there is no impact to be shown, this view will be empty.

-
Toggle for details on Usage, Customization, & Delegate
Usage
SwiftUI
BKPersonalImpactView(config: BKPersonalImpactViewConfiguration(),delegate: delegate)UIKit
let bkView = BKPersonalImpactView(config: BKPersonalImpactViewConfiguration(),delegate: delegate)let childView = UIHostingController(rootView: bkView)addChild(childView)childView.view.frame = view.frameview.addSubview(childView.view)childView.didMove(toParent: self)Customization
Fully customizable via the BKPersonalImpactViewConfiguration which gets passed into the view on init.
public struct BKPersonalImpactViewConfiguration {var imageConfig: BKImageConfigurationvar causeTitleConfig: BKTextConfiguration // "Combat child hunger"var nonprofitNameConfig: BKTextConfiguration // "Atlanta Community Food.."var goalDescriptionConfig: BKTextConfiguration // "Fund 5 meals.."var goalCompletionConfig: BKTextConfiguration // "Funded 2 times.."var borderConfig: BKBorderConfigurationvar progressBarTextConfig: BKTextConfiguration // "14% funded"/// Determines whether or not the change button is shownvar shouldShowChangeButton: Boolvar changeButtonTextConfig: BKTextConfiguration/// The vertical padding between each of the major elementsvar verticalPadding: CGFloat/// BG Color for the entire viewvar backgroundColor: ColorDelegate
public protocol BKPersonalImpactDelegate: AnyObject {/// If this view is setup to allow the user to change their selected nonprofit, this method is called when the user taps that optionfunc onChangeTap()}
BKCommunityImpactView
Shows the overall community impact for the users last impacted nonprofit with a button allowing the user to see all of their impact. If there is no impact or a saved selected nonprofit for that user, this view will be empty.

-
Toggle for details on Usage, Customization, & Delegate
Usage
SwiftUI
BKCommunityImpactView(config: BKCommunityImpactViewConfiguration(),delegate: delegate)UIKit
let bkView = BKCommunityImpactView(config: BKCommunityImpactViewConfiguration(),delegate: delegate)let childView = UIHostingController(rootView: bkView)addChild(childView)childView.view.frame = view.frameview.addSubview(childView.view)childView.didMove(toParent: self)Customization
public struct BKCommunityImpactViewConfiguration {var nonprofitTextConfig: BKTextConfiguration // "Atlanta Community Food.."var buttonConfig: BKButtonConfiguration/// The imageConfig width property is not honored. It will just be the width of the entire widget minus padding.var imageConfig: BKImageConfigurationvar cornerRadius: CGFloatvar backgroundColor: Colorvar progressBarHorizontalPadding: CGFloat/// This will set the horizontal padding for the nonprofit name and buttonvar horizontalPadding: CGFloat/// This will set the vertical padding between all different elementsvar verticalPadding: CGFloatDelegate
public protocol BKCommunityImpactViewDelegate: AnyObject {/// Method which is called after user taps the button on the BKCommunityImpactViewfunc onButtonTap()}
BKOrderPageView
A simple way to show either the BKMinimalNonprofitSelectionView or the BKImpactOverviewView after an order has been placed. If the user never selected a nonprofit during a transaction this gives them the opportunity to do so now. Transactions can only be redeemed within 30 days. If the user did select a nonprofit, this view will show their impact for a given transaction.
Screen Recording 2023-01-12 at 12.25.44 PM.mov
-
Toggle for details on Usage, Customization, & Delegate
Usage
In order to redeem a transaction for a donation we need some info about the purchase which gets passed into the BKOrderPageView init in the form of a BKTransaction.
BKTransaction(cartTotal: Float,currencyCode: String,email: String? = nil,postalCode: String? = nil,countryCode: String? = nil)// sample usagelet transaction = BKTransaction(cartTotal: 20.0,currencyCode: "USD",email: "aaa@test.com",postalCode: "97123",countryCode: "US")SwiftUI
BKOrderPageView(transaction: transaction,orderId: "ABCD1234",minNonprofitConfig: BKMinimalNonprofitViewConfiguration(),impactOverviewConfig: BKImpactOverviewConfiguration(),minNonprofitDelegate: selectionDelegate,impactOverviewDelegate: impactDelegate)UIKit
let bkView = BKOrderPageView(transaction: transaction,orderId: "ABCD1234",minNonprofitConfig: BKMinimalNonprofitViewConfiguration(),impactOverviewConfig: BKImpactOverviewConfiguration(),minNonprofitDelegate: selectionDelegate,impactOverviewDelegate: impactDelegate)let childView = UIHostingController(rootView: bkView)addChild(childView)childView.view.frame = view.frameview.addSubview(childView.view)childView.didMove(toParent: self)Customization
Since there are two views possible to be displayed here there are two separate configs that get passed in during init of the BKOrderPageView, BKMinimalNonprofitViewConfiguration & BKImpactOverviewConfiguration. Since the BKMinimalNonprofitConfig was covered above here is the options for the BKImpactOverviewConfiguration.
public struct BKImpactOverviewConfiguration {var logoHeaderConfig: BKLogoHeaderConfiguration // For the logo at the topvar widgetTitle: BKTextConfiguration // "You just made an impact"var widgetSubtitle: BKTextConfiguration // "Check out the impact.."/// The height of the nonprofit image displayed on the card////// Defaults to 225. The width is the size of the view minus outside paddingvar cardImageHeight: CGFloatvar cardTitle: BKTextConfiguration // "Your Impact"var cardDescription: BKTextConfiguration // "Fund <n> meals for .."var cardBorderConfig: BKBorderConfigurationvar cardBackgroundColor: Color/// The tappable text residing after each cardvar linkText: BKTextConfiguration/// The vertical padding between each of the major elementsvar verticalPadding: CGFloat/// BG Color for the entire viewvar backgroundColor: ColorDelegates
Again since there are two possible view states you can pass in two different delegates into the init, BKNonprofitSelectionViewDelegate & BKImpactOverviewDelegate. See the section above for description of the BKNonprofitSelectionViewDelegate.
public protocol BKImpactOverviewDelegate: AnyObject {/// Delegate method which is called after the user taps the link to/// visit a nonprofit's website////// - Parameters:/// - website: The nonproift's website url in the form of a Stringfunc onWebsiteLinkTap(website: String)/// Method which is called when user taps to see the communities impactfunc onSeeAllCommunityImpactTap()/// Called when the view is loadingfunc onLoading()/// Method which is called when loading is complete////// - Parameters:/// - success: Returns true if loaded successfully, false if notfunc onLoaded(_ success: Bool)}