Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Jchen20-1 committed Apr 30, 2024
2 parents e862566 + a114dec commit 890aeeb
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 16 deletions.
47 changes: 47 additions & 0 deletions app/imports/ui/components/AdminHome.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import { Container, Row, Col, Card, Button } from 'react-bootstrap';
import '../css/AdminHome.css';
import { COMPONENT_IDS } from '../utilities/ComponentIDs';
import AdminHoursStats from './AdminHoursStats';
import AdminSiteStats from './AdminSiteStats';
import AdminRecentEvents from './AdminRecentEvents';

/** Main component in home page upon logging in as admin. */
const AdminHome = () => (
<Container className="py-5" id={COMPONENT_IDS.ADMIN_HOME_PAGE}>
<Card className="admin-card-background rounded-4">
<Row className="p-3">
<Col className="col-4">
<AdminSiteStats />
<Card className="rounded-4">
<Card.Header><h3 className="text-center">Site Management</h3></Card.Header>
<Card.Body className="mx-3">
<Row className="text-center">
<Button variant="outline-dark" href="/event-moderation" className="rounded-0 management-btn" id={COMPONENT_IDS.ADMIN_HOME_EVENT_MODERATION}>
Events
</Button>
<Button variant="outline-dark" href="/organization-moderation" className="rounded-0 management-btn" id={COMPONENT_IDS.ADMIN_HOME_ORGANIZATION_MODERATION}>
Organizations
</Button>
<Button variant="outline-dark" href="/user-moderation" className="rounded-0 management-btn" id={COMPONENT_IDS.ADMIN_HOME_USER_MODERATION}>
Users
</Button>
<Button variant="outline-dark" className="rounded-0 management-btn" id={COMPONENT_IDS.ADMIN_HOME_REVIEW_MODERATION}>
Reviews
</Button>
</Row>
</Card.Body>
</Card>
</Col>
<Col className="col-8 align-content-center">
<AdminHoursStats />
</Col>
</Row>
<Row>
<AdminRecentEvents />
</Row>
</Card>
</Container>
);

export default AdminHome;
37 changes: 37 additions & 0 deletions app/imports/ui/components/AdminRecentEvents.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { useTracker } from 'meteor/react-meteor-data';
import { Container, Row, Col } from 'react-bootstrap';
import { Events } from '../../api/event/EventCollection';
import LoadingSpinner from './LoadingSpinner';
import EventCard from './EventCard';

const AdminRecentEvents = () => {

const { ready, recentEvents } = useTracker(() => {
const subscription = Events.subscribeEvent();
const recent = Events.find({}).fetch().reverse().slice(0, 6);
return {
ready: subscription.ready(),
recentEvents: recent,
};
});

return ready ? (
<Container className="py-3">
<Row className="text-center">
<h2>Recent Events</h2>
</Row>
<Row className="px-3">
{recentEvents.map((item) => (
<Col key={item._id} md={4} className="py-2">
<EventCard event={item} />
</Col>
))}
</Row>
</Container>
) : (
<LoadingSpinner />
);
};

export default AdminRecentEvents;
1 change: 0 additions & 1 deletion app/imports/ui/components/UpcomingEventCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const UpcomingEventCard = () => {
userProfile: userProfileData,
};
});

return (
ready ? (
<Card className="w-100 my-1">
Expand Down
27 changes: 13 additions & 14 deletions app/imports/ui/components/UserCalendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import moment from 'moment';
import { Card } from 'react-bootstrap';
import { useTracker } from 'meteor/react-meteor-data';
import { Meteor } from 'meteor/meteor';
import '../css/Calendar.css';
import { UserProfiles } from '../../api/user/UserProfileCollection';
import { Events, eventPublications } from '../../api/event/EventCollection';
import LoadingSpinner from './LoadingSpinner';
Expand Down Expand Up @@ -73,20 +74,18 @@ const UserCalendar = () => {
};

return (
<Card style={{ width: 'calc(100% - 20px)', height: 'calc(100% - 20px)', padding: '10px' }}>
<div style={{ width: '100%', height: '100%', backgroundColor: 'white', color: 'black' }}>
<Calendar
localizer={localize}
events={getCommittedEvents()}
startAccessor="startTime"
endAccessor="endTime"
selectable
onSelectEvent={handleEventSelect}
components={{ toolbar: Toolbar }}
eventPropGetter={() => ({ style: { backgroundColor: '#03A696' } })}
style={{ color: 'black', width: 'calc(100% - 20px)', height: 'calc(100% - 20px)', margin: '10px' }}
/>
</div>
<Card className="calendar-card rounded-4">
<Calendar
localizer={localize}
events={getCommittedEvents()}
startAccessor="startTime"
endAccessor="endTime"
selectable
onSelectEvent={handleEventSelect}
components={{ toolbar: Toolbar }}
eventPropGetter={() => ({ style: { backgroundColor: '#03A696' } })}
className="rounded-4 p-3"
/>
</Card>
);
};
Expand Down
2 changes: 1 addition & 1 deletion app/imports/ui/components/UserDashboard.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Container, Row, Col, Card, Image, Button } from 'react-bootstrap';
import { Row, Col, Card, Image, Button, Container } from 'react-bootstrap';
import { Meteor } from 'meteor/meteor';
import { useTracker } from 'meteor/react-meteor-data';
import { UserProfiles } from '../../api/user/UserProfileCollection';
Expand Down
25 changes: 25 additions & 0 deletions app/imports/ui/components/UserHome.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import { Container, Row, Col, Card } from 'react-bootstrap';
import { PAGE_IDS } from '../utilities/PageIDs';
import '../css/UserHome.css';
import UserDashboard from './UserDashboard';
import UpcomingEventCard from './UpcomingEventCard';
import UserCalendar from './UserCalendar';

const UserHome = () => (
<Container id={PAGE_IDS.HOME_PAGE} className="py-5">
<Card className="user-card-background p-3 rounded-4">
<Row className="align-content-center">
<Col xs={12} md={5}>
<UserDashboard />
<UpcomingEventCard />
</Col>
<Col xs={12} md={7}>
<UserCalendar />
</Col>
</Row>
</Card>
</Container>
);

export default UserHome;
15 changes: 15 additions & 0 deletions app/imports/ui/css/Calendar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* Define styles for larger screens */
@media only screen and (min-width: 768px) {
.calendar-card {
width: 100% !important;
height: 100% !important;
}
}

/* Define styles for smaller screens */
@media only screen and (max-width: 390px) {
.calendar-card {
width: 79vw !important; /* 90% of viewport width */
height: 79vw !important; /* 90% of viewport width */
}
}
3 changes: 3 additions & 0 deletions app/imports/ui/css/UserHome.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.user-card-background {
background-color: var(--color2) !important;
}
150 changes: 150 additions & 0 deletions app/imports/ui/pages/AdminOrganizationModeration.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import React, { useState } from 'react';
import { Container, Row, Col, Card, Form, Button, ButtonGroup, Modal, Image } from 'react-bootstrap';
import Table from 'react-bootstrap/Table';
import swal from 'sweetalert';
import { Meteor } from 'meteor/meteor';
import Fuse from 'fuse.js';
import { useTracker } from 'meteor/react-meteor-data';
import { PAGE_IDS } from '../utilities/PageIDs';
import { COMPONENT_IDS } from '../utilities/ComponentIDs';
import LoadingSpinner from '../components/LoadingSpinner';
import { removeOrganization } from '../../startup/both/Methods';
import { Organization } from '../../api/organization/OrganizationCollection';
import '../css/AdminModeration.css';

/** This admin-only page moderates organizations. Able to view, edit, and delete organizations. */
const AdminOrganizationModeration = () => {
const { ready, organization } = useTracker(() => {
const subscription = Organization.subscribeOrganization(); // Subscribe to organization publication for the current user
const profile = Organization.find().fetch(); // Find the organization for the current user
return {
ready: subscription ? subscription.ready() : false,
organization: profile,
};
});

// Delete function variable definitions
const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);
const [orgIdToDelete, setOrgIdToDelete] = useState(null);
const toggleDeleteConfirmation = (orgId) => {
setShowDeleteConfirmation(!showDeleteConfirmation);
setOrgIdToDelete(orgId);
};

// Search variable definitions
let displayedOrganizations = organization;
const [searchQuery, setSearchQuery] = useState('');
const [searchPerformed, setSearchPerformed] = useState(false);
const handleSearchChange = (event) => {
setSearchQuery(event.target.value);
setSearchPerformed(true);
};

if (searchPerformed && searchQuery !== '') {
const fuseOptions = {
isCaseSensitive: false,
shouldSort: true,
includeMatches: true,
findAllMatches: true,
useExtendedSearch: false,
threshold: 0.2,
keys: ['name', 'type', 'email', 'phone'],
};

const fuse = new Fuse(organization, fuseOptions);
const result = fuse.search(searchQuery);
displayedOrganizations = result.map((item) => item.item);
}

const confirmDelete = () => {
Meteor.call(removeOrganization, orgIdToDelete, (error) => {
if (error) {
swal('Error', error.message, 'error');
} else {
swal('Success', 'Organization deleted successfully', 'success');
setShowDeleteConfirmation(false);
}
});
};

return ready ? (
<Container fluid className="color1 py-5" id={PAGE_IDS.ADMIN_ORGANIZATION_MODERATION}>
<Container className="">
<Row className="text-center pb-3">
<h1>Organization Moderation</h1>
</Row>
<Card className="rounded-4 p-3 org-moderation-background">
<Row className="justify-content-center">
<Col className="col-7">
<Form.Group className="search-bar">
<Form.Control
id={COMPONENT_IDS.ADMIN_ORGANIZATION_MODERATION_SEARCH_BAR}
type="text"
placeholder="Search for organizations..."
className="align-content-center"
value={searchQuery}
onChange={handleSearchChange}
/>
</Form.Group>
</Col>
</Row>
<Row>
<Col>
<Card.Body>
<Table striped bordered hover>
<thead>
<tr>
<th>PFP</th>
<th>Organization</th>
<th>Category</th>
<th>Email</th>
<th>Phone</th>
<th>Rating</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{displayedOrganizations.map((org) => (
<tr key={org._id}>
<td><Image src={org.image} className="org-mod-image" alt="Organization-submitted image" /></td>
<td>{org.name}</td>
<td>{org.type}</td>
<td>{org.contactEmail}</td>
<td>{org.phone}</td>
<td>{org.averageRating}</td>
<td className="text-center">
<ButtonGroup>
<Button variant="success" href={`/org-profile/${org._id}`}>View</Button>
<Button variant="warning" href={`/admin-edit-organization/${org._id}`}>Edit</Button>
<Button variant="danger" onClick={() => toggleDeleteConfirmation(org._id)}>Delete</Button>
</ButtonGroup>
</td>
</tr>
))}
</tbody>
</Table>
</Card.Body>
</Col>
</Row>
</Card>
<Modal show={showDeleteConfirmation} onHide={() => setShowDeleteConfirmation(false)}>
<Modal.Header closeButton>
<Modal.Title>Confirm Delete</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Are you sure you want to delete this Organization?</p>
<p>The user will be notified of this deletion.</p>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={() => setShowDeleteConfirmation(false)}>Cancel</Button>
<Button variant="danger" onClick={confirmDelete}>Confirm Delete</Button>
</Modal.Footer>
</Modal>
</Container>
</Container>
) : (
<LoadingSpinner />
);
};

export default AdminOrganizationModeration;
12 changes: 12 additions & 0 deletions app/imports/ui/utilities/ComponentIDs.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,16 @@ export const COMPONENT_IDS = {
EDIT_ORGANIZATION_PROFILE_ZIP_CODE: 'edit-organization-profile-zip-code',
EDIT_ORGANIZATION_PROFILE_COUNTRY: 'edit-organization-profile-country',
EDIT_ORGANIZATION_PROFILE_SUBMIT: 'edit-organization-profile-submit',
EDIT_ORGANIZATION_PROFILE_RETURN_TO_DASHBOARD: 'edit-organization-profile-return-to-dashboard',

ADMIN_HOME_PAGE: 'admin-home-page',
ADMIN_HOME_EVENT_MODERATION: 'admin-home-event-moderation',
ADMIN_HOME_ORGANIZATION_MODERATION: 'admin-home-organization-moderation',
ADMIN_HOME_USER_MODERATION: 'admin-home-user-moderation',
ADMIN_HOME_REVIEW_MODERATION: 'admin-home-review-moderation',
ADMIN_ORGANIZATION_MODERATION_SEARCH_BAR: 'admin-organization-moderation-search-bar',

TOS_MODAL_OPEN: 'tos-modal-open',
TOS_MODAL_ACCEPT: 'tos-modal-accept',
TOS_MODAL_DECLINE: 'tos-modal-decline',
};

0 comments on commit 890aeeb

Please sign in to comment.