added live search for ContactForm.tsx

This commit is contained in:
slawk0
2024-12-01 11:26:14 +01:00
parent 0e26a68f1c
commit 679abd1c55
4 changed files with 105 additions and 7 deletions

View File

@@ -2,6 +2,8 @@ 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;
};
@@ -12,7 +14,41 @@ type ContactFormProps = {
};
function ContactForm({ InitializeContact, setContactsList }: ContactFormProps) {
const { register, handleSubmit, reset } = useForm<Input>();
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);
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);
if (response.data.length < 1) {
setIsLoading(false);
setNotFound(true);
}
} 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 contact = data.contact.trim();
@@ -31,7 +67,6 @@ function ContactForm({ InitializeContact, setContactsList }: ContactFormProps) {
);
console.log('contact post response: ', response.data);
console.log('sdfjkljklsdfjklfdjklsdfjklsdf', response.data);
InitializeContact(response.data);
setContactsList((prevContacts) => {
@@ -42,6 +77,7 @@ function ContactForm({ InitializeContact, setContactsList }: ContactFormProps) {
});
reset({ contact: '' });
setSuggestions([]); // Clear suggestions after adding contact
} catch (error) {
console.error('Error adding contact:', error);
}
@@ -56,12 +92,36 @@ function ContactForm({ InitializeContact, setContactsList }: ContactFormProps) {
type="text"
placeholder="Enter contact"
{...register('contact', {
// valid username length (validated on signup)
minLength: 4,
maxLength: 20,
})}
/>
</form>
<div className="m-1">
{suggestions?.length > 0 ? (
<ul className="text-left p-1 bg-gray-800 shadow-md rounded-md w-full border">
{suggestions.map((suggestion) => (
<li
key={suggestion}
className="p-2 hover:bg-gray-100 cursor-pointer"
onClick={() => {
reset({ 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>
</>
);

View File

@@ -61,7 +61,7 @@ function Chat() {
function InitializeContact(newContact: ContactsProps) {
setMessages([]); // Clear messages from previous contact
localStorage.setItem('contact', JSON.stringify(newContact)); // Set current contact in localstorage
setCurrentContact(newContact); // Set state for current user (used in contactProfile.tsx and for filtering messages)
setCurrentContact(newContact);
console.log('Initialized contact');
fetchMessages(newContact.conversation_id).catch((e) =>
@@ -76,10 +76,10 @@ function Chat() {
console.log('Current contact is now: ', newContact);
}
const fetchMessages = async (currentContact: number) => {
console.log('Fetching messages for: ', currentContact);
const fetchMessages = async (conversation_id: number) => {
console.log('Fetching messages for: ', conversation_id);
await getMessages(currentContact)
await getMessages(conversation_id)
.then((messages) => {
setCursor(() => {
return Math.min(

View File

@@ -670,6 +670,20 @@ async function getConversationsForUser(user_id) {
}
}
async function contactSuggestion(username) {
const query = `
SELECT username FROM accounts
WHERE LOWER(username) LIKE $1
LIMIT 5;
`;
try {
const result = await client.query(query, [`%${username.toLowerCase()}%`]);
return result.rows.map((row) => row.username);
} catch (e) {
console.error("Failed to fetch contact suggestions", e);
return [];
}
}
function getTime() {
return new Date();
}
@@ -692,4 +706,5 @@ module.exports = {
addMemberToGroup,
addMemberToGroupByUsername,
getConversationsForUser,
contactSuggestion,
};

View File

@@ -42,6 +42,7 @@ const {
createGroup,
addMemberToGroup,
addMemberToGroupByUsername,
contactSuggestion,
} = require("./db/db");
const { extname } = require("node:path");
@@ -271,6 +272,28 @@ app.get("/api/chat/contacts", authorizeUser, async (req, res) => {
return res.status(200).json(contacts);
});
app.get(
"/api/chat/contacts/suggestions/:contact",
authorizeUser,
async (req, res) => {
const contact = req.params.contact;
if (!contact) {
return res.status(401).json({
message: "contact not provided",
});
}
try {
const suggestions = await contactSuggestion(contact);
console.log(
`contacts suggestions for contact: ${contact}, suggestions: ${suggestions}`,
);
return res.status(200).json(suggestions);
} catch (e) {
res.status(500).json({ message: "Failed to get contact suggestions" });
}
},
);
app.get("/api/chat/messages/:contact", authorizeUser, async (req, res) => {
if (!req.params.contact) {
return res.status(400).json({ message: "Missing contact parameter" });