From 9205857a39c431f2cc8b3cda2aab6d91d8514a17 Mon Sep 17 00:00:00 2001 From: yasen5 <167659798+yasen5@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:18:24 -1000 Subject: [PATCH 1/3] Add animation --- src/geographic-selection-provider.tsx | 16 +++- src/geographic-selection.tsx | 110 ++++++++++++++++---------- 2 files changed, 80 insertions(+), 46 deletions(-) diff --git a/src/geographic-selection-provider.tsx b/src/geographic-selection-provider.tsx index 9bd4f37..e06e49c 100644 --- a/src/geographic-selection-provider.tsx +++ b/src/geographic-selection-provider.tsx @@ -7,18 +7,24 @@ interface GeographicPageProps { setHoveredConcept: React.Dispatch>; presentNations: string[]; setPresentNations: React.Dispatch>; + quizSelectedCountries: string[]; + setQuizSelectedCountries: React.Dispatch>; } -const GeographicPageContext = createContext< - GeographicPageProps | undefined ->(undefined); +const GeographicPageContext = createContext( + undefined +); export const GeographicPageProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { + console.log("PROVIDER REMOUNTED"); const [selectedCountry, setSelectedCountry] = useState(null); const [hoveredConcept, setHoveredConcept] = useState(null); const [presentNations, setPresentNations] = useState([]); + const [quizSelectedCountries, setQuizSelectedCountries] = useState( + [] + ); return ( {children} @@ -44,4 +52,4 @@ export const useGeographicPageContext = () => { ); } return context; -}; \ No newline at end of file +}; diff --git a/src/geographic-selection.tsx b/src/geographic-selection.tsx index e44e02d..87160ad 100644 --- a/src/geographic-selection.tsx +++ b/src/geographic-selection.tsx @@ -118,36 +118,35 @@ export const InnerGeographicSelection: React.FC<{ return (
-
- - -
-
-
- -
-
- -
+
+ + +
+
+
+ +
+
+
- - {selectedCountry && - (() => { - const { timePeriod, ...notes } = - countryNotes[selectedCountry] || - generalNotes[selectedCountry]; - return ( - setSelectedCountry(null)}> - - - ); - })()}
+ + {selectedCountry && + (() => { + const { timePeriod, ...notes } = + countryNotes[selectedCountry] || generalNotes[selectedCountry]; + return ( + setSelectedCountry(null)}> + + + ); + })()} +
); @@ -242,8 +241,12 @@ const MapHandler: React.FC<{ const mapRef = useRef(null); const [canScrollRight, setCanScrollRight] = useState(false); const [canScrollLeft, setCanScrollLeft] = useState(false); - const { hoveredConcept, setPresentNations, setSelectedCountry } = - useGeographicPageContext(); + const { + hoveredConcept, + setPresentNations, + setSelectedCountry, + quizSelectedCountries, + } = useGeographicPageContext(); useEffect(() => { const svgEl = mapRef.current; @@ -295,19 +298,20 @@ const MapHandler: React.FC<{ const styles: Record = {}; nations.forEach((nation) => { const isHighlighted = - hoveredConcept && - generalNotes[hoveredConcept]?.applicableCountries.includes(nation); + quizSelectedCountries.includes(nation) || + (hoveredConcept && + generalNotes[hoveredConcept]?.applicableCountries.includes(nation)); styles[`[data-country="${nation}"]`] = { fill: countryColors[nation], cursor: "pointer", - opacity: isHighlighted ? 1 : hoveredConcept ? 0.3 : 1, + opacity: isHighlighted ? 1 : (hoveredConcept || quizSelectedCountries.length > 0) ? 0.3 : 1, stroke: isHighlighted ? "#333" : "none", strokeWidth: isHighlighted ? ".5px" : "0", transition: "opacity 0.2s ease, stroke 0.2s ease", }; }); return styles; - }, [countryColors, hoveredConcept]); + }, [countryColors, hoveredConcept, quizSelectedCountries]); const handleCountryClick = (event: React.MouseEvent) => { const target = event.target as SVGElement; @@ -391,17 +395,19 @@ const MapHandler: React.FC<{ ); }; +const animWaitTimeMs = 100; + const Quiz: React.FC = () => { const [quizOpen, setQuizOpen] = useState(false); const [chosenCountries, setChosenCountries] = useState<[string, string]>([ "", "", ]); - const { presentNations } = useGeographicPageContext(); + const { presentNations, setQuizSelectedCountries } = + useGeographicPageContext(); const maxTries = 20; - const pickCountries = () => { - if (!quizOpen) return; + const pickCountries = async () => { let numTries = 0; let country1: string; let notes1: { [section: string]: string[] }; @@ -435,24 +441,44 @@ const Quiz: React.FC = () => { }) ); setChosenCountries([country1, country2]); + for (let i = 0; i < 15; i++) { + setQuizSelectedCountries([ + presentNations[Math.floor(Math.random() * presentNations.length)], + ]); + await new Promise((resolve) => setTimeout(resolve, animWaitTimeMs)); + } + setQuizSelectedCountries([country1]); + await new Promise((resolve) => setTimeout(resolve, animWaitTimeMs)); + for (let i = 0; i < 15; i++) { + setQuizSelectedCountries([ + country1, + presentNations[Math.floor(Math.random() * presentNations.length)], + ]); + await new Promise((resolve) => setTimeout(resolve, animWaitTimeMs)); + } + setQuizSelectedCountries([country1, country2]); + await new Promise((resolve) => setTimeout(resolve, 1000)); + setQuizOpen(true); }; - useEffect(() => { - pickCountries(); - }, [quizOpen]); - return ( <> {!quizOpen && ( )} {quizOpen && ( - setQuizOpen(false)} opaqueness={0.75}> + { + setQuizOpen(false); + setQuizSelectedCountries([]); + }} + opaqueness={0.75} + >

Find similarities & differences

From ea830f62d56ef9538280dcbe439110babd8eaaaa Mon Sep 17 00:00:00 2001 From: yasen5 <167659798+yasen5@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:31:26 -1000 Subject: [PATCH 2/3] Freshen up the animation :P --- src/geographic-selection.tsx | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/geographic-selection.tsx b/src/geographic-selection.tsx index 87160ad..3d8f9fa 100644 --- a/src/geographic-selection.tsx +++ b/src/geographic-selection.tsx @@ -297,14 +297,19 @@ const MapHandler: React.FC<{ const countryStyles = useMemo(() => { const styles: Record = {}; nations.forEach((nation) => { + const quizSelected = quizSelectedCountries.includes(nation); const isHighlighted = - quizSelectedCountries.includes(nation) || + quizSelected || (hoveredConcept && generalNotes[hoveredConcept]?.applicableCountries.includes(nation)); styles[`[data-country="${nation}"]`] = { - fill: countryColors[nation], + fill: (!quizSelected) ? countryColors[nation] : (quizSelectedCountries[0] === nation) ? "blue" : "red", cursor: "pointer", - opacity: isHighlighted ? 1 : (hoveredConcept || quizSelectedCountries.length > 0) ? 0.3 : 1, + opacity: isHighlighted + ? 1 + : hoveredConcept || quizSelectedCountries.length > 0 + ? 0.3 + : 1, stroke: isHighlighted ? "#333" : "none", strokeWidth: isHighlighted ? ".5px" : "0", transition: "opacity 0.2s ease, stroke 0.2s ease", @@ -395,7 +400,7 @@ const MapHandler: React.FC<{ ); }; -const animWaitTimeMs = 100; +const animWaitTimeMs = 200; const Quiz: React.FC = () => { const [quizOpen, setQuizOpen] = useState(false); @@ -441,15 +446,16 @@ const Quiz: React.FC = () => { }) ); setChosenCountries([country1, country2]); - for (let i = 0; i < 15; i++) { + for (let i = 0; i < 8; i++) { setQuizSelectedCountries([ presentNations[Math.floor(Math.random() * presentNations.length)], ]); await new Promise((resolve) => setTimeout(resolve, animWaitTimeMs)); } setQuizSelectedCountries([country1]); + await new Promise((resolve) => setTimeout(resolve, 1000)); await new Promise((resolve) => setTimeout(resolve, animWaitTimeMs)); - for (let i = 0; i < 15; i++) { + for (let i = 0; i < 8; i++) { setQuizSelectedCountries([ country1, presentNations[Math.floor(Math.random() * presentNations.length)], @@ -481,7 +487,14 @@ const Quiz: React.FC = () => { >

Find similarities & differences

- +
From 436c53a5be6ea95153b6ea238167bb6280256f4f Mon Sep 17 00:00:00 2001 From: yasen5 <167659798+yasen5@users.noreply.github.com> Date: Wed, 26 Nov 2025 17:46:08 -1000 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/geographic-selection-provider.tsx | 2 +- src/geographic-selection.tsx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/geographic-selection-provider.tsx b/src/geographic-selection-provider.tsx index e06e49c..75bb62c 100644 --- a/src/geographic-selection-provider.tsx +++ b/src/geographic-selection-provider.tsx @@ -18,7 +18,7 @@ const GeographicPageContext = createContext( export const GeographicPageProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { - console.log("PROVIDER REMOUNTED"); + const [selectedCountry, setSelectedCountry] = useState(null); const [hoveredConcept, setHoveredConcept] = useState(null); const [presentNations, setPresentNations] = useState([]); diff --git a/src/geographic-selection.tsx b/src/geographic-selection.tsx index 3d8f9fa..1040a54 100644 --- a/src/geographic-selection.tsx +++ b/src/geographic-selection.tsx @@ -453,8 +453,7 @@ const Quiz: React.FC = () => { await new Promise((resolve) => setTimeout(resolve, animWaitTimeMs)); } setQuizSelectedCountries([country1]); - await new Promise((resolve) => setTimeout(resolve, 1000)); - await new Promise((resolve) => setTimeout(resolve, animWaitTimeMs)); + await new Promise((resolve) => setTimeout(resolve, 1000 + animWaitTimeMs)); for (let i = 0; i < 8; i++) { setQuizSelectedCountries([ country1,