From b1a7a679f011e11bb521efadf9b33a80a0b5b4a7 Mon Sep 17 00:00:00 2001
From: abias <abias1122@gmail.com>
Date: Sat, 20 May 2023 15:39:12 -0400
Subject: [PATCH] Refactor tabs into reuseable component

---
 src/shared/components/common/tabs.tsx         |  54 ++++++++
 src/shared/components/home/admin-settings.tsx | 124 +++++++-----------
 .../components/home/rate-limit-form.tsx       |  11 ++
 src/shared/components/person/settings.tsx     |  61 ++++-----
 4 files changed, 134 insertions(+), 116 deletions(-)
 create mode 100644 src/shared/components/common/tabs.tsx
 create mode 100644 src/shared/components/home/rate-limit-form.tsx

diff --git a/src/shared/components/common/tabs.tsx b/src/shared/components/common/tabs.tsx
new file mode 100644
index 0000000..36e1a01
--- /dev/null
+++ b/src/shared/components/common/tabs.tsx
@@ -0,0 +1,54 @@
+import { Component, InfernoNode, linkEvent } from "inferno";
+
+interface TabItem {
+  key: string;
+  getNode: () => InfernoNode;
+  label: string;
+}
+
+interface TabsProps {
+  tabs: TabItem[];
+}
+
+interface TabsState {
+  currentTab: string;
+}
+
+function handleSwitchTab({ ctx, tab }: { ctx: Tabs; tab: string }) {
+  console.log(tab);
+  ctx.setState({ currentTab: tab });
+}
+
+export default class Tabs extends Component<TabsProps, TabsState> {
+  constructor(props: TabsProps, context) {
+    super(props, context);
+
+    this.state = {
+      currentTab: props.tabs.length > 0 ? props.tabs[0].key : "",
+    };
+  }
+
+  render() {
+    return (
+      <div>
+        <ul className="nav nav-tabs mb-2">
+          {this.props.tabs.map(({ key, label }) => (
+            <li key={key} className="nav-item">
+              <button
+                className={`nav-link btn${
+                  this.state?.currentTab === key ? " active" : ""
+                }`}
+                onClick={linkEvent({ ctx: this, tab: key }, handleSwitchTab)}
+              >
+                {label}
+              </button>
+            </li>
+          ))}
+        </ul>
+        {this.props.tabs
+          .find(tab => tab.key === this.state?.currentTab)
+          ?.getNode()}
+      </div>
+    );
+  }
+}
diff --git a/src/shared/components/home/admin-settings.tsx b/src/shared/components/home/admin-settings.tsx
index ab897fe..3a2238b 100644
--- a/src/shared/components/home/admin-settings.tsx
+++ b/src/shared/components/home/admin-settings.tsx
@@ -28,6 +28,7 @@ import {
 } from "../../utils";
 import { HtmlTags } from "../common/html-tags";
 import { Spinner } from "../common/icon";
+import Tabs from "../common/tabs";
 import { PersonListing } from "../person/person-listing";
 import { EmojiForm } from "./emojis-form";
 import { SiteForm } from "./site-form";
@@ -39,7 +40,6 @@ interface AdminSettingsState {
   banned: PersonView[];
   loading: boolean;
   leaveAdminTeamLoading: boolean;
-  currentTab: string;
 }
 
 export class AdminSettings extends Component<any, AdminSettingsState> {
@@ -51,7 +51,6 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
     banned: [],
     loading: true,
     leaveAdminTeamLoading: false,
-    currentTab: "site",
   };
 
   constructor(props: any, context: any) {
@@ -119,83 +118,56 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
   render() {
     return (
       <div className="container-lg">
+        <HtmlTags
+          title={this.documentTitle}
+          path={this.context.router.route.match.url}
+        />
         {this.state.loading ? (
           <h5>
             <Spinner large />
           </h5>
         ) : (
-          <div>
-            <HtmlTags
-              title={this.documentTitle}
-              path={this.context.router.route.match.url}
-            />
-            <ul className="nav nav-tabs mb-2">
-              <li className="nav-item">
-                <button
-                  className={`nav-link btn ${
-                    this.state.currentTab == "site" && "active"
-                  }`}
-                  onClick={linkEvent(
-                    { ctx: this, tab: "site" },
-                    this.handleSwitchTab
-                  )}
-                >
-                  {i18n.t("site")}
-                </button>
-              </li>
-              <li className="nav-item">
-                <button
-                  className={`nav-link btn ${
-                    this.state.currentTab == "taglines" && "active"
-                  }`}
-                  onClick={linkEvent(
-                    { ctx: this, tab: "taglines" },
-                    this.handleSwitchTab
-                  )}
-                >
-                  {i18n.t("taglines")}
-                </button>
-              </li>
-              <li className="nav-item">
-                <button
-                  className={`nav-link btn ${
-                    this.state.currentTab == "emojis" && "active"
-                  }`}
-                  onClick={linkEvent(
-                    { ctx: this, tab: "emojis" },
-                    this.handleSwitchTab
-                  )}
-                >
-                  {i18n.t("emojis")}
-                </button>
-              </li>
-            </ul>
-            {this.state.currentTab == "site" && (
-              <div className="row">
-                <div className="col-12 col-md-6">
-                  <SiteForm
-                    siteRes={this.state.siteRes}
-                    instancesRes={this.state.instancesRes}
-                    showLocal={showLocal(this.isoData)}
-                  />
-                </div>
-                <div className="col-12 col-md-6">
-                  {this.admins()}
-                  {this.bannedUsers()}
-                </div>
-              </div>
-            )}
-            {this.state.currentTab == "taglines" && (
-              <div className="row">
-                <TaglineForm siteRes={this.state.siteRes}></TaglineForm>
-              </div>
-            )}
-            {this.state.currentTab == "emojis" && (
-              <div className="row">
-                <EmojiForm></EmojiForm>
-              </div>
-            )}
-          </div>
+          <Tabs
+            tabs={[
+              {
+                key: "site",
+                label: i18n.t("site"),
+                getNode: () => (
+                  <div className="row">
+                    <div className="col-12 col-md-6">
+                      <SiteForm
+                        siteRes={this.state.siteRes}
+                        instancesRes={this.state.instancesRes}
+                        showLocal={showLocal(this.isoData)}
+                      />
+                    </div>
+                    <div className="col-12 col-md-6">
+                      {this.admins()}
+                      {this.bannedUsers()}
+                    </div>
+                  </div>
+                ),
+              },
+              {
+                key: "taglines",
+                label: i18n.t("taglines"),
+                getNode: () => (
+                  <div className="row">
+                    <TaglineForm siteRes={this.state.siteRes} />
+                  </div>
+                ),
+              },
+              {
+                key: "emojis",
+                label: i18n.t("emojis"),
+                getNode: () => (
+                  <div className="row">
+                    <EmojiForm />
+                  </div>
+                ),
+              },
+            ]}
+          />
         )}
       </div>
     );
@@ -247,10 +219,6 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
     );
   }
 
-  handleSwitchTab(i: { ctx: AdminSettings; tab: string }) {
-    i.ctx.setState({ currentTab: i.tab });
-  }
-
   handleLeaveAdminTeam(i: AdminSettings) {
     let auth = myAuth();
     if (auth) {
diff --git a/src/shared/components/home/rate-limit-form.tsx b/src/shared/components/home/rate-limit-form.tsx
new file mode 100644
index 0000000..b99c263
--- /dev/null
+++ b/src/shared/components/home/rate-limit-form.tsx
@@ -0,0 +1,11 @@
+import { Component } from "inferno";
+
+export default class RateLimitForm extends Component {
+  constructor(props, context) {
+    super(props, context);
+  }
+
+  render() {
+    return <></>;
+  }
+}
diff --git a/src/shared/components/person/settings.tsx b/src/shared/components/person/settings.tsx
index 95b2590..f6278f7 100644
--- a/src/shared/components/person/settings.tsx
+++ b/src/shared/components/person/settings.tsx
@@ -54,6 +54,7 @@ import { ListingTypeSelect } from "../common/listing-type-select";
 import { MarkdownTextArea } from "../common/markdown-textarea";
 import { SearchableSelect } from "../common/searchable-select";
 import { SortSelect } from "../common/sort-select";
+import Tabs from "../common/tabs";
 import { CommunityLink } from "../community/community-link";
 import { PersonListing } from "./person-listing";
 
@@ -176,6 +177,8 @@ export class Settings extends Component<any, SettingsState> {
 
     this.handleBannerUpload = this.handleBannerUpload.bind(this);
     this.handleBannerRemove = this.handleBannerRemove.bind(this);
+    this.userSettings = this.userSettings.bind(this);
+    this.blockCards = this.blockCards.bind(this);
 
     this.parseMessage = this.parseMessage.bind(this);
     this.subscription = wsSubscribe(this.parseMessage);
@@ -253,44 +256,26 @@ export class Settings extends Component<any, SettingsState> {
   render() {
     return (
       <div className="container-lg">
-        <>
-          <HtmlTags
-            title={this.documentTitle}
-            path={this.context.router.route.match.url}
-            description={this.documentTitle}
-            image={this.state.saveUserSettingsForm.avatar}
-          />
-          <ul className="nav nav-tabs mb-2">
-            <li className="nav-item">
-              <button
-                className={`nav-link btn ${
-                  this.state.currentTab == "settings" && "active"
-                }`}
-                onClick={linkEvent(
-                  { ctx: this, tab: "settings" },
-                  this.handleSwitchTab
-                )}
-              >
-                {i18n.t("settings")}
-              </button>
-            </li>
-            <li className="nav-item">
-              <button
-                className={`nav-link btn ${
-                  this.state.currentTab == "blocks" && "active"
-                }`}
-                onClick={linkEvent(
-                  { ctx: this, tab: "blocks" },
-                  this.handleSwitchTab
-                )}
-              >
-                {i18n.t("blocks")}
-              </button>
-            </li>
-          </ul>
-          {this.state.currentTab == "settings" && this.userSettings()}
-          {this.state.currentTab == "blocks" && this.blockCards()}
-        </>
+        <HtmlTags
+          title={this.documentTitle}
+          path={this.context.router.route.match.url}
+          description={this.documentTitle}
+          image={this.state.saveUserSettingsForm.avatar}
+        />
+        <Tabs
+          tabs={[
+            {
+              key: "settings",
+              label: i18n.t("settings"),
+              getNode: this.userSettings,
+            },
+            {
+              key: "blocks",
+              label: i18n.t("blocks"),
+              getNode: this.blockCards,
+            },
+          ]}
+        />
       </div>
     );
   }
-- 
2.44.1