From 83c3fa302adbc4c3adf63c59cfe87b51d83ecbcb Mon Sep 17 00:00:00 2001
From: Pinapelz <yukais@pinapelz.com>
Date: Mon, 5 May 2025 00:57:58 -0700
Subject: qol: make sub table sortable by different metrics

---
 src/components/SubscriberTable/SubscriberTable.tsx | 91 ++++++++++++++++++----
 1 file changed, 77 insertions(+), 14 deletions(-)

(limited to 'src/components/SubscriberTable/SubscriberTable.tsx')

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
-- 
cgit v1.2.3

