Auth: nedokoncena registracia sa da dokoncit novym QR kodom
Ucet bez potvrdeneho kodu (auth_token is NULL a totp_last_step == 0) uz neblokuje meno: opakovany register_account vyda novy secret (stary QR prestane platit) a login vyhodi RegistrationIncomplete, na ktoru server odpovie novym QR -- klient sa prepne na registracny tab. Admin statistiky vykazuju nedokoncene registracie osobitne, Hraci celkom pocita len potvrdene ucty. Novy event register v analytike. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { useGameStore } from '../store/gameStore';
|
||||
import { emit } from '../lib/socket';
|
||||
@@ -20,6 +20,15 @@ export default function Auth() {
|
||||
|
||||
const remember = (name: string) => localStorage.setItem('bridzik_name', name.trim());
|
||||
|
||||
// Server can push a registration payload even from the login tab (unfinished
|
||||
// registration → re-issued QR) — always land on the tab that shows it.
|
||||
useEffect(() => {
|
||||
if (registration) {
|
||||
setMode('register');
|
||||
setCode('');
|
||||
}
|
||||
}, [registration]);
|
||||
|
||||
const handleLogin = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!username.trim() || code.trim().length < 6) return;
|
||||
@@ -31,6 +40,7 @@ export default function Auth() {
|
||||
e.preventDefault();
|
||||
if (!username.trim()) return;
|
||||
remember(username);
|
||||
trackEvent('register');
|
||||
emit.registerAccount(username.trim());
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ interface DailyStats {
|
||||
completion_rate: number | null;
|
||||
avg_game_duration_minutes: number | null;
|
||||
total_players: number;
|
||||
unconfirmed_players: number;
|
||||
peak_hours: Record<string, number>;
|
||||
rounds_per_day: Record<string, number>;
|
||||
pageviews_per_day: Record<string, number>;
|
||||
@@ -155,6 +156,7 @@ export default function AdminStats() {
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className={`flex gap-3 ${desktop ? '' : 'flex-wrap'}`}>
|
||||
<SummaryCard label="Hráči celkom" value={String(data.total_players)} />
|
||||
<SummaryCard label="Nedokončené registrácie" value={String(data.unconfirmed_players)} />
|
||||
<SummaryCard
|
||||
label="Dokončené hry"
|
||||
value={data.completion_rate != null ? `${Math.round(data.completion_rate * 100)}%` : '—'}
|
||||
|
||||
Reference in New Issue
Block a user