152 lines
4.4 KiB
TypeScript
152 lines
4.4 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import axios from 'axios';
|
|
import Login from './components/Auth/Login';
|
|
import Register from './components/Auth/Register';
|
|
import LevelList from './components/Levels/LevelList';
|
|
import LevelEditor from './components/Levels/LevelEditor';
|
|
import GamePlayer from './components/Game/GamePlayer';
|
|
import { authAPI } from './api';
|
|
import { Level } from './types';
|
|
import './App.css';
|
|
|
|
type AppState = 'login' | 'register' | 'levels' | 'playing' | 'editing';
|
|
|
|
const App: React.FC = () => {
|
|
const [appState, setAppState] = useState<AppState>('login');
|
|
const [currentLevelId, setCurrentLevelId] = useState<number | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [authStatusMessage, setAuthStatusMessage] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
// Check if user is already logged in via cookie
|
|
validateAuth();
|
|
}, []);
|
|
|
|
const validateAuth = async () => {
|
|
try {
|
|
await authAPI.whoami();
|
|
setAppState('levels');
|
|
setAuthStatusMessage(null);
|
|
} catch (error: unknown) {
|
|
const message = axios.isAxiosError(error) && error.response?.status === 400
|
|
? (typeof error.response.data === 'string' ? error.response.data : error.response.data?.message || 'Bad Request')
|
|
: null;
|
|
setAuthStatusMessage(message ? `Auth check failed: ${message}` : null);
|
|
setAppState('login');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleAuthSuccess = () => {
|
|
setAppState('levels');
|
|
setAuthStatusMessage(null);
|
|
};
|
|
|
|
const handleLogout = async () => {
|
|
try {
|
|
await authAPI.logout();
|
|
} catch (error) {
|
|
console.error('Logout failed:', error);
|
|
} finally {
|
|
setAppState('login');
|
|
setCurrentLevelId(null);
|
|
setAuthStatusMessage(null);
|
|
}
|
|
};
|
|
|
|
const handlePlayLevel = (levelId: number) => {
|
|
setCurrentLevelId(levelId);
|
|
setAppState('playing');
|
|
};
|
|
|
|
const handleCreateLevel = () => {
|
|
setAppState('editing');
|
|
};
|
|
|
|
const handleCancelEditor = () => {
|
|
setAppState('levels');
|
|
};
|
|
|
|
const handleLevelSaved = (level: Level) => {
|
|
console.log('Level saved:', level);
|
|
setAppState('levels');
|
|
};
|
|
|
|
const handleBackToLevels = () => {
|
|
setCurrentLevelId(null);
|
|
setAppState('levels');
|
|
};
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="app-loading">
|
|
<div className="loading-spinner"></div>
|
|
<p>Loading Block Game...</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
switch (appState) {
|
|
case 'login':
|
|
return (
|
|
<Login
|
|
onLogin={handleAuthSuccess}
|
|
authStatusMessage={authStatusMessage ?? undefined}
|
|
onSwitchToRegister={() => {
|
|
setAuthStatusMessage(null);
|
|
setAppState('register');
|
|
}}
|
|
/>
|
|
);
|
|
|
|
case 'register':
|
|
return (
|
|
<Register
|
|
onRegister={handleAuthSuccess}
|
|
onSwitchToLogin={() => setAppState('login')}
|
|
/>
|
|
);
|
|
|
|
case 'levels':
|
|
return (
|
|
<LevelList
|
|
onPlayLevel={handlePlayLevel}
|
|
onCreateLevel={handleCreateLevel}
|
|
onLogout={handleLogout}
|
|
/>
|
|
);
|
|
|
|
case 'editing':
|
|
return (
|
|
<LevelEditor
|
|
onCancel={handleCancelEditor}
|
|
onSaved={handleLevelSaved}
|
|
/>
|
|
);
|
|
|
|
case 'playing':
|
|
if (!currentLevelId) {
|
|
setAppState('levels');
|
|
return null;
|
|
}
|
|
return (
|
|
<GamePlayer
|
|
levelId={currentLevelId}
|
|
onBack={handleBackToLevels}
|
|
/>
|
|
);
|
|
|
|
default:
|
|
return (
|
|
<div className="app-error">
|
|
<h1>Something went wrong</h1>
|
|
<button onClick={() => setAppState('login')}>
|
|
Go to Login
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
};
|
|
|
|
export default App; |