Files
ai-wpa/components/admin/ReportsManagement.tsx
2025-08-30 18:18:57 +05:30

285 lines
8.9 KiB
TypeScript

'use client'
import { useState } from 'react'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { Download, FileText, Users, CreditCard, Activity, BarChart3 } from 'lucide-react'
import { toast } from '@/hooks/use-toast'
const reportTypes = [
{
id: 'users',
name: 'Users Report',
description: 'Export all user data including registration info, roles, and verification status',
icon: Users,
},
{
id: 'transactions',
name: 'Transactions Report',
description: 'Export all transaction data including payments, refunds, and balance changes',
icon: CreditCard,
},
{
id: 'billing',
name: 'Billing Report',
description: 'Export billing records including service purchases and payment status',
icon: FileText,
},
{
id: 'developer-requests',
name: 'Developer Requests Report',
description: 'Export developer hire requests and their status',
icon: Activity,
},
{
id: 'summary',
name: 'Summary Report',
description: 'Comprehensive overview with key metrics and statistics',
icon: BarChart3,
},
]
export default function ReportsManagement() {
const [selectedReport, setSelectedReport] = useState('')
const [format, setFormat] = useState('json')
const [dateFrom, setDateFrom] = useState('')
const [dateTo, setDateTo] = useState('')
const [generating, setGenerating] = useState(false)
const handleGenerateReport = async () => {
if (!selectedReport) {
toast({
title: 'Error',
description: 'Please select a report type',
variant: 'destructive',
})
return
}
setGenerating(true)
try {
const token =
localStorage.getItem('token') ||
document.cookie
.split('; ')
.find((row) => row.startsWith('token='))
?.split('=')[1]
const params = new URLSearchParams({
type: selectedReport,
format,
...(dateFrom && { dateFrom }),
...(dateTo && { dateTo }),
})
const response = await fetch(`/api/admin/reports?${params}`, {
headers: {
Authorization: `Bearer ${token}`,
},
})
if (!response.ok) {
throw new Error('Failed to generate report')
}
if (format === 'csv') {
// Handle CSV download
const blob = await response.blob()
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `${selectedReport}_report_${new Date().toISOString().split('T')[0]}.csv`
document.body.appendChild(a)
a.click()
window.URL.revokeObjectURL(url)
document.body.removeChild(a)
} else {
// Handle JSON download
const data = await response.json()
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `${selectedReport}_report_${new Date().toISOString().split('T')[0]}.json`
document.body.appendChild(a)
a.click()
window.URL.revokeObjectURL(url)
document.body.removeChild(a)
}
toast({
title: 'Success',
description: 'Report generated and downloaded successfully',
})
} catch (error) {
console.error('Report generation error:', error)
toast({
title: 'Error',
description: 'Failed to generate report',
variant: 'destructive',
})
} finally {
setGenerating(false)
}
}
const handleQuickExport = async (reportType: string) => {
setSelectedReport(reportType)
setFormat('csv')
// Trigger immediate export
setTimeout(() => {
handleGenerateReport()
}, 100)
}
return (
<div className="space-y-6">
{/* Quick Export Cards */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{reportTypes.map((report) => (
<Card key={report.id} className="hover:shadow-lg transition-shadow cursor-pointer">
<CardContent className="p-4">
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="flex items-center mb-2">
<report.icon className="h-5 w-5 text-blue-600 mr-2" />
<h3 className="font-semibold">{report.name}</h3>
</div>
<p className="text-sm text-gray-600 mb-3">{report.description}</p>
<Button
size="sm"
variant="outline"
onClick={() => handleQuickExport(report.id)}
disabled={generating}
>
<Download className="h-4 w-4 mr-2" />
Quick Export CSV
</Button>
</div>
</div>
</CardContent>
</Card>
))}
</div>
{/* Custom Report Generator */}
<Card>
<CardHeader>
<CardTitle>Custom Report Generator</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<Label htmlFor="reportType">Report Type</Label>
<Select value={selectedReport} onValueChange={setSelectedReport}>
<SelectTrigger>
<SelectValue placeholder="Select report type" />
</SelectTrigger>
<SelectContent>
{reportTypes.map((report) => (
<SelectItem key={report.id} value={report.id}>
{report.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="format">Format</Label>
<Select value={format} onValueChange={setFormat}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="json">JSON</SelectItem>
<SelectItem value="csv">CSV</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<Label htmlFor="dateFrom">From Date</Label>
<Input
id="dateFrom"
type="date"
value={dateFrom}
onChange={(e) => setDateFrom(e.target.value)}
/>
</div>
<div>
<Label htmlFor="dateTo">To Date</Label>
<Input
id="dateTo"
type="date"
value={dateTo}
onChange={(e) => setDateTo(e.target.value)}
/>
</div>
</div>
<div className="flex justify-end">
<Button onClick={handleGenerateReport} disabled={generating || !selectedReport}>
<Download className="h-4 w-4 mr-2" />
{generating ? 'Generating...' : 'Generate Report'}
</Button>
</div>
</CardContent>
</Card>
{/* Report Guidelines */}
<Card>
<CardHeader>
<CardTitle>Report Guidelines</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<h4 className="font-semibold text-gray-900">Data Privacy</h4>
<p className="text-sm text-gray-600">
Exported reports contain sensitive user data. Ensure compliance with data protection
regulations and handle all exported data securely.
</p>
</div>
<div>
<h4 className="font-semibold text-gray-900">File Formats</h4>
<ul className="text-sm text-gray-600 space-y-1">
<li>
<strong>JSON:</strong> Complete data with full structure, suitable for technical
analysis
</li>
<li>
<strong>CSV:</strong> Simplified tabular format, suitable for spreadsheet
applications
</li>
</ul>
</div>
<div>
<h4 className="font-semibold text-gray-900">Date Filtering</h4>
<p className="text-sm text-gray-600">
Use date filters to limit report scope. Large date ranges may result in slower
generation times and larger file sizes.
</p>
</div>
</div>
</CardContent>
</Card>
</div>
)
}