Files
relay/client/src/components/chat/ContactForm.tsx

171 lines
5.2 KiB
TypeScript

import { useForm, SubmitHandler } from 'react-hook-form';
import { ContactsProps } from '../../pages/Chat.tsx';
import { axiosClient } from '../../App.tsx';
import { AxiosResponse } from 'axios';
import { useEffect, useState } from 'react';
import LoadingWheel from './LoadingWheel.tsx';
type Input = {
contact: string;
};
type ContactFormProps = {
InitializeContact: (contact: ContactsProps) => void;
setContactsList: React.Dispatch<React.SetStateAction<ContactsProps[]>>;
};
function ContactForm({ InitializeContact, setContactsList }: ContactFormProps) {
const { register, handleSubmit, reset, watch } = useForm<Input>();
const contactInput = watch('contact');
const [suggestions, setSuggestions] = useState<string[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [notFound, setNotFound] = useState<boolean>(false);
const [selectedIndex, setSelectedIndex] = useState<number>(0);
useEffect(() => {
const fetchSuggestions = async () => {
if (contactInput?.length >= 3) {
try {
setIsLoading(true);
const response: AxiosResponse<string[]> = await axiosClient.get(
`/api/chat/contacts/suggestions/${contactInput}`,
);
setSuggestions(response.data);
setSelectedIndex(0); // Reset selection to first item when suggestions update
if (response.data.length < 1) {
setIsLoading(false);
setNotFound(true);
} else {
setIsLoading(false);
setNotFound(false);
}
} catch (error) {
setIsLoading(false);
console.error('Error fetching suggestions:', error);
}
} else {
setNotFound(false);
setIsLoading(false);
setSuggestions([]);
}
};
const delay = setTimeout(() => {
fetchSuggestions();
}, 300);
return () => clearTimeout(delay);
}, [contactInput]);
const submitContact: SubmitHandler<Input> = async (data) => {
const contactToSubmit =
suggestions.length > 0 ? suggestions[selectedIndex] : data.contact.trim();
try {
setContactsList((prevContacts) => {
if (prevContacts.some((c) => c.username === contactToSubmit)) {
return prevContacts;
}
return prevContacts;
});
console.log('Submit contact: ', contactToSubmit);
const response: AxiosResponse<ContactsProps> = await axiosClient.post(
`/api/chat/contact/${contactToSubmit}`,
);
console.log('contact post response: ', response.data);
InitializeContact(response.data);
setContactsList((prevContacts) => {
if (!prevContacts.some((c) => c.username === contactToSubmit)) {
return [...prevContacts, response.data];
}
return prevContacts;
});
reset({ contact: '' });
setSuggestions([]);
} catch (error) {
console.error('Error adding contact:', error);
}
};
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (suggestions.length > 0) {
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
setSelectedIndex((prev) => (prev + 1) % suggestions.length);
break;
case 'ArrowUp':
e.preventDefault();
setSelectedIndex(
(prev) => (prev - 1 + suggestions.length) % suggestions.length,
);
break;
case 'Enter':
if (suggestions.length > 0) {
e.preventDefault();
reset({ contact: suggestions[selectedIndex] });
handleSubmit(submitContact)();
}
break;
}
}
};
return (
<>
<div className="text-center">
<form onSubmit={handleSubmit(submitContact)}>
<input
className="text-black bg-green-50 pl-2 shadow-lg rounded-md h-8 mb-2 mt-2"
type="text"
placeholder="Search for user"
onKeyDown={handleKeyDown}
{...register('contact', {
minLength: 4,
maxLength: 20,
})}
/>
</form>
<div className="m-1">
{suggestions?.length > 0 ? (
<ul className="text-left p-2 bg-gray-900 shadow-md rounded-md w-full border">
{suggestions.map((suggestion, index) => (
<li
key={suggestion}
className={`p-1 cursor-pointer rounded-md mt-1 mb-1 ${
index === selectedIndex
? 'bg-gray-500'
: 'hover:bg-gray-500'
}`}
onClick={() => {
reset({ contact: suggestion });
handleSubmit(() =>
submitContact({ contact: suggestion }),
)();
setSuggestions([]);
}}
>
{suggestion}
</li>
))}
</ul>
) : isLoading ? (
<LoadingWheel />
) : null}
{notFound ? (
<p className="p-1 bg-gray-800 shadow-md rounded-md w-full border text-gray-400">
user not found
</p>
) : null}
</div>
</div>
</>
);
}
export default ContactForm;