# AppNest Templates - Integration Frontend Components

A comprehensive React component library for building integration templates with field mapping, triggers, and data import functionality. Built with TypeScript and Twigs React components.

## 📦 Installation

```bash
npm install @sparrowengg/integrations-templates-frontend
# or
yarn add @sparrowengg/integrations-templates-frontend
```

## 🚀 Quick Start

```tsx
import { Mapping, IntegrationTemplate } from '@sparrowengg/integrations-templates-frontend';
import '@sparrowengg/integrations-templates-frontend/dist/es/index.css';

// Basic mapping example
function MyMappingComponent() {
  return (
    <Mapping
      integrationName="Salesforce"
      // ... mapping props
    />
  );
}
```

## 🏗️ Architecture

The library is organized into several main modules:

- **Mapping** - Complex field mapping between survey data and integration fields
- **Single Mapping** - Simplified single-step mapping with configuration
- **Triggers** - Conditional trigger setup with filter conditions
- **Contact Import** - Contact data import with scheduling and mapping
- **Dynamic Mapping** - Dynamic field mapping capabilities
- **Filter** - Filter components for data filtering
- **Cascader Dropdown** - Hierarchical dropdown navigation
- **Integration Template** - Main wrapper component that orchestrates all modules

## 📚 Components Documentation

### Mapping Component

The Mapping component provides a comprehensive interface for mapping survey fields to integration fields with support for complex configurations, event setup, and field validation.

#### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `havingTypeDropdown` | `boolean` | ✅ | Whether to show integration field type dropdown |
| `onSaveMappingLoader` | `boolean` | ✅ | Loading state for save operation |
| `surveyDetails` | `SurveyDetails` | ✅ | Survey information object |
| `integrationName` | `string` | ✅ | Name of the target integration |
| `fields` | `FieldType[]` | ✅ | Array of mapping field configurations |
| `setFields` | `React.Dispatch<React.SetStateAction<FieldType[]>>` | ✅ | State setter for fields |
| `integrationFields` | `IntegrationFieldType[]` | ✅ | Available integration fields |
| `setIntegrationFields` | `React.Dispatch<React.SetStateAction<IntegrationFieldType[]>>` | ✅ | State setter for integration fields |
| `apiURL` | `string` | ❌ | API endpoint URL (defaults to SurveySparrow URL) |
| `token` | `string` | ✅ | Authentication token |
| `accounts` | `AccountsFieldType` | ✅ | Account selection configuration |
| `events` | `EventFieldType` | ✅ | Event selection configuration |
| `actions` | `ActionsFieldType` | ✅ | Action selection configuration |
| `isMappingPage` | `boolean` | ✅ | Current page state (event setup vs mapping) |
| `surveyType` | `string` | ✅ | Type of survey |
| `navigateMappingPage` | `(value?: boolean) => void` | ✅ | Navigation handler |
| `customList` | `CustomListFieldType` | ✅ | Custom list configuration |
| `oldResponse` | `OldResponseFieldType` | ✅ | Old response handling configuration |
| `hasPreviousMapping` | `boolean` | ✅ | Whether previous mapping exists |
| `onSaveHandler` | `() => void` | ✅ | Save operation handler |
| `editField` | `EditField \| null` | ✅ | Field being edited |
| `previousMappingHandler` | `(value?: boolean) => void` | ✅ | Previous mapping navigation handler |
| `onDeleteHandler` | `(id: string \| number) => void` | ❌ | Delete field handler |
| `draftHandler` | `(type: string \| null, editFieldId?: string \| number) => void` | ✅ | Draft save handler |
| `configuration` | `ConfigurationObject` | ✅ | Configuration setup object |

#### FieldType

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `string` | ✅ | Unique field identifier |
| `surveySparrowField` | `SelectOption \| null` | ✅ | Selected survey field |
| `integrationField` | `SelectOption \| null` | ✅ | Selected integration field |
| `integrationFieldType` | `SelectOption \| null` | ✅ | Integration field type |
| `isEssentialField` | `boolean` | ✅ | Whether field is required for integration |
| `essentialFieldLabel` | `string` | ❌ | Label for essential field |
| `mappedType` | `SelectOption` | ✅ | Field mapping type |
| `defaultValue` | `FormFieldValue` | ❌ | Default field value |
| `dependency` | `Record<string, unknown> \| null` | ✅ | Field dependencies |

#### Example

```tsx
import { Mapping } from '@sparrowengg/integrations-templates-frontend';

function MappingExample() {
  const [fields, setFields] = useState([
    {
      id: "email_field",
      surveySparrowField: null,
      integrationField: null,
      integrationFieldType: null,
      isEssentialField: true,
      essentialFieldLabel: "Email",
      mappedType: { label: "Email", value: "email" },
      defaultValue: null,
      dependency: null
    }
  ]);

  const [integrationFields, setIntegrationFields] = useState([
    {
      id: "email",
      label: "Email Address",
      value: "email",
      type: "string"
    }
  ]);

  return (
    <Mapping
      havingTypeDropdown={true}
      onSaveMappingLoader={false}
      surveyDetails={{
        surveyName: "Customer Feedback Survey",
        surveyId: "survey_123"
      }}
      integrationName="Salesforce"
      fields={fields}
      setFields={setFields}
      integrationFields={integrationFields}
      setIntegrationFields={setIntegrationFields}
      token="your_auth_token"
      accounts={{
        hasAccounts: true,
        options: [{ label: "Main Account", value: "acc_1" }],
        value: null,
        onChangeHandler: (value) => console.log('Account selected:', value)
      }}
      events={{
        hasEvents: true,
        options: [{ label: "Contact Update", value: "contact_update" }],
        value: null,
        onChangeHandler: (value) => console.log('Event selected:', value)
      }}
      actions={{
        hasActions: true,
        options: [{ label: "Create Contact", value: "create_contact" }],
        value: null,
        onChangeHandler: (value) => console.log('Action selected:', value)
      }}
      isMappingPage={false}
      surveyType="standard"
      navigateMappingPage={(value) => console.log('Navigate to mapping:', value)}
      customList={{ hasCustomList: false, value: null, onChangeHandler: () => {} }}
      oldResponse={{ hasOldResponse: false, value: null, onChangeHandler: () => {} }}
      hasPreviousMapping={false}
      onSaveHandler={() => console.log('Mapping saved')}
      editField={null}
      previousMappingHandler={() => console.log('Go back')}
      draftHandler={(type, id) => console.log('Save draft:', type, id)}
      configuration={{
        hasConfiguration: false,
        configurationFields: [],
        configuredFields: {},
        title: "Event Configuration"
      }}
    />
  );
}
```

---

### SingleMapping Component

The SingleMapping component provides a simplified mapping interface with configuration steps, ideal for straightforward integration scenarios.

#### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `hasPreviousMapping` | `boolean` | ❌ | Whether previous mapping exists |
| `integrationFields` | `IntegrationField[]` | ✅ | Available integration fields |
| `configuration` | `SingleMappingConfiguration` | ✅ | Configuration object |
| `token` | `string` | ❌ | Authentication token |
| `isMappingPage` | `boolean` | ✅ | Current page state |
| `navigateMappingPage` | `(value?: boolean) => void` | ✅ | Navigation handler |
| `apiURL` | `string` | ❌ | API endpoint URL |
| `surveyDetails` | `SurveyDetails` | ✅ | Survey information |
| `onSaveHandler` | `(fields: any) => void` | ✅ | Save handler |
| `setIntegrationFields` | `React.Dispatch<React.SetStateAction<any>>` | ✅ | Integration fields setter |
| `hasExistingMapping` | `boolean` | ✅ | Whether existing mapping is present |
| `importResponse` | `ImportResponse` | ✅ | Import response configuration |
| `editField` | `any` | ❌ | Field being edited |
| `previousMappingHandler` | `(value?: boolean) => void` | ❌ | Previous mapping handler |

#### Example

```tsx
import { SingleMapping } from '@sparrowengg/integrations-templates-frontend';

function SingleMappingExample() {
  const [integrationFields, setIntegrationFields] = useState([
    { id: 1, label: "Name", value: "name", type: "string" },
    { id: 2, label: "Email", value: "email", type: "email" }
  ]);

  return (
    <SingleMapping
      integrationFields={integrationFields}
      setIntegrationFields={setIntegrationFields}
      configuration={{
        importOptions: {
          showImportOptions: true,
          excludeResponse: {
            id: "exclude",
            label: "Exclude existing responses",
            ifChecked: () => "Existing responses will be excluded",
            ifUnchecked: () => "All responses will be included",
            fieldType: "checkbox",
            value: false,
            onChangeHandler: (value) => console.log('Exclude changed:', value)
          },
          options: [
            {
              id: 1,
              label: "Import All Data",
              value: "all",
              description: "Import all available data",
              type: null
            }
          ],
          onChangeHandler: (value) => console.log('Import option changed:', value)
        },
        hasConfiguration: true,
        configuredFields: {},
        configurationFields: [],
        onSaveHandler: () => console.log('Configuration saved')
      }}
      isMappingPage={false}
      navigateMappingPage={(value) => console.log('Navigate:', value)}
      surveyDetails={{
        surveyName: "Product Feedback",
        surveyId: "prod_survey_1"
      }}
      onSaveHandler={(fields) => console.log('Single mapping saved:', fields)}
      hasExistingMapping={false}
      importResponse={{
        hasImportResponse: true,
        value: { importMethod: "SEND_ALL_DATA" },
        onChangeHandler: (value) => console.log('Import response changed:', value)
      }}
    />
  );
}
```

---

### Triggers Component

The Triggers component provides a comprehensive interface for setting up conditional triggers with filter conditions and notification settings.

#### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `draftHandler` | `(type: string \| null, editFieldId?: string) => void` | ✅ | Draft save handler |
| `onSaveTriggerLoader` | `boolean` | ✅ | Loading state for save operation |
| `objects` | `ObjectsFieldType` | ✅ | Object selection configuration |
| `accounts` | `AccountsFieldType` | ✅ | Account selection configuration |
| `actions` | `ActionsFieldType` | ✅ | Action selection configuration |
| `isTriggerPage` | `boolean` | ✅ | Current page state |
| `navigateTriggerPage` | `(isTriggerPage: boolean) => void` | ✅ | Page navigation handler |
| `previousMapping` | `boolean` | ✅ | Whether previous mapping exists |
| `onSaveHandler` | `(editFieldId?: string) => void` | ✅ | Save operation handler |
| `previousMappingHandler` | `() => void` | ✅ | Previous mapping navigation |
| `surveyDetails` | `SurveyDetails` | ✅ | Survey information |
| `hasNestedCondition` | `boolean` | ✅ | Whether nested conditions are supported |
| `fields` | `TriggerField` | ✅ | Trigger field configuration |
| `token` | `string` | ✅ | Authentication token |
| `apiURL` | `string` | ✅ | API endpoint URL |
| `setFields` | `(fields: TriggerField) => void` | ✅ | Fields state setter |
| `shareRecipentOptions` | `SelectOption[]` | ✅ | Share recipient options |
| `shareChannelOptions` | `SelectOption[]` | ✅ | Share channel options |
| `triggerDetails` | `TriggerDetails` | ✅ | Trigger details configuration |
| `setTriggerDetails` | `(details: TriggerDetails) => void` | ✅ | Trigger details setter |
| `editField` | `EditField \| null` | ✅ | Field being edited |
| `fieldOptions` | `SelectOption[]` | ✅ | Available field options |
| `variableOptions` | `SelectOption[]` | ✅ | Available variable options |

#### TriggerField

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `string` | ✅ | Unique trigger identifier |
| `filters` | `FilterGroup[]` | ✅ | Array of filter groups |

#### FilterGroup

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `string` | ✅ | Filter group identifier |
| `conditions` | `FilterCondition[]` | ✅ | Array of filter conditions |
| `operator` | `'AND' \| 'OR'` | ✅ | Logical operator between conditions |

#### Example

```tsx
import { Triggers } from '@sparrowengg/integrations-templates-frontend';

function TriggersExample() {
  const [triggerFields, setTriggerFields] = useState({
    id: "trigger_1",
    filters: [
      {
        id: "group_1",
        conditions: [
          {
            id: "condition_1",
            field: { label: "Score", value: "score" },
            operator: { label: "Greater than", value: "gt" },
            value: 8
          }
        ],
        operator: "AND"
      }
    ]
  });

  const [triggerDetails, setTriggerDetails] = useState({
    shareChannel: { label: "Email", value: "email" },
    shareRecipient: { label: "Admin", value: "admin@company.com" },
    shareType: { label: "Notification", value: "notification" }
  });

  return (
    <Triggers
      draftHandler={(type, id) => console.log('Save draft:', type, id)}
      onSaveTriggerLoader={false}
      objects={{
        hasObjects: true,
        options: [{ label: "Survey Response", value: "response" }],
        value: { label: "Survey Response", value: "response" },
        onChangeHandler: (value) => console.log('Object selected:', value)
      }}
      accounts={{
        hasAccounts: false,
        options: [],
        value: null,
        onChangeHandler: () => {}
      }}
      actions={{
        hasActions: true,
        options: [{ label: "Send Notification", value: "notify" }],
        value: { label: "Send Notification", value: "notify" },
        onChangeHandler: (value) => console.log('Action selected:', value)
      }}
      isTriggerPage={false}
      navigateTriggerPage={(value) => console.log('Navigate to trigger page:', value)}
      previousMapping={false}
      onSaveHandler={(id) => console.log('Trigger saved:', id)}
      previousMappingHandler={() => console.log('Go back')}
      surveyDetails={{
        surveyName: "Customer Satisfaction",
        surveyId: "csat_survey"
      }}
      hasNestedCondition={true}
      fields={triggerFields}
      token="auth_token"
      apiURL="https://api.example.com"
      setFields={setTriggerFields}
      shareRecipentOptions={[
        { label: "Admin", value: "admin@company.com" },
        { label: "Manager", value: "manager@company.com" }
      ]}
      shareChannelOptions={[
        { label: "Email", value: "email" },
        { label: "Slack", value: "slack" }
      ]}
      triggerDetails={triggerDetails}
      setTriggerDetails={setTriggerDetails}
      editField={null}
      fieldOptions={[
        { label: "Score", value: "score" },
        { label: "Category", value: "category" }
      ]}
      variableOptions={[
        { label: "Response ID", value: "response_id" },
        { label: "Respondent Email", value: "respondent_email" }
      ]}
    />
  );
}
```

---

### ContactImport Component

The ContactImport component provides functionality for importing contact data with mapping, scheduling, and management capabilities.

#### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `dashboardDescription` | `string` | ✅ | Description text for dashboard |
| `existingImports` | `Array<CompletedImportTypes \| ScheduledImportTypes> \| null` | ✅ | Existing import records |
| `hasPreviousMapping` | `boolean` | ❌ | Whether previous mapping exists |
| `previousMappingHandler` | `(value?: boolean) => void` | ✅ | Previous mapping handler |
| `onSaveHandler` | `() => void` | ✅ | Save operation handler |
| `isContactMappingPage` | `boolean` | ✅ | Current page state |
| `navigateMappingPage` | `(value?: boolean) => void` | ✅ | Navigation handler |
| `contactImportField` | `ContactImportFieldType` | ✅ | Contact import configuration |
| `setContactImportField` | `React.Dispatch<React.SetStateAction<ContactImportFieldType>>` | ✅ | Configuration setter |
| `listSegmentOptions` | `SelectOption[]` | ✅ | List segment options |
| `integrationName` | `string` | ✅ | Integration name |
| `contactProperties` | `ContactProperty[]` | ✅ | Available contact properties |
| `invitePortal` | `InvitePortalType` | ✅ | Invite portal configuration |

#### ContactImportFieldType

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `configure` | `ConfigureObject \| null` | ✅ | Configuration settings |
| `description` | `string \| null` | ✅ | Import description |
| `id` | `string \| number \| null` | ✅ | Import identifier |
| `fields` | `ContactFieldType[]` | ✅ | Field mappings |
| `invitePortal` | `boolean` | ✅ | Whether to invite to portal |

#### Example

```tsx
import { ContactImport } from '@sparrowengg/integrations-templates-frontend';

function ContactImportExample() {
  const [contactImportField, setContactImportField] = useState({
    configure: null,
    description: null,
    id: null,
    fields: [],
    invitePortal: false
  });

  return (
    <ContactImport
      dashboardDescription="Manage your contact imports and sync data with your integration."
      existingImports={[]}
      hasPreviousMapping={false}
      previousMappingHandler={() => console.log('Go back')}
      onSaveHandler={() => console.log('Import saved')}
      isContactMappingPage={false}
      navigateMappingPage={(value) => console.log('Navigate:', value)}
      contactImportField={contactImportField}
      setContactImportField={setContactImportField}
      listSegmentOptions={[
        { label: "All Contacts", value: "all" },
        { label: "Active Subscribers", value: "active" }
      ]}
      integrationName="Mailchimp"
      contactProperties={[
        { id: 1, label: "Email", value: "email", type: "email" },
        { id: 2, label: "First Name", value: "first_name", type: "text" }
      ]}
      invitePortal={{
        hasInvitePortal: true,
        value: false,
        onChangeHandler: (value) => console.log('Invite portal:', value)
      }}
    />
  );
}
```

---

### IntegrationTemplate Component

The IntegrationTemplate is the main orchestrating component that manages the flow between different integration steps including mapping, triggers, and dashboard views.

#### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `singleMapping` | `SingleMappingType` | ❌ | Single mapping configuration |
| `draftHandler` | `(type: string \| null) => void` | ✅ | Draft save handler |
| `onMappingEditHandler` | `(field: unknown) => void` | ✅ | Mapping edit handler |
| `fieldOptions` | `FieldOptionsType` | ✅ | Available field options |
| `triggerEnabled` | `boolean` | ✅ | Whether triggers are enabled |
| `mappingEnabled` | `boolean` | ✅ | Whether mapping is enabled |
| `mappingComponent` | `React.ReactElement` | ✅ | Mapping component instance |
| `singleMappingComponent` | `React.ReactElement` | ❌ | Single mapping component instance |
| `mapping` | `MappingState` | ✅ | Mapping state object |
| `triggerComponent` | `React.ReactElement` | ✅ | Trigger component instance |
| `trigger` | `TriggerState` | ✅ | Trigger state object |
| `integrationName` | `string` | ✅ | Integration name |
| `onDeleteHandler` | `(id: string \| number) => void` | ❌ | Delete handler |
| `toggleDashboardField` | `(id: string \| number, status: boolean) => void` | ❌ | Dashboard field toggle |
| `dashboardDescription` | `string` | ✅ | Dashboard description |
| `mappingDescription` | `string` | ✅ | Mapping description |
| `triggerDescription` | `string` | ✅ | Trigger description |
| `handlePreviousNavigation` | `() => void` | ✅ | Previous navigation handler |
| `surveyType` | `string` | ❌ | Survey type |
| `syncMapping` | `(id: string \| number) => void` | ❌ | Sync mapping handler |

#### Example

```tsx
import { IntegrationTemplate, Mapping, Triggers } from '@sparrowengg/integrations-templates-frontend';

function IntegrationTemplateExample() {
  const [mappingFields, setMappingFields] = useState({ type: "MAPPING", fields: [] });
  const [triggerFields, setTriggerFields] = useState([]);

  const mappingComponent = (
    <Mapping
      // ... mapping props
      onSaveHandler={() => console.log('Mapping saved')}
    />
  );

  const triggerComponent = (
    <Triggers
      // ... trigger props
      onSaveHandler={() => console.log('Trigger saved')}
    />
  );

  return (
    <IntegrationTemplate
      draftHandler={(type) => console.log('Save draft:', type)}
      onMappingEditHandler={(field) => console.log('Edit mapping:', field)}
      fieldOptions={[
        { label: "Email", value: "email" },
        { label: "Name", value: "name" }
      ]}
      triggerEnabled={true}
      mappingEnabled={true}
      mappingComponent={mappingComponent}
      mapping={{
        mappedFields: mappingFields,
        setMappedFields: setMappingFields
      }}
      triggerComponent={triggerComponent}
      trigger={{
        mappedFields: triggerFields,
        setMappedFields: setTriggerFields
      }}
      integrationName="Salesforce"
      dashboardDescription="Manage your Salesforce integration configurations."
      mappingDescription="Map survey fields to Salesforce objects."
      triggerDescription="Set up automated triggers based on survey responses."
      handlePreviousNavigation={() => console.log('Navigate back')}
    />
  );
}
```

## 🎨 Styling

The library includes built-in CSS styles. Make sure to import the stylesheet:

```tsx
import '@sparrowengg/integrations-templates-frontend/dist/es/index.css';
```

All components use the Twigs React design system and support custom theming through the ThemeProvider.

## 🔧 Advanced Usage

### Custom Theme Configuration

```tsx
import { ThemeProvider } from '@sparrowengg/twigs-react';

const customTheme = {
  fonts: {
    body: "Inter, sans-serif",
    heading: "Inter, sans-serif"
  },
  colors: {
    primary500: "#4A9CA6"
  }
};

function App() {
  return (
    <ThemeProvider theme={customTheme}>
      {/* Your components */}
    </ThemeProvider>
  );
}
```

### Error Handling

Components provide error states and validation feedback:

```tsx
// Field with validation error
{
  id: "email",
  type: "input",
  label: "Email",
  value: "invalid-email",
  changeFieldValue: handleChange,
  required: true,
  // Error will be shown if validation fails
}
```

### Loading States

Most components support loading states for async operations:

```tsx
<Mapping
  onSaveMappingLoader={true} // Shows loading spinner on save button
  // ... other props
/>
```

## 🤝 TypeScript Support

The library is built with TypeScript and provides comprehensive type definitions for all components and props. Import types as needed:

```tsx
import type { 
  MappingProps, 
  TriggerProps,
  SelectOption,
  FieldType 
} from '@sparrowengg/integrations-templates-frontend';
```

## 📖 API Reference

### Common Types

#### SelectOption
```tsx
type SelectOption = {
  label: string;
  value: string | number;
  type?: string;
};
```

#### SurveyDetails
```tsx
type SurveyDetails = {
  surveyName: string;
  surveyId: string | number;
};
```

#### FormFieldValue
```tsx
type FormFieldValue = string | number | boolean | null | SelectOption | SelectOption[];
```
