harshapitla/github-actions-analytics
0
1import React, { useMemo } from "react";2import {3 BarChart,4 Bar,5 XAxis,6 YAxis,7 CartesianGrid,8 Tooltip,9 ResponsiveContainer,10 Cell,11} from "recharts";12import ChartCard from "../components/charts/ChartCard";13 14const COLORS = [15 "#f59e0b",16 "#d97706",17 "#b45309",18 "#92400e",19 "#78350f",20 "#451a03",21 "#eab308",22 "#ca8a04",23 "#a16207",24 "#854d0e",25];26 27function CustomTooltip({ active, payload, label }) {28 if (active && payload && payload.length) {29 const data = payload[0].payload;30 return (31 <div32 style={{33 background: "rgba(5, 18, 35, 0.9)",34 padding: "8px 12px",35 borderRadius: 6,36 border: "1px solid #334155",37 maxWidth: "350px",38 }}39 >40 <div style={{ marginBottom: 4, fontWeight: "bold" }}>41 {data.action_title}42 </div>43 <div style={{ color: "#f59e0b", fontWeight: "bold" }}>44 ⚠ PRIME VERIFICATION CANDIDATE45 </div>46 <div style={{ color: "#8884d8" }}>47 Contributors: {data.no_of_contributors}48 </div>49 <div style={{ color: "#82ca9d" }}>50 Stars: {data.no_of_stars.toLocaleString()}51 </div>52 <div style={{ color: "#fbbf24", marginTop: 4 }}>53 Trust Score: {data.trustScore}54 </div>55 <div style={{ fontSize: 12, color: "#94a3b8", marginTop: 4 }}>56 Publisher: {data.publisher}57 </div>58 {data.tags && (59 <div style={{ fontSize: 12, color: "#94a3b8" }}>60 Tags: {data.tags}61 </div>62 )}63 </div>64 );65 }66 return null;67}68 69export default function TrustedNonVerifiedChart({ rows = [] }) {70 const topCandidates = useMemo(() => {71 if (!Array.isArray(rows)) return [];72 73 // Calculate median values for "trusted" threshold74 const validRows = rows.filter((row) => {75 const contributors = parseInt(row.no_of_contributors) || 0;76 const stars = parseInt(row.no_of_stars) || 0;77 return contributors >= 0 && stars >= 0;78 });79 80 const contributors = validRows81 .map((row) => parseInt(row.no_of_contributors) || 0)82 .sort((a, b) => a - b);83 const stars = validRows84 .map((row) => parseInt(row.no_of_stars) || 0)85 .sort((a, b) => a - b);86 87 const medianContributors =88 contributors[Math.floor(contributors.length / 2)] || 5;89 const medianStars = stars[Math.floor(stars.length / 2)] || 50;90 91 // Find non-verified actions that exceed median thresholds (trusted but not verified)92 const candidates = validRows93 .filter((row) => {94 const isVerified =95 String(row.is_action_verified).toLowerCase() === "true";96 const contributors = parseInt(row.no_of_contributors) || 0;97 const stars = parseInt(row.no_of_stars) || 0;98 99 // Must be non-verified AND exceed median thresholds100 return (101 !isVerified &&102 contributors >= medianContributors &&103 stars >= medianStars104 );105 })106 .map((row) => {107 const contributors = parseInt(row.no_of_contributors) || 0;108 const stars = parseInt(row.no_of_stars) || 0;109 110 // Create trust score: higher weight on stars since they indicate broader adoption111 const normalizedStars = Math.min(stars / 1000, 10); // Cap at 10 for very popular actions112 const normalizedContributors = Math.min(contributors / 50, 5); // Cap at 5 for high-contributor actions113 const trustScore =114 Math.round((normalizedStars * 2 + normalizedContributors) * 10) / 10;115 116 return {117 action_title: row.action_title || row.name || "Unknown Action",118 publisher: row.publisher || "(unknown)",119 tags: row.tags || "",120 no_of_contributors: contributors,121 no_of_stars: stars,122 trustScore,123 shortTitle:124 (row.action_title || row.name || "Unknown").length > 25125 ? (row.action_title || row.name || "Unknown").substring(0, 22) +126 "..."127 : row.action_title || row.name || "Unknown",128 };129 });130 131 // Sort by trust score and take top 10132 return candidates133 .sort((a, b) => b.trustScore - a.trustScore)134 .slice(0, 10)135 .map((action, index) => ({136 ...action,137 rank: index + 1,138 }));139 }, [rows]);140 141 if (!topCandidates.length) {142 return (143 <ChartCard144 title="Trusted Non-Verified Actions"145 subtitle="Non-verified actions demonstrating strong user trust"146 >147 <p className="small">148 No prime verification candidates found in the current dataset.149 </p>150 </ChartCard>151 );152 }153 154 return (155 <ChartCard156 title="Trusted Non-Verified Actions"157 subtitle="Non-verified actions demonstrating strong user trust"158 >159 <div style={{ height: 450 }}>160 <ResponsiveContainer>161 <BarChart162 data={topCandidates}163 layout="horizontal"164 margin={{ top: 20, right: 30, left: 100, bottom: 20 }}165 >166 <CartesianGrid strokeDasharray="3 3" stroke="#334155" />167 <XAxis168 type="number"169 stroke="#fbbf24"170 label={{171 value: "Trust Score",172 angle: 0,173 position: "insideBottom",174 offset: -5,175 }}176 />177 <YAxis178 type="category"179 dataKey="shortTitle"180 stroke="#94a3b8"181 fontSize={11}182 width={90}183 />184 <Tooltip content={<CustomTooltip />} />185 <Bar dataKey="trustScore" name="Trust Score" radius={[0, 4, 4, 0]}>186 {topCandidates.map((entry, index) => (187 <Cell188 key={`cell-${index}`}189 fill={COLORS[index % COLORS.length]}190 />191 ))}192 </Bar>193 </BarChart>194 </ResponsiveContainer>195 </div>196 197 <div style={{ marginTop: 20, fontSize: 14, color: "#94a3b8" }}>198 <div199 style={{200 display: "grid",201 gridTemplateColumns: "1fr 1fr",202 gap: "16px",203 marginBottom: 16,204 }}205 >206 <div207 style={{208 textAlign: "center",209 padding: "12px",210 backgroundColor: "rgba(245, 158, 11, 0.1)",211 borderRadius: "8px",212 }}213 >214 <div style={{ fontSize: 18, marginBottom: 8 }}>🎯</div>215 <div216 style={{ fontWeight: "bold", color: "#f59e0b", marginBottom: 4 }}217 >218 Prime Candidates219 </div>220 <p style={{ fontSize: 12 }}>221 Non-verified actions exceeding median trust thresholds222 </p>223 </div>224 225 <div226 style={{227 textAlign: "center",228 padding: "12px",229 backgroundColor: "rgba(16, 185, 129, 0.1)",230 borderRadius: "8px",231 }}232 >233 <div style={{ fontSize: 18, marginBottom: 8 }}>✅</div>234 <div235 style={{ fontWeight: "bold", color: "#10b981", marginBottom: 4 }}236 >237 Ready for Verification238 </div>239 <p style={{ fontSize: 12 }}>240 These actions have earned community trust241 </p>242 </div>243 </div>244 245 <div246 style={{247 textAlign: "center",248 fontSize: 12,249 borderTop: "1px solid #334155",250 paddingTop: 12,251 }}252 >253 <p>254 <strong>Trust Score Formula:</strong> (Stars/1000 × 2) +255 (Contributors/50)256 <br />257 <em>258 Actions ranked by trust score - higher scores indicate stronger259 community validation260 </em>261 </p>262 </div>263 </div>264 </ChartCard>265 );266}267 