web-next: rediseño de security-token, recover, vote-points + rename-guild
- /security-token: diseño completo del original (info + advertencia + NOTA 7 días), fecha en formato HH:MM:SS DD-MM-YYYY, botón "Token enviado", enlace a /recover. - /recover: 4 opciones (contraseña por usuario, nombre de cuenta, token de seguridad y enlace de activación por correo); recuperación de token nueva; Turnstile por envío. - /vote-points: caja de info con las 7 secciones Q&A + panel "Sitios de votación" con tarjetas inline-div (imagen, PV, último voto), botón refrescar; abre el sitio y acredita PV al volver. lib/vote.ts + getVoteSitesForAccount. - /rename-guild: renombra una hermandad de la que la cuenta es Maestro por 1000 PD + token de seguridad; SOAP .guild rename con comillas; reembolsa los PD si SOAP falla. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,29 @@ export async function getVoteSites(): Promise<VoteSite[]> {
|
||||
}
|
||||
}
|
||||
|
||||
export interface VoteSiteStatus extends VoteSite {
|
||||
lastVoteAt: string | null // ISO del último voto de la cuenta en este sitio, o null
|
||||
}
|
||||
|
||||
/** Sitios de votación con la fecha del último voto de la cuenta (para el recuadro). */
|
||||
export async function getVoteSitesForAccount(accountId: number): Promise<VoteSiteStatus[]> {
|
||||
const sites = await getVoteSites()
|
||||
if (!accountId) return sites.map((s) => ({ ...s, lastVoteAt: null }))
|
||||
try {
|
||||
const [rows] = await db(DB.default).query<RowDataPacket[]>(
|
||||
'SELECT vote_site_id, MAX(created_at) AS last FROM home_votelog WHERE account_id = ? GROUP BY vote_site_id',
|
||||
[accountId],
|
||||
)
|
||||
const map = new Map(rows.map((r) => [Number(r.vote_site_id), r.last as Date]))
|
||||
return sites.map((s) => {
|
||||
const last = map.get(s.id)
|
||||
return { ...s, lastVoteAt: last ? new Date(last).toISOString() : null }
|
||||
})
|
||||
} catch {
|
||||
return sites.map((s) => ({ ...s, lastVoteAt: null }))
|
||||
}
|
||||
}
|
||||
|
||||
export async function registerVote(accountId: number, url: string): Promise<VoteResult> {
|
||||
const [siteRows] = await db(DB.default).query<RowDataPacket[]>(
|
||||
'SELECT id, name, points FROM home_votesite WHERE url = ?',
|
||||
|
||||
Reference in New Issue
Block a user