Skip to content

Commit 32af6aa

Browse files
Add CPDashboard search bar with clear and icon
1 parent ac8c731 commit 32af6aa

3 files changed

Lines changed: 1038 additions & 594 deletions

File tree

src/components/CommunityPortal/CPDashboard.jsx

Lines changed: 93 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { useState, useEffect } from 'react';
22
import { Container, Row, Col, Card, CardBody, Button, Input } from 'reactstrap';
3-
import './CPDashboard.css';
4-
import { FaCalendarAlt, FaMapMarkerAlt, FaUserAlt } from 'react-icons/fa';
3+
import { FaCalendarAlt, FaMapMarkerAlt, FaUserAlt, FaSearch, FaTimes } from 'react-icons/fa';
4+
import styles from './CPDashboard.module.css';
55

66
export function CPDashboard() {
77
const [events, setEvents] = useState([]);
8-
const [search, setSearch] = useState('');
8+
const [searchInput, setSearchInput] = useState('');
9+
const [searchQuery, setSearchQuery] = useState('');
910

1011
useEffect(() => {
1112
const mockEvents = [
@@ -37,69 +38,108 @@ export function CPDashboard() {
3738
setEvents(mockEvents);
3839
}, []);
3940

41+
const handleSearchClick = () => {
42+
setSearchQuery(searchInput.trim());
43+
};
44+
45+
const handleSearchKeyDown = e => {
46+
if (e.key === 'Enter') {
47+
setSearchQuery(searchInput.trim());
48+
}
49+
};
50+
51+
const filteredEvents = events.filter(event => {
52+
if (!searchQuery) return true;
53+
const term = searchQuery.toLowerCase();
54+
return (
55+
event.title.toLowerCase().includes(term) ||
56+
event.location.toLowerCase().includes(term) ||
57+
event.organizer.toLowerCase().includes(term)
58+
);
59+
});
60+
4061
return (
41-
<Container fluid className="dashboard-container">
42-
<header className="dashboard-header">
62+
<Container fluid className={styles['dashboard-container']}>
63+
<header className={styles['dashboard-header']}>
4364
<h1>All Events</h1>
44-
<div className="dashboard-controls">
45-
<div className="dashboard-search-container">
65+
66+
<div className={styles['dashboard-controls']}>
67+
<div className={styles['dashboard-search-container']}>
4668
<Input
69+
id="search"
4770
type="search"
4871
placeholder="Search events..."
49-
value={search}
50-
onChange={e => setSearch(e.target.value)}
51-
className="dashboard-search"
72+
value={searchInput}
73+
onChange={e => setSearchInput(e.target.value)}
74+
onKeyDown={handleSearchKeyDown}
75+
className={styles['dashboard-search-input']}
5276
/>
77+
78+
{searchInput && (
79+
<button
80+
type="button"
81+
className={styles['dashboard-clear-btn']}
82+
onClick={() => {
83+
setSearchInput('');
84+
setSearchQuery('');
85+
}}
86+
>
87+
<FaTimes />
88+
</button>
89+
)}
90+
91+
<button
92+
type="button"
93+
className={styles['dashboard-search-icon-btn']}
94+
onClick={handleSearchClick}
95+
aria-label="Search events"
96+
>
97+
<FaSearch />
98+
</button>
5399
</div>
54-
{/* <Dropdown isOpen={dropdownOpen} toggle={toggleDropdown} className="community-dropdown">
55-
<DropdownToggle caret color="secondary">
56-
Community Portal
57-
</DropdownToggle>
58-
<DropdownMenu>
59-
<DropdownItem onClick={() => handleNavigation('/home')}>Home</DropdownItem>
60-
<DropdownItem onClick={() => handleNavigation('/events')}>Events</DropdownItem>
61-
<DropdownItem onClick={() => handleNavigation('/about')}>About Us</DropdownItem>
62-
<DropdownItem onClick={() => handleNavigation('/contact')}>Contact</DropdownItem>
63-
</DropdownMenu>
64-
</Dropdown> */}
65100
</div>
66101
</header>
67102

68103
<Row>
69-
<Col md={3} className="dashboard-sidebar">
70-
<div className="filter-section">
104+
<Col md={3} className={styles['dashboard-sidebar']}>
105+
<div className={styles['filter-section']}>
71106
<h4>Search Filters</h4>
72-
<div className="filter-item">
107+
108+
<div className={styles['filter-item']}>
73109
<label htmlFor="date-tomorrow"> Dates</label>
74-
<div className="filter-options-horizontal">
110+
<div className={styles['filter-options-horizontal']}>
75111
<div>
76112
<Input type="radio" name="dates" /> Tomorrow
77113
</div>
78114
<div>
79115
<Input type="radio" name="dates" /> This Weekend
80116
</div>
81117
</div>
82-
<Input type="date" placeholder="Ending After" className="date-filter" />
118+
<Input type="date" placeholder="Ending After" className={styles['date-filter']} />
83119
</div>
84-
<div className="filter-item">
120+
121+
<div className={styles['filter-item']}>
85122
<label htmlFor="online-only">Online</label>
86123
<div>
87124
<Input type="checkbox" /> Online Only
88125
</div>
89126
</div>
90-
<div className="filter-item">
127+
128+
<div className={styles['filter-item']}>
91129
<label htmlFor="branches">Branches</label>
92130
<Input type="select">
93131
<option>Select branches</option>
94132
</Input>
95133
</div>
96-
<div className="filter-item">
134+
135+
<div className={styles['filter-item']}>
97136
<label htmlFor="themes">Themes</label>
98137
<Input type="select">
99138
<option>Select themes</option>
100139
</Input>
101140
</div>
102-
<div className="filter-item">
141+
142+
<div className={styles['filter-item']}>
103143
<label htmlFor="categories">Categories</label>
104144
<Input type="select">
105145
<option>Select categories</option>
@@ -108,36 +148,42 @@ export function CPDashboard() {
108148
</div>
109149
</Col>
110150

111-
<Col md={9} className="dashboard-main">
112-
<h2 className="section-title">Events</h2>
151+
<Col md={9} className={styles['dashboard-main']}>
152+
<h2 className={styles['section-title']}>Events</h2>
153+
113154
<Row>
114-
{events.length > 0 ? (
115-
events.map(event => (
116-
<Col md={4} key={event.id} className="event-card-col">
117-
<Card className="event-card">
118-
<div className="event-card-img-container">
119-
<img src={event.image} alt={event.title} className="event-card-img" />
155+
{filteredEvents.length > 0 ? (
156+
filteredEvents.map(event => (
157+
<Col md={4} key={event.id} className={styles['event-card-col']}>
158+
<Card className={styles['event-card']}>
159+
<div className={styles['event-card-img-container']}>
160+
<img
161+
src={event.image}
162+
alt={event.title}
163+
className={styles['event-card-img']}
164+
/>
120165
</div>
121166
<CardBody>
122-
<h5 className="event-title">{event.title}</h5>
123-
<p className="event-date">
124-
<FaCalendarAlt className="event-icon" /> {event.date}
167+
<h5 className={styles['event-title']}>{event.title}</h5>
168+
<p className={styles['event-date']}>
169+
<FaCalendarAlt className={styles['event-icon']} /> {event.date}
125170
</p>
126-
<p className="event-location">
127-
<FaMapMarkerAlt className="event-icon" /> {event.location}
171+
<p className={styles['event-location']}>
172+
<FaMapMarkerAlt className={styles['event-icon']} /> {event.location}
128173
</p>
129-
<p className="event-organizer">
130-
<FaUserAlt className="event-icon" /> {event.organizer}
174+
<p className={styles['event-organizer']}>
175+
<FaUserAlt className={styles['event-icon']} /> {event.organizer}
131176
</p>
132177
</CardBody>
133178
</Card>
134179
</Col>
135180
))
136181
) : (
137-
<div className="no-events">No events available</div>
182+
<div className={styles['no-events']}>No events available</div>
138183
)}
139184
</Row>
140-
<div className="dashboard-actions">
185+
186+
<div className={styles['dashboard-actions']}>
141187
<Button color="primary">Show Past Events</Button>
142188
</div>
143189
</Col>

src/components/CommunityPortal/CPDashboard.css renamed to src/components/CommunityPortal/CPDashboard.module.css

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
body {
1+
:global(body) {
22
font-family: 'Poppins', sans-serif;
33
background: #fff;
44
margin: 0;
55
padding: 0;
66
}
77

88
.dashboard-container {
9-
padding: 40px 20px;
9+
padding: 40px 10px;
1010
max-width: 1400px;
1111
margin: 0 auto;
1212
background: #ffffff;
@@ -19,10 +19,40 @@ body {
1919
justify-content: space-between;
2020
align-items: center;
2121
margin-bottom: 30px;
22-
padding: 20px;
22+
padding: 16px 24px;
2323
background: linear-gradient(120deg, #ffffff, #f8f9fa);
2424
border-radius: 12px;
25-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
25+
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
26+
}
27+
28+
.dashboard-controls {
29+
display: flex;
30+
align-items: center;
31+
}
32+
33+
.dashboard-search {
34+
border: none;
35+
padding: 8px 16px;
36+
min-width: 260px;
37+
border-radius: 999px 0 0 999px;
38+
outline: none;
39+
}
40+
41+
.dashboard-search:focus {
42+
box-shadow: none;
43+
}
44+
45+
.dashboard-search-button {
46+
border-radius: 0 999px 999px 0;
47+
border: none;
48+
display: flex;
49+
align-items: center;
50+
justify-content: center;
51+
padding: 0 18px;
52+
}
53+
54+
.dashboard-search-icon {
55+
font-size: 1rem;
2656
}
2757

2858
.dashboard-header h1 {
@@ -41,6 +71,57 @@ body {
4171
transition: all 0.3s ease;
4272
}
4373

74+
/* pill input */
75+
.dashboard-search-input {
76+
padding: 8px 90px 8px 16px; /* extra right padding for icons */
77+
border-radius: 999px;
78+
border: 2px solid #1b3c55;
79+
min-width: 260px;
80+
outline: none;
81+
}
82+
83+
/* clear X button */
84+
.dashboard-clear-btn {
85+
position: absolute;
86+
right: 35px;
87+
top: 45%;
88+
transform: translateY(-50%);
89+
border: none;
90+
background: transparent;
91+
cursor: pointer;
92+
font-size: 0.9rem;
93+
color: #1b3c55;
94+
}
95+
96+
/* blue circular search button inside the bar */
97+
.dashboard-search-icon-btn {
98+
position: absolute;
99+
right: 4px;
100+
top: 50%;
101+
transform: translateY(-50%);
102+
width: 34px;
103+
height: 34px;
104+
border-radius: 50%;
105+
cursor: pointer;
106+
background: #ffffff; /* 🔹 icon background now white */
107+
display: flex;
108+
align-items: center;
109+
justify-content: center;
110+
color: #1b3c55; /* blue magnifying-glass icon */
111+
font-size: 0.9rem;
112+
}
113+
114+
115+
.dashboard-search-container {
116+
position: relative;
117+
display: inline-flex;
118+
align-items: center;
119+
border-radius: 999px;
120+
overflow: hidden;
121+
box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
122+
background: #ffffff;
123+
}
124+
44125
.dashboard-search-container input:focus {
45126
border-color: #34495e;
46127
box-shadow: 0 0 8px rgba(52, 73, 94, 0.3);
@@ -154,3 +235,12 @@ body {
154235
background-color: #34495e;
155236
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
156237
}
238+
239+
/* Hide browser's built-in clear icon for search inputs */
240+
.dashboard-search-input::-webkit-search-cancel-button,
241+
.dashboard-search-input::-webkit-search-decoration,
242+
.dashboard-search-input::-webkit-search-results-button,
243+
.dashboard-search-input::-webkit-search-results-decoration {
244+
-webkit-appearance: none;
245+
appearance: none;
246+
}

0 commit comments

Comments
 (0)