/**
* Player Zoom Card โ shows player info with photo, stats, fun fact
*/
import { escapeHTML, setHTML } from '../utils/dom.js';
export class PlayerCard {
constructor(containerEl) {
this.containerEl = containerEl;
}
render() {
if (!this.containerEl) return;
setHTML(this.containerEl, `
`);
this.containerEl.querySelector('.player-card__close')?.addEventListener('click', () => this.hide());
}
show(sceneData) {
if (!this.containerEl) return;
const contentEl = this.containerEl.querySelector('#player-card-content');
if (!contentEl) return;
const safeHome = escapeHTML(sceneData.homeTeam || 'Unknown');
const safeAway = escapeHTML(sceneData.awayTeam || 'Unknown');
const safeScore = escapeHTML(sceneData.score || 'unknown');
const safeMinute = escapeHTML(sceneData.minute || 'unknown');
const safeInFocus = escapeHTML(sceneData.inFocus || 'Player in focus');
const safePhase = escapeHTML(sceneData.phase || 'open play');
const safeFunFact = escapeHTML(sceneData.funFact || 'No extra context available for this frame.');
// A named player is only shown when Gemini could legibly identify one.
const named = sceneData.player && sceneData.player !== 'Unknown'
? escapeHTML(sceneData.player) : null;
const safeConfidence = Number.isFinite(Number(sceneData.confidence)) ? Number(sceneData.confidence) : 0;
const notConfigured = sceneData.source === 'not-configured';
const isUncertain = Boolean(sceneData.isUncertain) || safeConfidence < 0.7;
const confClass = isUncertain ? 'confidence-tag--low' : 'confidence-tag--high';
const confLabel = notConfigured
? 'AI vision unavailable'
: `${isUncertain ? 'Reading' : 'Clear read'} ยท ${Math.round(safeConfidence * 100)}% confidence`;
setHTML(contentEl, `
In focus
${named ? `${named} โ ` : ''}${safeInFocus}
Phase
${safePhase}
What Gemini sees: ${safeFunFact}
`);
this.containerEl.hidden = false;
const cardEl = this.containerEl.querySelector('.player-card');
cardEl?.focus();
this._bindFocusTrap(cardEl);
}
showLoading() {
if (!this.containerEl) return;
const contentEl = this.containerEl.querySelector('#player-card-content');
if (contentEl) {
setHTML(contentEl, `
Analyzing camera frame with Gemini Vision...
`);
}
this.containerEl.hidden = false;
}
showError(msg) {
if (!this.containerEl) return;
const contentEl = this.containerEl.querySelector('#player-card-content');
if (contentEl) {
setHTML(contentEl, `${escapeHTML(msg)}
`);
}
this.containerEl.hidden = false;
}
_bindFocusTrap(cardEl) {
if (!cardEl) return;
this._unbindFocusTrap();
this._focusTrapHandler = (e) => {
if (e.key !== 'Tab') return;
const focusables = cardEl.querySelectorAll('button, [tabindex="0"]');
if (focusables.length === 0) return;
const first = focusables[0];
const last = focusables[focusables.length - 1];
if (e.shiftKey) {
if (document.activeElement === first) {
last.focus();
e.preventDefault();
}
} else {
if (document.activeElement === last) {
first.focus();
e.preventDefault();
}
}
};
cardEl.addEventListener('keydown', this._focusTrapHandler);
}
_unbindFocusTrap() {
if (this._focusTrapHandler && this.containerEl) {
const cardEl = this.containerEl.querySelector('.player-card');
cardEl?.removeEventListener('keydown', this._focusTrapHandler);
this._focusTrapHandler = null;
}
}
hide() {
this._unbindFocusTrap();
if (this.containerEl) this.containerEl.hidden = true;
}
}