chart-configs.ts (8474B)
1 import type { Data, Layout } from "plotly.js" 2 import { HeatmapDay } from "./heatmap" 3 4 // Helper function to generate heatmap data 5 export const generateHeatmapData = (intensity = 1, seed = 42): HeatmapDay[] => { 6 const today = new Date() 7 const data = [] 8 9 // Generate data for the past year (52 weeks) 10 for (let i = 0; i < 364; i++) { 11 const date = new Date(today) 12 date.setDate(today.getDate() - i) 13 14 // Use a simple algorithm to generate semi-random but consistent data 15 const dayOfYear = Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000) 16 const value = Math.floor(Math.sin(dayOfYear * 0.1 + seed) * Math.cos(date.getMonth() * 0.3 + seed) * 10 * intensity) 17 18 data.push({ 19 date: date.toISOString().split("T")[0] as string, 20 count: Math.max(0, value), 21 }) 22 } 23 24 // Sort by date (oldest first) 25 return data.reverse() 26 } 27 28 export interface RoomActivityData { 29 name: string 30 reports: number 31 bans: number 32 } 33 34 // Room Activity Chart Config 35 export const getRoomActivityConfig = (roomData: RoomActivityData[]): { 36 data: Data[], 37 layout: Partial<Layout> 38 } => { 39 return { 40 data: [ 41 { 42 y: roomData.map((item) => item.name), 43 x: roomData.map((item) => item.reports), 44 name: "Reports", 45 type: "bar", 46 orientation: "h", 47 marker: { 48 color: "#9333ea", 49 }, 50 }, 51 { 52 y: roomData.map((item) => item.name), 53 x: roomData.map((item) => item.bans), 54 name: "Bans", 55 type: "bar", 56 orientation: "h", 57 marker: { 58 color: "#dc2626", 59 }, 60 }, 61 ], 62 layout: { 63 paper_bgcolor: "rgba(0,0,0,0)", 64 plot_bgcolor: "rgba(0,0,0,0)", 65 font: { 66 color: "#9ca3af", 67 }, 68 margin: { 69 l: 10, // Increased left margin for room names 70 r: 10, 71 t: 10, 72 b: 10, 73 pad: 10, 74 }, 75 barmode: "stack", 76 legend: { 77 orientation: "h", 78 xanchor: "center", 79 x: 0.5, 80 y: -0.2, 81 }, 82 xaxis: { 83 gridcolor: "#1f2937", 84 zerolinecolor: "#1f2937", 85 automargin: true, 86 }, 87 yaxis: { 88 gridcolor: "#1f2937", 89 automargin: true, 90 }, 91 height: 280, 92 autosize: true, 93 }, 94 } 95 } 96 97 export interface ReportTypeData { 98 id: number; 99 label: string; 100 value: number; 101 color: string; 102 } 103 104 // Report Types Pie Chart Config 105 export const getReportTypesConfig = (reportData: ReportTypeData[]): { 106 data: Data[], 107 layout: Partial<Layout> 108 } => { 109 return { 110 data: [ 111 { 112 values: reportData.map((item) => item.value), 113 labels: reportData.map((item) => item.label), 114 type: "pie", 115 hole: 0.5, 116 marker: { 117 colors: reportData.map((item) => item.color), 118 }, 119 textinfo: "label+percent", 120 textposition: "outside", 121 insidetextorientation: "radial", 122 hoverinfo: "label+value+percent", 123 hoverlabel: { 124 bgcolor: "#374151", 125 bordercolor: "#374151", 126 font: { 127 size: 12, 128 family: "Inter, sans-serif", 129 color: "#ffffff" 130 }, 131 }, 132 // Add slice animation on hover 133 pull: Array(reportData.length).fill(0), 134 hovertemplate: "<b>%{label}</b><br>Count: %{value}<br>Percentage: %{percent}<extra></extra>", 135 }, 136 ], 137 layout: { 138 paper_bgcolor: "rgba(0,0,0,0)", 139 plot_bgcolor: "rgba(0,0,0,0)", 140 font: { 141 color: "#9ca3af", 142 }, 143 margin: { 144 l: 30, 145 r: 30, 146 t: 30, 147 b: 30, 148 pad: 10, 149 }, 150 showlegend: false, 151 height: 280, 152 autosize: true, 153 annotations: [ 154 { 155 font: { 156 size: 12, 157 color: "#9ca3af", 158 }, 159 showarrow: false, 160 text: "Report Types", 161 x: 0.5, 162 y: 0.5, 163 }, 164 ], 165 // Add hover animations 166 hovermode: "closest", 167 updatemenus: [ 168 { 169 type: "dropdown", 170 showactive: false, 171 visible: false, // Hidden menu that enables hover effects 172 }, 173 ], 174 }, 175 } 176 } 177 178 export interface MonthlyActivityData { 179 month: string 180 year: number 181 reports: number 182 bans: number 183 } 184 185 // Monthly Activity Bar Chart Config 186 export const getMonthlyActivityConfig = (monthlyData: MonthlyActivityData[]): { 187 data: Data[], 188 layout: Partial<Layout> 189 } => { 190 return { 191 data: [ 192 { 193 x: monthlyData.map((item) => `${item.month} ${item.year}`), 194 y: monthlyData.map((item) => item.reports), 195 name: "Reports", 196 type: "bar", 197 marker: { 198 color: "#9333ea", 199 }, 200 }, 201 { 202 x: monthlyData.map((item) => `${item.month} ${item.year}`), 203 y: monthlyData.map((item) => item.bans), 204 name: "Bans", 205 type: "bar", 206 marker: { 207 color: "#dc2626", 208 }, 209 }, 210 ], 211 layout: { 212 paper_bgcolor: "rgba(0,0,0,0)", 213 plot_bgcolor: "rgba(0,0,0,0)", 214 font: { 215 color: "#9ca3af", 216 }, 217 margin: { 218 l: 40, 219 r: 10, 220 t: 10, 221 b: 40, 222 pad: 10, 223 }, 224 barmode: "group", 225 legend: { 226 orientation: "h", 227 xanchor: "center", 228 x: 0.5, 229 y: -0.2, 230 }, 231 xaxis: { 232 gridcolor: "#1f2937", 233 tickfont: { 234 size: 10, 235 }, 236 automargin: true, 237 }, 238 yaxis: { 239 gridcolor: "#1f2937", 240 zerolinecolor: "#1f2937", 241 automargin: true, 242 }, 243 height: 280, 244 autosize: true, 245 }, 246 } 247 } 248 249 export interface BannedServerData { 250 label: string 251 value: number 252 secondaryLabel: string 253 } 254 255 // Banned Servers Horizontal Bar Chart Config 256 export const getBannedServersConfig = (serversData: BannedServerData[]): { 257 data: Data[], 258 layout: Partial<Layout> 259 } => { 260 return { 261 data: [ 262 { 263 y: serversData.map((item) => item.label), 264 x: serversData.map((item) => item.value), 265 type: "bar", 266 orientation: "h", 267 marker: { 268 color: "#dc2626", 269 }, 270 text: serversData.map((item) => item.secondaryLabel), 271 textposition: "auto", 272 hoverinfo: "x+text", 273 }, 274 ], 275 layout: { 276 paper_bgcolor: "rgba(0,0,0,0)", 277 plot_bgcolor: "rgba(0,0,0,0)", 278 font: { 279 color: "#9ca3af", 280 }, 281 margin: { 282 l: 10, 283 r: 10, 284 t: 10, 285 b: 40, 286 pad: 10, 287 }, 288 xaxis: { 289 gridcolor: "#1f2937", 290 zerolinecolor: "#1f2937", 291 automargin: true, 292 }, 293 yaxis: { 294 gridcolor: "#1f2937", 295 zerolinecolor: "#1f2937", 296 automargin: true, 297 }, 298 height: 220, 299 autosize: true, 300 }, 301 } 302 }