Moved to next js ssr (with fixes)
This commit is contained in:
@@ -1,16 +1,262 @@
|
||||
'use client';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Box, LinearProgress } from '@mui/material';
|
||||
import React from 'react';
|
||||
import {
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
Box,
|
||||
Container,
|
||||
Divider,
|
||||
Grid2,
|
||||
Link,
|
||||
List,
|
||||
ListItem,
|
||||
Paper,
|
||||
Typography,
|
||||
Theme,
|
||||
} from '@mui/material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { ArrowBack, ExpandMore } from '@mui/icons-material';
|
||||
import { IconUrl } from '@/src/core/api';
|
||||
import { IMod } from '@/src/types/Imod';
|
||||
import { Irace } from '@/src/types/Irace';
|
||||
import '@/src/css/Unit.css';
|
||||
import { IRaceUnits, IUnitShort } from '@/src/types/IUnitShort';
|
||||
import { IBuildingShort, IRaceBuildings } from '@/src/types/IBuildingShort';
|
||||
import { StyledLink } from '@/src/commons/StyledLink';
|
||||
import { BackButton } from '@/src/commons/BackButton';
|
||||
|
||||
const RacePageLegacy = dynamic(() => import('@/src/legacy-pages/RacePageFast'), {
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 8 }}>
|
||||
<LinearProgress sx={{ width: '200px' }} />
|
||||
</Box>
|
||||
),
|
||||
});
|
||||
const SectionTitle = styled(Typography)(({ theme }) => ({
|
||||
fontWeight: 700,
|
||||
mb: 2,
|
||||
fontSize: '1.25rem',
|
||||
}));
|
||||
|
||||
export default function RacePageClient() {
|
||||
return <RacePageLegacy />;
|
||||
const UnitCard = styled(Paper)(({ theme }) => ({
|
||||
background: theme.palette.mode === 'dark'
|
||||
? 'linear-gradient(145deg, #1a1a2e 0%, #16213e 100%)'
|
||||
: 'linear-gradient(145deg, #ffffff 0%, #f5f5f5 100%)',
|
||||
border: `1px solid ${theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'}`,
|
||||
borderRadius: '16px',
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
'&:hover': {
|
||||
boxShadow: theme.palette.mode === 'dark' ? '0 20px 40px rgba(255, 255, 255, 0.1)' : '0 20px 40px rgba(0, 0, 0, 0.2)',
|
||||
borderColor: theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.3)',
|
||||
},
|
||||
}));
|
||||
|
||||
const BuildingCard = styled(UnitCard)(({ theme }) => ({
|
||||
padding: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const UnitLink = styled(Link)(({ theme }) => ({
|
||||
color: theme.palette.text.primary,
|
||||
textDecoration: 'none',
|
||||
display: 'block',
|
||||
'&:hover': { color: theme.palette.mode === 'dark' ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)' }
|
||||
}));
|
||||
|
||||
const LoadingText = styled(Typography)(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
}));
|
||||
|
||||
function Unit(unit: IUnitShort, modId: number, raceId: string, theme: Theme) { const isDark = theme.palette.mode === 'dark';
|
||||
|
||||
return (
|
||||
<UnitLink href={"/mod/" + modId + "/race/" + raceId + "/unit/" + unit.id}>
|
||||
<ListItem sx={{
|
||||
color: theme.palette.text.primary,
|
||||
padding: '1.5rem 2rem',
|
||||
marginBottom: '0.5rem',
|
||||
background: isDark
|
||||
? 'linear-gradient(145deg, #1a1a2e 0%, #16213e 100%)'
|
||||
: 'linear-gradient(145deg, #ffffff 0%, #f5f5f5 100%)',
|
||||
borderRadius: '16px',
|
||||
border: `1px solid ${isDark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'}`,
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
'&:hover': {
|
||||
boxShadow: isDark ? '0 20px 40px rgba(255, 255, 255, 0.1)' : '0 20px 40px rgba(0, 0, 0, 0.2)',
|
||||
borderColor: isDark ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.3)',
|
||||
}
|
||||
}}>
|
||||
{unit.icon && <img className="unitIcon" src={IconUrl + unit.icon.replaceAll('\\', '/')} />}
|
||||
{unit.name}
|
||||
{unit.canDetect && <span> <img style={{ verticalAlign: "top" }}
|
||||
src="/images/DETECT_YES.webp" /></span>}
|
||||
</ListItem>
|
||||
</UnitLink>
|
||||
)
|
||||
}
|
||||
|
||||
function UnitSmall(unit: IUnitShort, modId: number, raceId: string) {
|
||||
var unitName = ""
|
||||
if (unit.name.length > 21) {
|
||||
unitName = unit.name.substring(0, 19) + "...";
|
||||
} else {
|
||||
unitName = unit.name;
|
||||
}
|
||||
|
||||
return (<StyledLink href={"/mod/" + modId + "/race/" + raceId + "/unit/" + unit.id} >
|
||||
{unit.icon && <img className="unitIconSmall" src={IconUrl + unit.icon.replaceAll('\\', '/')} />}
|
||||
<span style={{ fontSize: 14 }}>{unitName}</span>
|
||||
{unit.canDetect && <span> <img
|
||||
src="/images/DETECT_YES.webp" /></span>}<br /></StyledLink>)
|
||||
}
|
||||
|
||||
function Building(building: IBuildingShort, modId: number, raceId: string, theme: Theme) {
|
||||
const isDark = theme.palette.mode === 'dark';
|
||||
|
||||
return (<Grid2 size={{ xs: 12, md: 3 }}>
|
||||
<Link href={"/mod/" + modId + "/race/" + raceId + "/building/" + building.id} sx={{
|
||||
textDecoration: 'none',
|
||||
display: 'block',
|
||||
'&:hover': { color: isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)' }
|
||||
}}>
|
||||
<BuildingCard elevation={0}>
|
||||
<ListItem sx={{}}>
|
||||
{building.icon && <img className="unitIcon" src={IconUrl + building.icon.replaceAll('\\', '/')} />}
|
||||
<StyledLink>{building.name}</StyledLink>
|
||||
{building.canDetect && <span> <img style={{ verticalAlign: "top" }}
|
||||
src="/images/DETECT_YES.webp" /></span>}
|
||||
</ListItem>
|
||||
{building.units.map(unit => UnitSmall(unit, modId, raceId))}
|
||||
</BuildingCard>
|
||||
</Link>
|
||||
</Grid2>)
|
||||
}
|
||||
|
||||
interface UnitsProps {
|
||||
raceId: string;
|
||||
modId: number;
|
||||
units: IRaceUnits | null;
|
||||
buildings: IRaceBuildings | null;
|
||||
}
|
||||
|
||||
function Units({ raceId, modId, units, buildings }: UnitsProps) {
|
||||
const theme = useTheme();
|
||||
const isDark = theme.palette.mode === 'dark';
|
||||
|
||||
if (units) {
|
||||
const accordionSx = isDark ? {
|
||||
background: 'linear-gradient(145deg, #1a1a2e 0%, #16213e 100%)',
|
||||
border: '1px solid rgba(255, 255, 255, 0.1)',
|
||||
borderRadius: '12px',
|
||||
'&:before': { display: 'none' },
|
||||
'&.Mui-expanded': { margin: '0 0 8px 0' },
|
||||
} : {
|
||||
background: 'linear-gradient(145deg, #ffffff 0%, #f5f5f5 100%)',
|
||||
border: '1px solid rgba(0, 0, 0, 0.1)',
|
||||
borderRadius: '12px',
|
||||
'&:before': { display: 'none' },
|
||||
'&.Mui-expanded': { margin: '0 0 8px 0' },
|
||||
};
|
||||
|
||||
return (buildings != null ?
|
||||
<Box>
|
||||
<Grid2 container spacing={2}>
|
||||
{buildings.buildings.map(building => Building(building, modId, raceId, theme))}
|
||||
</Grid2>
|
||||
{buildings.buildingsAdvanced.length > 0 && <Box sx={{ mt: 3 }}>
|
||||
<Divider sx={{ my: 2, borderColor: isDark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)' }} />
|
||||
<SectionTitle>Advanced buildings</SectionTitle>
|
||||
<Grid2 container spacing={2}>
|
||||
{buildings.buildingsAdvanced.map(building => Building(building, modId, raceId, theme))}
|
||||
</Grid2><br /></Box>}
|
||||
<Box sx={{ mt: 3 }}>
|
||||
<Accordion sx={accordionSx}>
|
||||
<AccordionSummary
|
||||
expandIcon={<ExpandMore sx={{ color: isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)' }} />}
|
||||
aria-controls="units-accordion"
|
||||
id="units-accordion"
|
||||
sx={{ color: isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)', '& .MuiAccordionSummary-content': { margin: '12px 0' }, '& .MuiAccordionSummary-content.Mui-expanded': { margin: '12px 0' } }}
|
||||
>
|
||||
<SectionTitle sx={{ mb: 0, display: 'flex', alignItems: 'center' }}>All units</SectionTitle>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Grid2 container spacing={2}>
|
||||
<Grid2 size={{ xs: 12, md: 4 }}>
|
||||
<Typography variant="h6" sx={{ color: isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)', fontWeight: 600, mb: 2 }}>Infantry</Typography>
|
||||
{units.infantry.map(unit => Unit(unit, modId, raceId, theme))}
|
||||
</Grid2>
|
||||
<Grid2 size={{ xs: 12, md: 4 }}>
|
||||
<Typography variant="h6" sx={{ color: isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)', fontWeight: 600, mb: 2 }}>Tech</Typography>
|
||||
<List>
|
||||
{units.tech.map(unit => Unit(unit, modId, raceId, theme))}
|
||||
</List>
|
||||
</Grid2>
|
||||
<Grid2 size={{ xs: 12, md: 4 }}>
|
||||
<Typography variant="h6" sx={{ color: isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)', fontWeight: 600, mb: 2 }}>Support</Typography>
|
||||
<List>
|
||||
{units.support.map(unit => Unit(unit, modId, raceId, theme))}
|
||||
</List>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</Box>
|
||||
</Box> : <LoadingText>Loading</LoadingText>
|
||||
)
|
||||
} else {
|
||||
return <LoadingText>Loading...</LoadingText>;
|
||||
}
|
||||
}
|
||||
|
||||
interface RacePageClientProps {
|
||||
initialMod: IMod | null;
|
||||
initialRace: Irace | null;
|
||||
raceUnits: IRaceUnits | null;
|
||||
raceBuildings: IRaceBuildings | null;
|
||||
}
|
||||
|
||||
export default function RacePageClient({ initialMod, initialRace, raceUnits, raceBuildings }: RacePageClientProps) {
|
||||
const theme = useTheme();
|
||||
|
||||
if (initialMod != null && initialRace != null) {
|
||||
const backRef = "/mod/" + initialMod.id;
|
||||
const isDark = theme.palette.mode === 'dark';
|
||||
|
||||
return (
|
||||
<Container maxWidth="lg">
|
||||
<BackButton
|
||||
variant="outlined"
|
||||
startIcon={<ArrowBack />}
|
||||
href={backRef}
|
||||
>
|
||||
Back to mod
|
||||
</BackButton>
|
||||
|
||||
<Box sx={{ mb: 4 }}>
|
||||
<Typography variant="h3" component="h1" sx={{
|
||||
fontWeight: 800,
|
||||
mb: 1,
|
||||
background: isDark
|
||||
? 'linear-gradient(135deg, #dee2e6 0%, #e0e0e0 100%)'
|
||||
: 'none',
|
||||
WebkitBackgroundClip: isDark ? 'text' : 'initial',
|
||||
WebkitTextFillColor: isDark ? '#dee2e6' : 'initial',
|
||||
color: isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)',
|
||||
}}>
|
||||
{initialRace.name}
|
||||
</Typography>
|
||||
<Typography variant="h6" sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
fontWeight: 500,
|
||||
}}>
|
||||
{initialMod.name} ({initialMod.version})
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Units raceId={initialRace.id} modId={initialMod.id} units={raceUnits} buildings={raceBuildings} />
|
||||
</Container>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Container maxWidth="lg">
|
||||
<LoadingText variant="h5" sx={{ py: 8, textAlign: 'center' }}>
|
||||
Race not found
|
||||
</LoadingText>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user