Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion backend/src/db/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ diesel::table! {
diesel::table! {
users (uid) {
uid -> Text,
#[max_length = 40]
username -> Varchar,
is_guest -> Bool,
}
Expand Down
2 changes: 1 addition & 1 deletion backend/src/extractors/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl FromRequest for AuthenticatedUser {
.expect("couldn't retrieve server config");
let auth_token = req_clone
.headers()
.get("x-authentication")
.get("x-authorization")
.ok_or(AuthenticationError::MissingToken)?
.to_str()
.map_err(|err| {
Expand Down
12 changes: 10 additions & 2 deletions js/frontend/components/game-online/GameOnline.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Game } from 'hive-db';
import { HexCoordinate, TileId } from 'hive-lib';
import { useCallback } from 'react';
import { useCallback, useEffect } from 'react';
import {
useGameDispatch,
useGameSelector
Expand All @@ -14,9 +14,11 @@ import {
import {
ghostClicked,
tableClicked,
tableStackClicked
tableStackClicked,
authTokenAdded
} from '../../state/game-online/slice';
import { Table } from '../game-common/Table';
import { usePlayer } from '../../../hive-db/src/PlayerProvider';

const GameOnline = ({ uid, game }: { uid: string | null; game: Game }) => {
const hexSize = 50;
Expand All @@ -26,6 +28,12 @@ const GameOnline = ({ uid, game }: { uid: string | null; game: Game }) => {
const ghosts = useGameSelector(selectValidMovesForTile);
const selectedTileId = useGameSelector(selectSelectedTileId);
const boardCentered = useGameSelector(selectBoardCentered);
const { authToken } = usePlayer();

console.log(ghosts);

// TODO: Neel: probably not the right place to do this
useEffect(() => dispatch(authTokenAdded(authToken)));

const onClickTable = useCallback(() => dispatch(tableClicked()), [dispatch]);
const onClickTableStack = useCallback(
Expand Down
10 changes: 5 additions & 5 deletions js/frontend/components/lists/ListLobbyGames.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
acceptGameChallenge,
GameChallenge,
useLobbyChallenges,
usePlayer,
usePlayer
} from 'hive-db';
import { Button } from '@chakra-ui/react';
import { Header, HeaderItem } from './Header';
Expand All @@ -26,15 +26,15 @@ const LobbyChallengeRow = ({ challenge }: LobbyChallengeRowProps) => {
return (
<Row>
<RowItem>{challenge.challenger.username}</RowItem>
<RowItem>{isRated ? 'Rated' : 'Unrated'}</RowItem>
<RowItem>{isRated ? 'Rated' : 'Not rated'}</RowItem>
<RowItem>{tournament ? 'Tournament' : 'Normal'}</RowItem>
<ExpansionsItem ladybug={ladybug} mosquito={mosquito} pillbug={pillbug} />
<RowItem>{challenge.createdAt.toDateString()}</RowItem>
<RowItem>
<Button
colorScheme="green"
colorScheme='green'
disabled={!canAccept}
size="sm"
size='sm'
onClick={() => {
acceptGameChallenge(challenge.id, authToken)
.then((game) => console.log(game)) // TODO: navigate to the newly created game
Expand All @@ -55,7 +55,7 @@ const ListLobbyGames = (props: ListLobbyGamesProps) => {
const { data: challenges, isLoading, error } = useLobbyChallenges();

if (isLoading || error) {
return <Spinner />
return <Spinner />;
}

return (
Expand Down
60 changes: 40 additions & 20 deletions js/frontend/components/lists/ListPlayerChallenges.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { Button, Input, Popover, PopoverArrow, PopoverBody, PopoverCloseButton, PopoverContent, PopoverHeader, PopoverTrigger, Spinner, useClipboard } from '@chakra-ui/react';
import {
Button,
Input,
Popover,
PopoverArrow,
PopoverBody,
PopoverCloseButton,
PopoverContent,
PopoverHeader,
PopoverTrigger,
Spinner,
useClipboard
} from '@chakra-ui/react';
import {
deleteGameChallenge,
GameChallenge,
usePlayerChallenges,
usePlayer,
useLobbyChallenges,
useLobbyChallenges
} from 'hive-db';
import { HTMLAttributes, useState } from 'react';
import { Header, HeaderItem } from './Header';
Expand All @@ -16,9 +28,7 @@ const ShareLinkButton = ({ text }: { text: string }) => {
return (
<Popover>
<PopoverTrigger>
<Button size='xs'>
Share link
</Button>
<Button size='xs'>Share link</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
Expand All @@ -28,7 +38,7 @@ const ShareLinkButton = ({ text }: { text: string }) => {
Send this link to a friend to invite them!
</PopoverHeader>
<Input
type="text"
type='text'
size='sm'
isReadOnly={true}
onFocus={handleInputFocus}
Expand All @@ -37,10 +47,16 @@ const ShareLinkButton = ({ text }: { text: string }) => {
</PopoverBody>
</PopoverContent>
</Popover>
)
}
);
};

const DeleteButton = ({ id, onDelete }: { id: string, onDelete: () => void }) => {
const DeleteButton = ({
id,
onDelete
}: {
id: string;
onDelete: () => void;
}) => {
const { authToken } = usePlayer();
return (
<Button
Expand Down Expand Up @@ -73,7 +89,7 @@ const PlayerChallengeRow = ({ challenge }: PlayerChallengeRowProps) => {
const pillbug = challenge.gameType.pillbug;
return (
<Row>
<RowItem>{isRated ? 'Rated' : 'Unrated'}</RowItem>
<RowItem>{isRated ? 'Rated' : 'Not rated'}</RowItem>
<RowItem>{isPublic ? 'Public' : 'Private'}</RowItem>
<RowItem>{tournament ? 'Tournament' : 'Normal'}</RowItem>
<ExpansionsItem ladybug={ladybug} mosquito={mosquito} pillbug={pillbug} />
Expand All @@ -82,15 +98,19 @@ const PlayerChallengeRow = ({ challenge }: PlayerChallengeRowProps) => {
<ShareLinkButton text={challenge.getChallengeUrl()} />
</RowItem>
<RowItem>
<DeleteButton id={id} onDelete={() => {
const removeChallenge = (challenges) => challenges.filter((other) => {
return other.id == challenge.id;
});
mutatePlayerChallenges(removeChallenge);
if (challenge.public) {
mutateLobbyChallenges(removeChallenge);
}
}} />
<DeleteButton
id={id}
onDelete={() => {
const removeChallenge = (challenges) =>
challenges.filter((other) => {
return other.id == challenge.id;
});
mutatePlayerChallenges(removeChallenge);
if (challenge.public) {
mutateLobbyChallenges(removeChallenge);
}
}}
/>
</RowItem>
</Row>
);
Expand All @@ -101,7 +121,7 @@ const ListPlayerChallenges = (props: HTMLAttributes<HTMLDivElement>) => {
const { challenges, error, isLoading } = usePlayerChallenges();

if (isLoading || error) {
return <Spinner />
return <Spinner />;
}

return (
Expand Down
95 changes: 68 additions & 27 deletions js/frontend/pages/challenge/[challengeId].tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import Head from 'next/head';
import { useRouter } from 'next/router';
import { acceptGameChallenge, ExpansionsChoice, GameChallenge, getGameChallenge, usePlayer, UserData } from 'hive-db';
import {
acceptGameChallenge,
ExpansionsChoice,
GameChallenge,
getGameChallenge,
usePlayer,
UserData
} from 'hive-db';
import { NavBar } from '../../components/nav/NavBar';
import { useTitle } from '../../hooks/useTitle';
import { useEffect, useState } from 'react';
import { Body } from '../../components/common/Body';
import { Footer } from '../../components/common/Footer';
import { Button, List, ListIcon, ListItem } from '@chakra-ui/react';
import { MdCalendarToday, MdCircle, MdOutlineContrast, MdLooksOne, MdOutlineBugReport, MdOutlineCircle, MdOutlineEmojiEvents } from 'react-icons/md';
import {
MdCalendarToday,
MdCircle,
MdOutlineContrast,
MdLooksOne,
MdOutlineBugReport,
MdOutlineCircle,
MdOutlineEmojiEvents
} from 'react-icons/md';

function getExpansionDescription(gameType: ExpansionsChoice): string {
const expansionPieces = []
const expansionPieces = [];
if (gameType.mosquito) {
expansionPieces.push('Mosquito');
}
Expand All @@ -27,53 +42,69 @@ function getExpansionDescription(gameType: ExpansionsChoice): string {
}
}

const ColorChoiceItem = ({colorChoice}: {colorChoice: string}) => {
const ColorChoiceItem = ({ colorChoice }: { colorChoice: string }) => {
switch (colorChoice) {
case 'White':
return <><ListIcon as={MdOutlineCircle} />{'Challenger is white'}</>;
return (
<>
<ListIcon as={MdOutlineCircle} />
{'Challenger is white'}
</>
);
case 'Black':
return <><ListIcon as={MdCircle} />{'Challenger is black'}</>;
return (
<>
<ListIcon as={MdCircle} />
{'Challenger is black'}
</>
);
case 'Random':
return <><ListIcon as={MdOutlineContrast} />{'Random color choice'}</>;
return (
<>
<ListIcon as={MdOutlineContrast} />
{'Random color choice'}
</>
);
}
}
};

interface ChallengeInfoBoxProps {
challenge: GameChallenge,
challenge: GameChallenge;
}

const ChallengeInfoBox = ({ challenge }: ChallengeInfoBoxProps) => {
const { rated, tournamentQueenRule, gameType, colorChoice, createdAt } = challenge;
const { rated, tournamentQueenRule, gameType, colorChoice, createdAt } =
challenge;
return (
<>
<List>
<ListItem>
<ListIcon as={MdOutlineEmojiEvents} />
{ rated ? 'Rated' : 'Unrated' }
{rated ? 'Rated' : 'Not rated'}
</ListItem>
<ListItem>
<ListIcon as={MdLooksOne}/>
{ tournamentQueenRule ? 'Tournament opening' : 'Unrestricted opening' }
<ListIcon as={MdLooksOne} />
{tournamentQueenRule ? 'Tournament opening' : 'Unrestricted opening'}
</ListItem>
<ListItem>
<ListIcon as={MdOutlineBugReport} />
{ getExpansionDescription(gameType) }
{getExpansionDescription(gameType)}
</ListItem>
<ListItem>
<ListIcon as={MdCalendarToday} />
{ `Created ${createdAt.toLocaleDateString()}` }
{`Created ${createdAt.toLocaleDateString()}`}
</ListItem>
<ListItem>
<ColorChoiceItem colorChoice={colorChoice}></ColorChoiceItem>
</ListItem>
</List>
</>
)
}
);
};

interface AcceptChallengeProps {
challenge: GameChallenge,
user?: UserData,
challenge: GameChallenge;
user?: UserData;
}

const AcceptChallenge = (props: AcceptChallengeProps) => {
Expand All @@ -87,10 +118,12 @@ const AcceptChallenge = (props: AcceptChallengeProps) => {
{`${challenge.challenger.username} has challenged you to a game`}
</div>
<ChallengeInfoBox challenge={challenge}></ChallengeInfoBox>
{ !user ? 'In order to accept this invite, please log in first.' :
{!user ? (
'In order to accept this invite, please log in first.'
) : (
<Button
colorScheme="green"
size="lg"
colorScheme='green'
size='lg'
onClick={() => {
acceptGameChallenge(challenge.id, authToken)
.then((game) => console.log(game)) // TODO: navigate to the newly created game
Expand All @@ -99,11 +132,11 @@ const AcceptChallenge = (props: AcceptChallengeProps) => {
>
Accept Challenge
</Button>
}
)}
</div>
</>
);
}
};

const Challenge = () => {
const router = useRouter();
Expand All @@ -115,8 +148,9 @@ const Challenge = () => {
useEffect(() => {
if (!challengeId) return;

getGameChallenge(challengeId as string)
.then((challenge) => setChallenge(challenge));
getGameChallenge(challengeId as string).then((challenge) =>
setChallenge(challenge)
);
}, [challengeId]);

return (
Expand All @@ -128,7 +162,14 @@ const Challenge = () => {
<Body className='my-12'>
<div className='grid grid-cols-12 gap-4'>
<div className='col-span-8 flex flex-col space-y-4'>
{ !challenge ? 'Loading...' : <AcceptChallenge challenge={challenge} user={user}></AcceptChallenge>}
{!challenge ? (
'Loading...'
) : (
<AcceptChallenge
challenge={challenge}
user={user}
></AcceptChallenge>
)}
</div>
</div>
</Body>
Expand Down
Loading