mirror of
https://github.com/JustAnimeCore/JustAnime.git
synced 2026-04-17 22:01:45 +00:00
home page done
This commit is contained in:
@@ -14,13 +14,14 @@ import "./Banner.css";
|
|||||||
function Banner({ item, index }) {
|
function Banner({ item, index }) {
|
||||||
const { language } = useLanguage();
|
const { language } = useLanguage();
|
||||||
return (
|
return (
|
||||||
<section className="spotlight w-full h-full relative rounded-2xl overflow-hidden">
|
<section className="spotlight w-full h-full relative rounded-md overflow-hidden">
|
||||||
<img
|
<img
|
||||||
src={`${item.poster}`}
|
src={`${item.poster}`}
|
||||||
alt={getSafeTitle(item.title, language, item.japanese_title)}
|
alt={getSafeTitle(item.title, language, item.japanese_title)}
|
||||||
className="absolute inset-0 object-cover w-full h-full rounded-2xl"
|
className="absolute inset-0 object-cover w-full h-full rounded-md"
|
||||||
|
draggable="false"
|
||||||
/>
|
/>
|
||||||
<div className="spotlight-overlay absolute inset-0 z-[1] rounded-2xl"></div>
|
<div className="spotlight-overlay absolute inset-0 z-[1] rounded-md"></div>
|
||||||
|
|
||||||
<div className="absolute flex flex-col left-0 bottom-[40px] w-[55%] p-4 z-[2] max-[1390px]:w-[45%] max-[1390px]:bottom-[40px] max-[1300px]:w-[600px] max-[1120px]:w-[60%] max-md:w-[90%] max-md:bottom-[20px] max-[300px]:w-full">
|
<div className="absolute flex flex-col left-0 bottom-[40px] w-[55%] p-4 z-[2] max-[1390px]:w-[45%] max-[1390px]:bottom-[40px] max-[1300px]:w-[600px] max-[1120px]:w-[60%] max-md:w-[90%] max-md:bottom-[20px] max-[300px]:w-full">
|
||||||
<p className="text-[#ffbade] font-semibold text-[20px] w-fit max-[1300px]:text-[15px]">
|
<p className="text-[#ffbade] font-semibold text-[20px] w-fit max-[1300px]:text-[15px]">
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ const CategoryCard = React.memo(
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={`grid ${cardStyle || 'grid-cols-6 max-[1400px]:grid-cols-4 max-[758px]:grid-cols-3 max-[478px]:grid-cols-3'} gap-x-3 gap-y-8 mt-6 transition-all duration-300 ease-in-out max-[478px]:gap-x-2`}>
|
<div className={`grid ${cardStyle || 'grid-cols-5 max-[1400px]:grid-cols-4 max-[758px]:grid-cols-3 max-[478px]:grid-cols-3'} gap-x-3 gap-y-8 mt-6 transition-all duration-300 ease-in-out max-[478px]:gap-x-2`}>
|
||||||
{itemsToRender.remainingItems.map((item, index) => (
|
{itemsToRender.remainingItems.map((item, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ function Footer() {
|
|||||||
hosts and providers. {website_name} is not responsible for any media
|
hosts and providers. {website_name} is not responsible for any media
|
||||||
files shown by the video providers.
|
files shown by the video providers.
|
||||||
</p>
|
</p>
|
||||||
<p>© {website_name}. All rights reserved.</p>
|
<p>© 2026 <a href="https://justanime.site" className="hover:text-white/60 underline transition-colors">{website_name}</a>. All rights reserved.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ function Genre({ data }) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative pt-[20px] max-sm:pt-[15px]">
|
<div className="relative pt-2 max-sm:pt-[15px]">
|
||||||
<div className="relative flex items-center min-h-[32px] max-sm:min-h-[28px]">
|
<div className="relative flex items-center min-h-[32px] max-sm:min-h-[28px]">
|
||||||
{/* Content first for proper stacking */}
|
{/* Content first for proper stacking */}
|
||||||
<div
|
<div
|
||||||
ref={scrollContainerRef}
|
ref={scrollContainerRef}
|
||||||
className="absolute inset-0 overflow-x-auto no-scrollbar scroll-smooth"
|
className="absolute inset-0 overflow-x-auto no-scrollbar scroll-smooth"
|
||||||
style={{
|
style={{
|
||||||
@@ -51,7 +51,7 @@ function Genre({ data }) {
|
|||||||
|
|
||||||
{/* Left button and gradient */}
|
{/* Left button and gradient */}
|
||||||
<div className="relative z-20 flex items-center">
|
<div className="relative z-20 flex items-center">
|
||||||
<button
|
<button
|
||||||
onClick={() => scroll('left')}
|
onClick={() => scroll('left')}
|
||||||
className="bg-[#1a1a1a] hover:bg-[#252525] h-8 max-sm:h-7 w-8 max-sm:w-7 flex items-center justify-center rounded-[4px] transition-all duration-300 ease-in-out focus:outline-none active:scale-95"
|
className="bg-[#1a1a1a] hover:bg-[#252525] h-8 max-sm:h-7 w-8 max-sm:w-7 flex items-center justify-center rounded-[4px] transition-all duration-300 ease-in-out focus:outline-none active:scale-95"
|
||||||
>
|
>
|
||||||
@@ -68,7 +68,7 @@ function Genre({ data }) {
|
|||||||
{/* Right button and gradient */}
|
{/* Right button and gradient */}
|
||||||
<div className="relative z-20 flex items-center">
|
<div className="relative z-20 flex items-center">
|
||||||
<div className="h-8 max-sm:h-7 w-20 max-sm:w-12 bg-gradient-to-l from-[#0a0a0a] via-[#0a0a0a]/80 to-transparent max-sm:from-[#0a0a0a]/60 max-sm:via-[#0a0a0a]/40 pointer-events-none"></div>
|
<div className="h-8 max-sm:h-7 w-20 max-sm:w-12 bg-gradient-to-l from-[#0a0a0a] via-[#0a0a0a]/80 to-transparent max-sm:from-[#0a0a0a]/60 max-sm:via-[#0a0a0a]/40 pointer-events-none"></div>
|
||||||
<button
|
<button
|
||||||
onClick={() => scroll('right')}
|
onClick={() => scroll('right')}
|
||||||
className="bg-[#1a1a1a] hover:bg-[#252525] h-8 max-sm:h-7 w-8 max-sm:w-7 flex items-center justify-center rounded-[4px] transition-all duration-300 ease-in-out focus:outline-none active:scale-95"
|
className="bg-[#1a1a1a] hover:bg-[#252525] h-8 max-sm:h-7 w-8 max-sm:w-7 flex items-center justify-center rounded-[4px] transition-all duration-300 ease-in-out focus:outline-none active:scale-95"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ const Spotlight = ({ spotlights }) => {
|
|||||||
spaceBetween={0}
|
spaceBetween={0}
|
||||||
slidesPerView={1}
|
slidesPerView={1}
|
||||||
loop={true}
|
loop={true}
|
||||||
allowTouchMove={false}
|
allowTouchMove={true}
|
||||||
|
grabCursor={true}
|
||||||
navigation={{
|
navigation={{
|
||||||
nextEl: ".button-next",
|
nextEl: ".button-next",
|
||||||
prevEl: ".button-prev",
|
prevEl: ".button-prev",
|
||||||
@@ -31,7 +32,7 @@ const Spotlight = ({ spotlights }) => {
|
|||||||
disableOnInteraction: false,
|
disableOnInteraction: false,
|
||||||
}}
|
}}
|
||||||
modules={[Navigation, Autoplay, Pagination]}
|
modules={[Navigation, Autoplay, Pagination]}
|
||||||
className="h-[450px] max-[1390px]:h-full rounded-2xl overflow-hidden relative"
|
className="h-[450px] max-[1390px]:h-full rounded-md overflow-hidden relative"
|
||||||
style={{
|
style={{
|
||||||
"--swiper-pagination-bullet-inactive-color": "rgba(255, 255, 255, 0.5)",
|
"--swiper-pagination-bullet-inactive-color": "rgba(255, 255, 255, 0.5)",
|
||||||
"--swiper-pagination-bullet-inactive-opacity": "1",
|
"--swiper-pagination-bullet-inactive-opacity": "1",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import CategoryCard from "@/src/components/categorycard/CategoryCard.jsx";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { FaChevronRight } from "react-icons/fa";
|
import { FaChevronRight } from "react-icons/fa";
|
||||||
|
|
||||||
function TabbedAnimeSection({ topAiring, mostFavorite, latestCompleted, className = "" }) {
|
function TabbedAnimeSection({ topAiring, mostFavorite, latestCompleted, className = "", limit = 10 }) {
|
||||||
const [activeTab, setActiveTab] = useState("airing");
|
const [activeTab, setActiveTab] = useState("airing");
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
@@ -24,7 +24,7 @@ function TabbedAnimeSection({ topAiring, mostFavorite, latestCompleted, classNam
|
|||||||
key={tab.id}
|
key={tab.id}
|
||||||
onClick={() => setActiveTab(tab.id)}
|
onClick={() => setActiveTab(tab.id)}
|
||||||
className={`relative px-6 py-4 text-[15px] font-medium transition-all duration-300
|
className={`relative px-6 py-4 text-[15px] font-medium transition-all duration-300
|
||||||
${activeTab === tab.id
|
${activeTab === tab.id
|
||||||
? "text-white after:absolute after:bottom-0 after:left-0 after:w-full after:h-[2px] after:bg-primary after:rounded-t-full"
|
? "text-white after:absolute after:bottom-0 after:left-0 after:w-full after:h-[2px] after:bg-primary after:rounded-t-full"
|
||||||
: "text-[#ffffff80] hover:text-white"
|
: "text-[#ffffff80] hover:text-white"
|
||||||
}
|
}
|
||||||
@@ -55,8 +55,9 @@ function TabbedAnimeSection({ topAiring, mostFavorite, latestCompleted, classNam
|
|||||||
<CategoryCard
|
<CategoryCard
|
||||||
data={activeTabData.data}
|
data={activeTabData.data}
|
||||||
path={activeTabData.path}
|
path={activeTabData.path}
|
||||||
limit={12}
|
limit={limit}
|
||||||
showViewMore={false}
|
showViewMore={false}
|
||||||
|
cardStyle="grid-cols-5 max-[1400px]:grid-cols-4 max-[758px]:grid-cols-3 max-[478px]:grid-cols-3"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const Trending = ({ trending, className }) => {
|
|||||||
const { language } = useLanguage();
|
const { language } = useLanguage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`bg-[#141414] rounded-lg p-4 ${className}`}>
|
<div className={`bg-[#141414] rounded-lg py-4 px-1.5 ${className}`}>
|
||||||
<div className="flex items-center gap-2 mb-4">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
<FontAwesomeIcon icon={faFire} className="text-white/90" />
|
<FontAwesomeIcon icon={faFire} className="text-white/90" />
|
||||||
<h2 className="text-xl font-semibold text-white">Trending Now</h2>
|
<h2 className="text-xl font-semibold text-white">Trending Now</h2>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
import website_name from "@/src/config/website.js";
|
import website_name from "@/src/config/website.js";
|
||||||
import Spotlight from "@/src/components/spotlight/Spotlight.jsx";
|
import Spotlight from "@/src/components/spotlight/Spotlight.jsx";
|
||||||
import Trending from "@/src/components/trending/Trending.jsx";
|
import Trending from "@/src/components/trending/Trending.jsx";
|
||||||
@@ -19,6 +20,17 @@ import {
|
|||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
const { homeInfo, homeInfoLoading, error } = useHomeInfo();
|
const { homeInfo, homeInfoLoading, error } = useHomeInfo();
|
||||||
|
const [itemLimit, setItemLimit] = useState(window.innerWidth > 1400 ? 10 : 12);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleResize = () => {
|
||||||
|
setItemLimit(window.innerWidth > 1400 ? 10 : 12);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("resize", handleResize);
|
||||||
|
return () => window.removeEventListener("resize", handleResize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (homeInfoLoading) return <Loader type="home" />;
|
if (homeInfoLoading) return <Loader type="home" />;
|
||||||
if (error) return <Error />;
|
if (error) return <Error />;
|
||||||
if (!homeInfo) return <Error error="404" />;
|
if (!homeInfo) return <Error error="404" />;
|
||||||
@@ -63,26 +75,28 @@ function Home() {
|
|||||||
</div>
|
</div>
|
||||||
<ContinueWatching />
|
<ContinueWatching />
|
||||||
|
|
||||||
<div className="w-full grid grid-cols-[minmax(0,75%),minmax(0,25%)] gap-x-6 max-[1200px]:flex flex-col">
|
<div className="w-full grid grid-cols-[minmax(0,75%),minmax(0,25%)] gap-x-4 max-[1200px]:flex flex-col">
|
||||||
<div>
|
<div>
|
||||||
<CategoryCard
|
<CategoryCard
|
||||||
label="Latest Episode"
|
label="Latest Episode"
|
||||||
data={homeInfo.latest_episode}
|
data={homeInfo.latest_episode}
|
||||||
className="mt-[60px]"
|
className="mt-8"
|
||||||
path="recently-updated"
|
path="recently-updated"
|
||||||
limit={12}
|
limit={itemLimit}
|
||||||
|
cardStyle="grid-cols-5 max-[1400px]:grid-cols-4 max-[758px]:grid-cols-3 max-[478px]:grid-cols-3"
|
||||||
/>
|
/>
|
||||||
<Schedule className="mt-8" />
|
<Schedule className="mt-8" />
|
||||||
<TabbedAnimeSection
|
<TabbedAnimeSection
|
||||||
topAiring={homeInfo.top_airing}
|
topAiring={homeInfo.top_airing}
|
||||||
mostFavorite={homeInfo.most_favorite}
|
mostFavorite={homeInfo.most_favorite}
|
||||||
latestCompleted={homeInfo.latest_completed}
|
latestCompleted={homeInfo.latest_completed}
|
||||||
className="mt-8"
|
className="mt-4"
|
||||||
|
limit={itemLimit}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full mt-[60px]">
|
<div className="w-full mt-8">
|
||||||
<Trending trending={homeInfo.trending} />
|
<Trending trending={homeInfo.trending} />
|
||||||
<Topten data={homeInfo.topten} className="mt-12" />
|
<Topten data={homeInfo.topten} className="mt-8" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user