Update Version (Beta): login + leaderboard/ word definition
This commit is contained in:
@@ -16,6 +16,7 @@ let authSession = null
|
||||
let authProfile = null
|
||||
let leaderboardScope = "hour"
|
||||
let latestLeaderboardRows = []
|
||||
let lastDefinition = null
|
||||
|
||||
const WORD_LENGTH = 5
|
||||
const MAX_GUESSES = 6
|
||||
@@ -96,7 +97,7 @@ const statsModal = document.getElementById("stats-modal")
|
||||
const statsGrid = document.getElementById("stats-grid")
|
||||
const statsNote = document.getElementById("stats-note")
|
||||
const guessBars = document.getElementById("guess-bars")
|
||||
const historyList = document.getElementById("history-list")
|
||||
const statsDefinition = document.getElementById("stats-definition")
|
||||
const resetStatsButton = document.getElementById("reset-stats")
|
||||
const shareResultsButton = document.getElementById("share-results")
|
||||
|
||||
@@ -419,6 +420,7 @@ function applyHourlyRound(round) {
|
||||
guesses: round.guessCount || MAX_GUESSES,
|
||||
word: round.word || ""
|
||||
}
|
||||
if (round.word) loadWordDefinition(round.word, Boolean(round.won))
|
||||
lockUntilNextWord()
|
||||
return
|
||||
}
|
||||
@@ -1123,6 +1125,11 @@ function playCelebrationSound() {
|
||||
}
|
||||
|
||||
async function showWordDefinition(word, isWin = true) {
|
||||
const definition = await loadWordDefinition(word, isWin)
|
||||
showDefinitionAlert(definition)
|
||||
}
|
||||
|
||||
async function loadWordDefinition(word, isWin = true) {
|
||||
try {
|
||||
const response = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${word}`)
|
||||
if (!response.ok) throw new Error(`API request failed: ${response.status}`)
|
||||
@@ -1135,20 +1142,23 @@ async function showWordDefinition(word, isWin = true) {
|
||||
|
||||
if (!definition) throw new Error("No definition found")
|
||||
|
||||
showDefinitionAlert({
|
||||
lastDefinition = {
|
||||
title: `${word.toUpperCase()} ${partOfSpeech ? `(${partOfSpeech})` : ""}`,
|
||||
body: definition,
|
||||
example,
|
||||
isWin
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.info("Definition lookup unavailable:", error)
|
||||
showDefinitionAlert({
|
||||
lastDefinition = {
|
||||
title: word.toUpperCase(),
|
||||
body: "Definition not available at the moment.",
|
||||
isWin
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
renderStatsDefinition()
|
||||
return lastDefinition
|
||||
}
|
||||
|
||||
function showDefinitionAlert({ title, body, example, isWin }) {
|
||||
@@ -1308,7 +1318,7 @@ async function renderStats() {
|
||||
.join("")
|
||||
|
||||
renderStatsNote(summary)
|
||||
await renderHistory()
|
||||
renderStatsDefinition()
|
||||
}
|
||||
|
||||
function renderStatsNote(summary) {
|
||||
@@ -1372,60 +1382,25 @@ async function getHourlySummary() {
|
||||
}
|
||||
}
|
||||
|
||||
async function renderHistory() {
|
||||
if (!historyList) return
|
||||
function renderStatsDefinition() {
|
||||
if (!statsDefinition) return
|
||||
|
||||
if (hourlyRound?.backend !== "supabase") {
|
||||
historyList.innerHTML = '<div class="leaderboard-empty">Sign in to keep a cross-device history.</div>'
|
||||
if (!lastResult) {
|
||||
statsDefinition.innerHTML = "Finish this hour's word to reveal its definition here."
|
||||
return
|
||||
}
|
||||
|
||||
const rows = await getPlayerHistory()
|
||||
if (rows.length === 0) {
|
||||
historyList.innerHTML = '<div class="leaderboard-empty">No completed rounds yet.</div>'
|
||||
if (!lastDefinition) {
|
||||
statsDefinition.innerHTML = "Loading definition..."
|
||||
return
|
||||
}
|
||||
|
||||
historyList.innerHTML = rows
|
||||
.map(row => `
|
||||
<div class="history-row">
|
||||
<span>
|
||||
<span class="history-word">${escapeHtml(row.word)}</span>
|
||||
<span class="history-meta">${formatHistoryHour(row.hourStart)}</span>
|
||||
</span>
|
||||
<span class="history-meta">${row.won ? `${row.guessCount}/6` : "X/6"}</span>
|
||||
</div>
|
||||
`)
|
||||
.join("")
|
||||
}
|
||||
|
||||
async function getPlayerHistory() {
|
||||
const client = getSupabaseClient()
|
||||
if (!client || !authSession) return []
|
||||
|
||||
const { data, error } = await client.rpc("get_player_history", { history_limit: 8 })
|
||||
if (error) {
|
||||
console.warn("Failed to load history:", error)
|
||||
return []
|
||||
}
|
||||
|
||||
return (Array.isArray(data) ? data : []).map(row => ({
|
||||
hourStart: row.hour_start,
|
||||
word: row.word || "-----",
|
||||
won: Boolean(row.won),
|
||||
guessCount: row.guess_count || MAX_GUESSES,
|
||||
completedAt: row.completed_at
|
||||
}))
|
||||
}
|
||||
|
||||
function formatHistoryHour(value) {
|
||||
if (!value) return ""
|
||||
|
||||
return new Intl.DateTimeFormat(undefined, {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
hour: "numeric"
|
||||
}).format(new Date(value))
|
||||
statsDefinition.innerHTML = `
|
||||
<span class="word-label">${lastResult.won ? "Solved word" : "Answer"}</span>
|
||||
<strong>${escapeHtml(lastDefinition.title)}</strong>
|
||||
<span>${escapeHtml(lastDefinition.body)}</span>
|
||||
${lastDefinition.example ? `<em>Example: ${escapeHtml(lastDefinition.example)}</em>` : ""}
|
||||
`
|
||||
}
|
||||
|
||||
function renderLeaderboardLoading() {
|
||||
|
||||
Reference in New Issue
Block a user