Skip to content

Commit

Permalink
add score stats to anime page
Browse files Browse the repository at this point in the history
  • Loading branch information
olexh committed Mar 29, 2024
1 parent 42664d2 commit 61734e7
Show file tree
Hide file tree
Showing 26 changed files with 266 additions and 129 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Metadata, ResolvingMetadata } from 'next';

import Characters from '../../_components/characters';
import Characters from '@/app/(pages)/anime/[slug]/components/characters';

export async function generateMetadata(
{ params }: { params: { slug: string } },
Expand Down
2 changes: 1 addition & 1 deletion app/(pages)/anime/[slug]/(animeDetails)/franchise/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Metadata, ResolvingMetadata } from 'next';

import Franchise from '../../_components/franchise';
import Franchise from '@/app/(pages)/anime/[slug]/components/franchise';

export async function generateMetadata(
{ params }: { params: { slug: string } },
Expand Down
2 changes: 1 addition & 1 deletion app/(pages)/anime/[slug]/(animeDetails)/links/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Metadata, ResolvingMetadata } from 'next';

import Links from '../../_components/links';
import Links from '@/app/(pages)/anime/[slug]/components/links';

export async function generateMetadata(
{ params }: { params: { slug: string } },
Expand Down
2 changes: 1 addition & 1 deletion app/(pages)/anime/[slug]/(animeDetails)/media/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Metadata, ResolvingMetadata } from 'next';

import Media from '../../_components/media';
import Media from '@/app/(pages)/anime/[slug]/components/media';

export async function generateMetadata(
{ params }: { params: { slug: string } },
Expand Down
2 changes: 1 addition & 1 deletion app/(pages)/anime/[slug]/(animeDetails)/staff/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Metadata, ResolvingMetadata } from 'next';

import Staff from '../../_components/staff';
import Staff from '@/app/(pages)/anime/[slug]/components/staff';

export async function generateMetadata(
{ params }: { params: { slug: string } },
Expand Down
95 changes: 0 additions & 95 deletions app/(pages)/anime/[slug]/_components/watchlist-stats.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getCookie } from '@/app/actions';
import WatchListButton from '@/components/watchlist-button';

import WatchStats from './_components/watch-stats';
import WatchStats from '@/app/(pages)/anime/[slug]/components/actions/components/watch-stats';

interface Props {
anime?: API.AnimeInfo;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use client';

import { useParams } from 'next/navigation';

import Small from '@/components/typography/small';
import useAnimeInfo from '@/services/hooks/anime/useAnimeInfo';

import Stats from './ui/stats';


const Score = () => {
const params = useParams();
const { data } = useAnimeInfo({ slug: String(params.slug) });

if (!data) {
return null;
}

const sumStats =
data.stats.score_1 +
data.stats.score_2 +
data.stats.score_3 +
data.stats.score_4 +
data.stats.score_5 +
data.stats.score_6 +
data.stats.score_7 +
data.stats.score_8 +
data.stats.score_9 +
data.stats.score_10;

const stats = Object.keys(data.stats)
.reverse()
.reduce((acc: Hikka.WatchStat[], stat) => {
if (
stat.includes('score') &&
data.stats[stat as API.StatType] > 0
) {
const percentage =
(100 * data.stats[stat as API.StatType]) / sumStats;

acc.push({
icon: <Small>{stat.split('score_')[1]}</Small>,
percentage,
value: data.stats[stat as API.StatType],
});
}

return acc;
}, []);

return <Stats stats={stats} />;
};

export default Score;
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
'use client';

import { NumericFormat } from 'react-number-format';

import Small from '@/components/typography/small';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip';

interface Props {
stats: Hikka.WatchStat[];
}

const Stats = ({ stats }: Props) => {
return (
<div className="relative overflow-hidden rounded-lg border border-secondary/60 bg-secondary/30 p-4">
<div className="flex flex-col justify-center gap-2">
{stats.map((stat) => {
return (
<Tooltip
key={`${stat.value}-${stat.percentage}`}
delayDuration={0}
>
<TooltipTrigger>
<div className="flex items-center justify-between gap-2">
<div className="flex w-full flex-1 items-center gap-2">
{stat.icon && (
<div className="flex size-6 items-center justify-center rounded-md bg-secondary">
{stat.icon}
</div>
)}
<div className="relative h-2 w-full flex-1 overflow-hidden rounded-md">
<div
className="absolute bottom-0 left-0 size-full bg-primary opacity-10"
style={{
backgroundColor: stat.color,
}}
/>
<div
className="absolute bottom-0 left-0 flex h-2 w-full items-end justify-center bg-primary"
style={{
backgroundColor: stat.color,
width: `${stat.percentage}%`,
}}
></div>
</div>
</div>
<Small className="w-14 text-right text-muted-foreground">
<NumericFormat
thousandSeparator
displayType="text"
value={stat.value}
decimalScale={1}
/>
</Small>
</div>
</TooltipTrigger>
<TooltipContent align="center" side="left">
{stat.percentage.toFixed(2)}%
</TooltipContent>
</Tooltip>
);
})}
</div>
</div>
);
};

export default Stats;
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use client';

import { createElement } from 'react';

import { useParams } from 'next/navigation';

import useAnimeInfo from '@/services/hooks/anime/useAnimeInfo';
import { WATCH_STATUS } from '@/utils/constants';

import Stats from './ui/stats';


const Watchlist = () => {
const params = useParams();
const { data } = useAnimeInfo({ slug: String(params.slug) });

if (!data) {
return null;
}

const sumStats =
data.stats.completed +
data.stats.on_hold +
data.stats.dropped +
data.stats.planned +
data.stats.watching;

const stats = Object.keys(data.stats).reduce(
(acc: Hikka.WatchStat[], stat) => {
if (!stat.includes('score')) {
const status = WATCH_STATUS[stat as API.WatchStatus];
const percentage =
(100 * data.stats[stat as API.StatType]) / sumStats;

acc.push({
percentage,
value: data.stats[stat as API.StatType],
icon: status.icon && createElement(status.icon),
color: status.color!,
});
}

return acc;
},
[],
);

return <Stats stats={stats} />;
};

export default Watchlist;
39 changes: 39 additions & 0 deletions app/(pages)/anime/[slug]/components/watch-stats/watch-stats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import SubHeader from '@/components/sub-header';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';

import Score from './components/score';
import Watchlist from './components/watchlist';

const WatchStats = () => {
return (
<div className="flex flex-col gap-8">
<SubHeader title="Статистика">
<ToggleGroup
type="single"
value="MAL"
variant="outline"
size="badge"
>
<ToggleGroupItem value="MAL" aria-label="MAL">
MAL
</ToggleGroupItem>
</ToggleGroup>
</SubHeader>
<Tabs defaultValue="watchlist">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="watchlist">У списках</TabsTrigger>
<TabsTrigger value="score">Оцінки</TabsTrigger>
</TabsList>
<TabsContent value="watchlist">
<Watchlist />
</TabsContent>
<TabsContent value="score">
<Score />
</TabsContent>
</Tabs>
</div>
);
};

export default WatchStats;
6 changes: 3 additions & 3 deletions app/(pages)/anime/[slug]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import getDeclensionWord from '@/utils/getDeclensionWord';
import getQueryClient from '@/utils/getQueryClient';
import parseTextFromMarkDown from '@/utils/parseTextFromMarkDown';

import Actions from './_components/actions';
import Cover from './_components/cover';
import Title from './_components/title';
import Actions from '@/app/(pages)/anime/[slug]/components/actions';
import Cover from '@/app/(pages)/anime/[slug]/components/cover';
import Title from '@/app/(pages)/anime/[slug]/components/title';


interface Props extends PropsWithChildren {
Expand Down
Loading

0 comments on commit 61734e7

Please sign in to comment.