Skip to content

Commit 20b73de

Browse files
committed
Replaces TextField for theme and title with a react-select dropdown of options from dictionary.com, formatted to only allow capitalized, singularized words
1 parent 02253bf commit 20b73de

File tree

7 files changed

+276
-62
lines changed

7 files changed

+276
-62
lines changed

components/canvas/QuestionMasterDialog.tsx

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import {
77
Button,
88
Dialog,
99
DialogContent,
10-
TextField,
1110
Typography,
1211
} from "@mui/material"
1312
import React, { useEffect, useState } from "react"
14-
import { sendWebSocketMessage } from "./utils"
13+
import { OptionType, sendWebSocketMessage } from "./utils"
14+
import WordSearchSelect from "./WordSearchSelect"
1515

1616
const QuestionMasterDialog = ({
1717
gameCode,
@@ -22,6 +22,12 @@ const QuestionMasterDialog = ({
2222
}) => {
2323
const [theme, setTheme] = useState("")
2424
const [title, setTitle] = useState("")
25+
const [selectedTheme, setSelectedTheme] = useState<OptionType | undefined>(
26+
undefined
27+
)
28+
const [selectedTitle, setSelectedTitle] = useState<OptionType | undefined>(
29+
undefined
30+
)
2531
const [isOpen, setIsOpen] = useState(true)
2632
const [isBackDropOpen, setIsBackDropOpen] = useState(false)
2733

@@ -83,30 +89,26 @@ const QuestionMasterDialog = ({
8389
}
8490
}
8591

86-
const capitalizeAndOneWord = (input: string) => {
87-
const words = input.split(/\s+/) // Split by any whitespace
88-
if (words.length > 0) {
89-
const firstWord = words[0]
90-
return (
91-
firstWord.charAt(0).toUpperCase() + firstWord.slice(1).toLowerCase()
92-
)
93-
}
94-
return ""
95-
}
96-
97-
const handleThemeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
98-
setTheme(capitalizeAndOneWord(e.target.value))
92+
const handleThemeSelectChange = (option: OptionType | null) => {
93+
setSelectedTheme(option ?? undefined)
94+
setTheme(option ? option.value : "")
9995
}
10096

101-
const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
102-
setTitle(capitalizeAndOneWord(e.target.value))
97+
const handleTitleSelectChange = (option: OptionType | null) => {
98+
setSelectedTitle(option ?? undefined)
99+
setTitle(option ? option.value : "")
103100
}
104101

105102
return (
106103
<>
107-
<Dialog open={isOpen}>
104+
<Dialog open={isOpen} PaperProps={{ style: { overflowY: "visible" } }}>
108105
<DialogContent
109-
sx={{ textAlign: "center", minWidth: "400px", paddingBottom: 1 }}
106+
sx={{
107+
textAlign: "center",
108+
minWidth: "400px",
109+
paddingBottom: 1,
110+
overflowY: "visible",
111+
}}
110112
>
111113
<Typography variant="h6" fontWeight="bold">
112114
You are the Question Master!
@@ -124,24 +126,20 @@ const QuestionMasterDialog = ({
124126
<Box marginLeft={"-1em"} marginBottom={"0.2em"}>
125127
<Typography variant="body2">① What is your theme?</Typography>
126128
</Box>
127-
<TextField
128-
fullWidth
129-
variant="standard"
130-
placeholder="Animals"
131-
value={theme}
132-
onChange={handleThemeChange}
129+
<WordSearchSelect
130+
placeholder="Animal"
131+
onChange={handleThemeSelectChange}
132+
value={selectedTheme}
133133
/>
134134
</Box>
135135
<Box width="45%">
136136
<Box marginLeft={"-2em"} marginBottom={"0.2em"}>
137137
<Typography variant="body2">② What is your title?</Typography>
138138
</Box>
139-
<TextField
140-
fullWidth
141-
variant="standard"
139+
<WordSearchSelect
142140
placeholder="Lion"
143-
value={title}
144-
onChange={handleTitleChange}
141+
onChange={handleTitleSelectChange}
142+
value={selectedTitle}
145143
/>
146144
</Box>
147145
</Box>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from "react"
2+
import AsyncSelect from "react-select/async"
3+
import { debounce } from "lodash"
4+
import { OptionType } from "./utils"
5+
6+
interface WordSearchSelectProps {
7+
placeholder?: string
8+
onChange: (selectedOption: any) => void
9+
value: OptionType | undefined
10+
}
11+
12+
const WordSearchSelect: React.FC<WordSearchSelectProps> = ({
13+
placeholder,
14+
onChange,
15+
value,
16+
}) => {
17+
const loadOptions = (
18+
inputValue: string,
19+
callback: (options: OptionType[]) => void
20+
) => {
21+
fetch(`/api/words/search?text=${inputValue}`)
22+
.then((response) => response.json())
23+
.then((data) => {
24+
const options = data.map((word: string) => ({
25+
label: word,
26+
value: word,
27+
}))
28+
callback(options)
29+
})
30+
}
31+
32+
const debouncedLoadOptions = debounce(loadOptions, 500)
33+
34+
const customStyles = {
35+
menu: (provided: any) => ({ ...provided, zIndex: 9999 }),
36+
}
37+
38+
return (
39+
<AsyncSelect<OptionType>
40+
loadOptions={debouncedLoadOptions}
41+
onChange={onChange}
42+
value={value}
43+
placeholder={placeholder}
44+
styles={customStyles}
45+
/>
46+
)
47+
}
48+
49+
export default WordSearchSelect

components/canvas/YouWereCaughtDialog.tsx

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
"use client"
22

3-
import {
4-
Box,
5-
Button,
6-
DialogContent,
7-
TextField,
8-
Typography,
9-
} from "@mui/material"
3+
import { Box, Button, DialogContent, Typography } from "@mui/material"
104
import React, { useState } from "react"
11-
import { sendWebSocketMessage } from "./utils"
5+
import { OptionType, sendWebSocketMessage } from "./utils"
6+
import WordSearchSelect from "./WordSearchSelect"
127

138
const YouWereCaughtDialog = ({
149
canvasWebSocket,
@@ -18,20 +13,13 @@ const YouWereCaughtDialog = ({
1813
gameCode: string
1914
}) => {
2015
const [title, setTitle] = useState("")
16+
const [selectedTitle, setSelectedTitle] = useState<OptionType | undefined>(
17+
undefined
18+
)
2119

22-
const capitalizeAndOneWord = (input: string) => {
23-
const words = input.split(/\s+/) // Split by any whitespace
24-
if (words.length > 0) {
25-
const firstWord = words[0]
26-
return (
27-
firstWord.charAt(0).toUpperCase() + firstWord.slice(1).toLowerCase()
28-
)
29-
}
30-
return ""
31-
}
32-
33-
const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
34-
setTitle(capitalizeAndOneWord(e.target.value))
20+
const handleTitleSelectChange = (option: OptionType | null) => {
21+
setSelectedTitle(option ?? undefined)
22+
setTitle(option ? option.value : "")
3523
}
3624

3725
const handleSubmitTitle = () => {
@@ -50,8 +38,9 @@ const YouWereCaughtDialog = ({
5038
paddingRight={4}
5139
width={"40em"}
5240
height={"24em"}
41+
sx={{ overflowY: "visible" }}
5342
>
54-
<DialogContent>
43+
<DialogContent sx={{ overflowY: "visible" }}>
5544
<Box
5645
display="flex"
5746
flexDirection="column"
@@ -71,12 +60,11 @@ const YouWereCaughtDialog = ({
7160
</Box>
7261
<Box display={"flex"} flexDirection={"row"} gap={2}>
7362
<Typography variant="body1">What is the title?</Typography>
74-
<Box marginTop={"-3px"}>
75-
<TextField
76-
variant="standard"
63+
<Box marginTop={"-8px"} width={"15em"}>
64+
<WordSearchSelect
7765
placeholder="Title"
78-
value={title}
79-
onChange={handleTitleChange}
66+
onChange={handleTitleSelectChange}
67+
value={selectedTitle}
8068
/>
8169
</Box>
8270
</Box>

components/canvas/utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@ export const sendWebSocketMessage = (socket: WebSocket | null, data: object) =>
1414
}
1515
}
1616
}
17+
18+
export interface OptionType {
19+
label: string
20+
value: string
21+
}

0 commit comments

Comments
 (0)