58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
import { apiClient } from "@/lib/api/client"
|
|
import type { ContactImportInput } from "@/lib/contacts/import-parsers"
|
|
|
|
/** Backend bulk-import item (user derived from token; never in the body). */
|
|
export type BulkImportContact = {
|
|
full_name?: string
|
|
email?: string
|
|
phone?: string
|
|
org?: string
|
|
uid?: string
|
|
raw_vcard?: string
|
|
}
|
|
|
|
export type BulkImportResult = {
|
|
created: number
|
|
failed: { index: number; error: string }[]
|
|
}
|
|
|
|
/** Backend caps: 5000 contacts / request, 8 MiB body. */
|
|
const MAX_PER_REQUEST = 5000
|
|
|
|
export function importInputToBulk(c: ContactImportInput): BulkImportContact {
|
|
const fullName = `${c.firstName} ${c.lastName}`.trim()
|
|
return {
|
|
full_name: fullName || c.emails[0]?.value || undefined,
|
|
email: c.emails[0]?.value,
|
|
phone: c.phones[0]?.value,
|
|
org: c.company,
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk import contacts into a book via POST /contacts/books/{bookID}/import,
|
|
* chunked to respect the backend per-request cap. Replaces the previous
|
|
* N-times-POST loop.
|
|
*/
|
|
export async function bulkImportContacts(
|
|
bookId: string,
|
|
contacts: (BulkImportContact | string)[]
|
|
): Promise<BulkImportResult> {
|
|
let created = 0
|
|
const failed: { index: number; error: string }[] = []
|
|
|
|
for (let offset = 0; offset < contacts.length; offset += MAX_PER_REQUEST) {
|
|
const chunk = contacts.slice(offset, offset + MAX_PER_REQUEST)
|
|
const res = await apiClient.post<BulkImportResult>(
|
|
`/contacts/books/${encodeURIComponent(bookId)}/import`,
|
|
{ contacts: chunk }
|
|
)
|
|
created += res?.created ?? 0
|
|
for (const f of res?.failed ?? []) {
|
|
failed.push({ index: f.index + offset, error: f.error })
|
|
}
|
|
}
|
|
|
|
return { created, failed }
|
|
}
|