added option to delete message
This commit is contained in:
@@ -26,7 +26,7 @@ function AddGroupMember({ contact }: AddGroupMemberProps) {
|
||||
const onSubmit: SubmitHandler<Inputs> = async (data) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const response = await axiosClient.post(`/api/chat/groups/add/`, {
|
||||
const response = await axiosClient.post(`/api/chat/groups/addMember/`, {
|
||||
group_id: contact?.conversation_id,
|
||||
username: data.username,
|
||||
});
|
||||
|
||||
@@ -35,6 +35,9 @@ function ContactForm({ InitializeContact, setContactsList }: ContactFormProps) {
|
||||
if (response.data.length < 1) {
|
||||
setIsLoading(false);
|
||||
setNotFound(true);
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
setNotFound(false);
|
||||
}
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
@@ -128,11 +131,11 @@ function ContactForm({ InitializeContact, setContactsList }: ContactFormProps) {
|
||||
</form>
|
||||
<div className="m-1">
|
||||
{suggestions?.length > 0 ? (
|
||||
<ul className="text-left p-1 bg-gray-900 shadow-md rounded-md w-full border">
|
||||
<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-2 cursor-pointer ${
|
||||
className={`p-1 cursor-pointer rounded-md mt-1 mb-1 ${
|
||||
index === selectedIndex
|
||||
? 'bg-gray-500'
|
||||
: 'hover:bg-gray-500'
|
||||
|
||||
@@ -76,6 +76,10 @@ function ContactsList({
|
||||
}}
|
||||
key={contact.conversation_id}
|
||||
>
|
||||
{/*{contact.type == 'group' ? (*/}
|
||||
{/* <img className="w-6 invert m-1" src={GroupIco} alt="group icon" />*/}
|
||||
{/*) : null}*/}
|
||||
|
||||
<span className="flex-shrink-0">
|
||||
{/*user_id: {contact.user_id}, contact id: {contact.id}, group_id: {contact.group_id} username: */}
|
||||
{contact.username}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { File } from 'lucide-react';
|
||||
import { Paperclip } from 'lucide-react';
|
||||
const FileBox = ({ url }: { url: string }) => {
|
||||
const fileNameWithSuffix = url.split('/').pop();
|
||||
const fullFileName = fileNameWithSuffix?.replace(/-\d+$/, '');
|
||||
@@ -7,7 +7,7 @@ const FileBox = ({ url }: { url: string }) => {
|
||||
return (
|
||||
<div className="flex items-center bg-gray-800 border border-gray-700 rounded-lg p-3 max-w-xs shadow-sm">
|
||||
<div className="flex items-center space-x-3">
|
||||
<File className="text-green-100 w-6 h-6" />
|
||||
<Paperclip className="text-white w-6 h-6" />
|
||||
<div className="flex-1">
|
||||
<a
|
||||
href={url}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { customAlphabet } from 'nanoid';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import { ChatMessages, ContactsProps } from '../../pages/Chat.tsx';
|
||||
import { axiosClient } from '../../App.tsx';
|
||||
import { File, Paperclip } from 'lucide-react';
|
||||
|
||||
const nanoid = customAlphabet('1234567890', 5);
|
||||
|
||||
@@ -168,7 +169,7 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files && e.target.files.length > 0) {
|
||||
setFile(e.target.files[0]);
|
||||
setValue('attachment', e.target.files); // Update form state with file
|
||||
setValue('attachment', e.target.files);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -216,14 +217,22 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-2">
|
||||
<label
|
||||
htmlFor="attachment"
|
||||
className="flex items-center justify-center hover:cursor-pointer p-1 rounded-full hover:bg-gray-800"
|
||||
>
|
||||
<Paperclip size={24} />
|
||||
</label>
|
||||
<input
|
||||
name="attachment"
|
||||
id="attachment"
|
||||
type="file"
|
||||
accept="*/*"
|
||||
onChange={handleFileChange}
|
||||
disabled={isUploading}
|
||||
ref={fileInputRef}
|
||||
className="hidden"
|
||||
/>
|
||||
{isUploading && (
|
||||
<span className="text-gray-500 text-sm">Uploading...</span>
|
||||
|
||||
@@ -6,6 +6,8 @@ import LoadingWheel from './LoadingWheel.tsx';
|
||||
import { ChatMessages } from '../../pages/Chat.tsx';
|
||||
import FileBox from './FIleBox.tsx';
|
||||
import { ContactsProps } from '../../pages/Chat.tsx';
|
||||
import { Trash2 } from 'lucide-react';
|
||||
import { axiosClient } from '../../App.tsx';
|
||||
|
||||
type MessagesAreaProps = {
|
||||
messages: ChatMessages[];
|
||||
@@ -27,6 +29,7 @@ function MessagesArea({
|
||||
messageHandler,
|
||||
fetchPreviousMessages,
|
||||
errorMessage,
|
||||
setMessages,
|
||||
}: MessagesAreaProps) {
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -50,6 +53,15 @@ function MessagesArea({
|
||||
}
|
||||
};
|
||||
|
||||
const deleteMessage = async (message_id: number) => {
|
||||
const response = await axiosClient.delete(
|
||||
`/api/chat/messages/${message_id}`,
|
||||
);
|
||||
console.log('Delete message response: ', response.data);
|
||||
setMessages((prevMessages) =>
|
||||
prevMessages.filter((message) => message.message_id !== message_id),
|
||||
);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!socket) return;
|
||||
|
||||
@@ -129,27 +141,35 @@ function MessagesArea({
|
||||
|
||||
const messageList = messages.map((msg: ChatMessages) => (
|
||||
<li
|
||||
className={`whitespace-pre-wrap ml-2 rounded p-1 ${
|
||||
msg.pending
|
||||
? 'text-gray-400' // Gray style for pending messages
|
||||
: 'hover:bg-gray-900'
|
||||
className={`whitespace-pre-wrap ml-2 rounded p-1 group ${
|
||||
msg.pending ? 'text-gray-400' : 'hover:bg-gray-900'
|
||||
}`}
|
||||
key={msg.message_id || msg.tempId}
|
||||
>
|
||||
{msg.message_id || msg.tempId} {msg.sender}: {msg.message}
|
||||
{msg.attachment_url ? (
|
||||
<div className="mt-2">
|
||||
{msg.attachment_url.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/i) ? (
|
||||
<img
|
||||
src={msg.attachment_url}
|
||||
alt="attachment"
|
||||
className="max-w-full max-h-64 object-contain rounded"
|
||||
/>
|
||||
) : (
|
||||
<FileBox url={msg.attachment_url} />
|
||||
)}
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
{msg.sender}: {msg.message}
|
||||
{msg.attachment_url ? (
|
||||
<div className="mt-2">
|
||||
{msg.attachment_url.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/i) ? (
|
||||
<img
|
||||
src={msg.attachment_url}
|
||||
alt="attachment"
|
||||
className="max-w-full max-h-64 object-contain rounded"
|
||||
/>
|
||||
) : (
|
||||
<FileBox url={msg.attachment_url} />
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
<Trash2
|
||||
className="opacity-0 group-hover:opacity-100 h-5 w-5 ml-2 flex-shrink-0 cursor-pointer text-gray-400 hover:text-red-500"
|
||||
onClick={() => {
|
||||
deleteMessage(msg.message_id);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
));
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ function Chat() {
|
||||
<div className="flex-shrink-0">
|
||||
<ContactProfile contact={currentContact} />
|
||||
</div>
|
||||
<hr className="flex-shrink-0" />
|
||||
<hr />
|
||||
<div className="flex-grow overflow-x-hidden overflow-y-auto m-2">
|
||||
<MessagesArea
|
||||
messages={messages}
|
||||
|
||||
@@ -684,6 +684,43 @@ async function contactSuggestion(username) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteMessage(user_id, message_id) {
|
||||
const checkMessageOwnershipQuery = `
|
||||
SELECT user_id FROM Messages WHERE message_id = $1;
|
||||
`;
|
||||
|
||||
const deleteMessageQuery = `
|
||||
DELETE FROM Messages WHERE message_id = $1;
|
||||
`;
|
||||
|
||||
try {
|
||||
const checkResult = await client.query(checkMessageOwnershipQuery, [
|
||||
message_id,
|
||||
]);
|
||||
if (checkResult.rows.length === 0) {
|
||||
return { message: "Message not found." };
|
||||
}
|
||||
|
||||
const messageOwnerId = checkResult.rows[0].user_id;
|
||||
if (user_id !== messageOwnerId) {
|
||||
console.error("User is not authorized to delete this message");
|
||||
return { message: "It's not your message bro" };
|
||||
}
|
||||
const deleteResult = await client.query(deleteMessageQuery, [message_id]);
|
||||
if (deleteResult.rowCount > 0) {
|
||||
console.log("Message deleted successfully");
|
||||
return { message: "Message deleted successfully" };
|
||||
} else {
|
||||
console.log("Failed to delete message");
|
||||
return { message: "Failed to delete message." };
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to delete message ", e);
|
||||
return { message: "Failed to delete message" };
|
||||
}
|
||||
}
|
||||
|
||||
function getTime() {
|
||||
return new Date();
|
||||
}
|
||||
@@ -707,4 +744,5 @@ module.exports = {
|
||||
addMemberToGroupByUsername,
|
||||
getConversationsForUser,
|
||||
contactSuggestion,
|
||||
deleteMessage,
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@ const {
|
||||
addMemberToGroup,
|
||||
addMemberToGroupByUsername,
|
||||
contactSuggestion,
|
||||
deleteMessage,
|
||||
} = require("./db/db");
|
||||
const { extname } = require("node:path");
|
||||
|
||||
@@ -348,7 +349,7 @@ app.post("/api/chat/groups/create", authorizeUser, async (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
app.post("/api/chat/groups/add", async (req, res) => {
|
||||
app.post("/api/chat/groups/addMember", async (req, res) => {
|
||||
const username = req.body.username;
|
||||
const group_id = req.body.group_id;
|
||||
if (!username) {
|
||||
@@ -364,6 +365,25 @@ app.post("/api/chat/groups/add", async (req, res) => {
|
||||
res.status(500).json({ message: "Failed to add member" });
|
||||
});
|
||||
|
||||
app.delete(
|
||||
"/api/chat/messages/:message_id",
|
||||
authorizeUser,
|
||||
async (req, res) => {
|
||||
const message_id = req.params.message_id;
|
||||
console.log("delete message: ", req.user.user_id, message_id);
|
||||
if (!message_id) {
|
||||
return res.status(500).json({ message: "No message_id provided" });
|
||||
}
|
||||
|
||||
const result = await deleteMessage(req.user.user_id, message_id);
|
||||
if (result.message) {
|
||||
return res.status(200).json({ message: result.message });
|
||||
} else {
|
||||
return res.status(200).json({ message: "Successfully deleted message" });
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
initializeSocket(io);
|
||||
|
||||
server.listen(PORT, () => {
|
||||
|
||||
Reference in New Issue
Block a user