Update player.html
Browse files- player.html +31 -8
player.html
CHANGED
|
@@ -25,7 +25,12 @@
|
|
| 25 |
.player-team a { color: #f97316; text-decoration: none; }
|
| 26 |
.player-team a:hover { text-decoration: underline; }
|
| 27 |
.mention-count-header { font-size: 48px; font-weight: bold; color: #f97316; }
|
| 28 |
-
.mention-count-label { font-size: 14px; color: #888; text-transform: uppercase; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
.section-title { font-size: 18px; font-weight: 600; color: #333; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #f97316; }
|
| 30 |
.mentions-list { display: flex; flex-direction: column; gap: 15px; margin-bottom: 30px; }
|
| 31 |
.mention-card { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
|
|
@@ -65,8 +70,13 @@
|
|
| 65 |
<div class="player-header">
|
| 66 |
<div class="player-name" id="playerName">Loading...</div>
|
| 67 |
<div class="player-team" id="playerTeam"></div>
|
| 68 |
-
<div class="
|
| 69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
</div>
|
| 71 |
<div class="section-title">Recent Mentions</div>
|
| 72 |
<div class="mentions-list" id="mentionsList"><div class="loading"><div class="spinner"></div><p>Loading...</p></div></div>
|
|
@@ -111,9 +121,12 @@
|
|
| 111 |
function processText(text) {
|
| 112 |
if (!text) return '';
|
| 113 |
let escaped = escapeHtml(text);
|
| 114 |
-
// Match URLs
|
| 115 |
-
escaped = escaped.replace(/(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/
|
| 116 |
-
|
|
|
|
|
|
|
|
|
|
| 117 |
for (const player of allPlayers) {
|
| 118 |
if (player === playerName) continue;
|
| 119 |
const regex = new RegExp(`\\b(${player.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})\\b`, 'gi');
|
|
@@ -141,11 +154,21 @@
|
|
| 141 |
if (info.team) document.getElementById('playerTeam').innerHTML = `<a href="/team/${encodeURIComponent(info.team)}">${info.team}</a>`;
|
| 142 |
if (info.teammates?.length) document.getElementById('relatedGrid').innerHTML = info.teammates.map(t => `<a href="/player/${encodeURIComponent(t)}" class="related-link">${t}</a>`).join('');
|
| 143 |
else document.getElementById('relatedGrid').innerHTML = '<p style="color:#888">No teammates</p>';
|
| 144 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
try {
|
| 147 |
const mentions = await (await fetch(`/api/mentions/${encodeURIComponent(playerName)}?limit=50`)).json();
|
| 148 |
-
document.getElementById('totalMentions').textContent = mentions.length;
|
| 149 |
if (!mentions.length) { document.getElementById('mentionsList').innerHTML = '<div class="empty-state"><h3>No mentions found</h3></div>'; return; }
|
| 150 |
document.getElementById('mentionsList').innerHTML = mentions.map(m => {
|
| 151 |
const avatarUrl = m.author_avatar || 'https://cdn.bsky.app/img/avatar/plain/did:plc:default/default@jpeg';
|
|
|
|
| 25 |
.player-team a { color: #f97316; text-decoration: none; }
|
| 26 |
.player-team a:hover { text-decoration: underline; }
|
| 27 |
.mention-count-header { font-size: 48px; font-weight: bold; color: #f97316; }
|
| 28 |
+
.mention-count-label { font-size: 14px; color: #888; text-transform: uppercase; margin-bottom: 20px; }
|
| 29 |
+
.period-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin-top: 15px; }
|
| 30 |
+
.period-stat { background: #f8f9fa; border-radius: 8px; padding: 12px; text-align: center; }
|
| 31 |
+
.period-label { font-size: 12px; color: #888; font-weight: 600; margin-bottom: 4px; }
|
| 32 |
+
.period-mentions { font-size: 20px; font-weight: bold; color: #f97316; }
|
| 33 |
+
.period-rank { font-size: 11px; color: #666; margin-top: 2px; }
|
| 34 |
.section-title { font-size: 18px; font-weight: 600; color: #333; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #f97316; }
|
| 35 |
.mentions-list { display: flex; flex-direction: column; gap: 15px; margin-bottom: 30px; }
|
| 36 |
.mention-card { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
|
|
|
|
| 70 |
<div class="player-header">
|
| 71 |
<div class="player-name" id="playerName">Loading...</div>
|
| 72 |
<div class="player-team" id="playerTeam"></div>
|
| 73 |
+
<div class="period-stats" id="periodStats">
|
| 74 |
+
<div class="period-stat"><div class="period-label">6h</div><div class="period-mentions">-</div><div class="period-rank"></div></div>
|
| 75 |
+
<div class="period-stat"><div class="period-label">12h</div><div class="period-mentions">-</div><div class="period-rank"></div></div>
|
| 76 |
+
<div class="period-stat"><div class="period-label">24h</div><div class="period-mentions">-</div><div class="period-rank"></div></div>
|
| 77 |
+
<div class="period-stat"><div class="period-label">48h</div><div class="period-mentions">-</div><div class="period-rank"></div></div>
|
| 78 |
+
<div class="period-stat"><div class="period-label">7d</div><div class="period-mentions">-</div><div class="period-rank"></div></div>
|
| 79 |
+
</div>
|
| 80 |
</div>
|
| 81 |
<div class="section-title">Recent Mentions</div>
|
| 82 |
<div class="mentions-list" id="mentionsList"><div class="loading"><div class="spinner"></div><p>Loading...</p></div></div>
|
|
|
|
| 121 |
function processText(text) {
|
| 122 |
if (!text) return '';
|
| 123 |
let escaped = escapeHtml(text);
|
| 124 |
+
// Match URLs - https://, http://, and common short domains
|
| 125 |
+
escaped = escaped.replace(/(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/gi, '<a href="$1" target="_blank">$1</a>');
|
| 126 |
+
// Match youtu.be, bit.ly, etc without protocol
|
| 127 |
+
escaped = escaped.replace(/(?<![\/\w])((?:youtu\.be|bit\.ly|t\.co|tinyurl\.com|goo\.gl)\/[^\s<]+[^<.,:;"')\]\s])/gi, '<a href="https://$1" target="_blank">$1</a>');
|
| 128 |
+
// Match www. URLs
|
| 129 |
+
escaped = escaped.replace(/(?<![\/\w])(www\.[^\s<]+[^<.,:;"')\]\s])/gi, '<a href="https://$1" target="_blank">$1</a>');
|
| 130 |
for (const player of allPlayers) {
|
| 131 |
if (player === playerName) continue;
|
| 132 |
const regex = new RegExp(`\\b(${player.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})\\b`, 'gi');
|
|
|
|
| 154 |
if (info.team) document.getElementById('playerTeam').innerHTML = `<a href="/team/${encodeURIComponent(info.team)}">${info.team}</a>`;
|
| 155 |
if (info.teammates?.length) document.getElementById('relatedGrid').innerHTML = info.teammates.map(t => `<a href="/player/${encodeURIComponent(t)}" class="related-link">${t}</a>`).join('');
|
| 156 |
else document.getElementById('relatedGrid').innerHTML = '<p style="color:#888">No teammates</p>';
|
| 157 |
+
|
| 158 |
+
// Populate period stats
|
| 159 |
+
if (info.period_stats) {
|
| 160 |
+
document.getElementById('periodStats').innerHTML = info.period_stats.map(p => `
|
| 161 |
+
<div class="period-stat">
|
| 162 |
+
<div class="period-label">${p.label}</div>
|
| 163 |
+
<div class="period-mentions">${p.mentions}</div>
|
| 164 |
+
<div class="period-rank">${p.rank ? '#' + p.rank : '-'}</div>
|
| 165 |
+
</div>
|
| 166 |
+
`).join('');
|
| 167 |
+
}
|
| 168 |
+
} catch (e) { console.error(e); }
|
| 169 |
|
| 170 |
try {
|
| 171 |
const mentions = await (await fetch(`/api/mentions/${encodeURIComponent(playerName)}?limit=50`)).json();
|
|
|
|
| 172 |
if (!mentions.length) { document.getElementById('mentionsList').innerHTML = '<div class="empty-state"><h3>No mentions found</h3></div>'; return; }
|
| 173 |
document.getElementById('mentionsList').innerHTML = mentions.map(m => {
|
| 174 |
const avatarUrl = m.author_avatar || 'https://cdn.bsky.app/img/avatar/plain/did:plc:default/default@jpeg';
|