From 4c4f8214637ac8d19e16f71d20542982a5eedad7 Mon Sep 17 00:00:00 2001 From: real-zephex Date: Sat, 11 May 2024 01:33:00 +0530 Subject: UI changes, Logic change and complete re-write for anime page --- src/app/anime/[id]/buttons.jsx | 153 ----------------- src/app/anime/[id]/info.module.css | 187 --------------------- src/app/anime/[id]/loading.jsx | 9 - src/app/anime/[id]/loading.module.css | 22 --- src/app/anime/[id]/page.jsx | 116 +++++++------ src/app/anime/anime.module.css | 3 - src/app/anime/components/cacher.js | 29 ++++ src/app/anime/components/episode_buttons.jsx | 131 +++++++++++++++ src/app/anime/components/popularAnimes.jsx | 51 ++++++ src/app/anime/components/recentEpisodes.jsx | 54 ++++++ src/app/anime/components/search.jsx | 49 ++++++ src/app/anime/components/search_results.jsx | 42 +++++ src/app/anime/components/topAiring.jsx | 54 ++++++ src/app/anime/data-fetch/request.js | 54 ++++++ .../anime/history/continueWatching/cw.module.css | 59 ------- src/app/anime/history/continueWatching/page.jsx | 65 ------- src/app/anime/history/storeData.js | 35 ---- src/app/anime/page.jsx | 33 ++-- src/app/anime/popular/page.jsx | 52 ------ src/app/anime/recent/page.jsx | 52 ------ src/app/anime/search/components/fetchInfo.js | 14 -- src/app/anime/search/components/fetchedInfo.js | 45 ----- src/app/anime/search/page.jsx | 69 -------- src/app/anime/search/search.module.css | 114 ------------- src/app/anime/styles/anime.module.css | 4 + src/app/anime/styles/buttons.module.css | 87 ++++++++++ src/app/anime/styles/info.module.css | 55 ++++++ src/app/anime/styles/pop_recent_top.module.css | 60 +++++++ src/app/anime/styles/search.module.css | 77 +++++++++ src/app/anime/top-airing/page.jsx | 52 ------ src/app/anime/top-airing/trending.module.css | 79 --------- src/app/anime/videoLinkfetcher.js | 46 ----- 32 files changed, 825 insertions(+), 1127 deletions(-) delete mode 100644 src/app/anime/[id]/buttons.jsx delete mode 100644 src/app/anime/[id]/info.module.css delete mode 100644 src/app/anime/[id]/loading.jsx delete mode 100644 src/app/anime/[id]/loading.module.css delete mode 100644 src/app/anime/anime.module.css create mode 100644 src/app/anime/components/cacher.js create mode 100644 src/app/anime/components/episode_buttons.jsx create mode 100644 src/app/anime/components/popularAnimes.jsx create mode 100644 src/app/anime/components/recentEpisodes.jsx create mode 100644 src/app/anime/components/search.jsx create mode 100644 src/app/anime/components/search_results.jsx create mode 100644 src/app/anime/components/topAiring.jsx create mode 100644 src/app/anime/data-fetch/request.js delete mode 100644 src/app/anime/history/continueWatching/cw.module.css delete mode 100644 src/app/anime/history/continueWatching/page.jsx delete mode 100644 src/app/anime/history/storeData.js delete mode 100644 src/app/anime/popular/page.jsx delete mode 100644 src/app/anime/recent/page.jsx delete mode 100644 src/app/anime/search/components/fetchInfo.js delete mode 100644 src/app/anime/search/components/fetchedInfo.js delete mode 100644 src/app/anime/search/page.jsx delete mode 100644 src/app/anime/search/search.module.css create mode 100644 src/app/anime/styles/anime.module.css create mode 100644 src/app/anime/styles/buttons.module.css create mode 100644 src/app/anime/styles/info.module.css create mode 100644 src/app/anime/styles/pop_recent_top.module.css create mode 100644 src/app/anime/styles/search.module.css delete mode 100644 src/app/anime/top-airing/page.jsx delete mode 100644 src/app/anime/top-airing/trending.module.css delete mode 100644 src/app/anime/videoLinkfetcher.js (limited to 'src') diff --git a/src/app/anime/[id]/buttons.jsx b/src/app/anime/[id]/buttons.jsx deleted file mode 100644 index c1b4615..0000000 --- a/src/app/anime/[id]/buttons.jsx +++ /dev/null @@ -1,153 +0,0 @@ -"use client"; - -import styles from "./info.module.css"; -import { useState, useEffect } from "react"; -import { fetch_video_link } from "../videoLinkfetcher"; -import { MediaPlayer, MediaProvider } from "@vidstack/react"; -import "@vidstack/react/player/styles/default/theme.css"; -import "@vidstack/react/player/styles/default/layouts/video.css"; -import { - defaultLayoutIcons, - DefaultVideoLayout, -} from "@vidstack/react/player/layouts/default"; -import { storeLocal } from "../history/storeData"; - -export default function Button({ data2: info }) { - const currentDate = new Date(); - const [videoLink, setVideoLink] = useState(null); - const [buttonGroups, setButtonGroups] = useState(null); - - useEffect(() => { - create_button_group(0, 50); - }, []); - - const groups = createGroups(info.episodes, 50); - - async function video(id) { - const link = await fetch_video_link(id); - if (link === undefined) { - alert("Sorry, but not links were found"); - } else { - setVideoLink(link); - } - } - - function createGroups(array, size) { - const groups = []; - for (let i = 0; i < array.length; i += size) { - groups.push(array.slice(i, i + size)); - } - return groups; - } - - function store_to_local(name, image, episode, id) { - let newData = { - name: name, - image: image, - episode: episode, - id: id, - type: "anime", - date: `${currentDate.getDate()}-${String( - currentDate.getMonth() + 1 - ).padStart(2, "0")}`, - time: `${currentDate.getHours()}:${String( - currentDate.getMinutes() - ).padStart(2, "0")}`, - }; - storeLocal(newData); - } - - function create_button_group(start, end) { - setButtonGroups( -
- {info.episodes && - info.episodes.slice(start, end).map((item, index) => ( - - ))} -
- ); - } - - function handleSelectChange(event) { - const selectedIndex = event.target.selectedIndex; - const selectedGroup = groups[selectedIndex]; - if (selectedGroup) { - create_button_group( - selectedGroup[0].number - 1, - selectedGroup[selectedGroup.length - 1].number - ); - } - } - - return ( -
-

Episodes:

- {info.episodes && ( - - )} - {buttonGroups} - {videoLink && ( - - )} -
- ); -} diff --git a/src/app/anime/[id]/info.module.css b/src/app/anime/[id]/info.module.css deleted file mode 100644 index fd14d32..0000000 --- a/src/app/anime/[id]/info.module.css +++ /dev/null @@ -1,187 +0,0 @@ -.dramaInfoContainer { - display: flex; - flex-direction: column; -} - -.dramaInfo { - display: flex; - flex-direction: column; - width: 98%; - margin: 80px auto; -} - -.titleContainer { - display: flex; - justify-content: space-between; - align-items: center; -} - -.titleContainer p { - color: var(--neon-green); - width: 60%; - font-weight: 500; - font-size: 34px; -} - -.titleContainer img { - aspect-ratio: 16 / 9; - border-radius: 10px; -} - -.animeDescription h2 { - color: #ffffff81; - margin: 20px 0px -10px 0px; -} - -.animeDescription p { - color: rgba(255, 255, 255, 0.637); -} - -.SelectClass { - background-color: #272727; - color: white; - font-family: "Lexend Deca", serif; - border: none; - outline: none; - padding: 0.5rem; - border-radius: 0.5rem; - text-align: center; -} - -.SelectClass::-webkit-scrollbar { - width: 0; -} - -.SelectClass option:checked { - background-color: rgb(0, 160, 223); -} - -.buttonContainer { - margin: 0px; - height: 200px; - overflow-y: auto; - border-radius: 10px; -} - -.buttonHeader { - margin: 0px 10px 10px 0px; - color: #ffffff81; -} - -.buttonContainer button { - transition: transform 200ms ease-in-out; -} - -.buttonContainer button:focus { - opacity: 0.7; - transition: transform 200ms ease-in; - background-color: var(--soft-purple); - transform: scale(0.9); -} - -.buttonContainer::-webkit-scrollbar { - width: 5px; -} - -.buttonContainer::-webkit-scrollbar-thumb { - background-color: var(--soft-purple); - border-radius: 1rem; -} - -.dramaButton { - padding: 10px; - font-family: "Lexend Deca", serif; - margin: 0.5rem 0.5rem 0px 0px; - width: 55px; - border-radius: 5px; - text-align: center; - border: none; - outline: none; - color: white; - background-color: #3d3d3d; - transition: background-color 200ms ease-in-out; - cursor: pointer; -} - -.dramaButton:hover { - background-color: #1f1f1f; - transition: background-color 200ms ease-in; -} - -.infoPageContainer p { - color: white; -} - -.animeDetails { - color: white; -} - -.genreEntries { - margin: 3px; - padding: 4px; - border-radius: 5px; - color: var(--neon-yellow); - background-color: #303030; -} - -.animeType span { - color: var(--light-green); -} - -.animeRelease span { - color: var(--soft-purple); -} - -.videoPopUp { - height: 100dvh; - width: 100dvw; - background-color: #141414ee; - position: fixed; - bottom: 0; - left: 0; - right: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - z-index: 1; - overflow-y: auto; -} - -.closeButton { - font-family: "Lexend Deca", serif; - font-size: 16px; - background-color: var(--pastel-red); - padding: 0.5rem 1.5rem; - border: 0; - outline: 0; - border-radius: 0.5rem; - cursor: pointer; - margin: 5px; -} - -.video { - width: 60vw; -} - -.VideoPlayer { - width: 100%; -} - -@media screen and (max-width: 768px) { - .titleContainer p { - font-size: 28px; - } - - .animeDetails { - font-size: 14px; - } - - .video { - width: 100%; - } - - .buttonContainer { - text-align: center; - } -} diff --git a/src/app/anime/[id]/loading.jsx b/src/app/anime/[id]/loading.jsx deleted file mode 100644 index 12876eb..0000000 --- a/src/app/anime/[id]/loading.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import styles from "./loading.module.css"; - -export default async function Loading() { - return ( -
-
-
- ); -} diff --git a/src/app/anime/[id]/loading.module.css b/src/app/anime/[id]/loading.module.css deleted file mode 100644 index a9feceb..0000000 --- a/src/app/anime/[id]/loading.module.css +++ /dev/null @@ -1,22 +0,0 @@ -.Main { - height: 100vh; - width: 100vw; - display: flex; - justify-content: center; - align-items: center; -} - -.LoadingContainer { - width: 50px; - height: 50px; - border-radius: 50%; - border: 8px solid; - border-color: #f4f4f4 #0000; - animation: s1 1s infinite; -} - -@keyframes s1 { - to { - transform: rotate(0.5turn); - } -} diff --git a/src/app/anime/[id]/page.jsx b/src/app/anime/[id]/page.jsx index d133118..7368e96 100644 --- a/src/app/anime/[id]/page.jsx +++ b/src/app/anime/[id]/page.jsx @@ -1,68 +1,74 @@ -import styles from "./info.module.css"; import Image from "next/image"; -import Button from "./buttons"; -import { preFetchAnimeLinks } from "../videoLinkfetcher"; -export default async function AnimeInfo({ params }) { - let animeID = params.id; +import { anime_info } from "../data-fetch/request"; +import styles from "../styles/info.module.css"; +import EpisodesButtons from "../components/episode_buttons"; - const info = await getAnimeInfo(animeID); +import { preFetchVideoLinks } from "../components/cacher"; - preFetchAnimeLinks(info); +const AnimeInfoHomepage = async ({ params }) => { + const id = params.id; + const data = await anime_info(id); + + preFetchVideoLinks(data); return ( -
-
- {info && ( -
-
-

{info.title}

+
+
+ {data && ( +
+
Drama +
+

+ {data.title} +

+

+ Description: + {data.description} +

+
+ + + Genres: + + {data.genres && + data.genres.map((item, index) => ( + + {item} + {index !== + data.genres.length - 1 && + ", "} + + ))} + +

+ Episodes:{" "} + {data.totalEpisodes} +

+

+ Release year:{" "} + {data.releaseDate} +

+

+ Status: {data.status} +

+

+ Type: {data.type} +

+
-
-

Description

-

{info.description}

-
-
+ )} - -
- Genres: - {info.genres && - info.genres.map((item, index) => ( - - {item} - - ))} -

- Type: {info && info.type} -

-

- Release year: - - {" "} - {info && info.releaseDate}, {info && info.status} - -

-
- -
-
+ + ); -} +}; -async function getAnimeInfo(anime_id) { - const res = await fetch( - "https://consumet-jade.vercel.app/anime/gogoanime/info/" + anime_id, - { next: { revalidate: 7200 } } - ); - const data = await res.json(); - return data; -} +export default AnimeInfoHomepage; diff --git a/src/app/anime/anime.module.css b/src/app/anime/anime.module.css deleted file mode 100644 index 72c6fde..0000000 --- a/src/app/anime/anime.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.main { - margin: 50px auto; -} diff --git a/src/app/anime/components/cacher.js b/src/app/anime/components/cacher.js new file mode 100644 index 0000000..acc780a --- /dev/null +++ b/src/app/anime/components/cacher.js @@ -0,0 +1,29 @@ +"use server"; + +import { info_url, watch_url } from "../../../../utils/anime_urls"; + +export async function preFetchAnimeInfo(data) { + try { + const fetchPromises = data.results.map(async (element) => { + await fetch(info_url(element.id), { next: { revalidate: 21600 } }); + }); + + await Promise.all(fetchPromises); + console.log("Anime info pre-fetched successfully!"); + } catch (error) { + console.error("Error occurred while pre-fetching anime info: ", error); + } +} + +export async function preFetchVideoLinks(data) { + try { + const fetchPromises = data.episodes.map(async (element) => { + await fetch(watch_url(element.id), { next: { revalidate: 21600 } }); + }); + + await Promise.all(fetchPromises); + console.log("Anime video links info pre-fetched successfully!"); + } catch (error) { + console.error("Error occurred while pre-fetching anime info: ", error); + } +} diff --git a/src/app/anime/components/episode_buttons.jsx b/src/app/anime/components/episode_buttons.jsx new file mode 100644 index 0000000..f76704f --- /dev/null +++ b/src/app/anime/components/episode_buttons.jsx @@ -0,0 +1,131 @@ +"use client"; +import { useState, useEffect } from "react"; +import { MediaPlayer, MediaProvider } from "@vidstack/react"; +import "@vidstack/react/player/styles/default/theme.css"; +import "@vidstack/react/player/styles/default/layouts/video.css"; +import { + defaultLayoutIcons, + DefaultVideoLayout, +} from "@vidstack/react/player/layouts/default"; + +import styles from "../styles/buttons.module.css"; +import { video_url } from "../data-fetch/request"; + +const EpisodesButtons = ({ data: data }) => { + const [videoLink, setVideoLink] = useState(null); + const [buttonGroups, setButtonGroups] = useState(null); + const [videoLoading, setVideoLoading] = useState(null); + + useEffect(() => { + setButtonGroups(createButtonGroups(0, 50)); + }, []); + + const groups = createGroups(data.episodes, 50); + + async function getVideoURL(epID) { + setVideoLoading(true); + const data = await video_url(epID); + setVideoLink(data.sources[data.sources.length - 2].url); + setVideoLoading(false); + } + + function createButtonGroups(start, end) { + return ( +
+ {data.episodes && + data.episodes.slice(start, end).map((item, index) => ( + + ))} +
+ ); + } + + function handleSelectChange(event) { + const selectedIndex = event.target.selectedIndex; + const selectedGroup = groups[selectedIndex]; + if (selectedGroup) { + setButtonGroups( + createButtonGroups( + selectedGroup[0].number - 1, + selectedGroup[selectedGroup.length - 1].number + ) + ); + } + } + + return ( +
+ {data.episodes && ( + + )} + {buttonGroups} + {videoLoading && ( +

Loading...

+ )} + {videoLink && ( + + )} +
+ ); +}; + +function createGroups(array, size) { + const groups = []; + for (let i = 0; i < array.length; i += size) { + groups.push(array.slice(i, i + size)); + } + return groups; +} + +export default EpisodesButtons; diff --git a/src/app/anime/components/popularAnimes.jsx b/src/app/anime/components/popularAnimes.jsx new file mode 100644 index 0000000..2259a42 --- /dev/null +++ b/src/app/anime/components/popularAnimes.jsx @@ -0,0 +1,51 @@ +import Link from "next/link"; +import Image from "next/image"; +import { Atkinson_Hyperlegible } from "next/font/google"; + +import styles from "../styles/pop_recent_top.module.css"; +import { popular, anime_info } from "../data-fetch/request"; +import { preFetchAnimeInfo, preFetchVideoLinks } from "./cacher"; + +const atkinson = Atkinson_Hyperlegible({ subsets: ["latin"], weight: "400" }); + +const PopularAnimes = async () => { + const data = await popular(); + + preFetchAnimeInfo(data); + + return ( +
+
+

Popular Animes

+
+ {data && + data.results.map((item, index) => ( + +
+ Anime Poster Image +

{item.title}

+
+ + ))} +
+
+
+ ); +}; + +export default PopularAnimes; diff --git a/src/app/anime/components/recentEpisodes.jsx b/src/app/anime/components/recentEpisodes.jsx new file mode 100644 index 0000000..43ad1de --- /dev/null +++ b/src/app/anime/components/recentEpisodes.jsx @@ -0,0 +1,54 @@ +import Link from "next/link"; +import Image from "next/image"; +import { Atkinson_Hyperlegible } from "next/font/google"; + +import styles from "../styles/pop_recent_top.module.css"; +import { recent } from "../data-fetch/request"; +import { preFetchAnimeInfo } from "./cacher"; + +const atkinson = Atkinson_Hyperlegible({ subsets: ["latin"], weight: "400" }); + +const RecentAnimes = async () => { + const data = await recent(); + + preFetchAnimeInfo(data); + + return ( +
+
+

Recent Releases

+
+ {data && + data.results.map((item, index) => ( + +
+ Anime Poster Image +

{item.title}

+

+ Episode: {item.episodeNumber} +

+
+ + ))} +
+
+
+ ); +}; + +export default RecentAnimes; diff --git a/src/app/anime/components/search.jsx b/src/app/anime/components/search.jsx new file mode 100644 index 0000000..7bb22ba --- /dev/null +++ b/src/app/anime/components/search.jsx @@ -0,0 +1,49 @@ +"use client"; + +import { FaSearch } from "react-icons/fa"; +import { useState } from "react"; + +import styles from "../styles/search.module.css"; +import SearchResults from "./search_results"; + +const SearcBar = () => { + const [title, setTitle] = useState(""); + const [searchResults, setSearchResults] = useState(null); + + const handleSearchInput = async (title) => { + setSearchResults(await SearchResults(title)); + }; + + return ( +
+
+
+ + { + if (event.target.value.trim() != "") { + setTitle(event.target.value); + } + }} + autoComplete="off" + onKeyDown={async (event) => { + if ( + event.code === "Enter" || + event.key === "Enter" || + event.code === 13 + ) { + await handleSearchInput(title); + } + }} + > +
+
+ {searchResults} +
+ ); +}; + +export default SearcBar; diff --git a/src/app/anime/components/search_results.jsx b/src/app/anime/components/search_results.jsx new file mode 100644 index 0000000..d4c8146 --- /dev/null +++ b/src/app/anime/components/search_results.jsx @@ -0,0 +1,42 @@ +import { Atkinson_Hyperlegible } from "next/font/google"; +import Link from "next/link"; +import Image from "next/image"; + +import styles from "../styles/search.module.css"; +import { search_results } from "../data-fetch/request"; +import { preFetchAnimeInfo } from "./cacher"; + +const atkinson = Atkinson_Hyperlegible({ subsets: ["latin"], weight: "400" }); + +const SearchResults = async (title) => { + const data = await search_results(title); + + preFetchAnimeInfo(data); + + return ( +
+ {data && + data.results.map((item, index) => ( + +
+

{item.title}

+ Anime Poster +
+ + ))} +
+ ); +}; + +export default SearchResults; diff --git a/src/app/anime/components/topAiring.jsx b/src/app/anime/components/topAiring.jsx new file mode 100644 index 0000000..28d3f6d --- /dev/null +++ b/src/app/anime/components/topAiring.jsx @@ -0,0 +1,54 @@ +import Link from "next/link"; +import Image from "next/image"; +import { Atkinson_Hyperlegible } from "next/font/google"; + +import styles from "../styles/pop_recent_top.module.css"; +import { top_airing } from "../data-fetch/request"; +import { preFetchAnimeInfo } from "./cacher"; + +const atkinson = Atkinson_Hyperlegible({ subsets: ["latin"], weight: "400" }); + +const TopAiringAnimes = async () => { + const data = await top_airing(); + + preFetchAnimeInfo(data); + + return ( +
+
+

Top Airing Animes

+
+ {data && + data.results.map((item, index) => ( + +
+ Anime Poster Image +

{item.title}

+

+ Episode: {item.episodeNumber} +

+
+ + ))} +
+
+
+ ); +}; + +export default TopAiringAnimes; diff --git a/src/app/anime/data-fetch/request.js b/src/app/anime/data-fetch/request.js new file mode 100644 index 0000000..3d22b7a --- /dev/null +++ b/src/app/anime/data-fetch/request.js @@ -0,0 +1,54 @@ +"use server"; + +import { + popular_url, + recent_epsiodes_url, + top_airing_url, + search_url, + info_url, + watch_url, +} from "../../../../utils/anime_urls"; + +export const popular = async () => { + const res = await fetch(popular_url, { next: { revalidate: 21600 } }); + const data = await res.json(); + return data; +}; + +export const recent = async () => { + const res = await fetch(recent_epsiodes_url, { + next: { revalidate: 21600 }, + }); + const data = await res.json(); + return data; +}; + +export const top_airing = async () => { + const res = await fetch(top_airing_url, { next: { revalidate: 21600 } }); + const data = await res.json(); + return data; +}; + +export const search_results = async (title) => { + const res = await fetch(search_url(title), { + next: { revalidate: 21600 }, + }); + const data = await res.json(); + return data; +}; + +export const anime_info = async (id) => { + const res = await fetch(info_url(id), { + next: { revalidate: 21600 }, + }); + const data = await res.json(); + return data; +}; + +export const video_url = async (episodeId) => { + const res = await fetch(watch_url(episodeId), { + next: { revalidate: 21600 }, + }); + const data = await res.json(); + return data; +}; diff --git a/src/app/anime/history/continueWatching/cw.module.css b/src/app/anime/history/continueWatching/cw.module.css deleted file mode 100644 index cf79acc..0000000 --- a/src/app/anime/history/continueWatching/cw.module.css +++ /dev/null @@ -1,59 +0,0 @@ -.main { - width: 99%; - margin: 80px auto; -} - -.mainText { - color: var(--light-green); - font-size: 24px; -} - -.animeContainer { - font-size: 18px; - margin: 0px; -} - -.animeEntry { - display: flex; - align-items: center; - justify-content: space-between; - padding: 5px; - margin-bottom: 0.5rem; - border-radius: 1rem; - background-color: #1f1f1f; -} - -.animeEntry img { - width: 10%; - height: auto; - border-radius: 0.8rem; -} - -.titleContainer { - color: white; - margin-left: 0.2rem; -} - -.titleContainer h3 { - margin: 0px; -} - -.EpisodeCount { - color: var(--soft-purple); - margin: 0px; -} - -.date { - color: var(--neon-yellow); - margin: 0px; -} - -@media screen and (max-width: 768px) { - .animeContainer { - font-size: 14px; - } - - .animeEntry img { - width: 35%; - } -} diff --git a/src/app/anime/history/continueWatching/page.jsx b/src/app/anime/history/continueWatching/page.jsx deleted file mode 100644 index ecb73fc..0000000 --- a/src/app/anime/history/continueWatching/page.jsx +++ /dev/null @@ -1,65 +0,0 @@ -"use client"; - -import React, { useState, useEffect } from "react"; -import Image from "next/image"; -import styles from "./cw.module.css"; -import Link from "next/link"; - -const ContinueWatching = () => { - const [localItems, setLocalItems] = useState(null); - - useEffect(() => { - const newData = get_local(); - setLocalItems(newData); - }, []); // Empty dependency array means this effect runs only once after the initial render - - function get_local() { - try { - const data = localStorage.getItem("data"); - return JSON.parse(data); - } catch (error) { - console.log("error", error); - return false; - } - } - - return ( -
-

Continue Watching

- {localItems && ( -
- {localItems.watchHis && - localItems.watchHis.map((item, index) => ( - -
-
-

{item.name}

-

- Episode watching: {item.episode} -

-

- Last watched on: {item.date} at{" "} - {item.time} hours -

-
- Continue anime poster -
- - ))} -
- )} -
- ); -}; - -export default ContinueWatching; diff --git a/src/app/anime/history/storeData.js b/src/app/anime/history/storeData.js deleted file mode 100644 index 4008095..0000000 --- a/src/app/anime/history/storeData.js +++ /dev/null @@ -1,35 +0,0 @@ -"use client"; - -export function storeLocal(watchData) { - const currentDate = new Date(); - const jsonData = localStorage.getItem("data"); - const dataObject = jsonData ? JSON.parse(jsonData) : {}; - - if (!dataObject.watchHis) { - dataObject.watchHis = []; - } - - let found = false; - dataObject.watchHis.forEach((element) => { - if (element.name === watchData.name) { - let episode = watchData.episode; - let date = `${currentDate.getDate()}-${String( - currentDate.getMonth() + 1 - ).padStart(2, "0")}`; - let time = `${currentDate.getHours()}:${String( - currentDate.getMinutes() - ).padStart(2, "0")}`; - element.episode = episode; - element.date = date; - element.time = time; - found = true; - } - }); - - if (!found) { - dataObject.watchHis.push(watchData); - } - - let updatedData = JSON.stringify(dataObject); - localStorage.setItem("data", updatedData); -} diff --git a/src/app/anime/page.jsx b/src/app/anime/page.jsx index 8fdbf86..209105b 100644 --- a/src/app/anime/page.jsx +++ b/src/app/anime/page.jsx @@ -1,18 +1,19 @@ -import styles from "./anime.module.css"; -import Trending from "./top-airing/page"; -import Releases from "./recent/page"; -import Popular from "./popular/page"; -import Input from "./search/page"; - -export default async function Anime() { +import styles from "./styles/anime.module.css"; +import PopularAnimes from "./components/popularAnimes"; +import RecentAnimes from "./components/recentEpisodes"; +import TopAiringAnimes from "./components/topAiring"; +import SearcBar from "./components/search"; +const AnimeHomepage = async () => { return ( -
- - -
- -
- -
+
+ + +
+ +
+ +
); -} +}; + +export default AnimeHomepage; diff --git a/src/app/anime/popular/page.jsx b/src/app/anime/popular/page.jsx deleted file mode 100644 index 3ddd251..0000000 --- a/src/app/anime/popular/page.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import styles from "../top-airing/trending.module.css"; -import Image from "next/image"; -import Link from "next/link"; -import { preFetchAnimeInfo } from "../videoLinkfetcher"; - -export default async function Popular() { - const data = await test(); - preFetchAnimeInfo(data); - - return ( -
-
-

Popular

-
- -
- {data && - data.results.map((item, index) => ( - -
- Drama -

{item.title}

-
- - ))} -
-
- ); -} - -async function test() { - const res = await fetch( - "https://consumet-jade.vercel.app/anime/gogoanime/popular", - { next: { revalidate: 21600 } } - ); - const data = res.json(); - return data; -} diff --git a/src/app/anime/recent/page.jsx b/src/app/anime/recent/page.jsx deleted file mode 100644 index 44aa301..0000000 --- a/src/app/anime/recent/page.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import Image from "next/image"; -import Link from "next/link"; -import styles from "../top-airing/trending.module.css"; -import { preFetchAnimeInfo } from "../videoLinkfetcher"; - -export default async function Recent() { - const data = await test(); - preFetchAnimeInfo(data); - - return ( -
-
-

Recent Releases

-
- -
- {data && - data.results.map((item, index) => ( - -
- Drama -

{item.title}

-
- - ))} -
-
- ); -} - -async function test() { - const res = await fetch( - "https://consumet-jade.vercel.app/anime/gogoanime/recent-episodes", - { next: { revalidate: 21600 } } - ); - const data = res.json(); - return data; -} diff --git a/src/app/anime/search/components/fetchInfo.js b/src/app/anime/search/components/fetchInfo.js deleted file mode 100644 index 2f81345..0000000 --- a/src/app/anime/search/components/fetchInfo.js +++ /dev/null @@ -1,14 +0,0 @@ -"use server"; - -export default async function Results(id) { - return await testFunction(id); -} - -async function testFunction(title) { - const res = await fetch( - "https://consumet-jade.vercel.app/anime/gogoanime/" + title, - { next: { revalidate: 21600 } } - ); - const data = await res.json(); - return data; -} diff --git a/src/app/anime/search/components/fetchedInfo.js b/src/app/anime/search/components/fetchedInfo.js deleted file mode 100644 index 359e745..0000000 --- a/src/app/anime/search/components/fetchedInfo.js +++ /dev/null @@ -1,45 +0,0 @@ -import styles from "../search.module.css"; -import Link from "next/link"; -import Image from "next/image"; -import { preFetchAnimeInfo } from "../../videoLinkfetcher"; - -export default async function fetchedInfo(data) { - preFetchAnimeInfo(data); - return ( -
- {data ? ( - data.results && data.results.length > 0 ? ( - data.results.map((item, index) => ( - -
-

{item.title}

- Drama Poster -
- - )) - ) : ( -
-

- No results found -

-
- ) - ) : null} -
- ); -} diff --git a/src/app/anime/search/page.jsx b/src/app/anime/search/page.jsx deleted file mode 100644 index f543fd8..0000000 --- a/src/app/anime/search/page.jsx +++ /dev/null @@ -1,69 +0,0 @@ -"use client"; - -import styles from "./search.module.css"; -import { FaSearch } from "react-icons/fa"; // Import the search icon from react-icons library -import { useState } from "react"; -import Results from "./components/fetchInfo"; -import fetchedInfo from "./components/fetchedInfo"; -import Link from "next/link"; - -export default function Input() { - const [searchedAnime, setSearchedAnime] = useState(null); - const [loading, setLoading] = useState(null); - const [info, setInfo] = useState(null); - - const handleKeyPress = async (event) => { - if ( - (event.code === "Enter" || - event.key === "Enter" || - event.code === 13) && - searchedAnime !== "" - ) { - setLoading(true); - setInfo(await fetchedInfo(await Results(searchedAnime))); - setLoading(false); - } else if ( - (event.code === "Enter" || - event.key === "Enter" || - event.code === 13) && - searchedAnime === "" - ) { - alert("Input cannot be empty"); - } - }; - - return ( -
-
-
- - { - if (event.target.value.trim() !== "") { - setSearchedAnime(event.target.value); - } - }} - onKeyDown={(event) => handleKeyPress(event)} - placeholder="Enter anime title" - className={styles.SearchInput} - > -
-
- -
-
- - {loading && ( -

- Please wait while we crunch all the data for you -

- )} - - {info} -
- ); -} diff --git a/src/app/anime/search/search.module.css b/src/app/anime/search/search.module.css deleted file mode 100644 index a185e36..0000000 --- a/src/app/anime/search/search.module.css +++ /dev/null @@ -1,114 +0,0 @@ -.waitWhileLoading { - font-size: 18px; - text-align: center; - color: white; -} - -.inputContainer { - display: flex; - align-items: center; - margin: 0 0.3rem 0 0.3rem; -} - -.inputContainer button { - margin: 5px; - background-color: #121212; - padding: 10px; - border-radius: 10px; - outline: none; - border: none; - color: white; - font-family: "Lexend Deca", serif; -} - -.inputContainer button a { - text-decoration: none; - color: white; -} - -.searchContainer input { - border: none; - border-radius: 5px; - color: white; - outline: none; - background: none; - width: 100%; - font-family: "Lexend Deca", serif; - font-size: 16px; -} - -.searchContainer { - display: flex; - align-items: center; - justify-content: center; - margin: 20px 0px 20px 0px; - background-color: #121212; - padding: 10px; - border-radius: 10px; - width: 30%; -} - -.searchIcon { - color: white; - margin-right: 5px; -} - -.animeEntry { - display: flex; - overflow-x: auto; - margin: 0 0 1rem 0.5rem; -} - -.animeEntry:hover .anime { - opacity: 0.5; -} - -.animeEntry:hover .anime:hover { - opacity: 1; - background-color: #292929; -} - -.animeEntry::-webkit-scrollbar { - height: 5px; -} - -.animeEntry::-webkit-scrollbar-track { - background-color: #636363; - border-radius: 5px; -} - -.animeEntry::-webkit-scrollbar-thumb { - background-color: rgba(196, 196, 196, 0.692); - border-radius: 5px; -} - -.anime { - display: flex; - justify-content: space-between; - align-items: center; - padding: 5px; - margin: 0 10px 0 0; - border-radius: 0.5rem; - transition: opacity 200ms ease-in, background-color 200ms linear; - background-color: #242424d0; -} - -.anime p { - color: white; - width: 20dvw; - font-size: 18px; -} - -.animeImage { - border-radius: 0.5rem; -} - -@media screen and (max-width: 768px) { - .searchContainer { - width: 100%; - } - - .anime p { - width: 50dvw; - } -} \ No newline at end of file diff --git a/src/app/anime/styles/anime.module.css b/src/app/anime/styles/anime.module.css new file mode 100644 index 0000000..e5d402a --- /dev/null +++ b/src/app/anime/styles/anime.module.css @@ -0,0 +1,4 @@ +.Main { + max-width: 99%; + margin: 65px auto; +} \ No newline at end of file diff --git a/src/app/anime/styles/buttons.module.css b/src/app/anime/styles/buttons.module.css new file mode 100644 index 0000000..d092a7f --- /dev/null +++ b/src/app/anime/styles/buttons.module.css @@ -0,0 +1,87 @@ +.animeButtonContainer { + margin-top: 1rem; +} + +.dramaButton { + background-color: #1f1f1fd2; + outline: none; + border: none; + color: white; + font-family: "Atkinson Hyperlegible", serif; + width: 50px; + padding: 0.5rem; + margin: 0 0.2rem 0.2rem 0; + border-radius: 0.5rem; + cursor: pointer; + transition: background-color 200ms ease, scale 200ms ease; +} + +.dramaButton:hover { + background-color: #121212; + scale: 0.95; +} + +.dramaButton:focus { + background-color: var(--soft-purple); + scale: 0.95; +} + +.Main { + display: flex; + align-items: center; + flex-direction: column; + text-align: center; +} + +.SelectClass { + text-align: center; + outline: none; + border: none; + padding: 0.4rem; + font-family: "Lexend Deca", serif; + background-color: #1f1f1fd2; + color: white; + border-radius: 0.5rem; +} + +.SelectClass::-webkit-scrollbar { + width: 0; +} + +/* Video Player */ + +.videoPopUp { + height: 100dvh; + width: 100dvw; + background-color: #141414ee; + position: fixed; + bottom: 0; + left: 0; + right: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + z-index: 1; + overflow-y: auto; +} + +.closeButton { + font-family: "Lexend Deca", serif; + font-size: 16px; + background-color: var(--pastel-red); + padding: 0.5rem 1.5rem; + border: 0; + outline: 0; + border-radius: 0.5rem; + cursor: pointer; + margin: 5px; +} + +.video { + width: 60vw; +} + +.VideoPlayer { + width: 100%; +} \ No newline at end of file diff --git a/src/app/anime/styles/info.module.css b/src/app/anime/styles/info.module.css new file mode 100644 index 0000000..4e65bdd --- /dev/null +++ b/src/app/anime/styles/info.module.css @@ -0,0 +1,55 @@ +.main { + width: 50%; + margin: 60px auto; + color: white; +} + +.AnimeHeroSection { + display: flex; + align-items: center; +} + +.AnimeHeroSection img { + padding: 0.5rem 0.7rem 0rem 0; +} + +.animeDescription { + max-height: 100px; + overflow: auto; +} + +.animeDescription::-webkit-scrollbar { + width: 4px; +} + +.animeDescription::-webkit-scrollbar-thumb { + background-color: gray; + border-radius: 1rem; +} + +.AnimeHeroSection p { + margin: 0; +} + +.animeTitle { + font-size: 28px; + color: var(--neon-green); +} + +@media screen and (max-width: 1024px) { + .main { + width: 100%; + } + + .AnimeHeroSection { + font-size: 14px; + } + + .animeTitle { + font-size: 24px; + } + + .AnimeHeroSection img { + padding: 0.4rem 0.4rem 0 0; + } +} \ No newline at end of file diff --git a/src/app/anime/styles/pop_recent_top.module.css b/src/app/anime/styles/pop_recent_top.module.css new file mode 100644 index 0000000..0bfe682 --- /dev/null +++ b/src/app/anime/styles/pop_recent_top.module.css @@ -0,0 +1,60 @@ +.AnimeHeaderText { + color: white; + margin: 0.4rem 0 0 0; +} + +.AnimeContainer { + margin: 0.2rem 0 0 0; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + grid-gap: 0.7rem; +} + +.AnimeEntry { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + text-align: center; + padding: 0.8rem; + border-radius: 0.5rem; + background-color: #1f1f1f; +} + +.AnimeEntry img { + border-radius: 0.5rem; +} + +.AnimeEntry p { + margin: 0.2rem 0 -0.4rem 0; + max-width: 160px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.EpisodeText { + color: var(--neon-yellow); + font-size: small; + padding-top: 0.2rem; +} +.AnimeContainer::-webkit-scrollbar { + height: 0.2rem; +} + +.AnimeContainer::-webkit-scrollbar-track { + background-color: var(--soft-purple); +} + +.AnimeContainer::-webkit-scrollbar-thumb { + background-color: var(--neon-yellow); + border-radius: 1rem; +} + +@media screen and (max-width: 768px) { + .AnimeContainer { + display: flex; + overflow: auto; + align-items: center; + } +} \ No newline at end of file diff --git a/src/app/anime/styles/search.module.css b/src/app/anime/styles/search.module.css new file mode 100644 index 0000000..7c7957f --- /dev/null +++ b/src/app/anime/styles/search.module.css @@ -0,0 +1,77 @@ +.SearchBarContainer { + padding: 1rem 0 0.8rem 0; + width: 40%; +} + +.SearchInputContainer { + display: flex; + align-items: center; + background-color: #121212; + padding: 0.5rem; + border-radius: 0.5rem; +} + +.SearchInputContainer input { + background-color: transparent; + border: none; + outline: none; + color: white; + margin-left: 0.5rem; + font-size: 18px; + font-family: "Atkinson Hyperlegible", serif; + width: 100%; +} + +/* Search Results */ + +.SearchResultsContainer { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); + grid-gap: 0.7rem; +} + +.AnimeEntry { + display: flex; + align-items: center; + justify-content: space-between; + background-color: #252525be; + padding: 0.5rem; + border-radius: 0.5rem; +} + +.AnimeEntry p { + font-size: 18px; +} + +.AnimeEntry img { + border-radius: 0.5rem; +} + +.SearchResultsContainer::-webkit-scrollbar { + height: 0.2rem; +} + +.SearchResultsContainer::-webkit-scrollbar-track { + background-color: var(--softer-purple); +} + +.SearchResultsContainer::-webkit-scrollbar-thumb { + background-color: var(--light-green); + border-radius: 1rem; +} + +@media screen and (max-width: 768px) { + .SearchBarContainer { + width: 100%; + } + + .SearchResultsContainer { + display: flex; + align-items: center; + overflow: auto; + } + + .AnimeEntry p { + width: 50vw; + } +} \ No newline at end of file diff --git a/src/app/anime/top-airing/page.jsx b/src/app/anime/top-airing/page.jsx deleted file mode 100644 index 0102371..0000000 --- a/src/app/anime/top-airing/page.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import styles from "./trending.module.css"; -import Image from "next/image"; -import Link from "next/link"; -import { preFetchAnimeInfo } from "../videoLinkfetcher"; - -export default async function Trending() { - const data = await test(); - preFetchAnimeInfo(data); - - return ( -
-
-

Trending

-
- -
- {data && - data.results.map((item, index) => ( - -
- Drama -

{item.title}

-
- - ))} -
-
- ); -} - -async function test() { - const res = await fetch( - "https://consumet-jade.vercel.app/anime/gogoanime/top-airing", - { next: { revalidate: 21600 } } - ); - const data = res.json(); - return data; -} diff --git a/src/app/anime/top-airing/trending.module.css b/src/app/anime/top-airing/trending.module.css deleted file mode 100644 index cd1a672..0000000 --- a/src/app/anime/top-airing/trending.module.css +++ /dev/null @@ -1,79 +0,0 @@ -.TrendingText h1 { - margin: 0px 0px 0.5rem 0.5rem; - text-align: center; - color: transparent; - background: linear-gradient(90deg, - var(--neon-green) 40%, - var(--light-green) 60%, - var(--neon-yellow) 80%, - var(--soft-purple) 100%); - background-size: 60% 50%; - background-clip: text; -} - -.trending { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - grid-gap: 0.5rem; - align-items: center; - margin-left: 0.5rem; -} - -.TrendingContainer:hover .trendingEntries { - opacity: 0.5; -} - -.TrendingContainer:hover .trendingEntries:hover { - opacity: 1; - transform: scale(1.02); -} - -.trending::-webkit-scrollbar { - height: 0px; -} - -.trendingEntries { - transition: transform 400ms ease; - background-color: #1f1f1fbb; - padding: 0.5rem; - border-radius: 0.4rem; - transition: opacity 400ms ease, transform 400ms ease; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -.trendingEntries p { - text-align: center; - width: auto; - max-width: 160px; - margin: 0.5rem 0 0 0; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -.trendingEntries img { - border-radius: 0.4rem; - box-shadow: 0 0 10px 5px rgba(18, 18, 18, 0.863); -} - -@media screen and (max-width: 768px) { - .TrendingText p { - text-align: start; - font-size: 26px; - margin-bottom: 1rem; - } - - .trending { - display: flex; - overflow-x: auto; - overflow-y: hidden; - margin-top: -8px; - } - - .trendingEntries img { - width: auto; - } -} \ No newline at end of file diff --git a/src/app/anime/videoLinkfetcher.js b/src/app/anime/videoLinkfetcher.js deleted file mode 100644 index a718534..0000000 --- a/src/app/anime/videoLinkfetcher.js +++ /dev/null @@ -1,46 +0,0 @@ -"use server"; -export async function fetch_video_link(id) { - try { - const res = await fetch( - `https://consumet-jade.vercel.app/anime/gogoanime/watch/${id}`, - { cache: "force-cache" } - ); - const data = await res.json(); - let vidLink = data.sources[data.sources.length - 2].url; - return vidLink; - } catch (error) { - console.log("Mehh Error", error); - } -} - -export async function preFetchAnimeLinks(data, n = 40) { - const limit = Math.min(n, data.episodes.length); - - try { - const fetchPromises = []; - for (let i = 0; i < limit; i++) { - const element = data.episodes[i]; - const link = `https://consumet-jade.vercel.app/anime/gogoanime/watch/${element.id}`; - fetchPromises.push(fetch(link, { cache: "force-cache" })); - } - - await Promise.all(fetchPromises); - console.log("Video links pre-fetched successfully!"); - } catch (error) { - console.error("Error occurred while pre-fetching video links:", error); - } -} - -export async function preFetchAnimeInfo(data) { - try { - const fetchPromises = data.results.map(async (element) => { - const link = `https://anime-sensei-api.vercel.app/anime/gogoanime/info/${element.id}`; - await fetch(link, { next: { revalidate: 86400 } }); - }); - - await Promise.all(fetchPromises); - console.log("Anime info pre-fetched successfully!"); - } catch (error) { - console.error("Error occurred while pre-fetching anime info: ", error); - } -} -- cgit v1.2.3 From 513eb617bc627bdc406eddd0f3124411017cbe50 Mon Sep 17 00:00:00 2001 From: real-zephex Date: Sat, 11 May 2024 01:42:48 +0530 Subject: adjustments to the cache system --- src/app/anime/[id]/page.jsx | 2 +- src/app/anime/components/cacher.js | 2 +- src/app/anime/components/episode_buttons.jsx | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/app/anime/[id]/page.jsx b/src/app/anime/[id]/page.jsx index 7368e96..0b85e8e 100644 --- a/src/app/anime/[id]/page.jsx +++ b/src/app/anime/[id]/page.jsx @@ -10,7 +10,7 @@ const AnimeInfoHomepage = async ({ params }) => { const id = params.id; const data = await anime_info(id); - preFetchVideoLinks(data); + preFetchVideoLinks(data.episodes.slice(0, 49)); return (
diff --git a/src/app/anime/components/cacher.js b/src/app/anime/components/cacher.js index acc780a..d3008fa 100644 --- a/src/app/anime/components/cacher.js +++ b/src/app/anime/components/cacher.js @@ -17,7 +17,7 @@ export async function preFetchAnimeInfo(data) { export async function preFetchVideoLinks(data) { try { - const fetchPromises = data.episodes.map(async (element) => { + const fetchPromises = data.map(async (element) => { await fetch(watch_url(element.id), { next: { revalidate: 21600 } }); }); diff --git a/src/app/anime/components/episode_buttons.jsx b/src/app/anime/components/episode_buttons.jsx index f76704f..3336470 100644 --- a/src/app/anime/components/episode_buttons.jsx +++ b/src/app/anime/components/episode_buttons.jsx @@ -10,6 +10,7 @@ import { import styles from "../styles/buttons.module.css"; import { video_url } from "../data-fetch/request"; +import { preFetchVideoLinks } from "./cacher"; const EpisodesButtons = ({ data: data }) => { const [videoLink, setVideoLink] = useState(null); @@ -66,6 +67,12 @@ const EpisodesButtons = ({ data: data }) => { selectedGroup[selectedGroup.length - 1].number ) ); + preFetchVideoLinks( + data.episodes.slice( + selectedGroup[0].number - 1, + selectedGroup[selectedGroup.length - 1].number + ) + ); } } -- cgit v1.2.3 From 6c56263791c80676518532c9f91e0fb3d84fd079 Mon Sep 17 00:00:00 2001 From: real-zephex Date: Sat, 11 May 2024 02:01:28 +0530 Subject: adjustments to the cache system --- src/app/anime/[id]/page.jsx | 3 ++- src/app/anime/components/episode_buttons.jsx | 11 +++++++++++ src/app/anime/styles/buttons.module.css | 11 +++++++++++ src/app/anime/styles/pop_recent_top.module.css | 6 +----- 4 files changed, 25 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/app/anime/[id]/page.jsx b/src/app/anime/[id]/page.jsx index 0b85e8e..edd100a 100644 --- a/src/app/anime/[id]/page.jsx +++ b/src/app/anime/[id]/page.jsx @@ -10,7 +10,8 @@ const AnimeInfoHomepage = async ({ params }) => { const id = params.id; const data = await anime_info(id); - preFetchVideoLinks(data.episodes.slice(0, 49)); + const sliceLength = Math.min(data.episodes.length, 49); + preFetchVideoLinks(data.episodes.slice(0, sliceLength)); return (
diff --git a/src/app/anime/components/episode_buttons.jsx b/src/app/anime/components/episode_buttons.jsx index 3336470..9d6e1ca 100644 --- a/src/app/anime/components/episode_buttons.jsx +++ b/src/app/anime/components/episode_buttons.jsx @@ -31,6 +31,16 @@ const EpisodesButtons = ({ data: data }) => { } function createButtonGroups(start, end) { + try { + document.getElementById("episode-button").style.backgroundColor = + "#1f1f1fd2"; + } catch (error) { + console.error( + "ERROR: This error is expected. This is done in order to reset the background color of the buttons. I can't think of a better way than this....so yeah.", + error.message + ); + } + return (
{data.episodes && @@ -38,6 +48,7 @@ const EpisodesButtons = ({ data: data }) => {
+ + + {searchResults}
diff --git a/src/app/anime/styles/info.module.css b/src/app/anime/styles/info.module.css index 4e65bdd..4216b37 100644 --- a/src/app/anime/styles/info.module.css +++ b/src/app/anime/styles/info.module.css @@ -9,21 +9,29 @@ align-items: center; } +.AnimeHeroSection strong { + color: var(--neon-yellow); +} + .AnimeHeroSection img { - padding: 0.5rem 0.7rem 0rem 0; + width: auto; + height: auto; + padding: 0.5rem 0.7rem 0.5rem 0.7rem; + border-radius: 1rem; } .animeDescription { max-height: 100px; overflow: auto; + color: var(--light-sky); } .animeDescription::-webkit-scrollbar { - width: 4px; + width: 3px; } .animeDescription::-webkit-scrollbar-thumb { - background-color: gray; + background-color: var(--nord-yellow); border-radius: 1rem; } @@ -50,6 +58,18 @@ } .AnimeHeroSection img { - padding: 0.4rem 0.4rem 0 0; + padding: 0.4rem 0.4rem 0.4rem 0.4rem; + } +} + +@media screen and (max-width: 425px) { + .AnimeHeroSection { + display: flex; + align-items: center; + flex-direction: column; + } + + .animeTitle { + text-align: center; } } \ No newline at end of file diff --git a/src/app/anime/styles/search.module.css b/src/app/anime/styles/search.module.css index 7c7957f..d3564f7 100644 --- a/src/app/anime/styles/search.module.css +++ b/src/app/anime/styles/search.module.css @@ -1,6 +1,7 @@ .SearchBarContainer { padding: 1rem 0 0.8rem 0; - width: 40%; + display: flex; + align-items: center; } .SearchInputContainer { @@ -9,6 +10,18 @@ background-color: #121212; padding: 0.5rem; border-radius: 0.5rem; + width: 40%; +} + +.animeHistoryButton { + font-family: "Lexend Deca", serif; + outline: none; + border: none; + background-color: #121212; + color: white; + margin: 0 0 0 0.4rem; + padding: 0.5rem; + cursor: pointer; } .SearchInputContainer input { diff --git a/src/app/globals.css b/src/app/globals.css index db28734..233d7d1 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -7,6 +7,20 @@ --pastel-red: #ff6868; --soft-purple: #beadfa; --softer-purple: #d0bfff; + + + --nord-red: #BF616A; + --nord-green: #A3BE8C; + --nord-yellow: #EBCB8B; + --nord-orange: #D08770; + --nord-pink: #B48EAD; + + --nord-bg-darkest: #2E3440; + --nord-bg-darker: #3B4252; + --nord-bg-dark: #434C5E; + --nord-bg-darklight: #4C566A; + + --light-sky: #CAF4FF; } body { @@ -17,4 +31,4 @@ body { body::-webkit-scrollbar { width: 0; -} +} \ No newline at end of file -- cgit v1.2.3 From 755d67a651fa1be9d20606541b514a88938b76ce Mon Sep 17 00:00:00 2001 From: real-zephex Date: Sat, 11 May 2024 09:15:30 +0530 Subject: added anime history section --- src/app/anime/components/storeHistory.js | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/app/anime/components/storeHistory.js (limited to 'src') diff --git a/src/app/anime/components/storeHistory.js b/src/app/anime/components/storeHistory.js new file mode 100644 index 0000000..bd41815 --- /dev/null +++ b/src/app/anime/components/storeHistory.js @@ -0,0 +1,35 @@ +"use client"; + +export function storeLocal(watchData) { + const currentDate = new Date(); + const jsonData = localStorage.getItem("data"); + const dataObject = jsonData ? JSON.parse(jsonData) : {}; + + if (!dataObject.watchHis) { + dataObject.watchHis = []; + } + + let found = false; + dataObject.watchHis.forEach((element) => { + if (element.name === watchData.name) { + let episode = watchData.episode; + let date = `${currentDate.getDate()}-${String( + currentDate.getMonth() + 1 + ).padStart(2, "0")}`; + let time = `${currentDate.getHours()}:${String( + currentDate.getMinutes() + ).padStart(2, "0")}`; + element.episode = episode; + element.date = date; + element.time = time; + found = true; + } + }); + + if (!found) { + dataObject.watchHis.push(watchData); + } + + let updatedData = JSON.stringify(dataObject); + localStorage.setItem("data", updatedData); +} -- cgit v1.2.3 From 482185a71909123a0152d358c8fb90d427cc1c54 Mon Sep 17 00:00:00 2001 From: real-zephex Date: Sat, 11 May 2024 19:34:42 +0530 Subject: adjustments to the search bar on the anime page --- src/app/anime/components/search.jsx | 2 +- src/app/anime/styles/search.module.css | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/app/anime/components/search.jsx b/src/app/anime/components/search.jsx index f916217..b8b4b53 100644 --- a/src/app/anime/components/search.jsx +++ b/src/app/anime/components/search.jsx @@ -41,7 +41,7 @@ const SearcBar = () => { }} >
- + diff --git a/src/app/anime/styles/search.module.css b/src/app/anime/styles/search.module.css index d3564f7..b7e35ab 100644 --- a/src/app/anime/styles/search.module.css +++ b/src/app/anime/styles/search.module.css @@ -2,6 +2,7 @@ padding: 1rem 0 0.8rem 0; display: flex; align-items: center; + width: 100%; } .SearchInputContainer { @@ -19,9 +20,10 @@ border: none; background-color: #121212; color: white; - margin: 0 0 0 0.4rem; + margin: 0 0.1rem 0 0.2rem; padding: 0.5rem; cursor: pointer; + border-radius: 0.5rem; } .SearchInputContainer input { @@ -74,7 +76,7 @@ } @media screen and (max-width: 768px) { - .SearchBarContainer { + .SearchInputContainer { width: 100%; } -- cgit v1.2.3 From 9f40285893d1a765787d99721c44061bd50be6a8 Mon Sep 17 00:00:00 2001 From: real-zephex Date: Sat, 11 May 2024 19:34:45 +0530 Subject: adjustments to the search bar on the anime page --- src/app/anime/continueWatching/page.jsx | 65 +++++++++++++++++++++++++++++++++ src/app/anime/styles/cw.module.css | 59 ++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/app/anime/continueWatching/page.jsx create mode 100644 src/app/anime/styles/cw.module.css (limited to 'src') diff --git a/src/app/anime/continueWatching/page.jsx b/src/app/anime/continueWatching/page.jsx new file mode 100644 index 0000000..eb28a2f --- /dev/null +++ b/src/app/anime/continueWatching/page.jsx @@ -0,0 +1,65 @@ +"use client"; + +import React, { useState, useEffect } from "react"; +import Image from "next/image"; +import styles from "../styles/cw.module.css"; +import Link from "next/link"; + +const ContinueWatching = () => { + const [localItems, setLocalItems] = useState(null); + + useEffect(() => { + const newData = get_local(); + setLocalItems(newData); + }, []); // Empty dependency array means this effect runs only once after the initial render + + function get_local() { + try { + const data = localStorage.getItem("data"); + return JSON.parse(data); + } catch (error) { + console.log("error", error); + return false; + } + } + + return ( +
+

Continue Watching

+ {localItems && ( +
+ {localItems.watchHis && + localItems.watchHis.map((item, index) => ( + +
+
+

{item.name}

+

+ Episode watching: {item.episode} +

+

+ Last watched on: {item.date} at{" "} + {item.time} hours +

+
+ Continue anime poster +
+ + ))} +
+ )} +
+ ); +}; + +export default ContinueWatching; diff --git a/src/app/anime/styles/cw.module.css b/src/app/anime/styles/cw.module.css new file mode 100644 index 0000000..cb579c7 --- /dev/null +++ b/src/app/anime/styles/cw.module.css @@ -0,0 +1,59 @@ +.main { + width: 99%; + margin: 60px auto; +} + +.mainText { + color: white; + font-size: 24px; + margin: 0.2rem 0 0.2rem 0; +} + +.animeContainer { + font-size: 18px; + margin: 0px; +} + +.animeEntry { + display: flex; + align-items: center; + justify-content: space-between; + padding: 5px; + margin-bottom: 0.5rem; + border-radius: 0.4rem; + background-color: #1f1f1f; +} + +.animeEntry img { + border-radius: 0.4rem; + margin-left: 0.2rem; +} + +.titleContainer { + color: white; + margin-left: 0.2rem; +} + +.titleContainer h3 { + margin: 0px; +} + +.EpisodeCount { + color: var(--soft-purple); + margin: 0px; +} + +.date { + color: var(--neon-yellow); + margin: 0px; +} + +@media screen and (max-width: 768px) { + .animeContainer { + font-size: 14px; + } + + .animeEntry img { + width: 35%; + } +} \ No newline at end of file -- cgit v1.2.3 From 5a75c4551b3f6cc28aa7e9bef2dc56a36a8a494b Mon Sep 17 00:00:00 2001 From: real-zephex Date: Mon, 13 May 2024 21:23:36 +0530 Subject: added loading.jsx file and it's css subpart --- src/app/anime/[id]/page.jsx | 18 ++++++++++++------ src/app/anime/components/search.jsx | 9 +++++++++ src/app/anime/loading.jsx | 11 +++++++++++ src/app/anime/styles/loading.module.css | 12 ++++++++++++ src/app/anime/styles/search.module.css | 6 ++++++ src/app/movies/components/video_player.jsx | 2 +- src/app/movies/styles/info.module.css | 9 +++++++++ 7 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/app/anime/loading.jsx create mode 100644 src/app/anime/styles/loading.module.css (limited to 'src') diff --git a/src/app/anime/[id]/page.jsx b/src/app/anime/[id]/page.jsx index f107313..7715dc6 100644 --- a/src/app/anime/[id]/page.jsx +++ b/src/app/anime/[id]/page.jsx @@ -28,11 +28,15 @@ const AnimeInfoHomepage = async ({ params }) => { />

- {data.title} + + {data.title || "Not Found"} +

Description: - {data.description} + {data.description || "Not Found"}


@@ -51,17 +55,19 @@ const AnimeInfoHomepage = async ({ params }) => {

Episodes:{" "} - {data.totalEpisodes} + {data.totalEpisodes || "Not Found"}

Release year:{" "} - {data.releaseDate} + {data.releaseDate || "Not Found"}

- Status: {data.status} + Status:{" "} + {data.status || "Not Found"}

- Type: {data.type} + Type:{" "} + {data.type || "Not Found"}

diff --git a/src/app/anime/components/search.jsx b/src/app/anime/components/search.jsx index b8b4b53..66c491a 100644 --- a/src/app/anime/components/search.jsx +++ b/src/app/anime/components/search.jsx @@ -10,9 +10,13 @@ import SearchResults from "./search_results"; const SearcBar = () => { const [title, setTitle] = useState(""); const [searchResults, setSearchResults] = useState(null); + const [loading, setLoading] = useState(false); const handleSearchInput = async (title) => { + setSearchResults(null); + setLoading(true); setSearchResults(await SearchResults(title)); + setLoading(false); }; return ( @@ -47,6 +51,11 @@ const SearcBar = () => { + {loading && ( +

+ Please wait while we crunch up all the data..... +

+ )} {searchResults} ); diff --git a/src/app/anime/loading.jsx b/src/app/anime/loading.jsx new file mode 100644 index 0000000..00ce39c --- /dev/null +++ b/src/app/anime/loading.jsx @@ -0,0 +1,11 @@ +import styles from "./styles/loading.module.css"; + +const Loading = async () => { + return ( +
+ Loading... +
+ ); +}; + +export default Loading; diff --git a/src/app/anime/styles/loading.module.css b/src/app/anime/styles/loading.module.css new file mode 100644 index 0000000..f0d0606 --- /dev/null +++ b/src/app/anime/styles/loading.module.css @@ -0,0 +1,12 @@ +.LoadingContainer { + height: 100vh; + width: 100vw; + display: flex; + align-items: center; + justify-content: center; +} + +.LoadingContainer strong { + color: white; + font-size: 20px; +} \ No newline at end of file diff --git a/src/app/anime/styles/search.module.css b/src/app/anime/styles/search.module.css index b7e35ab..25fa4d4 100644 --- a/src/app/anime/styles/search.module.css +++ b/src/app/anime/styles/search.module.css @@ -37,6 +37,11 @@ width: 100%; } +.SearchLoading { + color: white; + text-align: center; +} + /* Search Results */ .SearchResultsContainer { @@ -60,6 +65,7 @@ .AnimeEntry img { border-radius: 0.5rem; + margin-left: 0.2rem; } .SearchResultsContainer::-webkit-scrollbar { diff --git a/src/app/movies/components/video_player.jsx b/src/app/movies/components/video_player.jsx index 86ff8e5..86b6748 100644 --- a/src/app/movies/components/video_player.jsx +++ b/src/app/movies/components/video_player.jsx @@ -7,7 +7,7 @@ export default function VIDEO_PLAYER({ id: id }) { const [frame, setFrame] = useState(null); useEffect(() => { - make_player(`https://vidsrc.pro/embed/movie/${id}`); + make_player(`https://vidsrc.icu/embed/movie/${id}`); }, []); function make_player(url) { diff --git a/src/app/movies/styles/info.module.css b/src/app/movies/styles/info.module.css index a0da8d9..b848f7f 100644 --- a/src/app/movies/styles/info.module.css +++ b/src/app/movies/styles/info.module.css @@ -53,6 +53,15 @@ overflow: auto; } +.MovieDescription::-webkit-scrollbar { + width: 5px; +} + +.MovieDescription::-webkit-scrollbar-thumb { + background-color: var(--nord-yellow); + border-radius: 1rem; +} + .OtherInfo { display: flex; flex-direction: column; -- cgit v1.2.3