report-list.tsx (13959B)
1 "use client"; 2 3 import { Report } from "@/app/dashboard/mockData"; 4 import { AlertTriangle, Badge, Ban, CheckCircle, Filter, MessageSquare, UserPlus } from "lucide-react"; 5 import { useState } from "react"; 6 import { Button } from "../ui/button"; 7 import { BlurredText } from "../blurred-text"; 8 import { BlurredImage } from "../blurred-image"; 9 import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "../ui/dialog"; 10 11 interface ReportListProps { 12 reports: Report[] 13 filter: "all" | "message" | "invite" | "high" 14 } 15 16 export default function ReportList({ reports, filter }: ReportListProps) { 17 const [selectedReport, setSelectedReport] = useState<string | null>(null) 18 19 const filteredReports = 20 filter === "all" 21 ? reports 22 : filter === "high" 23 ? reports.filter((r) => r.priority === "high") 24 : reports.filter((r) => r.type === filter) 25 return ( 26 <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> 27 <div className="space-y-4"> 28 <h3 className="text-sm font-medium text-gray-400">Report List</h3> 29 {filteredReports.length > 0 ? ( 30 filteredReports.map((report) => ( 31 <div 32 key={report.id} 33 className={`p-3 rounded-md border cursor-pointer transition-colors ${selectedReport === report.id 34 ? "bg-gray-800 border-purple-600" 35 : "bg-gray-900 border-gray-800 hover:border-gray-700" 36 }`} 37 onClick={() => setSelectedReport(report.id)} 38 > 39 <div className="flex items-center justify-between mb-2"> 40 <div className="flex items-center gap-2"> 41 {report.type === "message" ? ( 42 <MessageSquare className="h-4 w-4 text-blue-400" /> 43 ) : ( 44 <UserPlus className="h-4 w-4 text-green-400" /> 45 )} 46 <span className="text-sm font-medium"> 47 {report.type === "message" ? "Message Report" : "Invite Report"} 48 </span> 49 </div> 50 <Badge 51 className={ 52 report.priority === "high" 53 ? "text-red-300 hover:bg-red-900/70" 54 : "text-yellow-300 hover:bg-yellow-900/70" 55 } 56 > 57 {report.priority} 58 </Badge> 59 </div> 60 <p className="text-xs text-gray-400 mb-1">{report.room}</p> 61 <p className="text-xs text-gray-400 mb-1"> 62 {report.type === "message" 63 ? `From: ${report.subject.sender}` 64 : `From: ${report.subject.sender} To: ${report.subject.target}`} 65 </p> 66 <p className="text-xs text-gray-500">{new Date(report.timestamp).toLocaleString()}</p> 67 </div> 68 )) 69 ) : ( 70 <div className="flex flex-col items-center justify-center p-8 text-center"> 71 <CheckCircle className="h-8 w-8 text-gray-500 mb-2" /> 72 <p className="text-gray-400">No active reports</p> 73 </div> 74 )} 75 </div> 76 77 <div className="space-y-4"> 78 <h3 className="text-sm font-medium text-gray-400">Report Details</h3> 79 {selectedReport ? ( 80 (() => { 81 const report = reports.find((r) => r.id === selectedReport) 82 if (!report) return <p>Select a report to view details</p> 83 84 return ( 85 <div className="space-y-4"> 86 <div className="p-4 rounded-md bg-gray-900 border border-gray-800"> 87 <div className="flex items-center justify-between mb-3"> 88 <h4 className="font-medium">Report Information</h4> 89 <Badge className="bg-purple-900/50 text-purple-300">{report.status}</Badge> 90 </div> 91 92 <div className="space-y-2 text-sm"> 93 <div className="flex justify-between"> 94 <span className="text-gray-400">Reported by:</span> 95 <span>{report.reporter}</span> 96 </div> 97 <div className="flex justify-between"> 98 <span className="text-gray-400">Room:</span> 99 <span>{report.room}</span> 100 </div> 101 <div className="flex justify-between"> 102 <span className="text-gray-400">Reason:</span> 103 <span>{report.reason}</span> 104 </div> 105 <div className="flex justify-between"> 106 <span className="text-gray-400">Time:</span> 107 <span>{new Date(report.timestamp).toLocaleString()}</span> 108 </div> 109 </div> 110 </div> 111 112 <div className="p-4 rounded-md bg-gray-900 border border-gray-800"> 113 <h4 className="font-medium mb-3"> 114 {report.type === "message" ? "Message Content" : "Invite Details"} 115 </h4> 116 117 {report.type === "message" && ( 118 <div className="space-y-3"> 119 <div className="flex justify-between text-sm"> 120 <span className="text-gray-400">Sender:</span> 121 <span>{report.subject.sender}</span> 122 </div> 123 <div className="flex justify-between text-sm"> 124 <span className="text-gray-400">Message ID:</span> 125 <span className="font-mono text-xs">{report.subject.id}</span> 126 </div> 127 <div className="flex justify-between text-sm"> 128 <span className="text-gray-400">Time:</span> 129 <span>{new Date(report.subject.timestamp).toLocaleString()}</span> 130 </div> 131 132 <div className="mt-4"> 133 <div className="flex items-center justify-between mb-2"> 134 <span className="text-sm text-gray-400">Content:</span> 135 {report.subject.content?.msgtype === "m.text" && ( 136 <Button variant="ghost" size="sm" className="h-6 px-2 text-gray-400"> 137 <Filter className="h-3 w-3 mr-1" /> 138 Filter 139 </Button> 140 )} 141 </div> 142 143 {report.subject.content?.msgtype === "m.text" ? ( 144 <BlurredText text={report.subject.content?.body} /> 145 ) : report.subject.content?.msgtype === "m.image" ? ( 146 <div className="mt-2"> 147 <BlurredImage 148 src="/placeholder.svg?height=300&width=400" 149 alt={report.subject.content?.body} 150 width={400} 151 height={300} 152 /> 153 <p className="text-xs text-gray-500 mt-1">Image: {report.subject.content.body}</p> 154 </div> 155 ) : ( 156 <p className="text-sm">Unsupported content type</p> 157 )} 158 </div> 159 </div> 160 )} 161 162 {report.type === "invite" && ( 163 <div className="space-y-3"> 164 <div className="flex justify-between text-sm"> 165 <span className="text-gray-400">Sender:</span> 166 <span>{report.subject.sender}</span> 167 </div> 168 <div className="flex justify-between text-sm"> 169 <span className="text-gray-400">Target:</span> 170 <span>{report.subject.target}</span> 171 </div> 172 <div className="flex justify-between text-sm"> 173 <span className="text-gray-400">Time:</span> 174 <span>{new Date(report.subject.timestamp).toLocaleString()}</span> 175 </div> 176 </div> 177 )} 178 </div> 179 180 <div className="flex gap-2 mt-4"> 181 <Button className="bg-green-600 text-white hover:bg-green-700"> 182 <CheckCircle className="mr-2 h-4 w-4" /> 183 Resolve 184 </Button> 185 <Dialog> 186 <DialogTrigger asChild> 187 <Button 188 variant="outline" 189 className="border-red-500 text-red-400 hover:bg-red-950 hover:text-red-300" 190 > 191 <Ban className="mr-2 h-4 w-4" /> 192 Ban User 193 </Button> 194 </DialogTrigger> 195 <DialogContent className="bg-gray-950 border-gray-800"> 196 <DialogHeader> 197 <DialogTitle>Ban User</DialogTitle> 198 <DialogDescription className="text-gray-400"> 199 Ban {report.subject.sender} from your Matrix rooms 200 </DialogDescription> 201 </DialogHeader> 202 {/* Ban dialog content */} 203 </DialogContent> 204 </Dialog> 205 {report.type === "message" && ( 206 <Button 207 variant="outline" 208 className="border-gray-700 text-gray-400 hover:bg-gray-900 hover:text-gray-300" 209 > 210 <MessageSquare className="mr-2 h-4 w-4" /> 211 Delete Message 212 </Button> 213 )} 214 </div> 215 </div> 216 ) 217 })() 218 ) : ( 219 <div className="flex flex-col items-center justify-center p-8 text-center"> 220 <AlertTriangle className="h-8 w-8 text-gray-500 mb-2" /> 221 <p className="text-gray-400">Select a report to view details</p> 222 </div> 223 )} 224 </div> 225 </div> 226 ) 227 }