feat: favorite actors top-5 stat in profile trends
All checks were successful
CI / Check / Test (push) Successful in 1h5m14s
All checks were successful
CI / Check / Test (push) Successful in 1h5m14s
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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([]),
|
||||
|
||||
@@ -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}}"
|
||||
|
||||
Reference in New Issue
Block a user