perplexity-hackathon-LawMitra / perplexity_hackathon / legal-chat-pwa / src / components / ChatMessage.tsx
ChatMessage.tsx
Raw
'use client';

import React, { useState } from 'react';
import { Message } from '@/types';
import { FaPlay, FaPause, FaUser, FaRobot, FaVolumeUp } from 'react-icons/fa';

interface ChatMessageProps {
  message: Message;
}

export function ChatMessage({ message }: ChatMessageProps) {
  const [isPlaying, setIsPlaying] = useState(false);
  const [audio, setAudio] = useState<HTMLAudioElement | null>(null);
  const [playbackProgress, setPlaybackProgress] = useState(0);

  const toggleAudio = () => {
    if (!message.audioUrl) return;

    if (!audio) {
      const newAudio = new Audio(message.audioUrl);
      newAudio.addEventListener('ended', () => {
        setIsPlaying(false);
        setPlaybackProgress(0);
      });
      newAudio.addEventListener('timeupdate', () => {
        setPlaybackProgress((newAudio.currentTime / newAudio.duration) * 100);
      });
      setAudio(newAudio);
      newAudio.play();
      setIsPlaying(true);
    } else {
      if (isPlaying) {
        audio.pause();
        setIsPlaying(false);
      } else {
        audio.play();
        setIsPlaying(true);
      }
    }
  };

  return (
    <div
      className={`group flex gap-3 ${
        message.type === 'user' ? 'flex-row-reverse' : 'flex-row'
      } items-start`}
    >
      <div
        className={`flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full ${
          message.type === 'user'
            ? 'bg-gradient-to-br from-blue-500 to-blue-600'
            : 'bg-gradient-to-br from-gray-600 to-gray-700'
        } shadow-lg`}
      >
        {message.type === 'user' ? (
          <FaUser className="text-white" />
        ) : (
          <FaRobot className="text-white" />
        )}
      </div>
      <div
        className={`flex max-w-[80%] flex-col ${
          message.type === 'user' ? 'items-end' : 'items-start'
        }`}
      >
        <div
          className={`relative rounded-2xl px-4 py-3 shadow-sm transition-all group-hover:shadow-md ${
            message.type === 'user'
              ? 'bg-gradient-to-br from-blue-500 to-blue-600 text-white'
              : 'bg-white'
          }`}
        >
          <p className={`text-sm ${message.type === 'user' ? '' : 'text-gray-800'}`}>
            {message.text}
          </p>
          {message.audioUrl && (
            <div className="mt-2 flex items-center gap-2">
              <button
                onClick={toggleAudio}
                className={`flex items-center gap-2 rounded-full p-1.5 text-xs transition-colors ${
                  message.type === 'user'
                    ? 'bg-blue-400/30 text-white hover:bg-blue-400/40'
                    : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
                }`}
              >
                {isPlaying ? (
                  <FaPause className="h-3 w-3" />
                ) : (
                  <FaPlay className="h-3 w-3" />
                )}
                <FaVolumeUp className="h-3 w-3" />
              </button>
              {isPlaying && (
                <div className="flex-1">
                  <div className="h-1 overflow-hidden rounded-full bg-gray-200">
                    <div
                      className={`h-full rounded-full transition-all ${
                        message.type === 'user' ? 'bg-blue-300' : 'bg-blue-500'
                      }`}
                      style={{ width: `${playbackProgress}%` }}
                    />
                  </div>
                </div>
              )}
            </div>
          )}
        </div>
        <span
          className={`mt-1 text-xs ${
            message.type === 'user' ? 'text-gray-500' : 'text-gray-400'
          }`}
        >
          {new Date(message.timestamp).toLocaleTimeString([], {
            hour: '2-digit',
            minute: '2-digit',
          })}
        </span>
      </div>
    </div>
  );
}