From 1329de64a342fe04de30eb748201b1fa3b529ac2 Mon Sep 17 00:00:00 2001 From: arnavg24-arch Date: Fri, 6 Feb 2026 08:49:10 -0500 Subject: [PATCH 1/2] Fix CoStar Coloring: smooth typing, drag-and-drop UI labels, and focus fixes --- frontend/src/components/CostarColoring.tsx | 132 ++++++++++++++++----- 1 file changed, 100 insertions(+), 32 deletions(-) diff --git a/frontend/src/components/CostarColoring.tsx b/frontend/src/components/CostarColoring.tsx index efe9ee51..d41141be 100644 --- a/frontend/src/components/CostarColoring.tsx +++ b/frontend/src/components/CostarColoring.tsx @@ -32,6 +32,14 @@ const availableParts = [ "letter_r", ]; +// Helper function to format display names (e.g., "letter_c" -> "Letter C") +const formatDisplayName = (name: string): string => { + return name + .split("_") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "); +}; + enum AlertType { NONE, SUCCESS, @@ -54,6 +62,7 @@ export function CostarColoring({ letter_a: "", letter_r: "", }); + const [rowColors, setRowColors] = useState(["", "", "", "", "", ""]); const [currentColorIndex, setCurrentColorIndex] = useState(0); const colorNextPart = (color: string) => { @@ -91,36 +100,74 @@ export function CostarColoring({ }); } }; + const handleValueOnBlur = (value: string, isColorInput: boolean = false) => { + const val = value.toLowerCase().trim(); - const handleValueOnBlur = (value: string) => { - if ( - !availableColors.includes(value) && - !availableParts.includes(value) && - value !== "" - ) { - setCurrentAlert({ - type: AlertType.FAILURE, - message: "That isn't quite one of the options. Try again.", - }); + + if (isColorInput) { + const strippedValue = val.startsWith('"') && val.endsWith('"') + ? val.substring(1, val.length - 1) + : val; + + if ( + !availableColors.includes(strippedValue) && + value !== "" + ) { + setCurrentAlert({ + type: AlertType.FAILURE, + message: "That isn't quite one of the options. Try again.", + }); + } + } else { + // For letter input + if ( + !availableParts.includes(val) && + value !== "" + ) { + setCurrentAlert({ + type: AlertType.FAILURE, + message: "That isn't quite one of the options. Try again.", + }); + } } }; - const handleColorChange = (part: string, value: string) => { + + + const handleColorChange = (part: string, value: string, rowIndex?: number) => { const val = value.toLowerCase(); if (availableParts.includes(val)) { setCurrentAlert({ type: AlertType.FAILURE, message: "This value is a color, not a body part!", }); + return; } if (value.startsWith('"') && value.endsWith('"')) { const strippedValue = val.substring(1, val.length - 1); - if (availableColors.includes(strippedValue) && part !== "") { + if (availableColors.includes(strippedValue)) { setCurrentAlert({ type: AlertType.SUCCESS, message: "Correct!" }); - setColors((prevColors) => ({ - ...prevColors, - [part]: strippedValue, - })); + + // If typeVariable mode, store by row index + if (props?.typeVariable && rowIndex !== undefined) { + const updatedRowColors = [...rowColors]; + updatedRowColors[rowIndex] = strippedValue; + setRowColors(updatedRowColors); + + // Also update the actual variable if it's been typed + if (part && part !== "") { + setColors((prevColors) => ({ + ...prevColors, + [part]: strippedValue, + })); + } + } else { + // Normal mode - store by variable name + setColors((prevColors) => ({ + ...prevColors, + [part]: strippedValue, + })); + } } else if (availableParts.includes(strippedValue)) { setCurrentAlert({ type: AlertType.FAILURE, @@ -130,6 +177,8 @@ export function CostarColoring({ } }; + + function handleOnDrop(e: React.DragEvent, part: string) { const color = e.dataTransfer.getData("Color") as string; const temp = (colors[part as keyof CostarColorState] = color); @@ -188,40 +237,41 @@ export function CostarColoring({ onDragOver={(e) => handleDragOver(e)} className="border-2 flex flex-row rounded-sm outline-dotted text-center" > -