diff options
| author | Pinapelz <yukais@pinapelz.com> | 2023-11-26 02:36:07 -0800 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2023-11-26 02:36:07 -0800 |
| commit | 13625d722a421441c1edc6eb1256b7e20f20544d (patch) | |
| tree | 9035666485280eba681fe90a7ae0ff18924a99ea /src | |
| parent | 174cbcc1a1667b254d19bca31463f900845ea8ee (diff) | |
use SSR for rendering graph + transition demo to PhaseConnect
- I like Phase Connect
Diffstat (limited to 'src')
| -rw-r--r-- | src/app/globals.css | 1 | ||||
| -rw-r--r-- | src/app/layout.tsx | 2 | ||||
| -rw-r--r-- | src/app/page.tsx | 2 | ||||
| -rw-r--r-- | src/components/DataChart/DataChart.tsx | 64 | ||||
| -rw-r--r-- | src/components/Footer/Footer.tsx | 10 | ||||
| -rw-r--r-- | src/components/SubscriberTable/SubscriberTable.tsx | 2 | ||||
| -rw-r--r-- | src/components/TitleBar/TitleBar.tsx | 26 | ||||
| -rw-r--r-- | src/components/TitleBar/TitleBarStyle.css | 1 | ||||
| -rw-r--r-- | src/pages/stats/[slug].tsx | 77 |
9 files changed, 95 insertions, 90 deletions
diff --git a/src/app/globals.css b/src/app/globals.css index b5c61c9..e6d1700 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,3 +1,4 @@ @tailwind base; @tailwind components; @tailwind utilities; +@import url('https://fonts.googleapis.com/css2?family=Quantico:wght@400;700&display=swap'); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3fdc727..a8df895 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -7,7 +7,7 @@ const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Nijitracker - Nijisanji Subscriber Tracker', - description: 'Nijitracker, historical subscriber data for members of Nijisanji', + description: 'Nijitracker, historical subscriber data for members of Phase Connect', } export default function RootLayout({ diff --git a/src/app/page.tsx b/src/app/page.tsx index 6016d89..ed29653 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -6,7 +6,7 @@ async function Home(){ const data: SubscriberDataTableProp = await getData(); return( <> - <TitleBar title="Nijitracker" /> + <TitleBar title="PhaseTracker" backgroundColor='black' /> <div className="sm:block hidden mt-4" style={{ overflow: 'hidden', height: '105vh', position: 'relative' }}> <iframe src={apiUrl} style={{ position: 'absolute', top: 0, left: 0 }} width="100%" height="100%"></iframe> </div> diff --git a/src/components/DataChart/DataChart.tsx b/src/components/DataChart/DataChart.tsx index a82fa26..9fbc5fe 100644 --- a/src/components/DataChart/DataChart.tsx +++ b/src/components/DataChart/DataChart.tsx @@ -1,5 +1,4 @@ -"use client"; -import React, {useEffect, useState} from 'react'; +import React from 'react'; import { Chart as ChartJS, CategoryScale, @@ -24,55 +23,13 @@ ChartJS.register( ); - - - -interface Dataset { - label: string; - data: number[]; - borderColor: string; - backgroundColor: string; -} - -interface DataChartResponseProps { - labels: string[]; - datasets: Dataset[]; -} - interface DataChartProps { - channel_name: string; - requestUrl?: string; + channel_name?: string; + chartData?: any; graphTitle?: string; } -const DataChart: React.FC<DataChartProps> = ({ channel_name, requestUrl, graphTitle }) => { - const [data, setData] = useState<DataChartResponseProps | null>(); - const apiUrl = process.env.NEXT_PUBLIC_API_URL - - useEffect(() => { - const fetchData = async () => { - try { - const response = await fetch(requestUrl || `${apiUrl}/api/subscribers/${channel_name}`); - const json = await response.json(); - setData({ - labels: json.labels, - datasets: [ - { - label: 'Subscriber Count', - data: json.datasets, - borderColor: 'rgb(255, 99, 132)', - backgroundColor: 'rgba(255, 99, 132, 0.5)', - }, - ], - }); - } catch (error) { - console.error('Error fetching data:', error); - } - }; - - fetchData(); - }, [apiUrl, channel_name, requestUrl]); - +const DataChart: React.FC<DataChartProps> = ({ channel_name, chartData, graphTitle }) => { const options = { responsive: true, plugins: { @@ -97,10 +54,19 @@ const DataChart: React.FC<DataChartProps> = ({ channel_name, requestUrl, graphTi } }; - if (!data) { - return <div>Loading...</div>; + const data = { + labels: chartData.labels, + datasets: [ + { + label: 'Subscriber Count', + data: chartData.datasets, + borderColor: 'rgb(255, 99, 132)', + backgroundColor: 'rgba(255, 99, 132, 0.5)', + }, + ], } + return <Line options={options} data={data} />; }; diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx index 6585e52..7fb8303 100644 --- a/src/components/Footer/Footer.tsx +++ b/src/components/Footer/Footer.tsx @@ -4,16 +4,16 @@ import React from 'react'; const Footer = () => { return ( <footer> - <div className="text-center"> - <p className="text-bold"> + <div className="text-center mt-4"> + <p className="font-bold"> Information </p> <p className="text-m"> - Information is collected once per hour. Data collection will stop once a liver has graduated. + Information is collected once per hour. Data collection will stop upon graduation <br/> - This page is in now way affiliated with ANYCOLOR or with any of the channels listed here. + This page is in now way affiliated with Phase Connect or with any of the channels listed here. <br/> - Date Started: 2023-03-26 + Date Started: 2023-04-01 </p> <p className="p-4"> <a className="hover:underline text-bold" href="https://github.com/pinapelz/Nijitrack">Source Code</a><br/> diff --git a/src/components/SubscriberTable/SubscriberTable.tsx b/src/components/SubscriberTable/SubscriberTable.tsx index 8094e21..31ca24f 100644 --- a/src/components/SubscriberTable/SubscriberTable.tsx +++ b/src/components/SubscriberTable/SubscriberTable.tsx @@ -28,7 +28,7 @@ return ( </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' }}> + <thead className="text-m sm:text-lg text-white rounded-md" style={{ backgroundColor: 'black' }}> <tr> <th scope="col" className="py-1 px-1 sm:px-3 hidden sm:table-cell"> RANK diff --git a/src/components/TitleBar/TitleBar.tsx b/src/components/TitleBar/TitleBar.tsx index 85fbfbd..05a0e5d 100644 --- a/src/components/TitleBar/TitleBar.tsx +++ b/src/components/TitleBar/TitleBar.tsx @@ -1,25 +1,29 @@ import React from 'react'; +import '../TitleBar/TitleBarStyle.css' interface TitleBarProps { title: string; redirectUrl?: string; showHomeButton?: boolean; + backgroundColor?: string; } -const TitleBar: React.FC<TitleBarProps> = ({ title, redirectUrl, showHomeButton }) => { +const TitleBar: React.FC<TitleBarProps> = ({ title, redirectUrl, showHomeButton, backgroundColor }) => { return ( - <div className="title-bar p-5 shadow-md" style={{ backgroundColor: '#2D4B71' }}> - <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> - <a href={redirectUrl}> - <span className="text-white text-4xl font-bold">{title}</span> - </a> - {showHomeButton && ( - <a href="/"> - <button className="bg-white text-blue-500 hover:bg-blue-500 hover:text-white font-bold py-2 px-4 rounded-full">Home</button> + <> + <div className="title-bar p-5 shadow-md" style={{ backgroundColor: backgroundColor || '#2D4B71' }}> + <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> + <a href={redirectUrl}> + <span className="text-white text-4xl font-bold" style={{ fontFamily: 'Quantico, sans-serif' }}>{title}</span> </a> - )} + {showHomeButton && ( + <a href="/"> + <button className="bg-white text-black font-bold py-2 px-4 rounded-lg">Home</button> + </a> + )} + </div> </div> - </div> + </> ); }; diff --git a/src/components/TitleBar/TitleBarStyle.css b/src/components/TitleBar/TitleBarStyle.css new file mode 100644 index 0000000..703f01d --- /dev/null +++ b/src/components/TitleBar/TitleBarStyle.css @@ -0,0 +1 @@ +@import url('https://fonts.googleapis.com/css2?family=Quantico:wght@400;700&display=swap'); diff --git a/src/pages/stats/[slug].tsx b/src/pages/stats/[slug].tsx index d02d665..1e76d65 100644 --- a/src/pages/stats/[slug].tsx +++ b/src/pages/stats/[slug].tsx @@ -1,11 +1,9 @@ -"use client"; -import React, { useEffect, useState } from "react"; import { useRouter } from "next/router"; +import { GetServerSideProps } from "next"; import "../../app/globals.css"; import TitleBar from "../../components/TitleBar/TitleBar"; import { ChannelCard } from "@/components/channel-card"; import DataChart from "@/components/DataChart/DataChart"; -import axios from "axios"; interface ChannelDataProp { channel_name: string; @@ -18,28 +16,32 @@ interface ChannelDataProp { next_milestone_date: string; } -export default function Page() { - const [channelData, setChannelData] = useState<ChannelDataProp | null>(null); - const router = useRouter(); - const { slug } = router.query; - useEffect(() => { - const apiUrl = process.env.NEXT_PUBLIC_API_URL; - if (slug) { - const encodedSlug = encodeURIComponent(slug as string); - console.log(apiUrl + `/api/channel/${encodedSlug}`); - axios.get(apiUrl + `/api/channel/${encodedSlug}`).then((response) => { - console.log(response); - setChannelData(response.data); - }); - } - }, [slug]); +interface GraphDataProp{ + labels: string[]; + datasets: number[]; +} + +export const getServerSideProps: GetServerSideProps = async (context) => { + const { slug } = context.params || {}; + + const chartData = await getGraphData(slug as string); + const channelData = await getChannelData(slug as string); + return { + props: { + chartData, + channelData, + slug + }, + }; +}; + +function Page({ chartData, channelData, slug }: { chartData: GraphDataProp, channelData: ChannelDataProp, slug: string }) { return ( <> - <TitleBar title={slug as string} redirectUrl="/" showHomeButton /> + <TitleBar title={slug as string} redirectUrl="/" showHomeButton backgroundColor="black" /> <div className="flex justify-center"> <div className="flex flex-col items-center"> - {channelData && ( <ChannelCard name={channelData.channel_name} avatarUrl={channelData.profile_pic} @@ -50,14 +52,45 @@ export default function Page() { nextMilestoneDays={channelData.days_until_next_milestone} nextMilestoneDate={channelData.next_milestone_date} /> - )} </div> </div> <div className="px-48 mb-10 mt-10"> <div className="mb-12"> - <DataChart channel_name={slug as string}/> + <DataChart channel_name={slug as string} chartData={chartData}/> </div> </div> </> ); } + +async function getGraphData(slug: string){ + const encodedSlug = encodeURIComponent(slug as string); + const apiUrl = process.env.NEXT_PUBLIC_API_URL + const response = await fetch(apiUrl+`/api/subscribers/${encodedSlug}`, { + headers: { + 'Cache-Control': 'no-cache' + }, + cache: 'no-cache' + }); + if(!response.ok){ + console.log(response.statusText); + } + return response.json(); +} + +async function getChannelData(slug: string){ + const encodedSlug = encodeURIComponent(slug as string); + const apiUrl = process.env.NEXT_PUBLIC_API_URL + const response = await fetch(apiUrl+`/api/channel/${encodedSlug}`, { + headers: { + 'Cache-Control': 'no-cache' + }, + cache: 'no-cache' + }); + if(!response.ok){ + console.log(response.statusText); + } + return response.json(); +} + +export default Page; |
