diff --git a/frontend/src/components/ReportTopAlbums.tsx b/frontend/src/components/ReportTopAlbums.tsx
index 479bcaa..22031cb 100644
--- a/frontend/src/components/ReportTopAlbums.tsx
+++ b/frontend/src/components/ReportTopAlbums.tsx
@@ -5,6 +5,7 @@ import { TimeOptions } from "../api/entities/time-options";
import { TimePreset } from "../api/entities/time-preset.enum";
import { useTopAlbums } from "../hooks/use-api";
import { useAuth } from "../hooks/use-auth";
+import { getMaxCount } from "../util/getMaxCount";
import { ReportTimeOptions } from "./ReportTimeOptions";
import { TopListItem } from "./TopListItem";
@@ -27,6 +28,7 @@ export const ReportTopAlbums: React.FC = () => {
const { topAlbums, isLoading } = useTopAlbums(options);
const reportHasItems = !isLoading && topAlbums.length !== 0;
+ const maxCount = getMaxCount(topAlbums);
if (!user) {
return ;
@@ -55,7 +57,12 @@ export const ReportTopAlbums: React.FC = () => {
)}
{reportHasItems &&
topAlbums.map(({ album, count }) => (
-
+
))}
@@ -66,7 +73,8 @@ export const ReportTopAlbums: React.FC = () => {
const ReportItem: React.FC<{
album: Album;
count: number;
-}> = ({ album, count }) => {
+ maxCount: number;
+}> = ({ album, count, maxCount }) => {
const artists = album.artists?.map((artist) => artist.name).join(", ") || "";
return (
@@ -75,6 +83,7 @@ const ReportItem: React.FC<{
title={album.name}
subTitle={artists}
count={count}
+ maxCount={maxCount}
/>
);
};
diff --git a/frontend/src/components/ReportTopArtists.tsx b/frontend/src/components/ReportTopArtists.tsx
index f58153a..abe37df 100644
--- a/frontend/src/components/ReportTopArtists.tsx
+++ b/frontend/src/components/ReportTopArtists.tsx
@@ -4,6 +4,7 @@ import { TimeOptions } from "../api/entities/time-options";
import { TimePreset } from "../api/entities/time-preset.enum";
import { useTopArtists } from "../hooks/use-api";
import { useAuth } from "../hooks/use-auth";
+import { getMaxCount } from "../util/getMaxCount";
import { ReportTimeOptions } from "./ReportTimeOptions";
import { TopListItem } from "./TopListItem";
@@ -26,6 +27,7 @@ export const ReportTopArtists: React.FC = () => {
const { topArtists, isLoading } = useTopArtists(options);
const reportHasItems = !isLoading && topArtists.length !== 0;
+ const maxCount = getMaxCount(topArtists);
if (!user) {
return ;
@@ -54,7 +56,12 @@ export const ReportTopArtists: React.FC = () => {
)}
{reportHasItems &&
topArtists.map(({ artist, count }) => (
-
+
))}
diff --git a/frontend/src/components/ReportTopTracks.tsx b/frontend/src/components/ReportTopTracks.tsx
index e3ef730..3a8ec27 100644
--- a/frontend/src/components/ReportTopTracks.tsx
+++ b/frontend/src/components/ReportTopTracks.tsx
@@ -5,6 +5,7 @@ import { TimePreset } from "../api/entities/time-preset.enum";
import { Track } from "../api/entities/track";
import { useTopTracks } from "../hooks/use-api";
import { useAuth } from "../hooks/use-auth";
+import { getMaxCount } from "../util/getMaxCount";
import { ReportTimeOptions } from "./ReportTimeOptions";
import { TopListItem } from "./TopListItem";
@@ -32,6 +33,8 @@ export const ReportTopTracks: React.FC = () => {
return ;
}
+ const maxCount = getMaxCount(topTracks);
+
return (
@@ -55,7 +58,7 @@ export const ReportTopTracks: React.FC = () => {
)}
{reportHasItems &&
topTracks.map(({ track, count }) => (
-
+
))}
@@ -66,7 +69,8 @@ export const ReportTopTracks: React.FC = () => {
const ReportItem: React.FC<{
track: Track;
count: number;
-}> = ({ track, count }) => {
+ maxCount: number;
+}> = ({ track, count, maxCount }) => {
const artists = track.artists?.map((artist) => artist.name).join(", ") || "";
return (
@@ -75,6 +79,7 @@ const ReportItem: React.FC<{
title={track.name}
subTitle={artists}
count={count}
+ maxCount={maxCount}
/>
);
};
diff --git a/frontend/src/components/TopListItem.tsx b/frontend/src/components/TopListItem.tsx
index 2727796..c678610 100644
--- a/frontend/src/components/TopListItem.tsx
+++ b/frontend/src/components/TopListItem.tsx
@@ -1,23 +1,55 @@
import React from "react";
-export const TopListItem: React.FC<{
+export interface TopListItemProps {
key: string;
title: string;
subTitle?: string;
count: number;
-}> = ({ key, title, subTitle, count }) => {
+
+ /**
+ * Highest Number that is displayed in the top list. Used to display a "progress bar".
+ */
+ maxCount?: number;
+}
+
+export const TopListItem: React.FC = ({
+ key,
+ title,
+ subTitle,
+ count,
+ maxCount,
+}) => {
return (
-
-
- {title}
+
+
+
+ {title}
+
+ {subTitle &&
{subTitle}
}
- {subTitle &&
{subTitle}
}
+
{count}
-
{count}
+ {maxCount && isMaxCountValid(maxCount) && (
+
+ )}
);
};
+
+const isMaxCountValid = (maxCount: number) =>
+ !(Number.isNaN(maxCount) || maxCount === 0);
+
+const numberToPercent = (ratio: number) =>
+ ratio.toLocaleString(undefined, {
+ style: "percent",
+ minimumFractionDigits: 2,
+ });
diff --git a/frontend/src/util/getMaxCount.ts b/frontend/src/util/getMaxCount.ts
new file mode 100644
index 0000000..f37d440
--- /dev/null
+++ b/frontend/src/util/getMaxCount.ts
@@ -0,0 +1,11 @@
+interface TopListItemEntity {
+ count: number;
+}
+
+/**
+ * Get max count for top list. Returns at least 1 to make sure we do not run into issues
+ * with empty list (would normally return -Infinity) or 0 (could cause divide by zero error).
+ */
+export function getMaxCount(items: TopListItemEntity[]): number {
+ return Math.max(1, ...items.map(({ count }) => count));
+}
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index dc896ec..8c3ab91 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -39,6 +39,8 @@ module.exports = {
},
yellow: colors.yellow,
+ teal: colors.teal,
+ violet: colors.violet,
},
},
};