diff --git a/spa/src/aero-theme.css b/spa/src/aero-theme.css
index 79eedd7..1070ffe 100644
--- a/spa/src/aero-theme.css
+++ b/spa/src/aero-theme.css
@@ -298,6 +298,11 @@ body > #root {
color: oklch(0.985 0 0);
}
+/* Chart label readability */
+[data-slot="chart"] .recharts-cartesian-axis-tick text {
+ fill: rgba(255, 255, 255, 0.85) !important;
+}
+
/* Star glow for filled amber stars */
.aero-star-filled {
filter: drop-shadow(0 0 4px var(--aero-primary-glow)) drop-shadow(0 0 1px var(--aero-primary));
diff --git a/spa/src/components/profile-view.tsx b/spa/src/components/profile-view.tsx
index 9682850..de9405a 100644
--- a/spa/src/components/profile-view.tsx
+++ b/spa/src/components/profile-view.tsx
@@ -1,7 +1,9 @@
import { Link } from "@tanstack/react-router"
import { useCallback } from "react"
import { useTranslation } from "react-i18next"
+import { Bar, BarChart, XAxis, YAxis } from "recharts"
import { User } from "lucide-react"
+import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from "@/components/ui/chart"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Skeleton } from "@/components/ui/skeleton"
@@ -136,6 +138,10 @@ function DiaryTab({ sortBy }: { sortBy: string; userId?: string }) {
)
}
+const trendChartConfig = {
+ count: { label: "Movies", color: "var(--primary)" },
+} satisfies ChartConfig
+
function TrendsView({
data,
}: {
@@ -183,17 +189,14 @@ function TrendsView({
{t("profile.monthlyActivity")}
- {data.trends.monthly_ratings.map((m) => (
-
- {m.month_label}
-
- {t("common.filmsAvg", { count: m.count, avg: m.avg_rating.toFixed(1) })}
-
-
- ))}
+
+
+ v.slice(0, 3)} tick={{ fontSize: 10, fill: "rgba(255,255,255,0.85)" }} tickLine={false} axisLine={false} />
+
+ } />
+
+
+
)}
diff --git a/spa/src/components/rating-histogram.tsx b/spa/src/components/rating-histogram.tsx
index 5de426b..e0ef250 100644
--- a/spa/src/components/rating-histogram.tsx
+++ b/spa/src/components/rating-histogram.tsx
@@ -1,26 +1,24 @@
+import { Bar, BarChart, XAxis } from "recharts"
+import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from "@/components/ui/chart"
+
+const chartConfig = {
+ count: { label: "Reviews", color: "var(--primary)" },
+} satisfies ChartConfig
+
type RatingHistogramProps = {
histogram: number[]
}
export function RatingHistogram({ histogram }: RatingHistogramProps) {
- const max = Math.max(...histogram, 1)
+ const data = histogram.map((count, i) => ({ rating: `${i + 1}★`, count }))
return (
-
-
- {histogram.map((count, i) => (
-
0 ? 2 : 0 }}
- />
- ))}
-
-
- {[1, 2, 3, 4, 5].map((n) => (
-
{n}
- ))}
-
-
+
+
+
+ } />
+
+
+
)
}
diff --git a/spa/src/routes/_app/wrapup.$id.tsx b/spa/src/routes/_app/wrapup.$id.tsx
index 7bb930a..3bde4ce 100644
--- a/spa/src/routes/_app/wrapup.$id.tsx
+++ b/spa/src/routes/_app/wrapup.$id.tsx
@@ -1,10 +1,20 @@
import { createFileRoute, Link } from "@tanstack/react-router"
import { lazy, Suspense, useState } from "react"
import { useTranslation } from "react-i18next"
+import { Bar, BarChart, XAxis, YAxis } from "recharts"
import { BarChart3, DollarSign, Globe, Hash, Share2, Star, Users } from "lucide-react"
+import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from "@/components/ui/chart"
import { BackButton } from "@/components/back-button"
import { Button } from "@/components/ui/button"
+const monthlyChartConfig = {
+ count: { label: "Movies", color: "var(--primary)" },
+} satisfies ChartConfig
+
+const genreChartConfig = {
+ count: { label: "Movies", color: "var(--primary)" },
+} satisfies ChartConfig
+
const WrapUpShareCard = lazy(() => import("@/components/wrapup-share-card").then((m) => ({ default: m.WrapUpShareCard })))
import { Badge } from "@/components/ui/badge"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
@@ -111,18 +121,14 @@ function WrapUpReportPage() {
{t("wrapup.genresExplored", { count: report.genre_diversity })}
- {report.top_genres.slice(0, 8).map((g) => {
- const max = report.top_genres[0]?.count ?? 1
- return (
-
-
{g.genre}
-
-
{g.count}
-
- )
- })}
+
+
+
+
+ } />
+
+
+
{report.highest_rated_genre && (
{t("wrapup.highestRated", { genre: report.highest_rated_genre })}
@@ -144,24 +150,14 @@ function WrapUpReportPage() {
- {(() => {
- const max = Math.max(...report.movies_per_month.map((x) => x.count))
- const barHeight = 96
- return (
-
- {report.movies_per_month.map((m) => {
- const h = max > 0 ? Math.max((m.count / max) * barHeight, 4) : 4
- return (
-
-
{m.count}
-
-
{m.year_month.slice(5)}
-
- )
- })}
-
- )
- })()}
+
+
+ v.slice(5)} tick={{ fontSize: 10, fill: "rgba(255,255,255,0.85)" }} tickLine={false} axisLine={false} />
+
+ report.movies_per_month.find((m) => m.year_month === String(v))?.label ?? String(v)} />} />
+
+
+
)}