Skip to content

Commit f99c7a5

Browse files
committed
feat: 방 검색 기능, 검색어 리셋, 퀴즈 수정 기능 구현
1 parent 523617b commit f99c7a5

File tree

9 files changed

+611
-44
lines changed

9 files changed

+611
-44
lines changed

src/layout/game/components/GameSettings.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@ function GameSettings({ roomId }) {
3636
className="w-full px-4 py-3 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors font-medium"
3737
onClick={() => setQuizSelectModalOpen(true)}
3838
>
39-
{selectedQuiz ? selectedQuiz.title : "퀴즈 선택"}
39+
{"퀴즈 선택"}
4040
</button>
41-
{selectedQuiz && <p className="text-sm text-gray-600 mt-2">{selectedQuiz.description}</p>}
4241
</div>
4342
<div className="grid grid-cols-2 gap-4">
4443
<div>

src/pages/quiz/EditQuiz.js

Lines changed: 497 additions & 0 deletions
Large diffs are not rendered by default.

src/pages/quiz/QuizCard.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import styles from './quiz.module.scss';
22
import {Image, Stack} from "react-bootstrap";
3-
import sample from '../../assets/images/sample.png';
43

54
const QuizCard = ({ quiz, onClick }) => {
6-
console.log(quiz)
75
return (
86
<div
97
className={`${styles.quizCard} position-relative`}

src/pages/quiz/QuizDetailModal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const QuizDetailModal = ({ isOpen, onClose, quiz }) => {
101101
<Stack direction="horizontal" gap={3}>
102102
<Button
103103
variant="outline-primary"
104-
onClick={() => navigate(`${quiz.id}/edit`)}
104+
onClick={() => navigate(`${quiz.quizId}/edit`)}
105105
className="px-4 py-2 fw-medium rounded-3"
106106
>
107107
퀴즈 수정

src/pages/quiz/QuizList.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const options = [
1515
{ value: 'creator', label: '제작자' },
1616
];
1717

18-
const quizRequest = async (params = {}) => {
18+
const quizListRequest = async (params = {}) => {
1919
const response = await axios.get('/quizzes', { params });
2020
return response.data;
2121
};
@@ -33,7 +33,7 @@ const QuizList = () => {
3333
});
3434
const { data, refetch } = useApiQuery(
3535
['quizList', queryParams],
36-
() => quizRequest(queryParams),
36+
() => quizListRequest(queryParams),
3737
{
3838
keepPreviousData: true,
3939
staleTime: 1000 * 60 * 5,
@@ -85,6 +85,17 @@ const QuizList = () => {
8585
window.scrollTo({ top: 0, behavior: 'smooth' });
8686
};
8787

88+
const handleReset = () => {
89+
setKeyword('');
90+
setQueryParams({
91+
page: 1,
92+
size: 8,
93+
title: '',
94+
creator: '',
95+
});
96+
// setSearchOn(false);
97+
};
98+
8899
return (
89100
<Container fluid className="px-4">
90101
{/* 검색 영역과 퀴즈 생성 버튼 */}
@@ -99,14 +110,21 @@ const QuizList = () => {
99110
onChange={handleSearchTypeChange}
100111
/>
101112
</div>
102-
<Form.Control
103-
type="text"
104-
placeholder="검색어를 입력하세요..."
105-
value={keyword}
106-
onChange={(e) => setKeyword(e.target.value)}
107-
onKeyDown={handleKeyDown}
108-
className={`flex-fill ${styles.searchInput}`}
109-
/>
113+
<div className={styles.searchInputWrapper}>
114+
<Form.Control
115+
type="text"
116+
placeholder="검색어를 입력하세요..."
117+
value={keyword}
118+
onChange={(e) => setKeyword(e.target.value)}
119+
onKeyDown={handleKeyDown}
120+
className={`flex-fill ${styles.searchInput}`}
121+
/>
122+
{keyword && (
123+
<button className={styles.clearButton} onClick={handleReset}>
124+
125+
</button>
126+
)}
127+
</div>
110128
<Button variant="danger" type="submit" className={`${styles.buttonBase} ${styles.searchButton}`}>
111129
검색
112130
</Button>

src/pages/quiz/quiz.module.scss

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151

5252
.createButton {
5353
min-width: 140px;
54+
margin-top: 2px;
5455
background: linear-gradient(145deg, #ffd700, #ffb300);
5556
color: #333;
5657
box-shadow: 0 2px 8px rgba(255, 215, 0, 0.25);
@@ -63,4 +64,21 @@
6364
border-radius: 12px;
6465
font-size: 14px;
6566
padding: 0 16px;
66-
}
67+
}
68+
69+
.searchInputWrapper {
70+
position: relative;
71+
display: flex;
72+
align-items: center;
73+
flex: 1;
74+
}
75+
76+
.clearButton {
77+
position: absolute;
78+
right: 8px;
79+
background: transparent;
80+
border: none;
81+
font-size: 16px;
82+
cursor: pointer;
83+
color: #aaa;
84+
}

src/pages/room/RoomList.js

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ const enterRoomRequest = async (params) => {
2828
}
2929

3030
const RoomList = () => {
31-
const [searchTerm, setSearchTerm] = useState("")
32-
const [currentPage, setCurrentPage] = useState(1)
33-
const [rooms, setRooms] = useState([])
34-
const [filteredRooms, setFilteredRooms] = useState([])
35-
const [isModalOpen, setIsModalOpen] = useState(false)
36-
const [isFullModalOpen, setIsFullModalOpen] = useState(false)
37-
const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false)
38-
const [selectedRoom, setSelectedRoom] = useState(null)
31+
const [searchTerm, setSearchTerm] = useState("");
32+
const [currentPage, setCurrentPage] = useState(1);
33+
const [rooms, setRooms] = useState([]);
34+
const [filteredRooms, setFilteredRooms] = useState([]);
35+
const [isModalOpen, setIsModalOpen] = useState(false);
36+
const [isFullModalOpen, setIsFullModalOpen] = useState(false);
37+
const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false);
38+
const [selectedRoom, setSelectedRoom] = useState(null);
39+
const [searchOn, setSearchOn] = useState(false);
3940
const navigate = useNavigate();
4041
const ROOMS_PER_PAGE = 8 // 한 페이지당 8개
4142

@@ -61,18 +62,25 @@ const RoomList = () => {
6162

6263
useEffect(() => {
6364
if (data) {
64-
setRooms(data.rooms)
65-
setFilteredRooms(data.rooms)
65+
setRooms(data.rooms);
66+
setFilteredRooms(data.rooms);
6667
}
6768
}, [data])
6869

6970
const handleSearch = () => {
70-
// 검색 로직 구현
71-
const filtered = rooms.filter((room) => room.title.toLowerCase().includes(searchTerm.toLowerCase()))
72-
setFilteredRooms(filtered)
73-
setCurrentPage(1) // 검색 시 첫 페이지로 이동
71+
const filtered = rooms.filter((room) => room.roomName.toLowerCase().includes(searchTerm.toLowerCase()));
72+
setFilteredRooms(filtered);
73+
setCurrentPage(1); // 검색 시 첫 페이지로 이동
74+
setSearchOn(true);
7475
}
7576

77+
const handleReset = () => {
78+
setSearchTerm('');
79+
setFilteredRooms(rooms);
80+
setCurrentPage(1); // 검색 시 첫 페이지로 이동
81+
setSearchOn(false);
82+
};
83+
7684
const handleCreateRoom = (newRoomData) => {
7785
createRoomMutate(newRoomData);
7886
setIsModalOpen(false);
@@ -91,10 +99,6 @@ const RoomList = () => {
9199
enterRoomMutate({ roomId: room.roomId, password: password });
92100
}
93101

94-
const handlePageChange = (page) => {
95-
setCurrentPage(page)
96-
}
97-
98102
const handleKeyPress = (e) => {
99103
if (e.key === "Enter") {
100104
handleSearch()
@@ -117,14 +121,24 @@ const RoomList = () => {
117121
{/* Search Section */}
118122
<section className={styles.searchSection}>
119123
<div className={styles.searchInputGroup}>
120-
<input
121-
type="text"
122-
className={styles.searchInput}
123-
placeholder="방 제목을 입력하세요..."
124-
value={searchTerm}
125-
onChange={(e) => setSearchTerm(e.target.value)}
126-
onKeyPress={handleKeyPress}
127-
/>
124+
<div className={styles.searchInputWrapper}>
125+
<input
126+
type="text"
127+
className={styles.searchInput}
128+
placeholder="방 제목을 입력하세요..."
129+
value={searchTerm}
130+
onChange={(e) => {
131+
setSearchTerm(e.target.value);
132+
setSearchOn(false);
133+
}}
134+
onKeyPress={handleKeyPress}
135+
/>
136+
{searchTerm && (
137+
<button className={styles.clearButton} onClick={handleReset}>
138+
139+
</button>
140+
)}
141+
</div>
128142
<button className={styles.searchButton} onClick={handleSearch}>
129143
검색
130144
</button>
@@ -135,7 +149,7 @@ const RoomList = () => {
135149
</section>
136150

137151
{/* 검색 결과 정보 */}
138-
{searchTerm && (
152+
{searchTerm && searchOn && (
139153
<div className={styles.searchInfo}>
140154
<p>
141155
"{searchTerm}" 검색 결과: {filteredRooms.length}개의 방

src/pages/room/room.module.scss

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,27 @@ body {
103103
gap: 15px;
104104
}
105105

106+
.searchInputWrapper {
107+
position: relative;
108+
display: flex;
109+
align-items: center;
110+
flex: 1;
111+
}
112+
113+
//.searchInput {
114+
// padding-right: 30px; /* X 버튼 영역 확보 */
115+
//}
116+
117+
.clearButton {
118+
position: absolute;
119+
right: 8px;
120+
background: transparent;
121+
border: none;
122+
font-size: 16px;
123+
cursor: pointer;
124+
color: #aaa;
125+
}
126+
106127
.searchLabel {
107128
font-size: 16px;
108129
font-weight: bold;
@@ -892,3 +913,4 @@ body {
892913
}
893914
}
894915
}
916+

src/routes/BaseRoutes.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Rank from "../pages/rank/Rank";
1212
import MyPage from "../pages/mypage/MyPage";
1313
import HostPage from "../pages/game/HostPage";
1414
import ParticipantPage from "../pages/game/ParticipantPage";
15+
import EditQuiz from "../pages/quiz/EditQuiz";
1516

1617
const BaseRoutes = () => {
1718
return (
@@ -30,7 +31,7 @@ const BaseRoutes = () => {
3031
<Route path="/quiz" element={<Layout />}>
3132
<Route index element={<QuizList />} />
3233
<Route path={"create"} element={<CreateQuiz />} />
33-
<Route path={":id/edit"} element={<CreateQuiz />} />
34+
<Route path={":id/edit"} element={<EditQuiz />} />
3435
</Route>
3536
<Route path="/rank" element={<Layout />}>
3637
<Route index element={<Rank />} />

0 commit comments

Comments
 (0)