🎨 style(index.html): update meta description and title for better SEO and user experience
🔧 refactor(App.js): introduce MUI theme for dark mode and improve code readability 🔧 refactor(ConsoleCard.js): remove image and center text for better UI 🔧 refactor(ConsoleList.js): use MUI Box for better layout and code readability 🔧 refactor(GameCard.js): remove unused code and center text for better UI 🔧 refactor(GameList.js): add search and pagination functionality for better UX 🔧 refactor(GamePlayer.js): improve game loading logic and code readability 🔧 refactor(Topbar.js): add navigation to home on title click for better UX 🔧 refactor(ConsolePage.jsx, GamePage.jsx, HomePage.jsx): add Topbar for consistent navigation across pages
This commit is contained in:
parent
1dcc6f00f5
commit
5c54c73a56
@ -7,7 +7,7 @@
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
content="Gros site bien legal la, bien nintendo friendly, on a que de la joie ici, PTDR"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
@ -24,7 +24,7 @@
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>Site de Retrogaming legal</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
24
src/App.js
24
src/App.js
@ -9,10 +9,25 @@ import ConsoleList from './page_elements/ConsoleList';
|
||||
import GameList from './page_elements/GameList';
|
||||
import GamePlayer from './page_elements/GamePlayer';
|
||||
import Topbar from './page_elements/Topbar';
|
||||
|
||||
import {createTheme, ThemeProvider } from '@mui/material/styles';
|
||||
import * as React from 'react';
|
||||
var API_URL = process.env.VIDEOGAME_API_URL
|
||||
|
||||
|
||||
const dacula_theme = createTheme({
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
primary: {
|
||||
main: '#bd93f9',
|
||||
},
|
||||
background: {
|
||||
paper: '#44475a',
|
||||
default: '#282a36',
|
||||
},
|
||||
divider: '#44475a',
|
||||
},
|
||||
})
|
||||
|
||||
function App() {
|
||||
console.log(API_URL);
|
||||
const [gameId, setGameId] = React.useState(0);
|
||||
@ -43,10 +58,11 @@ function App() {
|
||||
}
|
||||
|
||||
return <>
|
||||
<Topbar/>
|
||||
<Router/>
|
||||
<ThemeProvider theme={dacula_theme}>
|
||||
<Router/>
|
||||
</ThemeProvider>
|
||||
</>
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
@ -34,14 +34,9 @@ export default function ConsoleCard(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<Card style={{margin: "10px"}} onClick={() => navigate("/console/"+game_console_id)} sx={{ width: 250 }}>
|
||||
<Card onClick={() => navigate("/console/"+game_console_id)}
|
||||
sx={{ width: 250, margin: "10px", textAlign:"center" }}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="140"
|
||||
image={placeholder}
|
||||
alt="green iguana"
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
{game_console}
|
||||
|
@ -6,6 +6,9 @@ import ConsoleCard from './ConsoleCard';
|
||||
import axios from 'axios';
|
||||
import * as React from 'react';
|
||||
import { LinearProgress } from '@mui/material';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
|
||||
|
||||
function ConsoleList(props) {
|
||||
const [game_consoles, setGameConsoles] = React.useState([]);
|
||||
@ -14,7 +17,7 @@ function ConsoleList(props) {
|
||||
|
||||
if (!has_loaded){
|
||||
let consoles = JSON.parse(localStorage.getItem("consoles"));
|
||||
|
||||
|
||||
if (consoles !== null) {
|
||||
console.log("loaded cache");
|
||||
for (const game_console of consoles) {
|
||||
@ -42,16 +45,26 @@ function ConsoleList(props) {
|
||||
|
||||
if (!has_loaded){
|
||||
return (
|
||||
<div style={{display: "flex", flexWrap:"wrap", flexDirection:"row", justifyContent:"center"}}>
|
||||
<div style={{display: "flex", flexWrap:"wrap", flexDirection:"row", alignItems:"center", justifyContent:"center"}}>
|
||||
<LinearProgress />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else{
|
||||
return (
|
||||
<div style={{display: "flex", flexWrap:"wrap", flexDirection:"row", justifyContent:"center"}}>
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="row"
|
||||
flexWrap="wrap"
|
||||
justifyContent="center"
|
||||
flex="1 0 21%"
|
||||
alignItems="center"
|
||||
gap={1}
|
||||
p={2}
|
||||
sx={{
|
||||
}}>
|
||||
{game_consoles}
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +1,24 @@
|
||||
import * as React from 'react';
|
||||
import Card from '@mui/material/Card';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
import CardMedia from '@mui/material/CardMedia';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { CardActionArea } from '@mui/material';
|
||||
import placeholder from '../images/placeholder.jpg';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export default function GameCard(props) {
|
||||
const game_name = props.name;
|
||||
const game_id = props.id;
|
||||
const liste = true;
|
||||
const navigate = useNavigate();
|
||||
|
||||
if (liste) {
|
||||
return (
|
||||
<Card sx={{ }} style={{margin:"20px"}} onClick={ ()=> navigate("/console/"+props.console_id+"/"+game_id)}>
|
||||
<Card sx={{margin:"20px", flexGrow:1}} onClick={ ()=> navigate("/console/"+props.console_id+"/"+game_id)}>
|
||||
<CardActionArea>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
<Typography gutterBottom variant="h5" component="div" sx={{textAlign:"center"}}>
|
||||
{game_name}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Card sx={{ maxWidth: 150 }} style={{margin:"20px"}}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="140"
|
||||
image={placeholder}
|
||||
alt="green iguana"
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
{game_name}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,30 +3,47 @@ import '@fontsource/roboto/400.css';
|
||||
import '@fontsource/roboto/500.css';
|
||||
import '@fontsource/roboto/700.css';
|
||||
import * as React from 'react';
|
||||
import { CircularProgress, Popover } from '@mui/material';
|
||||
import { CircularProgress, Button,Typography,Box } from '@mui/material';
|
||||
import Pagination from '@mui/material/Pagination';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import axios from 'axios';
|
||||
import GameCard from './GameCard';
|
||||
import {TextField} from '@mui/material';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useSearchParams, useNavigate } from "react-router-dom";
|
||||
|
||||
|
||||
async function loadgamesfromlocalstorage(rom_name,console_id){
|
||||
var itemPerPage = 50;
|
||||
|
||||
async function loadgamesfromlocalstorage(rom_name,console_id,filter){
|
||||
let console_rom = JSON.parse(localStorage.getItem(rom_name));
|
||||
let game_components = []
|
||||
console_rom = console_rom.filter(roms => roms["name"].toLowerCase().includes(filter.toLowerCase()))
|
||||
console_rom.sort((a,b) => a["name"].localeCompare(b["name"]))
|
||||
for (const roms of console_rom) {
|
||||
const card = <GameCard id={roms["id"]} name={roms["name"]} console_id={console_id} />
|
||||
game_components.push(card);
|
||||
}
|
||||
return game_components;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function GameList(props) {
|
||||
const [game_consoles, setGameConsoles] = React.useState([]);
|
||||
const [has_loaded, setHasLoaded] = React.useState(false);
|
||||
const game_components = []
|
||||
const params = useParams()
|
||||
let console_id = params.consoleId;
|
||||
const [search_filter, setSearchFilter] = React.useState("");
|
||||
const [current_page, setCurrentPage] = React.useState(0);
|
||||
let [searchParams, setSearchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
console.log(searchParams);
|
||||
let filter = "";
|
||||
|
||||
if (searchParams.get("q") !== null){
|
||||
filter = searchParams.get("q");
|
||||
}
|
||||
console.log(filter);
|
||||
const game_components = [];
|
||||
const params = useParams();
|
||||
let console_id = params.consoleId;
|
||||
|
||||
let rom_name = "rom" + props.id;
|
||||
let console_rom = JSON.parse(localStorage.getItem(rom_name));
|
||||
@ -37,6 +54,8 @@ function GameList(props) {
|
||||
axios.get('https://videogamedb.simailadjalim.fr/consoles/'+ console_id + '/roms')
|
||||
.then((result) => {
|
||||
localStorage.setItem(rom_name,JSON.stringify(result.data));
|
||||
result.data = result.data.filter(roms => roms["name"].includes(filter));
|
||||
result.data.sort((a,b) => a["name"].localeCompare(b["name"]))
|
||||
for (const roms of result.data) {
|
||||
const card = <GameCard id={roms["id"]} name={roms["name"]} console_id={console_id} />
|
||||
game_components.push(card);
|
||||
@ -46,24 +65,65 @@ function GameList(props) {
|
||||
})
|
||||
}else{
|
||||
console.log("loading roms from cache");
|
||||
loadgamesfromlocalstorage(rom_name,props.id).then(game_components =>{
|
||||
loadgamesfromlocalstorage(rom_name,props.id,filter).then(game_components =>{
|
||||
setGameConsoles(game_components);
|
||||
setHasLoaded(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!has_loaded){
|
||||
return <>
|
||||
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
// 👇 Get input value
|
||||
setSearchParams({"q" : search_filter});
|
||||
navigate(0);
|
||||
}
|
||||
};
|
||||
|
||||
function NavigationButtons(){
|
||||
let len = (game_consoles.length - (game_consoles.length % itemPerPage)) / itemPerPage;
|
||||
console.log(len);
|
||||
|
||||
return (
|
||||
<Stack spacing={2} sx={{display:"flex",justifyContent:"center"}}>
|
||||
<Pagination count={len} page={current_page} onChange={(event,value)=>setCurrentPage(value)} />
|
||||
</Stack>)
|
||||
}
|
||||
|
||||
|
||||
if (!has_loaded){
|
||||
return <Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
justifyContent="center"
|
||||
padding="1rem"
|
||||
>
|
||||
<br/>
|
||||
<CircularProgress/>
|
||||
</>
|
||||
</Box>
|
||||
}
|
||||
else{
|
||||
let shown = game_consoles.slice(current_page*itemPerPage,current_page*itemPerPage+itemPerPage)
|
||||
return (
|
||||
<div style={{display: "flex", flexDirection: "column", flexWrap: "wrap"}}>
|
||||
<p>Jeux</p>
|
||||
{game_consoles}
|
||||
</div>
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
justifyContent="center"
|
||||
padding="1rem"
|
||||
>
|
||||
<TextField id="outlined-basic" label="Rechercher" variant="outlined" onKeyDown={handleKeyDown} sx={{marginBottom:"1rem"}} onChange={e => setSearchFilter(e.target.value)} />
|
||||
<NavigationButtons/>
|
||||
<Typography variant="h4"
|
||||
component="div"
|
||||
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' }, textAlign:"center", color:"white" }} >
|
||||
Jeux de cette console
|
||||
</Typography>
|
||||
<div style={{display: "flex", flexDirection: "row", flexWrap: "wrap", justifyContent:"space-evenly"}}>
|
||||
{shown}
|
||||
</div>
|
||||
<NavigationButtons/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,42 +4,51 @@ import Button from '@mui/material/Button';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
|
||||
|
||||
|
||||
export default function GamePlayer(props) {
|
||||
const [game, setGame] = React.useState(null);
|
||||
var game_id = props.id;
|
||||
var console_core = JSON.parse(localStorage.getItem("console"+props.consoleId)).core;
|
||||
console.log(console_core);
|
||||
axios.get('https://videogamedb.simailadjalim.fr/roms/' + game_id).then((result) => {
|
||||
setGame(result.data["name"]);
|
||||
})
|
||||
function handleDownload(){
|
||||
const fileUrl = 'https://videogamedb.simailadjalim.fr/roms/' + props.id + '?romfile=true';
|
||||
const link = document.createElement('a');
|
||||
link.href = fileUrl;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// Clean up the temporary URL and remove the <a> element
|
||||
document.body.removeChild(link);
|
||||
};
|
||||
return (
|
||||
<div style={{display: "flex",flexDirection:"column",alignItems:"center",width:"100%"}}>
|
||||
<h2>GamePlayer</h2>
|
||||
<h3>{game}</h3>
|
||||
<iframe
|
||||
title="EmulatorJS"
|
||||
src={"https://videogamedb.simailadjalim.fr/emulator?rom_id=" + game_id + "&console_core=" + console_core}
|
||||
width="640"
|
||||
height="480"
|
||||
allowFullScreen
|
||||
/>
|
||||
<Box sx={{
|
||||
paddingTop: "10px"
|
||||
}}>
|
||||
const [game, setGame] = React.useState(null);
|
||||
const [console_core,setConsoleCore] = React.useState(null);
|
||||
var game_id = props.id;
|
||||
var current_console = JSON.parse(localStorage.getItem("console"+props.consoleId));
|
||||
|
||||
</Box>
|
||||
<Button variant="contained" onClick={handleDownload}>Télécharger le jeu</Button>
|
||||
</div>
|
||||
);
|
||||
if (console_core == null) {
|
||||
if (current_console === null){
|
||||
axios.get('https://videogamedb.simailadjalim.fr/consoles/' + props.consoleId).then((result) => {
|
||||
localStorage.setItem("console"+props.consoleId,JSON.stringify(result.data));
|
||||
setConsoleCore(result.data["core"]);
|
||||
})
|
||||
}else{
|
||||
setConsoleCore(current_console.core);
|
||||
}
|
||||
}
|
||||
axios.get('https://videogamedb.simailadjalim.fr/roms/' + game_id).then((result) => {
|
||||
setGame(result.data["name"]);
|
||||
})
|
||||
function handleDownload(){
|
||||
const fileUrl = 'https://videogamedb.simailadjalim.fr/roms/' + props.id + '?romfile=true';
|
||||
const link = document.createElement('a');
|
||||
link.href = fileUrl;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// Clean up the temporary URL and remove the <a> element
|
||||
document.body.removeChild(link);
|
||||
};
|
||||
return (
|
||||
<div style={{display: "flex",flexDirection:"column",alignItems:"center",width:"100%"}}>
|
||||
<h2>GamePlayer</h2>
|
||||
<h3>{game}</h3>
|
||||
<iframe
|
||||
title="EmulatorJS"
|
||||
src={"https://videogamedb.simailadjalim.fr/emulator?rom_id=" + game_id + "&console_core=" + console_core}
|
||||
width="640"
|
||||
height="480"
|
||||
allowFullScreen
|
||||
/>
|
||||
<Box sx={{
|
||||
paddingTop: "10px"
|
||||
}}>
|
||||
|
||||
</Box>
|
||||
<Button variant="contained" onClick={handleDownload}>Télécharger le jeu</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import Typography from '@mui/material/Typography';
|
||||
import InputBase from '@mui/material/InputBase';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
|
||||
|
||||
const Search = styled('div')(({ theme }) => ({
|
||||
position: 'relative',
|
||||
@ -52,10 +55,11 @@ const StyledInputBase = styled(InputBase)(({ theme }) => ({
|
||||
}));
|
||||
|
||||
export default function Topbar() {
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Box sx={{ flexGrow: 1, marginBottom:"1rem" }}>
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<Toolbar >
|
||||
<IconButton
|
||||
size="large"
|
||||
edge="start"
|
||||
@ -69,6 +73,7 @@ export default function Topbar() {
|
||||
variant="h6"
|
||||
noWrap
|
||||
component="div"
|
||||
onClick={()=> navigate("/") }
|
||||
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
|
||||
>
|
||||
Gros site de retrogaming bien legal la
|
||||
|
@ -1,11 +1,12 @@
|
||||
import GameList from "../page_elements/GameList";
|
||||
import {useParams} from 'react-router-dom';
|
||||
|
||||
import Topbar from '../page_elements/Topbar';
|
||||
|
||||
export default function ConsolePage(){
|
||||
|
||||
const params = useParams();
|
||||
return <>
|
||||
<Topbar/>
|
||||
<GameList id={params.consoleId} />
|
||||
</>
|
||||
}
|
||||
|
@ -1,11 +1,15 @@
|
||||
import GamePlayer from "../page_elements/GamePlayer";
|
||||
import { useParams } from "react-router-dom";
|
||||
import Topbar from '../page_elements/Topbar';
|
||||
|
||||
|
||||
export default function GamePage() {
|
||||
const params = useParams();
|
||||
let gameId = params.gameId;
|
||||
let consoleId = params.consoleId;
|
||||
|
||||
return <GamePlayer id={gameId} consoleId={consoleId} />;
|
||||
|
||||
return <>
|
||||
<Topbar/>
|
||||
<GamePlayer id={gameId} consoleId={consoleId} />;
|
||||
</>
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
import ConsoleList from "../page_elements/ConsoleList";
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Topbar from '../page_elements/Topbar';
|
||||
|
||||
|
||||
export function HomePage(){
|
||||
return <>
|
||||
<Topbar/>
|
||||
<Typography
|
||||
variant="h3"
|
||||
noWrap
|
||||
component="div"
|
||||
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
|
||||
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' }, textAlign:"center", color:"white" }}
|
||||
>
|
||||
Bienvenue sur le site dont tu ne dois pas partager l'existance.
|
||||
</Typography>
|
||||
|
Loading…
Reference in New Issue
Block a user