aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <l.leblansch@gmail.com>2021-03-12 16:10:01 +0100
committerlonkaars <l.leblansch@gmail.com>2021-03-12 16:10:01 +0100
commita4c0d88cf6d2137f61fc6005ad2c6339c7f3c9d8 (patch)
treecdc60c55319a9de01cac59cd7a66576f8f7db619
parenta69b5df8beddb4a9b492e29ba32747c368666239 (diff)
toast context working
-rw-r--r--components/toast.tsx77
-rw-r--r--pages/_app.tsx5
-rw-r--r--pages/user.tsx25
3 files changed, 71 insertions, 36 deletions
diff --git a/components/toast.tsx b/components/toast.tsx
index 03a6255..5bfc0ae 100644
--- a/components/toast.tsx
+++ b/components/toast.tsx
@@ -1,10 +1,11 @@
-import { CSSProperties, ReactNode, Component } from "react";
+import { CSSProperties, ReactNode, useState, createContext } from "react";
import CloseIcon from '@material-ui/icons/Close';
-export function ToastArea(props: {
+function ToastArea(props: {
style?: CSSProperties
children?: ReactNode
+ rerender?: boolean;
}) {
return <div id="ToastArea" style={{
position: "fixed",
@@ -20,35 +21,32 @@ export function ToastArea(props: {
}}>{props.children}</div>
}
-export class Toast extends Component<{
+function Toast(props: {
text?: string
icon?: ReactNode
children?: ReactNode
type?: "normal"|"confirmation"|"error"
style?: CSSProperties
-}> {
- state = { render: true }
+}) {
+ var [visible, setVisibility] = useState(true);
- close = () => this.setState({ render: false })
+ setTimeout(() => setVisibility(false), 10e3);
- render () {
- if (!this.state.render) return null;
- return <div style={{
- padding: 0,
- marginBottom: 12,
- borderRadius: 8,
- boxShadow: "0 8px 12px -4px #00000033",
- color:
- this.props.type === "confirmation" ? "var(--background)" : "var(--text)",
- backgroundColor:
- this.props.type === "normal" ? "var(--background)" :
- this.props.type === "confirmation" ? "var(--disk-b)" :
- this.props.type === "error" ? "var(--disk-a)" : "var(--background)",
- ...this.props.style
- }}>
+ return visible && <div style={{
+ padding: 0,
+ marginBottom: 12,
+ borderRadius: 8,
+ boxShadow: "0 8px 12px -4px #00000033",
+ color:
+ props.type === "confirmation" ? "var(--background)" : "var(--text)",
+ backgroundColor:
+ props.type === "normal" ? "var(--background)" :
+ props.type === "confirmation" ? "var(--disk-b)" :
+ props.type === "error" ? "var(--disk-a)" : "var(--background)",
+ ...props.style
+ }}>
{
- this.props.children ?
- this.props.children :
+ props.children ||
<div style={{ lineHeight: 0 }}>
<div style={{
fontSize: 0,
@@ -56,24 +54,45 @@ export class Toast extends Component<{
display: "inline-block",
verticalAlign: "top",
width: 32, height: 32
- }}>{this.props.icon}</div>
+ }}>{props.icon}</div>
<h2 style={{
margin: "20px 0",
display: "inline-block",
width: "calc(100% - 128px)",
verticalAlign: "top",
- fontSize: 20
- }}>{this.props.text}</h2>
+ fontSize: 20,
+ userSelect: "none"
+ }}>{props.text}</h2>
<div style={{
padding: 20,
display: "inline-block",
cursor: "pointer"
- }} onClick={this.close}>
+ }} onClick={() => setVisibility(false)}>
<CloseIcon/>
</div>
</div>
}
- </div>
- }
+ </div>
+}
+
+export var ToastContext = createContext<{ toast?: (message: string,
+ type: "confirmation"|"normal"|"error",
+ icon?: ReactNode ) => void }>({});
+var toasts: Array<JSX.Element> = [];
+
+export function ToastContextWrapper(props: { children?: ReactNode }) {
+ var [dummyState, rerender] = useState(false);
+
+ return <ToastContext.Provider value={{ toast: (message: string,
+ type: "confirmation"|"normal"|"error",
+ icon?: ReactNode ) => {
+ toasts.push(<Toast type={type} text={message} icon={icon}/>);
+ rerender(!dummyState);
+ } }}>
+ { props.children }
+ <ToastArea rerender={dummyState}>
+ {toasts}
+ </ToastArea>
+ </ToastContext.Provider>
}
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 3c238b9..651d05d 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,5 +1,6 @@
import Head from 'next/head';
import { PreferencesContextWrapper } from '../components/preferencesContext';
+import { ToastContextWrapper } from '../components/toast';
import '../styles/global.css';
import '../styles/dark.css';
@@ -12,7 +13,9 @@ export default function VierOpEenRijWebsite({ Component, pageProps }) {
<link rel="stylesheet" href="/font/stylesheet.css"/>
</Head>
<PreferencesContextWrapper>
- <Component {...pageProps}/>
+ <ToastContextWrapper>
+ <Component {...pageProps}/>
+ </ToastContextWrapper>
</PreferencesContextWrapper>
</div>
}
diff --git a/pages/user.tsx b/pages/user.tsx
index 71177d3..c7a78e6 100644
--- a/pages/user.tsx
+++ b/pages/user.tsx
@@ -1,4 +1,4 @@
-import { ReactNode, Children, useState, useEffect } from 'react';
+import { ReactNode, Children, useState, useEffect, useContext } from 'react';
import Icon from '@mdi/react';
import axios from 'axios';
@@ -8,6 +8,7 @@ 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 PersonAddOutlinedIcon from '@material-ui/icons/PersonAddOutlined';
import AssignmentIndOutlinedIcon from '@material-ui/icons/AssignmentIndOutlined';
@@ -72,15 +73,19 @@ export default function AccountPage() {
var [user, setUser] = useState<userInfo>();
var [ownPage, setOwnPage] = useState(false);
var [gameInfo, setGameInfo] = useState<userGames>();
+ var [loggedIn, setLoggedIn] = useState(false);
var [editingStatus, setEditingStatus] = useState(false);
+ var { toast } = useContext(ToastContext);
+
useEffect(() => {(async() => {
if (gotData) return;
if (typeof window === "undefined") return;
var id = new URLSearchParams(window.location.search).get("id");
var loggedIn = document.cookie.includes("token");
+ setLoggedIn(loggedIn);
if (id || loggedIn) {
var self_id = "";
@@ -137,7 +142,7 @@ export default function AccountPage() {
<p id="status" contentEditable={editingStatus ? "true" : "false"} style={{
marginTop: 6,
transitionDuration: ".3s"
- }}>{user?.status}</p>
+ }} suppressContentEditableWarning={true}>{user?.status}</p>
</div>
<div style={{
position: "absolute",
@@ -145,7 +150,7 @@ export default function AccountPage() {
height: "40px",
bottom: 24, left: 24 + 12 + 128, right: 24
}}>
- {
+ { loggedIn && <div> {
ownPage ?
<div>
<IconLabelButton icon={<SettingsOutlinedIcon/>} href="/settings" text="Instellingen"/>
@@ -170,10 +175,18 @@ export default function AccountPage() {
}
</div> :
<div>
- <IconLabelButton icon={<Icon size={1} path={mdiAccountCancelOutline}/>} text="Blokkeren"/>
- <IconLabelButton icon={<PersonAddOutlinedIcon/>} text="Vriendschapsverzoek"/>
+ <IconLabelButton icon={<Icon size={1} path={mdiAccountCancelOutline}/>} text="Blokkeren" onclick={() => {
+ toast(`${user.username} geblokkeerd`,
+ "confirmation",
+ <Icon size={32 / 24} path={mdiAccountCancelOutline}/>)
+ }}/>
+ <IconLabelButton icon={<PersonAddOutlinedIcon/>} text="Vriendschapsverzoek" onclick={() => {
+ toast("Vriendschapsverzoek gestuurd",
+ "confirmation",
+ <PersonAddOutlinedIcon style={{ fontSize: 32 }}/>)
+ }}/>
</div>
- }
+ }</div>}
</div>
</Vierkant>
<InfoSection>