# Flutter 🦅

Our `CardScan` Flutter widget makes it easy to add insurance card scanning to any Flutter application in 5 minutes or less.

### Installation

Add the `insurance_card_scanner` package to your `pubspec.yaml` file.

```yaml
dependencies:
  flutter:
    sdk: flutter
  insurance_card_scanner: ^0.3.0
```

### Usage

Import the library widget into your project files:

```dart
import 'package:insurance_card_scanner/insurance_card_scanner.dart';
```

You can **optionally** add the API client for more custom applications.

```dart
import 'package:insurance_card_scanner/insurance_card_scanner_api.dart';
```

### Basic Example

```dart
import 'package:insurance_card_scanner/insurance_card_scanner.dart';

class ScannerWidgetScreen extends StatelessWidget {
  const ScannerWidgetScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Scanner widget'),
      ),
      body: CardScanner(
        properties: CardScanConfig(
          sessionToken: '<pass your token here>',
          onSuccess: (card) {
            print('Scan success');
          },
          onError: (message) {
            print(message ?? 'Unknown Scan error');
          },
          onCancel: () {
            Navigator.of(context).pop();
          },
        ),
      ),
    );
  }
}
```

### Available Properties

Both `CardScanner` and `CardScannerModal` should be passed a `CardScanConfig` instance with properties for server connection, callback handling and UI customization.

```dart
CardScanConfig(
  // Required
  sessionToken: token,
  live: false,
  onSuccess: onSuccess,

  // Recommended
  onCancel: onCancel,
  onError: onError,

  // Optional
  backsideSupport: scanBackside,
  onRetry: onRetry,

  // UI Customization
  messages: messages,
  messageStyle: messagesStyle,
  autoSwitchActiveColor: autoSwitchActiveColor,
  autoSwitchInactiveColor: autoSwitchInactiveColor,
  progressBarColor: progressBarColor,
  widgetBackgroundColor: widgetBackgroundColor,
)

```

### **Main Props**

<table><thead><tr><th width="289">Prop</th><th width="112">Required</th><th width="135">Type</th><th>Description</th></tr></thead><tbody><tr><td>live</td><td>false</td><td>Boolean</td><td>Toggle the production or sandbox version. <strong>Default</strong>: false</td></tr><tr><td>sessionToken</td><td>true</td><td>String</td><td>A JWT token for the current user, see <a href="../authentication">Authentication</a></td></tr><tr><td>onSuccess</td><td>true</td><td>Function</td><td>Called on successful scan. The first argument is the scanned card.</td></tr><tr><td>onCancel</td><td>false</td><td>Function</td><td>Triggered when the user cancels the CardScanner UI.</td></tr><tr><td>onError</td><td>false</td><td>Function</td><td>Called when an error is returned by the API or the CardScanner fails to initialize.</td></tr><tr><td>backsideSupport</td><td>false</td><td>Boolean</td><td>Enable scanning of the front and back side of the card.<br><strong>Default</strong>: false</td></tr><tr><td>onRetry</td><td>false</td><td>Function</td><td>Called when a failed scan triggers a retry.</td></tr></tbody></table>

### UI/UX Customization Props

The flutter widget is designed to be customizable. Please see the [#customization](#customization "mention") section of UI Components to adjust these elements to match your application's branding and theme:

[customization](https://docs.cardscan.ai/ui-components/customization "mention")

{% hint style="info" %}
**Note:** All UI/UX Props are optional
{% endhint %}

<table><thead><tr><th width="329.3333333333333">Prop</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>messages</td><td>Object</td><td>Customize the text displayed by the UI.</td></tr><tr><td>messageStyle</td><td>TextStyle</td><td>Set the size, color and background color of the text displayed by the UI.</td></tr><tr><td>autoSwitchActiveColor</td><td>Color</td><td>Set the color of the auto scan switch</td></tr><tr><td>autoSwitchInactiveColor</td><td>Color</td><td>Set the color of the disabled auto scan switch</td></tr><tr><td>progressBarColor</td><td>Color</td><td>Set the color of the progress bars or bounding box that surrounds the card scanning area.</td></tr><tr><td>widgetBackgroundColor</td><td>Color</td><td>Set the main background color for the widget.</td></tr></tbody></table>

### onSuccess Callback

The `onSuccess` callback allows you to execute a custom function when the card scanning process is completed successfully. This function receives the scanned card data as an argument.

#### Usage

To use the `onSuccess` callback, pass a function that receives the scanned card data:

```dart
void handleCardScanSuccess(Card card) {
  print('Card scanned successfully: $card');
}

CardScanner(
  sessionToken: token,
  onSuccess: handleCardScanSuccess,
)
```

In this example, the `handleCardScanSuccess` function logs the scanned card data to the console when the scanning process is completed successfully.

###

### onError Callback

The `onError` callback allows you to execute a custom function when there's a failure during the card scanning process. This function receives an error object as an argument.

#### Usage

To use the `onError` callback, pass a function that receives the error object:

```dart
void handleCardScanError(CardScanError error) {
  print('Scanning failed: $error');
}

CardScanner(
  sessionToken: token,
  onSuccess: handleCardScanSuccess,
  onError: handleCardScanError,
)

```

In this example, the `handleCardScanError` function logs the error object to the console when a scanning failure occurs.

By using the `onSuccess` and `onError` callbacks, you can handle successful and failed scanning events, allowing you to implement custom actions or display appropriate messages to the user.

### onCancel Callback

The `onCancel` callback enables you to execute a custom function when the user cancels the card scanning process. This can be useful for tracking user behavior, navigating to a different part of the application, or displaying an appropriate message.

#### Usage

To use the `onCancel` callback, pass a function that will be executed when the user cancels the scanning process:

```dart
import 'package:flutter/material.dart';
import 'package:insurance_card_scanner/insurance_card_scanner.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool showCardScanWidget = true;

  void handleCardScanSuccess(Card card) {
    // Handle card scan success
  }

  void handleCardScanError(CardScanError error) {
    // Handle card scan error
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Insurance Card Scanner'),
        ),
        body: showCardScanWidget
            ? CardScanner(
                sessionToken: token,
                onSuccess: handleCardScanSuccess,
                onError: handleCardScanError,
                onCancel: () => setState(() => showCardScanWidget = false),
              )
            : Container(),
      ),
    );
  }
}

```

In this example, we initialize the `showCardScanWidget` state variable to `true`. Then, we conditionally render the `CardScanner` widget based on the value of `showCardScanWidget`. We then use the `onCancel` callback to set the `showCardScanWidget` state variable to `false` when the user cancels the scanning process.

### onRetry Callback

The `onRetry` callback allows you to execute a custom function when a retry is triggered due to a scanning failure.

#### Usage

```dart
void handleRetry() {
  print('Retry triggered');
}

CardScanner(
  sessionToken: token,
  onSuccess: handleCardScanSuccess,
  onRetry: handleRetry,
)
```

In this example, the `handleRetry` function logs the retry event to the console when a retry is triggered.

### Camera Permissions 📸

Our SDK requires camera access to scan insurance cards. While the CardScan widget automatically requests camera permissions during widget load, it does not present any UI for handling permissions or manage permission failures, particularly on mobile devices.

**Requirement:** We require that developers handle camera permission requests ***before*** loading the CardScan widget. This will allow you to manage the permission flow consistently within your application, providing custom error handling and user feedback if permission is denied.

**Recommendation:** We recommend following best practices when requesting camera permissions:

* **Pre-flight the request:**

  Within your app, prompt the user with a clear explanation of why camera access is needed and ask for confirmation (Yes/No). This improves transparency, builds trust, and can reduce the likelihood of the user denying the request.
* **Handle permission rejection gracefully:**
  * **Soft rejection (user-level):** If the user declines the camera access within your app, provide a helpful message that explains the impact of this choice and give them the option to reconsider later.
  * **Hard rejection (system-level):** In case the user has previously denied the camera permission at the system level, guide them to the device settings where they can manually enable the camera access. Display an appropriate message explaining how to do this and the importance of enabling the permission for the app's functionality.

For Flutter applications, we recommend using the [permission\_handler](https://pub.dev/packages/permission_handler) package to manage camera permissions effectively.
