Skip to content

Commit

Permalink
Statistics Modal Frontend (#87)
Browse files Browse the repository at this point in the history
* base starter for statistic modal and table

* fit modal to content size and remove comments

* Revert "fit modal to content size and remove comments"

This reverts commit 6e421f2.

* fixed rev change

* base css for StatTable

* Season defaults to current one from published-schedule when opening stats modal

* pass in allseasons prop ps->pstable->statModal->statTable to dynamically render all available seasons and years in the select dropdowns

* style fixes

* changed double dropdown to single dropdown, visibility issue

* fixed select display bug

---------

Co-authored-by: subinqkim <[email protected]>
Co-authored-by: ThatMegamind <[email protected]>
Co-authored-by: michellelin1 <[email protected]>
  • Loading branch information
4 people authored Apr 27, 2024
1 parent 9e801b7 commit 1cc3095
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 4 deletions.
29 changes: 27 additions & 2 deletions src/components/Events/PublishedScheduleTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';
import { Table, Thead, Tbody, Tr, Th, Td, TableContainer, Box, IconButton, useDisclosure } from '@chakra-ui/react';
import AddDayModal from '../../pages/PublishedSchedule/AddDayModal.jsx'
import StatModal from '../../pages/PublishedSchedule/StatisticsModal.jsx';
import { AddIcon } from '@chakra-ui/icons';
import { IoStatsChart } from "react-icons/io5";
import { useAuthContext } from '../../common/AuthContext.jsx';
import AUTH_ROLES from '../../utils/auth_config.js';
const { ADMIN_ROLE } = AUTH_ROLES.AUTH_ROLES;


const PublishedScheduleTable = ({ season }) => {
const PublishedScheduleTable = ({ season, allSeasons }) => {
const {currentUser} = useAuthContext();

const [eventsInDay, setEventsInDay] = useState([]);
const seasonType = season.split(' ')[0];
const seasonYear = season.split(' ')[1];
const [dataShouldRevalidate, setShouldDataRevalidate] = useState(false);
const { isOpen: isOpenDay, onOpen: onOpenDay, onClose: onCloseDay } = useDisclosure();
const { isOpen: isOpenStats, onOpen: onOpenStats, onClose: onCloseStats } = useDisclosure();

const renderTable = async () => {
const { data } = await NPOBackend.get(
Expand Down Expand Up @@ -58,6 +60,24 @@ const PublishedScheduleTable = ({ season }) => {
return (
<Box>
{currentUser.type === ADMIN_ROLE &&
<>
<IconButton
bgColor="grey.700"
color="blue.700"
borderRadius="10rem"
position="fixed"
bottom="6rem"
right={{ base: '1rem', lg: '2rem', xl: '3rem' }}
fontSize="1.25rem"
w="3rem"
h="3rem"
_hover={{ bgColor: 'blue.500' }}
onClick={onOpenStats}
icon={<IoStatsChart />}
>
Stats
</IconButton>

<IconButton
bgColor="blue.700"
color="gray.50"
Expand All @@ -74,9 +94,13 @@ const PublishedScheduleTable = ({ season }) => {
>
Create
</IconButton>
</>
}

<AddDayModal isOpenDay={isOpenDay} onCloseDay={onCloseDay} setShouldDataRevalidate={setShouldDataRevalidate}/>
{ season && allSeasons &&
<StatModal isOpen={isOpenStats} onClose={onCloseStats} season={season} allSeasons={allSeasons}/>
}

<TableContainer borderWidth={1} borderRadius="10px">
<Table variant="simple">
Expand Down Expand Up @@ -115,6 +139,7 @@ const PublishedScheduleTable = ({ season }) => {

PublishedScheduleTable.propTypes = {
season: PropTypes.string.isRequired,
allSeasons: PropTypes.array.isRequired,
};

export default PublishedScheduleTable;
57 changes: 57 additions & 0 deletions src/components/StatTable/StatTable.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.container {
display: flex;
flex-direction: column;
align-items: center;
}

.select-container {
margin-top: 20px;
margin-bottom: 20px;
display: flex;
justify-content: center;
}

.table-container {
margin-top: 20px;
margin-bottom: 20px;
border: 1px solid #e1e4e8;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.table-container th {
background-color: #0e509c;
color: white;
padding: 15px;
text-align: center;
}

.table-container tbody td {
border-bottom: 1px solid #e1e4e8;
padding: 15px;
text-align: center;
}

.table-container tbody tr:last-child td:not(:first-child) {
background-color: #f0f8ff;
color: blue;
}

.table-container tbody tr:not(:last-child) td:last-child {
background-color: #f0f8ff;
color: blue;
}

.table-container tbody tr:last-child td:last-child {
border: none;
}

.table-body tr:nth-child(even) {
background-color: #f8f9fa;
}

.table-body tr:hover {
background-color: #e2f3ff;
transition: background-color 0.3s ease;
}
100 changes: 100 additions & 0 deletions src/components/StatTable/StatTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { useState, useEffect } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { NPOBackend } from '../../utils/auth_utils';
import { Box, Select } from '@chakra-ui/react';
import './StatTable.css';

const StatTable = ({ season, allSeasons }) => {
const [stats, setStats] = useState([]);
const [selectedSeason, setSelectedSeason] = useState(season);

useEffect(() => {
const fetchStats = async () => {
try {
const curSeason = selectedSeason.split(' ')[0];
const curYear = selectedSeason.split(' ')[1];
const response = await NPOBackend.get(`/published-schedule/stats?season=${curSeason.toLowerCase()}&year=${curYear}`);
const data = response.data;
setStats(data);
} catch (error) {
console.error('Error fetching statistics:', error);
}
};

fetchStats();
}, [selectedSeason]);

const transformData = () => {
const transformedData = {};

stats.forEach(stat => {
const eventType = stat.eventType;
const subject = stat.subject;
const totalCount = parseInt(stat.totalCount);

if (!transformedData[eventType]) {
transformedData[eventType] = {};
}

transformedData[eventType][subject] = totalCount;
});

return transformedData;
};

const transformedStats = transformData();

return (
<Box>
<Box mt="1rem">
<Select
textColor="black"
value={selectedSeason}
onChange={(e) => setSelectedSeason(e.target.value)}
width="max-content"
>
{allSeasons.map(item => (
<option key={item} value={item}>
{item}
</option>
))
}
</Select>
</Box>
<div className='table-container'>
<table>
<thead>
<tr>
<th>Event Type</th>
{Object.keys(transformedStats).length > 0 &&
Object.keys(transformedStats[Object.keys(transformedStats)[0]]).map(subject => (
<th key={subject} style={{ textTransform: 'capitalize' }}>{subject}</th>
))}
</tr>
</thead>
<tbody className='table-body'>
{Object.keys(transformedStats).map((eventType) => (
<React.Fragment key={eventType}>
<tr className='table-data'>
<td style={{ textTransform: 'capitalize' }}>{eventType}</td>
{Object.keys(transformedStats[eventType]).map(subject => (
<td key={`${eventType}-${subject}`} >{transformedStats[eventType][subject]}</td>
))}
</tr>
</React.Fragment>
))}
</tbody>
</table>
</div>
</Box>
);
};

StatTable.propTypes = {
season: PropTypes.string,
year: PropTypes.string,
allSeasons: PropTypes.array,
};

export default StatTable;
4 changes: 2 additions & 2 deletions src/pages/PublishedSchedule/PublishedSchedule.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ const PublishedSchedule = () => {

{/* tables for each season */}
{selectedSeason != '' ? (
<PublishedScheduleTable season={selectedSeason} />
<PublishedScheduleTable season={selectedSeason} allSeasons={allSeasons} />
) : (
<PublishedScheduleTable season={curSeason} />
<PublishedScheduleTable season={curSeason} allSeasons={allSeasons} />
)}
</Box>
);
Expand Down
34 changes: 34 additions & 0 deletions src/pages/PublishedSchedule/StatisticsModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import PropTypes from 'prop-types';
import {
Modal,
ModalOverlay,
ModalContent,
ModalBody,
ModalCloseButton,
} from '@chakra-ui/react';
import StatTable from '../../components/StatTable/StatTable';

const StatModal = ({ isOpen, onClose, season, allSeasons }) => {
return (
<>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent maxWidth={'fit-content'}>
<ModalCloseButton />
<ModalBody>
<StatTable season={season} allSeasons={allSeasons}/>
</ModalBody>
</ModalContent>
</Modal>
</>
);
};

StatModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
season: PropTypes.string.isRequired,
allSeasons: PropTypes.array.isRequired,
};

export default StatModal;

0 comments on commit 1cc3095

Please sign in to comment.