Files
workavia-calendar-front/src/components/Attendees/usePasteHandler.ts
T
Benoit TELLIER c9710d7651 feat: parse multiple attendees from pasted text (#723) (#731)
When pasting text containing multiple email addresses into the attendee
input, the component now splits by comma, semicolon, newline, or space
and adds each valid email as an individual attendee chip. Duplicates
are silently skipped. Any invalid chunks remain in the input field
with an error message so the user can correct them manually.

Co-authored-by: JacobiusMakes <jgalperin98@gmail.com>
2026-03-30 13:23:07 +02:00

71 lines
2.0 KiB
TypeScript

import { useCallback } from "react";
import type { SyntheticEvent } from "react";
import { isValidEmail } from "../../utils/isValidEmail";
import type { User } from "./PeopleSearch";
export function usePasteHandler({
freeSolo,
selectedUsers,
onChange,
setQuery,
setInputError,
t,
}: {
freeSolo?: boolean;
selectedUsers: User[];
onChange: (event: SyntheticEvent, users: User[]) => void;
setQuery: (value: string) => void;
setInputError: (error: string | null) => void;
t: (key: string) => string;
}) {
return useCallback(
(event: React.ClipboardEvent<HTMLInputElement>) => {
if (!freeSolo) return;
const pasted = event.clipboardData.getData("text/plain");
if (!pasted) return;
// Split by comma, semicolon, newline, or whitespace
const chunks = pasted
.split(/[,;\n\r\s]+/)
.map((s) => s.trim())
.filter(Boolean);
// If there is only one chunk, let the default Autocomplete behaviour handle it
if (chunks.length <= 1) return;
event.preventDefault();
const existingEmails = new Set(selectedUsers.map((u) => u.email));
const validUsers: User[] = [];
const invalid: string[] = [];
for (const chunk of chunks) {
if (!isValidEmail(chunk)) {
invalid.push(chunk);
} else if (!existingEmails.has(chunk)) {
existingEmails.add(chunk);
validUsers.push({ email: chunk, displayName: chunk });
}
// silently skip duplicates
}
if (validUsers.length > 0) {
onChange(event, [...selectedUsers, ...validUsers]);
}
if (invalid.length > 0) {
// Leave the invalid text in the input for manual correction
setQuery(invalid.join(", "));
setInputError(
t("peopleSearch.invalidEmail").replace("%{email}", invalid.join(", "))
);
} else {
setQuery("");
setInputError(null);
}
},
[freeSolo, selectedUsers, onChange, setQuery, setInputError, t]
);
}