From 2c78a037a9cd442dbd91ccd1753f2f1a1d976a9f Mon Sep 17 00:00:00 2001 From: Camille Moussu <66134347+Eriikah@users.noreply.github.com> Date: Thu, 25 Sep 2025 11:25:22 +0200 Subject: [PATCH] allow external attendees (#141) * [#122] added external attendees * fixup! [#122] added external attendees * fixup! [#122] added external attendees * Update src/components/Attendees/AttendeeSearch.tsx --------- Co-authored-by: Camille Moussu Co-authored-by: Benoit TELLIER --- __test__/components/PeopleSearch.test.tsx | 1 + src/components/Attendees/AttendeeSearch.tsx | 2 + src/components/Attendees/PeopleSearch.tsx | 64 +++++++++++++++---- src/components/Calendar/CalendarSearch.tsx | 1 + .../Calendar/TempCalendarsInput.tsx | 1 + 5 files changed, 56 insertions(+), 13 deletions(-) diff --git a/__test__/components/PeopleSearch.test.tsx b/__test__/components/PeopleSearch.test.tsx index 8758697..bfaae91 100644 --- a/__test__/components/PeopleSearch.test.tsx +++ b/__test__/components/PeopleSearch.test.tsx @@ -27,6 +27,7 @@ describe("PeopleSearch", () => { const onChange = jest.fn(); renderWithProviders( { setAttendees( @@ -48,6 +49,7 @@ export default function UserSearch({ ); setSelectedUsers(value); }} + freeSolo /> ); diff --git a/src/components/Attendees/PeopleSearch.tsx b/src/components/Attendees/PeopleSearch.tsx index 4ea53af..024ff88 100644 --- a/src/components/Attendees/PeopleSearch.tsx +++ b/src/components/Attendees/PeopleSearch.tsx @@ -32,24 +32,32 @@ export interface User { export function PeopleSearch({ selectedUsers, onChange, + objectTypes, disabled, + freeSolo, onToggleEventPreview, }: { selectedUsers: User[]; onChange: Function; + objectTypes: string[]; disabled?: boolean; + freeSolo?: boolean; onToggleEventPreview?: Function; }) { const [query, setQuery] = useState(""); const [loading, setLoading] = useState(false); const [options, setOptions] = useState([]); + + const isValidEmail = (email: string) => + /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); + const [error, setError] = useState(null); const theme = useTheme(); useEffect(() => { const delayDebounceFn = setTimeout(async () => { if (query) { setLoading(true); - const res = await searchUsers(query, ["user"]); + const res = await searchUsers(query, objectTypes); setOptions(res); setLoading(false); } @@ -60,20 +68,40 @@ export function PeopleSearch({ return ( x} fullWidth - getOptionLabel={(option) => option.displayName || option.email} + getOptionLabel={(option) => { + if (typeof option === "object") { + return option.displayName || option.email; + } else { + return option; + } + }} filterSelectedOptions value={selectedUsers} onInputChange={(event, value) => setQuery(value)} - onChange={(event, value) => onChange(event, value)} + onChange={(event, value) => { + const last = value[value.length - 1]; + if (typeof last === "string" && !isValidEmail(last)) { + setError(`"${last}" is not a valid email address`); + return; + } + setError(null); + const mapped = value.map((v: any) => + typeof v === "string" ? { email: v } : v + ); + onChange(event, mapped); + }} renderInput={(params) => ( { @@ -124,16 +152,26 @@ export function PeopleSearch({ ); }} renderValue={(value, getTagProps) => - value.map((option, index) => ( - - )) + value.map((option, index) => { + const isString = typeof option === "string"; + const label = isString ? option : option.displayName || option.email; + const chipColor = isString + ? theme.palette.grey[300] + : (option.color ?? theme.palette.grey[300]); + const textColor = theme.palette.getContrastText(chipColor); + + return ( + + ); + }) } /> ); diff --git a/src/components/Calendar/CalendarSearch.tsx b/src/components/Calendar/CalendarSearch.tsx index 9fe14f0..993e297 100644 --- a/src/components/Calendar/CalendarSearch.tsx +++ b/src/components/Calendar/CalendarSearch.tsx @@ -259,6 +259,7 @@ export default function CalendarSearch({ { setSelectedUsers(value); diff --git a/src/components/Calendar/TempCalendarsInput.tsx b/src/components/Calendar/TempCalendarsInput.tsx index 89682b2..4f481f2 100644 --- a/src/components/Calendar/TempCalendarsInput.tsx +++ b/src/components/Calendar/TempCalendarsInput.tsx @@ -105,6 +105,7 @@ export function TempCalendarsInput({ return (