# React DropZone 📤

The `CardScanDropZone` component provides an alternative to camera-based scanning by offering a **drag-and-drop file upload interface** for insurance card processing. This component is perfect for desktop workflows where users have digital images of their insurance cards ready to upload.

### Installation

```bash
$ npm i @cardscan.ai/insurance-cardscan-react
$ yarn add @cardscan.ai/insurance-cardscan-react
```

### Usage

Import the component into your project:

```javascript
import { CardScanDropZone } from "@cardscan.ai/insurance-cardscan-react";
```

### Basic Example

```jsx
import React from "react";
import { render } from "react-dom";
import { CardScanDropZone } from "@cardscan.ai/insurance-cardscan-react";

function onSuccess(card) {
  console.log("Card processed successfully:", card);
}

function onError(error) {
  console.error('Error occurred:', error);
}

// See Authentication on where to get this sessionToken
const sessionToken = 'JWT_TOKEN'

function App() {
  return (
    <div className="App">
      <div className="DropZoneContainer">
        <CardScanDropZone
          live={false}
          sessionToken={sessionToken}
          onSuccess={onSuccess}
          onError={onError}
          enableBackside={true}
          layout="side-by-side"
        />
      </div>
    </div>
  );
}

const rootElement = document.getElementById('root');
render(<App />, rootElement);
```

### Compatibility

* **Node Versions**: 14, 16, 18
* **React Versions**: >=17.0.2, 18.2.0+
* **Webpack Versions**: 4.x, 5.x
* **Babel Versions**: 6.x, 7.x

### Peer Dependencies

* **React**: >=17.0.2
* **React-DOM**: >=17.0.2
* **react-dropzone**: ^14.0.0

## Configuration

### Available Props

```jsx
<CardScanDropZone
  // Required
  live={false}
  sessionToken={token}
  onSuccess={onSuccess}

  // Recommended
  onCancel={onCancel}
  onError={onError}
  onProgress={onProgress}
  
  // Dropzone Options
  enableBackside={true}
  layout="side-by-side"
  
  // UI Customization
  messages={messages}
  frontDropIndicator={frontDropIndicator}
  backDropIndicator={backDropIndicator}
  successIndicator={successIndicator}
  errorIndicator={errorIndicator}
  
  // Styling
  widgetBackgroundColor="#ffffff"
  primaryColor="#007bff"
  progressBarColor="#28a745"
/>
```

### Main Props

| Prop           | Required | Type     | Description                                                                      |
| -------------- | -------- | -------- | -------------------------------------------------------------------------------- |
| live           | true     | Boolean  | Toggle production or sandbox version. **Default**: false                         |
| sessionToken   | true     | String   | JWT token for the current user, see [Authentication](/authentication.md)         |
| onSuccess      | true     | Function | Called on successful card processing. First argument is the processed card data. |
| onCancel       | false    | Function | Triggered when user cancels the upload process.                                  |
| onError        | false    | Function | Called when an error occurs during upload or processing.                         |
| onProgress     | false    | Function | Progress updates during card processing.                                         |
| enableBackside | false    | Boolean  | Enable uploading of both front and back card sides. **Default**: false           |
| layout         | false    | String   | Layout mode: `"side-by-side"` or `"sequential"`. **Default**: `"side-by-side"`   |

### Layout Options

The `layout` prop controls how the front and back upload zones are displayed:

#### Side-by-Side Layout

```jsx
<CardScanDropZone
  layout="side-by-side"
  enableBackside={true}
  // ... other props
/>
```

Both drop zones are visible simultaneously, allowing users to see both upload areas at once.

#### Sequential Layout

```jsx
<CardScanDropZone
  layout="sequential"
  enableBackside={true}
  // ... other props
/>
```

The back drop zone is hidden until the front card is successfully uploaded and processed.

## File Requirements

The CardScanDropZone component enforces the following file requirements:

* **File Types**: JPEG, PNG
* **File Size**: Maximum 5MB per file
* **Image Quality**: Clear, well-lit images for best OCR results

## Upload Workflow

1. **Front Card Upload**: User drags and drops or clicks to select the front card image
2. **File Validation**: Component validates file type and size
3. **Upload & Processing**: File is uploaded via secure S3 direct upload and processed
4. **Real-time Updates**: WebSocket connection provides live processing status
5. **Back Card (Optional)**: If `enableBackside` is true, back card upload becomes available
6. **Completion**: `onSuccess` callback is triggered with complete card data

## UI Customization

### Custom Messages

```jsx
const customMessages = {
  frontDropTitle: "Upload Front of Insurance Card",
  frontDropSubtitle: "Drag and drop or click to select",
  backDropTitle: "Upload Back of Insurance Card", 
  backDropSubtitle: "Drag and drop or click to select",
  frontProcessingTitle: "Processing Front Card...",
  backProcessingTitle: "Processing Back Card...",
  uploadingTitle: "Uploading...",
  successTitle: "Upload Complete!",
  errorTitle: "Upload Failed",
  fileTooLargeError: "File size must be under 5MB",
  invalidFileTypeError: "Please upload a JPEG or PNG file"
};

<CardScanDropZone
  messages={customMessages}
  // ... other props
/>
```

### Custom Components

Replace default UI elements with your own React components:

```jsx
const CustomFrontIndicator = () => (
  <div className="custom-drop-indicator">
    <h3>📄 Drop Front Card Here</h3>
  </div>
);

const CustomSuccessIndicator = () => (
  <div className="custom-success">
    <h3>✅ Card Processed Successfully!</h3>
  </div>
);

<CardScanDropZone
  frontDropIndicator={<CustomFrontIndicator />}
  successIndicator={<CustomSuccessIndicator />}
  // ... other props
/>
```

### CSS Styling

The component supports CSS custom properties for easy theming:

```css
.cardscan-dropzone {
  --dropzone-bg-color: #f8f9fa;
  --dropzone-border-color: #dee2e6;
  --dropzone-text-color: #212529;
  --dropzone-primary-color: #007bff;
  --dropzone-success-color: #28a745;
  --dropzone-error-color: #dc3545;
  --dropzone-border-radius: 8px;
}
```

Or use the styling props:

```jsx
<CardScanDropZone
  widgetBackgroundColor="#ffffff"
  primaryColor="#007bff"
  progressBarColor="#28a745"
  // ... other props
/>
```

## State Management

The CardScanDropZone uses XState for robust state management with the following states:

* **Initial**: Ready for front card upload
* **FrontUploading**: Front card being uploaded
* **FrontProcessing**: Front card being processed by ML pipeline
* **BackAvailable**: Ready for back card upload (if enabled)
* **BackUploading**: Back card being uploaded
* **BackProcessing**: Back card being processed
* **Success**: Both cards processed successfully
* **Error**: Upload or processing failed

## Callbacks

### onSuccess Callback

```jsx
const handleSuccess = (cardData) => {
  console.log('Processed card data:', cardData);
  // cardData contains extracted information from both front and back
};

<CardScanDropZone
  onSuccess={handleSuccess}
  // ... other props
/>
```

### onError Callback

```jsx
const handleError = (error) => {
  console.error('Upload error:', error);
  // Error object contains type, message, and code
};

<CardScanDropZone
  onError={handleError}
  // ... other props
/>
```

### onProgress Callback

```jsx
const handleProgress = (progress) => {
  console.log(`Processing: ${progress.cardSide} - State: ${progress.state}`);
};

<CardScanDropZone
  onProgress={handleProgress}
  // ... other props
/>
```

## Error Handling

The component handles various error scenarios:

| Error Type          | Description             | User Action               |
| ------------------- | ----------------------- | ------------------------- |
| FileTooLarge        | File exceeds 5MB limit  | Select a smaller file     |
| InvalidFileType     | File is not JPEG/PNG    | Select a valid image file |
| UploadFailed        | Network or server error | Try uploading again       |
| ProcessingFailed    | ML processing failed    | Try with a clearer image  |
| AuthenticationError | Invalid session token   | Refresh authentication    |

## Integration with CardScanView

The DropZone component can be used alongside the camera-based CardScanView:

```jsx
const [uploadMethod, setUploadMethod] = useState('camera');

return (
  <div>
    <div className="method-selector">
      <button onClick={() => setUploadMethod('camera')}>
        📸 Use Camera
      </button>
      <button onClick={() => setUploadMethod('upload')}>
        📤 Upload Files
      </button>
    </div>
    
    {uploadMethod === 'camera' ? (
      <CardScanView
        sessionToken={sessionToken}
        onSuccess={onSuccess}
        onError={onError}
      />
    ) : (
      <CardScanDropZone
        sessionToken={sessionToken}
        onSuccess={onSuccess}
        onError={onError}
        enableBackside={true}
      />
    )}
  </div>
);
```

## Best Practices

1. **File Validation**: Always handle file validation errors gracefully
2. **User Feedback**: Provide clear visual feedback during upload and processing
3. **Error Recovery**: Allow users to retry failed uploads easily
4. **Accessibility**: Ensure keyboard navigation and screen reader support
5. **Mobile Considerations**: Consider using CardScanView for mobile devices where camera access is preferred

## Troubleshooting

### Common Issues

**Files not uploading:**

* Check session token validity
* Verify file size is under 5MB
* Ensure file format is JPEG or PNG

**Processing takes too long:**

* Images with poor quality may require more processing time
* Consider implementing a timeout mechanism

**Styling not applying:**

* Ensure CSS custom properties have sufficient specificity
* Check for conflicting styles from other components

{% hint style="info" %}
**Need Help?** Contact <support@cardscan.ai> for assistance with the CardScanDropZone component.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.cardscan.ai/ui-components/react-dropzone.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
