aboutsummaryrefslogtreecommitdiff
path: root/pages
diff options
context:
space:
mode:
Diffstat (limited to 'pages')
-rw-r--r--pages/_app.tsx29
-rw-r--r--pages/blog/[post].tsx59
-rw-r--r--pages/game.tsx359
-rw-r--r--pages/index.tsx273
-rw-r--r--pages/login.tsx104
-rw-r--r--pages/register.tsx127
-rw-r--r--pages/search.tsx136
-rw-r--r--pages/settings.tsx128
-rw-r--r--pages/user.tsx544
9 files changed, 968 insertions, 791 deletions
diff --git a/pages/_app.tsx b/pages/_app.tsx
index fad7c33..0682a4d 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,38 +1,37 @@
import Head from 'next/head';
import { PreferencesContextWrapper } from '../components/preferencesContext';
-import { ToastContextWrapper } from '../components/toast';
import { SocketContextWrapper } from '../components/socketContext';
+import { ToastContextWrapper } from '../components/toast';
-import '../styles/global.css';
import '../styles/dark.css';
import '../styles/disk.css';
import '../styles/footer.css';
+import '../styles/global.css';
export default function VierOpEenRijWebsite({ Component, pageProps }) {
return <div>
<Head>
<title>4 op een rij</title>
- <link rel="stylesheet" href="/font/stylesheet.css"/>
+ <link rel='stylesheet' href='/font/stylesheet.css' />
- <link rel="icon" href="/favicon.svg" type="image/svg+xml"/>
- <link rel="icon" href="/favicon.png" type="image/png"/>
+ <link rel='icon' href='/favicon.svg' type='image/svg+xml' />
+ <link rel='icon' href='/favicon.png' type='image/png' />
- <meta property="og:site_name" content="4 op een rij"/>
- <meta property="og:url" content="http://connect4.pipeframe.xyz/"/>
- <meta property="og:title" content="Loek's epische vier op een rij website"/>
- <meta property="og:description" content="Kom vier op een rij spelen NU"/>
- <meta property="og:type" content="website"/>
- <meta name="og:image" itemProp="image" content="/favicon.png"/>
- <meta name="theme-color" content="#e16d82"/>
+ <meta property='og:site_name' content='4 op een rij' />
+ <meta property='og:url' content='http://connect4.pipeframe.xyz/' />
+ <meta property='og:title' content="Loek's epische vier op een rij website" />
+ <meta property='og:description' content='Kom vier op een rij spelen NU' />
+ <meta property='og:type' content='website' />
+ <meta name='og:image' itemProp='image' content='/favicon.png' />
+ <meta name='theme-color' content='#e16d82' />
</Head>
<PreferencesContextWrapper>
<ToastContextWrapper>
<SocketContextWrapper>
- <Component {...pageProps}/>
+ <Component {...pageProps} />
</SocketContextWrapper>
</ToastContextWrapper>
</PreferencesContextWrapper>
- </div>
+ </div>;
}
-
diff --git a/pages/blog/[post].tsx b/pages/blog/[post].tsx
index 9588517..9ebd3ad 100644
--- a/pages/blog/[post].tsx
+++ b/pages/blog/[post].tsx
@@ -1,50 +1,52 @@
-import micromark from 'micromark';
import { readdirSync, readFileSync } from 'fs';
-import { join } from 'path'
+import micromark from 'micromark';
+import { join } from 'path';
import { NavBar } from '../../components/navbar';
import { CenteredPage, PageTitle } from '../../components/page';
import { Vierkant } from '../../components/ui';
export default function Post(props: {
- post: string,
- content: string,
- tags: string
+ post: string;
+ content: string;
+ tags: string;
}) {
return <div>
- <NavBar/>
+ <NavBar />
<CenteredPage width={802}>
- <PageTitle>{props.post.replace(/_/g, " ")}</PageTitle>
+ <PageTitle>{props.post.replace(/_/g, ' ')}</PageTitle>
<Vierkant fullwidth>
- <div dangerouslySetInnerHTML={{__html: props.content}}>
+ <div dangerouslySetInnerHTML={{ __html: props.content }}>
</div>
</Vierkant>
</CenteredPage>
- </div>
+ </div>;
}
function parseTags(fileContent: string) {
- var fileAsArr = fileContent.split("\n");
- var lastLine = fileAsArr[fileAsArr.length-1]
- if (!lastLine.startsWith(";tags:")) return {
- tags: [],
- result: ""
+ var fileAsArr = fileContent.split('\n');
+ var lastLine = fileAsArr[fileAsArr.length - 1];
+ if (!lastLine.startsWith(';tags:')) {
+ return {
+ tags: [],
+ result: '',
+ };
}
- var tags = lastLine.replace(";tags:", "").trim().split(" ");
+ var tags = lastLine.replace(';tags:', '').trim().split(' ');
- fileAsArr.pop()
- var result = fileAsArr.join("\n").trim()
+ fileAsArr.pop();
+ var result = fileAsArr.join('\n').trim();
- return { tags, result }
+ return { tags, result };
}
-export function getStaticProps(props: {params: { post: string }}) {
- var filename = join("news/", props.params.post + ".md")
- var filecontent = readFileSync(filename).toString().trim()
+export function getStaticProps(props: { params: { post: string; }; }) {
+ var filename = join('news/', props.params.post + '.md');
+ var filecontent = readFileSync(filename).toString().trim();
var parsed = parseTags(filecontent);
- var content = micromark(parsed.result)
+ var content = micromark(parsed.result);
return {
props: {
@@ -52,21 +54,20 @@ export function getStaticProps(props: {params: { post: string }}) {
content,
tags: parsed.tags,
},
- }
+ };
}
export function getStaticPaths() {
- var files = readdirSync("news").filter(f => f.endsWith(".md"));
+ var files = readdirSync('news').filter(f => f.endsWith('.md'));
return {
paths: files.map((f) => {
return {
params: {
- post: f.substr(0, f.length - 3)
- }
- }
+ post: f.substr(0, f.length - 3),
+ },
+ };
}),
fallback: false,
- }
+ };
}
-
diff --git a/pages/game.tsx b/pages/game.tsx
index 4fa58a9..b5200a7 100644
--- a/pages/game.tsx
+++ b/pages/game.tsx
@@ -1,24 +1,24 @@
-import { CSSProperties, useState, useEffect, useContext } from 'react';
+import Icon from '@mdi/react';
import axios from 'axios';
+import copy from 'copy-to-clipboard';
+import { CSSProperties, useContext, useEffect, useState } from 'react';
import * as cookies from 'react-cookies';
-import { SocketContext } from '../components/socketContext';
import { Socket } from 'socket.io-client';
-import Icon from '@mdi/react';
-import copy from 'copy-to-clipboard';
+import { SocketContext } from '../components/socketContext';
-import { NavBar } from '../components/navbar';
-import { CenteredPage } from '../components/page';
-import { VoerBord } from '../components/voerBord';
import { DialogBox } from '../components/dialogBox';
-import { CurrentGameSettings } from '../components/gameSettings';
-import { Button, SearchBar, IconLabelButton } from '../components/ui';
import { GameBar } from '../components/gameBar';
+import { CurrentGameSettings } from '../components/gameSettings';
+import { NavBar } from '../components/navbar';
+import { CenteredPage } from '../components/page';
import { ToastContext, toastType } from '../components/toast';
+import { Button, IconLabelButton, SearchBar } from '../components/ui';
+import { VoerBord } from '../components/voerBord';
-import WifiTetheringRoundedIcon from '@material-ui/icons/WifiTetheringRounded';
+import FlagOutlinedIcon from '@material-ui/icons/FlagOutlined';
import LinkRoundedIcon from '@material-ui/icons/LinkRounded';
import RefreshIcon from '@material-ui/icons/Refresh';
-import FlagOutlinedIcon from '@material-ui/icons/FlagOutlined';
+import WifiTetheringRoundedIcon from '@material-ui/icons/WifiTetheringRounded';
import { mdiContentCopy } from '@mdi/js';
function VoerGame(props: {
@@ -37,49 +37,51 @@ function VoerGame(props: {
var board: Array<number> = [...Array(width * height)].map(() => 0);
useEffect(() => {
- props.io.on("connect", () => console.log("connect"));
- props.io.on("disconnect", () => console.log("disconnect"));
+ props.io.on('connect', () => console.log('connect'));
+ props.io.on('disconnect', () => console.log('disconnect'));
- props.io.on("fieldUpdate", (data: { field: string }) => {
- board = data.field.split("").map(i => Number(i));
- for(let i = 0; i < data.field.length; i++)
+ props.io.on('fieldUpdate', (data: { field: string; }) => {
+ board = data.field.split('').map(i => Number(i));
+ for (let i = 0; i < data.field.length; i++) {
document.getElementById(`pos-${i}`).parentNode.children.item(1).classList.add(`state-${data.field[i]}`);
+ }
});
- props.io.on("turnUpdate", (data: { player1: boolean }) => setTurn(data.player1));
+ props.io.on('turnUpdate', (data: { player1: boolean; }) => setTurn(data.player1));
- props.io.on("finish", (data: {
- winPositions: Array<Array<number>>
- boardFull: boolean
- winner: number
- }) => {
+ props.io.on('finish', (data: {
+ winPositions: Array<Array<number>>;
+ boardFull: boolean;
+ winner: number;
+ }) => {
// setWinPositions(data.winPositions);
if (data.boardFull) setOutcome(0);
if (data.winPositions.length > 0) setOutcome(board[data.winPositions[0][0]]);
});
- props.io.on("resign", () => {
- props.toast({ message: "Het potje is opgegeven",
- type: "normal",
- icon: <FlagOutlinedIcon/>});
+ props.io.on('resign', () => {
+ props.toast({ message: 'Het potje is opgegeven', type: 'normal', icon: <FlagOutlinedIcon /> });
});
}, []);
- return <div style={{
- position: "relative",
- top: "50%",
- transform: "translateY(-50%)",
- maxWidth: "100vh",
- margin: "0 auto"
- }}>
+ return <div
+ style={{
+ position: 'relative',
+ top: '50%',
+ transform: 'translateY(-50%)',
+ maxWidth: '100vh',
+ margin: '0 auto',
+ }}
+ >
<VoerBord
- width={width} height={height}
+ width={width}
+ height={height}
onMove={move => {
- props.io.emit("newMove", {
+ props.io.emit('newMove', {
move: move % width + 1,
- token: cookies.load("token"), //TODO: get token from request
- game_id: props.gameID
+ token: cookies.load('token'), // TODO: get token from request
+ game_id: props.gameID,
});
}}
active={props.active && outcome == -1}
@@ -88,14 +90,16 @@ function VoerGame(props: {
turn={turn}
player1={props.player1}
active={props.active}
- resignFunction={() => { props.io.emit("resign", { game_id: props.gameID }) }}
+ resignFunction={() => {
+ props.io.emit('resign', { game_id: props.gameID });
+ }}
/>
<GameOutcomeDialog
outcome={outcome}
player={props.player1 ? 1 : 2}
visible={outcome != -1}
/>
- </div>
+ </div>;
}
function GameOutcomeDialog(props: {
@@ -104,180 +108,209 @@ function GameOutcomeDialog(props: {
visible: boolean;
}) {
return <DialogBox
- title="Speluitkomst"
- style={{ display: props.visible ? "inline-block" : "none" }}
+ title='Speluitkomst'
+ style={{ display: props.visible ? 'inline-block' : 'none' }}
onclick={() => {
- window.history.replaceState(null, null, "/");
+ window.history.replaceState(null, null, '/');
window.location.reload();
- }}>
- <div style={{
- width: "100%",
- textAlign: "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
- }}>{
- props.outcome == 0 ? "Gelijkspel" :
- props.outcome == props.player ? "Verloren" :
- props.outcome != props.player ? "Gewonnen" :
- "???"
- }</h2>
- { false && <p style={{ marginTop: 24 }}>
- 0 Gemiste winstzetten<br/>
- 6 Optimale zetten<br/>
- 0 Blunders
- </p> }
- { false && <IconLabelButton text="Opnieuw spelen" icon={<RefreshIcon/>} style={{
- float: "none",
- marginTop: 24,
- padding: "12px 32px"
- }}/> }
+ }}
+ >
+ <div
+ style={{
+ width: '100%',
+ textAlign: '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,
+ }}
+ >
+ {props.outcome == 0
+ ? 'Gelijkspel'
+ : props.outcome == props.player
+ ? 'Verloren'
+ : props.outcome != props.player
+ ? 'Gewonnen'
+ : '???'}
+ </h2>
+ {false && <p style={{ marginTop: 24 }}>
+ 0 Gemiste winstzetten<br />
+ 6 Optimale zetten<br />
+ 0 Blunders
+ </p>}
+ {false && <IconLabelButton
+ text='Opnieuw spelen'
+ icon={<RefreshIcon />}
+ style={{
+ float: 'none',
+ marginTop: 24,
+ padding: '12px 32px',
+ }}
+ />}
</div>
- </DialogBox>
+ </DialogBox>;
}
var InviteButtonStyle: CSSProperties = {
- backgroundColor: "var(--page-background)",
+ backgroundColor: 'var(--page-background)',
height: 160,
- padding: 12
-}
+ padding: 12,
+};
var InviteButtonIconStyle: CSSProperties = {
fontSize: 100,
- position: "absolute",
+ position: 'absolute',
top: 12,
- left: "50%",
- transform: "translateX(-50%)"
-}
+ left: '50%',
+ transform: 'translateX(-50%)',
+};
var InviteButtonLabelStyle: CSSProperties = {
- position: "absolute",
+ position: 'absolute',
bottom: 12,
- left: "50%",
- transform: "translateX(-50%)",
- textAlign: "center",
- color: "var(--text-alt)",
+ left: '50%',
+ transform: 'translateX(-50%)',
+ textAlign: 'center',
+ color: 'var(--text-alt)',
width: 136,
fontSize: 20,
- userSelect: "none"
-}
+ userSelect: 'none',
+};
export default function GamePage() {
- var [gameID, setGameID] = useState("");
+ var [gameID, setGameID] = useState('');
var [player1, setPlayer1] = useState(true);
var [active, setActive] = useState(false);
- var [gameIDUrl, setGameIDUrl] = useState("");
+ var [gameIDUrl, setGameIDUrl] = useState('');
var { io } = useContext(SocketContext);
var { toast } = useContext(ToastContext);
useEffect(() => {
- var gameIDUrl = new URLSearchParams(window.location.search).get("id") || "";
+ var gameIDUrl = new URLSearchParams(window.location.search).get('id') || '';
setGameIDUrl(gameIDUrl);
if (!gameIDUrl || gameIDUrl == gameID) return;
- axios.request<{ id: string, player_1: boolean, game_started: boolean }>({
- method: "post",
- url: "/api/game/accept",
- headers: {"content-type": "application/json"},
- data: { id: gameIDUrl }
- })
- .then(response => {
- setGameID(response.data.id);
- setPlayer1(response.data.player_1);
- io.emit("registerGameListener", { game_id: response.data.id });
- setActive(true);
+ axios.request<{ id: string; player_1: boolean; game_started: boolean; }>({
+ method: 'post',
+ url: '/api/game/accept',
+ headers: { 'content-type': 'application/json' },
+ data: { id: gameIDUrl },
})
- .catch(err => {
- toast({ message: "error",
- type: "confirmation",
- description: err.toString() });
- });
+ .then(response => {
+ setGameID(response.data.id);
+ setPlayer1(response.data.player_1);
+ io.emit('registerGameListener', { game_id: response.data.id });
+ setActive(true);
+ })
+ .catch(err => {
+ toast({ message: 'error', type: 'confirmation', description: err.toString() });
+ });
setGameID(gameIDUrl);
}, []);
useEffect(() => {
- io.on("gameStart", () => setActive(true));
+ io.on('gameStart', () => setActive(true));
}, []);
return <div>
- <NavBar/>
- <CenteredPage width={900} style={{ height: "100vh" }}>
+ <NavBar />
+ <CenteredPage width={900} style={{ height: '100vh' }}>
<VoerGame
active={active}
gameID={gameID}
player1={player1}
io={io}
- toast={toast}/>
+ toast={toast}
+ />
<DialogBox
- title="Nieuw spel"
- style={{ display: gameIDUrl || gameID ? "none" : "inline-block" }}
- onclick={() => { window.history.go(-1); }}>
- <CurrentGameSettings/>
- <div style={{
- marginTop: 24,
- display: "grid",
- gridTemplateColumns: "1fr 1fr",
- gridGap: 24
- }}>
- <Button style={InviteButtonStyle} onclick={() => {
- axios.request<{ id: string, player_1: boolean, game_started: boolean }>({
- url: "/api/game/random",
- })
- .then(response => {
- setGameID(response.data.id);
- window.history.replaceState(null, null, "?id=" + response.data.id);
- setPlayer1(response.data.player_1);
- io.emit("registerGameListener", { game_id: response.data.id });
- if (response.data.game_started) setActive(true);
- })
- .catch(() => {});
- }}>
- <WifiTetheringRoundedIcon style={{
- color: "var(--disk-b)",
- ...InviteButtonIconStyle
- }}/>
+ title='Nieuw spel'
+ style={{ display: gameIDUrl || gameID ? 'none' : 'inline-block' }}
+ onclick={() => {
+ window.history.go(-1);
+ }}
+ >
+ <CurrentGameSettings />
+ <div
+ style={{
+ marginTop: 24,
+ display: 'grid',
+ gridTemplateColumns: '1fr 1fr',
+ gridGap: 24,
+ }}
+ >
+ <Button
+ style={InviteButtonStyle}
+ onclick={() => {
+ axios.request<{ id: string; player_1: boolean; game_started: boolean; }>({
+ url: '/api/game/random',
+ })
+ .then(response => {
+ setGameID(response.data.id);
+ window.history.replaceState(null, null, '?id=' + response.data.id);
+ setPlayer1(response.data.player_1);
+ io.emit('registerGameListener', { game_id: response.data.id });
+ if (response.data.game_started) setActive(true);
+ })
+ .catch(() => {});
+ }}
+ >
+ <WifiTetheringRoundedIcon
+ style={{
+ color: 'var(--disk-b)',
+ ...InviteButtonIconStyle,
+ }}
+ />
<h2 style={InviteButtonLabelStyle}>Willekeurige speler</h2>
</Button>
- <Button style={InviteButtonStyle} onclick={() => {
- axios.request<{ id: string }>({
- method: "post",
- url: "/api/game/new",
- headers: {"content-type": "application/json"},
- data: {}
- })
- .then(response => {
- setGameID(response.data.id);
- window.history.replaceState(null, null, "?id=" + response.data.id);
- setPlayer1(true);
- io.emit("registerGameListener", { game_id: response.data.id });
- setActive(false);
+ <Button
+ style={InviteButtonStyle}
+ onclick={() => {
+ axios.request<{ id: string; }>({
+ method: 'post',
+ url: '/api/game/new',
+ headers: { 'content-type': 'application/json' },
+ data: {},
+ })
+ .then(response => {
+ setGameID(response.data.id);
+ window.history.replaceState(null, null, '?id=' + response.data.id);
+ setPlayer1(true);
+ io.emit('registerGameListener', { game_id: response.data.id });
+ setActive(false);
- copy(window.location.href);
- toast({ message: "Link gekopiƫerd naar klembord",
- type: "confirmation",
- icon: <Icon size={1} path={mdiContentCopy}/> });
- })
- .catch(() => {});
- }}>
- <LinkRoundedIcon style={{
- color: "var(--disk-a)",
- ...InviteButtonIconStyle
- }}/>
+ copy(window.location.href);
+ toast({
+ message: 'Link gekopiƫerd naar klembord',
+ type: 'confirmation',
+ icon: <Icon size={1} path={mdiContentCopy} />,
+ });
+ })
+ .catch(() => {});
+ }}
+ >
+ <LinkRoundedIcon
+ style={{
+ color: 'var(--disk-a)',
+ ...InviteButtonIconStyle,
+ }}
+ />
<h2 style={InviteButtonLabelStyle}>Uitnodigen via link</h2>
</Button>
</div>
- <SearchBar label="Zoeken in vriendenlijst"/>
+ <SearchBar label='Zoeken in vriendenlijst' />
</DialogBox>
</CenteredPage>
- </div>
+ </div>;
}
-
diff --git a/pages/index.tsx b/pages/index.tsx
index 9bfe2a7..354efc5 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -1,84 +1,94 @@
-import { CSSProperties, useState, useEffect, useContext } from 'react';
import axios from 'axios';
-import { userInfo, userGameTotals, userGames } from '../api/api';
-import { SocketContext } from '../components/socketContext';
+import { CSSProperties, useContext, useEffect, useState } from 'react';
+import { userGames, userGameTotals, userInfo } from '../api/api';
import { Footer } from '../components/footer';
+import { SocketContext } from '../components/socketContext';
+import { AccountAvatar } from '../components/account';
import { NavBar } from '../components/navbar';
import { CenteredPage, PageTitle } from '../components/page';
-import { Vierkant, Button } from '../components/ui';
-import { AccountAvatar } from '../components/account';
import RecentGames from '../components/recentGames';
+import { Button, Vierkant } from '../components/ui';
-import VideogameAssetIcon from '@material-ui/icons/VideogameAsset';
import ExtensionIcon from '@material-ui/icons/Extension';
+import VideogameAssetIcon from '@material-ui/icons/VideogameAsset';
-import Icon from '@mdi/react';
import { mdiRobotExcited } from '@mdi/js';
+import Icon from '@mdi/react';
var GameModeIconStyle: CSSProperties = {
fontSize: 64,
width: 64,
height: 64,
- display: "inline-block",
- position: "absolute",
+ display: 'inline-block',
+ position: 'absolute',
top: 24,
- left: "50%",
- transform: "translateX(-50%)"
-}
+ left: '50%',
+ transform: 'translateX(-50%)',
+};
var GameModeTextStyle: CSSProperties = {
- whiteSpace: "nowrap",
- display: "inline-block",
- position: "absolute",
+ whiteSpace: 'nowrap',
+ display: 'inline-block',
+ position: 'absolute',
bottom: 24,
- left: "50%",
- transform: "translateX(-50%)",
- userSelect: "none",
- fontWeight: 500
-}
+ left: '50%',
+ transform: 'translateX(-50%)',
+ userSelect: 'none',
+ fontWeight: 500,
+};
var SquareSize: CSSProperties = {
width: 90,
- height: 90
-}
+ height: 90,
+};
var LoginOrRegisterBoxStyle: CSSProperties = {
- verticalAlign: "top",
+ verticalAlign: 'top',
height: `calc(${SquareSize.height}px + 24px * 2)`,
- width: "100%",
- maxWidth: `calc(100% - ${SquareSize.width}px - 12px * 2 - 24px * 2)`
-}
+ width: '100%',
+ maxWidth: `calc(100% - ${SquareSize.width}px - 12px * 2 - 24px * 2)`,
+};
var InnerLoginOrRegisterBoxStyle: CSSProperties = {
- position: "relative",
- width: "100%",
- height: "100%"
-}
+ 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</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"/>
+ 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
+ </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>
- </div>
+ </div>;
}
function AccountBox(props: {
@@ -86,116 +96,123 @@ function AccountBox(props: {
sumGameInfo: userGameTotals;
}) {
return <div style={InnerLoginOrRegisterBoxStyle}>
- <div style={{
- position: "absolute",
- top: 0, left: 0,
- ...SquareSize
- }}>
- <AccountAvatar size={90}/>
+ <div
+ style={{
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ ...SquareSize,
+ }}
+ >
+ <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>
+ <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>
+ <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>
</p>
</div>
- </div>
+ </div>;
}
export default function HomePage() {
- var server = typeof window === "undefined";
- var loggedIn = !server && document.cookie.includes("token");
+ var server = typeof window === 'undefined';
+ var loggedIn = !server && document.cookie.includes('token');
var { io } = useContext(SocketContext);
useEffect(() => {
- io.on("connect", () => { console.log("gert") });
+ io.on('connect', () => {
+ console.log('gert');
+ });
}, []);
var [userInfo, setUserInfo] = useState<userInfo>();
var [gameInfo, setGameInfo] = useState<userGames>();
- useEffect(() => {( async () => {
- if (!loggedIn) return;
- var userInfoReq = await axios.request<userInfo>({
- method: "get",
- url: `/api/user/info`,
- headers: {"content-type": "application/json"}
- });
- setUserInfo(userInfoReq.data);
- })()}, []);
-
- useEffect(() => {( async () => {
- if (!loggedIn) return;
- var userGamesReq = await axios.request<userGames>({
- method: "get",
- url: `/api/user/games`,
- headers: {"content-type": "application/json"}
- });
- setGameInfo(userGamesReq.data);
- })()}, []);
+ useEffect(() => {
+ (async () => {
+ if (!loggedIn) return;
+ var userInfoReq = await axios.request<userInfo>({
+ method: 'get',
+ url: `/api/user/info`,
+ headers: { 'content-type': 'application/json' },
+ });
+ setUserInfo(userInfoReq.data);
+ })();
+ }, []);
+
+ useEffect(() => {
+ (async () => {
+ if (!loggedIn) return;
+ var userGamesReq = await axios.request<userGames>({
+ method: 'get',
+ url: `/api/user/games`,
+ headers: { 'content-type': 'application/json' },
+ });
+ setGameInfo(userGamesReq.data);
+ })();
+ }, []);
return <div>
- <NavBar/>
+ <NavBar />
<CenteredPage width={802}>
<PageTitle>4 op een rij</PageTitle>
<div>
- <Vierkant href="/game">
- <VideogameAssetIcon style={GameModeIconStyle}/>
+ <Vierkant href='/game'>
+ <VideogameAssetIcon style={GameModeIconStyle} />
<span style={GameModeTextStyle}>Nieuw spel</span>
<div style={SquareSize}></div>
</Vierkant>
- {
- false &&
- <Vierkant href="/">
- <ExtensionIcon style={GameModeIconStyle}/>
+ {false
+ && <Vierkant href='/'>
+ <ExtensionIcon style={GameModeIconStyle} />
<span style={GameModeTextStyle}>Puzzels</span>
<div style={SquareSize}></div>
- </Vierkant>
- }
- {
- false &&
- <Vierkant href="/">
- <Icon path={mdiRobotExcited} style={GameModeIconStyle}/>
+ </Vierkant>}
+ {false
+ && <Vierkant href='/'>
+ <Icon path={mdiRobotExcited} style={GameModeIconStyle} />
<span style={GameModeTextStyle}>Tegen computer</span>
<div style={SquareSize}></div>
- </Vierkant>
- }
+ </Vierkant>}
<Vierkant style={LoginOrRegisterBoxStyle}>
- {
- loggedIn ?
- <AccountBox info={userInfo} sumGameInfo={gameInfo?.totals}/> :
- <LoginOrRegisterBox/>
- }
+ {loggedIn
+ ? <AccountBox info={userInfo} sumGameInfo={gameInfo?.totals} />
+ : <LoginOrRegisterBox />}
</Vierkant>
</div>
- {
- loggedIn &&
- <Vierkant fullwidth>
- <RecentGames games={gameInfo?.games}/>
- </Vierkant>
- }
+ {loggedIn
+ && <Vierkant fullwidth>
+ <RecentGames games={gameInfo?.games} />
+ </Vierkant>}
<Vierkant fullwidth>
<h2>Nieuws ofzo</h2>
- <p style={{ margin: "6px 0" }}>Chess.com heeft heel veel troep waar niemand naar kijkt</p>
+ <p style={{ margin: '6px 0' }}>Chess.com heeft heel veel troep waar niemand naar kijkt</p>
</Vierkant>
</CenteredPage>
- <Footer/>
- </div>
+ <Footer />
+ </div>;
}
-
diff --git a/pages/login.tsx b/pages/login.tsx
index abfca04..1e14573 100644
--- a/pages/login.tsx
+++ b/pages/login.tsx
@@ -3,47 +3,43 @@ import { FormEvent, useContext } from 'react';
import { NavBar } from '../components/navbar';
import { CenteredPage } from '../components/page';
-import { Vierkant, Input, Button } from '../components/ui';
import { ToastContext, toastType } from '../components/toast';
+import { Button, Input, Vierkant } from '../components/ui';
+import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
import ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined';
import VpnKeyIcon from '@material-ui/icons/VpnKey';
-import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
function submitLogin(event?: FormEvent<HTMLFormElement>, toast?: toastType) {
event?.preventDefault();
var formData = {
- email: (document.getElementById("email") as HTMLInputElement).value,
- password: (document.getElementById("password") as HTMLInputElement).value
- }
+ email: (document.getElementById('email') as HTMLInputElement).value,
+ password: (document.getElementById('password') as HTMLInputElement).value,
+ };
- if ( !formData.email ||
- !formData.password ) {
- toast({ message: "Vul alsjeblieft alle velden in!",
- type: "error",
- icon: <ReportProblemOutlinedIcon/>});
+ if (
+ !formData.email
+ || !formData.password
+ ) {
+ toast({ message: 'Vul alsjeblieft alle velden in!', type: 'error', icon: <ReportProblemOutlinedIcon /> });
return;
}
axios({
- method: "post",
+ method: 'post',
url: `${window.location.origin}/api/auth/login`,
- headers: {"content-type": "application/json"},
- data: formData
+ headers: { 'content-type': 'application/json' },
+ data: formData,
})
- .then(() => window.location.pathname = "/")
- .catch(error => {
- if (error.response.status === 401) {
- toast({ message: "Verkeerde gebruikersnaam of wachtwoord!",
- type: "error",
- icon: <VpnKeyIcon/>});
- return;
- }
- toast({ message: "Er is iets fout gegaan",
- type: "error",
- icon: <ErrorOutlineIcon/>});
- });
+ .then(() => window.location.pathname = '/')
+ .catch(error => {
+ if (error.response.status === 401) {
+ toast({ message: 'Verkeerde gebruikersnaam of wachtwoord!', type: 'error', icon: <VpnKeyIcon /> });
+ return;
+ }
+ toast({ message: 'Er is iets fout gegaan', type: 'error', icon: <ErrorOutlineIcon /> });
+ });
}
export default function LoginPage() {
@@ -51,29 +47,46 @@ 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"
- }}>
+ <NavBar />
+ <CenteredPage width={500} style={{ height: '100vh' }}>
+ <div
+ style={{
+ position: 'relative',
+ top: '50%',
+ transform: 'translateY(-50%)',
+ margin: '0 auto',
+ textAlign: 'center',
+ }}
+ >
<Vierkant>
<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"
- }}>
- <Button href="/register" text="Registreren" style={{ backgroundColor: "var(--background-alt)"}}></Button>
- <Button text="Inloggen" onclick={() => submitLogin(null, toast)}></Button>
+ <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',
+ }}
+ >
+ <Button
+ href='/register'
+ text='Registreren'
+ style={{ backgroundColor: 'var(--background-alt)' }}
+ >
+ </Button>
+ <Button text='Inloggen' onclick={() => submitLogin(null, toast)}></Button>
</div>
- <input type="submit" style={{ display: "none" }}/>
+ <input type='submit' style={{ display: 'none' }} />
</form>
</Vierkant>
</div>
@@ -81,4 +94,3 @@ export default function LoginPage() {
</div>
);
}
-
diff --git a/pages/register.tsx b/pages/register.tsx
index 5c0e37b..f78d092 100644
--- a/pages/register.tsx
+++ b/pages/register.tsx
@@ -4,27 +4,27 @@ import { FormEvent, useContext } from 'react';
import { NavBar } from '../components/navbar';
import { CenteredPage } from '../components/page';
-import { Vierkant, Input, Button } from '../components/ui';
import { ToastContext, toastType } from '../components/toast';
+import { Button, Input, Vierkant } from '../components/ui';
-import ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined';
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
+import ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined';
function submitRegister(event?: FormEvent<HTMLFormElement>, toast?: toastType) {
event?.preventDefault();
var formData = {
- username: (document.getElementById("username") as HTMLInputElement).value,
- email: (document.getElementById("email") as HTMLInputElement).value,
- password: (document.getElementById("password") as HTMLInputElement).value
- }
+ username: (document.getElementById('username') as HTMLInputElement).value,
+ email: (document.getElementById('email') as HTMLInputElement).value,
+ password: (document.getElementById('password') as HTMLInputElement).value,
+ };
- if ( !formData.username ||
- !formData.email ||
- !formData.password ) {
- toast({ message: "Vul alsjeblieft alle velden in!",
- type: "error",
- icon: <ReportProblemOutlinedIcon/>});
+ if (
+ !formData.username
+ || !formData.email
+ || !formData.password
+ ) {
+ toast({ message: 'Vul alsjeblieft alle velden in!', type: 'error', icon: <ReportProblemOutlinedIcon /> });
return;
}
@@ -39,47 +39,47 @@ function submitRegister(event?: FormEvent<HTMLFormElement>, toast?: toastType) {
* https://stackoverflow.com/questions/5142103/regex-to-validate-password-strength
*/
- if ( formData.username.length < 3 || formData.username.length > 35 ) {
- toast({ message: "Ongeldige gebruikersnaam",
- description: "Je gebruikersnaam moet tussen de 3 en 35 letters zijn",
- type: "error",
- icon: <ReportProblemOutlinedIcon/>});
+ if (formData.username.length < 3 || formData.username.length > 35) {
+ toast({
+ message: 'Ongeldige gebruikersnaam',
+ description: 'Je gebruikersnaam moet tussen de 3 en 35 letters zijn',
+ type: 'error',
+ icon: <ReportProblemOutlinedIcon />,
+ });
return;
}
- if ( !validateEmail(formData.email) ) {
- toast({ message: "Ongeldig email-adres",
- type: "error",
- icon: <ReportProblemOutlinedIcon/>});
+ if (!validateEmail(formData.email)) {
+ toast({ message: 'Ongeldig email-adres', type: 'error', icon: <ReportProblemOutlinedIcon /> });
return;
}
- //TODO: wachtwoord max 72 tekens ivm bcrypt
- if ( !formData.password.match(passwordRegex) ) {
- toast({ message: "Ongeldig wachtwoord",
- description: "Je wachtwoord moet een hoofdletter, kleine letter en een getal bevatten",
- type: "error",
- icon: <ReportProblemOutlinedIcon/>});
+ // TODO: wachtwoord max 72 tekens ivm bcrypt
+ if (!formData.password.match(passwordRegex)) {
+ toast({
+ message: 'Ongeldig wachtwoord',
+ description: 'Je wachtwoord moet een hoofdletter, kleine letter en een getal bevatten',
+ type: 'error',
+ icon: <ReportProblemOutlinedIcon />,
+ });
return;
}
-
+
axios({
- method: "post",
+ method: 'post',
url: `${window.location.origin}/api/auth/signup`,
- headers: {"content-type": "application/json"},
- data: formData
- })
- .then(() => {
- //TODO: email verificatie
- // redirect naar home, automatische login
- window.location.pathname = "/";
+ headers: { 'content-type': 'application/json' },
+ data: formData,
})
- .catch(error => {
- toast({ message: "Er is iets fout gegaan",
- type: "error",
- icon: <ErrorOutlineIcon/>});
- console.log(error);
- });
+ .then(() => {
+ // TODO: email verificatie
+ // redirect naar home, automatische login
+ window.location.pathname = '/';
+ })
+ .catch(error => {
+ toast({ message: 'Er is iets fout gegaan', type: 'error', icon: <ErrorOutlineIcon /> });
+ console.log(error);
+ });
}
export default function RegisterPage() {
@@ -87,22 +87,36 @@ 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"
- }}>
+ <NavBar />
+ <CenteredPage width={500} style={{ height: '100vh' }}>
+ <div
+ style={{
+ position: 'relative',
+ top: '50%',
+ transform: 'translateY(-50%)',
+ margin: '0 auto',
+ textAlign: 'center',
+ }}
+ >
<Vierkant>
<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>
- <Button text="Registreren" style={{ marginTop: 24 }} onclick={() => submitRegister(null, toast)}></Button>
- <input type="submit" style={{ display: "none" }}/>
+ <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>
+ <Button
+ text='Registreren'
+ style={{ marginTop: 24 }}
+ onclick={() => submitRegister(null, toast)}
+ >
+ </Button>
+ <input type='submit' style={{ display: 'none' }} />
</form>
</Vierkant>
</div>
@@ -110,4 +124,3 @@ export default function RegisterPage() {
</div>
);
}
-
diff --git a/pages/search.tsx b/pages/search.tsx
index 50a2410..2b8668a 100644
--- a/pages/search.tsx
+++ b/pages/search.tsx
@@ -1,45 +1,53 @@
-import { FormEvent, useState } from 'react';
import axios from 'axios';
+import { FormEvent, useState } from 'react';
+import { userInfo } from '../api/api';
+import { AccountAvatar } from '../components/account';
import { NavBar } from '../components/navbar';
-import { Vierkant, Button, Input } from '../components/ui';
import { CenteredPage, PageTitle } from '../components/page';
-import { AccountAvatar } from '../components/account';
-import { userInfo } from '../api/api';
+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('searchBar') as HTMLInputElement).value;
if (query.length < 3) return;
- axios.request<{ "results": Array<userInfo> }>({
- method: "post",
+ axios.request<{ 'results': Array<userInfo>; }>({
+ method: 'post',
url: `${window.location.origin}/api/social/search`,
- headers: {"content-type": "application/json"},
- data: { "query": query }
+ headers: { 'content-type': 'application/json' },
+ data: { 'query': query },
})
- .then(response => callback(response.data.results))
- .catch(() => {});
+ .then(response => callback(response.data.results))
+ .catch(() => {});
}
-function SearchResults(props: { userList: Array<userInfo> }) {
+function SearchResults(props: { userList: Array<userInfo>; }) {
return <div>
- { props.userList?.map(user => <SearchResult user={user} key={user.id}/>) }
+ {props.userList?.map(user => <SearchResult user={user} key={user.id} />)}
</div>;
}
-function SearchResult(props: { user: userInfo }) {
- return <Vierkant style={{
- padding: 12
- }} fullwidth href={"/user?id=" + props.user.id}>
- <div style={{ position: "relative" }}>
- <AccountAvatar size={48} id={props.user.id}/>
- <div style={{
- position: "absolute",
- top: 0, right: 0, bottom: 0,
- left: 48 + 12
- }}>
+function SearchResult(props: { user: userInfo; }) {
+ return <Vierkant
+ style={{
+ padding: 12,
+ }}
+ fullwidth
+ href={'/user?id=' + props.user.id}
+ >
+ <div style={{ position: 'relative' }}>
+ <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>
@@ -50,27 +58,42 @@ function SearchResult(props: { user: userInfo }) {
function SearchBar(props: {
searchFunction: (event?: FormEvent<HTMLFormElement>) => void;
}) {
- return <Vierkant fullwidth style={{
- padding: 8,
- marginBottom: 24
- }}>
+ return <Vierkant
+ fullwidth
+ style={{
+ padding: 8,
+ marginBottom: 24,
+ }}
+ >
<form onSubmit={props.searchFunction}>
- <Input id="searchBar" 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)"
- }}/>
- <Button style={{
- padding: 12,
- float: "right",
- display: "inline-block",
- borderRadius: 4
- }} onclick={props.searchFunction}><SearchOutlinedIcon/></Button>
- <input type="submit" style={{ display: "none" }}/>
+ <Input
+ id='searchBar'
+ 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)',
+ }}
+ />
+ <Button
+ style={{
+ padding: 12,
+ float: 'right',
+ display: 'inline-block',
+ borderRadius: 4,
+ }}
+ onclick={props.searchFunction}
+ >
+ <SearchOutlinedIcon />
+ </Button>
+ <input type='submit' style={{ display: 'none' }} />
</form>
- </Vierkant>
+ </Vierkant>;
}
export default function HomePage() {
@@ -80,21 +103,24 @@ export default function HomePage() {
event.preventDefault();
search(results => setResults(results));
setSearched(true);
- }
+ };
return <div>
- <NavBar/>
+ <NavBar />
<CenteredPage width={802}>
<PageTitle>Zoeken</PageTitle>
- <SearchBar searchFunction={getSearchResults}/>
- <SearchResults userList={results}/>
- { searched && results.length == 0 && <h1 style={{
- opacity: .6,
- color: "var(--text)",
- textAlign: "center",
- margin: "24px 32px"
- }}>Geen zoekresultaten gevonden</h1> }
+ <SearchBar searchFunction={getSearchResults} />
+ <SearchResults userList={results} />
+ {searched && results.length == 0 && <h1
+ style={{
+ opacity: .6,
+ color: 'var(--text)',
+ textAlign: 'center',
+ margin: '24px 32px',
+ }}
+ >
+ Geen zoekresultaten gevonden
+ </h1>}
</CenteredPage>
- </div>
+ </div>;
}
-
diff --git a/pages/settings.tsx b/pages/settings.tsx
index dcaa866..0f40a90 100644
--- a/pages/settings.tsx
+++ b/pages/settings.tsx
@@ -1,35 +1,35 @@
-import { CSSProperties, useContext } from 'react';
-import * as cookies from 'react-cookies';
import axios from 'axios';
import reduce from 'image-blob-reduce';
+import { CSSProperties, useContext } from 'react';
+import * as cookies from 'react-cookies';
-import { NavBar } from '../components/navbar';
-import { CenteredPage, PageTitle } from '../components/page';
-import { Vierkant, IconLabelButton, CheckBox, ColorPicker } from '../components/ui';
import { AccountAvatar } from '../components/account';
+import { Footer } from '../components/footer';
import { CurrentGameSettings } from '../components/gameSettings';
+import { NavBar } from '../components/navbar';
+import { CenteredPage, PageTitle } from '../components/page';
import PreferencesContext from '../components/preferencesContext';
-import { Footer } from '../components/footer';
+import { CheckBox, ColorPicker, IconLabelButton, Vierkant } from '../components/ui';
import EditOutlinedIcon from '@material-ui/icons/EditOutlined';
-import VisibilityOutlinedIcon from '@material-ui/icons/VisibilityOutlined';
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
+ minHeight: 40,
};
async function uploadNewProfileImage() {
if (!this.result) return;
- var result = this.result.split(";");
+ var result = this.result.split(';');
var mimeType = result[0].substr(5);
- if (!["image/png", "image/jpeg"].includes(mimeType)) return;
+ if (!['image/png', 'image/jpeg'].includes(mimeType)) return;
- var blob = await (await fetch(this.result)).blob()
+ var blob = await (await fetch(this.result)).blob();
var image = await new reduce().toBlob(blob, { max: 256 });
var reader = new FileReader();
@@ -37,13 +37,13 @@ async function uploadNewProfileImage() {
reader.readAsBinaryString(image);
reader.onload = async () => {
await axios.request({
- method: "post",
+ method: 'post',
url: `/api/user/avatar`,
- headers: {"content-type": "image/png"},
- data: btoa(reader.result as string)
+ headers: { 'content-type': 'image/png' },
+ data: btoa(reader.result as string),
});
- window.location.reload(); //TODO: this is straight garbage
- }
+ window.location.reload(); // TODO: this is straight garbage
+ };
}
export default function SettingsPage() {
@@ -51,48 +51,49 @@ export default function SettingsPage() {
return (
<div>
- <NavBar/>
+ <NavBar />
<CenteredPage width={802}>
<PageTitle>Instellingen</PageTitle>
<Vierkant fullwidth>
<h2>Account</h2>
<div style={SettingsSubsectionStyle}>
- <AccountAvatar size={100}/>
- <label htmlFor="pfUpload">
- <IconLabelButton text="Nieuwe profielfoto uploaden" icon={<PublishOutlinedIcon/>}/>
+ <AccountAvatar size={100} />
+ <label htmlFor='pfUpload'>
+ <IconLabelButton text='Nieuwe profielfoto uploaden' icon={<PublishOutlinedIcon />} />
</label>
<input
- type="file"
- id="pfUpload"
- accept=".png,.jpg,.jpeg"
- style={{ display: "none" }}
+ type='file'
+ id='pfUpload'
+ accept='.png,.jpg,.jpeg'
+ style={{ display: 'none' }}
onChange={event => {
- var file = event.target.files[0];
- if (!file) return;
+ var file = event.target.files[0];
+ if (!file) return;
- var reader = new FileReader();
- reader.onload = uploadNewProfileImage;
- reader.readAsDataURL(file);
- }}/>
+ var reader = new FileReader();
+ reader.onload = uploadNewProfileImage;
+ reader.readAsDataURL(file);
+ }}
+ />
</div>
<div style={SettingsSubsectionStyle}>
- <IconLabelButton text="Bewerken" icon={<EditOutlinedIcon/>}/>
- <div style={{ display: "block" }}>
+ <IconLabelButton text='Bewerken' icon={<EditOutlinedIcon />} />
+ <div style={{ display: 'block' }}>
<h3>Gebruikersnaam</h3>
<p>Hier staat hij dan</p>
</div>
</div>
<div style={SettingsSubsectionStyle}>
- <IconLabelButton text="Bewerken" icon={<EditOutlinedIcon/>}/>
- <IconLabelButton text="Onthullen" icon={<VisibilityOutlinedIcon/>}/>
- <div style={{ display: "block" }}>
+ <IconLabelButton text='Bewerken' icon={<EditOutlinedIcon />} />
+ <IconLabelButton text='Onthullen' icon={<VisibilityOutlinedIcon />} />
+ <div style={{ display: 'block' }}>
<h3>Email</h3>
<p>******@example.com</p>
</div>
</div>
<div style={SettingsSubsectionStyle}>
- <IconLabelButton text="Bewerken" icon={<EditOutlinedIcon/>}/>
- <div style={{ display: "block" }}>
+ <IconLabelButton text='Bewerken' icon={<EditOutlinedIcon />} />
+ <div style={{ display: 'block' }}>
<h3>Wachtwoord</h3>
</div>
</div>
@@ -100,23 +101,24 @@ export default function SettingsPage() {
<Vierkant fullwidth>
<h2>Kleuren</h2>
<div style={SettingsSubsectionStyle}>
- <ColorPicker/>
- <ColorPicker/>
- <div style={{ display: "block" }}>
+ <ColorPicker />
+ <ColorPicker />
+ <div style={{ display: 'block' }}>
<h3>Schijfjes</h3>
</div>
</div>
<div style={SettingsSubsectionStyle}>
- <ColorPicker/>
- <div style={{ display: "block" }}>
+ <ColorPicker />
+ <div style={{ display: 'block' }}>
<h3>Achtergrond</h3>
</div>
</div>
<div style={SettingsSubsectionStyle}>
- <div style={{ float: "right" }}>
- <CheckBox state={preferences?.darkMode} onclick={
- state => updatePreference({"darkMode": state})
- }/>
+ <div style={{ float: 'right' }}>
+ <CheckBox
+ state={preferences?.darkMode}
+ onclick={state => updatePreference({ 'darkMode': state })}
+ />
</div>
<h3>Donkere modus</h3>
</div>
@@ -124,27 +126,33 @@ export default function SettingsPage() {
<Vierkant fullwidth>
<h2>Standaard spelregels</h2>
<div style={SettingsSubsectionStyle}>
- <CurrentGameSettings/>
+ <CurrentGameSettings />
</div>
</Vierkant>
<Vierkant fullwidth>
<h2>Uitloggen</h2>
- <div style={{
- width: "100%",
- textAlign: "center"
- }}>
- <IconLabelButton icon={<ExitToAppOutlinedIcon/>} text="Uitloggen" style={{
- float: "none",
- marginLeft: 0
- }} onclick={() => {
- cookies.remove("token")
- window.location.pathname = "/";
- }}/>
+ <div
+ style={{
+ width: '100%',
+ textAlign: 'center',
+ }}
+ >
+ <IconLabelButton
+ icon={<ExitToAppOutlinedIcon />}
+ text='Uitloggen'
+ style={{
+ float: 'none',
+ marginLeft: 0,
+ }}
+ onclick={() => {
+ cookies.remove('token');
+ window.location.pathname = '/';
+ }}
+ />
</div>
</Vierkant>
</CenteredPage>
- <Footer/>
+ <Footer />
</div>
);
}
-
diff --git a/pages/user.tsx b/pages/user.tsx
index 5f5b1eb..4f7331c 100644
--- a/pages/user.tsx
+++ b/pages/user.tsx
@@ -1,89 +1,106 @@
-import { ReactNode, Children, useState, useEffect, useContext } from 'react';
import Icon from '@mdi/react';
import axios from 'axios';
+import { Children, ReactNode, useContext, useEffect, useState } from 'react';
+import { userGames, userInfo } from '../api/api';
+import { AccountAvatar } from '../components/account';
+import { Footer } from '../components/footer';
import { NavBar } from '../components/navbar';
import { CenteredPage, PageTitle } from '../components/page';
-import { Vierkant, IconLabelButton } from '../components/ui';
-import { AccountAvatar } from '../components/account';
-import { userInfo, userGames } from '../api/api';
import RecentGames from '../components/recentGames';
-import { ToastContext } from '../components/toast';
import { SocketContext } from '../components/socketContext';
-import { Footer } from '../components/footer';
+import { ToastContext } from '../components/toast';
+import { IconLabelButton, Vierkant } from '../components/ui';
-import PersonAddOutlinedIcon from '@material-ui/icons/PersonAddOutlined';
-import AssignmentIndOutlinedIcon from '@material-ui/icons/AssignmentIndOutlined';
import ArrowDownwardOutlinedIcon from '@material-ui/icons/ArrowDownwardOutlined';
import ArrowUpwardOutlinedIcon from '@material-ui/icons/ArrowUpwardOutlined';
-import PeopleOutlineOutlinedIcon from '@material-ui/icons/PeopleOutlineOutlined';
+import AssignmentIndOutlinedIcon from '@material-ui/icons/AssignmentIndOutlined';
+import DoneOutlinedIcon from '@material-ui/icons/DoneOutlined';
import EditOutlinedIcon from '@material-ui/icons/EditOutlined';
+import PeopleOutlineOutlinedIcon from '@material-ui/icons/PeopleOutlineOutlined';
+import PersonAddOutlinedIcon from '@material-ui/icons/PersonAddOutlined';
import SettingsOutlinedIcon from '@material-ui/icons/SettingsOutlined';
-import DoneOutlinedIcon from '@material-ui/icons/DoneOutlined';
import {
mdiAccountCancelOutline,
- mdiEqual,
+ mdiAccountMinusOutline,
+ mdiAccountRemoveOutline,
mdiCheckboxBlankCircle,
mdiClipboardTextOutline,
- mdiGamepadSquareOutline,
mdiEarth,
- mdiAccountMinusOutline,
- mdiAccountRemoveOutline } from '@mdi/js';
+ mdiEqual,
+ mdiGamepadSquareOutline,
+} from '@mdi/js';
function InfoModule(props: {
label: string;
icon: ReactNode;
}) {
- return <div style={{
- position: "relative",
- height: "100%"
- }}>
- <div style={{
- position: "absolute",
- left: "50%",
- transform: "translateX(-50%)"
- }}>{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"
- }}>{props.label}</span>
+ return <div
+ style={{
+ position: 'relative',
+ height: '100%',
+ }}
+ >
+ <div
+ style={{
+ position: 'absolute',
+ left: '50%',
+ transform: 'translateX(-50%)',
+ }}
+ >
+ {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',
+ }}
+ >
+ {props.label}
+ </span>
</div>
- </div>
+ </div>;
}
-function InfoSection(props: { children: ReactNode }) {
+function InfoSection(props: { children: ReactNode; }) {
return <Vierkant fullwidth>
- <div style={{
- display: "grid",
- gridTemplateColumns: `repeat(${Children.count(props.children)}, 1fr)`,
- gridGap: 12,
- height: 64
- }}>
+ <div
+ style={{
+ display: 'grid',
+ gridTemplateColumns: `repeat(${Children.count(props.children)}, 1fr)`,
+ gridGap: 12,
+ height: 64,
+ }}
+ >
{props.children}
</div>
- </Vierkant>
+ </Vierkant>;
}
export default function AccountPage() {
- var server = typeof window === "undefined";
- var loggedIn = !server && document.cookie.includes("token");
- var pageID = server ? "" : new URLSearchParams(window.location.search).get("id");
+ var server = typeof window === 'undefined';
+ var loggedIn = !server && document.cookie.includes('token');
+ var pageID = server ? '' : new URLSearchParams(window.location.search).get('id');
if (!loggedIn && !pageID) !server && window.history.go(-1);
- var reqData = loggedIn && pageID ? { "id": pageID } : undefined;
+ var reqData = loggedIn && pageID ? { 'id': pageID } : undefined;
var [user, setUser] = useState<userInfo>();
var [gameInfo, setGameInfo] = useState<userGames>();
var [editingStatus, setEditingStatus] = useState(false);
- var [relation, setRelation] = useState<userInfo["relation"]>("none");
+ var [relation, setRelation] = useState<userInfo['relation']>('none');
var [ownPage, setOwnPage] = useState(loggedIn && !pageID);
var { toast } = useContext(ToastContext);
@@ -91,237 +108,288 @@ export default function AccountPage() {
async function getUserData(): Promise<userInfo> {
var userReq = await axios.request<userInfo>({
- method: "post",
+ method: 'post',
url: `/api/user/info`,
- headers: {"content-type": "application/json"},
- data: reqData
+ headers: { 'content-type': 'application/json' },
+ data: reqData,
});
setUser(userReq.data);
- return userReq.data
+ return userReq.data;
}
async function getRelationTo(user: userInfo) {
var user = await getUserData();
- setRelation(user.relation || "none");
+ setRelation(user.relation || 'none');
}
function setIOListeners(user: userInfo) {
- io.on("changedRelation", (data: { id: string }) => {
+ io.on('changedRelation', (data: { id: string; }) => {
if (data.id != user.id) return;
getRelationTo(user);
});
- io.on("incomingFriendRequest", getRelationTo);
+ io.on('incomingFriendRequest', getRelationTo);
}
- useEffect(() => {(async() => {
- var user = await getUserData();
+ useEffect(() => {
+ (async () => {
+ var user = await getUserData();
- getRelationTo(user);
- setIOListeners(user);
- })()}, []);
+ getRelationTo(user);
+ setIOListeners(user);
+ })();
+ }, []);
- useEffect(() => {(async() => {
- var userReq = await axios.request<userInfo>({
- method: "post",
- url: `/api/user/info`,
- headers: {"content-type": "application/json"}
- });
- setOwnPage(ownPage || userReq.data.id == pageID);
- })()}, []);
+ useEffect(() => {
+ (async () => {
+ var userReq = await axios.request<userInfo>({
+ method: 'post',
+ url: `/api/user/info`,
+ headers: { 'content-type': 'application/json' },
+ });
+ setOwnPage(ownPage || userReq.data.id == pageID);
+ })();
+ }, []);
// Get recent games
- useEffect(() => {(async() => {
- var userGamesReq = await axios.request<userGames>({
- method: "post",
- url: `/api/user/games`,
- headers: {"content-type": "application/json"},
- data: reqData
- });
- setGameInfo(userGamesReq.data);
- })()}, []);
+ useEffect(() => {
+ (async () => {
+ var userGamesReq = await axios.request<userGames>({
+ method: 'post',
+ url: `/api/user/games`,
+ headers: { 'content-type': 'application/json' },
+ data: reqData,
+ });
+ setGameInfo(userGamesReq.data);
+ })();
+ }, []);
return <div>
- <NavBar/>
+ <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)"
- }}>
+ <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>
+ <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)}/> :
- <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}/>
+ <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)}
+ />
+ : <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",
- "icon": <Icon size={1} path={mdiAccountCancelOutline}/>,
- }
- }[relation] || {
- "endpoint": "/api/social/block",
- "action": `${user.username} geblokkeerd`,
- "relation": "blocked",
- "icon": <Icon size={1} path={mdiAccountCancelOutline}/>,
- }
+ 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} />,
+ };
- 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);
- });
- }}/>
- })()}
- {(() => {
- var icon = {
- "friends": <Icon size={1} path={mdiAccountMinusOutline}/>,
- "outgoing": <Icon size={1} path={mdiAccountRemoveOutline}/>,
- "incoming": <PersonAddOutlinedIcon/>
- }[relation] || <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,
+ });
+ setRelation(nextRelation.relation);
+ });
+ }}
+ />;
+ })()}
+ {(() => {
+ 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",
- "icon": <PersonAddOutlinedIcon/>,
- },
- }[relation] || {
- "endpoint": "/api/social/request",
- "action": `Vriendschapsverzoek gestuurd naar ${user.username}`,
- "relation": "outgoing",
- "icon": <PersonAddOutlinedIcon/>,
- }
+ 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 />,
+ };
- 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);
- });
- }}/>
- })()}
- </div>
- }</div>}
+ 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);
+ });
+ }}
+ />;
+ })()}
+ </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";
+ <InfoModule
+ icon={<Icon size={1} path={mdiCheckboxBlankCircle} color='var(--disk-b-text)' />}
+ 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"/>
+ 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;
- })()}/>
+ <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>
- <RecentGames games={gameInfo?.games}/>
+ <RecentGames games={gameInfo?.games} />
</Vierkant>
</CenteredPage>
- <Footer/>
- </div>
+ <Footer />
+ </div>;
}
-