File size: 4,654 Bytes
005df22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
110
111
112
113
114
115
116
117
118
119
import React, { useState } from 'react';
import { Loader2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { apiFetch } from '@/lib/api';

const EMPTY_DRAFT = { first_name: '', last_name: '', email: '', title: '', phone: '' };

/**
 * "Add a contact" mini-form for the associated-contacts section of a company-scoped detail
 * panel (Companies / Leads / Deals). Creates the contact via the generic POST /api/contacts
 * route with `company` locked to `companyName` — unlike the Companies page's own
 * /api/companies/{id}/contacts route, this doesn't require an existing Company row, so it
 * works even when the lead/deal's company hasn't synced into one yet.
 */
export default function AddContactForm({ companyName, onAdded, className }) {
    const [draft, setDraft] = useState(EMPTY_DRAFT);
    const [saving, setSaving] = useState(false);
    const [error, setError] = useState('');

    const setField = (key, value) => setDraft((d) => ({ ...d, [key]: value }));

    const save = async () => {
        const email = draft.email.trim();
        if (!email) {
            setError('Email is required');
            return;
        }
        if (!email.includes('@')) {
            setError('Enter a valid email address');
            return;
        }
        setSaving(true);
        setError('');
        try {
            const res = await apiFetch('/api/contacts', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    first_name: draft.first_name.trim(),
                    last_name: draft.last_name.trim(),
                    email,
                    title: draft.title.trim(),
                    phone: draft.phone.trim(),
                    company: companyName,
                }),
            });
            const data = await res.json().catch(() => ({}));
            if (!res.ok) {
                setError(typeof data.detail === 'string' ? data.detail : 'Could not save contact');
                return;
            }
            setDraft(EMPTY_DRAFT);
            onAdded && onAdded(data);
        } catch (e) {
            console.error(e);
            setError('Network error');
        } finally {
            setSaving(false);
        }
    };

    return (
        <div className={className || 'rounded-xl border border-slate-200 bg-slate-50/50 p-4'}>
            <h5 className="mb-3 text-sm font-semibold text-slate-700">Add a contact</h5>
            <div className="grid grid-cols-1 gap-2 sm:grid-cols-2">
                <Input
                    className="bg-white text-sm"
                    placeholder="First name"
                    value={draft.first_name}
                    onChange={(e) => setField('first_name', e.target.value)}
                    disabled={saving}
                />
                <Input
                    className="bg-white text-sm"
                    placeholder="Last name"
                    value={draft.last_name}
                    onChange={(e) => setField('last_name', e.target.value)}
                    disabled={saving}
                />
                <Input
                    className="bg-white text-sm sm:col-span-2"
                    type="email"
                    placeholder="Email"
                    value={draft.email}
                    onChange={(e) => setField('email', e.target.value)}
                    disabled={saving}
                />
                <Input
                    className="bg-white text-sm"
                    placeholder="Title"
                    value={draft.title}
                    onChange={(e) => setField('title', e.target.value)}
                    disabled={saving}
                />
                <Input
                    className="bg-white text-sm"
                    type="tel"
                    placeholder="Contact number"
                    value={draft.phone}
                    onChange={(e) => setField('phone', e.target.value)}
                    disabled={saving}
                />
            </div>
            {error ? <p className="mt-2 text-xs text-red-600">{error}</p> : null}
            <Button type="button" className="mt-3 w-full" onClick={save} disabled={saving}>
                {saving ? (
                    <>
                        <Loader2 className="mr-2 h-4 w-4 animate-spin" aria-hidden />
                        Saving…
                    </>
                ) : (
                    'Add contact'
                )}
            </Button>
        </div>
    );
}