From ef97d7cb6205a71a60b97192756c58ce620c55c2 Mon Sep 17 00:00:00 2001 From: Spencer Spenst Date: Fri, 29 Sep 2023 22:20:57 -0700 Subject: [PATCH 1/2] wip sidebar panels --- components/level/gameWrapper.tsx | 5 +- components/level/info/formattedLevelInfo.tsx | 42 +++++++++- components/level/info/suggestedPanel.tsx | 87 ++++++++++++++++++++ components/page/didYouKnowTip.tsx | 2 +- contexts/levelContext.ts | 4 +- pages/level/[username]/[slugName].tsx | 3 + 6 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 components/level/info/suggestedPanel.tsx diff --git a/components/level/gameWrapper.tsx b/components/level/gameWrapper.tsx index 191d0827b..f5760a743 100644 --- a/components/level/gameWrapper.tsx +++ b/components/level/gameWrapper.tsx @@ -1,3 +1,4 @@ +import { LevelContext } from '@root/contexts/levelContext'; import { PageContext } from '@root/contexts/pageContext'; import React, { useContext, useEffect, useState } from 'react'; import Collection from '../../models/db/collection'; @@ -16,6 +17,7 @@ interface GameWrapperProps { } export default function GameWrapper({ chapter, collection, level, onNext, onPrev, user }: GameWrapperProps) { + const levelContext = useContext(LevelContext); const [postGameModalOpen, setShowPostGameModalOpen] = useState(false); const { setPreventKeyDownEvent } = useContext(PageContext); @@ -34,7 +36,8 @@ export default function GameWrapper({ chapter, collection, level, onNext, onPrev level={level} onNext={collection ? onNext : undefined} onPrev={collection ? onPrev : undefined} - onSolve={() => setTimeout(() => setShowPostGameModalOpen(true), 200)} + // onSolve={() => setTimeout(() => setShowPostGameModalOpen(true), 200)} + onSolve={() => levelContext && levelContext.setSidebarIndex(1)} /> } - {/* Reviews */}
- +
+ + + { + if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') { + e.preventDefault(); + } + }}> + {({ selected }) => ( +
+ Reviews +
+ )} +
+ { + if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') { + e.preventDefault(); + } + }}> + {({ selected }) => ( +
+ Suggestions +
+ )} +
+
+ + + + + + + + +
+
); } diff --git a/components/level/info/suggestedPanel.tsx b/components/level/info/suggestedPanel.tsx new file mode 100644 index 000000000..981ef0bad --- /dev/null +++ b/components/level/info/suggestedPanel.tsx @@ -0,0 +1,87 @@ +import DidYouKnowTip from '@root/components/page/didYouKnowTip'; +import useHomePageData, { HomepageDataType } from '@root/hooks/useHomePageData'; +import Collection from '@root/models/db/collection'; +import Level, { EnrichedLevel } from '@root/models/db/level'; +import User from '@root/models/db/user'; +import Link from 'next/link'; +import React, { useEffect, useState } from 'react'; +import Card from '../../cards/card'; +import ChapterSelectCard from '../../cards/chapterSelectCard'; +import RecommendedLevel from '../../homepage/recommendedLevel'; + +interface SuggestedPanelProps { + chapter?: string; + collection?: Collection; + level: Level; + reqUser: User | undefined | null; +} + +export default function SuggestedPanel({ chapter, collection, level, reqUser }: SuggestedPanelProps) { + let nextLevel: EnrichedLevel | undefined = undefined; + let lastLevelInCollection = false; + + if (collection && collection.levels) { + const levelIndex = collection.levels.findIndex((l) => l._id === level._id); + + if (levelIndex + 1 < collection.levels.length) { + nextLevel = collection.levels[levelIndex + 1] as EnrichedLevel; + } else { + lastLevelInCollection = true; + } + } + + const { data } = useHomePageData([HomepageDataType.RecommendedLevel], nextLevel !== undefined); + const recommendedLevel = data && data[HomepageDataType.RecommendedLevel]; + const [queryParams, setQueryParams] = useState({}); + + // NB: this useEffect only runs when entering the level page + // (moving between levels within a collection does not remount this component) + // this is ok for now because query params are currently never expected + // to change when going between two level pages + useEffect(() => { + setQueryParams(new URLSearchParams(window.location.search)); + }, []); + + const hrefOverride = nextLevel ? `/level/${nextLevel.slug}?${queryParams}` : undefined; + + return (<> +
+

+ Congratulations! +

+

+ You completed {level.name}! +

+
+
+ {!reqUser ? +
+ Sign up (or use a Guest Account) to save your progress and get access to more features. +
+ : + <> + {lastLevelInCollection && collection && +
+ {level.name} is the last level in {collection.name}. +
+ } + {chapter && !isNaN(Number(chapter)) ? + +
+ +
+
+ : + + } + + } + +
+ ); +} diff --git a/components/page/didYouKnowTip.tsx b/components/page/didYouKnowTip.tsx index c3da7e0b0..28818bbfc 100644 --- a/components/page/didYouKnowTip.tsx +++ b/components/page/didYouKnowTip.tsx @@ -3,7 +3,7 @@ import Link from 'next/link'; import React, { useRef } from 'react'; interface DidYouKnowTipProps { - reqUser: User | null; + reqUser: User | undefined | null; } export default function DidYouKnowTip({ reqUser }: DidYouKnowTipProps) { diff --git a/contexts/levelContext.ts b/contexts/levelContext.ts index 1e41e7816..cbc2bfb1a 100644 --- a/contexts/levelContext.ts +++ b/contexts/levelContext.ts @@ -50,9 +50,11 @@ interface LevelContextInterface { level: EnrichedLevel; mutateLevel: () => void; mutateProStatsLevel: KeyedMutator; + proStatsLevel?: ProStatsLevel; records: Record[] | undefined; reviews: Review[] | undefined; - proStatsLevel?: ProStatsLevel; + setSidebarIndex: React.Dispatch>; + sidebarIndex: number; } export const LevelContext = createContext(null); diff --git a/pages/level/[username]/[slugName].tsx b/pages/level/[username]/[slugName].tsx index 34549d482..4ae71ed84 100644 --- a/pages/level/[username]/[slugName].tsx +++ b/pages/level/[username]/[slugName].tsx @@ -59,6 +59,7 @@ export default function LevelPage({ _level, reqUser }: LevelProps) { const [level, setLevel] = useState(_level); const { mutateProStatsLevel, proStatsLevel } = useProStatsLevel(level); const router = useRouter(); + const [sidebarIndex, setSidebarIndex] = useState(0); const { chapter, cid, slugName, ts, username } = router.query as LevelUrlQueryParams; const { collection } = useCollectionById(cid); @@ -225,6 +226,8 @@ export default function LevelPage({ _level, reqUser }: LevelProps) { proStatsLevel: proStatsLevel, records: records, reviews: reviews, + setSidebarIndex: setSidebarIndex, + sidebarIndex: sidebarIndex, }}> Date: Fri, 29 Sep 2023 23:01:47 -0700 Subject: [PATCH 2/2] PLEASE --- components/cards/card.tsx | 2 +- components/level/info/formattedLevelInfo.tsx | 6 ++-- components/level/info/suggestedPanel.tsx | 31 ++++++++++---------- contexts/levelContext.ts | 3 ++ pages/level/[username]/[slugName].tsx | 3 ++ 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/components/cards/card.tsx b/components/cards/card.tsx index 4ffadbaf4..ab0aa705c 100644 --- a/components/cards/card.tsx +++ b/components/cards/card.tsx @@ -12,7 +12,7 @@ export default function Card({ children, id, title, tooltip }: CardProps) { const tooltipId = `card-tooltip-${id}`; return ( -
-
+
{({ selected }) => ( -
+
Reviews
)} @@ -254,7 +254,7 @@ export default function FormattedLevelInfo({ level }: FormattedLevelInfoProps) { } }}> {({ selected }) => ( -
+
Suggestions
)} diff --git a/components/level/info/suggestedPanel.tsx b/components/level/info/suggestedPanel.tsx index 981ef0bad..738d04387 100644 --- a/components/level/info/suggestedPanel.tsx +++ b/components/level/info/suggestedPanel.tsx @@ -1,28 +1,34 @@ import DidYouKnowTip from '@root/components/page/didYouKnowTip'; +import { LevelContext } from '@root/contexts/levelContext'; import useHomePageData, { HomepageDataType } from '@root/hooks/useHomePageData'; -import Collection from '@root/models/db/collection'; import Level, { EnrichedLevel } from '@root/models/db/level'; import User from '@root/models/db/user'; import Link from 'next/link'; -import React, { useEffect, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import Card from '../../cards/card'; import ChapterSelectCard from '../../cards/chapterSelectCard'; import RecommendedLevel from '../../homepage/recommendedLevel'; interface SuggestedPanelProps { - chapter?: string; - collection?: Collection; level: Level; reqUser: User | undefined | null; } -export default function SuggestedPanel({ chapter, collection, level, reqUser }: SuggestedPanelProps) { +export default function SuggestedPanel({ level, reqUser }: SuggestedPanelProps) { + const levelContext = useContext(LevelContext); + + const collection = levelContext?.collection; + const chapter = levelContext?.chapter; let nextLevel: EnrichedLevel | undefined = undefined; let lastLevelInCollection = false; + console.log(collection); + if (collection && collection.levels) { const levelIndex = collection.levels.findIndex((l) => l._id === level._id); + console.log(levelIndex, collection.levels.length); + if (levelIndex + 1 < collection.levels.length) { nextLevel = collection.levels[levelIndex + 1] as EnrichedLevel; } else { @@ -30,6 +36,7 @@ export default function SuggestedPanel({ chapter, collection, level, reqUser }: } } + // TODO: don't use SWR here, or at least don't refetch every time you switch to the panel const { data } = useHomePageData([HomepageDataType.RecommendedLevel], nextLevel !== undefined); const recommendedLevel = data && data[HomepageDataType.RecommendedLevel]; const [queryParams, setQueryParams] = useState({}); @@ -45,15 +52,7 @@ export default function SuggestedPanel({ chapter, collection, level, reqUser }: const hrefOverride = nextLevel ? `/level/${nextLevel.slug}?${queryParams}` : undefined; return (<> -
-

- Congratulations! -

-

- You completed {level.name}! -

-
-
+
{!reqUser ?
Sign up (or use a Guest Account) to save your progress and get access to more features. @@ -65,10 +64,10 @@ export default function SuggestedPanel({ chapter, collection, level, reqUser }: {level.name} is the last level in {collection.name}.
} - {chapter && !isNaN(Number(chapter)) ? + {chapter !== undefined && lastLevelInCollection ?
- +
: diff --git a/contexts/levelContext.ts b/contexts/levelContext.ts index cbc2bfb1a..bbae7468a 100644 --- a/contexts/levelContext.ts +++ b/contexts/levelContext.ts @@ -1,3 +1,4 @@ +import Collection from '@root/models/db/collection'; import { createContext } from 'react'; import { KeyedMutator } from 'swr'; import ProStatsLevelType from '../constants/proStatsLevelType'; @@ -45,6 +46,8 @@ export interface ProStatsCommunityStepData { } interface LevelContextInterface { + chapter: number | undefined; + collection: Collection | undefined; getReviews: () => void; inCampaign: boolean; // true means you are playing an unbeaten level in the campaign level: EnrichedLevel; diff --git a/pages/level/[username]/[slugName].tsx b/pages/level/[username]/[slugName].tsx index 4ae71ed84..0dd3ef3a4 100644 --- a/pages/level/[username]/[slugName].tsx +++ b/pages/level/[username]/[slugName].tsx @@ -66,6 +66,7 @@ export default function LevelPage({ _level, reqUser }: LevelProps) { // handle pressing "Next level" useEffect(() => { setLevel(_level); + setSidebarIndex(0); }, [_level]); const mutateLevel = useCallback(() => { @@ -218,6 +219,8 @@ export default function LevelPage({ _level, reqUser }: LevelProps) { }} />