"use client"; import { sendMessageApi } from "@/utils/api"; import { useEffect, useState, useRef } from "react"; import { IoMdAttach, IoMdSend } from "react-icons/io"; import { FaMicrophone, FaRegStopCircle } from "react-icons/fa"; import { Loader2, X } from "lucide-react"; import { useReactMediaRecorder } from "react-media-recorder"; import { toast } from "sonner"; import { t } from "@/utils"; import CustomImage from "@/components/Common/CustomImage"; const SendMessage = ({ selectedChatDetails, setChatMessages }) => { const isAllowToChat = selectedChatDetails?.item?.status === "approved" || selectedChatDetails?.item?.status === "featured"; if (!isAllowToChat) { return (
{t("thisAd")} {selectedChatDetails?.item?.status}
); } const id = selectedChatDetails?.id; const [message, setMessage] = useState(""); const [selectedFile, setSelectedFile] = useState(null); const [previewUrl, setPreviewUrl] = useState(""); const [isSending, setIsSending] = useState(false); const fileInputRef = useRef(null); // Voice recording setup const { status, startRecording, stopRecording, mediaBlobUrl, error } = useReactMediaRecorder({ audio: true, blobPropertyBag: { type: "audio/mpeg" }, }); const isRecording = status === "recording"; const [recordingDuration, setRecordingDuration] = useState(0); // Format recording duration as mm:ss const formatDuration = (seconds) => { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return `${mins.toString().padStart(2, "0")}:${secs .toString() .padStart(2, "0")}`; }; // Timer for recording useEffect(() => { let timer; if (isRecording) { timer = setInterval(() => { setRecordingDuration((prev) => prev + 1); }, 1000); } else { setRecordingDuration(0); } return () => clearInterval(timer); }, [isRecording]); useEffect(() => { return () => { if (previewUrl) { URL.revokeObjectURL(previewUrl); } stopRecording(); }; }, []); // Handle recorded audio useEffect(() => { if (mediaBlobUrl && status === "stopped") { handleRecordedAudio(); } }, [mediaBlobUrl, status]); const handleRecordedAudio = async () => { try { const response = await fetch(mediaBlobUrl); const blob = await response.blob(); const audioFile = new File([blob], "recording.mp3", { type: "audio/mpeg", }); sendMessage(audioFile); } catch (err) { console.error("Error processing audio:", err); toast.error("Failed to process recording"); } }; const handleFileSelect = (e) => { const file = e.target.files[0]; if (!file) return; // Check if file is an image const allowedTypes = ["image/jpeg", "image/png", "image/jpg"]; if (!allowedTypes.includes(file.type)) { toast.error("Only image files (JPEG, PNG, JPG) are allowed"); return; } // Create preview URL for image const fileUrl = URL.createObjectURL(file); setPreviewUrl(fileUrl); setSelectedFile(file); }; const removeSelectedFile = () => { if (previewUrl) { URL.revokeObjectURL(previewUrl); } setSelectedFile(null); setPreviewUrl(""); // Reset file input value to allow selecting the same file again if (fileInputRef.current) { fileInputRef.current.value = ""; } }; const sendMessage = async (audioFile = null) => { if ((!message.trim() && !selectedFile && !audioFile) || isSending) return; const params = { item_offer_id: id, message: message ? message : "", file: selectedFile ? selectedFile : "", audio: audioFile ? audioFile : "", }; try { setIsSending(true); const response = await sendMessageApi.sendMessage(params); if (!response?.data?.error) { setChatMessages((prev) => [...prev, response.data.data]); setMessage(""); removeSelectedFile(); } else { toast.error(response?.data?.message || "Failed to send message"); } } catch (error) { console.error(error); toast.error("Error sending message"); } finally { setIsSending(false); } }; const handleVoiceButtonClick = () => { if (isRecording) { stopRecording(); } else { startRecording(); if (error) { console.log(error); switch (error) { case "permission_denied": toast.error(t("microphoneAccessDenied")); break; case "no_specified_media_found": toast.error(t("noMicrophoneFound")); break; default: toast.error(t("somethingWentWrong")); } } } }; return (
{/* File Preview */} {previewUrl && (
)} {/* Input Area */}
{!isRecording && ( <> )} {isRecording ? (
{t("recording")} {formatDuration(recordingDuration)}
) : (