Skip to content

Commit

Permalink
Fix Statistics Chart (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
zacktraczyk authored Jan 14, 2024
1 parent 8187249 commit 263157d
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 12 deletions.
92 changes: 88 additions & 4 deletions src/components/Charts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,24 @@ const rechartsArrayToPieChartData = (
})
}

/**
* Add numerical date field to recharts array for correct x-axis plotting
* @param rechartsArray array of recharts objects for plotting
* @returns array with date added for correct x-axis plotting
*/
export const rechartsArrayAddDate = (rechartsArray: ReChartsArray) => {
return rechartsArray.map(rechartsObject => {
return {
name: rechartsObject.name,
value: rechartsObject.value,
date: new Date(rechartsObject.name).getTime(),
date_to_string: new Date(
new Date(rechartsObject.name).getTime()
).toLocaleString(),
}
})
}

/**
* Format date ticks
* @param tick tick to format
Expand All @@ -92,6 +110,38 @@ const dateTickFormatter = (tick: string) => {
return `${date.getMonth() + 1}/${date.getDate()}`
}

/**
* Get date ticks
* @param startDate start date
* @param endDate end date
* @param intervalDays days between ticks
* @returns array of date ticks evenly spaced
*/
const getDateTicks = (
startDate: Date,
endDate: Date,
intervalDays: number
): number[] => {
const DAY_LENGTH = 86400000
const nextSundayAfterStartDate = new Date(startDate.getTime())
nextSundayAfterStartDate.setDate(
startDate.getDate() + ((7 - startDate.getDay()) % 7)
)

const endDateTime = new Date(endDate.getTime()).getTime()
const intervalLength = DAY_LENGTH * intervalDays

const dateTicks = []
let currDateTime = nextSundayAfterStartDate.getTime()

while (currDateTime < endDateTime) {
dateTicks.push(currDateTime)
currDateTime += intervalLength
}

return dateTicks
}

// Components

const BarCustomTooltip = ({ active, payload, label }: any) => {
Expand Down Expand Up @@ -245,12 +295,13 @@ const LineCustomTooltip = ({ active, payload, label }: any) => {
<p className='font-subtext text-white'>
{payload[0].value}
{label ? " " + label : ""}
{" on " + payload[0].payload.name}
</p>
</div>
)
}

export const LineChart = ({
export const DateLineChart = ({
data,
title,
label,
Expand All @@ -261,24 +312,49 @@ export const LineChart = ({
label?: string
data: ReChartsArray
}) => {
if (!data) {
return (
<div className='flex h-[30rem] w-full min-w-0 items-center justify-center bg-error/10'>
<p className='text-center text-error'>No Data provided for {title}</p>
</div>
)
}

const lineChartData = rechartsArrayAddDate(data)

const domain: [(dataMin: number) => number, (dataMin: number) => number] = [
dataMin => dataMin,
dataMax => dataMax,
]

const ticks = getDateTicks(
new Date(lineChartData[0].name),
new Date(lineChartData[data.length - 1].name),
7
)

return (
<div className='text-md hidden h-[30rem] w-full min-w-full flex-col items-center gap-5 md:flex'>
<div className='text-md hidden h-[30rem] w-full min-w-0 flex-col items-center gap-5 self-stretch md:flex'>
{title && <h3 className='font-title capitalize'>{title}</h3>}
<ResponsiveContainer width='100%' height='100%'>
<RechartsLineChart
width={700}
height={400}
data={data}
data={lineChartData}
className='font-subtext text-xs '
>
<Tooltip
content={props => <LineCustomTooltip {...props} label={label} />}
/>
<CartesianGrid strokeDasharray='3 3' stroke='#D3DAF4' opacity={0.2} />
<XAxis
dataKey='name'
dataKey='date'
scale='time'
type='number'
stroke='#D3DAF4'
tickFormatter={dateTickFormatter}
ticks={ticks}
domain={domain}
/>
<YAxis dataKey='value' stroke='#D3DAF4' />
<Line
Expand All @@ -305,6 +381,14 @@ export const SimpleTable = ({
data: { [key: string]: number }
otherData: ReChartsArray
}) => {
if (!data) {
return (
<div className='flex h-[400px] w-full max-w-xs items-center justify-center bg-error/10'>
<p className='text-center text-error'>No Data provided for {title}</p>
</div>
)
}

return (
<div className='flex w-full max-w-xs grow flex-col items-center rounded-lg bg-blue-imperial px-10 py-5 ring-2 ring-inset ring-white/10'>
<div className='flex w-full max-w-xs flex-col gap-2'>
Expand Down
4 changes: 4 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,13 @@ export type Statistics = {
attendence_possible_wo_reimbursement: ReChartsArray

tshirt_size: { [key: string]: number }
rsvpd_tshirt_size: { [key: string]: number }
other_tshirt_size: ReChartsArray
rsvpd_other_tshirt_size: ReChartsArray
dietary_restrictions: { [key: string]: number }
rsvpd_dietary_restrictions: { [key: string]: number }
other_dietary_restrictions: ReChartsArray
rsvpd_other_dietary_restrictions: ReChartsArray
}
referral: {
cruzhacks_referral: ReChartsArray
Expand Down
59 changes: 51 additions & 8 deletions src/views/portal/admin/dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from "react"
import { ReChartsArray, Statistics } from "../../../../utils/types"
import useStatistics from "../../../../hooks/useStatistics"
import {
LineChart,
BarChart,
DateLineChart,
PieChart,
SimpleTable,
} from "../../../../components/Charts"
Expand Down Expand Up @@ -62,6 +62,7 @@ const DashboardAdmin = () => {
<DemographicsEducationBreakdown
demographics={statistics.demographics}
/>
<LogisticsRSVPBreakdown logistics={statistics.logistics} />
<LogisticsBreakdown logistics={statistics.logistics} />
<ReferalBreakdown referral={statistics.referral} />
</div>
Expand All @@ -84,7 +85,6 @@ const SubmissionsBreakdown = ({
if (!submissions) return null

let total_submissions = 0

const total_submissions_over_time = submissions.per_day.map(entry => {
return {
name: entry.name,
Expand All @@ -96,14 +96,14 @@ const SubmissionsBreakdown = ({
<div className='rounded-3xl bg-[#4659FF]/10 p-10 md:space-y-10'>
<h2 className='font-title text-xl uppercase underline'>Submissions</h2>

<div className='flex items-center justify-center'>
<div className='flex w-full max-w-5xl flex-col items-center justify-center lg:flex-row'>
<LineChart
<div className='flex w-full items-center justify-center'>
<div className='flex w-full flex-col items-center justify-center xl:flex-row'>
<DateLineChart
data={total_submissions_over_time}
title='Total Applications Over Time'
label='total apps'
label='total applications'
/>
<div className='flex flex-col items-center gap-2 p-10'>
<div className='flex shrink-0 flex-col items-center gap-2 p-10'>
<p className='w-full rounded-lg bg-blue-imperial px-10 py-5 text-center font-subtext text-xl font-bold text-gold ring-2 ring-inset ring-white/10'>
{submissions.total} Total Submissions
</p>
Expand Down Expand Up @@ -239,6 +239,47 @@ const DemographicsEducationBreakdown = ({
</div>
)
}

const LogisticsRSVPBreakdown = ({
logistics,
}: {
logistics: Statistics["logistics"]
}) => {
if (!logistics) return null

return (
<div className='space-y-10 rounded-3xl bg-[#4659FF]/10 p-10'>
<h2 className='font-title text-xl uppercase underline'>
Logistics - Attending Hackers
</h2>

<div className='flex flex-col items-start justify-center gap-10 md:flex-row'>
<SimpleTable
title='T-Shirt Sizes'
fields={["XS", "S", "M", "L", "XL", "XXL", "XXXL"]}
data={logistics.rsvpd_tshirt_size}
otherData={logistics.rsvpd_other_tshirt_size}
/>
<SimpleTable
title='Dietary Restrictions'
fields={[
"Gluten-Free",
"Vegan",
"Vegetarian",
"No Beef",
"No Pork",
"Peanut Allergies",
"Lactose Intolerant",
"None",
]}
data={logistics.rsvpd_dietary_restrictions}
otherData={logistics.rsvpd_other_dietary_restrictions}
/>
</div>
</div>
)
}

const LogisticsBreakdown = ({
logistics,
}: {
Expand All @@ -248,7 +289,9 @@ const LogisticsBreakdown = ({

return (
<div className='space-y-10 rounded-3xl bg-[#4659FF]/10 p-10'>
<h2 className='font-title text-xl uppercase underline'>Logistics</h2>
<h2 className='font-title text-xl uppercase underline'>
Logistics - all applicants
</h2>

<div className='flex flex-col items-start justify-center gap-10 md:flex-row'>
<SimpleTable
Expand Down

0 comments on commit 263157d

Please sign in to comment.