Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .stylelintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public/
node_modules/
dist/
build/
coverage/
2 changes: 1 addition & 1 deletion src/actions/__tests__/authActions.js.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,4 @@ describe('authActions', () => {

expect(setHeaderData(data)).toEqual(expectedAction); // Assert the action
});
});
});
8 changes: 4 additions & 4 deletions src/actions/authActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export const getHeaderData = userId => {
};
};

export const logoutUser = () => dispatch => {
export const logoutUser = () => (dispatch) => {
// Clear any active force-logout timer before logging out
dispatch(stopForceLogout());
localStorage.removeItem(tokenKey);
Expand All @@ -135,18 +135,18 @@ export const startForceLogout = (delayMs = 20000) => (dispatch, getState) => {
const timerId = setTimeout(async () => {
try {
const { userProfile } = getState();

if (userProfile && userProfile._id) {
const { firstName: name, lastName, personalLinks, adminLinks, _id } = userProfile;

await axios.put(ENDPOINTS.USER_PROFILE(_id), {
firstName: name,
lastName,
personalLinks,
adminLinks,
isAcknowledged: true,
});

// eslint-disable-next-line no-console
console.log('Permission changes acknowledged during force logout');
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Auth/PermissionWatcher.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import axios from 'axios';
import { ENDPOINTS } from '~/utils/URL';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
}

.darkMode .dropdownButton {
color: #eee;
color: #ccc;
background: #2b2b2b;
border: 1px solid #555;
}
Expand All @@ -93,7 +93,7 @@

.darkMode .dropdownMenu {
background: #2c2c2c;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
box-shadow: 0 2px 8px #000;
}

/* React-select overrides */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
/* src/components/CommunityPortal/Activities/activityId/Resources.module.css */
.resourcesUsage {
background: white;
padding: 20px;
border-radius: 8px;
font-family: Arial, sans-serif;
width: 100%;
}

/* border for all the row data */
.resourceRow {
Expand Down
43 changes: 40 additions & 3 deletions src/components/CommunityPortal/Activities/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@
color: red;
}

/* Resource Monitoring Title */
.resourceMonitoring .resourceTitle {
font-weight: bold;
color: grey;
text-align: left;
font-size: 1.2rem;
margin-bottom: 5px;
}

.registrationForm,
.filters {
margin: 20px 0;
Expand Down Expand Up @@ -240,17 +249,24 @@
font-size: 1.5em;
}

.status.active {
.myEvent .status {
padding: 5px;
border-radius: 5px;
color: white;
font-weight: bold;
}

.myEvent .status.active {
background-color: rgb(200, 240, 200);
color: green;
}

.status.closed {
.myEvent .status.closed {
background-color: rgb(191, 191, 238);
color: purple;
}

.status.cancelled {
.myEvent .status.cancelled {
background-color: rgb(239, 170, 170);
color: red;
}
Expand Down Expand Up @@ -321,12 +337,22 @@

/* Resource Monitoring */



.resourceValue {
font-weight: bold;
color: black;
font-size: 1rem;
}

.resourceMonitoring .resourceStats {
display: flex;
align-items: center;
margin-top: 10px;
}



/* My Events toggle button */
.viewToggle button {
padding: 10px 20px;
Expand Down Expand Up @@ -370,6 +396,17 @@
background-color: #0056b3;
}

.myEvent .createNewBtn {
padding: 8px 20px;
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}



.registerinfo {
display: flex;
flex-direction: column;
Expand Down
74 changes: 62 additions & 12 deletions src/components/CommunityPortal/CPDashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function CPDashboard() {
const [events, setEvents] = useState([]);
const [searchInput, setSearchInput] = useState('');
const [searchQuery, setSearchQuery] = useState('');
const [selectedDate, setSelectedDate] = useState('');
const [onlineOnly, setOnlineOnly] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [dateFilter, setDateFilter] = useState('');
Expand Down Expand Up @@ -99,6 +100,25 @@ export function CPDashboard() {
});
};

// Helper function to extract date in YYYY-MM-DD format from event date
const parseEventDate = dateString => {
if (!dateString) return null;

try {
// Try to parse as ISO date string or standard date
const parsedDate = new Date(dateString);
if (!isNaN(parsedDate.getTime())) {
const year = parsedDate.getFullYear();
const month = String(parsedDate.getMonth() + 1).padStart(2, '0');
const day = String(parsedDate.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
} catch (error) {
console.error('Error parsing date:', error);
}
return null;
};

function isTomorrow(dateString) {
const input = new Date(dateString);

Expand Down Expand Up @@ -133,11 +153,17 @@ export function CPDashboard() {
if (!isOnlineEvent) return false;
}

// Filter by date filter
// Filter by date filter (Tomorrow / Weekend)
if (dateFilter === 'tomorrow') {
return isTomorrow(event.date);
if (!isTomorrow(event.date)) return false;
} else if (dateFilter === 'weekend') {
return isComingWeekend(event.date);
if (!isComingWeekend(event.date)) return false;
}

// Filter by specific date (if selected)
const eventDate = event.date ? parseEventDate(event.date) : null;
if (selectedDate && eventDate !== selectedDate) {
return false;
}

// Filter by search query if provided
Expand All @@ -151,6 +177,11 @@ export function CPDashboard() {
);
});

// Reset pagination to page 1 when filters change
useEffect(() => {
setPagination(prev => ({ ...prev, currentPage: 1 }));
}, [searchQuery, selectedDate, onlineOnly, dateFilter]);

const totalPages = Math.ceil(filteredEvents.length / pagination.limit) || 1;

const displayedEvents = filteredEvents.slice(
Expand Down Expand Up @@ -180,11 +211,11 @@ export function CPDashboard() {
}

return (
<Container className={styles.cp_dashboard_container}>
<header className={styles.cp_dashboard_header}>
<Container className={styles.dashboardContainer}>
<header className={`${styles.dashboardHeader} ${darkMode ? styles.darkHeader : ''}`}>
<h1>All Events</h1>
<div>
<div className={styles.cp_dashboard_search_container}>
<div className={styles.dashboardSearchContainer}>
<Input
id="search"
type="search"
Expand Down Expand Up @@ -265,11 +296,24 @@ export function CPDashboard() {
</FormGroup>
</div>
<div className={styles.dashboardActions}>
<Button color="primary" onClick={() => setDateFilter('')}>
<Button
color="primary"
onClick={() => {
setDateFilter('');
setSelectedDate('');
}}
>
Clear date filter
</Button>
</div>
<Input type="date" placeholder="Ending After" className={styles['date-filter']} />
<Input
type="date"
placeholder="Select Date"
className={styles.dateFilter}
value={selectedDate}
onChange={e => setSelectedDate(e.target.value)}
style={{ marginTop: '10px' }}
/>
</div>

<div className={styles.filterItem}>
Expand Down Expand Up @@ -316,7 +360,11 @@ export function CPDashboard() {
<h2 className={styles.sectionTitle}>Events</h2>

<Row>
{displayedEvents.length > 0 ? (
{isLoading ? (
<div className={styles.noEvents}>Loading events...</div>
) : error ? (
<div className={styles.noEvents}>{error}</div>
) : displayedEvents.length > 0 ? (
displayedEvents.map(event => (
<Col md={4} key={event.id} className={styles.eventCardCol}>
<Card className={styles.eventCard}>
Expand All @@ -330,13 +378,15 @@ export function CPDashboard() {
<CardBody>
<h5 className={styles.eventTitle}>{event.title}</h5>
<p className={styles.eventDate}>
<FaCalendarAlt /> {formatDate(event.date)}
<FaCalendarAlt className={styles.eventIcon} /> {formatDate(event.date)}
</p>
<p className={styles.eventLocation}>
<FaMapMarkerAlt /> {event.location}
<FaMapMarkerAlt className={styles.eventIcon} />{' '}
{event.location || 'Location TBD'}
</p>
<p className={styles.eventOrganizer}>
<FaUserAlt /> {event.organizer}
<FaUserAlt className={styles.eventIcon} />{' '}
{event.organizer || 'Organizer TBD'}
</p>
</CardBody>
</Card>
Expand Down
Loading
Loading