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

import React, { useState } from 'react';
import { FaSearch, FaUser, FaPhone, FaFileAlt, FaPlay, FaPause, FaUserCircle } from 'react-icons/fa';
import { Card } from './shared/Card';

interface UserHistory {
  cases: Array<{
    id: string;
    type: string;
    description: string;
    status: string;
    createdAt: Date;
    transcripts: string[];
  }>;
  questions: Array<{
    text: string;
    answer: string;
    timestamp: Date;
    audioUrl?: string;
  }>;
}

interface User {
  uid: string;
  name: string;
  phoneNumber: string;
  email: string;
}

export function NGODashboard() {
  const [phoneNumber, setPhoneNumber] = useState('');
  const [user, setUser] = useState<User | null>(null);
  const [history, setHistory] = useState<UserHistory | null>(null);
  const [loading, setLoading] = useState(false);
  const [currentAudio, setCurrentAudio] = useState<HTMLAudioElement | null>(null);
  const [isPlaying, setIsPlaying] = useState(false);

  const searchUser = async () => {
    setLoading(true);
    try {
      const response = await fetch(`/api/ngo/users/${phoneNumber}`, {
        headers: {
          Authorization: `Bearer ${localStorage.getItem('token')}`,
        },
      });
      const data = await response.json();

      if (data.success) {
        setUser(data.data.user);
        setHistory(data.data.history);
      }
    } catch (error) {
      console.error('Error searching user:', error);
    } finally {
      setLoading(false);
    }
  };

  const handleAudioPlay = (audioUrl: string) => {
    if (currentAudio) {
      currentAudio.pause();
      setIsPlaying(false);
    }

    if (!isPlaying || currentAudio?.src !== audioUrl) {
      const audio = new Audio(audioUrl);
      audio.addEventListener('ended', () => setIsPlaying(false));
      audio.play();
      setCurrentAudio(audio);
      setIsPlaying(true);
    }
  };

  const addFollowUp = async (caseId: string, question: string) => {
    try {
      const response = await fetch('/api/ngo/follow-up', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${localStorage.getItem('token')}`,
        },
        body: JSON.stringify({ caseId, question }),
      });

      if (response.ok) {
        searchUser();
      }
    } catch (error) {
      console.error('Error adding follow-up:', error);
    }
  };

  return (
    <div className="min-h-screen bg-gray-50 p-6">
      <div className="mx-auto max-w-7xl">
        <div className="mb-8">
          <h1 className="mb-6 text-3xl font-bold text-gray-900">
            NGO Remote Assist Portal
          </h1>
          <Card>
            <div className="flex items-center gap-4">
              <div className="flex-1">
                <div className="relative">
                  <input
                    type="tel"
                    value={phoneNumber}
                    onChange={(e) => setPhoneNumber(e.target.value)}
                    placeholder="Enter phone number..."
                    className="w-full rounded-lg border border-gray-300 bg-white px-4 py-3 pl-12 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-200"
                  />
                  <FaPhone className="absolute left-4 top-4 text-gray-400" />
                </div>
              </div>
              <button
                onClick={searchUser}
                disabled={loading}
                className="flex min-w-[120px] items-center justify-center gap-2 rounded-lg bg-blue-500 px-6 py-3 font-medium text-white transition-colors hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-200 disabled:opacity-50"
              >
                {loading ? (
                  <div className="h-5 w-5 animate-spin rounded-full border-b-2 border-white"></div>
                ) : (
                  <>
                    <FaSearch className="text-lg" />
                    Search
                  </>
                )}
              </button>
            </div>
          </Card>
        </div>

        {user && (
          <Card className="mb-8" gradient>
            <div className="flex items-center gap-6">
              <div className="flex h-16 w-16 items-center justify-center rounded-full bg-blue-100 text-blue-500">
                <FaUserCircle className="h-12 w-12" />
              </div>
              <div>
                <h2 className="text-2xl font-semibold text-gray-900">
                  {user.name}
                </h2>
                <div className="mt-1 flex items-center gap-4 text-gray-600">
                  <div className="flex items-center gap-2">
                    <FaPhone className="text-gray-400" />
                    {user.phoneNumber}
                  </div>
                  <div className="flex items-center gap-2">
                    <FaFileAlt className="text-gray-400" />
                    {history?.cases.length || 0} Cases
                  </div>
                </div>
              </div>
            </div>
          </Card>
        )}

        {history && (
          <div className="grid gap-6 lg:grid-cols-2">
            <Card title="Recent Questions">
              <div className="divide-y divide-gray-100">
                {history.questions.map((question, index) => (
                  <div key={index} className="py-4">
                    <p className="mb-2 font-medium text-gray-900">
                      {question.text}
                    </p>
                    <p className="mb-3 text-gray-600">{question.answer}</p>
                    {question.audioUrl && (
                      <button
                        onClick={() => handleAudioPlay(question.audioUrl!)}
                        className="flex items-center gap-2 rounded-lg bg-gray-100 px-4 py-2 text-sm text-gray-700 transition-colors hover:bg-gray-200"
                      >
                        {isPlaying && currentAudio?.src === question.audioUrl ? (
                          <FaPause className="text-gray-600" />
                        ) : (
                          <FaPlay className="text-gray-600" />
                        )}
                        {isPlaying && currentAudio?.src === question.audioUrl
                          ? 'Pause Audio'
                          : 'Play Audio'}
                      </button>
                    )}
                    <p className="mt-2 text-sm text-gray-500">
                      {new Date(question.timestamp).toLocaleString()}
                    </p>
                  </div>
                ))}
              </div>
            </Card>

            <Card title="Cases">
              <div className="divide-y divide-gray-100">
                {history.cases.map((case_) => (
                  <div key={case_.id} className="py-4">
                    <div className="mb-3 flex items-center justify-between">
                      <div>
                        <h3 className="font-semibold text-gray-900">
                          {case_.type}
                        </h3>
                        <p className="text-sm text-gray-500">
                          Status:{' '}
                          <span
                            className={`inline-block rounded-full px-2 py-1 text-xs font-medium ${
                              case_.status === 'resolved'
                                ? 'bg-green-100 text-green-800'
                                : case_.status === 'in_progress'
                                ? 'bg-yellow-100 text-yellow-800'
                                : 'bg-blue-100 text-blue-800'
                            }`}
                          >
                            {case_.status}
                          </span>
                        </p>
                      </div>
                      <button
                        onClick={() => {
                          const question = prompt('Enter follow-up question:');
                          if (question) {
                            addFollowUp(case_.id, question);
                          }
                        }}
                        className="rounded-lg bg-blue-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-200"
                      >
                        Add Follow-up
                      </button>
                    </div>
                    <p className="mb-4 text-gray-700">{case_.description}</p>
                    {case_.transcripts.length > 0 && (
                      <div className="mt-4">
                        <h4 className="mb-2 font-semibold text-gray-900">
                          Transcripts
                        </h4>
                        <div className="space-y-2">
                          {case_.transcripts.map((transcript, index) => (
                            <div
                              key={index}
                              className="rounded-lg bg-gray-50 p-3 text-sm text-gray-700"
                            >
                              {transcript}
                            </div>
                          ))}
                        </div>
                      </div>
                    )}
                  </div>
                ))}
              </div>
            </Card>
          </div>
        )}
      </div>
    </div>
  );
}