Skip to content

feat: Contact Import — CSV/Excel with column mapping and duplicate detection#156

Merged
Systemsaholic merged 6 commits intomainfrom
feature/contact-import-backend
Apr 3, 2026
Merged

feat: Contact Import — CSV/Excel with column mapping and duplicate detection#156
Systemsaholic merged 6 commits intomainfrom
feature/contact-import-backend

Conversation

@Systemsaholic
Copy link
Copy Markdown
Owner

@Systemsaholic Systemsaholic commented Apr 3, 2026

Summary

Full contact import system: upload CSV/Excel files, map columns to Tailfire fields, preview with duplicate detection, import with auto-tagging and ownership rules.

Backend (706 lines)

  • ContactImportService — preview + confirm with:
    • Duplicate matching: email → name+DOB → name-only (possible_match)
    • Multi-match resolution: agent-owned > agency-wide > skip
    • Ownership rules: agents can't modify other agents' contacts
    • Fill-only merge: only updates null fields on existing contacts
    • Auto-tagging via TagsService
  • ContactImportControllerPOST /contacts/import/preview + POST /contacts/import/confirm
  • ownerId fix — now persisted in ContactsService.create()

Frontend

  • Parse utilities — Papa Parse (CSV) + SheetJS (Excel), column auto-detection, date/phone/country normalization
  • ImportColumnMapper — column mapping UI with auto-detect + tag input
  • ImportPreviewTable — disposition badges (new/update/possible_match/skip), per-row actions
  • ContactImportWizard — 4-step dialog: Upload → Map Columns → Preview → Import
  • Import button added to contacts page header

New Dependencies

  • papaparse + @types/papaparse — CSV parsing
  • xlsx (SheetJS) — Excel parsing

Test plan

  • Click Import → wizard opens
  • Upload CSV with common headers → auto-detection maps columns
  • Preview shows dispositions (new/update/skip) with match details
  • Import creates contacts with correct ownership and tags
  • Existing contacts matched by email get fill-only merge
  • Contacts owned by other agents are skipped

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features
    • Added bulk contacts import functionality supporting CSV and Excel file uploads
    • Multi-step import wizard guides users through column mapping, tag assignment, and preview validation
    • Automatic duplicate detection identifies new contacts, updates, and potential matches during preview
    • Confirmation step allows users to confirm, skip, or merge detected duplicates before final import
    • Tags can be assigned to all imported contacts in a single action

Systemsaholic and others added 6 commits April 3, 2026 09:39
ContactImportService with duplicate matching (email → name+DOB → name),
ownership rules, fill-only merge, multi-match resolution.
POST /contacts/import/preview and POST /contacts/import/confirm.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…hooks

React Query mutations following the cruise booking import pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Column auto-detection, date/phone/country normalization, CSV/Excel parsing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Column mapping UI with auto-detected defaults, override dropdowns,
and tag input for import tagging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Preview table with per-row selection, disposition coloring,
and action dropdowns for possible_match rows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4-step wizard: Upload → Column Mapping → Preview → Import.
Import button added to contacts page header.
Also fixes pre-existing strict-mode type errors in parse-contacts,
column-detection, and normalize-contacts (non-null assertions for
regex capture groups and array accesses).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Systemsaholic Systemsaholic merged commit 6f4bf43 into main Apr 3, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tailfire-client Ready Ready Preview, Comment Apr 3, 2026 1:53pm
tailfire-ota Ready Ready Preview, Comment Apr 3, 2026 1:53pm

Request Review

@Systemsaholic Systemsaholic deleted the feature/contact-import-backend branch April 3, 2026 13:52
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 3, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e311c8b5-d488-4ace-be75-ebe3bab96ccd

📥 Commits

Reviewing files that changed from the base of the PR and between 1726477 and f38bd4a.

📒 Files selected for processing (11)
  • apps/admin/src/app/contacts/_components/contact-import-wizard.tsx
  • apps/admin/src/app/contacts/_components/import-column-mapper.tsx
  • apps/admin/src/app/contacts/_components/import-preview-table.tsx
  • apps/admin/src/app/contacts/page.tsx
  • apps/admin/src/hooks/use-contact-import.ts
  • apps/admin/src/lib/import/column-detection.ts
  • apps/admin/src/lib/import/normalize-contacts.ts
  • apps/admin/src/lib/import/parse-contacts.ts
  • apps/api/src/contacts/contact-import.controller.ts
  • apps/api/src/contacts/contact-import.service.ts
  • apps/api/src/contacts/contacts.module.ts

📝 Walkthrough

Walkthrough

This PR introduces a comprehensive contacts import workflow for the admin panel and backend. The changes include a multi-step import wizard UI (file upload → column mapping → preview → results), file parsing for CSV/Excel, data normalization utilities, duplicate detection and contact merge logic, and corresponding API endpoints for preview and confirmation phases.

Changes

Cohort / File(s) Summary
Admin Import UI Components
apps/admin/src/app/contacts/_components/contact-import-wizard.tsx, apps/admin/src/app/contacts/_components/import-column-mapper.tsx, apps/admin/src/app/contacts/_components/import-preview-table.tsx
Introduces multi-step import wizard managing upload, mapping, preview, and results states. Includes column-to-field mapping interface with tag assignment and a preview table with row-level action controls (create/merge/skip) for possible matches and aggregate statistics display.
Admin Page Integration
apps/admin/src/app/contacts/page.tsx
Adds "Import" button to contacts page header and integrates ContactImportWizard dialog control via local state.
Admin Import Hooks
apps/admin/src/hooks/use-contact-import.ts
Exports two React Query mutations: useContactImportPreview for POST to /contacts/import/preview and useContactImportConfirm for POST to /contacts/import/confirm with automatic contacts list cache invalidation on success.
Import File Parsing
apps/admin/src/lib/import/parse-contacts.ts
Implements async file parsing supporting CSV (Papa Parse) and Excel (SheetJS) formats with normalized string output and error handling for unsupported/empty files.
Import Data Utilities
apps/admin/src/lib/import/column-detection.ts, apps/admin/src/lib/import/normalize-contacts.ts
Provides column auto-detection against predefined field mappings, full-name splitting, and data normalization for phone, date, country, and contact fields with multi-format support and validation.
API Import Endpoints
apps/api/src/contacts/contact-import.controller.ts
NestJS controller exposing two endpoints: POST /contacts/import/preview and POST /contacts/import/confirm with authentication and delegation to import service.
API Import Service
apps/api/src/contacts/contact-import.service.ts
Core service implementing two-phase import: preview phase performs duplicate detection across email, name+DOB, and name-only strategies with ownership scoping; confirm phase creates/merges contacts with fill-only merge semantics, ownership enforcement, and bulk tag assignment with fallback to case-insensitive lookup.
Module Configuration
apps/api/src/contacts/contacts.module.ts
Updates ContactsModule to register import controller and service, adds TagsModule import, and reorders controller registration to prioritize /contacts/import route over /contacts/:id.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Wizard as Import Wizard
    participant Admin as Admin Frontend
    participant Preview as Preview API
    participant Service as Import Service
    participant DB as Database

    User->>Wizard: 1. Upload file + map columns
    Wizard->>Admin: Parse & normalize rows
    Admin->>Admin: Auto-detect mapping
    User->>Wizard: 2. Review preview & select actions
    Wizard->>Preview: POST /contacts/import/preview
    Preview->>Service: preview(rows, auth)
    Service->>DB: Query duplicates (email, name+DOB, name)
    DB-->>Service: Match candidates
    Service-->>Preview: Dispositions (new/update/possible_match/skip)
    Preview-->>Admin: Preview results with summary
    Wizard->>Wizard: Display preview table with action dropdown
    User->>Wizard: 3. Confirm import & assign tags
    Wizard->>Wizard: Collect row actions & selected tags
    Wizard->>Preview: POST /contacts/import/confirm
    Preview->>Service: confirm(rows, tags, auth)
    Service->>DB: Create new contacts
    Service->>DB: Merge (fill-only) existing contacts
    Service->>DB: Assign tags to contacts
    DB-->>Service: Success/error per-row results
    Service-->>Preview: Confirmation summary & errors
    Preview-->>Admin: Import complete with statistics
    Admin-->>User: Display results dialog
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~70 minutes

Possibly related PRs

Poem

🐰 With files parsed and columns aligned,
Duplicates detected, contacts entwined,
Preview, then merge with tags in tow,
Bulk imports now steal the show!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/contact-import-backend

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant