From b912685b1b9b7c08aae0c1939a21bc5c47c21b2d Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Wed, 5 Nov 2025 00:36:05 -0500 Subject: [PATCH 1/9] impl --- src/App.tsx | 7 +++++++ src/components/shared/preventBackBttn.tsx | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/components/shared/preventBackBttn.tsx diff --git a/src/App.tsx b/src/App.tsx index 2e84d3b..8b60cdd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,6 +14,7 @@ import ThankYou from "./pages/ThankYou"; import UserError from "./pages/Error"; import PoemViewer from "./pages/PoemViewer"; import usePreventRefresh from "./components/shared/preventRefresh"; +import usePreventBack from "./components/shared/preventBackBttn"; import { nanoid } from "nanoid"; // import AudienceInstructions from "./pages/audience/instructions/Instructions"; @@ -60,9 +61,15 @@ function App() { const [userData, setUserData] = useState(null); const [sessionId, setSessionId] = useState(null); const saveTimerRef = useRef(null); + const [hasPressedBack, setHasPressedBack] = useState(false); + usePreventRefresh( "To make sure your session counts, please avoid refreshing the page. Do you still want to refresh?" ); + usePreventBack( + "To make sure your session counts, please avoid pressing the back button.", + setHasPressedBack + ); // clear session storage and set the session ID on first render useEffect(() => { diff --git a/src/components/shared/preventBackBttn.tsx b/src/components/shared/preventBackBttn.tsx new file mode 100644 index 0000000..27e8fe0 --- /dev/null +++ b/src/components/shared/preventBackBttn.tsx @@ -0,0 +1,21 @@ +import { useEffect } from "react"; + +export default function usePreventBack( + message: string = "Are you sure you want to go back?", + setHasPressedBack: React.Dispatch> +) { + useEffect(() => { + window.history.pushState(null, "", window.location.pathname); + + const handlePopState = () => { + alert(message); + setHasPressedBack(true); + }; + + window.addEventListener("popstate", handlePopState); + + return () => { + window.removeEventListener("popstate", handlePopState); + }; + }, [message, setHasPressedBack]); +} From 2722ae1ed79470753fe2e80534037bf46ff406c9 Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Wed, 5 Nov 2025 00:45:59 -0500 Subject: [PATCH 2/9] yeehaw --- src/components/chatbot/Chatbot.tsx | 4 +++- src/pages/artist/instructions/Instructions.tsx | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/chatbot/Chatbot.tsx b/src/components/chatbot/Chatbot.tsx index c1fae52..b1f986c 100644 --- a/src/components/chatbot/Chatbot.tsx +++ b/src/components/chatbot/Chatbot.tsx @@ -85,7 +85,9 @@ export default function ChatTab({ const openingMessage = { role: Role.LLM, content: - "Hello! I'm your assistant for today. I am just ChatGPT, so feel free to use me just as you would in your day-to-day activities. I'm here to help you brainstorm, refine, or analyze blackout poetry as you create your own piece.", + stage == "SPARK" + ? "Hello! I'm your assistant for today. I am just ChatGPT, so feel free to use me just as you would in your day-to-day activities. I'm here to help you brainstorm, refine, or analyze blackout poetry as you create your own piece." + : "LLM During the Writing stage", }; useEffect(() => { diff --git a/src/pages/artist/instructions/Instructions.tsx b/src/pages/artist/instructions/Instructions.tsx index 6e43c25..77fac96 100644 --- a/src/pages/artist/instructions/Instructions.tsx +++ b/src/pages/artist/instructions/Instructions.tsx @@ -35,7 +35,9 @@ const ArtistInstructions = () => {
In this study, you will be introduced to blackout poetry and write - your own poem! + your own blackout poem! We will walk you through the whole process, + and know that blackout poetry is easier than writing a poem because + you are provided with the source material.
@@ -60,12 +62,12 @@ const ArtistInstructions = () => { Blackout Example 1 Blackout Example 2
From 765422ed6b925393f5b15495ef43f6302ffd4dc7 Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Thu, 6 Nov 2025 20:08:17 -0500 Subject: [PATCH 3/9] thou shall not reverse --- src/App.tsx | 4 +--- src/components/shared/preventBackBttn.tsx | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 8b60cdd..0deaae5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -61,14 +61,12 @@ function App() { const [userData, setUserData] = useState(null); const [sessionId, setSessionId] = useState(null); const saveTimerRef = useRef(null); - const [hasPressedBack, setHasPressedBack] = useState(false); usePreventRefresh( "To make sure your session counts, please avoid refreshing the page. Do you still want to refresh?" ); usePreventBack( - "To make sure your session counts, please avoid pressing the back button.", - setHasPressedBack + "To make sure your session counts, please avoid pressing the back button." ); // clear session storage and set the session ID on first render diff --git a/src/components/shared/preventBackBttn.tsx b/src/components/shared/preventBackBttn.tsx index 27e8fe0..0eff896 100644 --- a/src/components/shared/preventBackBttn.tsx +++ b/src/components/shared/preventBackBttn.tsx @@ -1,15 +1,11 @@ import { useEffect } from "react"; -export default function usePreventBack( - message: string = "Are you sure you want to go back?", - setHasPressedBack: React.Dispatch> -) { +export default function usePreventBack(message: string) { useEffect(() => { window.history.pushState(null, "", window.location.pathname); const handlePopState = () => { alert(message); - setHasPressedBack(true); }; window.addEventListener("popstate", handlePopState); @@ -17,5 +13,5 @@ export default function usePreventBack( return () => { window.removeEventListener("popstate", handlePopState); }; - }, [message, setHasPressedBack]); + }, [message]); } From 2549f09bc19a4e85bcab212ca170aa5b7f474cda Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Thu, 6 Nov 2025 21:01:29 -0500 Subject: [PATCH 4/9] attempt 1 --- src/components/shared/pages/multiPage.tsx | 75 +++++++++++++------ .../artist/instructions/Instructions.tsx | 4 +- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/components/shared/pages/multiPage.tsx b/src/components/shared/pages/multiPage.tsx index 0985eeb..bcf0a74 100644 --- a/src/components/shared/pages/multiPage.tsx +++ b/src/components/shared/pages/multiPage.tsx @@ -51,9 +51,12 @@ function MultiPageTemplate({ const [isTimeUp, setIsTimeUp] = useState(false); const [progress, setProgress] = useState(0); const [isVisible, setIsVisible] = useState(false); + const [countdown, setCountdown] = useState(null); + const [showCountdownVisible, setShowCountdownVisible] = useState(false); const autoRedirectTimeoutRef = useRef(null); const timerRef = useRef(null); + const countdownRef = useRef(null); const isDraggingX = useRef(false); const isDraggingY = useRef(false); @@ -135,6 +138,17 @@ function MultiPageTemplate({ setIsTimeUp(true); clearInterval(timerRef.current!); + setCountdown(autoRedirectDuration); + countdownRef.current = setInterval(() => { + setCountdown((prev) => { + if (prev && prev > 1) return prev - 1; + clearInterval(countdownRef.current!); + return 0; + }); + }, 1000); + + setTimeout(() => setShowCountdownVisible(true), 30); + autoRedirectTimeoutRef.current = setTimeout(() => { startFadeOut(); }, autoRedirectDuration * 1000); @@ -163,6 +177,16 @@ function MultiPageTemplate({ startFadeOut(); }; + const formatTime = (seconds: number) => { + const m = Math.floor(seconds / 60) + .toString() + .padStart(2, "0"); + const s = Math.floor(seconds % 60) + .toString() + .padStart(2, "0"); + return `${m}:${s}`; + }; + return (
-
-

{title}

- -
+
+
+

{title}

+

+ {description} +

+
+ +
+ -
-

{description}

+ {isTimeUp && countdown !== null && ( +

+ Your next step starts in {formatTime(countdown)} +

+ )} +
diff --git a/src/pages/artist/instructions/Instructions.tsx b/src/pages/artist/instructions/Instructions.tsx index 58b85e7..17b0a61 100644 --- a/src/pages/artist/instructions/Instructions.tsx +++ b/src/pages/artist/instructions/Instructions.tsx @@ -103,7 +103,9 @@ const ArtistInstructions = () => {

Important: please do not take screenshots, copy text, or consult external tools such as ChatGPT. We're interested in your best - effort and what you learn. + effort and what you learn! In addition, do not refresh or use the + browser's back/forward buttons as you will not be able to continue + the task.

From e772c00eed764dd388a8b0fd004826748c078fe5 Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Thu, 6 Nov 2025 21:14:58 -0500 Subject: [PATCH 5/9] version 2 --- src/components/shared/pages/multiPage.tsx | 36 +++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/components/shared/pages/multiPage.tsx b/src/components/shared/pages/multiPage.tsx index bcf0a74..75b08e7 100644 --- a/src/components/shared/pages/multiPage.tsx +++ b/src/components/shared/pages/multiPage.tsx @@ -207,14 +207,10 @@ function MultiPageTemplate({ style={{ height: `${topHeight}%` }} >
-
-
-

{title}

-

- {description} -

-
- +
+

{title}

+
+

{description}

+
+
{children}
From 1a0be78cf3e72ea87fbafe6426f19391682bfe11 Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Mon, 10 Nov 2025 01:25:17 -0500 Subject: [PATCH 6/9] select punctuation --- src/components/blackout/Blackout.tsx | 36 ++++++++++++++++++++++------ src/pages/artist/step1/Step1.tsx | 2 +- src/pages/artist/step2/Step2.tsx | 2 +- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/components/blackout/Blackout.tsx b/src/components/blackout/Blackout.tsx index ecb32ee..9a8fd16 100644 --- a/src/components/blackout/Blackout.tsx +++ b/src/components/blackout/Blackout.tsx @@ -18,8 +18,8 @@ const BlackoutPoetry: React.FC = ({ const [passageText] = useState( "Twilight settled over Zuckerman’s barn, and a feeling of peace. Fern knew it was almost suppertime but she couldn’t bear to leave. Swallows passed on silent wings, in and out of the doorways, bringing food to their young ones. From across the road a bird sang “Whippoorwill, whippoorwill!” Lurvy sat down under an apple tree and lit his pipe; the animals sniffed the familiar smell of strong tobacco. Wilbur heard the trill of the tree toad and the occasional slamming of the kitchen door. All these sounds made him feel comfortable and happy, for he loved life and loved to be a part of the world on a summer evening. But as he lay there he remembered what the old sheep had told him. The thought of death came to him and he began to tremble with fear." ); + const words = passageText.match(/[\w’']+|[.,!?;:“”"()\-\—]/g); - const words = passageText.split(" "); const [historyIndex, setHistoryIndex] = useState(-1); // Track undo/redo position const [history, setHistory] = useState([]); @@ -141,19 +141,30 @@ const BlackoutPoetry: React.FC = ({ className="leading-relaxed flex flex-wrap select-none h-max" onCopy={(e) => e.preventDefault()} > - {words.map((word, i) => { + {words?.map((word, i) => { const isSelected = selectedWordIndexes.includes(i); const textColor = isSelected ? "text-main text-light-grey-1" : "text-main hover:text-blue-800 hover:underline"; + const nextIsPunctuation = + i < words.length - 1 && /^[.,!?;:“”"()\-\—]$/.test(words[i + 1]); + + const isPunctuation = /^[.,!?;:“”"()\-\—]$/.test(word); + + const spacingClass = isPunctuation + ? "pl-0 pr-1" + : nextIsPunctuation + ? "pl-1 pr-0" + : "px-1"; + return ( toggleSelect(i)} - className={`cursor-pointer transition px-1 duration-200 ${textColor}`} + className={`cursor-pointer transition duration-200 ${spacingClass} ${textColor}`} > - {word + " "} + {word} ); })} @@ -164,18 +175,29 @@ const BlackoutPoetry: React.FC = ({ className="leading-relaxed flex flex-wrap select-none h-max" onCopy={(e) => e.preventDefault()} > - {words.map((word, i) => { + {words?.map((word, i) => { const isSelected = selectedWordIndexes.includes(i); const blackoutStyle = isSelected ? "text-main text-dark-grey" : "text-main text-dark-grey bg-dark-grey"; + const nextIsPunctuation = + i < words.length - 1 && /^[.,!?;:“”"()\-\—]$/.test(words[i + 1]); + + const isPunctuation = /^[.,!?;:“”"()\-\—]$/.test(word); + + const spacingClass = isPunctuation + ? "pl-0 pr-1" + : nextIsPunctuation + ? "pl-1 pr-0" + : "px-1"; + return ( - {word + " "} + {word} ); })} diff --git a/src/pages/artist/step1/Step1.tsx b/src/pages/artist/step1/Step1.tsx index 6ad8870..713a5de 100644 --- a/src/pages/artist/step1/Step1.tsx +++ b/src/pages/artist/step1/Step1.tsx @@ -61,7 +61,7 @@ const ArtistStep1 = () => { title="Step 1: Familiarize yourself with the text" description="This is your time to familiarize yourself with the text and brainstorm for your poem. Feel free to take any notes in the text box below. Your notes will be accessible during the writing portion." duration={60} - autoRedirectDuration={120} + autoRedirectDuration={300} afterDuration={onComplete} buttonText="Begin Writing" llmAccess={userType == "TOTAL_ACCESS" || userType == "SPARK"} diff --git a/src/pages/artist/step2/Step2.tsx b/src/pages/artist/step2/Step2.tsx index 8839a4f..fec47cf 100644 --- a/src/pages/artist/step2/Step2.tsx +++ b/src/pages/artist/step2/Step2.tsx @@ -64,7 +64,7 @@ const ArtistStep2 = () => { title="Step 2: Write your poem" description="Create a poem by clicking on words in the passage." duration={180} - autoRedirectDuration={120} + autoRedirectDuration={420} afterDuration={onComplete} buttonText="Submit" llmAccess={userType == "TOTAL_ACCESS" || userType == "WRITING"} From 5de3e3361ec29d32dd7a84ba817341df8c2bf2d1 Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Mon, 10 Nov 2025 11:42:25 -0500 Subject: [PATCH 7/9] Revert "select punctuation" This reverts commit 1a0be78cf3e72ea87fbafe6426f19391682bfe11. --- src/components/blackout/Blackout.tsx | 40 ++++++++-------------------- src/pages/artist/step1/Step1.tsx | 2 +- src/pages/artist/step2/Step2.tsx | 2 +- 3 files changed, 13 insertions(+), 31 deletions(-) diff --git a/src/components/blackout/Blackout.tsx b/src/components/blackout/Blackout.tsx index ee25957..aec1afb 100644 --- a/src/components/blackout/Blackout.tsx +++ b/src/components/blackout/Blackout.tsx @@ -17,7 +17,11 @@ const BlackoutPoetry: React.FC = ({ setSelectedWordIndexes, setPoemSnapshots, }) => { - const words = passageText.match(/[\w’']+|[.,!?;:“”"()\-\—]/g); + const [passageText] = useState( + "Twilight settled over Zuckerman’s barn, and a feeling of peace. Fern knew it was almost suppertime but she couldn’t bear to leave. Swallows passed on silent wings, in and out of the doorways, bringing food to their young ones. From across the road a bird sang “Whippoorwill, whippoorwill!” Lurvy sat down under an apple tree and lit his pipe; the animals sniffed the familiar smell of strong tobacco. Wilbur heard the trill of the tree toad and the occasional slamming of the kitchen door. All these sounds made him feel comfortable and happy, for he loved life and loved to be a part of the world on a summer evening. But as he lay there he remembered what the old sheep had told him. The thought of death came to him and he began to tremble with fear." + ); + + const words = passageText.split(" "); const [historyIndex, setHistoryIndex] = useState(-1); // Track undo/redo position const [history, setHistory] = useState([]); @@ -139,30 +143,19 @@ const BlackoutPoetry: React.FC = ({ className="leading-relaxed flex flex-wrap select-none h-max" onCopy={(e) => e.preventDefault()} > - {words?.map((word, i) => { + {words.map((word, i) => { const isSelected = selectedWordIndexes.includes(i); const textColor = isSelected ? "text-main text-light-grey-1" : "text-main hover:text-blue-800 hover:underline"; - const nextIsPunctuation = - i < words.length - 1 && /^[.,!?;:“”"()\-\—]$/.test(words[i + 1]); - - const isPunctuation = /^[.,!?;:“”"()\-\—]$/.test(word); - - const spacingClass = isPunctuation - ? "pl-0 pr-1" - : nextIsPunctuation - ? "pl-1 pr-0" - : "px-1"; - return ( toggleSelect(i)} - className={`cursor-pointer transition duration-200 ${spacingClass} ${textColor}`} + className={`cursor-pointer transition px-1 duration-200 ${textColor}`} > - {word} + {word + " "} ); })} @@ -173,29 +166,18 @@ const BlackoutPoetry: React.FC = ({ className="leading-relaxed flex flex-wrap select-none h-max" onCopy={(e) => e.preventDefault()} > - {words?.map((word, i) => { + {words.map((word, i) => { const isSelected = selectedWordIndexes.includes(i); const blackoutStyle = isSelected ? "text-main text-dark-grey" : "text-main text-dark-grey bg-dark-grey"; - const nextIsPunctuation = - i < words.length - 1 && /^[.,!?;:“”"()\-\—]$/.test(words[i + 1]); - - const isPunctuation = /^[.,!?;:“”"()\-\—]$/.test(word); - - const spacingClass = isPunctuation - ? "pl-0 pr-1" - : nextIsPunctuation - ? "pl-1 pr-0" - : "px-1"; - return ( - {word} + {word + " "} ); })} diff --git a/src/pages/artist/step1/Step1.tsx b/src/pages/artist/step1/Step1.tsx index f87d6f2..a93ff86 100644 --- a/src/pages/artist/step1/Step1.tsx +++ b/src/pages/artist/step1/Step1.tsx @@ -63,7 +63,7 @@ const ArtistStep1 = () => { title="Step 1: Familiarize yourself with the text" description="This is your time to familiarize yourself with the text and brainstorm for your poem. Feel free to take any notes in the text box below. Your notes will be accessible during the writing portion." duration={60} - autoRedirectDuration={300} + autoRedirectDuration={120} afterDuration={onComplete} buttonText="Begin Writing" llmAccess={userType == "TOTAL_ACCESS" || userType == "SPARK"} diff --git a/src/pages/artist/step2/Step2.tsx b/src/pages/artist/step2/Step2.tsx index 372d795..9458147 100644 --- a/src/pages/artist/step2/Step2.tsx +++ b/src/pages/artist/step2/Step2.tsx @@ -63,7 +63,7 @@ const ArtistStep2 = () => { title="Step 2: Write your poem" description="Create a poem by clicking on words in the passage." duration={180} - autoRedirectDuration={420} + autoRedirectDuration={120} afterDuration={onComplete} buttonText="Submit" llmAccess={userType == "TOTAL_ACCESS" || userType == "WRITING"} From f5b3cad5b14df1d83cd314f7c6fe12e1606bc95b Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Mon, 10 Nov 2025 11:42:48 -0500 Subject: [PATCH 8/9] yeehaw --- src/components/blackout/Blackout.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/blackout/Blackout.tsx b/src/components/blackout/Blackout.tsx index aec1afb..d05b121 100644 --- a/src/components/blackout/Blackout.tsx +++ b/src/components/blackout/Blackout.tsx @@ -17,10 +17,6 @@ const BlackoutPoetry: React.FC = ({ setSelectedWordIndexes, setPoemSnapshots, }) => { - const [passageText] = useState( - "Twilight settled over Zuckerman’s barn, and a feeling of peace. Fern knew it was almost suppertime but she couldn’t bear to leave. Swallows passed on silent wings, in and out of the doorways, bringing food to their young ones. From across the road a bird sang “Whippoorwill, whippoorwill!” Lurvy sat down under an apple tree and lit his pipe; the animals sniffed the familiar smell of strong tobacco. Wilbur heard the trill of the tree toad and the occasional slamming of the kitchen door. All these sounds made him feel comfortable and happy, for he loved life and loved to be a part of the world on a summer evening. But as he lay there he remembered what the old sheep had told him. The thought of death came to him and he began to tremble with fear." - ); - const words = passageText.split(" "); const [historyIndex, setHistoryIndex] = useState(-1); // Track undo/redo position const [history, setHistory] = useState([]); From 4765c1419577398a2f6ce54813e75062166866fd Mon Sep 17 00:00:00 2001 From: Sarah Wang Date: Mon, 10 Nov 2025 11:46:20 -0500 Subject: [PATCH 9/9] asejfuphrfa --- src/components/chatbot/Chatbot.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/chatbot/Chatbot.tsx b/src/components/chatbot/Chatbot.tsx index 9fc6aca..98da85e 100644 --- a/src/components/chatbot/Chatbot.tsx +++ b/src/components/chatbot/Chatbot.tsx @@ -80,9 +80,7 @@ export default function ChatTab({ const openingMessage = { role: Role.LLM, content: - stage == "SPARK" - ? "Hello! I'm your assistant for today. I am just ChatGPT, so feel free to use me just as you would in your day-to-day activities. I'm here to help you brainstorm, refine, or analyze blackout poetry as you create your own piece." - : "LLM During the Writing stage", + "Hello! I'm your assistant for today. I am just ChatGPT, so feel free to use me just as you would in your day-to-day activities. I'm here to help you brainstorm, refine, or analyze blackout poetry as you create your own piece.", }; useEffect(() => {