aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/_componenets/Footer/Footer.tsx27
-rw-r--r--src/app/_componenets/SubscriberTable/SubscriberTable.tsx67
-rw-r--r--src/app/_componenets/SubscriberTable/SubscriberTableRow.tsx35
-rw-r--r--src/app/_componenets/TitleBar/TitleBar.tsx18
-rw-r--r--src/app/globals.css24
-rw-r--r--src/app/layout.tsx9
-rw-r--r--src/app/page.tsx138
-rw-r--r--src/pages/stats/[slug].tsx16
8 files changed, 197 insertions, 137 deletions
diff --git a/src/app/_componenets/Footer/Footer.tsx b/src/app/_componenets/Footer/Footer.tsx
new file mode 100644
index 0000000..f23c677
--- /dev/null
+++ b/src/app/_componenets/Footer/Footer.tsx
@@ -0,0 +1,27 @@
+
+import React from 'react';
+
+const Footer = () => {
+ return (
+ <footer>
+ <div className="text-center">
+ <p className="text-bold">
+ Information
+ </p>
+ <p className="text-m">
+ Information is collected once per hour. Data collection will stop once a liver has graduated.
+ <br/>
+ This page is in now way affiliated with ANYCOLOR or with any of the channels listed here.
+ <br/>
+ Date Started: 2023-03-26
+ </p>
+ <p className="p-4">
+ <a className="hover:underline text-bold" href="https://github.com/pinapelz/Nijitrack">Source Code</a><br/>
+ We are currently under construction!
+ </p>
+ </div>
+ </footer>
+ );
+};
+
+export default Footer;
diff --git a/src/app/_componenets/SubscriberTable/SubscriberTable.tsx b/src/app/_componenets/SubscriberTable/SubscriberTable.tsx
new file mode 100644
index 0000000..a538bdd
--- /dev/null
+++ b/src/app/_componenets/SubscriberTable/SubscriberTable.tsx
@@ -0,0 +1,67 @@
+import React from "react";
+import Image from "next/image";
+import ChannelRow from "./SubscriberTableRow";
+
+interface ChannelDataProp {
+ channel_name: string;
+ profile_pic: string;
+ subscribers: number;
+ sub_org: string;
+ video_count: number;
+ day_diff: number;
+}
+
+interface SubscriberDataTableProp {
+ channel_data: ChannelDataProp[];
+ timestamp: string;
+}
+
+const DataTable = ({ channel_data, timestamp }: SubscriberDataTableProp) => {
+ if (!channel_data) {
+ return null;
+ }
+
+return (
+ <>
+ <div className="text-center sm:mt-5">
+ <h1 className="text-2xl font-bold text-gray-800">Subscriber Count</h1>
+ <p className="text-gray-500 text-sm">Last Updated: {timestamp}</p>
+ </div>
+ <div className="px-2 sm:px-48 py-4 sm:py-8 relative shadow-md rounded-l text-left overflow-auto">
+ <table className="w-full text-m sm:text-xl text-black bg-white">
+ <thead className="text-m sm:text-lg text-white" style={{ backgroundColor: '#2D4B71' }}>
+ <tr>
+ <th scope="col" className="py-1 px-1 sm:px-3 hidden sm:table-cell">
+ RANK
+ </th>
+ <th scope="col" className="py-1 px-1 sm:px-3">
+ CHANNEL
+ </th>
+ <th scope="col" className="py-1 px-1 sm:px-3 hidden sm:table-cell">
+ GROUP
+ </th>
+ <th scope="col" className="py-1 px-1 sm:px-3 hidden sm:table-cell">
+ VIDEO COUNT
+ </th>
+ <th scope="col" className="py-1 px-1 sm:px-3">
+ SUBSCRIBERS
+ </th>
+ <th scope="col" className="py-1 px-1 sm:px-3">
+ DIFF (24H)
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {channel_data.map((channel, index) => (
+ <ChannelRow key={index} channel={channel} index={index} />
+ ))}
+ </tbody>
+ </table>
+ </div>
+ </>
+);
+};
+
+export default DataTable;
+export type { SubscriberDataTableProp };
+export type { ChannelDataProp };
diff --git a/src/app/_componenets/SubscriberTable/SubscriberTableRow.tsx b/src/app/_componenets/SubscriberTable/SubscriberTableRow.tsx
new file mode 100644
index 0000000..619a5b8
--- /dev/null
+++ b/src/app/_componenets/SubscriberTable/SubscriberTableRow.tsx
@@ -0,0 +1,35 @@
+"use client"
+import React from 'react';
+import Image from 'next/image';
+import { ChannelDataProp } from './SubscriberTable';
+
+interface ChannelRowProps {
+ channel: ChannelDataProp;
+ index: number;
+}
+
+const ChannelRow: React.FC<ChannelRowProps> = ({ channel, index }) => (
+<tr key={index} className="border-b hover:bg-gray-100 cursor-pointer">
+ <td className="py-3 px-1 sm:px-3 hidden sm:table-cell">{index + 1}</td>
+ <td className="py-3 px-1 sm:px-3 flex items-center">
+ <Image
+ src={channel.profile_pic}
+ alt={channel.channel_name}
+ width={50}
+ height={50}
+ className="rounded-full"
+ />
+ <span className="ml-2">
+ {channel.channel_name}
+ </span>
+ </td>
+ <td className="py-3 px-1 sm:px-3 hidden sm:table-cell">{channel.sub_org}</td>
+ <td className="py-3 px-1 sm:px-3 hidden sm:table-cell">{channel.video_count}</td>
+ <td className="py-3 px-1 sm:px-3">{Number(channel.subscribers).toLocaleString()}</td>
+ <td className="py-3 px-1 sm:px-3">
+ {channel.day_diff > 0 ? `+${Number(channel.day_diff).toLocaleString()}` : Number(channel.day_diff).toLocaleString()}
+ </td>
+ </tr>
+);
+
+export default ChannelRow; \ No newline at end of file
diff --git a/src/app/_componenets/TitleBar/TitleBar.tsx b/src/app/_componenets/TitleBar/TitleBar.tsx
new file mode 100644
index 0000000..27bebfc
--- /dev/null
+++ b/src/app/_componenets/TitleBar/TitleBar.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import Image from 'next/image';
+
+interface TitleBarProps {
+ title: string;
+}
+
+const TitleBar: React.FC<TitleBarProps> = ({ title }) => {
+ return (
+ <div className="title-bar p-5 shadow-md" style={{ backgroundColor: '#2D4B71' }}>
+ <div style={{ width: 'fit-content', whiteSpace: 'nowrap', overflow: 'hidden' }}>
+ <span className="text-white text-4xl font-bold">{title}</span>
+ </div>
+ </div>
+ );
+};
+
+export default TitleBar; \ No newline at end of file
diff --git a/src/app/globals.css b/src/app/globals.css
index fd81e88..b5c61c9 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -1,27 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
-
-:root {
- --foreground-rgb: 0, 0, 0;
- --background-start-rgb: 214, 219, 220;
- --background-end-rgb: 255, 255, 255;
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --foreground-rgb: 255, 255, 255;
- --background-start-rgb: 0, 0, 0;
- --background-end-rgb: 0, 0, 0;
- }
-}
-
-body {
- color: rgb(var(--foreground-rgb));
- background: linear-gradient(
- to bottom,
- transparent,
- rgb(var(--background-end-rgb))
- )
- rgb(var(--background-start-rgb));
-}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 40e027f..ae0349f 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,12 +1,13 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
+import Footer from './_componenets/Footer/Footer'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
- title: 'Create Next App',
- description: 'Generated by create next app',
+ title: 'Nijitracker - Nijisanji Subscriber Tracker',
+ description: 'Nijitracker, historical subscriber data for members of Nijisanji',
}
export default function RootLayout({
@@ -16,7 +17,9 @@ export default function RootLayout({
}) {
return (
<html lang="en">
- <body className={inter.className}>{children}</body>
+ <body className={inter.className}>{children}
+ <Footer />
+ </body>
</html>
)
}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index b973266..81c12b6 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,113 +1,31 @@
-import Image from 'next/image'
+import SubscriberTable, {SubscriberDataTableProp} from './_componenets/SubscriberTable/SubscriberTable';
+import TitleBar from './_componenets/TitleBar/TitleBar';
-export default function Home() {
- return (
- <main className="flex min-h-screen flex-col items-center justify-between p-24">
- <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
- <p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
- Get started by editing&nbsp;
- <code className="font-mono font-bold">src/app/page.tsx</code>
- </p>
- <div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
- <a
- className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
- href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
- target="_blank"
- rel="noopener noreferrer"
- >
- By{' '}
- <Image
- src="/vercel.svg"
- alt="Vercel Logo"
- className="dark:invert"
- width={100}
- height={24}
- priority
- />
- </a>
- </div>
- </div>
-
- <div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700 before:dark:opacity-10 after:dark:from-sky-900 after:dark:via-[#0141ff] after:dark:opacity-40 before:lg:h-[360px] z-[-1]">
- <Image
- className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
- src="/next.svg"
- alt="Next.js Logo"
- width={180}
- height={37}
- priority
- />
- </div>
-
- <div className="mb-32 grid text-center lg:max-w-5xl lg:w-full lg:mb-0 lg:grid-cols-4 lg:text-left">
- <a
- href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
- className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2 className={`mb-3 text-2xl font-semibold`}>
- Docs{' '}
- <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
- -&gt;
- </span>
- </h2>
- <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
- Find in-depth information about Next.js features and API.
- </p>
- </a>
-
- <a
- href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
- className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2 className={`mb-3 text-2xl font-semibold`}>
- Learn{' '}
- <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
- -&gt;
- </span>
- </h2>
- <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
- Learn about Next.js in an interactive course with&nbsp;quizzes!
- </p>
- </a>
-
- <a
- href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
- className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2 className={`mb-3 text-2xl font-semibold`}>
- Templates{' '}
- <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
- -&gt;
- </span>
- </h2>
- <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
- Explore starter templates for Next.js.
- </p>
- </a>
+async function Home(){
+ const apiUrl = process.env.NEXT_PUBLIC_API_URL
+ const data: SubscriberDataTableProp = await getData();
+ return(
+ <>
+ <TitleBar title="Nijitracker" />
+ <div className="sm:block hidden mt-4" style={{ overflow: 'hidden', height: '88vh', position: 'relative' }}>
+ <iframe src={apiUrl} style={{ position: 'absolute', top: 0, left: 0 }} width="100%" height="100%"></iframe>
+ </div>
+ <SubscriberTable {...data} />
+ </>
+ );
+}
- <a
- href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
- className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2 className={`mb-3 text-2xl font-semibold`}>
- Deploy{' '}
- <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
- -&gt;
- </span>
- </h2>
- <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
- Instantly deploy your Next.js site to a shareable URL with Vercel.
- </p>
- </a>
- </div>
- </main>
- )
+async function getData(){
+ const apiUrl = process.env.NEXT_PUBLIC_API_URL
+ const response = await fetch(apiUrl+'/api/subscribers', {
+ headers: {
+ 'Cache-Control': 'no-cache'
+ },
+ cache: 'no-cache'
+ });
+ if(!response.ok){
+ console.log(response.statusText);
+ }
+ return response.json();
}
+export default Home; \ No newline at end of file
diff --git a/src/pages/stats/[slug].tsx b/src/pages/stats/[slug].tsx
new file mode 100644
index 0000000..03f8adf
--- /dev/null
+++ b/src/pages/stats/[slug].tsx
@@ -0,0 +1,16 @@
+"use client"
+import { useRouter } from 'next/router'
+
+export default function Page() {
+ const router = useRouter();
+ return (
+ <div className="flex items-center justify-center h-screen">
+ <div className="bg-black p-8 rounded-lg shadow-lg">
+ <h1 className="text-2xl font-bold mb-4">Under Construction</h1>
+ <p className="text-gray-600">We are currently working on this page. Please check back later.</p>
+ <p className="text-gray-600">Thank you for your patience</p>
+ <p className="text-gray-600">Slug: {router.query.slug}</p>
+ </div>
+ </div>
+ );
+} \ No newline at end of file
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage