fix(frontend): add selectable timeframe and styling to listens report

This commit is contained in:
Julian Tölle 2020-05-14 01:35:24 +02:00
parent cab349c7d0
commit cc7f4b354d

View file

@ -9,6 +9,7 @@ import {
Tooltip,
XAxis,
YAxis,
TooltipProps,
} from "recharts";
import { getListensReport } from "../api/api";
import { ListenReportItem } from "../api/entities/listen-report-item";
@ -51,7 +52,30 @@ export const ReportListens: React.FC = () => {
<div className="flex justify-between">
<p className="text-2xl font-normal text-gray-700">Listen Report</p>
</div>
<div>
<div className="shadow-xl bg-gray-100 rounded p-5 m-2">
<div className="md:flex">
<div className="text-gray-700">
<label className="text-sm">Timeframe</label>
<select
className="block appearance-none min-w-full md:win-w-0 md:w-1/4 bg-white border border-gray-400 hover:border-gray-500 p-2 rounded shadow leading-tight focus:outline-none focus:shadow-outline"
onChange={(e) =>
setReportOptions({
...reportOptions,
timeFrame: e.target.value as
| "day"
| "week"
| "month"
| "year",
})
}
>
<option value="day">Daily</option>
<option value="week">Weekly</option>
<option value="month">Monthly</option>
<option value="year">Yearly</option>
</select>
</div>
</div>
{isLoading && (
<div>
<span>Loading Listens</span>
@ -63,7 +87,7 @@ export const ReportListens: React.FC = () => {
</div>
)}
{report.length > 0 && (
<div className="table-auto my-2 w-full text-gray-700">
<div className="w-full text-gray-700 mt-5">
<ReportGraph options={reportOptions} data={report} />
</div>
)}
@ -82,41 +106,113 @@ const ReportGraph: React.FC<{
date: getTime(date),
}));
const ReportTooltip: React.FC<TooltipProps> = ({
active,
payload,
label,
}) => {
if (!active || payload === undefined) {
return null;
}
const [{ value: listens }] = payload;
const date = format(
label as number,
dateFormatFromTimeFrame(options.timeFrame)
);
return (
<ResponsiveContainer width="90%" height={400}>
<div className="bg-gray-100 shadow-xl p-2 rounded text-sm font-light">
<p>{date}</p>
<p>
Listens: <span className="font-bold">{listens}</span>
</p>
</div>
);
};
return (
<div className="w-full">
<ResponsiveContainer width="100%" height={400}>
<AreaChart
data={dataLocal}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
left: -20,
}}
>
<defs>
<linearGradient id="colorPv" x1="0" y1="0" x2="0" y2="1">
<linearGradient id="colorCount" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#48bb78" stopOpacity={0.8} />
<stop offset="90%" stopColor="#48bb78" stopOpacity={0.1} />
</linearGradient>
</defs>
<CartesianGrid vertical={false} />
<CartesianGrid strokeDasharray="3 3" />
<XAxis
scale="time"
type="number"
domain={["auto", "auto"]}
dataKey="date"
tickFormatter={(date) => format(date, "P")}
tickFormatter={(date) =>
format(date, shortDateFormatFromTimeFrame(options.timeFrame))
}
/>
<YAxis />
<Tooltip separator=": " formatter={(value) => [value, "Listens"]} />
<Tooltip content={ReportTooltip} />
<Area
type="monotone"
dataKey="count"
stroke="#48bb78"
fillOpacity={1}
fill="url(#colorPv)"
fill="url(#colorCount)"
/>
</AreaChart>
</ResponsiveContainer>
</div>
);
};
const shortDateFormatFromTimeFrame = (
timeFrame: "day" | "week" | "month" | "year"
): string => {
const FORMAT_DAY = "P";
const FORMAT_WEEK = "'Week' w yyyy";
const FORMAT_MONTH = "LLL yyyy";
const FORMAT_YEAR = "yyyy";
const FORMAT_DEFAULT = FORMAT_DAY;
switch (timeFrame) {
case "day":
return FORMAT_DAY;
case "week":
return FORMAT_WEEK;
case "month":
return FORMAT_MONTH;
case "year":
return FORMAT_YEAR;
default:
return FORMAT_DEFAULT;
}
};
const dateFormatFromTimeFrame = (
timeFrame: "day" | "week" | "month" | "year"
): string => {
const FORMAT_DAY = "PPPP";
const FORMAT_WEEK = "'Week starting on' PPPP";
const FORMAT_MONTH = "LLLL yyyy";
const FORMAT_YEAR = "yyyy";
const FORMAT_DEFAULT = FORMAT_DAY;
switch (timeFrame) {
case "day":
return FORMAT_DAY;
case "week":
return FORMAT_WEEK;
case "month":
return FORMAT_MONTH;
case "year":
return FORMAT_YEAR;
default:
return FORMAT_DEFAULT;
}
};