Files
n3wt-school/Front-End/src/components/RecipientInput.js
2025-05-12 14:03:47 +02:00

153 lines
5.0 KiB
JavaScript

import React, { useState } from 'react';
import { getGravatarUrl } from '@/utils/gravatar'; // Assurez-vous que cette fonction est définie pour générer les URLs Gravatar
import { getRightStr } from '@/utils/rights'; // Fonction existante pour récupérer le nom des rôles
import logger from '@/utils/logger';
export default function RecipientInput({
label,
recipients,
setRecipients,
searchRecipients, // Fonction pour effectuer la recherche
establishmentId, // ID de l'établissement
required = false, // Ajout de la prop required avec valeur par défaut
}) {
const [inputValue, setInputValue] = useState('');
const [suggestions, setSuggestions] = useState([]);
const [selectedIndex, setSelectedIndex] = useState(-1);
const handleInputChange = async (e) => {
const value = e.target.value;
setInputValue(value);
if (value.trim() !== '') {
try {
const results = await searchRecipients(establishmentId, value);
setSuggestions(results);
} catch (error) {
logger.error('Erreur lors de la recherche des destinataires:', error);
setSuggestions([]);
}
} else {
setSuggestions([]);
}
};
const handleKeyDown = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
if (selectedIndex >= 0 && selectedIndex < suggestions.length) {
handleSuggestionClick(suggestions[selectedIndex]);
} else {
const trimmedValue = inputValue.trim();
if (trimmedValue && !recipients.includes(trimmedValue)) {
setRecipients([...recipients, trimmedValue]);
setInputValue('');
setSuggestions([]);
}
}
} else if (e.key === 'ArrowDown') {
e.preventDefault();
setSelectedIndex((prevIndex) =>
prevIndex < suggestions.length - 1 ? prevIndex + 1 : 0
);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
setSelectedIndex((prevIndex) =>
prevIndex > 0 ? prevIndex - 1 : suggestions.length - 1
);
}
};
const handleSuggestionClick = (suggestion) => {
if (!recipients.includes(suggestion.email)) {
setRecipients([...recipients, suggestion.email]);
}
setInputValue('');
setSuggestions([]);
};
const handleRemoveRecipient = (email) => {
setRecipients(recipients.filter((recipient) => recipient !== email));
};
return (
<div className="mb-4">
<label className="block text-sm font-medium text-gray-700">
{label}
{required && <span className="text-red-500 ml-1">*</span>}
</label>
<div
className={`
mt-1 flex flex-wrap items-center gap-2 border rounded-md
border-gray-200 hover:border-gray-400 focus-within:border-gray-500
transition-colors
`}
>
{recipients.map((email, index) => (
<div
key={index}
className="flex items-center bg-gray-100 text-gray-700 px-2 py-1 rounded-full"
>
<img
src={getGravatarUrl(email)}
alt={email}
className="w-6 h-6 rounded-full mr-2"
/>
<span className="mr-2">{email}</span>
<button
type="button"
onClick={() => handleRemoveRecipient(email)}
className="text-gray-500 hover:text-gray-700"
>
&times;
</button>
</div>
))}
<input
type="text"
value={inputValue}
onChange={handleInputChange}
onKeyDown={handleKeyDown}
placeholder="Rechercher des destinataires"
className="flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none rounded-md"
required={required}
/>
</div>
{suggestions.length > 0 && (
<ul className="border rounded mt-2 bg-white shadow">
{suggestions.map((suggestion, index) => (
<li
key={suggestion.id}
className={`p-2 cursor-pointer ${
index === selectedIndex ? 'bg-gray-200' : ''
}`}
onClick={() => handleSuggestionClick(suggestion)}
>
<div className="flex items-center gap-2">
<img
src={getGravatarUrl(suggestion.email)}
alt={suggestion.email}
className="w-8 h-8 rounded-full"
/>
<div>
<p className="font-medium">
{suggestion.first_name && suggestion.last_name
? `${suggestion.first_name} ${suggestion.last_name}`
: suggestion.email}
</p>
<p className="text-sm text-gray-500">{suggestion.email}</p>
<p className="text-xs text-gray-400">
{suggestion.roles
.map((role) => getRightStr(role.role_type) || 'Inconnu')
.join(', ')}
</p>
</div>
</div>
</li>
))}
</ul>
)}
</div>
);
}