Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event stats #36

Open
wants to merge 41 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
09795f2
init layout and styling
isa-leroux448 Jul 21, 2024
5e3ddf1
add tailwind styling and refactor
isa-leroux448 Jul 21, 2024
0d2055b
add responsiveness
isa-leroux448 Jul 21, 2024
bfbe843
add navbar profile link
isa-leroux448 Jul 21, 2024
16bbc2c
replace bizbot svg with png
isa-leroux448 Jul 30, 2024
e04139c
achieved front-end view for pop up. just need to plan how the data wi…
m20arcusk Jul 30, 2024
8b3ce41
frontend visuals achieved, just need to refactor the method the data …
m20arcusk Aug 2, 2024
0960883
updated and imported some types for the questions and respones as wel…
m20arcusk Aug 8, 2024
7a29faa
small fix on a comment
m20arcusk Aug 8, 2024
a519108
didn't mean to delete BasicInformation in types.ts so I added it back
m20arcusk Aug 8, 2024
a3279ab
update mock registrant data
isa-leroux448 Aug 12, 2024
f22c4b2
create percentage bar component
isa-leroux448 Aug 12, 2024
811fdb6
create basic layout
isa-leroux448 Aug 13, 2024
a5d779f
make charts responsive on horizontal resize
isa-leroux448 Aug 13, 2024
bdf2754
removed console.log testing lines and updated tailwind with divider c…
m20arcusk Aug 14, 2024
d16fc21
updated the fetchQuestion function to use async and await
m20arcusk Aug 14, 2024
37d9f2a
fetch backend
AllanT102 Aug 15, 2024
58753d5
add responsiveness
isa-leroux448 Aug 15, 2024
3e2f2dc
responsiveness fixes
isa-leroux448 Aug 15, 2024
347bd40
code clean up
isa-leroux448 Aug 15, 2024
b6eb611
Merge branch 'dev' of https://github.com/ubc-biztech/bt-web-v2 into e…
isa-leroux448 Aug 15, 2024
2cce179
fetch backend
AllanT102 Aug 15, 2024
be3925a
Delete .env
AllanT102 Aug 15, 2024
1aef301
ignore
AllanT102 Aug 15, 2024
f817709
changed to use async and await and now grabbing user responses from r…
m20arcusk Aug 16, 2024
0f6fb2a
update types
isa-leroux448 Aug 17, 2024
ece81fb
comment out edit text
isa-leroux448 Aug 17, 2024
1fa423d
update date handling in profile event card
isa-leroux448 Aug 17, 2024
a712364
Merge branch 'dev' of https://github.com/ubc-biztech/bt-web-v2 into p…
isa-leroux448 Aug 17, 2024
34adaa5
move head
isa-leroux448 Aug 17, 2024
edbbf14
updated userResponse type and changed how it is accessed in userRespo…
m20arcusk Aug 17, 2024
8185620
Merge pull request #37 from ubc-biztech/fetchbackend
AllanT102 Aug 17, 2024
5ab669a
resolved merge conflicts
m20arcusk Aug 18, 2024
231e7ec
Merge pull request #34 from ubc-biztech/registration-user-popup
m20arcusk Aug 18, 2024
d5c4fea
Merge branch 'dev' of https://github.com/ubc-biztech/bt-web-v2 into p…
isa-leroux448 Aug 19, 2024
38064ee
Merge pull request #26 from ubc-biztech/profile-page
isa-leroux448 Aug 19, 2024
af530d7
add chart empty states
isa-leroux448 Aug 19, 2024
9edec04
replace Attendee type with Registration
isa-leroux448 Aug 20, 2024
d1bb883
Merge branch 'event-stats' of https://github.com/ubc-biztech/bt-web-v…
isa-leroux448 Aug 26, 2024
cf8ce98
fix attendee table popup nested object issues
isa-leroux448 Aug 26, 2024
2227669
fix package-lock file
isa-leroux448 Aug 26, 2024
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
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"@aws-amplify/adapter-nextjs": "^1.2.10",
"@aws-amplify/auth": "^6.3.7",
"@aws-amplify/ui-react": "^6.1.12",
"aws-amplify": "^6.3.8",
"@radix-ui/react-checkbox": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
Expand All @@ -29,6 +28,7 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"framer-motion": "^11.2.10",
"lodash": "^4.17.21",
"lucide-react": "^0.396.0",
"next": "14.2.3",
"react": "^18",
Expand Down
9 changes: 9 additions & 0 deletions src/components/Stats/ChartBox.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.dynamicWidth {
width: 100%;
}

@media (min-width: 1024px) {
.dynamicWidth {
width: var(--dynamic-width);
}
}
33 changes: 33 additions & 0 deletions src/components/Stats/ChartBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { ReactNode } from "react";
import styles from './ChartBox.module.css'

interface ChartBoxProps {
height?: string;
width?: string;
title: string;
children: ReactNode;
}

const ChartBox: React.FC<ChartBoxProps> = ({
children,
title,
height = "100%",
width = "100%",
}) => {
return (
<div
className={`bg-dark-slate my-2 p-4 flex flex-col rounded ${styles.dynamicWidth}`}
style={{
height: height,
'--dynamic-width': width
} as React.CSSProperties}
>
<p className="text-white font-600 mb-2">{title}</p>
<div className="flex-grow flex items-center">
<div className="flex-grow">{children}</div>
</div>
</div>
);
};

export default ChartBox;
81 changes: 81 additions & 0 deletions src/components/Stats/PercentageBars.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useState, useEffect } from "react";
import { StatsChartData } from "@/types/types";

interface PercentageBarsProps {
data: StatsChartData[];
}

export const barColors = ['#A0C86E', '#75CFF5', '#E75A7C', '#FFC960', '#C082D6', '#7F94FF', '#EB8273']

const calculateBarPercentages = (
data: StatsChartData[],
total: number
) => {
const percentages: { [key: string]: number } = {};

data.forEach((item) => {
const { label, value } = item;
percentages[label] = (value / total) * 100;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is total always gonna be non zero?

});
return percentages;
};

const getColorForIndex = (index: number): string => {
return barColors[index % barColors.length];
};

const PercentageBars: React.FC<PercentageBarsProps> = ({ data }) => {
const [total, setTotal] = useState(0);
const [percentages, setPercentages] = useState<{ [key: string]: number }>({});

useEffect(() => {
const totalValue = data.reduce((sum, item) => sum + item.value, 0);
setTotal(totalValue);
setPercentages(calculateBarPercentages(data, totalValue));
}, [data]);

return (
<div>
<div className="flex h-[50px] w-full mb-3 pt-6">
{Object.entries(percentages).map(([label, percentage], index) => (
<div
key={label}
className="flex items-center justify-center relative"
style={{
flex: `0 0 ${percentage}%`,
backgroundColor: getColorForIndex(index),
borderTopLeftRadius: index === 0 ? "4px" : "0",
borderBottomLeftRadius: index === 0 ? "4px" : "0",
borderTopRightRadius:
index === Object.entries(percentages).length - 1 ? "4px" : "0",
borderBottomRightRadius:
index === Object.entries(percentages).length - 1 ? "4px" : "0",
}}
>
<div className="absolute top-[-25px] left-[50%] text-white text-sm font-medium translate-x-[-50%]">
{percentage.toFixed(1)}%
</div>
</div>
))}
</div>
<div className="flex items-center w-full text-white">
<div className="flex flex-wrap">
{Object.keys(percentages).map((label, index) => (
<div key={label} className="flex items-center mr-5 text-xs">
<div
className="w-4 h-4 mr-2 rounded-[2px]"
style={{
backgroundColor: getColorForIndex(index),
}}
/>
<span>{label}</span>
</div>
))}
</div>
<p className="ml-auto self-end font-600">Total registered: {total}</p>
</div>
</div>
);
};

export default PercentageBars;
69 changes: 37 additions & 32 deletions src/components/Stats/StatsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,51 @@
import { StatsChartData } from "@/types/types";

interface StatsTableProps {
title: string;
data: Object;
data: StatsChartData[];
}

const StatsTable: React.FC<StatsTableProps> = ({ title, data }) => {
const renderData = (data: Object, marginValue: number = 0): JSX.Element[] => {
return Object.entries(data).map(([label, count]) => {
if (typeof count === "number" || typeof count === "string") {
return (
<>
<div
className="col-span-2"
style={{ marginLeft: `${marginValue}px` }}
>
{label}
</div>
<div className="col-span-1 text-right">{count}</div>
</>
);
const StatsTable: React.FC<StatsTableProps> = ({ data }) => {
const renderData = () => {
const simpleData: JSX.Element[] = [];
const groupedData: { [key: string]: StatsChartData[] } =
{};

data.forEach((item) => {
const [parent, child] = item.label.split(":");
if (child) {
if (!groupedData[parent]) {
groupedData[parent] = [];
}
groupedData[parent].push({ label: child, value: item.value });
} else {
return (
simpleData.push(
<>
<div
className="col-span-2"
style={{ marginLeft: `${marginValue}px` }}
>
{label}
</div>
{renderData(count, marginValue + 16)}
<div className="col-span-2">{item.label}</div>
<div className="col-span-1 text-right">{item.value}</div>
</>
);
}
});

Object.entries(groupedData).forEach(([parent, children]) => {
simpleData.push(
<>
<div className="col-span-3 font-bold">{parent}</div>
{children.map(({ label, value }) => (
<>
<div className="col-span-2 pl-4">{label}</div>
<div className="col-span-1 text-right">{value}</div>
</>
))}
</>
);
});

return simpleData;
};

return (
<div className="bg-dark-slate p-8 w-1/3 rounded-md">
<h5 className="text-white">{title}</h5>
<br />
<div className="grid grid-cols-3 gap-2 text-pale-blue">
{renderData(data)}
</div>
</div>
<div className="grid grid-cols-3 gap-2 text-pale-blue">{renderData()}</div>
);
};

Expand Down
48 changes: 29 additions & 19 deletions src/components/stats/BarChart.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
import React from "react";
import { StatsChartData } from "@/types/types";
import { debounce } from "lodash";
import React, { useEffect, useState } from "react";
import { Chart } from "react-google-charts";

interface BarChartProps {
data: { label: string; value: number }[];
data: StatsChartData[];
title?: string;
width?: number;
height?: number;
}

const BarChart: React.FC<BarChartProps> = ({
data,
title = "Bar Chart",
width = 600,
height = 400,
title,
width = "100%",
height = "100%",
}) => {
const chartData = [
["Label", "Value"],
...data.map((item) => [item.label, item.value]),
];

// Re-render the chart component when window is resized horizontally
const [windowWidth, setWindowWidth] = useState<number | null>(null);
useEffect(() => {
setWindowWidth(window.innerWidth);
const handleResize = debounce(() => {
setWindowWidth(window.innerWidth);
}, 25);
window.addEventListener('resize', handleResize);

return () => {
window.removeEventListener('resize', handleResize);
};
}, []);

const options = {
backgroundColor: "transparent",
chartArea: {
left: "10%",
top: "20%",
width: "80%",
height: "70%",
},
Expand Down Expand Up @@ -81,18 +95,14 @@ const BarChart: React.FC<BarChartProps> = ({
};

return (
<div
className={`bg-login-form-card rounded-md font-poppins`}
style={{ width: width + "px" }}
>
<Chart
chartType="ColumnChart"
data={chartData}
options={options}
width={width + "px"}
height={height + "px"}
/>
</div>
<Chart
key={windowWidth}
chartType="ColumnChart"
data={chartData}
options={options}
width={width}
height={height}
/>
);
};

Expand Down
54 changes: 34 additions & 20 deletions src/components/stats/PieChart.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
import React from 'react';
import { Chart } from 'react-google-charts';

import React, { useEffect, useState } from "react";
import { Chart } from "react-google-charts";
import { debounce } from "lodash";
import { StatsChartData } from "@/types/types";
interface PieChartProps {
data: { label: string; value: number }[];
data: StatsChartData[];
title?: string;
width?: number;
height?: number;
}

const PieChart: React.FC<PieChartProps> = ({
data,
title = 'Pie Chart',
width = 600,
height = 400,
title,
width = "100%",
height = "100%",
}) => {
// Format the data for Google Charts
const chartData = [
['Label', 'Value'],
...data.map(item => [item.label, item.value]),
];

// Re-render the chart component when window is resized horizontally
const [windowWidth, setWindowWidth] = useState<number | null>(null);
useEffect(() => {
setWindowWidth(window.innerWidth);
const handleResize = debounce(() => {
setWindowWidth(window.innerWidth);
}, 25);
window.addEventListener('resize', handleResize);

return () => {
window.removeEventListener('resize', handleResize);
};
}, []);

const options = {
backgroundColor: 'transparent',
pieHole: 0.4,
Expand Down Expand Up @@ -58,24 +73,23 @@ const PieChart: React.FC<PieChartProps> = ({
showColorCode: true
},
chartArea: {
left: '10%',
top: '20%',
width: '80%',
height: '70%',
left: "0%",
top: "5%",
width: "100%",
height: "100%",
},
fontName: 'Poppins'
};

return (
<div className={`bg-login-form-card rounded-md font-poppins`} style={{width: width + 'px'}}>
<Chart
chartType="PieChart"
data={chartData}
options={options}
width={width + 'px'}
height={height + 'px'}
/>
</div>
<Chart
key={windowWidth}
chartType="PieChart"
data={chartData}
options={options}
width={width}
height={height}
/>
);
};

Expand Down
Loading