feat: Füge Wallet-Unterstützung zur Crash-Seite hinzu und verbessere WebSocket-Verbindung

This commit is contained in:
2025-11-23 13:08:00 +01:00
parent 2beb5efdb4
commit 3624fff9d8
2 changed files with 62 additions and 17 deletions

View File

@@ -14,6 +14,18 @@ server {
root /usr/share/nginx/html;
index index.html;
# --- WebSocket-Route ---
# Dieser Block fängt Anfragen an /ws ab und leitet sie mit den
# nötigen Headern für eine WebSocket-Verbindung weiter.
location /ws {
proxy_pass http://bierbaron_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
# --- API-Routen (HTTP) ---
location ~ ^/(api|auth|me|wallet|slot|admin|health)($|/) {
proxy_pass http://bierbaron_backend;
proxy_http_version 1.1;
@@ -25,14 +37,15 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header Cookie $http_cookie;
}
# --- Statisches Frontend (Single Page Application) ---
location / {
try_files $uri /index.html;
}
# Optionale Caching-Regeln für statische Assets
location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|webp|woff|woff2|ttf)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800, immutable";

View File

@@ -1,6 +1,6 @@
// frontend/src/pages/CrashPage.tsx
import React, { useState, useEffect, useRef } from 'react';
import { MeResponse } from '../api';
import { MeResponse, WalletResponse, getWallet } from '../api';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
interface CrashPageProps {
@@ -11,11 +11,28 @@ export const CrashPage: React.FC<CrashPageProps> = ({ me }) => {
const [phase, setPhase] = useState('connecting');
const [multiplier, setMultiplier] = useState(1.00);
const [history, setHistory] = useState<{ time: number, value: number }[]>([]);
const [wallet, setWallet] = useState<WalletResponse | null>(null);
const [error, setError] = useState<string | null>(null);
const ws = useRef<WebSocket | null>(null);
// --- HINZUGEFÜGT: Lade das Wallet des Benutzers ---
useEffect(() => {
// Die WebSocket-URL muss auf deine Domain zeigen, aber mit wss:// (für https)
const wsUrl = `wss://${window.location.host}`;
async function loadWallet() {
if (me) {
try {
const walletData = await getWallet();
setWallet(walletData);
} catch (err: any) {
setError("Konnte das Guthaben nicht laden.");
}
}
}
loadWallet();
}, [me]);
useEffect(() => {
// --- DER FIX: Verbinde zum /ws Pfad ---
const wsUrl = `wss://${window.location.host}/ws`;
ws.current = new WebSocket(wsUrl);
ws.current.onopen = () => {
@@ -33,7 +50,7 @@ export const CrashPage: React.FC<CrashPageProps> = ({ me }) => {
break;
case 'newRound':
setPhase(data.phase);
setHistory([]); // Graphen zurücksetzen
setHistory([]);
setMultiplier(1.00);
break;
case 'roundStart':
@@ -73,26 +90,41 @@ export const CrashPage: React.FC<CrashPageProps> = ({ me }) => {
}
};
if (!me) {
return (
<div style={{ textAlign: "center", padding: "40px 0" }}>
<h2>🚀 Bier-Crash</h2>
<p>Bitte logge dich mit Discord ein, um zu spielen.</p>
</div>
);
}
return (
<div>
<h2>🚀 Bier-Crash</h2>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 3fr', gap: '24px' }}>
{error && <div style={{ color: 'red', marginBottom: '1rem' }}>{error}</div>}
<div style={{ display: 'grid', gridTemplateColumns: '1fr 3fr', gap: '24px', alignItems: 'flex-start' }}>
{/* Linke Spalte: Steuerung */}
<div>
<h4>Dein Einsatz</h4>
<input type="number" placeholder="100" style={{ width: '100%', padding: '8px', background: '#0b0b10', border: '1px solid #555', color: 'white', borderRadius: '4px' }} />
<button style={{ width: '100%', padding: '12px', marginTop: '16px', background: 'limegreen', border: 'none', borderRadius: '4px', color: 'white', fontWeight: 'bold' }}>
Einsatz platzieren
</button>
<button style={{ width: '100%', padding: '12px', marginTop: '8px', background: 'dodgerblue', border: 'none', borderRadius: '4px', color: 'white', fontWeight: 'bold' }}>
CASHOUT
</button>
<div style={{ background: '#1a1a2e', padding: '16px', borderRadius: '8px' }}>
<h4>Dein Guthaben</h4>
<p style={{ fontSize: '1.5rem', margin: '0 0 16px 0', color: '#ffb347' }}>
{wallet ? wallet.balance.toLocaleString('de-DE') : '...'} Bierkästen
</p>
<h4>Dein Einsatz</h4>
<input type="number" placeholder="100" style={{ width: '100%', padding: '8px', background: '#0b0b10', border: '1px solid #555', color: 'white', borderRadius: '4px' }} />
<button style={{ width: '100%', padding: '12px', marginTop: '16px', background: 'limegreen', border: 'none', borderRadius: '4px', color: 'white', fontWeight: 'bold' }}>
Einsatz platzieren
</button>
<button style={{ width: '100%', padding: '12px', marginTop: '8px', background: 'dodgerblue', border: 'none', borderRadius: '4px', color: 'white', fontWeight: 'bold' }}>
CASHOUT
</button>
</div>
</div>
{/* Rechte Spalte: Graph und Multiplikator */}
<div style={{ background: '#0b0b10', padding: '16px', borderRadius: '8px', position: 'relative', height: '400px' }}>
<div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', textAlign: 'center', zIndex: 1 }}>
<h1 style={{ fontSize: '4rem', margin: 0, color: phase === 'crashed' ? 'salmon' : 'white' }}>
<h1 style={{ fontSize: '4rem', margin: 0, color: phase === 'crashed' ? 'salmon' : 'white', transition: 'color 0.3s' }}>
{multiplier.toFixed(2)}x
</h1>
<p style={{ margin: 0, fontSize: '1.2rem' }}>{getStatusMessage()}</p>
@@ -100,7 +132,7 @@ export const CrashPage: React.FC<CrashPageProps> = ({ me }) => {
<ResponsiveContainer>
<LineChart data={history}>
<XAxis type="number" dataKey="time" hide />
<YAxis type="number" domain={['auto', 'auto']} hide />
<YAxis type="number" domain={[1, 'auto']} hide />
<Tooltip content={() => null} />
<Line type="monotone" dataKey="value" stroke="#8884d8" strokeWidth={4} dot={false} isAnimationActive={false} />
</LineChart>