🚧 wip: share genre tags UI for reuse

This commit is contained in:
2026-04-06 21:09:27 +07:00
parent a277372f43
commit 09ae6dd8fb
5 changed files with 143 additions and 10 deletions

View File

@ -1,4 +1,42 @@
export const getAnimeBySlug = async (slug: string) => {
export interface GetAnimeBySlugResponse {
success: boolean;
status: number;
message: string;
data: {
id: string;
title: string;
titleAlternative: {
type: string;
title: string;
}[];
genres: {
slug: string;
name: string;
}[];
slug: string;
malId: number;
pictureMedium: string;
pictureLarge: string;
country: string;
score: string;
status: string;
startAiring: string;
endAiring: string;
synopsis: string;
ageRating: string;
mediaType: string;
source: string;
onDraft: boolean;
uploadedBy: string;
deletedAt: null | string;
createdAt: string;
updatedAt: string;
};
}
export const getAnimeBySlug = async (
slug: string,
): Promise<GetAnimeBySlugResponse> => {
return {
success: true,
status: 200,
@ -20,6 +58,20 @@ export const getAnimeBySlug = async (slug: string) => {
title: "Sakamoto Days",
},
],
genres: [
{
slug: "action",
name: "Action",
},
{
slug: "slice-of-life",
name: "Slice of Life",
},
{
slug: "comedy",
name: "Comedy",
},
],
slug: "sakamoto-days",
malId: 58939,
pictureMedium: "https://myanimelist.net/images/anime/1026/146459.webp",

View File

@ -0,0 +1,56 @@
"use client";
import { GetAnimeBySlugResponse } from "../../actions/getAnimeBySlug";
import GenreTags from "@/shared/components/GenreTags";
const AnimeInformationClient = ({ data }: { data: GetAnimeBySlugResponse }) => {
return (
<section className="flex gap-4">
<div>
<img
src={data.data.pictureMedium}
alt={data.data.title}
className="h-fit w-78 overflow-hidden rounded-lg"
/>
</div>
<div className="tracking-tight">
<div className="flex flex-col gap-0.5">
<h1 className="tracking-tighter text-5xl font-bold">
{data.data.title}
</h1>
<h3 className="ml-0.5 tracking-tight text-xl font-medium text-muted-foreground">
{data.data.titleAlternative[0].title}
</h3>
</div>
<div className="mt-2">
<GenreTags genres={data.data.genres} />
</div>
<table>
<tbody>
<tr className="">
<td className="font-medium text-sm text-muted-foreground">
Score
</td>
<td className="text-sm">{data.data.score}</td>
</tr>
<tr>
<td className="font-medium text-sm text-muted-foreground">
Status
</td>
<td className="text-sm">{data.data.status}</td>
</tr>
<tr>
<td className="font-medium text-sm text-muted-foreground">
Airing
</td>
<td className="text-sm">
{data.data.startAiring} - {data.data.endAiring}
</td>
</tr>
</tbody>
</table>
</div>
</section>
);
};
export default AnimeInformationClient;

View File

@ -1,9 +1,14 @@
import { getAnimeBySlug } from "../../actions/getAnimeBySlug";
import AnimeInformationClient from "./main.client";
const AnimeInformationMain = async () => {
const data = async () => await getAnimeBySlug("sakamoto-days");
const result = await data();
return <div>Data: {JSON.stringify(result)}</div>;
return (
<div>
<AnimeInformationClient data={result} />
</div>
);
};
export default AnimeInformationMain;

View File

@ -7,6 +7,7 @@ import { Swiper, SwiperSlide } from "swiper/react";
import { Icon } from "@iconify/react";
import Link from "next/link";
import AddToList from "./AddToList";
import GenreTags from "@/shared/components/GenreTags";
export interface HeroSwiperProps {
data: {
@ -50,14 +51,8 @@ const HeroSwiper = (props: HeroSwiperProps) => {
<h1 className="text-6xl font-semibold tracking-tight">
{slide.title}
</h1>
<div className="mt-4 flex gap-1.5">
{slide.genres.map((genre) => (
<Link href={`/genres/${genre.slug}`} key={genre.slug}>
<Badge className="bg-neutral-100/60 backdrop-blur-lg text-neutral-800">
{genre.name}
</Badge>
</Link>
))}
<div className="mt-4">
<GenreTags genres={slide.genres} />
</div>
<p className="mt-4 font-medium text-base max-w-[40vw] line-clamp-6">
{slide.synopsis}

View File

@ -0,0 +1,25 @@
import Link from "next/link";
import { Badge } from "../libs/shadcn/ui/badge";
type GenreTagsProps = {
genres: {
slug: string;
name: string;
}[];
};
const GenreTags = ({ genres }: GenreTagsProps) => {
return (
<div className="flex gap-1.5">
{genres.map((genre, index) => (
<Link href={`/genres/${genre.slug}`} key={index}>
<Badge className="bg-neutral-100/60 backdrop-blur-lg text-neutral-800">
{genre.name}
</Badge>
</Link>
))}
</div>
);
};
export default GenreTags;