Skip to content

Commit

Permalink
Merge pull request #590 from NBISweden/dev/horizontal-bar
Browse files Browse the repository at this point in the history
Horizontal bar for time overview
  • Loading branch information
HenrikeW authored Aug 29, 2022
2 parents 836c854 + 737915f commit b2194ac
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
118 changes: 118 additions & 0 deletions frontend/src/components/BarChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, { useEffect, useState, useContext } from "react";
import { AuthContext } from "../components/AuthProvider";
import { getTimeEntries } from "../utils";
import { FetchedTimeEntry } from "../model";

export const BarChart = ({ loading }: { loading: boolean }) => {
const [spentTime, setSpentTime] = useState<{ [key: string]: number }>({});
const [total, setTotal] = useState<number>(0);
const context = useContext(AuthContext);
const today = new Date();
const oneYearAgo = new Date();
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);

useEffect(() => {
// Whenever the user has saved changes we want to fetch the year's time entries
// to immediately show changes in the chart.
// That is, we fetch everytime loading turns back to false.
// It's false when the page renders the first time, so we also fetch then.
if (!loading) {
getHoursPerActivity();
}
}, [loading]);

const getHoursPerActivity = async () => {
const timeEntries = await getTimeEntries(
undefined,
oneYearAgo,
today,
context
);
let activityHours: { [key: string]: number } = {};
timeEntries.map((entry: FetchedTimeEntry) => {
if (!activityHours[entry.activity.name]) {
activityHours[entry.activity.name] = 0;
}
activityHours[entry.activity.name] += entry.hours;
});
const sortedActivityHours = Object.keys(activityHours)
.sort()
.reduce(
(previousKey, currentKey) => ({
...previousKey,
[currentKey]: activityHours[currentKey],
}),
{}
);
setSpentTime(sortedActivityHours);
};

useEffect(() => {
const total = Object.values(spentTime).reduce(
(previousValue, currentValue) => previousValue + currentValue,
0
);
setTotal(total);
}, [spentTime]);

const getPercent = (value: number) => {
return Math.round((value / total) * 100);
};

const colors = [
"hsl(76deg 55% 53%)",
"hsl(288deg 13% 61%)",
"hsl(185deg 24% 80%)",
"hsl(26deg 91% 65%)",
"hsl(0deg 0% 75%)",
"hsl(186deg 30% 60%)",
"hsl(76deg 55% 77%)",
"hsl(291deg 13% 81%)",
"hsl(27deg 91% 77%)",
"hsl(76deg 55% 65%)",
"hsl(186deg 30% 86%)",
"hsl(0deg 0% 83%)",
"hsl(76deg 55% 42%)",
"hsl(26deg 91% 54%)",
"hsl(291deg 13% 90%)",
"hsl(185deg 24% 60%) ",
];

return (
<section className="overview-wrapper">
<h2 className="overview-heading">This year's work</h2>
<div className="bar-chart-wrapper">
{Object.keys(spentTime).length > 0 ? (
Object.keys(spentTime).map((key, index) => {
// If the number of hours is so low that the width would be rounded down to 0%,
// make it a thin slice anyway to show that it's there
const width =
getPercent(spentTime[key]) > 0
? `${getPercent(spentTime[key])}%`
: "4px";

return (
<div
key={spentTime[key]}
style={{
width: width,
backgroundColor: `${colors[index]}`,
}}
className="bar-chart-section"
>
<p>{key}</p>
<p>
{spentTime[key]}h, {getPercent(spentTime[key])}%
</p>
</div>
);
})
) : (
<div className="bar-chart-section">
Nothing to display - you haven't logged any time yet.
</div>
)}
</div>
</section>
);
};
35 changes: 35 additions & 0 deletions frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,41 @@ Other button classes are defined further down together with other classes for th
margin-left: 0.5rem;
}

/* OVERVIEW SECTION */
.overview-wrapper {
padding: 1rem 1.5rem;
background-color: hsl(0deg 0% 97%);
margin-top: 0.2rem;
}

.overview-bar {
width: 100%;
height: 2rem;
}

.overview-heading {
font-size: 1rem;
}

.bar-chart-wrapper {
display: flex;
width: 100%;
border-radius: 4px;
overflow: hidden;
}

.bar-chart-section {
overflow: hidden;
height: 100%;
padding-left: 0.3rem;
}

.bar-chart-section > p {
display: block ruby;
margin: 0;
font-size: 0.8rem;
}

.vacation-plan-picker-label {
margin: 0 0 0.1rem;
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/pages/Report.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import warning from "../icons/exclamation-triangle.svg";
import check from "../icons/check.svg";
import up from "../icons/caret-up-fill.svg";
import down from "../icons/caret-down-fill.svg";
import { BarChart } from "../components/BarChart";

const beforeUnloadHandler = (event) => {
event.preventDefault();
Expand Down Expand Up @@ -829,6 +830,7 @@ export const Report = () => {
</div>
</div>
</section>
<BarChart loading={isLoading}></BarChart>
</main>
<div className="footer">
<section className="footer-container">
Expand Down

0 comments on commit b2194ac

Please sign in to comment.