feat: favorite actors top-5 stat in profile trends
All checks were successful
CI / Check / Test (push) Successful in 1h5m14s

This commit is contained in:
2026-08-09 20:59:18 +02:00
parent d282e8ea7e
commit 4d221e60de
13 changed files with 297 additions and 10 deletions

View File

@@ -19,6 +19,7 @@ import { WATCH_MEDIUMS } from "@/lib/watch-mediums"
import { ReviewDetailSheet } from "@/components/review-detail-sheet"
import { DiaryCalendar } from "@/components/diary-calendar"
import type { DiaryEntryDto } from "@/lib/api/common"
import { tmdbProfileUrl } from "@/lib/api/client"
import type { UserProfileResponse } from "@/features/users"
type ProfileViewProps = {
@@ -231,6 +232,7 @@ function TrendsView({
data: {
trends?: {
top_directors: { director: string; count: number }[]
top_actors?: { name: string; profile_path?: string; movie_count: number; score: number }[]
monthly_ratings: {
month_label: string
avg_rating: number
@@ -269,6 +271,33 @@ function TrendsView({
</Card>
)}
{data.trends.top_actors && data.trends.top_actors.length > 0 && (
<Card size="sm">
<CardHeader>
<CardTitle className="text-sm">{t("profile.topActors")}</CardTitle>
</CardHeader>
<CardContent>
{data.trends.top_actors.map((a) => (
<div
key={a.name}
className="flex items-center gap-3 py-1.5"
>
<Avatar size="sm">
{a.profile_path && (
<AvatarImage src={tmdbProfileUrl(a.profile_path)} />
)}
<AvatarFallback>{a.name[0]}</AvatarFallback>
</Avatar>
<span className="flex-1 truncate text-sm">{a.name}</span>
<span className="text-xs text-muted-foreground">
{t("common.films", { count: a.movie_count })}
</span>
</div>
))}
</CardContent>
</Card>
)}
{data.trends.top_genres.length > 0 && (
<Card size="sm">
<CardHeader>

View File

@@ -48,6 +48,14 @@ export const directorStatDtoSchema = z.object({
})
export type DirectorStatDto = z.infer<typeof directorStatDtoSchema>
export const actorStatDtoSchema = z.object({
name: z.string(),
profile_path: z.string().optional(),
movie_count: z.number(),
score: z.number(),
})
export type ActorStatDto = z.infer<typeof actorStatDtoSchema>
export const genreStatDtoSchema = z.object({
genre: z.string(),
count: z.number(),
@@ -64,6 +72,7 @@ export const userTrendsDtoSchema = z.object({
monthly_ratings: z.array(monthlyRatingDtoSchema),
top_directors: z.array(directorStatDtoSchema),
max_director_count: z.number(),
top_actors: z.array(actorStatDtoSchema).default([]),
top_genres: z.array(genreStatDtoSchema).default([]),
rating_distribution: z.array(z.number()).default([]),
watch_medium_distribution: z.array(watchMediumStatDtoSchema).default([]),

View File

@@ -125,6 +125,7 @@
"noEntries": "No entries",
"noTrends": "No trends yet",
"topDirectors": "Top Directors",
"topActors": "Favorite Actors",
"monthlyActivity": "Monthly Activity",
"searchPlaceholder": "Search entries...",
"watchedAgo": "Watched {{when}}"