feat/recommendation #10

Merged
vivy-agent merged 7 commits from feat/recommendation into main 2026-03-15 22:36:55 +07:00
12 changed files with 457 additions and 3 deletions
Showing only changes of commit 74ad82c4f0 - Show all commits

View File

@ -13,7 +13,7 @@ export type RecommendationAnime = {
export const getRecommendationAnimeAction = async (): Promise<
RecommendationAnime[]
> => {
// await new Promise((resolve) => setTimeout(resolve, 2000));
await new Promise((resolve) => setTimeout(resolve, 2000));
return [
{

View File

@ -1,16 +1,21 @@
import { Button } from "@/shared/libs/shadcn/ui/button";
import { ButtonGroup } from "@/shared/libs/shadcn/ui/button-group";
import { ArrowLeft, ArrowRight } from "lucide-react";
import React from "react";
const ScrollingButton = () => {
const ScrollingButton = ({
scrollLeft,
scrollRight,
}: {
scrollLeft: () => void;
scrollRight: () => void;
}) => {
return (
<div>
<ButtonGroup>
<Button variant="outline">
<Button variant="outline" onClick={scrollLeft}>
<ArrowLeft />
</Button>
<Button variant="outline">
<Button variant="outline" onClick={scrollRight}>
<ArrowRight />
</Button>
</ButtonGroup>

View File

@ -0,0 +1,46 @@
"use client";
import { useRef } from "react";
import { RecommendationAnime } from "../../actions/getRecommenationAnime";
import AnimeRecommendationCard from "./components/Card";
import ScrollingButton from "./components/ScrollingButton";
import { Skeleton } from "@/shared/libs/shadcn/ui/skeleton";
const RecommendationClient = ({
result,
}: {
result: RecommendationAnime[];
}) => {
const scrollingContainer = useRef<HTMLDivElement | null>(null);
const scrollLeft = () => {
console.log("scroll left");
if (scrollingContainer.current) {
scrollingContainer.current.scrollBy({ left: -788, behavior: "smooth" });
}
};
const scrollRight = () => {
console.log("scroll right");
if (scrollingContainer.current) {
scrollingContainer.current.scrollBy({ left: 788, behavior: "smooth" });
}
};
return (
<div>
<div className="absolute top-0 right-0">
<ScrollingButton scrollLeft={scrollLeft} scrollRight={scrollRight} />
</div>
<div
className="flex gap-2 w-full overflow-x-scroll py-2 mt-2 hide-scrollbar relative"
ref={scrollingContainer}
>
{result.map((item, index) => (
<AnimeRecommendationCard data={item} key={index} />
))}
</div>
</div>
);
};
export default RecommendationClient;

View File

@ -1,16 +1,10 @@
import { getRecommendationAnimeAction } from "../../actions/getRecommenationAnime";
import AnimeRecommendationCard from "./components/Card";
import RecommendationClient from "./main.client";
const RecommendationMain = async () => {
const data = async () => await getRecommendationAnimeAction();
const result = await data();
return (
<div className="flex gap-2 w-full overflow-x-scroll py-2 my-2 hide-scrollbar">
{result.map((item, index) => (
<AnimeRecommendationCard data={item} key={index} />
))}
</div>
);
return <RecommendationClient result={result} />;
};
export default RecommendationMain;

View File

@ -1,5 +1,19 @@
import { Skeleton } from "@/shared/libs/shadcn/ui/skeleton";
const RecommendationSkeleton = () => {
return <div>loading...</div>;
const skeletonLenght = 6;
return (
<div className="flex gap-2 w-full overflow-hidden mt-4">
{[...Array(skeletonLenght)].map((_, index) => (
<div tabIndex={index}>
<Skeleton className="h-88 w-64" />
<Skeleton className="mt-3 h-6 w-64 rounded-full" />
<Skeleton className="mt-1 h-4 w-12 rounded-full" />
</div>
))}
</div>
);
};
export default RecommendationSkeleton;

View File

@ -5,14 +5,11 @@ import ScrollingButton from "./components/ScrollingButton";
const Recommendation = async () => {
return (
<div className="mt-12">
<div className="mt-12 relative">
<div className="flex justify-between">
<h1 className="text-[26px] text-neutral-100 font-semibold w-fit tracking-tight">
Maybe You Like
</h1>
<div>
<ScrollingButton />
</div>
</div>
<Suspense fallback={<RecommendationSkeleton />}>
<RecommendationMain />