🎨 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="theme-color" content="#000000" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
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" />
|
<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.
|
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`.
|
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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
20
src/App.js
20
src/App.js
@ -9,10 +9,25 @@ import ConsoleList from './page_elements/ConsoleList';
|
|||||||
import GameList from './page_elements/GameList';
|
import GameList from './page_elements/GameList';
|
||||||
import GamePlayer from './page_elements/GamePlayer';
|
import GamePlayer from './page_elements/GamePlayer';
|
||||||
import Topbar from './page_elements/Topbar';
|
import Topbar from './page_elements/Topbar';
|
||||||
|
import {createTheme, ThemeProvider } from '@mui/material/styles';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
var API_URL = process.env.VIDEOGAME_API_URL
|
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() {
|
function App() {
|
||||||
console.log(API_URL);
|
console.log(API_URL);
|
||||||
const [gameId, setGameId] = React.useState(0);
|
const [gameId, setGameId] = React.useState(0);
|
||||||
@ -43,8 +58,9 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<Topbar/>
|
<ThemeProvider theme={dacula_theme}>
|
||||||
<Router/>
|
<Router/>
|
||||||
|
</ThemeProvider>
|
||||||
</>
|
</>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,14 +34,9 @@ export default function ConsoleCard(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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>
|
<CardActionArea>
|
||||||
<CardMedia
|
|
||||||
component="img"
|
|
||||||
height="140"
|
|
||||||
image={placeholder}
|
|
||||||
alt="green iguana"
|
|
||||||
/>
|
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography gutterBottom variant="h5" component="div">
|
<Typography gutterBottom variant="h5" component="div">
|
||||||
{game_console}
|
{game_console}
|
||||||
|
@ -6,6 +6,9 @@ import ConsoleCard from './ConsoleCard';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { LinearProgress } from '@mui/material';
|
import { LinearProgress } from '@mui/material';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function ConsoleList(props) {
|
function ConsoleList(props) {
|
||||||
const [game_consoles, setGameConsoles] = React.useState([]);
|
const [game_consoles, setGameConsoles] = React.useState([]);
|
||||||
@ -42,16 +45,26 @@ function ConsoleList(props) {
|
|||||||
|
|
||||||
if (!has_loaded){
|
if (!has_loaded){
|
||||||
return (
|
return (
|
||||||
<div style={{display: "flex", flexWrap:"wrap", flexDirection:"row", justifyContent:"center"}}>
|
<div style={{display: "flex", flexWrap:"wrap", flexDirection:"row", alignItems:"center", justifyContent:"center"}}>
|
||||||
<LinearProgress />
|
<LinearProgress />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
return (
|
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}
|
{game_consoles}
|
||||||
</div>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,24 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Card from '@mui/material/Card';
|
import Card from '@mui/material/Card';
|
||||||
import CardContent from '@mui/material/CardContent';
|
import CardContent from '@mui/material/CardContent';
|
||||||
import CardMedia from '@mui/material/CardMedia';
|
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import { CardActionArea } from '@mui/material';
|
import { CardActionArea } from '@mui/material';
|
||||||
import placeholder from '../images/placeholder.jpg';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
export default function GameCard(props) {
|
export default function GameCard(props) {
|
||||||
const game_name = props.name;
|
const game_name = props.name;
|
||||||
const game_id = props.id;
|
const game_id = props.id;
|
||||||
const liste = true;
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
if (liste) {
|
|
||||||
return (
|
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>
|
<CardActionArea>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography gutterBottom variant="h5" component="div">
|
<Typography gutterBottom variant="h5" component="div" sx={{textAlign:"center"}}>
|
||||||
{game_name}
|
{game_name}
|
||||||
</Typography>
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</CardActionArea>
|
</CardActionArea>
|
||||||
</Card>
|
</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/500.css';
|
||||||
import '@fontsource/roboto/700.css';
|
import '@fontsource/roboto/700.css';
|
||||||
import * as React from 'react';
|
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 axios from 'axios';
|
||||||
import GameCard from './GameCard';
|
import GameCard from './GameCard';
|
||||||
|
import {TextField} from '@mui/material';
|
||||||
import { useParams } from 'react-router-dom';
|
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 console_rom = JSON.parse(localStorage.getItem(rom_name));
|
||||||
let game_components = []
|
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) {
|
for (const roms of console_rom) {
|
||||||
const card = <GameCard id={roms["id"]} name={roms["name"]} console_id={console_id} />
|
const card = <GameCard id={roms["id"]} name={roms["name"]} console_id={console_id} />
|
||||||
game_components.push(card);
|
game_components.push(card);
|
||||||
}
|
}
|
||||||
return game_components;
|
return game_components;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function GameList(props) {
|
function GameList(props) {
|
||||||
const [game_consoles, setGameConsoles] = React.useState([]);
|
const [game_consoles, setGameConsoles] = React.useState([]);
|
||||||
const [has_loaded, setHasLoaded] = React.useState(false);
|
const [has_loaded, setHasLoaded] = React.useState(false);
|
||||||
const game_components = []
|
const [search_filter, setSearchFilter] = React.useState("");
|
||||||
const params = useParams()
|
const [current_page, setCurrentPage] = React.useState(0);
|
||||||
let console_id = params.consoleId;
|
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 rom_name = "rom" + props.id;
|
||||||
let console_rom = JSON.parse(localStorage.getItem(rom_name));
|
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')
|
axios.get('https://videogamedb.simailadjalim.fr/consoles/'+ console_id + '/roms')
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
localStorage.setItem(rom_name,JSON.stringify(result.data));
|
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) {
|
for (const roms of result.data) {
|
||||||
const card = <GameCard id={roms["id"]} name={roms["name"]} console_id={console_id} />
|
const card = <GameCard id={roms["id"]} name={roms["name"]} console_id={console_id} />
|
||||||
game_components.push(card);
|
game_components.push(card);
|
||||||
@ -46,24 +65,65 @@ function GameList(props) {
|
|||||||
})
|
})
|
||||||
}else{
|
}else{
|
||||||
console.log("loading roms from cache");
|
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);
|
setGameConsoles(game_components);
|
||||||
setHasLoaded(true);
|
setHasLoaded(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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){
|
if (!has_loaded){
|
||||||
return <>
|
return <Box
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
justifyContent="center"
|
||||||
|
padding="1rem"
|
||||||
|
>
|
||||||
<br/>
|
<br/>
|
||||||
<CircularProgress/>
|
<CircularProgress/>
|
||||||
</>
|
</Box>
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
let shown = game_consoles.slice(current_page*itemPerPage,current_page*itemPerPage+itemPerPage)
|
||||||
return (
|
return (
|
||||||
<div style={{display: "flex", flexDirection: "column", flexWrap: "wrap"}}>
|
<Box
|
||||||
<p>Jeux</p>
|
display="flex"
|
||||||
{game_consoles}
|
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>
|
</div>
|
||||||
|
<NavigationButtons/>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,22 @@ import Button from '@mui/material/Button';
|
|||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default function GamePlayer(props) {
|
export default function GamePlayer(props) {
|
||||||
const [game, setGame] = React.useState(null);
|
const [game, setGame] = React.useState(null);
|
||||||
|
const [console_core,setConsoleCore] = React.useState(null);
|
||||||
var game_id = props.id;
|
var game_id = props.id;
|
||||||
var console_core = JSON.parse(localStorage.getItem("console"+props.consoleId)).core;
|
var current_console = JSON.parse(localStorage.getItem("console"+props.consoleId));
|
||||||
console.log(console_core);
|
|
||||||
|
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) => {
|
axios.get('https://videogamedb.simailadjalim.fr/roms/' + game_id).then((result) => {
|
||||||
setGame(result.data["name"]);
|
setGame(result.data["name"]);
|
||||||
})
|
})
|
||||||
|
@ -8,6 +8,9 @@ import Typography from '@mui/material/Typography';
|
|||||||
import InputBase from '@mui/material/InputBase';
|
import InputBase from '@mui/material/InputBase';
|
||||||
import MenuIcon from '@mui/icons-material/Menu';
|
import MenuIcon from '@mui/icons-material/Menu';
|
||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Search = styled('div')(({ theme }) => ({
|
const Search = styled('div')(({ theme }) => ({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
@ -52,10 +55,11 @@ const StyledInputBase = styled(InputBase)(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
export default function Topbar() {
|
export default function Topbar() {
|
||||||
|
const navigate = useNavigate();
|
||||||
return (
|
return (
|
||||||
<Box sx={{ flexGrow: 1 }}>
|
<Box sx={{ flexGrow: 1, marginBottom:"1rem" }}>
|
||||||
<AppBar position="static">
|
<AppBar position="static">
|
||||||
<Toolbar>
|
<Toolbar >
|
||||||
<IconButton
|
<IconButton
|
||||||
size="large"
|
size="large"
|
||||||
edge="start"
|
edge="start"
|
||||||
@ -69,6 +73,7 @@ export default function Topbar() {
|
|||||||
variant="h6"
|
variant="h6"
|
||||||
noWrap
|
noWrap
|
||||||
component="div"
|
component="div"
|
||||||
|
onClick={()=> navigate("/") }
|
||||||
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
|
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
|
||||||
>
|
>
|
||||||
Gros site de retrogaming bien legal la
|
Gros site de retrogaming bien legal la
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import GameList from "../page_elements/GameList";
|
import GameList from "../page_elements/GameList";
|
||||||
import {useParams} from 'react-router-dom';
|
import {useParams} from 'react-router-dom';
|
||||||
|
import Topbar from '../page_elements/Topbar';
|
||||||
|
|
||||||
export default function ConsolePage(){
|
export default function ConsolePage(){
|
||||||
|
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
return <>
|
return <>
|
||||||
|
<Topbar/>
|
||||||
<GameList id={params.consoleId} />
|
<GameList id={params.consoleId} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import GamePlayer from "../page_elements/GamePlayer";
|
import GamePlayer from "../page_elements/GamePlayer";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
import Topbar from '../page_elements/Topbar';
|
||||||
|
|
||||||
|
|
||||||
export default function GamePage() {
|
export default function GamePage() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
let gameId = params.gameId;
|
let gameId = params.gameId;
|
||||||
let consoleId = params.consoleId;
|
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 ConsoleList from "../page_elements/ConsoleList";
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
import Topbar from '../page_elements/Topbar';
|
||||||
|
|
||||||
|
|
||||||
export function HomePage(){
|
export function HomePage(){
|
||||||
return <>
|
return <>
|
||||||
|
<Topbar/>
|
||||||
<Typography
|
<Typography
|
||||||
variant="h3"
|
variant="h3"
|
||||||
noWrap
|
|
||||||
component="div"
|
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.
|
Bienvenue sur le site dont tu ne dois pas partager l'existance.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
Loading…
Reference in New Issue
Block a user