diff options
author | Loek Le Blansch <32883851+lonkaars@users.noreply.github.com> | 2021-04-21 10:40:52 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-21 10:40:52 +0200 |
commit | dadc722875b2095bd3d6c4ab628a644197b85f7b (patch) | |
tree | 9e061708fad5bfdcc40f4c40662d77fbc42cfe64 /pages | |
parent | c603cb79e7ba7fdbb101a506e36f6d8d70b3a8f4 (diff) | |
parent | 5cb39d822716c650e520c3855ef049ff308a348c (diff) |
Merge pull request #12 from lonkaars/css-files
big redesign css move thing
Diffstat (limited to 'pages')
-rw-r--r-- | pages/_app.tsx | 14 | ||||
-rw-r--r-- | pages/game.tsx | 109 | ||||
-rw-r--r-- | pages/index.tsx | 153 | ||||
-rw-r--r-- | pages/login.tsx | 46 | ||||
-rw-r--r-- | pages/register.tsx | 40 | ||||
-rw-r--r-- | pages/search.tsx | 64 | ||||
-rw-r--r-- | pages/settings.tsx | 63 | ||||
-rw-r--r-- | pages/user.tsx | 456 |
8 files changed, 348 insertions, 597 deletions
diff --git a/pages/_app.tsx b/pages/_app.tsx index 0682a4d..c1347e8 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -7,6 +7,20 @@ import '../styles/dark.css'; import '../styles/disk.css'; import '../styles/footer.css'; import '../styles/global.css'; +import '../styles/navbar.css'; +import '../styles/notifications.css'; +import '../styles/recentGames.css'; +import '../styles/toast.css'; +import '../styles/ui.css'; +import '../styles/utility.css'; + +import '../styles/game.css'; +import '../styles/gameSettings.css'; +import '../styles/index.css'; +import '../styles/loginregister.css'; +import '../styles/search.css'; +import '../styles/settings.css'; +import '../styles/user.css'; export default function VierOpEenRijWebsite({ Component, pageProps }) { return <div> diff --git a/pages/game.tsx b/pages/game.tsx index b5200a7..de2c089 100644 --- a/pages/game.tsx +++ b/pages/game.tsx @@ -1,7 +1,7 @@ import Icon from '@mdi/react'; import axios from 'axios'; import copy from 'copy-to-clipboard'; -import { CSSProperties, useContext, useEffect, useState } from 'react'; +import { useContext, useEffect, useState } from 'react'; import * as cookies from 'react-cookies'; import { Socket } from 'socket.io-client'; import { SocketContext } from '../components/socketContext'; @@ -65,15 +65,7 @@ function VoerGame(props: { }); }, []); - return <div - style={{ - position: 'relative', - top: '50%', - transform: 'translateY(-50%)', - maxWidth: '100vh', - margin: '0 auto', - }} - > + return <div className='voerGame posrel abscenterv'> <VoerBord width={width} height={height} @@ -109,30 +101,22 @@ function GameOutcomeDialog(props: { }) { return <DialogBox title='Speluitkomst' - style={{ display: props.visible ? 'inline-block' : 'none' }} + hidden={!props.visible} + className='outcomeDialog' onclick={() => { window.history.replaceState(null, null, '/'); window.location.reload(); }} > - <div - style={{ - width: '100%', - textAlign: 'center', - }} - > + <div className='inner fullwidth center'> <h2 - style={{ - color: props.outcome == 0 - ? 'var(--text)' - : props.outcome == props.player - ? 'var(--disk-a-text)' - : props.outcome != props.player - ? 'var(--disk-b-text)' - : 'var(--text)', - opacity: props.outcome == 0 ? .75 : 1, - marginTop: 8, - }} + className={'outcome' + ' ' + (props.outcome == 0 + ? 'draw' + : props.outcome == props.player + ? 'lose' + : props.outcome != props.player + ? 'win' + : 'draw')} > {props.outcome == 0 ? 'Gelijkspel' @@ -142,7 +126,7 @@ function GameOutcomeDialog(props: { ? 'Gewonnen' : '???'} </h2> - {false && <p style={{ marginTop: 24 }}> + {false && <p className='analysis'> 0 Gemiste winstzetten<br /> 6 Optimale zetten<br /> 0 Blunders @@ -150,42 +134,11 @@ function GameOutcomeDialog(props: { {false && <IconLabelButton text='Opnieuw spelen' icon={<RefreshIcon />} - style={{ - float: 'none', - marginTop: 24, - padding: '12px 32px', - }} />} </div> </DialogBox>; } -var InviteButtonStyle: CSSProperties = { - backgroundColor: 'var(--page-background)', - height: 160, - padding: 12, -}; - -var InviteButtonIconStyle: CSSProperties = { - fontSize: 100, - position: 'absolute', - top: 12, - left: '50%', - transform: 'translateX(-50%)', -}; - -var InviteButtonLabelStyle: CSSProperties = { - position: 'absolute', - bottom: 12, - left: '50%', - transform: 'translateX(-50%)', - textAlign: 'center', - color: 'var(--text-alt)', - width: 136, - fontSize: 20, - userSelect: 'none', -}; - export default function GamePage() { var [gameID, setGameID] = useState(''); var [player1, setPlayer1] = useState(true); @@ -226,7 +179,7 @@ export default function GamePage() { return <div> <NavBar /> - <CenteredPage width={900} style={{ height: '100vh' }}> + <CenteredPage width={900} className='h100vh'> <VoerGame active={active} gameID={gameID} @@ -236,22 +189,16 @@ export default function GamePage() { /> <DialogBox title='Nieuw spel' - style={{ display: gameIDUrl || gameID ? 'none' : 'inline-block' }} + className='newGameDialog' + hidden={!!(gameIDUrl || gameID)} onclick={() => { window.history.go(-1); }} > <CurrentGameSettings /> - <div - style={{ - marginTop: 24, - display: 'grid', - gridTemplateColumns: '1fr 1fr', - gridGap: 24, - }} - > + <div className='sidebyside gg-l'> <Button - style={InviteButtonStyle} + className='inviteButton random pad-m' onclick={() => { axios.request<{ id: string; player_1: boolean; game_started: boolean; }>({ url: '/api/game/random', @@ -266,16 +213,11 @@ export default function GamePage() { .catch(() => {}); }} > - <WifiTetheringRoundedIcon - style={{ - color: 'var(--disk-b)', - ...InviteButtonIconStyle, - }} - /> - <h2 style={InviteButtonLabelStyle}>Willekeurige speler</h2> + <WifiTetheringRoundedIcon className='icon posabs abscenterh' /> + <h2 className='label center posabs abscenterh nosel'>Willekeurige speler</h2> </Button> <Button - style={InviteButtonStyle} + className='inviteButton link pad-m' onclick={() => { axios.request<{ id: string; }>({ method: 'post', @@ -300,13 +242,8 @@ export default function GamePage() { .catch(() => {}); }} > - <LinkRoundedIcon - style={{ - color: 'var(--disk-a)', - ...InviteButtonIconStyle, - }} - /> - <h2 style={InviteButtonLabelStyle}>Uitnodigen via link</h2> + <LinkRoundedIcon className='icon posabs abscenterh' /> + <h2 className='label center posabs abscenterh nosel'>Uitnodigen via link</h2> </Button> </div> <SearchBar label='Zoeken in vriendenlijst' /> diff --git a/pages/index.tsx b/pages/index.tsx index 354efc5..c4b4baf 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,5 +1,5 @@ import axios from 'axios'; -import { CSSProperties, useContext, useEffect, useState } from 'react'; +import { useContext, useEffect, useState } from 'react'; import { userGames, userGameTotals, userInfo } from '../api/api'; import { Footer } from '../components/footer'; import { SocketContext } from '../components/socketContext'; @@ -16,77 +16,14 @@ import VideogameAssetIcon from '@material-ui/icons/VideogameAsset'; import { mdiRobotExcited } from '@mdi/js'; import Icon from '@mdi/react'; -var GameModeIconStyle: CSSProperties = { - fontSize: 64, - width: 64, - height: 64, - display: 'inline-block', - position: 'absolute', - top: 24, - left: '50%', - transform: 'translateX(-50%)', -}; - -var GameModeTextStyle: CSSProperties = { - whiteSpace: 'nowrap', - display: 'inline-block', - position: 'absolute', - bottom: 24, - left: '50%', - transform: 'translateX(-50%)', - userSelect: 'none', - fontWeight: 500, -}; - -var SquareSize: CSSProperties = { - width: 90, - height: 90, -}; - -var LoginOrRegisterBoxStyle: CSSProperties = { - verticalAlign: 'top', - height: `calc(${SquareSize.height}px + 24px * 2)`, - width: '100%', - maxWidth: `calc(100% - ${SquareSize.width}px - 12px * 2 - 24px * 2)`, -}; - -var InnerLoginOrRegisterBoxStyle: CSSProperties = { - position: 'relative', - width: '100%', - height: '100%', -}; - function LoginOrRegisterBox() { - return <div style={{ ...InnerLoginOrRegisterBoxStyle, textAlign: 'center' }}> - <span - style={{ - userSelect: 'none', - display: 'inline-block', - position: 'absolute', - fontSize: 14, - left: 0, - right: 0, - top: 0, - margin: '0 auto', - minWidth: 240, - maxWidth: 350, - }} - > - Log in of maak een account aan om je scores op te slaan en toegang te krijgen tot meer functies + return <div className='inner'> + <span className='registerMessage posabs h0 t0'> + Log in of maak een account aan om toegang tot meer functies te krijgen </span> - <div - style={{ - display: 'grid', - gridGap: 24, - gridTemplateColumns: '1fr 1fr', - position: 'absolute', - left: 0, - right: 0, - bottom: 0, - }} - > - <Button href='/register' text='Registreren' style={{ backgroundColor: 'var(--background-alt)' }} /> - <Button href='/login' text='Inloggen' /> + <div className='sidebyside posabs h0 b0'> + <Button href='/register' text='Registreren' className='register' /> + <Button href='/login' text='Inloggen' className='login' /> </div> </div>; } @@ -95,44 +32,19 @@ function AccountBox(props: { info: userInfo; sumGameInfo: userGameTotals; }) { - return <div style={InnerLoginOrRegisterBoxStyle}> - <div - style={{ - position: 'absolute', - top: 0, - left: 0, - ...SquareSize, - }} - > + return <div className='inner profile'> + <div className='picture posabs l0 t0'> <AccountAvatar size={90} /> </div> - <div - style={{ - position: 'absolute', - top: 0, - left: 102, - width: 'calc(100% - 90px - 12px)', - height: '100%', - }} - > - <h2 - style={{ - maxWidth: 178, - fontSize: 20, - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }} - > - {props.info?.username} - </h2> - <p style={{ marginTop: 6 }}>Score: {props.info?.rating}</p> - <p style={{ position: 'absolute', bottom: 0, left: 0 }}> - <span style={{ color: 'var(--disk-b-text)' }}>{props.sumGameInfo?.win} W</span> - <span style={{ margin: '0 3px' }}>/</span> - <span style={{ color: 'var(--disk-a-text)' }}>{props.sumGameInfo?.lose} V</span> - <span style={{ margin: '0 3px' }}>/</span> - <span style={{ opacity: .75 }}>{props.sumGameInfo?.draw} G</span> + <div className='info posabs t0'> + <h2 className='username truncate'>{props.info?.username}</h2> + <p className='score'>Score: {props.info?.rating}</p> + <p className='games posabs b0 l0'> + <span className='outcome win'>{props.sumGameInfo?.win} W</span> + <span className='divider'>/</span> + <span className='outcome lose'>{props.sumGameInfo?.lose} V</span> + <span className='divider'>/</span> + <span className='outcome draw'>{props.sumGameInfo?.draw} G</span> </p> </div> </div>; @@ -180,35 +92,32 @@ export default function HomePage() { <NavBar /> <CenteredPage width={802}> <PageTitle>4 op een rij</PageTitle> - <div> - <Vierkant href='/game'> - <VideogameAssetIcon style={GameModeIconStyle} /> - <span style={GameModeTextStyle}>Nieuw spel</span> - <div style={SquareSize}></div> + <div className='topbar'> + <Vierkant className='gamemode bg-800' href='/game'> + <VideogameAssetIcon className='icon' /> + <span className='text'>Nieuw spel</span> </Vierkant> {false - && <Vierkant href='/'> - <ExtensionIcon style={GameModeIconStyle} /> - <span style={GameModeTextStyle}>Puzzels</span> - <div style={SquareSize}></div> + && <Vierkant className='gamemode bg-800' href='/'> + <ExtensionIcon className='icon' /> + <span className='text'>Puzzels</span> </Vierkant>} {false - && <Vierkant href='/'> - <Icon path={mdiRobotExcited} style={GameModeIconStyle} /> - <span style={GameModeTextStyle}>Tegen computer</span> - <div style={SquareSize}></div> + && <Vierkant className='gamemode bg-800' href='/'> + <Icon path={mdiRobotExcited} className='icon' /> + <span className='text'>Tegen computer</span> </Vierkant>} - <Vierkant style={LoginOrRegisterBoxStyle}> + <Vierkant className='loginOrRegisterBox pad-l valigntop bg-800'> {loggedIn ? <AccountBox info={userInfo} sumGameInfo={gameInfo?.totals} /> : <LoginOrRegisterBox />} </Vierkant> </div> {loggedIn - && <Vierkant fullwidth> + && <Vierkant className='w100m2m pad-l bg-800'> <RecentGames games={gameInfo?.games} /> </Vierkant>} - <Vierkant fullwidth> + <Vierkant className='w100m2m pad-l bg-800'> <h2>Nieuws ofzo</h2> <p style={{ margin: '6px 0' }}>Chess.com heeft heel veel troep waar niemand naar kijkt</p> </Vierkant> diff --git a/pages/login.tsx b/pages/login.tsx index 1e14573..da13f45 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -48,45 +48,33 @@ export default function LoginPage() { return ( <div> <NavBar /> - <CenteredPage width={500} style={{ height: '100vh' }}> - <div - style={{ - position: 'relative', - top: '50%', - transform: 'translateY(-50%)', - margin: '0 auto', - textAlign: 'center', - }} - > - <Vierkant> + <CenteredPage width={500} className='h100vh'> + <div className='posrel center centeredForm'> + <Vierkant className='pad-l bg-800'> <form onSubmit={(e) => submitLogin(e, toast)}> <Input autofocus autocomplete='username' id='email' label='email of gebruikersnaam' - style={{ marginBottom: 12 }} - > - </Input> - <Input autocomplete='current-password' id='password' label='wachtwoord' type='password'> - </Input> - <div - style={{ - marginTop: 24, - gridGap: 24, - display: 'grid', - gridTemplateColumns: '1fr 1fr', - }} - > + className='pad-m fullwidth bg-900 round-t' + /> + <Input + autocomplete='current-password' + id='password' + label='wachtwoord' + type='password' + className='pad-m fullwidth bg-900 round-t' + /> + <div className='sidebyside'> <Button href='/register' text='Registreren' - style={{ backgroundColor: 'var(--background-alt)' }} - > - </Button> - <Button text='Inloggen' onclick={() => submitLogin(null, toast)}></Button> + className='register bg-700 fg-100' + /> + <Button text='Inloggen' className='login' onclick={() => submitLogin(null, toast)} /> </div> - <input type='submit' style={{ display: 'none' }} /> + <input type='submit' className='dispnone' /> </form> </Vierkant> </div> diff --git a/pages/register.tsx b/pages/register.tsx index f78d092..bc2fc0f 100644 --- a/pages/register.tsx +++ b/pages/register.tsx @@ -88,35 +88,35 @@ export default function RegisterPage() { return ( <div> <NavBar /> - <CenteredPage width={500} style={{ height: '100vh' }}> - <div - style={{ - position: 'relative', - top: '50%', - transform: 'translateY(-50%)', - margin: '0 auto', - textAlign: 'center', - }} - > - <Vierkant> + <CenteredPage width={500} className='h100vh'> + <div className='posrel center centeredForm'> + <Vierkant className='pad-l bg-800'> <form onSubmit={(e) => submitRegister(e, toast)}> <Input autofocus autocomplete='username' id='username' label='gebruikersnaam' - style={{ marginBottom: 12 }} - > - </Input> - <Input autocomplete='email' id='email' label='email' style={{ marginBottom: 12 }}></Input> - <Input autocomplete='new-password' id='password' label='wachtwoord' type='password'></Input> + className='pad-m fullwidth bg-900 round-t' + /> + <Input + autocomplete='email' + id='email' + label='email' + className='pad-m fullwidth bg-900 round-t' + /> + <Input + autocomplete='new-password' + id='password' + label='wachtwoord' + type='password' + className='pad-m fullwidth bg-900 round-t' + /> <Button text='Registreren' - style={{ marginTop: 24 }} onclick={() => submitRegister(null, toast)} - > - </Button> - <input type='submit' style={{ display: 'none' }} /> + /> + <input type='submit' className='dispnone' /> </form> </Vierkant> </div> diff --git a/pages/search.tsx b/pages/search.tsx index 2b8668a..99f99b0 100644 --- a/pages/search.tsx +++ b/pages/search.tsx @@ -10,7 +10,7 @@ import { Button, Input, Vierkant } from '../components/ui'; import SearchOutlinedIcon from '@material-ui/icons/SearchOutlined'; function search(callback: (results: Array<userInfo>) => void) { - var query: string = (document.getElementById('searchBar') as HTMLInputElement).value; + var query: string = (document.getElementById('bigSearchBar') as HTMLInputElement).value; if (query.length < 3) return; axios.request<{ 'results': Array<userInfo>; }>({ @@ -24,74 +24,45 @@ function search(callback: (results: Array<userInfo>) => void) { } function SearchResults(props: { userList: Array<userInfo>; }) { - return <div> + return <div className='results w100m2m'> {props.userList?.map(user => <SearchResult user={user} key={user.id} />)} </div>; } function SearchResult(props: { user: userInfo; }) { return <Vierkant - style={{ - padding: 12, - }} - fullwidth + className='result bg-800 pad-m fullwidth' href={'/user?id=' + props.user.id} > - <div style={{ position: 'relative' }}> + <div className='inner posrel'> <AccountAvatar size={48} id={props.user.id} /> - <div - style={{ - position: 'absolute', - top: 0, - right: 0, - bottom: 0, - left: 48 + 12, - }} - > - <b>{props.user.username}</b> - <p>{props.user.status}</p> + <div className='userInfo posabs v0 r0'> + <b className='username'>{props.user.username}</b> + <p className='status'>{props.user.status}</p> </div> </div> </Vierkant>; } -function SearchBar(props: { +function BigSearchBar(props: { searchFunction: (event?: FormEvent<HTMLFormElement>) => void; }) { - return <Vierkant - fullwidth - style={{ - padding: 8, - marginBottom: 24, - }} - > + return <Vierkant className='pad-m bg-800 w100m2m bigSearchBar posrel'> <form onSubmit={props.searchFunction}> <Input - id='searchBar' + id='bigSearchBar' label='Zoeken voor gebruikers...' autocomplete='off' - dark autofocus - style={{ - backgroundColor: 'var(--background)', - color: 'var(--text)', - padding: 14, - fontSize: 16, - width: 'calc(100% - 48px - 14px * 2)', - }} + className='pad-m posabs abscenterv' /> <Button - style={{ - padding: 12, - float: 'right', - display: 'inline-block', - borderRadius: 4, - }} + className='pad-m dispinbl valigntop floatr' onclick={props.searchFunction} > <SearchOutlinedIcon /> </Button> - <input type='submit' style={{ display: 'none' }} /> + <input type='submit' className='dispnone' /> </form> </Vierkant>; } @@ -109,15 +80,10 @@ export default function HomePage() { <NavBar /> <CenteredPage width={802}> <PageTitle>Zoeken</PageTitle> - <SearchBar searchFunction={getSearchResults} /> + <BigSearchBar searchFunction={getSearchResults} /> <SearchResults userList={results} /> {searched && results.length == 0 && <h1 - style={{ - opacity: .6, - color: 'var(--text)', - textAlign: 'center', - margin: '24px 32px', - }} + className='noresults center subtile' > Geen zoekresultaten gevonden </h1>} diff --git a/pages/settings.tsx b/pages/settings.tsx index 0f40a90..0ca2c30 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -1,7 +1,6 @@ import axios from 'axios'; import reduce from 'image-blob-reduce'; -import { CSSProperties, useContext } from 'react'; -import * as cookies from 'react-cookies'; +import { useContext } from 'react'; import { AccountAvatar } from '../components/account'; import { Footer } from '../components/footer'; @@ -16,11 +15,6 @@ import ExitToAppOutlinedIcon from '@material-ui/icons/ExitToAppOutlined'; import PublishOutlinedIcon from '@material-ui/icons/PublishOutlined'; import VisibilityOutlinedIcon from '@material-ui/icons/VisibilityOutlined'; -var SettingsSubsectionStyle: CSSProperties = { - marginTop: 24, - minHeight: 40, -}; - async function uploadNewProfileImage() { if (!this.result) return; @@ -54,9 +48,9 @@ export default function SettingsPage() { <NavBar /> <CenteredPage width={802}> <PageTitle>Instellingen</PageTitle> - <Vierkant fullwidth> + <Vierkant className='section account w100m2m pad-l bg-800'> <h2>Account</h2> - <div style={SettingsSubsectionStyle}> + <div className='subsection'> <AccountAvatar size={100} /> <label htmlFor='pfUpload'> <IconLabelButton text='Nieuwe profielfoto uploaden' icon={<PublishOutlinedIcon />} /> @@ -65,7 +59,7 @@ export default function SettingsPage() { type='file' id='pfUpload' accept='.png,.jpg,.jpeg' - style={{ display: 'none' }} + className='dispnone' onChange={event => { var file = event.target.files[0]; if (!file) return; @@ -76,45 +70,45 @@ export default function SettingsPage() { }} /> </div> - <div style={SettingsSubsectionStyle}> + <div className='subsection'> <IconLabelButton text='Bewerken' icon={<EditOutlinedIcon />} /> - <div style={{ display: 'block' }}> + <div className='dispbl'> <h3>Gebruikersnaam</h3> <p>Hier staat hij dan</p> </div> </div> - <div style={SettingsSubsectionStyle}> + <div className='subsection'> <IconLabelButton text='Bewerken' icon={<EditOutlinedIcon />} /> <IconLabelButton text='Onthullen' icon={<VisibilityOutlinedIcon />} /> - <div style={{ display: 'block' }}> + <div className='dispbl'> <h3>Email</h3> <p>******@example.com</p> </div> </div> - <div style={SettingsSubsectionStyle}> + <div className='subsection'> <IconLabelButton text='Bewerken' icon={<EditOutlinedIcon />} /> - <div style={{ display: 'block' }}> + <div className='dispbl'> <h3>Wachtwoord</h3> </div> </div> </Vierkant> - <Vierkant fullwidth> + <Vierkant className='section colors w100m2m pad-l bg-800'> <h2>Kleuren</h2> - <div style={SettingsSubsectionStyle}> + <div className='subsection'> <ColorPicker /> <ColorPicker /> - <div style={{ display: 'block' }}> + <div className='dispbl'> <h3>Schijfjes</h3> </div> </div> - <div style={SettingsSubsectionStyle}> + <div className='subsection'> <ColorPicker /> - <div style={{ display: 'block' }}> + <div className='dispbl'> <h3>Achtergrond</h3> </div> </div> - <div style={SettingsSubsectionStyle}> - <div style={{ float: 'right' }}> + <div className='subsection'> + <div className='floatr'> <CheckBox state={preferences?.darkMode} onclick={state => updatePreference({ 'darkMode': state })} @@ -123,31 +117,20 @@ export default function SettingsPage() { <h3>Donkere modus</h3> </div> </Vierkant> - <Vierkant fullwidth> + <Vierkant className='section gamerules w100m2m pad-l bg-800'> <h2>Standaard spelregels</h2> - <div style={SettingsSubsectionStyle}> + <div className='subsection'> <CurrentGameSettings /> </div> </Vierkant> - <Vierkant fullwidth> + <Vierkant className='section logout w100m2m pad-l bg-800'> <h2>Uitloggen</h2> - <div - style={{ - width: '100%', - textAlign: 'center', - }} - > + <div className='center'> <IconLabelButton + className='dispinbl' icon={<ExitToAppOutlinedIcon />} text='Uitloggen' - style={{ - float: 'none', - marginLeft: 0, - }} - onclick={() => { - cookies.remove('token'); - window.location.pathname = '/'; - }} + href='/logout' /> </div> </Vierkant> diff --git a/pages/user.tsx b/pages/user.tsx index 4f7331c..9741275 100644 --- a/pages/user.tsx +++ b/pages/user.tsx @@ -1,6 +1,6 @@ import Icon from '@mdi/react'; import axios from 'axios'; -import { Children, ReactNode, useContext, useEffect, useState } from 'react'; +import { ReactNode, useContext, useEffect, useState } from 'react'; import { userGames, userInfo } from '../api/api'; import { AccountAvatar } from '../components/account'; @@ -35,60 +35,18 @@ function InfoModule(props: { label: string; icon: ReactNode; }) { - return <div - style={{ - position: 'relative', - height: '100%', - }} - > - <div - style={{ - position: 'absolute', - left: '50%', - transform: 'translateX(-50%)', - }} - > + return <div className='infoModule posrel'> + <div className='iconWrapper posabs'> {props.icon} </div> - <div - style={{ - position: 'absolute', - top: 24 + 6, - left: 0, - right: 0, - bottom: 0, - }} - > - <span - style={{ - position: 'absolute', - top: '50%', - transform: 'translateY(-50%)', - width: '100%', - textAlign: 'center', - }} - > + <div className='labelWrapper posabs h0 b0'> + <span className='label posabs center fullwidth'> {props.label} </span> </div> </div>; } -function InfoSection(props: { children: ReactNode; }) { - return <Vierkant fullwidth> - <div - style={{ - display: 'grid', - gridTemplateColumns: `repeat(${Children.count(props.children)}, 1fr)`, - gridGap: 12, - height: 64, - }} - > - {props.children} - </div> - </Vierkant>; -} - export default function AccountPage() { var server = typeof window === 'undefined'; var loggedIn = !server && document.cookie.includes('token'); @@ -167,226 +125,222 @@ export default function AccountPage() { <NavBar /> <CenteredPage width={802}> <PageTitle>Profiel</PageTitle> - <Vierkant fullwidth> - <AccountAvatar size={128} id={user?.id || ''} /> - <div - style={{ - display: 'inline-block', - verticalAlign: 'top', - marginLeft: 12, - width: 'calc(100% - 128px - 12px)', - }} - > - <h2 style={{ fontSize: 32 }}>{user?.username}</h2> - <p - id='status' - contentEditable={editingStatus ? 'true' : 'false'} - style={{ - marginTop: 6, - transitionDuration: '.3s', - }} - suppressContentEditableWarning={true} - > - {user?.status} - </p> - </div> - <div - style={{ - position: 'absolute', - backgroundColor: 'var(--background)', - height: '40px', - bottom: 24, - left: 24 + 12 + 128, - right: 24, - }} - > - {loggedIn && <div> - {ownPage - ? <div> - <IconLabelButton icon={<SettingsOutlinedIcon />} href='/settings' text='Instellingen' /> - {!editingStatus - ? <IconLabelButton - icon={<EditOutlinedIcon />} - text='Status bewerken' - onclick={() => setEditingStatus(true)} + <Vierkant className='accountHeader w100m2m pad-l bg-800'> + <div className='inner posrel'> + <AccountAvatar size={128} id={user?.id || ''} /> + <div className='userInfo dispinbl valigntop'> + <h2 className='username'>{user?.username}</h2> + <p + id='status' + className='status round-t' + contentEditable={editingStatus ? 'true' : 'false'} + suppressContentEditableWarning={true} + > + {user?.status} + </p> + </div> + <div className='posabs b0 r0'> + {loggedIn && <div> + {ownPage + ? <div> + <IconLabelButton + icon={<SettingsOutlinedIcon />} + href='/settings' + text='Instellingen' /> - : <IconLabelButton - icon={<DoneOutlinedIcon />} - text='Status opslaan' - onclick={() => { - setEditingStatus(false); - axios.request({ - method: 'post', - url: `/api/user/status`, - headers: { 'content-type': 'application/json' }, - data: { 'status': document.getElementById('status').innerText }, - }); - }} - />} - </div> - : <div> - {(() => { - var icon = { - 'blocked': <Icon size={1} path={mdiAccountCancelOutline} />, - }[relation] || <Icon size={1} path={mdiAccountCancelOutline} />; + {!editingStatus + ? <IconLabelButton + icon={<EditOutlinedIcon />} + text='Status bewerken' + onclick={() => setEditingStatus(true)} + /> + : <IconLabelButton + icon={<DoneOutlinedIcon />} + text='Status opslaan' + onclick={() => { + setEditingStatus(false); + axios.request({ + method: 'post', + url: `/api/user/status`, + headers: { 'content-type': 'application/json' }, + data: { 'status': document.getElementById('status').innerText }, + }); + }} + />} + </div> + : <div> + {(() => { + var icon = { + 'blocked': <Icon size={1} path={mdiAccountCancelOutline} />, + }[relation] || <Icon size={1} path={mdiAccountCancelOutline} />; - var text = { - 'blocked': 'Deblokkeren', - }[relation] || 'Blokkeren'; + var text = { + 'blocked': 'Deblokkeren', + }[relation] || 'Blokkeren'; - return <IconLabelButton - icon={icon} - text={text} - onclick={() => { - var nextRelation = { - 'blocked': { - 'endpoint': '/api/social/unblock', - 'action': `${user.username} gedeblokkeerd`, - 'relation': 'none', + return <IconLabelButton + icon={icon} + text={text} + onclick={() => { + var nextRelation = { + 'blocked': { + 'endpoint': '/api/social/unblock', + 'action': `${user.username} gedeblokkeerd`, + 'relation': 'none', + 'icon': <Icon size={1} path={mdiAccountCancelOutline} />, + }, + }[relation] || { + 'endpoint': '/api/social/block', + 'action': `${user.username} geblokkeerd`, + 'relation': 'blocked', 'icon': <Icon size={1} path={mdiAccountCancelOutline} />, - }, - }[relation] || { - 'endpoint': '/api/social/block', - 'action': `${user.username} geblokkeerd`, - 'relation': 'blocked', - 'icon': <Icon size={1} path={mdiAccountCancelOutline} />, - }; + }; - axios.request({ - method: 'post', - url: nextRelation.endpoint, - headers: { 'content-type': 'application/json' }, - data: { 'id': user?.id }, - }) - .then(() => { - toast({ - message: nextRelation.action, - type: 'confirmation', - icon: nextRelation.icon, + axios.request({ + method: 'post', + url: nextRelation.endpoint, + headers: { 'content-type': 'application/json' }, + data: { 'id': user?.id }, + }) + .then(() => { + toast({ + message: nextRelation.action, + type: 'confirmation', + icon: nextRelation.icon, + }); + setRelation(nextRelation.relation); }); - setRelation(nextRelation.relation); - }); - }} - />; - })()} - {(() => { - var icon = { - 'friends': <Icon size={1} path={mdiAccountMinusOutline} />, - 'outgoing': <Icon size={1} path={mdiAccountRemoveOutline} />, - 'incoming': <PersonAddOutlinedIcon />, - }[relation] || <PersonAddOutlinedIcon />; + }} + />; + })()} + {(() => { + var icon = { + 'friends': <Icon size={1} path={mdiAccountMinusOutline} />, + 'outgoing': <Icon size={1} path={mdiAccountRemoveOutline} />, + 'incoming': <PersonAddOutlinedIcon />, + }[relation] || <PersonAddOutlinedIcon />; - var text = { - 'friends': 'Vriend verwijderen', - 'outgoing': 'Vriendschapsverzoek annuleren', - 'incoming': 'Vriendschapsverzoek accepteren', - }[relation] || 'Vriendschapsverzoek sturen'; + var text = { + 'friends': 'Vriend verwijderen', + 'outgoing': 'Vriendschapsverzoek annuleren', + 'incoming': 'Vriendschapsverzoek accepteren', + }[relation] || 'Vriendschapsverzoek sturen'; - return <IconLabelButton - icon={icon} - text={text} - onclick={() => { - var nextRelation = { - 'friends': { - 'endpoint': '/api/social/remove', - 'action': `${user.username} succesvol verwijderd als vriend`, - 'relation': 'none', - 'icon': <Icon size={1} path={mdiAccountMinusOutline} />, - }, - 'outgoing': { - 'endpoint': '/api/social/remove', - 'action': `Vriendschapsverzoek naar ${user.username} geannuleerd`, - 'relation': 'none', - 'icon': <Icon size={1} path={mdiAccountMinusOutline} />, - }, - 'incoming': { - 'endpoint': '/api/social/accept', - 'action': `Vriendschapsverzoek van ${user.username} geaccepteerd`, - 'relation': 'friends', + return <IconLabelButton + icon={icon} + text={text} + onclick={() => { + var nextRelation = { + 'friends': { + 'endpoint': '/api/social/remove', + 'action': `${user.username} succesvol verwijderd als vriend`, + 'relation': 'none', + 'icon': <Icon size={1} path={mdiAccountMinusOutline} />, + }, + 'outgoing': { + 'endpoint': '/api/social/remove', + 'action': + `Vriendschapsverzoek naar ${user.username} geannuleerd`, + 'relation': 'none', + 'icon': <Icon size={1} path={mdiAccountMinusOutline} />, + }, + 'incoming': { + 'endpoint': '/api/social/accept', + 'action': + `Vriendschapsverzoek van ${user.username} geaccepteerd`, + 'relation': 'friends', + 'icon': <PersonAddOutlinedIcon />, + }, + }[relation] || { + 'endpoint': '/api/social/request', + 'action': `Vriendschapsverzoek gestuurd naar ${user.username}`, + 'relation': 'outgoing', 'icon': <PersonAddOutlinedIcon />, - }, - }[relation] || { - 'endpoint': '/api/social/request', - 'action': `Vriendschapsverzoek gestuurd naar ${user.username}`, - 'relation': 'outgoing', - 'icon': <PersonAddOutlinedIcon />, - }; + }; - axios.request({ - method: 'post', - url: nextRelation.endpoint, - headers: { 'content-type': 'application/json' }, - data: { 'id': user?.id }, - }) - .then(() => { - toast({ - message: nextRelation.action, - type: 'confirmation', - icon: nextRelation.icon, + axios.request({ + method: 'post', + url: nextRelation.endpoint, + headers: { 'content-type': 'application/json' }, + data: { 'id': user?.id }, + }) + .then(() => { + toast({ + message: nextRelation.action, + type: 'confirmation', + icon: nextRelation.icon, + }); + setRelation(nextRelation.relation); }); - setRelation(nextRelation.relation); - }); - }} - />; - })()} - </div>} - </div>} + }} + />; + })()} + </div>} + </div>} + </div> </div> </Vierkant> - <InfoSection> - <InfoModule - icon={<Icon size={1} path={mdiCheckboxBlankCircle} color='var(--disk-b-text)' />} - label='Online' - /> - <InfoModule - icon={<AssignmentIndOutlinedIcon />} - label={(() => { - var memberSince = 'Lid sinds'; + <Vierkant className='infosection pad-l w100m2m bg-800'> + <div className='inner sidebyside'> + <InfoModule + icon={<Icon size={1} path={mdiCheckboxBlankCircle} className='outcome win' />} + label='Online' + /> + <InfoModule + icon={<AssignmentIndOutlinedIcon />} + label={(() => { + var memberSince = 'Lid sinds'; - var registered = new Date(user?.registered); - memberSince += ' ' + registered.toLocaleString('nl-nl', { month: 'long', day: 'numeric' }); + var registered = new Date(user?.registered); + memberSince += ' ' + registered.toLocaleString('nl-nl', { month: 'long', day: 'numeric' }); - var currentYear = new Date().getFullYear(); - var memberYear = registered.getFullYear(); - if (currentYear != memberYear) memberSince += ' ' + memberYear; + var currentYear = new Date().getFullYear(); + var memberYear = registered.getFullYear(); + if (currentYear != memberYear) memberSince += ' ' + memberYear; - return memberSince; - })()} - /> - <InfoModule - icon={<PeopleOutlineOutlinedIcon />} - label={(() => { - var label = user?.friends.toString() + ' '; - label += user?.friends == 1 ? 'vriend' : 'vrienden'; - return label; - })()} - /> - <InfoModule icon={<Icon size={1} path={mdiEarth} />} label='Nederland' /> - </InfoSection> - <InfoSection> - <InfoModule - icon={<ArrowUpwardOutlinedIcon style={{ color: 'var(--disk-b-text)' }} />} - label={gameInfo?.totals.win + ' keer gewonnen'} - /> - <InfoModule - icon={<Icon size={1} path={mdiEqual} />} - label={gameInfo?.totals.draw + ' keer gelijkspel'} - /> - <InfoModule - icon={<ArrowDownwardOutlinedIcon style={{ color: 'var(--disk-a-text)' }} />} - label={gameInfo?.totals.lose + ' keer verloren'} - /> - <InfoModule icon={<Icon size={1} path={mdiClipboardTextOutline} />} label={'Score: ' + user?.rating} /> - <InfoModule - icon={<Icon size={1} path={mdiGamepadSquareOutline} />} - label={(() => { - var label = gameInfo?.totals.games.toString() + ' '; - label += gameInfo?.totals.games == 1 ? 'potje' : 'potjes'; - return label; - })()} - /> - </InfoSection> - <Vierkant> + return memberSince; + })()} + /> + <InfoModule + icon={<PeopleOutlineOutlinedIcon />} + label={(() => { + var label = user?.friends.toString() + ' '; + label += user?.friends == 1 ? 'vriend' : 'vrienden'; + return label; + })()} + /> + <InfoModule icon={<Icon size={1} path={mdiEarth} />} label='Nederland' /> + </div> + </Vierkant> + <Vierkant className='infosection pad-l w100m2m sidebyside bg-800'> + <div className='inner sidebyside'> + <InfoModule + icon={<ArrowUpwardOutlinedIcon className='outcome win' />} + label={gameInfo?.totals.win + ' keer gewonnen'} + /> + <InfoModule + icon={<Icon size={1} path={mdiEqual} className='subtile' />} + label={gameInfo?.totals.draw + ' keer gelijkspel'} + /> + <InfoModule + icon={<ArrowDownwardOutlinedIcon className='outcome lose' />} + label={gameInfo?.totals.lose + ' keer verloren'} + /> + <InfoModule + icon={<Icon size={1} path={mdiClipboardTextOutline} />} + label={'Score: ' + user?.rating} + /> + <InfoModule + icon={<Icon size={1} path={mdiGamepadSquareOutline} />} + label={(() => { + var label = gameInfo?.totals.games.toString() + ' '; + label += gameInfo?.totals.games == 1 ? 'potje' : 'potjes'; + return label; + })()} + /> + </div> + </Vierkant> + <Vierkant className='pad-l bg-800'> <RecentGames games={gameInfo?.games} /> </Vierkant> </CenteredPage> |