import { useState, useRef } from 'react' import { importContacts } from '../api/api' import './ImportContacts.css' /** * ImportContacts * * Opens a modal that lets the user upload a CSV or JSON file of contacts and * import them into the current event's guest list. * * Props: * eventId – UUID of the current event * onImportComplete – callback called when a real (non-dry-run) import succeeds */ function ImportContacts({ eventId, onImportComplete }) { const [open, setOpen] = useState(false) const [file, setFile] = useState(null) const [isDryRun, setIsDryRun] = useState(false) const [dragging, setDragging] = useState(false) const [loading, setLoading] = useState(false) const [result, setResult] = useState(null) // ImportContactsResponse const [error, setError] = useState('') const fileInputRef = useRef() // ── helpers ──────────────────────────────────────────────────────────────── const reset = () => { setFile(null) setResult(null) setError('') setLoading(false) setIsDryRun(false) } const handleClose = () => { setOpen(false) reset() } const handleFileChange = (e) => { const f = e.target.files?.[0] if (f) { setFile(f); setResult(null); setError('') } } const handleDrop = (e) => { e.preventDefault() setDragging(false) const f = e.dataTransfer.files?.[0] if (f) { setFile(f); setResult(null); setError('') } } // ── submit ───────────────────────────────────────────────────────────────── const handleUpload = async () => { if (!file) { setError('אנא בחר קובץ לפני ההעלאה.'); return } setLoading(true) setError('') setResult(null) try { const res = await importContacts(eventId, file, isDryRun) setResult(res) if (!isDryRun && (res.created > 0 || res.updated > 0) && onImportComplete) { onImportComplete() } } catch (err) { const msg = err?.response?.data?.detail || err.message || 'שגיאה בעת ייבוא הקובץ.' setError(typeof msg === 'string' ? msg : JSON.stringify(msg)) } finally { setLoading(false) } } // ── action label helpers ─────────────────────────────────────────────────── const actionLabel = { created: { text: 'נוצר', cls: 'badge-created' }, updated: { text: 'עודכן', cls: 'badge-updated' }, skipped: { text: 'דולג', cls: 'badge-skipped' }, error: { text: 'שגיאה', cls: 'badge-error' }, would_create: { text: 'ייווצר', cls: 'badge-dry' }, } // ── modal ────────────────────────────────────────────────────────────────── if (!open) { return ( ) } return (
{file.name}
לחץ להחלפת הקובץ
> ) : ( <> 📄גרור קובץ CSV או JSON לכאן
או לחץ לבחירת קובץ
> )}CSV — כל שורה = אורח. עמודות נתמכות:
First Name, Last Name, Full Name, Phone, Email, RSVP, Meal, Notes, Side, Table
JSON — מערך של אובייקטים עם אותן שדות, או {`{"data":[…]}`}.
הייבוא ניתן לביצוע כפעולת מה-Excel שיצאת: אותן עמודות שמופיעות בייצוא לאקסל.
| # | שם | טלפון | פעולה | הערה |
|---|---|---|---|---|
| {r.row} | {r.name || '—'} | {r.phone || '—'} | {lbl.text} | {r.reason || ''} |