Skip to content
Open
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
239 changes: 131 additions & 108 deletions src/components/CommunityPortal/CPDashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,100 @@
import { Container, Row, Col, Card, CardBody, Button, Input } from 'reactstrap';
import styles from './CPDashboard.module.css';
import { FaCalendarAlt, FaMapMarkerAlt, FaUserAlt } from 'react-icons/fa';
import { ENDPOINTS } from '../../utils/URL';

Check warning on line 5 in src/components/CommunityPortal/CPDashboard.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import of 'ENDPOINTS'.

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZr6EQJr0BxmTJuUSI-w&open=AZr6EQJr0BxmTJuUSI-w&pullRequest=4305
import axios from 'axios';

Check warning on line 6 in src/components/CommunityPortal/CPDashboard.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import of 'axios'.

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZr6EQJr0BxmTJuUSI-x&open=AZr6EQJr0BxmTJuUSI-x&pullRequest=4305

export function CPDashboard() {
const [events, setEvents] = useState([]);
const [search, setSearch] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [pagination, setPagination] = useState({
currentPage: 1,
totalPages: 5,
total: 0,
limit: 6,
});

const FALLBACK_IMG =
'https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?auto=format&fit=crop&w=600&q=60';

const FixedRatioImage = ({ src, alt, fallback }) => (
<div
style={{
width: '100%',
aspectRatio: '4 / 3',
overflow: 'hidden',
background: '#f2f2f2',
}}
>
<img
src={src || fallback}
alt={alt}
loading="lazy"
onError={e => {
if (e.currentTarget.src !== fallback) e.currentTarget.src = fallback;
}}
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
display: 'block',
}}
/>
</div>
);
const [selectedDateFilter, setSelectedDateFilter] = useState('');
const [customDate, setCustomDate] = useState('');
const [filteredEvents, setFilteredEvents] = useState([]);

useEffect(() => {
const fetchEvents = async () => {
setIsLoading(true);

try {
const response = await axios.get(ENDPOINTS.EVENTS);
console.log('Fetched events:', response.data.events);
setEvents(response.data.events);
} catch (err) {
console.error('Here', err);
setError('Failed to load events');
} finally {
setIsLoading(false);
}
};

fetchEvents();
const mockEvents = [
{
id: 1,
title: 'PGSA Lunch Talks',
date: '2025-11-08T12:00:00',
location: 'Disque 919',
organizer: 'Physics Graduate Student Association',
image: 'https://via.placeholder.com/300',
},
{
id: 2,
title: 'Hot Chocolate/Bake Sale',
date: '2025-11-15T12:00:00',
location: 'G.C LeBow - Lobby Tabling Space 2',
organizer: 'Kappa Phi Gamma, Sorority Inc.',
image: 'https://via.placeholder.com/300',
},
{
id: 3,
title: 'Holiday Lunch',
date: '2025-11-22T12:00:00',
location: 'Hill Conference Room',
organizer: 'Chemical and Biological Engineering Graduate Society',
image: 'https://via.placeholder.com/300',
},
];
setEvents(mockEvents);
setFilteredEvents(mockEvents);
}, []);

const formatDate = dateStr => {
if (!dateStr) return 'Date TBD';
const date = new Date(dateStr);
useEffect(() => {
let filtered = [...events];
const today = new Date();

if (selectedDateFilter === 'tomorrow') {
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
filtered = events.filter(event => isSameDay(new Date(event.date), tomorrow));
} else if (selectedDateFilter === 'weekend') {
const today = new Date();
const dayOfWeek = today.getDay();

const daysUntilSaturday = (6 - dayOfWeek + 7) % 7;
const saturday = new Date(today);
saturday.setDate(today.getDate() + daysUntilSaturday);

const sunday = new Date(saturday);
sunday.setDate(saturday.getDate() + 1);

filtered = events.filter(event => {
const eventDate = parseToLocalDate(event.date);
return eventDate >= parseToLocalDate(saturday) && eventDate <= parseToLocalDate(sunday);
});
} else if (customDate) {
filtered = events.filter(event => isSameDay(event.date, customDate));
}

setFilteredEvents(filtered);
}, [selectedDateFilter, customDate, events]);

function parseToLocalDate(dateInput) {

Check warning on line 76 in src/components/CommunityPortal/CPDashboard.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Move function 'parseToLocalDate' to the outer scope.

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZr6EQJr0BxmTJuUSI-y&open=AZr6EQJr0BxmTJuUSI-y&pullRequest=4305
if (!dateInput) return null;

if (dateInput instanceof Date)
return new Date(dateInput.getFullYear(), dateInput.getMonth(), dateInput.getDate());

if (/^\d{4}-\d{2}-\d{2}$/.test(dateInput)) {
const [year, month, day] = dateInput.split('-').map(Number);
return new Date(year, month - 1, day);
}

const d = new Date(dateInput);
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
}

function isSameDay(date1, date2) {
const d1 = parseToLocalDate(date1);
const d2 = parseToLocalDate(date2);
return d1 && d2 && d1.getTime() === d2.getTime();
}

const formatDateForUI = dateString => {
const date = new Date(dateString);
return date.toLocaleString('en-US', {
weekday: 'long',
month: 'long',
Expand All @@ -77,17 +105,6 @@
});
};

const filteredEvents = events.filter(event =>
event.title?.toLowerCase().includes(search.toLowerCase()),
);

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

const displayedEvents = filteredEvents.slice(
(pagination.currentPage - 1) * pagination.limit,
pagination.currentPage * pagination.limit,
);

return (
<Container className={styles['dashboard-container']}>
<header className={styles['dashboard-header']}>
Expand All @@ -109,42 +126,52 @@
<Col md={3} className={styles['dashboard-sidebar']}>
<div className={styles['filter-section']}>
<h4>Search Filters</h4>
<div className={styles['filter-section-divider']}>
<div className={styles['filter-item']}>
<label htmlFor="date-tomorrow"> Dates</label>
<div className={styles['filter-options-horizontal']}>
<div>
<Input type="radio" name="dates" /> Tomorrow
</div>
<div>
<Input type="radio" name="dates" /> This Weekend
</div>
<div className="filter-item">
<label htmlFor="date-tomorrow"> Dates</label>
<div className="filter-options-horizontal">
<div>
<Input
type="radio"
name="dates"
checked={selectedDateFilter === 'tomorrow'}
onClick={() => {
setSelectedDateFilter(prev => (prev === 'tomorrow' ? '' : 'tomorrow'));
setCustomDate('');
}}
/>{' '}
Tomorrow
</div>
<Input type="date" placeholder="Ending After" className={styles['date-filter']} />
</div>
<div className={styles['filter-item']}>
<label htmlFor="online-only">Online</label>
<div>
<Input type="checkbox" /> Online Only
<Input
type="radio"
name="dates"
checked={selectedDateFilter === 'weekend'}
onClick={() => {
setSelectedDateFilter(prev => (prev === 'weekend' ? '' : 'weekend'));
setCustomDate('');
}}
/>{' '}
This Weekend
</div>
</div>
<div className={styles['filter-item']}>
<label htmlFor="branches">Branches</label>
<Input type="select">
<option>Select branches</option>
</Input>
</div>
<div className={styles['filter-item']}>
<label htmlFor="themes">Themes</label>
<Input type="select">
<option>Select themes</option>
</Input>
</div>
<div className={styles['filter-item']}>
<label htmlFor="categories">Categories</label>
<Input type="select">
<option>Select categories</option>
</Input>
<Input
type="date"
value={customDate}
onChange={e => {
setSelectedDateFilter('');
setCustomDate(e.target.value);
}}
className="date-filter"
/>
</div>
<div className="filter-item">
<label htmlFor="online-only">Online</label>
<div>
<Input type="checkbox" /> Online Only
</div>
</div>
</div>
Expand All @@ -153,21 +180,17 @@
<Col md={9} className={styles['dashboard-main']}>
<h2 className={styles['section-title']}>Events</h2>
<Row>
{events.length > 0 ? (
events.map(event => (
<Col md={4} key={event.id} className={styles['event-card-col']}>
<Card className={styles['event-card']}>
<div className={styles['event-card-img-container']}>
<img
src={event.image}
alt={event.title}
className={styles['event-card-img']}
/>
{filteredEvents.length > 0 ? (
filteredEvents.map(event => (
<Col md={4} key={event.id} className="event-card-col">
<Card className="event-card">
<div className="event-card-img-container">
<img src={event.image} alt={event.title} className="event-card-img" />
</div>
<CardBody>
<h5 className={styles['event-title']}>{event.title}</h5>
<p className={styles['event-date']}>
<FaCalendarAlt className={styles['event-icon']} /> {event.date}
<h5 className="event-title">{event.title}</h5>
<p className="event-date">
<FaCalendarAlt className="event-icon" /> {formatDateForUI(event.date)}
</p>
<p className={styles['event-location']}>
<FaMapMarkerAlt className={styles['event-icon']} /> {event.location}
Expand Down
Loading