Skip to content

Commit b85ab13

Browse files
authored
Merge pull request #57 from rayyan35p/main
UI Changes
2 parents 0020efd + e8e6d21 commit b85ab13

File tree

5 files changed

+167
-66
lines changed

5 files changed

+167
-66
lines changed

Frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"@testing-library/jest-dom": "^5.17.0",
88
"@testing-library/react": "^13.4.0",
99
"@testing-library/user-event": "^13.5.0",
10+
"ag-grid-react": "^32.3.2",
1011
"axios": "^1.7.7",
1112
"bootstrap": "^5.3.3",
1213
"jwt-decode": "^4.0.0",
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from 'react'
2+
import { useState, useEffect } from 'react'
3+
4+
function DetailQn({ question, handleClose }) {
5+
const [categories, setCategories] = useState(question.category);
6+
const [complexity, setComplexity] = useState(question.complexity);
7+
const [description, setDescription] = useState(question.description);
8+
const [title, setTitle] = useState(question.title);
9+
const [error, setError] = useState(null);
10+
11+
return (
12+
<div className='d-flex bg-primary justify-content-center align-items-center'>
13+
<div className="w-100 bg-white px-3 pb-3">
14+
{error && <div className="alert alert-danger">{error}</div>}
15+
<div className="mb-2">
16+
<b>Title</b>
17+
<div className="mt-1">
18+
<p>{title}</p>
19+
</div>
20+
</div>
21+
<div className="mb-2">
22+
<b>Category</b>
23+
24+
{/* Display selected categories as tags */}
25+
<div style={{ marginTop: '5px' }}>
26+
{categories.map((category, index) => (
27+
<span
28+
key={index}
29+
style={{
30+
display: 'inline-block',
31+
padding: '5px',
32+
margin: '5px',
33+
backgroundColor: '#e0e0e0',
34+
borderRadius: '5px'
35+
}}
36+
>
37+
{category}
38+
</span>
39+
))}
40+
</div>
41+
</div>
42+
<b>Complexity</b>
43+
<div className="mt-1">
44+
<p>{complexity}</p>
45+
</div>
46+
<div className="mb-3">
47+
<b>Description</b>
48+
<div className="mt-1">
49+
<p>{description}</p>
50+
</div>
51+
</div>
52+
</div>
53+
</div>
54+
)
55+
}
56+
57+
export default DetailQn

Frontend/src/components/question/Question.jsx

Lines changed: 98 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
import React, { useState, useEffect } from 'react';
22
import Modal from "react-bootstrap/Modal";
3-
import Table from "react-bootstrap/Table";
43
import ButtonGroup from "react-bootstrap/ButtonGroup";
54
import CreateQn from "./CreateQn";
65
import EditQn from "./EditQn";
6+
import DetailQn from "./DetailQn";
77
import questionService from "../../services/questions"
88
import userService from "../../services/users";
99
import categoryService from "../../services/categories";
10-
10+
import { AgGridReact } from 'ag-grid-react'; // React Data Grid Component
11+
import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the Data Grid
12+
import "ag-grid-community/styles/ag-theme-quartz.css"; // Optional Theme applied to the Data Grid
1113

1214
function Question() {
1315
const [questions, setQuestions] = useState([]);
1416
const [showComponent, setShowComponent] = useState(false);
1517
const [showDeleteModal, setShowDeleteModal] = useState(false);
1618
const [questionToDelete, setQuestionToDelete] = useState(null);
1719
const [showEditModal, setShowEditModal] = useState(false);
20+
const [showDetailModal, setShowDetailModal] = useState(false);
1821
const [currentQuestion, setCurrentQuestion] = useState(null);
1922
const [isAdmin, setIsAdmin] = useState(false);
2023

@@ -50,16 +53,20 @@ function Question() {
5053
console.log('Error:', e);
5154
});
5255
}, []);
53-
54-
const easyQuestions = questions.filter(q => q.complexity === "Easy")
55-
const mediumQuestions = questions.filter(q => q.complexity === "Medium")
56-
const hardQuestions = questions.filter(q => q.complexity === "Hard")
5756

5857
const addQuestion = (newQuestion) => {
5958
setQuestions((prevQuestions) => [...prevQuestions, newQuestion]);
6059
};
6160

62-
61+
const handleShowDetailModal = (question) => {
62+
setCurrentQuestion(question);
63+
setShowDetailModal(true);
64+
}
65+
66+
const handleCloseDetailModal = () => {
67+
setShowDetailModal(false);
68+
}
69+
6370
const editQuestion = (id, updatedQuestion) => {
6471
const updatedQuestions = questions.map((q) =>
6572
q._id === id ? { ...q, ...updatedQuestion } : q
@@ -128,52 +135,82 @@ function Question() {
128135
};
129136

130137

131-
const renderQuestionsTable = (questions) => {
132-
const sortedQuestions = [...questions].sort((a, b) => a.id - b.id)
138+
const renderQuestionsTable = () => {
139+
const editDeleteButtonComponent = (props) => {
140+
const question = props.data;
141+
return (
142+
<ButtonGroup className="container-fluid mt-1 mb-1">
143+
<button
144+
className='btn btn-success btn-sm'
145+
onClick={() => handleShowEditModal(question)}
146+
>
147+
Edit
148+
</button>
149+
<button className='btn btn-danger btn-sm' size="sm"
150+
onClick={() => handleShowDelete(question._id)}>
151+
Delete
152+
</button>
153+
</ButtonGroup>
154+
);
155+
};
133156

157+
const showDetailButtonComponent = (props) => {
158+
const question = props.data;
159+
return (
160+
<ButtonGroup className="container-fluid mt-1 mb-1">
161+
<button
162+
className='btn btn-info btn-sm'
163+
onClick={() => handleShowDetailModal(question)}
164+
>
165+
Show Details
166+
</button>
167+
</ButtonGroup>
168+
);
169+
};
170+
171+
const colDefs = [
172+
{ field: "id", flex: 1, wrapText: true, sort: "asc" },
173+
{ field: "title", flex: 4, wrapText: true},
174+
{ field: "category", flex: 3, autoHeight: true, cellDataType: 'text' },
175+
{
176+
field: "complexity",
177+
flex: 1.5,
178+
comparator: (valueA, valueB) => {
179+
if (valueA === valueB) return 0;
180+
if (valueA === "Easy" || valueB === "Hard") return -1;
181+
if (valueA === "Hard" || valueB === "Easy") return 1;
182+
}
183+
},
184+
{
185+
field: "details",
186+
width: 200,
187+
resizable: false,
188+
sortable: false,
189+
cellRenderer: showDetailButtonComponent },
190+
...(isAdmin ? [{
191+
field: "action",
192+
width: 200,
193+
resizable: false,
194+
sortable: false,
195+
cellRenderer: editDeleteButtonComponent
196+
}] : [])
197+
];
198+
134199
return (
135-
<Table>
136-
<thead>
137-
<tr>
138-
<th>ID</th>
139-
<th>Title</th>
140-
<th>Description</th>
141-
<th>Category</th>
142-
{isAdmin && (<th>Action</th>)}
143-
</tr>
144-
</thead>
145-
<tbody>
146-
{sortedQuestions.map((question) => (
147-
<tr key={question.id}>
148-
<td>{question.id}</td>
149-
<td>{question.title}</td>
150-
<td>{question.description}</td>
151-
<td>{question.category ? question.category.join(", ") : ''}</td>
152-
{isAdmin && (
153-
<td>
154-
<ButtonGroup className="mb-2">
155-
<button
156-
className='btn btn-success'
157-
onClick={() => handleShowEditModal(question)}
158-
>
159-
Edit
160-
</button>
161-
<button className='btn btn-danger' size="sm"
162-
onClick={() => handleShowDelete(question._id)}>
163-
Delete
164-
</button>
165-
</ButtonGroup>
166-
</td>
167-
)}
168-
</tr>
169-
))}
170-
</tbody>
171-
</Table>
200+
<div
201+
className="container-fluid ag-theme-quartz"
202+
style={{ height: 500 }}
203+
>
204+
<AgGridReact
205+
rowData={questions}
206+
columnDefs={colDefs}
207+
/>
208+
</div>
172209
);
173210
};
174211

175212
return (
176-
<div className="d-flex">
213+
<div className="container-fluid">
177214
<div className='bg-white rounded p-3 m-3'>
178215
<div className="d-flex justify-content-between">
179216
<h1>Questions</h1>
@@ -194,14 +231,7 @@ function Question() {
194231
<hr/>
195232

196233
<div className="container">
197-
<h2 className="p-2">Easy Questions</h2>
198-
{renderQuestionsTable(easyQuestions)}
199-
200-
<h2 className="p-2">Medium Questions</h2>
201-
{renderQuestionsTable(mediumQuestions)}
202-
203-
<h2 className="p-2">Hard Questions</h2>
204-
{renderQuestionsTable(hardQuestions)}
234+
{renderQuestionsTable()}
205235

206236
{/* Edit Modal */}
207237
<Modal show={showEditModal} onHide={handleCloseEditModal} backdrop="static">
@@ -217,6 +247,19 @@ function Question() {
217247
</Modal.Body>
218248
</Modal>
219249

250+
{/* Detail Modal */}
251+
<Modal show={showDetailModal} onHide={handleCloseDetailModal} backdrop="static">
252+
<Modal.Header closeButton>
253+
<Modal.Title>Question Details</Modal.Title>
254+
</Modal.Header>
255+
<Modal.Body>
256+
<DetailQn
257+
question={currentQuestion}
258+
handleClose={handleCloseDetailModal}
259+
/>
260+
</Modal.Body>
261+
</Modal>
262+
220263

221264
<Modal show={showDeleteModal} onHide={handleCloseDelete} centered>
222265
<Modal.Body className="text-center">

Frontend/src/components/user/EditProfilePage.jsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ function EditProfilePage() {
2727
return(
2828
<div>
2929
<NavigationBar/>
30-
<div className="row">
31-
<div className="Navbar col-2">
30+
{/* <div className="row"> */}
31+
{/* <div className="Navbar col-2">
3232
<ProfileSidebar userID={userID}/>
33-
</div>
34-
<div className="col-10">
33+
</div> */}
34+
{/* <div className="col-10"> */}
3535
<EditProfile/>
36-
</div>
37-
</div>
36+
{/* </div> */}
37+
{/* </div> */}
3838
</div>
3939
);
4040
}

Frontend/src/components/user/HistoryPage.jsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ function HistoryPage() {
3333
return(
3434
<div>
3535
<NavigationBar/>
36-
<div className="row">
37-
<div className="Navbar col-2">
36+
{/* <div className="row"> */}
37+
{/* <div className="Navbar col-2">
3838
<ProfileSidebar userID={userID}/>
39-
</div>
40-
<div className="col-10">
39+
</div> */}
40+
<div className="container-fluid p-5">
4141
<HistoryTable userID={userID}/>
4242
</div>
43-
</div>
43+
{/* </div> */}
4444
</div>
4545
);
4646
}

0 commit comments

Comments
 (0)