Skip to content

Commit 71fdb26

Browse files
committed
fix: lintErrorsAgain
1 parent 3cbc36b commit 71fdb26

2 files changed

Lines changed: 555 additions & 60 deletions

File tree

src/components/ResourceManagement/ResourceManagement.jsx

Lines changed: 284 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,207 @@
11
import { useState, useEffect } from 'react';
22
import styles from './ResourceManagement.module.css';
3+
import { useSelector } from 'react-redux';
4+
5+
function SearchBar({ onSearch }) {
6+
const darkMode = useSelector(state => state.theme.darkMode);
7+
const [searchTerm, setSearchTerm] = useState('');
8+
9+
const handleSearch = () => {
10+
onSearch(searchTerm);
11+
};
12+
13+
const handleKeyPress = e => {
14+
if (e.key === 'Enter') {
15+
handleSearch();
16+
}
17+
};
318

4-
function SearchBar() {
519
return (
6-
<div className={styles.searchBarContainer}>
7-
<div className={styles.searchBarContainerLeft}>
8-
<span className={styles.iconAdd}>+</span>
9-
<span className={styles.iconLines}>=</span>
10-
<span className={styles.iconToggle}></span>
20+
<div className={`${darkMode ? styles.darkMode : ''}`}>
21+
<div className={`${styles.searchBarContainer}`}>
22+
<div className={`${styles.searchBarContainerLeft}`}>
23+
<span className={`${styles.iconAdd}`}>+</span>
24+
<span className={`${styles.iconLines}`}>=</span>
25+
<span className={`${styles.iconToggle}`}></span>
26+
</div>
27+
<div className={`${styles.searchBarContainerRight}`}>
28+
<input
29+
type="text"
30+
className={`${styles.searchInput}`}
31+
placeholder="Search"
32+
value={searchTerm}
33+
onChange={e => setSearchTerm(e.target.value)}
34+
onKeyPress={handleKeyPress}
35+
/>
36+
<button type="button" className={`${styles.searchButton}`} onClick={handleSearch}>
37+
Search
38+
</button>
39+
</div>
1140
</div>
12-
<div className={styles.searchBarContainerRight}>
13-
<input type="text" className={styles.searchInput} placeholder="Search" />
14-
<button type="button" className={styles.searchButton}>
15-
Search
16-
</button>
41+
</div>
42+
);
43+
}
44+
45+
function AddLogModal({ isOpen, onClose, onAdd }) {
46+
const darkMode = useSelector(state => state.theme.darkMode);
47+
const [formData, setFormData] = useState({
48+
user: '',
49+
timeDuration: '',
50+
facilities: '',
51+
materials: '',
52+
});
53+
const [validationError, setValidationError] = useState('');
54+
55+
const handleChange = e => {
56+
const { name, value } = e.target;
57+
setFormData(prev => ({
58+
...prev,
59+
[name]: value,
60+
}));
61+
// Clear validation error when user starts typing
62+
if (validationError) {
63+
setValidationError('');
64+
}
65+
};
66+
67+
const handleSubmit = e => {
68+
e.preventDefault();
69+
if (formData.user && formData.timeDuration && formData.facilities && formData.materials) {
70+
onAdd(formData);
71+
setFormData({
72+
user: '',
73+
timeDuration: '',
74+
facilities: '',
75+
materials: '',
76+
});
77+
setValidationError('');
78+
onClose();
79+
} else {
80+
setValidationError('Please fill in all fields');
81+
}
82+
};
83+
84+
const handleOverlayClick = e => {
85+
// Only close if clicking directly on the overlay, not its children
86+
if (e.target === e.currentTarget) {
87+
onClose();
88+
}
89+
};
90+
91+
const handleOverlayKeyDown = e => {
92+
if (e.key === 'Escape') {
93+
onClose();
94+
}
95+
};
96+
97+
useEffect(() => {
98+
const handleEscKey = e => {
99+
if (e.key === 'Escape' && isOpen) {
100+
onClose();
101+
}
102+
};
103+
104+
if (isOpen) {
105+
document.addEventListener('keydown', handleEscKey);
106+
}
107+
108+
return () => {
109+
document.removeEventListener('keydown', handleEscKey);
110+
};
111+
}, [isOpen, onClose]);
112+
113+
if (!isOpen) return null;
114+
115+
return (
116+
<div className={`${darkMode ? styles.darkMode : ''}`}>
117+
<div
118+
className={`${styles.modalOverlay}`}
119+
onClick={handleOverlayClick}
120+
onKeyDown={handleOverlayKeyDown}
121+
role="button"
122+
tabIndex={0}
123+
aria-label="Close modal"
124+
>
125+
<div
126+
className={`${styles.modalContent}`}
127+
role="dialog"
128+
aria-modal="true"
129+
aria-labelledby="modal-title"
130+
>
131+
<div className={`${styles.modalHeader}`}>
132+
<h3 id="modal-title">Add New Log</h3>
133+
<button type="button" className={`${styles.closeButton}`} onClick={onClose}>
134+
×
135+
</button>
136+
</div>
137+
{validationError && (
138+
<div className={`${styles.errorMessage}`} role="alert">
139+
{validationError}
140+
</div>
141+
)}
142+
<form onSubmit={handleSubmit}>
143+
<div className={`${styles.formGroup}`}>
144+
<label htmlFor="user">User:</label>
145+
<input
146+
id="user"
147+
type="text"
148+
name="user"
149+
value={formData.user}
150+
onChange={handleChange}
151+
placeholder="First Last"
152+
/>
153+
</div>
154+
<div className={`${styles.formGroup}`}>
155+
<label htmlFor="timeDuration">Time/Duration:</label>
156+
<input
157+
id="timeDuration"
158+
type="text"
159+
name="timeDuration"
160+
value={formData.timeDuration}
161+
onChange={handleChange}
162+
placeholder="00:00:00"
163+
/>
164+
</div>
165+
<div className={`${styles.formGroup}`}>
166+
<label htmlFor="facilities">Facilities:</label>
167+
<input
168+
id="facilities"
169+
type="text"
170+
name="facilities"
171+
value={formData.facilities}
172+
onChange={handleChange}
173+
placeholder="e.g., Landing Page"
174+
/>
175+
</div>
176+
<div className={`${styles.formGroup}`}>
177+
<label htmlFor="materials">Materials:</label>
178+
<input
179+
id="materials"
180+
type="text"
181+
name="materials"
182+
value={formData.materials}
183+
onChange={handleChange}
184+
placeholder="e.g., Location"
185+
/>
186+
</div>
187+
<div className={`${styles.modalActions}`}>
188+
<button type="button" className={`${styles.cancelButton}`} onClick={onClose}>
189+
Cancel
190+
</button>
191+
<button type="submit" className={`${styles.submitButton}`}>
192+
Add Log
193+
</button>
194+
</div>
195+
</form>
196+
</div>
17197
</div>
18198
</div>
19199
);
20200
}
21201

22202
function ResourceManagement() {
23-
const [resources] = useState([
203+
const darkMode = useSelector(state => state.theme.darkMode);
204+
const [resources, setResources] = useState([
24205
{
25206
id: 1,
26207
user: 'First Last',
@@ -103,61 +284,105 @@ function ResourceManagement() {
103284
},
104285
]);
105286

287+
const [filteredResources, setFilteredResources] = useState(resources);
288+
const [isModalOpen, setIsModalOpen] = useState(false);
289+
290+
useEffect(() => {
291+
setFilteredResources(resources);
292+
}, [resources]);
293+
294+
const handleSearch = searchTerm => {
295+
if (!searchTerm.trim()) {
296+
setFilteredResources(resources);
297+
return;
298+
}
299+
300+
const filtered = resources.filter(
301+
resource =>
302+
resource.user.toLowerCase().includes(searchTerm.toLowerCase()) ||
303+
resource.facilities.toLowerCase().includes(searchTerm.toLowerCase()) ||
304+
resource.materials.toLowerCase().includes(searchTerm.toLowerCase()) ||
305+
resource.date.toLowerCase().includes(searchTerm.toLowerCase()),
306+
);
307+
setFilteredResources(filtered);
308+
};
309+
310+
const handleAddLog = newLog => {
311+
const newResource = {
312+
id: resources.length + 1,
313+
...newLog,
314+
date: 'Just now',
315+
};
316+
setResources(prev => [newResource, ...prev]);
317+
};
318+
106319
return (
107-
<div className={styles.resourceManagementDashboard}>
108-
<div className={styles.dashboardTitle}>
109-
<h2>Used Resources</h2>
110-
<button type="button" className={styles.addLogButton}>
111-
Add New Log
112-
</button>
113-
</div>
320+
<div className={`${darkMode ? styles.darkMode : ''}`}>
321+
<div className={`${styles.resourceManagementDashboard}`}>
322+
<div className={`${styles.dashboardTitle}`}>
323+
<h2>Used Resources</h2>
324+
<button
325+
type="button"
326+
className={`${styles.addLogButton}`}
327+
onClick={() => setIsModalOpen(true)}
328+
>
329+
Add New Log
330+
</button>
331+
</div>
114332

115-
<SearchBar />
333+
<SearchBar onSearch={handleSearch} />
116334

117-
<div className={styles.resourceList}>
118-
<div className={styles.resourceHeading}>
119-
<div className={styles.checkboxContainer}>
120-
<input type="checkbox" />
335+
<div className={`${styles.resourceList}`}>
336+
<div className={`${styles.resourceHeading}`}>
337+
<div className={`${styles.checkboxContainer}`}>
338+
<input type="checkbox" />
339+
</div>
340+
<div className={`${styles.resourceHeadingItem}`}>User</div>
341+
<div className={`${styles.resourceHeadingItem}`}>Time/Duration</div>
342+
<div className={`${styles.resourceHeadingItem}`}>Facilities</div>
343+
<div className={`${styles.resourceHeadingItem}`}>Materials</div>
344+
<div className={`${styles.resourceHeadingItem}`}>Date</div>
121345
</div>
122-
<div className={styles.resourceHeadingItem}>User</div>
123-
<div className={styles.resourceHeadingItem}>Time/Duration</div>
124-
<div className={styles.resourceHeadingItem}>Facilities</div>
125-
<div className={styles.resourceHeadingItem}>Materials</div>
126-
<div className={styles.resourceHeadingItem}>Date</div>
127-
</div>
128-
<hr className={styles.lineSperator} />
346+
<hr className={`${styles.lineSperator}`} />
129347

130-
{resources.map(resource => (
131-
<div key={resource.id}>
132-
<div className={styles.resourceItem}>
133-
<div className={styles.checkboxContainer}>
134-
<input type="checkbox" />
135-
</div>
136-
<div className={styles.resourceItemDetail}>{resource.user}</div>
137-
<div className={styles.resourceItemDetail}>{resource.timeDuration}</div>
138-
<div className={styles.resourceItemDetail}>{resource.facilities}</div>
139-
<div className={styles.resourceItemDetail}>{resource.materials}</div>
140-
<div className={styles.resourceItemDetail}>
141-
<span className={styles.calendarIcon}>📅</span> {resource.date}
348+
{filteredResources.map(resource => (
349+
<div key={resource.id}>
350+
<div className={`${styles.resourceItem}`}>
351+
<div className={`${styles.checkboxContainer}`}>
352+
<input type="checkbox" />
353+
</div>
354+
<div className={`${styles.resourceItemDetail}`}>{resource.user}</div>
355+
<div className={`${styles.resourceItemDetail}`}>{resource.timeDuration}</div>
356+
<div className={`${styles.resourceItemDetail}`}>{resource.facilities}</div>
357+
<div className={`${styles.resourceItemDetail}`}>{resource.materials}</div>
358+
<div className={`${styles.resourceItemDetail}`}>
359+
<span className={`${styles.calendarIcon}`}>📅</span> {resource.date}
360+
</div>
142361
</div>
362+
<hr className={`${styles.lineSperator}`} />
143363
</div>
144-
<hr className={styles.lineSperator} />
145-
</div>
146-
))}
147-
</div>
364+
))}
365+
</div>
366+
367+
<div className={`${styles.rmPagination}`}>
368+
<button type="button" className={`${styles.arrowButton}`}>
369+
370+
</button>
371+
<button type="button">1</button>
372+
<button type="button">2</button>
373+
<button type="button">3</button>
374+
<button type="button">4</button>
375+
<button type="button">5</button>
376+
<button type="button" className={`${styles.arrowButton}`}>
377+
378+
</button>
379+
</div>
148380

149-
<div className="pagination">
150-
<button type="button" className={styles.arrowButton}>
151-
152-
</button>
153-
<button type="button">1</button>
154-
<button type="button">2</button>
155-
<button type="button">3</button>
156-
<button type="button">4</button>
157-
<button type="button">5</button>
158-
<button type="button" className={styles.arrowButton}>
159-
160-
</button>
381+
<AddLogModal
382+
isOpen={isModalOpen}
383+
onClose={() => setIsModalOpen(false)}
384+
onAdd={handleAddLog}
385+
/>
161386
</div>
162387
</div>
163388
);

0 commit comments

Comments
 (0)