Skip to content

Commit

Permalink
fix: fix unclickable nav
Browse files Browse the repository at this point in the history
  • Loading branch information
LukeSchlangen committed Aug 21, 2023
1 parent 0ba3b87 commit 49a0706
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 64 deletions.
3 changes: 2 additions & 1 deletion app-dev/party-game/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"extends": [
"eslint:recommended",
"next",
"prettier"
"prettier",
"google"
],
"rules": {
"max-len": "off",
Expand Down
11 changes: 7 additions & 4 deletions app-dev/party-game/app/(authenticated-pages)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@
import useActiveGameList from '@/app/hooks/use-active-game-list';
import {useRouter} from 'next/navigation';
import Navbar from '@/app/components/navbar';
import {useEffect} from 'react';

export default function Home() {
const {activeGameList} = useActiveGameList();
const router = useRouter();

if (activeGameList.length > 0) {
const firstGameId = activeGameList[0].id;
router.push(`/game/${firstGameId}`);
}
useEffect(() => {
if (activeGameList.length > 0) {
const firstGameId = activeGameList[0].id;
router.push(`/game/${firstGameId}`);
}
}, [activeGameList, router]);

return (
<div>
Expand Down
17 changes: 10 additions & 7 deletions app-dev/party-game/app/api/create-game/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {unknownParser, unknownValidator} from '@/app/lib/zod-parser';
import {gamesRef, questionsRef} from '@/app/lib/firebase-server-initialization';
import {generateName} from '@/app/lib/name-generator';
import {getAuthenticatedUser} from '@/app/lib/server-side-auth';
import {Question, QuestionSchema, gameStates} from '@/app/types';
import {Game, Question, QuestionSchema, gameStates} from '@/app/types';
import {QueryDocumentSnapshot, Timestamp} from 'firebase-admin/firestore';
import {NextRequest, NextResponse} from 'next/server';
import {authenticationFailedResponse} from '@/app/lib/authentication-failed-response';
Expand All @@ -41,15 +41,16 @@ export async function POST(request: NextRequest) {


const querySnapshot = await questionsRef.get();
const questions = querySnapshot.docs.reduce((agg: Record<number, Question>, doc: QueryDocumentSnapshot, index: number) => {
const validQuestionsArray = querySnapshot.docs.reduce((agg: Question[], doc: QueryDocumentSnapshot) => {
const question = doc.data();
const errorMessage = unknownValidator(question, QuestionSchema);
if (errorMessage) {
console.warn(`WARNING: The question "${question?.prompt}" [Firestore ID: ${doc.id}] has an issue and will not be added to the game.`)
console.warn(`WARNING: The question "${question?.prompt}" [Firestore ID: ${doc.id}] has an issue and will not be added to the game.`);
return agg;
}
return {...agg, [index]: question};
}, {});
return [...agg, question];
}, []);
const questions = {...validQuestionsArray};
if (!authUser) throw new Error('User must be signed in to start game');
// create game with server endpoint

Expand All @@ -60,7 +61,7 @@ export async function POST(request: NextRequest) {

const startTime = Timestamp.now();

const gameRef = await gamesRef.add({
const newGame: Game= {
questions,
leader,
players: {},
Expand All @@ -69,7 +70,9 @@ export async function POST(request: NextRequest) {
startTime,
timePerQuestion: timePerQuestion + 1, // add one for padding between questions
timePerAnswer: timePerAnswer + 1, // add one for padding between questions
});
};

const gameRef = await gamesRef.add(newGame);

return NextResponse.json({gameId: gameRef.id}, {status: 200});
}
59 changes: 28 additions & 31 deletions app-dev/party-game/app/components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export default function Navbar() {

const pathname = usePathname();
const navigation = [
{name: 'Home', href: '/'},
{name: 'About', href: '/about'},
].map((route: { name: string, href: string }) => ({
{title: 'Home', href: '/'},
{title: 'About', href: '/about'},
].map((route) => ({
...route,
current: pathname === route.href,
}));
Expand All @@ -44,57 +44,54 @@ export default function Navbar() {
<>
<div className="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
<div className="relative flex h-16 items-center justify-between">
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
{/* Mobile menu button*/}
<Disclosure.Button id="disclosure-button" className="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:underline hover:decoration-[var(--google-cloud-blue)] hover:text-black">
<span className="sr-only">Open main menu</span>
{open ? (
<XMarkIcon className="block h-6 w-6" aria-hidden="true" />
) : (
<Bars3Icon className="block h-6 w-6" aria-hidden="true" />
)}
</Disclosure.Button>
<div className="absolute w-full flex flex-shrink-0 justify-center sm:justify-start">
<Image
src='/google-cloud-logo.svg'
alt='Google Cloud Logo'
width='80'
height='80'
className='block h-8 w-auto'
priority
/>
</div>
<div className="relative flex flex-1 items-center">
<div className="absolute w-full flex flex-shrink-0 justify-center sm:justify-start -z-20">
<Image
src='/google-cloud-logo.svg'
alt='Google Cloud Logo'
width='80'
height='80'
className='block h-8 w-auto'
priority
/>
</div>
<div className="absolute w-full flex justify-between">
<div className="hidden sm:ml-12 sm:block">
<div className="flex space-x-4">
{navigation.map((item) => (
<Link
key={item.name}
key={item.title}
href={item.href}
className={mergeClassNames(
item.current ? 'text-black underline' : 'text-gray-700 hover:underline hover:decoration-[var(--google-cloud-blue)] hover:text-black',
'rounded-md px-3 py-2 text-base font-medium'
)}
aria-current={item.current ? 'page' : undefined}
>
{item.name}
{item.title}
</Link>
))}
</div>
</div>
<div className="absolute w-full flex flex-shrink-0 justify-end -z-10">
{authUser.uid ? <SignOutButton /> : <SignInButton />}
<div className="inset-y-0 left-0 flex items-center sm:hidden">
{/* Mobile menu button*/}
<Disclosure.Button id="disclosure-button" className="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:underline hover:decoration-[var(--google-cloud-blue)] hover:text-black">
<span className="sr-only">Open main menu</span>
{open ? (
<XMarkIcon className="block h-6 w-6" aria-hidden="true" />
) : (
<Bars3Icon className="block h-6 w-6" aria-hidden="true" />
)}
</Disclosure.Button>
</div>
{authUser.uid ? <SignOutButton /> : <SignInButton />}
</div>
</div>
</div>

<Disclosure.Panel className="sm:hidden">
<div className="space-y-1 px-2 pt-2 pb-3">
{navigation.map((item) => (
<Disclosure.Button
key={item.name}
key={item.title}
as="a"
href={item.href}
className={mergeClassNames(
Expand All @@ -103,7 +100,7 @@ export default function Navbar() {
)}
aria-current={item.current ? 'page' : undefined}
>
{item.name}
{item.title}
</Disclosure.Button>
))}
</div>
Expand Down
4 changes: 3 additions & 1 deletion app-dev/party-game/app/hooks/use-active-game-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {DocumentReference, collection, onSnapshot, query, where} from 'firebase/

const useActiveGameList = () => {
const [activeGameList, setActiveGameList] = useState<DocumentReference[]>([]);
const [loading, setLoading] = useState<boolean>(true);

useEffect(() => {
const q = query(collection(db, 'games'), where('state', '!=', gameStates.GAME_OVER));
Expand All @@ -31,11 +32,12 @@ const useActiveGameList = () => {
games.push(doc.ref);
});
setActiveGameList(games);
setLoading(false);
});
return unsubscribe;
}, []);

return {activeGameList};
return {activeGameList, loading};
};

export default useActiveGameList;
44 changes: 24 additions & 20 deletions app-dev/party-game/app/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ const AnswerSchema = z.object({
isSelected: z.boolean().default(false),
text: z.string(),
});
export type Answer = z.infer<typeof AnswerSchema>;

export const QuestionSchema = z.object({
answers: z.array(AnswerSchema).min(1).max(4),
Expand All @@ -52,27 +51,32 @@ const GameStateEnum = z.enum(gameStatesOptions);
export const gameStates = GameStateEnum.Values;

export const LeaderSchema = z.object({
uid: z.string().default(''),
displayName: z.string().default(''),
uid: z.string(),
displayName: z.string(),
});
const emptyLeader = LeaderSchema.parse({
uid: '',
displayName: '',
});
const emptyLeader = LeaderSchema.parse({});

export const GameSchema = z.object({
questions: z.record(z.string(), QuestionSchema).default({}),
leader: LeaderSchema.default(emptyLeader),
players: z.record(z.string(), z.string()).default({}),
state: GameStateEnum.default(gameStates.NOT_STARTED),
currentQuestionIndex: z.number().int().nonnegative().default(0),
startTime: z.object({seconds: z.number()}).default({seconds: -1}),
timePerQuestion: TimePerQuestionSchema.default(60),
timePerAnswer: TimePerAnswerSchema.default(20),
questions: z.record(z.string(), QuestionSchema),
leader: LeaderSchema,
players: z.record(z.string(), z.string()),
state: GameStateEnum,
currentQuestionIndex: z.number().int().nonnegative(),
startTime: z.object({seconds: z.number()}),
timePerQuestion: TimePerQuestionSchema,
timePerAnswer: TimePerAnswerSchema,
});
export type Game = z.infer<typeof GameSchema>;
export const emptyGame = GameSchema.parse({});

const RouteWithCurrentStatusSchema = z.object({
name: z.string(),
href: z.string(),
current: z.string(),
export const emptyGame = GameSchema.parse({
questions: {},
leader: emptyLeader,
players: {},
state: 'NOT_STARTED',
currentQuestionIndex: 0,
startTime: {seconds: 0},
timePerQuestion: 60,
timePerAnswer: 20,
});
export type RouteWithCurrentStatus = z.infer<typeof RouteWithCurrentStatusSchema>;
export type Game = z.infer<typeof GameSchema>;

0 comments on commit 49a0706

Please sign in to comment.