# 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](https://docs.cardscan.ai/authentication) |
| 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 %}
