diff --git a/next.config.js b/next.config.js
index 4b9db8b..79ef6a5 100644
--- a/next.config.js
+++ b/next.config.js
@@ -12,7 +12,7 @@ const { i18n } = require('./next-i18next.config');
const nextConfig = {
basePath: '/dashboard',
// assetPrefix: '/dashboard/',
- reactStrictMode: true,
+ reactStrictMode: false,
i18n,
publicRuntimeConfig: {
diff --git a/package.json b/package.json
index 87f05eb..7020654 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"version": "6.6.0",
"private": true,
"scripts": {
- "dev": "next dev -p 3000",
+ "dev": "next dev -p 3001",
"build": "next build",
"start": "next start -p 3000",
"lint": "next lint"
diff --git a/public/image/Frame-48098164.svg b/public/image/Frame-48098164.svg
new file mode 100644
index 0000000..2aa3ee1
--- /dev/null
+++ b/public/image/Frame-48098164.svg
@@ -0,0 +1,2055 @@
+
diff --git a/public/image/face-smile.svg b/public/image/face-smile.svg
new file mode 100644
index 0000000..14d1e75
--- /dev/null
+++ b/public/image/face-smile.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/image/icon-park-outline_link.svg b/public/image/icon-park-outline_link.svg
new file mode 100644
index 0000000..5daa41c
--- /dev/null
+++ b/public/image/icon-park-outline_link.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/image/link-simple.svg b/public/image/link-simple.svg
new file mode 100644
index 0000000..3b1feea
--- /dev/null
+++ b/public/image/link-simple.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/image/microphone-01.svg b/public/image/microphone-01.svg
new file mode 100644
index 0000000..acdb138
--- /dev/null
+++ b/public/image/microphone-01.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/image/send-01.svg b/public/image/send-01.svg
new file mode 100644
index 0000000..2848199
--- /dev/null
+++ b/public/image/send-01.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/chat/chat-input.tsx b/src/components/chat/chat-input.tsx
index 5062d42..a766dae 100644
--- a/src/components/chat/chat-input.tsx
+++ b/src/components/chat/chat-input.tsx
@@ -1,13 +1,13 @@
import { PiTrash } from "react-icons/pi";
import Image from "next/image";
-import SendIcon from "public/assets/images/send-01.svg";
-import MicIcon from "public/assets/images/microphone-01.svg";
-import LinkIcon from "public/assets/images/link-simple.svg";
-import SmileIcon from "public/assets/images/face-smile.svg";
+import SendIcon from "public/image/send-01.svg";
+import MicIcon from "public/image/microphone-01.svg";
+import LinkIcon from "public/image/link-simple.svg";
+import SmileIcon from "public/image/face-smile.svg";
import { MdClose } from "react-icons/md";
import { useEffect, useState, useRef } from "react";
import { useWebSocket } from "@/contexts/WebSocket.context";
-import FileInput from "../ui/file-input";
+import FileInput from "./file-input";
import dynamic from "next/dynamic";
import EmojiPicker from "emoji-picker-react";
import { BsFillReplyFill } from "react-icons/bs";
diff --git a/src/components/chat/file-input.tsx b/src/components/chat/file-input.tsx
new file mode 100644
index 0000000..d671614
--- /dev/null
+++ b/src/components/chat/file-input.tsx
@@ -0,0 +1,80 @@
+import { useWebSocket } from "@/contexts/WebSocket.context";
+import Image from "next/image";
+import FaPlus from "public/image/icon-park-outline_link.svg";
+import { useEffect, useState } from "react";
+import { toast } from "react-toastify"; // Import toast from react-toastify
+import "react-toastify/dist/ReactToastify.css"; // Import CSS for toast
+
+// Define the allowed image, video, and audio extensions
+const IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "bmp", "tiff", "webp", "svg"];
+const VIDEO_EXTENSIONS = ["mp4", "mkv", "webm", "avi", "mov", "flv", "wmv"];
+const AUDIO_EXTENSIONS = ["mp3", "wav", "ogg", "flac", "aac", "m4a"];
+
+const getFileType = (extension : string) => {
+ const ext = extension.toLowerCase();
+
+ // Check if it's an image
+ if (IMAGE_EXTENSIONS.includes(ext)) {
+ return "image";
+ }
+
+ // Check if it's a video
+ if (VIDEO_EXTENSIONS.includes(ext)) {
+ return "video";
+ }
+
+ // Check if it's an audio file
+ if (AUDIO_EXTENSIONS.includes(ext)) {
+ return "audio";
+ }
+
+ // Everything else is a generic file
+ return "file";
+};
+
+const FileInput = () => {
+ const {setLoadingMessage} = useWebSocket()
+ const { sendFile } = useWebSocket();
+ const [file, setFile] = useState(null); // To store the selected file
+
+ const MAX_FILE_SIZE = 300 * 1024 * 1024; // 300 MB in bytes
+
+ const handleFileChange = async (event : any) => {
+ const selectedFile = event.target.files[0];
+
+ if (selectedFile) {
+ // Check file size
+ if (selectedFile.size > MAX_FILE_SIZE) {
+ toast.error("File is too large. Please select a file smaller than 300 MB.");
+ return; // Prevent further processing if the file is too large
+ }
+ selectedFile.status = "loading"
+ setLoadingMessage((prev) => [...prev, selectedFile]);
+
+ }
+ };
+
+ // Send the file when it's available
+
+
+ return (
+
+ {/* Hidden file input */}
+
+ {/* Label triggers the file input */}
+
+
+ );
+};
+
+export default FileInput;
diff --git a/src/components/chat/file-message.tsx b/src/components/chat/file-message.tsx
index 93fd75f..7500e5c 100644
--- a/src/components/chat/file-message.tsx
+++ b/src/components/chat/file-message.tsx
@@ -19,6 +19,8 @@ const fileTypes = {
};
const FileMessage = ({ file }) => {
+ console.log( "file Message",file);
+
const { sendFile } = useWebSocket();
const [percentage, setPercentage] = useState(1);
const isLoading = file.status === "loading";
@@ -95,7 +97,9 @@ const FileMessage = ({ file }) => {
})
.then((res) => {
const fileType = getFileType(fileExtension);
- sendFile({ ...res.data, type: fileType });
+ console.log("file sent");
+
+ sendFile({ ...res, type: fileType });
})
.catch((err) => console.error(err));
}
diff --git a/src/components/chat/message.tsx b/src/components/chat/message.tsx
index 7980141..ed58bec 100644
--- a/src/components/chat/message.tsx
+++ b/src/components/chat/message.tsx
@@ -1,26 +1,26 @@
-import { useState, useEffect, useCallback, useRef } from "react";
-import { useRouter } from "next/router";
-import ContextMenu from "./contex-menu"; // Import the ContextMenu component
-import Image from "next/image";
-import Seen from "public/image/quill_checkmark-double.svg";
-import UnSeen from "public/image/State=Send.svg";
-import Pending from "public/image/clock-fast-forward.png";
-import { useWebSocket } from "@/contexts/WebSocket.context";
-import Button from "../ui/button";
-import { Routes as ROUTES } from "@/config/routes";
+import { useState, useEffect, useCallback, useRef } from 'react';
+import { useRouter } from 'next/router';
+import ContextMenu from './contex-menu'; // Import the ContextMenu component
+import Image from 'next/image';
+import Seen from 'public/image/quill_checkmark-double.svg';
+import UnSeen from 'public/image/State=Send.svg';
+import Pending from 'public/image/clock-fast-forward.png';
+import { useWebSocket } from '@/contexts/WebSocket.context';
+import Button from '../ui/button';
+import { Routes as ROUTES } from '@/config/routes';
-import { HttpClient as http } from "@/data/client/http-client";
-import FileMessage from "./file-message";
-import ImageMessage from "./image-message";
-import AudioMessage from "./audio-message";
+import { HttpClient as http } from '@/data/client/http-client';
+import FileMessage from './file-message';
+import ImageMessage from './image-message';
+import AudioMessage from './audio-message';
const Message = ({ msg }) => {
- const isFileMessage = msg.status || msg?.mime_type === "file" ? true : false;
+ const isFileMessage = msg.status || msg?.mime_type === 'file' ? true : false;
const isLoadingMessage = msg.status ? true : false;
- const isAudioMessage = msg?.mime_type === "audio" ? true : false;
+ const isAudioMessage = msg?.mime_type === 'audio' ? true : false;
const isImageMessage =
- msg?.mime_type === "image" || msg?.mime_type === "video" ? true : false;
- const isTextMessage = msg.mime_type === "text" ? true : false;
+ msg?.mime_type === 'image' || msg?.mime_type === 'video' ? true : false;
+ const isTextMessage = msg.mime_type === 'text' ? true : false;
if (isLoadingMessage) {
return ;
}
@@ -46,7 +46,7 @@ const Message = ({ msg }) => {
const date = new Date(timestamp);
let hours = date.getHours();
const minutes = date.getMinutes();
- const ampm = hours >= 12 ? "PM" : "AM";
+ const ampm = hours >= 12 ? 'PM' : 'AM';
hours %= 12;
hours = hours || 12; // Convert '0' to '12'
@@ -55,16 +55,15 @@ const Message = ({ msg }) => {
return `${hours}:${formattedMinutes} ${ampm}`;
}, []);
-
// Handlers for context menu actions
const handleCopy = useCallback(() => {
navigator.clipboard
- .writeText(typeof msg === "string" ? msg : msg.content)
+ .writeText(typeof msg === 'string' ? msg : msg.content)
.then(() => {
- console.log("Copied to clipboard");
+ console.log('Copied to clipboard');
})
.catch((err) => {
- console.error("Failed to copy: ", err);
+ console.error('Failed to copy: ', err);
});
setShowMenu(false);
}, [msg]);
@@ -85,7 +84,7 @@ const Message = ({ msg }) => {
e.preventDefault();
setShowMenu((prev) => !prev);
},
- [setShowMenu]
+ [setShowMenu],
);
// Close menu if clicked outside
@@ -100,43 +99,43 @@ const Message = ({ msg }) => {
setShowMenu(false);
}
},
- [menuRef, messageRef]
+ [menuRef, messageRef],
);
// Handle escape key to close menu
const handleKeyDown = useCallback(
(e) => {
- if (e.key === "Escape") {
+ if (e.key === 'Escape') {
setShowMenu(false);
}
},
- [setShowMenu]
+ [setShowMenu],
);
useEffect(() => {
if (showMenu) {
- document.addEventListener("mousedown", handleClickOutside);
- document.addEventListener("keydown", handleKeyDown);
+ document.addEventListener('mousedown', handleClickOutside);
+ document.addEventListener('keydown', handleKeyDown);
} else {
- document.removeEventListener("mousedown", handleClickOutside);
- document.removeEventListener("keydown", handleKeyDown);
+ document.removeEventListener('mousedown', handleClickOutside);
+ document.removeEventListener('keydown', handleKeyDown);
}
// Cleanup on unmount
return () => {
- document.removeEventListener("mousedown", handleClickOutside);
- document.removeEventListener("keydown", handleKeyDown);
+ document.removeEventListener('mousedown', handleClickOutside);
+ document.removeEventListener('keydown', handleKeyDown);
};
}, [showMenu, handleClickOutside, handleKeyDown]);
- const isStringMessage = typeof msg === "string";
+ const isStringMessage = typeof msg === 'string';
const messageContent = isStringMessage ? msg : msg.content;
const messageKey = isStringMessage ? msg : msg.id;
const messageTime = isStringMessage
? formatTime()
: formatTime(msg.created_at);
- const isUser = !isStringMessage && msg?.by_user?.account_type === "user";
+ const isUser = !isStringMessage && msg?.by_user?.account_type === 'merchant';
const isSeen = !isStringMessage && msg?.is_read;
const product =
!isStringMessage && Object.keys(msg?.product_reply).length
@@ -161,14 +160,14 @@ const Message = ({ msg }) => {
key={messageKey}
className={`rounded-lg border p-2 mb-2 max-w-[525px] flex flex-col whitespace-pre-line break-words relative ${
isUser
- ? "self-end bg-[#323232] text-white"
+ ? 'self-end bg-[#323232] text-white'
: isStringMessage
- ? "self-end bg-[#323232] text-white"
- : "self-start bg-white text-gray-800"
+ ? 'self-end bg-[#323232] text-white'
+ : 'self-start bg-white text-gray-800'
}`}
tabIndex={0}
onKeyDown={(e) => {
- if (e.key === "ContextMenu" || (e.shiftKey && e.key === "F10")) {
+ if (e.key === 'ContextMenu' || (e.shiftKey && e.key === 'F10')) {
e.preventDefault();
setShowMenu(true);
}
@@ -184,28 +183,30 @@ const Message = ({ msg }) => {
onDelete={handleDelete}
menuRef={menuRef}
isUser={isUser}
- className={isUser ? "-right-2" : ""}
+ className={isUser ? '-right-2' : ''}
/>
{/* Render file message */}
{product && (
-
+ {product?.get_first_image && (
-
+ )}
+
{