# Data Import Wizard URL: /docs/web/components/data-import-wizard Multi-step modal wizard that turns an Excel/CSV upload into Docyrus data source records — drag-drop, auto-mapped column→field assignment, per-type config, value-renderer preview, and a result summary. **Demo:** ```tsx 'use client'; import { useState } from 'react'; import { Button } from '@docyrus/ui/primitives/ui/button'; import { DataImportWizard, type AnalysedFile, type ImportWizardStep, type WizardMappingMap, buildAutoMapping } from '@docyrus/ui/components/data-import-wizard'; const MOCK_FIELDS = [ { id: '1', slug: 'name', name: 'Name', type: 'field-text' }, { id: '2', slug: 'email', name: 'Email', type: 'field-email' }, { id: '3', slug: 'phone', name: 'Phone', type: 'field-phone' }, { id: '4', slug: 'company', name: 'Company', type: 'field-text' }, { id: '5', slug: 'status', name: 'Status', type: 'field-status', enums: [ { id: 's-active', name: 'Active', color: 'emerald-500', slug: 'active' }, { id: 's-lead', name: 'Lead', color: 'blue-500', slug: 'lead' }, { id: 's-cold', name: 'Cold', color: 'slate-500', slug: 'cold' } ] }, { id: '6', slug: 'last_contacted', name: 'Last contacted', type: 'field-date' } ] as const; const MOCK_ANALYSED: AnalysedFile = { fileName: 'demo-contacts.xlsx', columns: [ 'Full Name', 'Email Address', 'Phone', 'Company', 'Stage', 'Last Touch' ], rows: [ { 'Full Name': 'Ada Lovelace', 'Email Address': 'ada@analytical.engine', Phone: '5551112233', Company: 'Analytical Engine', Stage: 'Active', 'Last Touch': '2026-01-12' }, { 'Full Name': 'Alan Turing', 'Email Address': 'alan@bletchley.uk', Phone: '5550005555', Company: 'Bletchley Park', Stage: 'Lead', 'Last Touch': '2026-02-04' }, { 'Full Name': 'Grace Hopper', 'Email Address': 'grace@nhc.mil', Phone: '5557778888', Company: 'Naval History Command', Stage: 'Cold', 'Last Touch': '2025-11-30' } ], uniqueFieldIds: [], uniqueFieldSlugs: ['email'] }; export function DataImportWizardDemo() { const [open, setOpen] = useState(false); const [step, setStep] = useState {wizard} ); } ``` ## Wizard Steps | Step | Purpose | |------|---------| | **Upload** | Drag-drop / file picker. Validates extension + size client-side, then chains `upload → analyse` mutations. | | **Map fields** | One card per source column. Per type: relation `reference_key`, phone country code, date format, money/phone companion column. Auto-maps obvious matches. | | **Options** | Toggle "Update existing records on unique-key match" (`upsertUniqueFields`). Summary tiles for row, column, and unique-field counts. | | **Preview** | Renders the first N rows using `useDocyrusFieldComponent(field.type, 'value-renderer')` so every cell looks like it does in ``. | | **Result** | Tiles for successful records, warnings, duplicates, and errors. Per-row error list. "Import another file" / "Done" actions. | ## API Reference ### `` The dumb component. Drive every prop from your own state — typically through `useDocyrusDataImportWizard`, which already wires every prop. Only reach for the component directly when you need a custom state machine (e.g. a server-component wrapper). | Prop | Type | Description | |------|------|-------------| | `open` / `onOpenChange` | `boolean` / `(open: boolean) => void` | Modal open state. | | `step` / `onStepChange` | `ImportWizardStep` / `(step) => void` | Current step + setter. Steps: `upload`, `mapping`, `options`, `preview`, `progress`, `result`. | | `targetFields` | `ReadonlyArray` | Fields the user can map to. Supplied by the hook from `useDocyrusDataViewSelect`. | | `requiredFieldSlugs` | `ReadonlyArray` | Slugs that must be mapped before leaving the mapping step. | | `uniqueFieldSlugs` | `ReadonlyArray` | Slugs covered by unique indexes (drives the upsert toggle). | | `file` / `uploadedFile` / `analysedFile` / `importResult` | various | Snapshots of each phase's payload. | | `mapping` / `onMappingChange` | `WizardMappingMap` / `(next) => void` | Per-source-column mapping state. | | `upsertUniqueFields` / `onUpsertChange` | `boolean` / `(next) => void` | Upsert toggle. | | `isUploading` / `isAnalysing` / `isImporting` | `boolean` | Mutation pending flags. | | `uploadError` / `analyseError` / `importError` | `Error \| null` | Per-phase errors surfaced in the relevant step's banner. | | `onPickFile` / `onAnalyse` / `onConfirmMapping` / `onConfirmOptions` / `onStartImport` / `onReset` / `onClose` | callbacks | Hook into each step's primary action. | | `title` / `description` / `icon` | `ReactNode` / `ReactNode` / `string` | Header customization (defaults are translated). | | `previewRowCount` | `number` | Default `10`. | | `maxFileSizeBytes` | `number` | Default `20 * 1024 * 1024` (20 MB). | | `acceptedExtensions` | `ReadonlyArray` | Default `['xlsx', 'xls', 'csv']`. | | `className` | `string` | Extra class for the dialog body. | ## Components | Component | Description | |-----------|-------------| | `DataImportWizard` | Top-level shell — composes `AwesomeDialog` + `Stepper` + step bodies + footer. | | `UploadStep` | Step 1 — drag-drop + file picker + spinners. | | `MappingStep` | Step 2 — per-column target select + per-type sub-config. | | `OptionsStep` | Step 3 — upsert toggle + summary tiles. | | `PreviewStep` | Step 4 — value-renderer-driven preview table. | | `ProgressStep` | Steps 5/6 — progress UI + result summary tiles. | Each step component is exported individually so consumers can rearrange or replace them in custom flows. ## Helpers | Helper | Description | |--------|-------------| | `buildAutoMapping(columns, fields)` | Greedy slug + name + token-Jaccard matcher. Returns a `WizardMappingMap`. | | `inferFieldOptions(field)` | Default `fieldOptions` for `field-relation`, `field-phone`, and `field-date*` (matches the import API contract). | | `validateMapping(mapping, requiredSlugs)` | Returns `{ valid, missing, duplicateTargets }`. | | `buildImportOptions(mapping, fields, upsert, uniqueData?)` | Converts UI state to the `{ fieldMapping, fieldOptions, uniqueData, upsertUniqueFields }` POST body. | | `collectUniqueDataLookups(mapping, fields, analysedFile)` | Identifies columns that benefit from `uniqueData` pre-resolution. | | `buildUniqueDataPayload(specs, resolved)` | Merges pre-resolved `matchedId` maps with the lookup specs into the final payload entry. | | `getSecondarySlug(fieldType)` | Returns `'__amount_currency'` / `'__phone_country'` for composite field types. | | `slugify(value)` / `normalizeKey(value)` | Lowercase / kebab-case helpers used by the auto-mapper. | ## Type Exports | Type | Description | |------|-------------| | `DataImportWizardProps` | Props for the top-level component. | | `ImportWizardStep` | `'upload' \| 'mapping' \| 'options' \| 'preview' \| 'progress' \| 'result'`. | | `WizardMappingMap` | `Record`. | | `ColumnMappingState` | Per-source-column UI mapping: target slug, optional companion column, type-specific `fieldOptions`. | | `UploadedFileInfo` | Shape returned by the upload endpoint. | | `AnalysedFile` | Shape returned by the analyse endpoint (rows, columns, unique-field hints). | | `ImportPayloadOptions` | Body posted to the import endpoint. | | `ImportResultPayload` | Result returned by the import endpoint (success count, errors, duplicates). | | `MappingValidationResult` | `{ valid, missing, duplicateTargets }`. | | `ReservedTargetSlug` | `'name' \| 'description' \| 'created_on' \| 'autonumber_id'`. | | `UniqueDataLookupSpec` | Helper type produced by `collectUniqueDataLookups`. | ## Field-Type Awareness Like `useDocyrusDataGrid`, every field type is handled automatically: | Field type | Mapping-step extras | Preview | |------------|---------------------|---------| | `field-relation`, `field-relatedField`, `field-userSelect`, `field-userMultiSelect` | `reference_key` text input (defaults to `'name'`). | Relation chip via `RelationValue`. | | `field-phone` | Default country code input (`+90` default) + companion column for `__phone_country`. | Phone display. | | `field-money` | Companion column select for `__amount_currency`. | Currency formatter. | | `field-date`, `field-dateTime`, `field-dateRange` | DAY/MONTH/YEAR ordering select. | Tenant-aware date formatter. | | `field-enum`, `field-status`, `field-select`, `field-radioGroup`, `field-multiSelect`, `field-tagSelect` | Auto-mapped to the matching slug. | Color-coded enum chip. | | Reserved (`name`, `description`, `created_on`, `autonumber_id`) | Surfaced in the **System** group. | Plain text. | ## See Also - [`useDocyrusDataImportWizard`](/docs/web/hooks/use-docyrus-data-import-wizard) — smart hook that wires the wizard to a Docyrus data source in one call. - [`useDocyrusFieldComponent`](/docs/web/hooks/use-docyrus-field-component) — the registry that powers the preview-step value renderers. - [`useDocyrusDataGrid`](/docs/web/hooks/use-docyrus-data-grid) — companion hook for displaying the imported records in a grid.