Spaces:
Running
Running
| import React, { useState, useRef, useEffect } from 'react'; | |
| import logo from './assets/logo.jpg'; | |
| import './App.css'; | |
| import { VideoManagerLocal } from './utils/VideoManagerLocal'; | |
| import Home from './components/Home'; | |
| import FocusPageLocal from './components/FocusPageLocal'; | |
| import Achievement from './components/Achievement'; | |
| import Records from './components/Records'; | |
| import Help from './components/Help'; | |
| function App() { | |
| const [activeTab, setActiveTab] = useState('home'); | |
| const videoManagerRef = useRef(null); | |
| const [isSessionActive, setIsSessionActive] = useState(false); | |
| const [sessionResult, setSessionResult] = useState(null); | |
| const [isTutorialActive, setIsTutorialActive] = useState(false); | |
| useEffect(() => { | |
| fetch('/api/history', { method: 'DELETE' }) | |
| .then(() => { | |
| const backup = localStorage.getItem('focus_magic_backup'); | |
| if (backup) { | |
| try { | |
| const sessions = JSON.parse(backup); | |
| fetch('/api/import', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(sessions) | |
| }); | |
| console.log("History auto-recovered from browser cache."); | |
| } catch (err) { | |
| console.error("Failed to read magic backup", err); | |
| } | |
| } | |
| }) | |
| .catch(err => console.error(err)); | |
| const callbacks = { | |
| onSessionStart: () => { | |
| setIsSessionActive(true); | |
| setSessionResult(null); | |
| }, | |
| onSessionEnd: (summary) => { | |
| setIsSessionActive(false); | |
| if (summary) setSessionResult(summary); | |
| fetch('/api/sessions?filter=all') | |
| .then(res => res.json()) | |
| .then(data => { | |
| if (data && Array.isArray(data)) { | |
| localStorage.setItem('focus_magic_backup', JSON.stringify(data)); | |
| console.log("Session auto-saved to browser cache."); | |
| } | |
| }) | |
| .catch(err => console.error("Auto-save failed", err)); | |
| } | |
| }; | |
| videoManagerRef.current = new VideoManagerLocal(callbacks); | |
| return () => { | |
| if (videoManagerRef.current) videoManagerRef.current.stopStreaming(); | |
| }; | |
| }, []); | |
| const handleAvatarClick = () => { | |
| setActiveTab('home'); | |
| }; | |
| return ( | |
| <div className="app-container"> | |
| <nav id="top-menu"> | |
| <div className="avatar-container" onClick={handleAvatarClick} title="Back to Home"> | |
| <div className="avatar-circle user" style={{ backgroundColor: 'transparent', border: 'none' }}> | |
| <img | |
| src={logo} | |
| alt="FocusGuard Logo" | |
| style={{ width: '100%', height: '100%', objectFit: 'contain' }} | |
| /> | |
| </div> | |
| </div> | |
| <button className={`menu-btn ${activeTab === 'focus' ? 'active' : ''}`} onClick={() => setActiveTab('focus')}> | |
| Start Focus {isSessionActive && <span style={{ marginLeft: '8px', color: '#00FF00' }}>●</span>} | |
| </button> | |
| <div className="separator"></div> | |
| <button className={`menu-btn ${activeTab === 'achievement' ? 'active' : ''}`} onClick={() => setActiveTab('achievement')}> | |
| My Achievement | |
| </button> | |
| <div className="separator"></div> | |
| <button className={`menu-btn ${activeTab === 'records' ? 'active' : ''}`} onClick={() => setActiveTab('records')}> | |
| My Records | |
| </button> | |
| <div className="separator"></div> | |
| <button className={`menu-btn ${activeTab === 'help' ? 'active' : ''}`} onClick={() => setActiveTab('help')}> | |
| Help | |
| </button> | |
| </nav> | |
| {activeTab === 'home' && <Home setActiveTab={setActiveTab} setIsTutorialActive={setIsTutorialActive} />} | |
| <FocusPageLocal | |
| videoManager={videoManagerRef.current} | |
| sessionResult={sessionResult} | |
| setSessionResult={setSessionResult} | |
| isActive={activeTab === 'focus'} | |
| isTutorialActive={isTutorialActive} | |
| setIsTutorialActive={setIsTutorialActive} | |
| /> | |
| {activeTab === 'achievement' && <Achievement />} | |
| {activeTab === 'records' && <Records />} | |
| {activeTab === 'help' && <Help />} | |
| </div> | |
| ); | |
| } | |
| export default App; |