File size: 4,202 Bytes
c5fde49
 
6dd9bad
a966957
c5fde49
 
 
 
 
 
 
 
 
6dd9bad
 
 
 
c5fde49
 
 
 
3d1299e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c5fde49
 
3d1299e
c5fde49
 
 
 
 
 
 
 
 
 
3d1299e
 
 
 
 
 
 
 
 
c5fde49
3d1299e
 
 
6dd9bad
 
c5fde49
6dd9bad
 
 
 
 
3d1299e
a966957
3d1299e
 
c5fde49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import React from 'react';
import { read, utils } from 'xlsx';
import { api } from '../../lib/api';
import { logError } from '../../lib/logger';

interface FileImporterProps {
    token: string;
    selectedOrgId: string;
    onImportSuccess: (data: { listId: string; listName: string; count: number }) => void;
    onImportError: (error: string) => void;
    setIsUploading: (loading: boolean) => void;
}

export const FileImporter: React.FC<FileImporterProps> = ({
    token,
    selectedOrgId,
    onImportSuccess,
    onImportError,
    setIsUploading
}) => {
    
    const normalizeContacts = (rows: any[]): { phoneNumber: string; name?: string; attributes: Record<string, unknown> }[] => {
        const PHONE_KEYS = ['phonenumber', 'phone', 'telephone', 'téléphone', 'mobile', 'numero', 'numéro', 'number', 'whatsapp', 'tel'];
        const NAME_KEYS  = ['name', 'nom', 'prenom', 'prénom', 'firstname', 'lastname', 'fullname', 'contact'];

        return rows.reduce<{ phoneNumber: string; name?: string; attributes: Record<string, unknown> }[]>((acc, row) => {
            const keys = Object.keys(row);

            const phoneKey = keys.find(k => PHONE_KEYS.includes(k.toLowerCase().replace(/[\s_-]/g, '')));
            const nameKey  = keys.find(k => NAME_KEYS.includes(k.toLowerCase().replace(/[\s_-]/g, '')));

            const raw = phoneKey ? String(row[phoneKey]).replace(/\s+/g, '') : null;
            if (!raw) return acc; // skip rows with no phone

            // Keep remaining columns as attributes
            const attributes: Record<string, unknown> = {};
            keys.forEach(k => {
                if (k !== phoneKey && k !== nameKey) attributes[k] = row[k];
            });

            acc.push({
                phoneNumber: raw,
                ...(nameKey ? { name: String(row[nameKey]) } : {}),
                attributes
            });
            return acc;
        }, []);
    };

    const handleFile = async (file: File) => {
        if (!token || !selectedOrgId) return;

        setIsUploading(true);
        const reader = new FileReader();

        reader.onload = async (event) => {
            try {
                // 1. Parse Excel/CSV on the client side
                const data = new Uint8Array(event.target?.result as ArrayBuffer);
                const workbook = read(data, { type: 'array' });
                const firstSheetName = workbook.SheetNames[0];
                const worksheet = workbook.Sheets[firstSheetName];
                const rawRows = utils.sheet_to_json(worksheet);

                // 2. Normalize column names → { phoneNumber, name?, attributes }
                const contacts = normalizeContacts(rawRows);
                if (contacts.length === 0) {
                    onImportError("Aucun contact trouvé. Vérifiez que votre fichier contient une colonne \"Téléphone\" ou \"Mobile\".");
                    setIsUploading(false);
                    return;
                }

                // 3. Send JSON to the bulk endpoint
                const responseData = await api.post(`/v1/organizations/${selectedOrgId}/contacts/bulk`, {
                    contacts,
                    listName: file.name.split('.')[0]
                }, token, selectedOrgId);

                onImportSuccess({
                    listId: responseData.listId,
                    listName: responseData.listName,
                    count: responseData.results.created
                });
            } catch (err: any) {
                logError("Parsing/Upload failed:", err);
                const msg = typeof err?.message === 'string' && !err.message.includes('[object') ? err.message : "Une erreur technique est survenue.";
                onImportError(msg);
            } finally {
                setIsUploading(false);
            }
        };

        reader.readAsArrayBuffer(file);
    };

    return (
        <input 
            type="file" 
            id="crm-file-upload" 
            className="hidden" 
            accept=".xlsx,.csv"
            onChange={(e) => {
                const file = e.target.files?.[0];
                if (file) handleFile(file);
            }}
        />
    );
};