From 8559b615734760ff060ac2c714c8fca80d5ed251 Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Mon, 30 Jun 2025 00:59:25 -0700 Subject: add score import page --- frontend/src/App.tsx | 4 +- frontend/src/components/modals/JsonUploadModal.tsx | 161 +++++++++++++ frontend/src/pages/Home.tsx | 6 + frontend/src/pages/Import.tsx | 266 +++++++++++++++++++++ 4 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/modals/JsonUploadModal.tsx (limited to 'frontend') diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d317805..65f3355 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -3,6 +3,7 @@ import { AuthProvider } from './contexts/AuthContext'; import Landing from './pages/Landing'; import Login from './pages/Login'; import Register from './pages/Register'; +import Import from './pages/Import'; import Home from './pages/Home'; function App() { @@ -12,10 +13,11 @@ function App() { } /> } /> } /> + } /> } /> ); } -export default App; \ No newline at end of file +export default App; diff --git a/frontend/src/components/modals/JsonUploadModal.tsx b/frontend/src/components/modals/JsonUploadModal.tsx new file mode 100644 index 0000000..1cb541b --- /dev/null +++ b/frontend/src/components/modals/JsonUploadModal.tsx @@ -0,0 +1,161 @@ +import { useState, useRef } from 'react'; + +interface JsonUploadModalProps { + isOpen: boolean; + onClose: () => void; + onUpload: (data: any) => void; + game: string; +} + +const JsonUploadModal = ({ isOpen, onClose, onUpload, game }: JsonUploadModalProps) => { + const [file, setFile] = useState(null); + const [error, setError] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const fileInputRef = useRef(null); + + if (!isOpen) return null; + + const handleFileChange = (e: React.ChangeEvent) => { + const selectedFile = e.target.files?.[0]; + setError(''); + + if (selectedFile) { + if (!selectedFile.name.endsWith('.json')) { + setError('Please select a JSON file'); + return; + } + setFile(selectedFile); + } + }; + + const handleUpload = async () => { + if (!file) { + setError('Please select a file to upload'); + return; + } + + setIsLoading(true); + setError(''); + + try { + const text = await file.text(); + const data = JSON.parse(text); + onUpload(data); + setFile(null); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + onClose(); + } catch (err) { + if (err instanceof SyntaxError) { + setError('Invalid JSON file format'); + } else { + setError('Failed to process file. Please try again.'); + } + } finally { + setIsLoading(false); + } + }; + + const handleClose = () => { + setFile(null); + setError(''); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + onClose(); + }; + + return ( +
+ {/* Backdrop */} +
+ + {/* Modal */} +
+
+ {/* Header */} +
+

Import {game} Data

+

Upload your game data in JSON format

+
+ + {/* File Upload Area */} +
+ +
+ + {/* Error Message */} + {error && ( +
+

{error}

+
+ )} + + {/* Actions */} +
+ + +
+
+
+
+ ); +}; + +export default JsonUploadModal; diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index 1d87c8a..e42a2b8 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -66,6 +66,12 @@ const Home = () => { Mirage
+ + Import Data + Welcome back, {user.username} +
+ + + + + {/* Main Content */} +
+ {/* Header */} +
+

Import Data

+

Import your game scores and progress from various sources

+
+ + {/* Status Message */} + {uploadStatus.type && ( +
+

+ {uploadStatus.message} +

+
+ )} + + {/* Game Selection Card */} +
+
+

Select Game

+

+ Choose the game you want to import data for +

+ + {gamesLoading ? ( +
+
+
+ Loading games... +
+
+ ) : ( + + )} +
+ + {/* Import Options */} + {selectedGame && ( +
+

Import Options

+ +
+ {/* JSON Upload Card */} +
+
+ + + +
+

Batch-Manual Upload

+

+ Upload your game data from a Mirage compatible JSON file +

+ +
+
+
+ )} +
+
+ + {/* JSON Upload Modal */} + setIsJsonModalOpen(false)} + onUpload={handleJsonUpload} + game={supportedGames.find(g => g.internalName === selectedGame)?.formattedName || ''} + /> + + ); +}; + +export default Import; -- cgit v1.2.3