'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>
);
}