aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/SubscriberTable
diff options
context:
space:
mode:
authorPinapelz <yukais@pinapelz.com>2025-05-05 00:57:58 -0700
committerPinapelz <yukais@pinapelz.com>2025-05-05 01:03:54 -0700
commit83c3fa302adbc4c3adf63c59cfe87b51d83ecbcb (patch)
treeb0313e733161f9fa17fe5bca5ba92e6cfa613132 /src/components/SubscriberTable
parente7087490a95845413e76dfc08c54d1bbdb5ac5d7 (diff)
qol: make sub table sortable by different metrics
Diffstat (limited to 'src/components/SubscriberTable')
-rw-r--r--src/components/SubscriberTable/SubscriberTable.tsx91
1 files changed, 77 insertions, 14 deletions
diff --git a/src/components/SubscriberTable/SubscriberTable.tsx b/src/components/SubscriberTable/SubscriberTable.tsx
index 6c19e44..c308aee 100644
--- a/src/components/SubscriberTable/SubscriberTable.tsx
+++ b/src/components/SubscriberTable/SubscriberTable.tsx
@@ -1,4 +1,5 @@
-import React from "react";
+"use client";
+import React, { useState } from "react";
import ChannelRow from "./SubscriberTableRow";
interface ChannelDataProp {
@@ -19,13 +20,49 @@ interface SubscriberDataTableProp {
timestamp: string;
}
+type SortKey = keyof ChannelDataProp | "rank";
+
const DataTable = ({ channel_data, timestamp }: SubscriberDataTableProp) => {
- if (!channel_data) {
- return null;
- }
+ const [sortKey, setSortKey] = useState<SortKey>("subscribers");
+ const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc");
+ const [indexName, setIndexName] = useState<string>("RANK");
+
+ const handleSort = (key: SortKey) => {
+ if (sortKey === key) {
+ setSortOrder(sortOrder === "asc" ? "desc" : "asc");
+ } else {
+ setSortKey(key);
+ setSortOrder("desc");
+ }
+ if (key === "sub_org") {
+ setIndexName("INDEX");
+ } else {
+ setIndexName("RANK");
+ }
+ };
+
+ const sortedData = [...channel_data].sort((a, b) => {
+ let aValue: any, bValue: any;
+ if (sortKey === "rank") {
+ aValue = channel_data.indexOf(a) + 1;
+ bValue = channel_data.indexOf(b) + 1;
+ } else {
+ aValue = a[sortKey as keyof ChannelDataProp];
+ bValue = b[sortKey as keyof ChannelDataProp];
+ }
+ if (typeof aValue === "string") {
+ return sortOrder === "asc"
+ ? aValue.localeCompare(bValue)
+ : bValue.localeCompare(aValue);
+ }
+ return sortOrder === "asc" ? aValue - bValue : bValue - aValue;
+ });
return (
<>
+ <div className="sm:hidden text-center text-red-600 font-semibold my-2">
+ Limited data shown on mobile view!
+ </div>
<div
className="text-center sm:mt-5"
style={{ fontFamily: "Quantico, sans-serif" }}
@@ -40,7 +77,7 @@ const DataTable = ({ channel_data, timestamp }: SubscriberDataTableProp) => {
<div className="px-2 sm:px-48 py-4 sm:py-8 relative 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 rounded-md"
+ className="text-m sm:text-lg text-white rounded-md select-none"
style={{ backgroundColor: "black" }}
>
<tr>
@@ -48,39 +85,65 @@ const DataTable = ({ channel_data, timestamp }: SubscriberDataTableProp) => {
scope="col"
className="py-1 px-1 sm:px-3 hidden sm:table-cell"
>
- RANK
+ {indexName}
</th>
- <th scope="col" className="py-1 px-1 sm:px-3">
+ <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"
+ className="py-1 px-1 sm:px-3 hidden sm:table-cell cursor-pointer"
+ onClick={() => handleSort("sub_org")}
>
GROUP
+ {sortKey === "sub_org" && (
+ <span className="ml-1">{sortOrder === "asc" ? "▲" : "▼"}</span>
+ )}
</th>
<th
scope="col"
- className="py-1 px-1 sm:px-3 hidden sm:table-cell"
+ className="py-1 px-1 sm:px-3 hidden sm:table-cell cursor-pointer"
+ onClick={() => handleSort("video_count")}
>
VIDEO COUNT
+ {sortKey === "video_count" && (
+ <span className="ml-1">{sortOrder === "asc" ? "▲" : "▼"}</span>
+ )}
</th>
<th
scope="col"
- className="py-1 px-1 sm:px-3 hidden sm:table-cell"
+ className="py-1 px-1 sm:px-3 hidden sm:table-cell cursor-pointer"
+ onClick={() => handleSort("views")}
>
VIEW COUNT
+ {sortKey === "views" && (
+ <span className="ml-1">{sortOrder === "asc" ? "▲" : "▼"}</span>
+ )}
</th>
- <th scope="col" className="py-1 px-1 sm:px-3">
+ <th
+ scope="col"
+ className="py-1 px-1 sm:px-3 cursor-pointer"
+ onClick={() => handleSort("subscribers")}
+ >
SUBSCRIBERS
+ {sortKey === "subscribers" && (
+ <span className="ml-1">{sortOrder === "asc" ? "▲" : "▼"}</span>
+ )}
</th>
- <th scope="col" className="py-1 px-1 sm:px-3">
+ <th
+ scope="col"
+ className="py-1 px-1 sm:px-3"
+ onClick={() => handleSort("diff_1d")}
+ >
DIFF (24H)
</th>
</tr>
</thead>
<tbody>
- {channel_data.map((channel, index) => (
+ {sortedData.map((channel, index) => (
<ChannelRow
key={index}
channel={channel}
@@ -96,4 +159,4 @@ const DataTable = ({ channel_data, timestamp }: SubscriberDataTableProp) => {
export default DataTable;
export type { SubscriberDataTableProp };
-export type { ChannelDataProp };
+export type { ChannelDataProp }; \ No newline at end of file
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage