aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components/ui.tsx17
-rw-r--r--package.json1
-rw-r--r--pages/game.tsx47
-rw-r--r--styles/game.css20
-rw-r--r--yarn.lock5
5 files changed, 86 insertions, 4 deletions
diff --git a/components/ui.tsx b/components/ui.tsx
index 7474240..1e9997a 100644
--- a/components/ui.tsx
+++ b/components/ui.tsx
@@ -1,4 +1,5 @@
import { ReactNode, useEffect, useState } from 'react';
+import { v4 as uuid } from 'uuid';
import CheckBoxIcon from '@material-ui/icons/CheckBox';
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
@@ -79,6 +80,7 @@ export function Input(props: {
autocomplete?: string;
autofocus?: boolean;
className?: string;
+ onChange?: () => void;
}) {
return <input
id={props.id}
@@ -91,16 +93,25 @@ export function Input(props: {
className={'input' + ' ' + (props.dark ? 'dark' : 'light') + ' ' + props.className}
autoComplete={props.autocomplete}
autoFocus={props.autofocus}
+ onChange={props.onChange}
/>;
}
-export function SearchBar(props: { label?: string; }) {
- return <div className='searchBar round-t fullwidth'>
+export function SearchBar(props: {
+ label?: string;
+ search?: (query: string) => void;
+}) {
+ var id = uuid();
+
+ var getQuery = () => (document.getElementById(id).children[0] as HTMLInputElement).value;
+
+ return <div className='searchBar round-t fullwidth' id={id}>
<Input
label={props.label}
className='pad-m bg-700'
+ onChange={() => props.search && props.search(getQuery())}
/>
- <Button className='dispinbl valigntop'>
+ <Button className='dispinbl valigntop' onclick={() => props.search && props.search(getQuery())}>
<SearchIcon className='icon' />
</Button>
</div>;
diff --git a/package.json b/package.json
index 75fa8b1..d0e01e0 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"copy-to-clipboard": "^3.3.1",
"email-validator": "^2.0.4",
"friendly-time": "^1.1.1",
+ "fuse.js": "^6.4.6",
"image-blob-reduce": "^2.2.2",
"micromark": "^2.11.4",
"next": "^10.0.5",
diff --git a/pages/game.tsx b/pages/game.tsx
index de2c089..f6c6f5b 100644
--- a/pages/game.tsx
+++ b/pages/game.tsx
@@ -1,11 +1,13 @@
import Icon from '@mdi/react';
import axios from 'axios';
import copy from 'copy-to-clipboard';
+import Fuse from 'fuse.js';
import { useContext, useEffect, useState } from 'react';
import * as cookies from 'react-cookies';
import { Socket } from 'socket.io-client';
import { SocketContext } from '../components/socketContext';
+import { userInfo } from '../api/api';
import { DialogBox } from '../components/dialogBox';
import { GameBar } from '../components/gameBar';
import { CurrentGameSettings } from '../components/gameSettings';
@@ -15,11 +17,13 @@ import { ToastContext, toastType } from '../components/toast';
import { Button, IconLabelButton, SearchBar } from '../components/ui';
import { VoerBord } from '../components/voerBord';
+import AddIcon from '@material-ui/icons/Add';
import FlagOutlinedIcon from '@material-ui/icons/FlagOutlined';
import LinkRoundedIcon from '@material-ui/icons/LinkRounded';
import RefreshIcon from '@material-ui/icons/Refresh';
import WifiTetheringRoundedIcon from '@material-ui/icons/WifiTetheringRounded';
import { mdiContentCopy } from '@mdi/js';
+import { AccountAvatar } from '../components/account';
function VoerGame(props: {
gameID: string;
@@ -139,11 +143,28 @@ function GameOutcomeDialog(props: {
</DialogBox>;
}
+function InviteableFriend(props: { user?: userInfo; }) {
+ return <div className='round-t bg-700 inviteableFriend drop-1 posrel'>
+ <AccountAvatar size={44} id={props.user?.id} />
+ <span className='username nosel posabs abscenterv pad-m'>{props.user?.username}</span>
+ <Button className='floatr dispinbl' children={<AddIcon />} />
+ </div>;
+}
+
export default function GamePage() {
var [gameID, setGameID] = useState('');
var [player1, setPlayer1] = useState(true);
var [active, setActive] = useState(false);
var [gameIDUrl, setGameIDUrl] = useState('');
+ var [friendList, setFriendList] = useState<userInfo[]>([]);
+
+ var [query, setQuery] = useState('');
+ var [visibleFriends, setVisibleFriends] = useState<userInfo[]>([]);
+
+ var fuse = new Fuse(friendList, {
+ keys: ['username'],
+ isCaseSensitive: false,
+ });
var { io } = useContext(SocketContext);
var { toast } = useContext(ToastContext);
@@ -174,6 +195,27 @@ export default function GamePage() {
}, []);
useEffect(() => {
+ axios.request<{ friends: Array<userInfo>; }>({
+ method: 'get',
+ url: '/api/social/list/friends',
+ })
+ .then(response => {
+ console.log(response.data.friends);
+ setFriendList(response.data.friends);
+ })
+ .catch(err => {
+ toast({ message: 'error', type: 'error', description: err.toString() });
+ });
+ }, []);
+
+ useEffect(() => {
+ var fuseSearch = fuse.search(query);
+ var results = fuseSearch.map(res => res.item).slice(0, 5);
+
+ setVisibleFriends(results);
+ }, [query]);
+
+ useEffect(() => {
io.on('gameStart', () => setActive(true));
}, []);
@@ -246,7 +288,10 @@ export default function GamePage() {
<h2 className='label center posabs abscenterh nosel'>Uitnodigen via link</h2>
</Button>
</div>
- <SearchBar label='Zoeken in vriendenlijst' />
+ <div className='inviteFromFriendsList'>
+ <SearchBar label='Zoeken in vriendenlijst' search={q => setQuery(q)} />
+ {visibleFriends.map(user => <InviteableFriend user={user} />)}
+ </div>
</DialogBox>
</CenteredPage>
</div>;
diff --git a/styles/game.css b/styles/game.css
index d482f9b..5954991 100644
--- a/styles/game.css
+++ b/styles/game.css
@@ -74,3 +74,23 @@ html.dark .newGameDialog .inviteButton.random .icon { color: var(--confirm); }
html.dark .newGameDialog .inviteButton.link .icon { color: var(--error); }
html.dark .newGameDialog .searchBar .input { background-color: var(--gray-800); }
+.inviteFromFriendsList {
+ overflow-y: visible;
+ height: 44px;
+}
+
+html.dark .inviteFromFriendsList .inviteableFriend {
+ background-color: var(--gray-800);
+}
+.inviteFromFriendsList .inviteableFriend {
+ margin-top: var(--spacing-small);
+ overflow: hidden;
+ cursor: pointer;
+}
+
+.inviteFromFriendsList .inviteableFriend .button {
+ background-color: transparent;
+ color: var(--foreground);
+ padding: 10px;
+}
+
diff --git a/yarn.lock b/yarn.lock
index 05ae7bb..3be934e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5922,6 +5922,11 @@ functional-red-black-tree@^1.0.1:
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
+fuse.js@^6.4.6:
+ version "6.4.6"
+ resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-6.4.6.tgz#62f216c110e5aa22486aff20be7896d19a059b79"
+ integrity sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw==
+
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"